<commit_before>#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include "util.hpp"
#include "generated_raw/Arrays.ppr.hpp"

using namespace testing;
using namespace raw;

TEST(generated_raw_arrays, Builtin)
{
    data x(
        "\x01\x00\x00\x02",

        "\x01\x00\x02\x00"
    );

    Builtin* next = prophy::swap(reinterpret_cast<Builtin*>(x.input.data()));

    EXPECT_EQ(byte_distance(x.input.data(), next), 4);
    EXPECT_THAT(x.input, ContainerEq(x.expected));
}

TEST(generated_raw_arrays, BuiltinFixed)
{
    data x(
        "\x00\x02"
        "\x00\x02"
        "\x00\x02",

        "\x02\x00"
        "\x02\x00"
        "\x02\x00"
    );

    BuiltinFixed* next = prophy::swap(reinterpret_cast<BuiltinFixed*>(x.input.data()));

    EXPECT_EQ(byte_distance(x.input.data(), next), 6);
    EXPECT_THAT(x.input, ContainerEq(x.expected));
}

TEST(generated_raw_arrays, BuiltinDynamic)
{
    data x(
        "\x00\x00\x00\x03"
        "\x00\x05\x00\x06"
        "\x00\x07\xab\xcd",

        "\x03\x00\x00\x00"
        "\x05\x00\x06\x00"
        "\x07\x00\xab\xcd"
    );

    BuiltinDynamic* next = prophy::swap(reinterpret_cast<BuiltinDynamic*>(x.input.data()));

    EXPECT_EQ(byte_distance(x.input.data(), next), 12);
    EXPECT_THAT(x.input, ContainerEq(x.expected));
}

TEST(generated_raw_arrays, BuiltinLimited)
{
    data x(
        "\x00\x00\x00\x02"
        "\x00\x05\x00\x06"
        "\xab\xcd\xef\xba",

        "\x02\x00\x00\x00"
        "\x05\x00\x06\x00"
        "\xab\xcd\xef\xba"
    );

    BuiltinLimited* next = prophy::swap(reinterpret_cast<BuiltinLimited*>(x.input.data()));

    EXPECT_EQ(byte_distance(x.input.data(), next), 12);
    EXPECT_THAT(x.input, ContainerEq(x.expected));
}

TEST(generated_raw_arrays, BuiltinGreedy)
{
    data x(
        "\x00\x08\xab\xcd"
        "\x00\x00\x00\x01"
        "\x00\x00\x00\x02",

        "\x08\x00\xab\xcd"
        "\x01\x00\x00\x00"
        "\x02\x00\x00\x00"
    );

    BuiltinGreedy* next = prophy::swap(reinterpret_cast<BuiltinGreedy*>(x.input.data()));
    uint32_t* past_end = prophy::swap_n_fixed(
        prophy::cast<uint32_t*>(next), 2);

    EXPECT_EQ(byte_distance(x.input.data(), next), 4);
    EXPECT_EQ(byte_distance(x.input.data(), past_end), 12);
    EXPECT_THAT(x.input, ContainerEq(x.expected));
}
<commit_msg>strings used and compared<commit_after>#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include "generated_raw/Arrays.ppr.hpp"

using namespace testing;
using namespace raw;

TEST(generated_raw_arrays, Builtin)
{
    std::string data("\x01\x00\x00\x02", 4);
    Builtin* next = prophy::swap(reinterpret_cast<Builtin*>(data.begin().base()));

    EXPECT_EQ(4, reinterpret_cast<char*>(next) - data.data());
    EXPECT_EQ(std::string("\x01\x00\x02\x00", 4), std::string(data, 0, 4));
}

TEST(generated_raw_arrays, BuiltinFixed)
{
    std::string data(
            "\x00\x02"
            "\x00\x02"
            "\x00\x02", 6);
    BuiltinFixed* next = prophy::swap(reinterpret_cast<BuiltinFixed*>(data.begin().base()));

    EXPECT_EQ(6, reinterpret_cast<char*>(next) - data.data());
    EXPECT_EQ(std::string(
            "\x02\x00"
            "\x02\x00"
            "\x02\x00", 6), std::string(data, 0, 6));
}

TEST(generated_raw_arrays, BuiltinDynamic)
{
    std::string data(
            "\x00\x00\x00\x03"
            "\x00\x05\x00\x06"
            "\x00\x07\xab\xcd", 12);
    BuiltinDynamic* next = prophy::swap(reinterpret_cast<BuiltinDynamic*>(data.begin().base()));

    EXPECT_EQ(12, reinterpret_cast<char*>(next) - data.data());
    EXPECT_EQ(std::string(
            "\x03\x00\x00\x00"
            "\x05\x00\x06\x00"
            "\x07\x00\xab\xcd", 12), std::string(data, 0, 12));
}

TEST(generated_raw_arrays, BuiltinLimited)
{
    std::string data(
            "\x00\x00\x00\x02"
            "\x00\x05\x00\x06"
            "\xab\xcd\xef\xba", 12);
    BuiltinLimited* next = prophy::swap(reinterpret_cast<BuiltinLimited*>(data.begin().base()));

    EXPECT_EQ(12, reinterpret_cast<char*>(next) - data.data());
    EXPECT_EQ(std::string(
            "\x02\x00\x00\x00"
            "\x05\x00\x06\x00"
            "\xab\xcd\xef\xba", 12), std::string(data, 0, 12));
}

TEST(generated_raw_arrays, BuiltinGreedy)
{
    std::string data(
            "\x00\x08\xab\xcd"
            "\x00\x00\x00\x01"
            "\x00\x00\x00\x02", 12);
    BuiltinGreedy* next = prophy::swap(reinterpret_cast<BuiltinGreedy*>(data.begin().base()));

    EXPECT_EQ(4, reinterpret_cast<char*>(next) - data.data());
    EXPECT_EQ(std::string(
            "\x08\x00\xab\xcd"
            "\x00\x00\x00\x01"
            "\x00\x00\x00\x02", 12), std::string(data, 0, 12));
}
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Implementation of detector
 *
 * @copyright MIT License
 */

#include <memory>
#include <stdexcept>
#include <string>
#include <utility>

#include <Math/Rotation3D.h>
#include <Math/Translation3D.h>

#include "Detector.hpp"
#include "core/module/exceptions.h"

using namespace allpix;

/**
 * @throws InvalidModuleActionException If the detector model pointer is a null pointer
 *
 * Creates a detector without any electric field in the sensor.
 */
Detector::Detector(std::string name,
                   std::shared_ptr<DetectorModel> model,
                   ROOT::Math::XYZPoint position,
                   ROOT::Math::EulerAngles orientation)
    : Detector(std::move(name), std::move(position), orientation) {
    model_ = std::move(model);
    // Check if valid model is supplied
    if(model_ == nullptr) {
        throw InvalidModuleActionException("Detector model cannot be a null pointer");
    }

    // Build the transformation matrix
    build_transform();
}

/**
 * This constructor can only be called directly by the \ref GeometryManager to
 * instantiate incomplete detectors where the model is added later. It is ensured
 * that these detectors can never be accessed by modules before the detector
 * model is added.
 */
Detector::Detector(std::string name, ROOT::Math::XYZPoint position, ROOT::Math::EulerAngles orientation)
    : name_(std::move(name)), position_(std::move(position)), orientation_(orientation), electric_field_sizes_{{0, 0, 0}},
      electric_field_(nullptr) {}
void Detector::set_model(std::shared_ptr<DetectorModel> model) {
    model_ = std::move(model);
    build_transform();
}
void Detector::build_transform() {
    // Transform from center to local coordinate
    ROOT::Math::Translation3D translation_center(static_cast<ROOT::Math::XYZVector>(position_));
    ROOT::Math::Rotation3D rotation_center(orientation_);
    ROOT::Math::Transform3D transform_center(rotation_center.Inverse(), translation_center);
    // Transform from global to center
    ROOT::Math::Translation3D translation_local(static_cast<ROOT::Math::XYZVector>(model_->getCenter()));
    ROOT::Math::Transform3D transform_local(translation_local);
    // Compute total transform
    transform_ = transform_center * transform_local.Inverse();
}

std::string Detector::getName() const {
    return name_;
}
std::string Detector::getType() const {
    return model_->getType();
}

const std::shared_ptr<DetectorModel> Detector::getModel() const {
    return model_;
}

ROOT::Math::XYZPoint Detector::getPosition() const {
    return position_;
}
ROOT::Math::EulerAngles Detector::getOrientation() const {
    return orientation_;
}

/**
 * @warning The local coordinate position does normally not have its origin at the center of rotation
 *
 * The origin of the local frame is at the center of the first pixel in the middle of the sensor.
 */
ROOT::Math::XYZPoint Detector::getLocalPosition(const ROOT::Math::XYZPoint& global_pos) const {
    return transform_.Inverse()(global_pos);
}
ROOT::Math::XYZPoint Detector::getGlobalPosition(const ROOT::Math::XYZPoint& local_pos) const {
    return transform_(local_pos);
}

/**
 * The definition of inside the sensor is determined by the detector model
 */
bool Detector::isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const {
    return ((local_pos.x() >= model_->getSensorCenter().x() - model_->getSensorSize().x() / 2.0) &&
            (local_pos.x() <= model_->getSensorCenter().x() + model_->getSensorSize().x() / 2.0) &&
            (local_pos.y() >= model_->getSensorCenter().y() - model_->getSensorSize().y() / 2.0) &&
            (local_pos.y() <= model_->getSensorCenter().y() + model_->getSensorSize().y() / 2.0) &&
            (local_pos.z() >= model_->getSensorCenter().z() - model_->getSensorSize().z() / 2.0) &&
            (local_pos.z() <= model_->getSensorCenter().z() + model_->getSensorSize().z() / 2.0));
}

/**
 * The pixel has internal information about the size and location specific for this detector
 */
Pixel Detector::getPixel(unsigned int x, unsigned int y) {
    Pixel::Index index(x, y);

    auto size = model_->getPixelSize();

    // WARNING This relies on the origin of the local coordinate system
    auto local_x = size.x() * x;
    auto local_y = size.y() * y;
    auto local_z = model_->getSensorCenter().z() - model_->getSensorSize().z() / 2.0;

    auto local_center = ROOT::Math::XYZPoint(local_x, local_y, local_z);
    auto global_center = getGlobalPosition(local_center);

    return Pixel(index, local_center, global_center, size);
}

/**
 * The electric field is replicated for all pixels and uses flipping at each boundary (side effects are not modeled in this
 * stage). Outside of the sensor the electric field is strictly zero by definition.
 */
bool Detector::hasElectricField() const {
    return electric_field_sizes_[0] != 0 && electric_field_sizes_[1] != 0 && electric_field_sizes_[2] != 0;
}

/**
 * The electric field is replicated for all pixels and uses flipping at each boundary (side effects are not modeled in this
 * stage). Outside of the sensor the electric field is strictly zero by definition.
 */
ROOT::Math::XYZVector Detector::getElectricField(const ROOT::Math::XYZPoint& pos) const {
    double* field = get_electric_field_raw(pos.x(), pos.y(), pos.z());

    if(field == nullptr) {
        // FIXME: Determine what we should do if we have no external electric field...
        return ROOT::Math::XYZVector(0, 0, 0);
    }

    return ROOT::Math::XYZVector(*(field), *(field + 1), *(field + 2));
}

/**
 * The local position is first converted to pixel coordinates. The stored electric field if the index is odd.
 */
double* Detector::get_electric_field_raw(double x, double y, double z) const {
    // FIXME: We need to revisit this to be faster and not too specific

    // Compute corresponding pixel indices
    // WARNING This relies on the origin of the local coordinate system
    auto pixel_x = static_cast<int>(std::round(x / model_->getPixelSize().x()));
    auto pixel_y = static_cast<int>(std::round(y / model_->getPixelSize().y()));

    // Convert to the pixel frame
    x -= pixel_x * model_->getPixelSize().x();
    y -= pixel_y * model_->getPixelSize().y();

    // Do flipping if necessary
    if((pixel_x % 2) == 1) {
        x *= -1;
    }
    if((pixel_y % 2) == 1) {
        y *= -1;
    }

    // Compute indices
    auto x_ind = static_cast<int>(std::floor(static_cast<double>(electric_field_sizes_[0]) *
                                             (x + model_->getPixelSize().x() / 2.0) / model_->getPixelSize().x()));
    auto y_ind = static_cast<int>(std::floor(static_cast<double>(electric_field_sizes_[1]) *
                                             (y + model_->getPixelSize().y() / 2.0) / model_->getPixelSize().y()));
    auto z_ind = static_cast<int>(
        std::floor(static_cast<double>(electric_field_sizes_[2]) * (z - electric_field_thickness_domain_.first) /
                   (electric_field_thickness_domain_.second - electric_field_thickness_domain_.first)));

    // Check for indices within the sensor
    if(x_ind < 0 || x_ind >= static_cast<int>(electric_field_sizes_[0]) || y_ind < 0 ||
       y_ind >= static_cast<int>(electric_field_sizes_[1]) || z_ind < 0 ||
       z_ind >= static_cast<int>(electric_field_sizes_[2])) {
        return nullptr;
    }

    // Compute total index
    size_t tot_ind = static_cast<size_t>(x_ind) * electric_field_sizes_[1] * electric_field_sizes_[2] * 3 +
                     static_cast<size_t>(y_ind) * electric_field_sizes_[2] * 3 + static_cast<size_t>(z_ind) * 3;
    return &(*electric_field_)[tot_ind];
}

/**
 * @throws std::invalid_argument If the electric field sizes are incorrect or the thickness domain is outside the sensor
 *
 * The electric field is stored as a large flat array. If the sizes are denoted as respectively X_SIZE, Y_ SIZE and Z_SIZE,
 * each position (x, y, z) has three indices:
 * - x*Y_SIZE*Z_SIZE*3+y*Z_SIZE*3+z*3: the x-component of the electric field
 * - x*Y_SIZE*Z_SIZE*3+y*Z_SIZE*3+z*3+1: the y-component of the electric field
 * - x*Y_SIZE*Z_SIZE*3+y*Z_SIZE*3+z*3+2: the z-component of the electric field
 */
void Detector::setElectricField(std::shared_ptr<std::vector<double>> field,
                                std::array<size_t, 3> sizes,
                                std::pair<double, double> thickness_domain) {
    if(sizes[0] * sizes[1] * sizes[2] * 3 != field->size()) {
        throw std::invalid_argument("electric field does not match the given sizes");
    }
    if(thickness_domain.first + 1e-9 < model_->getSensorCenter().z() - model_->getSensorSize().z() / 2.0 ||
       model_->getSensorCenter().z() + model_->getSensorSize().z() / 2.0 < thickness_domain.second - 1e-9) {
        throw std::invalid_argument("thickness domain is outside sensor dimensions");
    }
    if(thickness_domain.first >= thickness_domain.second) {
        throw std::invalid_argument("end of thickness domain is before begin");
    }

    electric_field_ = std::move(field);
    electric_field_sizes_ = std::move(sizes);
    electric_field_thickness_domain_ = std::move(thickness_domain);
}
<commit_msg>fix lint<commit_after>/**
 * @file
 * @brief Implementation of detector
 *
 * @copyright MIT License
 */

#include <memory>
#include <stdexcept>
#include <string>
#include <utility>

#include <Math/Rotation3D.h>
#include <Math/Translation3D.h>

#include "Detector.hpp"
#include "core/module/exceptions.h"

using namespace allpix;

/**
 * @throws InvalidModuleActionException If the detector model pointer is a null pointer
 *
 * Creates a detector without any electric field in the sensor.
 */
Detector::Detector(std::string name,
                   std::shared_ptr<DetectorModel> model,
                   ROOT::Math::XYZPoint position,
                   ROOT::Math::EulerAngles orientation)
    : Detector(std::move(name), std::move(position), orientation) {
    model_ = std::move(model);
    // Check if valid model is supplied
    if(model_ == nullptr) {
        throw InvalidModuleActionException("Detector model cannot be a null pointer");
    }

    // Build the transformation matrix
    build_transform();
}

/**
 * This constructor can only be called directly by the \ref GeometryManager to
 * instantiate incomplete detectors where the model is added later. It is ensured
 * that these detectors can never be accessed by modules before the detector
 * model is added.
 */
Detector::Detector(std::string name, ROOT::Math::XYZPoint position, ROOT::Math::EulerAngles orientation)
    : name_(std::move(name)), position_(std::move(position)), orientation_(orientation), electric_field_sizes_{{0, 0, 0}},
      electric_field_(nullptr) {}
void Detector::set_model(std::shared_ptr<DetectorModel> model) {
    model_ = std::move(model);
    build_transform();
}
void Detector::build_transform() {
    // Transform from center to local coordinate
    ROOT::Math::Translation3D translation_center(static_cast<ROOT::Math::XYZVector>(position_));
    ROOT::Math::Rotation3D rotation_center(orientation_);
    ROOT::Math::Transform3D transform_center(rotation_center.Inverse(), translation_center);
    // Transform from global to center
    ROOT::Math::Translation3D translation_local(static_cast<ROOT::Math::XYZVector>(model_->getCenter()));
    ROOT::Math::Transform3D transform_local(translation_local);
    // Compute total transform
    transform_ = transform_center * transform_local.Inverse();
}

std::string Detector::getName() const {
    return name_;
}
std::string Detector::getType() const {
    return model_->getType();
}

const std::shared_ptr<DetectorModel> Detector::getModel() const {
    return model_;
}

ROOT::Math::XYZPoint Detector::getPosition() const {
    return position_;
}
ROOT::Math::EulerAngles Detector::getOrientation() const {
    return orientation_;
}

/**
 * @warning The local coordinate position does normally not have its origin at the center of rotation
 *
 * The origin of the local frame is at the center of the first pixel in the middle of the sensor.
 */
ROOT::Math::XYZPoint Detector::getLocalPosition(const ROOT::Math::XYZPoint& global_pos) const {
    return transform_.Inverse()(global_pos);
}
ROOT::Math::XYZPoint Detector::getGlobalPosition(const ROOT::Math::XYZPoint& local_pos) const {
    return transform_(local_pos);
}

/**
 * The definition of inside the sensor is determined by the detector model
 */
bool Detector::isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const {
    return ((local_pos.x() >= model_->getSensorCenter().x() - model_->getSensorSize().x() / 2.0) &&
            (local_pos.x() <= model_->getSensorCenter().x() + model_->getSensorSize().x() / 2.0) &&
            (local_pos.y() >= model_->getSensorCenter().y() - model_->getSensorSize().y() / 2.0) &&
            (local_pos.y() <= model_->getSensorCenter().y() + model_->getSensorSize().y() / 2.0) &&
            (local_pos.z() >= model_->getSensorCenter().z() - model_->getSensorSize().z() / 2.0) &&
            (local_pos.z() <= model_->getSensorCenter().z() + model_->getSensorSize().z() / 2.0));
}

/**
 * The pixel has internal information about the size and location specific for this detector
 */
Pixel Detector::getPixel(unsigned int x, unsigned int y) {
    Pixel::Index index(x, y);

    auto size = model_->getPixelSize();

    // WARNING This relies on the origin of the local coordinate system
    auto local_x = size.x() * x;
    auto local_y = size.y() * y;
    auto local_z = model_->getSensorCenter().z() - model_->getSensorSize().z() / 2.0;

    auto local_center = ROOT::Math::XYZPoint(local_x, local_y, local_z);
    auto global_center = getGlobalPosition(local_center);

    return Pixel(index, local_center, global_center, size);
}

/**
 * The electric field is replicated for all pixels and uses flipping at each boundary (side effects are not modeled in this
 * stage). Outside of the sensor the electric field is strictly zero by definition.
 */
bool Detector::hasElectricField() const {
    return electric_field_sizes_[0] != 0 && electric_field_sizes_[1] != 0 && electric_field_sizes_[2] != 0;
}

/**
 * The electric field is replicated for all pixels and uses flipping at each boundary (side effects are not modeled in this
 * stage). Outside of the sensor the electric field is strictly zero by definition.
 */
ROOT::Math::XYZVector Detector::getElectricField(const ROOT::Math::XYZPoint& pos) const {
    double* field = get_electric_field_raw(pos.x(), pos.y(), pos.z());

    if(field == nullptr) {
        // FIXME: Determine what we should do if we have no external electric field...
        return ROOT::Math::XYZVector(0, 0, 0);
    }

    return ROOT::Math::XYZVector(*(field), *(field + 1), *(field + 2));
}

/**
 * The local position is first converted to pixel coordinates. The stored electric field if the index is odd.
 */
double* Detector::get_electric_field_raw(double x, double y, double z) const {
    // FIXME: We need to revisit this to be faster and not too specific

    // Compute corresponding pixel indices
    // WARNING This relies on the origin of the local coordinate system
    auto pixel_x = static_cast<int>(std::round(x / model_->getPixelSize().x()));
    auto pixel_y = static_cast<int>(std::round(y / model_->getPixelSize().y()));

    // Convert to the pixel frame
    x -= pixel_x * model_->getPixelSize().x();
    y -= pixel_y * model_->getPixelSize().y();

    // Do flipping if necessary
    if((pixel_x % 2) == 1) {
        x *= -1;
    }
    if((pixel_y % 2) == 1) {
        y *= -1;
    }

    // Compute indices
    auto x_ind = static_cast<int>(std::floor(static_cast<double>(electric_field_sizes_[0]) *
                                             (x + model_->getPixelSize().x() / 2.0) / model_->getPixelSize().x()));
    auto y_ind = static_cast<int>(std::floor(static_cast<double>(electric_field_sizes_[1]) *
                                             (y + model_->getPixelSize().y() / 2.0) / model_->getPixelSize().y()));
    auto z_ind = static_cast<int>(
        std::floor(static_cast<double>(electric_field_sizes_[2]) * (z - electric_field_thickness_domain_.first) /
                   (electric_field_thickness_domain_.second - electric_field_thickness_domain_.first)));

    // Check for indices within the sensor
    if(x_ind < 0 || x_ind >= static_cast<int>(electric_field_sizes_[0]) || y_ind < 0 ||
       y_ind >= static_cast<int>(electric_field_sizes_[1]) || z_ind < 0 ||
       z_ind >= static_cast<int>(electric_field_sizes_[2])) {
        return nullptr;
    }

    // Compute total index
    size_t tot_ind = static_cast<size_t>(x_ind) * electric_field_sizes_[1] * electric_field_sizes_[2] * 3 +
                     static_cast<size_t>(y_ind) * electric_field_sizes_[2] * 3 + static_cast<size_t>(z_ind) * 3;
    return &(*electric_field_)[tot_ind];
}

/**
 * @throws std::invalid_argument If the electric field sizes are incorrect or the thickness domain is outside the sensor
 *
 * The electric field is stored as a large flat array. If the sizes are denoted as respectively X_SIZE, Y_ SIZE and Z_SIZE,
 * each position (x, y, z) has three indices:
 * - x*Y_SIZE*Z_SIZE*3+y*Z_SIZE*3+z*3: the x-component of the electric field
 * - x*Y_SIZE*Z_SIZE*3+y*Z_SIZE*3+z*3+1: the y-component of the electric field
 * - x*Y_SIZE*Z_SIZE*3+y*Z_SIZE*3+z*3+2: the z-component of the electric field
 */
void Detector::setElectricField(std::shared_ptr<std::vector<double>> field,
                                std::array<size_t, 3> sizes,
                                std::pair<double, double> thickness_domain) {
    if(sizes[0] * sizes[1] * sizes[2] * 3 != field->size()) {
        throw std::invalid_argument("electric field does not match the given sizes");
    }
    if(thickness_domain.first + 1e-9 < model_->getSensorCenter().z() - model_->getSensorSize().z() / 2.0 ||
       model_->getSensorCenter().z() + model_->getSensorSize().z() / 2.0 < thickness_domain.second - 1e-9) {
        throw std::invalid_argument("thickness domain is outside sensor dimensions");
    }
    if(thickness_domain.first >= thickness_domain.second) {
        throw std::invalid_argument("end of thickness domain is before begin");
    }

    electric_field_ = std::move(field);
    electric_field_sizes_ = sizes;
    electric_field_thickness_domain_ = std::move(thickness_domain);
}
<|endoftext|>


<commit_before>/* SfenParser.hpp
 *
 * Kubo Ryosuke
 */

#ifndef SUNFISH_CORE_RECORD_SFENPARSER_HPP__
#define SUNFISH_CORE_RECORD_SFENPARSER_HPP__

#include "core/move/Move.hpp"
#include "core/position/Position.hpp"
#include "core/record/Record.hpp"

namespace sunfish {

class SfenParser {
public:

  static bool parsePosition(const char* data, Position& position);

  static bool parsePosition(const std::string& data, Position& position) {
    return parsePosition(data.c_str(), position);
  }

  static bool parsePosition(const char* arg1,
                            const char* arg2,
                            const char* arg3,
                            const char* arg4,
                            Position& position);

  static bool parsePosition(const std::string& arg1,
                            const std::string& arg2,
                            const std::string& arg3,
                            const std::string& arg4,
                            Position& position) {
    return parsePosition(arg1.c_str(),
                         arg2.c_str(),
                         arg3.c_str(),
                         arg4.c_str(),
                         position);
  }

  static bool parseMove(const char* data, Move& move);

  static bool parseMove(const std::string& data, Move& move) {
    return parseMove(data.c_str(), move);
  }

  template <class iterator>
  static bool parseUsiCommand(const iterator& begin,
                              const iterator& end,
                              Record& record);

private:

  SfenParser();

};

template <class iterator>
inline
bool SfenParser::parseUsiCommand(const iterator& begin,
                                 const iterator& end,
                                 Record& record) {
  iterator ite = begin;

  if (ite == end || *ite != "position") {
    return false;
  }
  ite++;

  if (ite != end && *ite == "startpos") {
    record.initialPosition.initialize(Position::Handicap::Even);
    ite++;
  } else if (ite != end && *ite == "sfen") {
    auto& arg1 = *(ite++); if (ite == end) { return false; }
    auto& arg2 = *(ite++); if (ite == end) { return false; }
    auto& arg3 = *(ite++); if (ite == end) { return false; }
    auto& arg4 = *(ite++); if (ite == end) { return false; }
    bool ok = parsePosition(arg1,
                            arg2,
                            arg3,
                            arg4,
                            record.initialPosition);
    if (!ok) {
      return false;
    }
  } else {
    return false;
  }

  if (ite == end) {
    return true;
  }

  if (*ite != "moves") {
    return false;
  }
  ite++;

  for (; ite != end; ite++) {
    Move move;
    if (!parseMove(*ite, move)) {
      return false;
    }
    record.moveList.push_back(move);
  }

  return true;
}

} // namespace sunfish

#endif // SUNFISH_CORE_RECORD_SFENPARSER_HPP__
<commit_msg>Fix SfenParser<commit_after>/* SfenParser.hpp
 *
 * Kubo Ryosuke
 */

#ifndef SUNFISH_CORE_RECORD_SFENPARSER_HPP__
#define SUNFISH_CORE_RECORD_SFENPARSER_HPP__

#include "core/move/Move.hpp"
#include "core/position/Position.hpp"
#include "core/record/Record.hpp"

namespace sunfish {

class SfenParser {
public:

  static bool parsePosition(const char* data, Position& position);

  static bool parsePosition(const std::string& data, Position& position) {
    return parsePosition(data.c_str(), position);
  }

  static bool parsePosition(const char* arg1,
                            const char* arg2,
                            const char* arg3,
                            const char* arg4,
                            Position& position);

  static bool parsePosition(const std::string& arg1,
                            const std::string& arg2,
                            const std::string& arg3,
                            const std::string& arg4,
                            Position& position) {
    return parsePosition(arg1.c_str(),
                         arg2.c_str(),
                         arg3.c_str(),
                         arg4.c_str(),
                         position);
  }

  static bool parseMove(const char* data, Move& move);

  static bool parseMove(const std::string& data, Move& move) {
    return parseMove(data.c_str(), move);
  }

  template <class iterator>
  static bool parseUsiCommand(const iterator& begin,
                              const iterator& end,
                              Record& record);

private:

  SfenParser();

};

template <class iterator>
inline
bool SfenParser::parseUsiCommand(const iterator& begin,
                                 const iterator& end,
                                 Record& record) {
  iterator ite = begin;

  if (ite == end || *ite != "position") {
    return false;
  }
  ite++;

  if (ite != end && *ite == "startpos") {
    record.initialPosition.initialize(Position::Handicap::Even);
    ite++;
  } else if (ite != end && *ite == "sfen") {
    auto& arg1 = *(ite++); if (ite == end) { return false; }
    auto& arg2 = *(ite++); if (ite == end) { return false; }
    auto& arg3 = *(ite++); if (ite == end) { return false; }
    auto& arg4 = *(ite++); if (ite == end) { return false; }
    bool ok = parsePosition(arg1,
                            arg2,
                            arg3,
                            arg4,
                            record.initialPosition);
    if (!ok) {
      return false;
    }
  } else {
    return false;
  }

  record.moveList.clear();

  if (ite == end) {
    return true;
  }

  if (*ite != "moves") {
    return false;
  }
  ite++;

  for (; ite != end; ite++) {
    Move move;
    if (!parseMove(*ite, move)) {
      return false;
    }
    record.moveList.push_back(move);
  }

  return true;
}

} // namespace sunfish

#endif // SUNFISH_CORE_RECORD_SFENPARSER_HPP__
<|endoftext|>


<commit_before><commit_msg>oox: accelerate common case boolean reading.<commit_after><|endoftext|>


<commit_before>/*
Imposto Real
https://www.urionlinejudge.com.br/judge/pt/problems/view/2666
*/

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long int uint64;

uint64 menor_custo(int N, int C, vector<int> &impostos_devidos, vector< vector<int> > &adj);
uint64 menor_custo(int i, int N, int C, vector<int> &impostos_devidos, vector< vector<int> > &adj, vector<bool> &visitados, vector<uint64> &cofres);

int main(void) {
    ios::sync_with_stdio(false);

    int N, C,
        A, B, DIST;

    cin >> N >> C;

    vector<int> impostos_devidos(N);
    vector< vector<int> > adj(N, vector<int>(N, 0));

    for (int i = 0; i < N; i++) cin >> impostos_devidos[i];

    while (cin >> A >> B >> DIST) {
        adj[A - 1][B - 1] = adj[B - 1][A - 1] = DIST;
    }

    cout << menor_custo(N, C, impostos_devidos, adj) << endl;

    return EXIT_SUCCESS;
}

uint64 menor_custo(int N, int C, vector<int> &impostos_devidos, vector< vector<int> > &adj) {
    vector<bool> visitados(N, false);
    vector<uint64> cofres(N, 0);

    for (int i = 0; i < N; i++) cofres[i] = impostos_devidos[i];

    return menor_custo(0, N, C, impostos_devidos, adj, visitados, cofres);
}

uint64 menor_custo(int i, int N, int C, vector<int> &impostos_devidos, vector< vector<int> > &adj, vector<bool> &visitados, vector<uint64> &cofres) {
    visitados[i] = true;
    uint64 total = 0;

    for (int j = 0; j < N; j++) {
        if (adj[i][j] > 0 && !visitados[j]) {
            total += menor_custo(j, N, C, impostos_devidos, adj, visitados, cofres);
            total += ceil(1.0 * cofres[j] / C) * 2 * adj[i][j];
            cofres[i] += cofres[j];
        }
    }

    return total;
}<commit_msg>URI 2666 - Imposto Real<commit_after>/*
Imposto Real
https://www.urionlinejudge.com.br/judge/pt/problems/view/2666
*/

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long int uint64;

struct graph_node {
    int index;
    int weight;
};

uint64 menor_custo(int N, int C, vector<int> &impostos_devidos, vector< list<graph_node> > &adj);
uint64 menor_custo(int i, int N, int C, vector<int> &impostos_devidos, vector< list<graph_node> > &adj, vector<bool> &visitados, vector<uint64> &cofres);

int main(void) {
    ios::sync_with_stdio(false);

    int N, C,
        A, B, DIST;

    cin >> N >> C;

    vector<int> impostos_devidos(N);
    vector< list<graph_node> > adj(N);

    for (int i = 0; i < N; i++) cin >> impostos_devidos[i];

    while (cin >> A >> B >> DIST) {
        adj[A - 1].push_back({ B - 1, DIST });
        adj[B - 1].push_back({ A - 1, DIST });
    }

    cout << menor_custo(N, C, impostos_devidos, adj) << endl;

    return EXIT_SUCCESS;
}

uint64 menor_custo(int N, int C, vector<int> &impostos_devidos, vector< list<graph_node> > &adj) {
    vector<bool> visitados(N, false);
    vector<uint64> cofres(N, 0);

    for (int i = 0; i < N; i++) cofres[i] = impostos_devidos[i];

    return menor_custo(0, N, C, impostos_devidos, adj, visitados, cofres);
}

uint64 menor_custo(int i, int N, int C, vector<int> &impostos_devidos, vector< list<graph_node> > &adj,
    vector<bool> &visitados, vector<uint64> &cofres) {

    visitados[i] = true;
    uint64 total = 0;

    for (auto gn : adj[i]) {
        if (!visitados[gn.index]) {
            total += menor_custo(gn.index, N, C, impostos_devidos, adj, visitados, cofres);
            total += ceil(1.0 * cofres[gn.index] / C) * 2 * gn.weight;
            cofres[i] += cofres[gn.index];
        }
    }

    return total;
}<|endoftext|>


<commit_before>#include <sys/time.h>
#ifdef	USE_SYSLOG
#include <syslog.h>
#endif

#include <iostream>
#include <sstream>
#include <string>

#ifdef	USE_SYSLOG
static int syslog_priority(const Log::Priority&);
#endif
static std::ostream& operator<< (std::ostream&, const Log::Priority&);
static std::ostream& operator<< (std::ostream&, const struct timeval&);

void
Log::log(const Priority& priority, const LogHandle handle,
	 const std::string message)
{
#ifdef	USE_SYSLOG
	std::string syslog_message;

	syslog_message += "[";
	syslog_message += (std::string)handle;
	syslog_message += "]";
	syslog_message += " ";
	syslog_message += message;

	syslog(syslog_priority(priority), "%s", syslog_message.c_str());
#endif

	struct timeval now;
	int rv;

	rv = gettimeofday(&now, NULL);
	if (rv == -1)
		memset(&now, 0, sizeof now);

	std::cerr << now << " Log(" << (std::string)handle << ") " <<
		priority << ": " <<
		message <<
		std::endl;
}

#ifdef	USE_SYSLOG
static int
syslog_priority(const Log::Priority& priority)
{
	switch (priority) {
	case Log::Emergency:
		return (LOG_EMERG);
	case Log::Alert:
		return (LOG_ALERT);
	case Log::Critical:
		return (LOG_CRIT);
	case Log::Error:
		return (LOG_ERR);
	case Log::Warning:
		return (LOG_WARNING);
	case Log::Notice:
		return (LOG_NOTICE);
	case Log::Info:
		return (LOG_INFO);
	case Log::Debug:
		return (LOG_DEBUG);
	default:
		HALT("/log") << "Unhandled log priority!";
		return (-1);
	}
}
#endif

static std::ostream&
operator<< (std::ostream& os, const Log::Priority& priority)
{
	switch (priority) {
	case Log::Emergency:
		return (os << "EMERG");
	case Log::Alert:
		return (os << "ALERT");
	case Log::Critical:
		return (os << "CRIT");
	case Log::Error:
		return (os << "ERR");
	case Log::Warning:
		return (os << "WARNING");
	case Log::Notice:
		return (os << "NOTICE");
	case Log::Info:
		return (os << "INFO");
	case Log::Debug:
		return (os << "DEBUG");
	default:
		HALT("/log") << "Unhandled log priority!";
		return (os);
	}
}

static std::ostream&
operator<< (std::ostream& os, const struct timeval& tv)
{
	char buf[20];

	snprintf(buf, sizeof buf, "%lu.%06lu", tv.tv_sec, tv.tv_usec);
	return (os << buf);
}
<commit_msg>Grrr.  Definition of timeval isn't very standard, so just use %u.%06u and cast to unsigned.  That'll be good enough for a long time.  (No pun intended.)<commit_after>#include <sys/time.h>
#ifdef	USE_SYSLOG
#include <syslog.h>
#endif

#include <iostream>
#include <sstream>
#include <string>

#ifdef	USE_SYSLOG
static int syslog_priority(const Log::Priority&);
#endif
static std::ostream& operator<< (std::ostream&, const Log::Priority&);
static std::ostream& operator<< (std::ostream&, const struct timeval&);

void
Log::log(const Priority& priority, const LogHandle handle,
	 const std::string message)
{
#ifdef	USE_SYSLOG
	std::string syslog_message;

	syslog_message += "[";
	syslog_message += (std::string)handle;
	syslog_message += "]";
	syslog_message += " ";
	syslog_message += message;

	syslog(syslog_priority(priority), "%s", syslog_message.c_str());
#endif

	struct timeval now;
	int rv;

	rv = gettimeofday(&now, NULL);
	if (rv == -1)
		memset(&now, 0, sizeof now);

	std::cerr << now << " Log(" << (std::string)handle << ") " <<
		priority << ": " <<
		message <<
		std::endl;
}

#ifdef	USE_SYSLOG
static int
syslog_priority(const Log::Priority& priority)
{
	switch (priority) {
	case Log::Emergency:
		return (LOG_EMERG);
	case Log::Alert:
		return (LOG_ALERT);
	case Log::Critical:
		return (LOG_CRIT);
	case Log::Error:
		return (LOG_ERR);
	case Log::Warning:
		return (LOG_WARNING);
	case Log::Notice:
		return (LOG_NOTICE);
	case Log::Info:
		return (LOG_INFO);
	case Log::Debug:
		return (LOG_DEBUG);
	default:
		HALT("/log") << "Unhandled log priority!";
		return (-1);
	}
}
#endif

static std::ostream&
operator<< (std::ostream& os, const Log::Priority& priority)
{
	switch (priority) {
	case Log::Emergency:
		return (os << "EMERG");
	case Log::Alert:
		return (os << "ALERT");
	case Log::Critical:
		return (os << "CRIT");
	case Log::Error:
		return (os << "ERR");
	case Log::Warning:
		return (os << "WARNING");
	case Log::Notice:
		return (os << "NOTICE");
	case Log::Info:
		return (os << "INFO");
	case Log::Debug:
		return (os << "DEBUG");
	default:
		HALT("/log") << "Unhandled log priority!";
		return (os);
	}
}

static std::ostream&
operator<< (std::ostream& os, const struct timeval& tv)
{
	char buf[20];

	snprintf(buf, sizeof buf, "%u.%06u", (unsigned)tv.tv_sec,
		 (unsigned)tv.tv_usec);
	return (os << buf);
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//
// License:  See top level LICENSE.txt file
//
// Author:  David Burken
//
// Description: OSSIM Open JPEG plugin initialization
// code.
//
//----------------------------------------------------------------------------
// $Id: ossimOpjPluginInit.cpp 11046 2007-05-25 18:03:03Z gpotts $

#include <ossim/plugin/ossimSharedObjectBridge.h>
#include "ossimPluginConstants.h"
#include "ossimOpjReaderFactory.h"
#include "ossimOpjWriterFactory.h"
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>

static void setDescription(ossimString& description)
{
   description = "Open JPEG (j2k) reader / writer plugin\n\n";
}

extern "C"
{
   ossimSharedObjectInfo  myInfo;
   ossimString theDescription;
   std::vector<ossimString> theObjList;

   const char* getDescription()
   {
      return theDescription.c_str();
   }

   int getNumberOfClassNames()
   {
      return (int)theObjList.size();
   }

   const char* getClassName(int idx)
   {
      if(idx < (int)theObjList.size())
      {
         return theObjList[0].c_str();
      }
      return (const char*)0;
   }

   /* Note symbols need to be exported on windoze... */
   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
      ossimSharedObjectInfo** info)
   {
      myInfo.getDescription = getDescription;
      myInfo.getNumberOfClassNames = getNumberOfClassNames;
      myInfo.getClassName = getClassName;

      *info = &myInfo;

      /* Register the readers... */
      ossimImageHandlerRegistry::instance()->
        registerFactory(ossimOpjReaderFactory::instance());

      /* Register the writers... */
      ossimImageWriterFactoryRegistry::instance()->
         registerFactory(ossimOpjWriterFactory::instance());

      setDescription(theDescription);
  }

   /* Note symbols need to be exported on windoze... */
  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
  {
     ossimImageHandlerRegistry::instance()->
        unregisterFactory(ossimOpjReaderFactory::instance());

     ossimImageWriterFactoryRegistry::instance()->
        unregisterFactory(ossimOpjWriterFactory::instance());
  }
}
<commit_msg>Fixed include path of ossimPluginConstants.h.<commit_after>//----------------------------------------------------------------------------
//
// License:  See top level LICENSE.txt file
//
// Author:  David Burken
//
// Description: OSSIM Open JPEG plugin initialization
// code.
//
//----------------------------------------------------------------------------
// $Id$

#include <ossim/plugin/ossimSharedObjectBridge.h>
#include <ossim/plugin/ossimPluginConstants.h>
#include "ossimOpjReaderFactory.h"
#include "ossimOpjWriterFactory.h"
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>

static void setDescription(ossimString& description)
{
   description = "Open JPEG (j2k) reader / writer plugin\n\n";
}

extern "C"
{
   ossimSharedObjectInfo  myInfo;
   ossimString theDescription;
   std::vector<ossimString> theObjList;

   const char* getDescription()
   {
      return theDescription.c_str();
   }

   int getNumberOfClassNames()
   {
      return (int)theObjList.size();
   }

   const char* getClassName(int idx)
   {
      if(idx < (int)theObjList.size())
      {
         return theObjList[0].c_str();
      }
      return (const char*)0;
   }

   /* Note symbols need to be exported on windoze... */
   OSSIM_PLUGINS_DLL void ossimSharedLibraryInitialize(
      ossimSharedObjectInfo** info)
   {
      myInfo.getDescription = getDescription;
      myInfo.getNumberOfClassNames = getNumberOfClassNames;
      myInfo.getClassName = getClassName;

      *info = &myInfo;

      /* Register the readers... */
      ossimImageHandlerRegistry::instance()->
        registerFactory(ossimOpjReaderFactory::instance());

      /* Register the writers... */
      ossimImageWriterFactoryRegistry::instance()->
         registerFactory(ossimOpjWriterFactory::instance());

      setDescription(theDescription);
  }

   /* Note symbols need to be exported on windoze... */
  OSSIM_PLUGINS_DLL void ossimSharedLibraryFinalize()
  {
     ossimImageHandlerRegistry::instance()->
        unregisterFactory(ossimOpjReaderFactory::instance());

     ossimImageWriterFactoryRegistry::instance()->
        unregisterFactory(ossimOpjWriterFactory::instance());
  }
}
<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2016-2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "d3d12_state.h"
#include "d3d12_command_list.h"
#include "d3d12_manager.h"
#include "d3d12_resources.h"

D3D12RenderState::D3D12RenderState()
{
  views.clear();
  scissors.clear();

  rts.clear();
  rtSingle = false;
  dsv = PortableHandle();

  m_ResourceManager = NULL;

  heaps.clear();

  pipe = graphics.rootsig = compute.rootsig = ResourceId();
  graphics.sigelems.clear();
  compute.sigelems.clear();

  topo = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;

  stencilRef = 0;
  RDCEraseEl(blendFactor);

  RDCEraseEl(ibuffer);
  vbuffers.clear();
}

D3D12RenderState &D3D12RenderState::operator=(const D3D12RenderState &o)
{
  views = o.views;
  scissors = o.scissors;

  rts = o.rts;
  rtSingle = o.rtSingle;
  dsv = o.dsv;

  pipe = o.pipe;

  heaps = o.heaps;

  graphics.rootsig = o.graphics.rootsig;
  graphics.sigelems = o.graphics.sigelems;
  compute.rootsig = o.compute.rootsig;
  compute.sigelems = o.compute.sigelems;

  topo = o.topo;
  stencilRef = o.stencilRef;
  memcpy(blendFactor, o.blendFactor, sizeof(blendFactor));

  ibuffer = o.ibuffer;
  vbuffers = o.vbuffers;

  return *this;
}

vector<ResourceId> D3D12RenderState::GetRTVIDs() const
{
  vector<ResourceId> ret;

  if(rtSingle)
  {
    if(!rts.empty())
    {
      const D3D12Descriptor *descs = DescriptorFromPortableHandle(GetResourceManager(), rts[0]);

      for(UINT i = 0; i < rts.size(); i++)
      {
        RDCASSERT(descs[i].GetType() == D3D12Descriptor::TypeRTV);
        ret.push_back(GetResID(descs[i].nonsamp.resource));
      }
    }
  }
  else
  {
    for(UINT i = 0; i < rts.size(); i++)
    {
      WrappedID3D12DescriptorHeap *heap =
          GetResourceManager()->GetLiveAs<WrappedID3D12DescriptorHeap>(rts[0].heap);

      const D3D12Descriptor &desc = heap->GetDescriptors()[rts[i].index];

      RDCASSERT(desc.GetType() == D3D12Descriptor::TypeRTV);
      ret.push_back(GetResID(desc.nonsamp.resource));
    }
  }

  return ret;
}

ResourceId D3D12RenderState::GetDSVID() const
{
  if(dsv.heap != ResourceId())
  {
    const D3D12Descriptor *desc = DescriptorFromPortableHandle(GetResourceManager(), dsv);

    RDCASSERT(desc->GetType() == D3D12Descriptor::TypeDSV);

    return GetResID(desc->nonsamp.resource);
  }

  return ResourceId();
}

void D3D12RenderState::ApplyState(ID3D12GraphicsCommandList *cmd) const
{
  if(pipe != ResourceId())
    cmd->SetPipelineState(GetResourceManager()->GetCurrentAs<ID3D12PipelineState>(pipe));

  if(!views.empty())
    cmd->RSSetViewports((UINT)views.size(), &views[0]);

  if(!scissors.empty())
    cmd->RSSetScissorRects((UINT)scissors.size(), &scissors[0]);

  if(topo != D3D_PRIMITIVE_TOPOLOGY_UNDEFINED)
    cmd->IASetPrimitiveTopology(topo);

  cmd->OMSetStencilRef(stencilRef);
  cmd->OMSetBlendFactor(blendFactor);

  if(ibuffer.buf != ResourceId())
  {
    D3D12_INDEX_BUFFER_VIEW ib;

    ID3D12Resource *res = GetResourceManager()->GetCurrentAs<ID3D12Resource>(ibuffer.buf);
    if(res)
      ib.BufferLocation = res->GetGPUVirtualAddress() + ibuffer.offs;
    else
      ib.BufferLocation = 0;

    ib.Format = (ibuffer.bytewidth == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT);
    ib.SizeInBytes = ibuffer.size;

    cmd->IASetIndexBuffer(&ib);
  }

  for(size_t i = 0; i < vbuffers.size(); i++)
  {
    D3D12_VERTEX_BUFFER_VIEW vb;
    vb.BufferLocation = 0;

    if(vbuffers[i].buf != ResourceId())
    {
      ID3D12Resource *res = GetResourceManager()->GetCurrentAs<ID3D12Resource>(vbuffers[i].buf);
      if(res)
        vb.BufferLocation = res->GetGPUVirtualAddress() + vbuffers[i].offs;
      else
        vb.BufferLocation = 0;

      vb.StrideInBytes = vbuffers[i].stride;
      vb.SizeInBytes = vbuffers[i].size;

      cmd->IASetVertexBuffers((UINT)i, 1, &vb);
    }
  }

  std::vector<ID3D12DescriptorHeap *> descHeaps;
  descHeaps.resize(heaps.size());

  for(size_t i = 0; i < heaps.size(); i++)
    descHeaps[i] = GetResourceManager()->GetCurrentAs<ID3D12DescriptorHeap>(heaps[i]);

  if(!descHeaps.empty())
    cmd->SetDescriptorHeaps((UINT)descHeaps.size(), &descHeaps[0]);

  if(!rts.empty() || dsv.heap != ResourceId())
  {
    D3D12_CPU_DESCRIPTOR_HANDLE rtHandles[8];
    D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = CPUHandleFromPortableHandle(GetResourceManager(), dsv);

    UINT rtCount = (UINT)rts.size();
    UINT numActualHandles = rtSingle ? RDCMIN(1U, rtCount) : rtCount;

    for(UINT i = 0; i < numActualHandles; i++)
      rtHandles[i] = CPUHandleFromPortableHandle(GetResourceManager(), rts[i]);

    // need to unwrap here, as FromPortableHandle unwraps too.
    Unwrap(cmd)->OMSetRenderTargets((UINT)rts.size(), rtHandles, rtSingle ? TRUE : FALSE,
                                    dsv.heap != ResourceId() ? &dsvHandle : NULL);
  }

  if(graphics.rootsig != ResourceId())
  {
    cmd->SetGraphicsRootSignature(
        GetResourceManager()->GetCurrentAs<ID3D12RootSignature>(graphics.rootsig));

    ApplyGraphicsRootElements(cmd);
  }

  if(compute.rootsig != ResourceId())
  {
    cmd->SetComputeRootSignature(
        GetResourceManager()->GetCurrentAs<ID3D12RootSignature>(compute.rootsig));

    ApplyComputeRootElements(cmd);
  }
}

void D3D12RenderState::ApplyComputeRootElements(ID3D12GraphicsCommandList *cmd) const
{
  for(size_t i = 0; i < compute.sigelems.size(); i++)
  {
    // just don't set tables that aren't in the descriptor heaps, since it's invalid and can crash
    // and is probably just from stale bindings that aren't going to be used
    if(compute.sigelems[i].type != eRootTable ||
       std::find(heaps.begin(), heaps.end(), compute.sigelems[i].id) != heaps.end())
    {
      compute.sigelems[i].SetToCompute(GetResourceManager(), cmd, (UINT)i);
    }
    else
    {
      RDCDEBUG("Skipping setting possibly stale compute root table referring to heap %llu",
               compute.sigelems[i].id);
    }
  }
}

void D3D12RenderState::ApplyGraphicsRootElements(ID3D12GraphicsCommandList *cmd) const
{
  for(size_t i = 0; i < graphics.sigelems.size(); i++)
  {
    // just don't set tables that aren't in the descriptor heaps, since it's invalid and can crash
    // and is probably just from stale bindings that aren't going to be used
    if(graphics.sigelems[i].type != eRootTable ||
       std::find(heaps.begin(), heaps.end(), graphics.sigelems[i].id) != heaps.end())
    {
      graphics.sigelems[i].SetToGraphics(GetResourceManager(), cmd, (UINT)i);
    }
    else
    {
      RDCDEBUG("Skipping setting possibly stale graphics root table referring to heap %llu",
               graphics.sigelems[i].id);
    }
  }
}
<commit_msg>Don't apply graphics state to compute or copy command lists<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2016-2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "d3d12_state.h"
#include "d3d12_command_list.h"
#include "d3d12_manager.h"
#include "d3d12_resources.h"

D3D12RenderState::D3D12RenderState()
{
  views.clear();
  scissors.clear();

  rts.clear();
  rtSingle = false;
  dsv = PortableHandle();

  m_ResourceManager = NULL;

  heaps.clear();

  pipe = graphics.rootsig = compute.rootsig = ResourceId();
  graphics.sigelems.clear();
  compute.sigelems.clear();

  topo = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;

  stencilRef = 0;
  RDCEraseEl(blendFactor);

  RDCEraseEl(ibuffer);
  vbuffers.clear();
}

D3D12RenderState &D3D12RenderState::operator=(const D3D12RenderState &o)
{
  views = o.views;
  scissors = o.scissors;

  rts = o.rts;
  rtSingle = o.rtSingle;
  dsv = o.dsv;

  pipe = o.pipe;

  heaps = o.heaps;

  graphics.rootsig = o.graphics.rootsig;
  graphics.sigelems = o.graphics.sigelems;
  compute.rootsig = o.compute.rootsig;
  compute.sigelems = o.compute.sigelems;

  topo = o.topo;
  stencilRef = o.stencilRef;
  memcpy(blendFactor, o.blendFactor, sizeof(blendFactor));

  ibuffer = o.ibuffer;
  vbuffers = o.vbuffers;

  return *this;
}

vector<ResourceId> D3D12RenderState::GetRTVIDs() const
{
  vector<ResourceId> ret;

  if(rtSingle)
  {
    if(!rts.empty())
    {
      const D3D12Descriptor *descs = DescriptorFromPortableHandle(GetResourceManager(), rts[0]);

      for(UINT i = 0; i < rts.size(); i++)
      {
        RDCASSERT(descs[i].GetType() == D3D12Descriptor::TypeRTV);
        ret.push_back(GetResID(descs[i].nonsamp.resource));
      }
    }
  }
  else
  {
    for(UINT i = 0; i < rts.size(); i++)
    {
      WrappedID3D12DescriptorHeap *heap =
          GetResourceManager()->GetLiveAs<WrappedID3D12DescriptorHeap>(rts[0].heap);

      const D3D12Descriptor &desc = heap->GetDescriptors()[rts[i].index];

      RDCASSERT(desc.GetType() == D3D12Descriptor::TypeRTV);
      ret.push_back(GetResID(desc.nonsamp.resource));
    }
  }

  return ret;
}

ResourceId D3D12RenderState::GetDSVID() const
{
  if(dsv.heap != ResourceId())
  {
    const D3D12Descriptor *desc = DescriptorFromPortableHandle(GetResourceManager(), dsv);

    RDCASSERT(desc->GetType() == D3D12Descriptor::TypeDSV);

    return GetResID(desc->nonsamp.resource);
  }

  return ResourceId();
}

void D3D12RenderState::ApplyState(ID3D12GraphicsCommandList *cmd) const
{
  D3D12_COMMAND_LIST_TYPE type = cmd->GetType();

  if(type == D3D12_COMMAND_LIST_TYPE_DIRECT || type == D3D12_COMMAND_LIST_TYPE_BUNDLE)
  {
    if(pipe != ResourceId())
      cmd->SetPipelineState(GetResourceManager()->GetCurrentAs<ID3D12PipelineState>(pipe));

    if(!views.empty())
      cmd->RSSetViewports((UINT)views.size(), &views[0]);

    if(!scissors.empty())
      cmd->RSSetScissorRects((UINT)scissors.size(), &scissors[0]);

    if(topo != D3D_PRIMITIVE_TOPOLOGY_UNDEFINED)
      cmd->IASetPrimitiveTopology(topo);

    cmd->OMSetStencilRef(stencilRef);
    cmd->OMSetBlendFactor(blendFactor);

    if(ibuffer.buf != ResourceId())
    {
      D3D12_INDEX_BUFFER_VIEW ib;

      ID3D12Resource *res = GetResourceManager()->GetCurrentAs<ID3D12Resource>(ibuffer.buf);
      if(res)
        ib.BufferLocation = res->GetGPUVirtualAddress() + ibuffer.offs;
      else
        ib.BufferLocation = 0;

      ib.Format = (ibuffer.bytewidth == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT);
      ib.SizeInBytes = ibuffer.size;

      cmd->IASetIndexBuffer(&ib);
    }

    for(size_t i = 0; i < vbuffers.size(); i++)
    {
      D3D12_VERTEX_BUFFER_VIEW vb;
      vb.BufferLocation = 0;

      if(vbuffers[i].buf != ResourceId())
      {
        ID3D12Resource *res = GetResourceManager()->GetCurrentAs<ID3D12Resource>(vbuffers[i].buf);
        if(res)
          vb.BufferLocation = res->GetGPUVirtualAddress() + vbuffers[i].offs;
        else
          vb.BufferLocation = 0;

        vb.StrideInBytes = vbuffers[i].stride;
        vb.SizeInBytes = vbuffers[i].size;

        cmd->IASetVertexBuffers((UINT)i, 1, &vb);
      }
    }

    if(!rts.empty() || dsv.heap != ResourceId())
    {
      D3D12_CPU_DESCRIPTOR_HANDLE rtHandles[8];
      D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = CPUHandleFromPortableHandle(GetResourceManager(), dsv);

      UINT rtCount = (UINT)rts.size();
      UINT numActualHandles = rtSingle ? RDCMIN(1U, rtCount) : rtCount;

      for(UINT i = 0; i < numActualHandles; i++)
        rtHandles[i] = CPUHandleFromPortableHandle(GetResourceManager(), rts[i]);

      // need to unwrap here, as FromPortableHandle unwraps too.
      Unwrap(cmd)->OMSetRenderTargets((UINT)rts.size(), rtHandles, rtSingle ? TRUE : FALSE,
                                      dsv.heap != ResourceId() ? &dsvHandle : NULL);
    }
  }

  std::vector<ID3D12DescriptorHeap *> descHeaps;
  descHeaps.resize(heaps.size());

  for(size_t i = 0; i < heaps.size(); i++)
    descHeaps[i] = GetResourceManager()->GetCurrentAs<ID3D12DescriptorHeap>(heaps[i]);

  if(!descHeaps.empty())
    cmd->SetDescriptorHeaps((UINT)descHeaps.size(), &descHeaps[0]);

  if(graphics.rootsig != ResourceId())
  {
    cmd->SetGraphicsRootSignature(
        GetResourceManager()->GetCurrentAs<ID3D12RootSignature>(graphics.rootsig));

    ApplyGraphicsRootElements(cmd);
  }

  if(compute.rootsig != ResourceId())
  {
    cmd->SetComputeRootSignature(
        GetResourceManager()->GetCurrentAs<ID3D12RootSignature>(compute.rootsig));

    ApplyComputeRootElements(cmd);
  }
}

void D3D12RenderState::ApplyComputeRootElements(ID3D12GraphicsCommandList *cmd) const
{
  for(size_t i = 0; i < compute.sigelems.size(); i++)
  {
    // just don't set tables that aren't in the descriptor heaps, since it's invalid and can crash
    // and is probably just from stale bindings that aren't going to be used
    if(compute.sigelems[i].type != eRootTable ||
       std::find(heaps.begin(), heaps.end(), compute.sigelems[i].id) != heaps.end())
    {
      compute.sigelems[i].SetToCompute(GetResourceManager(), cmd, (UINT)i);
    }
    else
    {
      RDCDEBUG("Skipping setting possibly stale compute root table referring to heap %llu",
               compute.sigelems[i].id);
    }
  }
}

void D3D12RenderState::ApplyGraphicsRootElements(ID3D12GraphicsCommandList *cmd) const
{
  for(size_t i = 0; i < graphics.sigelems.size(); i++)
  {
    // just don't set tables that aren't in the descriptor heaps, since it's invalid and can crash
    // and is probably just from stale bindings that aren't going to be used
    if(graphics.sigelems[i].type != eRootTable ||
       std::find(heaps.begin(), heaps.end(), graphics.sigelems[i].id) != heaps.end())
    {
      graphics.sigelems[i].SetToGraphics(GetResourceManager(), cmd, (UINT)i);
    }
    else
    {
      RDCDEBUG("Skipping setting possibly stale graphics root table referring to heap %llu",
               graphics.sigelems[i].id);
    }
  }
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/kernels/internal/reference/strided_slice.h"

#include <cmath>
#include <cstring>

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"

namespace tflite {
namespace ops {
namespace micro {
namespace strided_slice {

constexpr int kInputTensor = 0;
constexpr int kBeginTensor = 1;
constexpr int kEndTensor = 2;
constexpr int kStridesTensor = 3;
constexpr int kOutputTensor = 0;

struct StridedSliceContext {
  StridedSliceContext(TfLiteContext* context, TfLiteNode* node) {
    params = reinterpret_cast<TfLiteStridedSliceParams*>(node->builtin_data);
    micro_context = GetMicroContext(context);
    input = micro_context->AllocateTempInputTensor(node, kInputTensor);
    begin = micro_context->AllocateTempInputTensor(node, kBeginTensor);
    end = micro_context->AllocateTempInputTensor(node, kEndTensor);
    strides = micro_context->AllocateTempInputTensor(node, kStridesTensor);
    output = micro_context->AllocateTempOutputTensor(node, kOutputTensor);
    dims = NumDimensions(input);
  }
  ~StridedSliceContext() {
    micro_context->DeallocateTempTfLiteTensor(input);
    micro_context->DeallocateTempTfLiteTensor(begin);
    micro_context->DeallocateTempTfLiteTensor(end);
    micro_context->DeallocateTempTfLiteTensor(strides);
    micro_context->DeallocateTempTfLiteTensor(output);
  }
  const TfLiteStridedSliceParams* params;
  MicroContext* micro_context;
  TfLiteTensor* input;
  TfLiteTensor* begin;
  TfLiteTensor* end;
  TfLiteTensor* strides;
  TfLiteTensor* output;
  int dims;
};

// This Op only supports 1-4D cases and since we use the reference 4D
// implementation, the 1-3D tensors are mapped to 4D.
const int kMaxDim = 4;

tflite::StridedSliceParams BuildStridedSliceParams(
    StridedSliceContext* op_context) {
  tflite::StridedSliceParams op_params;
  op_params.start_indices_count = op_context->dims;
  op_params.stop_indices_count = op_context->dims;
  op_params.strides_count = op_context->dims;

  for (int i = 0; i < op_context->dims; ++i) {
    op_params.start_indices[i] = GetTensorData<int32_t>(op_context->begin)[i];
    op_params.stop_indices[i] = GetTensorData<int32_t>(op_context->end)[i];
    op_params.strides[i] = GetTensorData<int32_t>(op_context->strides)[i];
  }

  op_params.begin_mask = op_context->params->begin_mask;
  op_params.ellipsis_mask = 0;
  op_params.end_mask = op_context->params->end_mask;
  op_params.new_axis_mask = 0;
  op_params.shrink_axis_mask = op_context->params->shrink_axis_mask;
  return op_params;
}

// Processes the indexing tensors (begin, end and strides) to resize the
// output tensor. This function is callable from both Prepare() and Eval() as
// long as the caller ensures the indexing tensors are present.
TfLiteStatus CheckOutputSize(TfLiteContext* context,
                             StridedSliceContext* op_context) {
  using ::tflite::strided_slice::StartForAxis;
  using ::tflite::strided_slice::StopForAxis;
  TfLiteIntArray* output_shape = op_context->output->dims;
  int shape_size = 0;
  auto op_params = BuildStridedSliceParams(op_context);
  auto input_shape = GetTensorShape(op_context->input);
  for (int idx = 0; idx < op_context->dims; ++idx) {
    int32_t stride = GetTensorData<int32_t>(op_context->strides)[idx];
    TF_LITE_ENSURE_MSG(context, stride != 0, "stride value has to be non-zero");
    int32_t begin = StartForAxis(op_params, input_shape, idx);
    int32_t end = StopForAxis(op_params, input_shape, idx, begin);

    // When shrinking an axis, the end position does not matter (and can be
    // incorrect when negative indexing is used, see Issue #19260). Always use
    // begin + 1 to generate a length 1 slice, since begin has
    // already been adjusted for negative indices by StartForAxis.
    const bool shrink_axis = op_context->params->shrink_axis_mask & (1 << idx);
    if (shrink_axis) {
      end = begin + 1;
    }

    // This is valid for both positive and negative strides
    int32_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
    dim_shape = dim_shape < 0 ? 0 : dim_shape;
    if (!shrink_axis) {
      TF_LITE_ENSURE_EQ(context, output_shape->data[shape_size], dim_shape);
      shape_size++;
    }
  }
  TF_LITE_ENSURE_EQ(context, output_shape->size, shape_size);
  return kTfLiteOk;
}

void* Init(TfLiteContext* context, const char* buffer, size_t length) {
  TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
  return context->AllocatePersistentBuffer(context, sizeof(StridedSliceParams));
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  StridedSliceParams* op_params =
      static_cast<StridedSliceParams*>(node->user_data);
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 4);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
  StridedSliceContext op_context(context, node);
  TF_LITE_ENSURE_MSG(context, op_context.dims <= kMaxDim,
                     "input dim should not exceed 4");
  auto params = BuildStridedSliceParams(&op_context);
  memcpy(op_params, &params, sizeof(StridedSliceParams));
  return CheckOutputSize(context, &op_context);
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  const StridedSliceParams& op_params =
      *(static_cast<const StridedSliceParams*>(node->user_data));

  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kInputTensor);
  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kOutputTensor);
  switch (output->type) {
    case kTfLiteFloat32:
      reference_ops::StridedSlice(op_params,
                                  tflite::micro::GetTensorShape(input),
                                  tflite::micro::GetTensorData<float>(input),
                                  tflite::micro::GetTensorShape(output),
                                  tflite::micro::GetTensorData<float>(output));
      break;
    case kTfLiteInt8:
      reference_ops::StridedSlice(op_params,
                                  tflite::micro::GetTensorShape(input),
                                  tflite::micro::GetTensorData<int8_t>(input),
                                  tflite::micro::GetTensorShape(output),
                                  tflite::micro::GetTensorData<int8_t>(output));
      break;
    case kTfLiteInt16:
      reference_ops::StridedSlice(
          op_params, tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int16_t>(input),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int16_t>(output));
      break;
    case kTfLiteInt32:
      reference_ops::StridedSlice(
          op_params, tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int32_t>(input),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int32_t>(output));
      break;
    default:
      MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
                  input->type);
      return kTfLiteError;
  }
  return kTfLiteOk;
}
}  // namespace strided_slice

TfLiteRegistration Register_STRIDED_SLICE() {
  return tflite::micro::RegisterOp(strided_slice::Init, strided_slice::Prepare,
                                   strided_slice::Eval);
}

}  // namespace micro
}  // namespace ops
}  // namespace tflite
<commit_msg>Micro conformer: strided slice needs to support bool type.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/kernels/internal/reference/strided_slice.h"

#include <cmath>
#include <cstring>

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"

namespace tflite {
namespace ops {
namespace micro {
namespace strided_slice {

constexpr int kInputTensor = 0;
constexpr int kBeginTensor = 1;
constexpr int kEndTensor = 2;
constexpr int kStridesTensor = 3;
constexpr int kOutputTensor = 0;

struct StridedSliceContext {
  StridedSliceContext(TfLiteContext* context, TfLiteNode* node) {
    params = reinterpret_cast<TfLiteStridedSliceParams*>(node->builtin_data);
    micro_context = GetMicroContext(context);
    input = micro_context->AllocateTempInputTensor(node, kInputTensor);
    begin = micro_context->AllocateTempInputTensor(node, kBeginTensor);
    end = micro_context->AllocateTempInputTensor(node, kEndTensor);
    strides = micro_context->AllocateTempInputTensor(node, kStridesTensor);
    output = micro_context->AllocateTempOutputTensor(node, kOutputTensor);
    dims = NumDimensions(input);
  }
  ~StridedSliceContext() {
    micro_context->DeallocateTempTfLiteTensor(input);
    micro_context->DeallocateTempTfLiteTensor(begin);
    micro_context->DeallocateTempTfLiteTensor(end);
    micro_context->DeallocateTempTfLiteTensor(strides);
    micro_context->DeallocateTempTfLiteTensor(output);
  }
  const TfLiteStridedSliceParams* params;
  MicroContext* micro_context;
  TfLiteTensor* input;
  TfLiteTensor* begin;
  TfLiteTensor* end;
  TfLiteTensor* strides;
  TfLiteTensor* output;
  int dims;
};

// This Op only supports 1-4D cases and since we use the reference 4D
// implementation, the 1-3D tensors are mapped to 4D.
const int kMaxDim = 4;

tflite::StridedSliceParams BuildStridedSliceParams(
    StridedSliceContext* op_context) {
  tflite::StridedSliceParams op_params;
  op_params.start_indices_count = op_context->dims;
  op_params.stop_indices_count = op_context->dims;
  op_params.strides_count = op_context->dims;

  for (int i = 0; i < op_context->dims; ++i) {
    op_params.start_indices[i] = GetTensorData<int32_t>(op_context->begin)[i];
    op_params.stop_indices[i] = GetTensorData<int32_t>(op_context->end)[i];
    op_params.strides[i] = GetTensorData<int32_t>(op_context->strides)[i];
  }

  op_params.begin_mask = op_context->params->begin_mask;
  op_params.ellipsis_mask = 0;
  op_params.end_mask = op_context->params->end_mask;
  op_params.new_axis_mask = 0;
  op_params.shrink_axis_mask = op_context->params->shrink_axis_mask;
  return op_params;
}

// Processes the indexing tensors (begin, end and strides) to resize the
// output tensor. This function is callable from both Prepare() and Eval() as
// long as the caller ensures the indexing tensors are present.
TfLiteStatus CheckOutputSize(TfLiteContext* context,
                             StridedSliceContext* op_context) {
  using ::tflite::strided_slice::StartForAxis;
  using ::tflite::strided_slice::StopForAxis;
  TfLiteIntArray* output_shape = op_context->output->dims;
  int shape_size = 0;
  auto op_params = BuildStridedSliceParams(op_context);
  auto input_shape = GetTensorShape(op_context->input);
  for (int idx = 0; idx < op_context->dims; ++idx) {
    int32_t stride = GetTensorData<int32_t>(op_context->strides)[idx];
    TF_LITE_ENSURE_MSG(context, stride != 0, "stride value has to be non-zero");
    int32_t begin = StartForAxis(op_params, input_shape, idx);
    int32_t end = StopForAxis(op_params, input_shape, idx, begin);

    // When shrinking an axis, the end position does not matter (and can be
    // incorrect when negative indexing is used, see Issue #19260). Always use
    // begin + 1 to generate a length 1 slice, since begin has
    // already been adjusted for negative indices by StartForAxis.
    const bool shrink_axis = op_context->params->shrink_axis_mask & (1 << idx);
    if (shrink_axis) {
      end = begin + 1;
    }

    // This is valid for both positive and negative strides
    int32_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
    dim_shape = dim_shape < 0 ? 0 : dim_shape;
    if (!shrink_axis) {
      TF_LITE_ENSURE_EQ(context, output_shape->data[shape_size], dim_shape);
      shape_size++;
    }
  }
  TF_LITE_ENSURE_EQ(context, output_shape->size, shape_size);
  return kTfLiteOk;
}

void* Init(TfLiteContext* context, const char* buffer, size_t length) {
  TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
  return context->AllocatePersistentBuffer(context, sizeof(StridedSliceParams));
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  StridedSliceParams* op_params =
      static_cast<StridedSliceParams*>(node->user_data);
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 4);
  TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
  StridedSliceContext op_context(context, node);
  TF_LITE_ENSURE_MSG(context, op_context.dims <= kMaxDim,
                     "input dim should not exceed 4");
  auto params = BuildStridedSliceParams(&op_context);
  memcpy(op_params, &params, sizeof(StridedSliceParams));
  return CheckOutputSize(context, &op_context);
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  const StridedSliceParams& op_params =
      *(static_cast<const StridedSliceParams*>(node->user_data));

  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kInputTensor);
  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kOutputTensor);
  switch (output->type) {
    case kTfLiteFloat32:
      reference_ops::StridedSlice(op_params,
                                  tflite::micro::GetTensorShape(input),
                                  tflite::micro::GetTensorData<float>(input),
                                  tflite::micro::GetTensorShape(output),
                                  tflite::micro::GetTensorData<float>(output));
      break;
    case kTfLiteInt8:
      reference_ops::StridedSlice(op_params,
                                  tflite::micro::GetTensorShape(input),
                                  tflite::micro::GetTensorData<int8_t>(input),
                                  tflite::micro::GetTensorShape(output),
                                  tflite::micro::GetTensorData<int8_t>(output));
      break;
    case kTfLiteInt16:
      reference_ops::StridedSlice(
          op_params, tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int16_t>(input),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int16_t>(output));
      break;
    case kTfLiteInt32:
      reference_ops::StridedSlice(
          op_params, tflite::micro::GetTensorShape(input),
          tflite::micro::GetTensorData<int32_t>(input),
          tflite::micro::GetTensorShape(output),
          tflite::micro::GetTensorData<int32_t>(output));
      break;
    case kTfLiteBool:
      reference_ops::StridedSlice(op_params,
                                  tflite::micro::GetTensorShape(input),
                                  tflite::micro::GetTensorData<bool>(input),
                                  tflite::micro::GetTensorShape(output),
                                  tflite::micro::GetTensorData<bool>(output));
      break;
    default:
      MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
                  input->type);
      return kTfLiteError;
  }
  return kTfLiteOk;
}
}  // namespace strided_slice

TfLiteRegistration Register_STRIDED_SLICE() {
  return tflite::micro::RegisterOp(strided_slice::Init, strided_slice::Prepare,
                                   strided_slice::Eval);
}

}  // namespace micro
}  // namespace ops
}  // namespace tflite
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core -verify %s

class A {
public:
    virtual void f(){};

};
class B : public A{
public:
  int m;
};
class C : public A{};

class BB: public B{};

// A lot of the tests below have the if statement in them, which forces the
// analyzer to explore both path - when the result is 0 and not. This makes
// sure that we definitely know that the result is non-0 (as the result of
// the cast).
int testDynCastFromRadar() {
    B aa;
    A *a = &aa;
    const int* res = 0;
    B *b = dynamic_cast<B*>(a);
    static const int i = 5;
    if(b) {
        res = &i;
    } else {
        res = 0;
    }
    return *res; // no warning
}

int testBaseToBase1() {
  B b;
  B *pb = &b;
  B *pbb = dynamic_cast<B*>(pb);
  const int* res = 0;
  static const int i = 5;
  if (pbb) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testMultipleLevelsOfSubclassing1() {
  BB bb;
  B *pb = &bb;
  A *pa = pb;
  B *b = dynamic_cast<B*>(pa);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testMultipleLevelsOfSubclassing2() {
  BB bb;
  A *pbb = &bb;
  B *b = dynamic_cast<B*>(pbb);
  BB *s = dynamic_cast<BB*>(b);
  const int* res = 0;
  static const int i = 5;
  if (s) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testMultipleLevelsOfSubclassing3() {
  BB bb;
  A *pbb = &bb;
  B *b = dynamic_cast<B*>(pbb);
  return b->m; // no warning
}

int testLHS() {
    B aa;
    A *a = &aa;
    return (dynamic_cast<B*>(a))->m;
}

int testLHS2() {
    B aa;
    A *a = &aa;
    return (*dynamic_cast<B*>(a)).m;
}

int testDynCastUnknown2(class A *a) {
  B *b = dynamic_cast<B*>(a);
  return b->m; // no warning
}

int testDynCastUnknown(class A *a) {
  B *b = dynamic_cast<B*>(a);
  const int* res = 0;
  static const int i = 5;
  if (b) {
    res = &i;
  } else {
    res = 0;
  }
  return *res; // expected-warning {{Dereference of null pointer}}
}

int testDynCastFail2() {
  C c;
  A *pa = &c;
  B *b = dynamic_cast<B*>(pa);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testLHSFail() {
    C c;
    A *a = &c;
    return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}}
}

int testBaseToDerivedFail() {
  A a;
  B *b = dynamic_cast<B*>(&a);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testConstZeroFail() {
  B *b = dynamic_cast<B*>((A *)0);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testConstZeroFail2() {
  A *a = 0;
  B *b = dynamic_cast<B*>(a);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testUpcast() {
  B b;
  A *a = dynamic_cast<A*>(&b);
  const int* res = 0;
  static const int i = 5;
  if (a) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testCastToVoidStar() {
  A a;
  void *b = dynamic_cast<void*>(&a);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testReferenceSuccesfulCast() {
  B rb;
  B &b = dynamic_cast<B&>(rb);
  int *x = 0;
  return *x; // expected-warning {{Dereference of null pointer}}
}

int testReferenceFailedCast() {
  A a;
  B &b = dynamic_cast<B&>(a);
  int *x = 0;
  return *x; // no warning (An exception is thrown by the cast.)
}

// Here we allow any outcome of the cast and this is good because there is a
// situation where this will fail. So if the user has written the code in this
// way, we assume they expect the cast to succeed.
// Note, this might need special handling if we track types of symbolic casts
// and use them for dynamic_cast handling.
int testDynCastMostLikelyWillFail(C *c) {
  B *b = 0;
  b = dynamic_cast<B*>(c);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // expected-warning{{Dereference of null pointer}}
}

class M : public B, public C {};
void callTestDynCastMostLikelyWillFail() {
  M m;
  testDynCastMostLikelyWillFail(&m);
}

// False positives/negatives.

// Due to symbolic regions not being typed.
int testDynCastFalsePositive(BB *c) {
  B *b = 0;
  b = dynamic_cast<B*>(c);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // expected-warning{{Dereference of null pointer}}
}

<commit_msg>[analyzer] Another dynamic_cast false positive/negative.<commit_after>// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core -verify %s

class A {
public:
    virtual void f(){};

};
class B : public A{
public:
  int m;
};
class C : public A{};

class BB: public B{};

// A lot of the tests below have the if statement in them, which forces the
// analyzer to explore both path - when the result is 0 and not. This makes
// sure that we definitely know that the result is non-0 (as the result of
// the cast).
int testDynCastFromRadar() {
    B aa;
    A *a = &aa;
    const int* res = 0;
    B *b = dynamic_cast<B*>(a);
    static const int i = 5;
    if(b) {
        res = &i;
    } else {
        res = 0;
    }
    return *res; // no warning
}

int testBaseToBase1() {
  B b;
  B *pb = &b;
  B *pbb = dynamic_cast<B*>(pb);
  const int* res = 0;
  static const int i = 5;
  if (pbb) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testMultipleLevelsOfSubclassing1() {
  BB bb;
  B *pb = &bb;
  A *pa = pb;
  B *b = dynamic_cast<B*>(pa);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testMultipleLevelsOfSubclassing2() {
  BB bb;
  A *pbb = &bb;
  B *b = dynamic_cast<B*>(pbb);
  BB *s = dynamic_cast<BB*>(b);
  const int* res = 0;
  static const int i = 5;
  if (s) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testMultipleLevelsOfSubclassing3() {
  BB bb;
  A *pbb = &bb;
  B *b = dynamic_cast<B*>(pbb);
  return b->m; // no warning
}

int testLHS() {
    B aa;
    A *a = &aa;
    return (dynamic_cast<B*>(a))->m;
}

int testLHS2() {
    B aa;
    A *a = &aa;
    return (*dynamic_cast<B*>(a)).m;
}

int testDynCastUnknown2(class A *a) {
  B *b = dynamic_cast<B*>(a);
  return b->m; // no warning
}

int testDynCastUnknown(class A *a) {
  B *b = dynamic_cast<B*>(a);
  const int* res = 0;
  static const int i = 5;
  if (b) {
    res = &i;
  } else {
    res = 0;
  }
  return *res; // expected-warning {{Dereference of null pointer}}
}

int testDynCastFail2() {
  C c;
  A *pa = &c;
  B *b = dynamic_cast<B*>(pa);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testLHSFail() {
    C c;
    A *a = &c;
    return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}}
}

int testBaseToDerivedFail() {
  A a;
  B *b = dynamic_cast<B*>(&a);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testConstZeroFail() {
  B *b = dynamic_cast<B*>((A *)0);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testConstZeroFail2() {
  A *a = 0;
  B *b = dynamic_cast<B*>(a);
  return b->m; // expected-warning {{dereference of a null pointer}}
}

int testUpcast() {
  B b;
  A *a = dynamic_cast<A*>(&b);
  const int* res = 0;
  static const int i = 5;
  if (a) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testCastToVoidStar() {
  A a;
  void *b = dynamic_cast<void*>(&a);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // no warning
}

int testReferenceSuccesfulCast() {
  B rb;
  B &b = dynamic_cast<B&>(rb);
  int *x = 0;
  return *x; // expected-warning {{Dereference of null pointer}}
}

int testReferenceFailedCast() {
  A a;
  B &b = dynamic_cast<B&>(a);
  int *x = 0;
  return *x; // no warning (An exception is thrown by the cast.)
}

// Here we allow any outcome of the cast and this is good because there is a
// situation where this will fail. So if the user has written the code in this
// way, we assume they expect the cast to succeed.
// Note, this might need special handling if we track types of symbolic casts
// and use them for dynamic_cast handling.
int testDynCastMostLikelyWillFail(C *c) {
  B *b = 0;
  b = dynamic_cast<B*>(c);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // expected-warning{{Dereference of null pointer}}
}

class M : public B, public C {};
void callTestDynCastMostLikelyWillFail() {
  M m;
  testDynCastMostLikelyWillFail(&m);
}

// False positives/negatives.

// Due to symbolic regions not being typed.
int testDynCastFalsePositive(BB *c) {
  B *b = 0;
  b = dynamic_cast<B*>(c);
  const int* res = 0;
  static const int i = 5;
  if (b) {
      res = &i;
  } else {
      res = 0;
  }
  return *res; // expected-warning{{Dereference of null pointer}}
}

// Does not work when we new an object.
int testDynCastFail3() {
  A *a = new A();
  B *b = dynamic_cast<B*>(a);
  return b->m;
}

<|endoftext|>