<commit_before>#include "polylineStyle.h"

#include "tangram.h"
#include "platform.h"
#include "material.h"
#include "gl/shaderProgram.h"
#include "gl/typedMesh.h"
#include "scene/stops.h"
#include "scene/drawRule.h"
#include "tile/tile.h"
#include "util/mapProjection.h"
#include "glm/vec3.hpp"

namespace Tangram {

struct PolylineVertex {
    glm::vec3 pos;
    glm::vec2 texcoord;
    glm::vec4 extrude;
    GLuint abgr;
    GLfloat layer;
};

using Mesh = TypedMesh<PolylineVertex>;

PolylineStyle::PolylineStyle(std::string _name, Blending _blendMode, GLenum _drawMode)
    : Style(_name, _blendMode, _drawMode) {
}

void PolylineStyle::constructVertexLayout() {

    // TODO: Ideally this would be in the same location as the struct that it basically describes
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_texcoord", 2, GL_FLOAT, false, 0},
        {"a_extrude", 4, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0},
        {"a_layer", 1, GL_FLOAT, false, 0}
    }));

}

void PolylineStyle::constructShaderProgram() {

    std::string vertShaderSrcStr = stringFromFile("shaders/polyline.vs", PathType::internal);
    std::string fragShaderSrcStr = stringFromFile("shaders/polyline.fs", PathType::internal);

    m_shaderProgram->setSourceStrings(fragShaderSrcStr, vertShaderSrcStr);
}

VboMesh* PolylineStyle::newMesh() const {
    return new Mesh(m_vertexLayout, m_drawMode);
}

PolylineStyle::Parameters PolylineStyle::parseRule(const DrawRule& _rule) const {
    Parameters p;

    uint32_t cap = 0, join = 0;

    _rule.get(StyleParamKey::extrude, p.extrude);
    _rule.get(StyleParamKey::color, p.color);
    _rule.get(StyleParamKey::cap, cap);
    _rule.get(StyleParamKey::join, join);
    _rule.get(StyleParamKey::order, p.order);

    p.cap = static_cast<CapTypes>(cap);
    p.join = static_cast<JoinTypes>(join);

    p.outlineOrder = p.order; // will offset from fill later

    if (_rule.get(StyleParamKey::outline_color, p.outlineColor) |
        _rule.get(StyleParamKey::outline_order, p.outlineOrder) |
        _rule.contains(StyleParamKey::outline_width) |
        _rule.get(StyleParamKey::outline_cap, cap) |
        _rule.get(StyleParamKey::outline_join, join)) {
        p.outlineOn = true;
        p.outlineCap = static_cast<CapTypes>(cap);
        p.outlineJoin = static_cast<JoinTypes>(join);
    }

    return p;
}

void PolylineStyle::buildPolygon(const Polygon& _poly, const DrawRule& _rule, const Properties& _props,
                                 VboMesh& _mesh, Tile& _tile) const {

    for (const auto& line : _poly) {
        buildLine(line, _rule, _props, _mesh, _tile);
    }
}

double widthMeterToPixel(int _zoom, double _tileSize, double _width) {
    // pixel per meter at z == 0
    double meterRes = _tileSize / (2.0 * MapProjection::HALF_CIRCUMFERENCE);
    // pixel per meter at zoom
    meterRes *= exp2(_zoom);

    return _width * meterRes;
}

bool evalStyleParamWidth(StyleParamKey _key, const DrawRule& _rule, const Tile& _tile,
                         float& width, float& dWdZ){

    int zoom  = _tile.getID().z;
    double tileSize = _tile.getProjection()->TileSize();

    // NB: 0.5 because 'width' will be extruded in both directions
    double tileRes = 0.5 / tileSize;

    auto& styleParam = _rule.findParameter(_key);
    if (styleParam.stops) {

        width = styleParam.stops->evalWidth(zoom);
        width *= tileRes;

        dWdZ = styleParam.stops->evalWidth(zoom + 1);
        dWdZ *= tileRes;
        // NB: Multiply by 2 for the outline to get the expected stroke pixel width.
        if (_key == StyleParamKey::outline_width) {
            width *= 2;
            dWdZ *= 2;
        }

        dWdZ -= width;

        return true;
    }

    if (styleParam.value.is<StyleParam::Width>()) {
        auto& widthParam = styleParam.value.get<StyleParam::Width>();

        width = widthParam.value;

        if (widthParam.isMeter()) {
            width = widthMeterToPixel(zoom, tileSize, width);
            width *= tileRes;
            dWdZ = width * 2;
        } else {
            width *= tileRes;
            dWdZ = width;
        }

        if (_key == StyleParamKey::outline_width) {
            width *= 2;
            dWdZ *= 2;
        }

        dWdZ -= width;

        return true;
    }

    LOGD("Invalid type for Width '%d'\n", styleParam.value.which());
    return false;
}

void PolylineStyle::buildLine(const Line& _line, const DrawRule& _rule, const Properties& _props,
                              VboMesh& _mesh, Tile& _tile) const {

    std::vector<PolylineVertex> vertices;

    Parameters params = parseRule(_rule);
    GLuint abgr = params.color;

    float dWdZ = 0.f;
    float width = 0.f;

    if (!evalStyleParamWidth(StyleParamKey::width, _rule, _tile, width, dWdZ)) {
        return;
    }

    if ( (width > -FLT_EPSILON && width < FLT_EPSILON) &&
         (dWdZ > -FLT_EPSILON && dWdZ < FLT_EPSILON) ) { return; }

    if (Tangram::getDebugFlag(Tangram::DebugFlags::proxy_colors)) {
        abgr = abgr << (_tile.getID().z % 6);
    }

    float height = 0.0f;
    auto& extrude = params.extrude;

    if (extrude[0] != 0.0f || extrude[1] != 0.0f) {
        const static std::string key_height("height");

        height = _props.getNumeric(key_height) * _tile.getInverseScale();
        if (std::isnan(extrude[1])) {
            if (!std::isnan(extrude[0])) {
                height = extrude[0];
            }
        } else { height = extrude[1]; }
    }

    PolyLineBuilder builder {
        [&](const glm::vec3& coord, const glm::vec2& normal, const glm::vec2& uv) {
            glm::vec4 extrude = { normal.x, normal.y, width, dWdZ };
            vertices.push_back({ {coord.x, coord.y, height}, uv, extrude, abgr, (float)params.order });
        },
        [&](size_t sizeHint){ vertices.reserve(sizeHint); },
        params.cap,
        params.join
    };

    Builders::buildPolyLine(_line, builder);

    if (params.outlineOn) {

        GLuint abgrOutline = params.outlineColor;
        float outlineOrder = std::min(params.outlineOrder, params.order) - .5f;

        float widthOutline = 0.f;
        float dWdZOutline = 0.f;

        if (evalStyleParamWidth(StyleParamKey::outline_width, _rule, _tile, widthOutline, dWdZOutline) &&
           ((widthOutline < -FLT_EPSILON || widthOutline > FLT_EPSILON) ||
           (dWdZOutline < -FLT_EPSILON || dWdZOutline > FLT_EPSILON)) ) {

            widthOutline += width;
            dWdZOutline += dWdZ;

            if (params.outlineCap != params.cap || params.outlineJoin != params.join) {
                // need to re-triangulate with different cap and/or join
                builder.cap = params.outlineCap;
                builder.join = params.outlineJoin;
                Builders::buildPolyLine(_line, builder);
            } else {
                // re-use indices from original line
                size_t oldSize = builder.indices.size();
                size_t offset = vertices.size();
                builder.indices.reserve(2 * oldSize);

                for(size_t i = 0; i < oldSize; i++) {
                    builder.indices.push_back(offset + builder.indices[i]);
                }
                for (size_t i = 0; i < offset; i++) {
                    const auto& v = vertices[i];
                    glm::vec4 extrudeOutline = { v.extrude.x, v.extrude.y, widthOutline, dWdZOutline };
                    vertices.push_back({ v.pos, v.texcoord, extrudeOutline, abgrOutline, outlineOrder });
                }
            }
        }
    }

    auto& mesh = static_cast<Mesh&>(_mesh);
    mesh.addVertices(std::move(vertices), std::move(builder.indices));
}

}
<commit_msg>omit drawing line with negative width<commit_after>#include "polylineStyle.h"

#include "tangram.h"
#include "platform.h"
#include "material.h"
#include "gl/shaderProgram.h"
#include "gl/typedMesh.h"
#include "scene/stops.h"
#include "scene/drawRule.h"
#include "tile/tile.h"
#include "util/mapProjection.h"
#include "glm/vec3.hpp"

namespace Tangram {

struct PolylineVertex {
    glm::vec3 pos;
    glm::vec2 texcoord;
    glm::vec4 extrude;
    GLuint abgr;
    GLfloat layer;
};

using Mesh = TypedMesh<PolylineVertex>;

PolylineStyle::PolylineStyle(std::string _name, Blending _blendMode, GLenum _drawMode)
    : Style(_name, _blendMode, _drawMode) {
}

void PolylineStyle::constructVertexLayout() {

    // TODO: Ideally this would be in the same location as the struct that it basically describes
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 3, GL_FLOAT, false, 0},
        {"a_texcoord", 2, GL_FLOAT, false, 0},
        {"a_extrude", 4, GL_FLOAT, false, 0},
        {"a_color", 4, GL_UNSIGNED_BYTE, true, 0},
        {"a_layer", 1, GL_FLOAT, false, 0}
    }));

}

void PolylineStyle::constructShaderProgram() {

    std::string vertShaderSrcStr = stringFromFile("shaders/polyline.vs", PathType::internal);
    std::string fragShaderSrcStr = stringFromFile("shaders/polyline.fs", PathType::internal);

    m_shaderProgram->setSourceStrings(fragShaderSrcStr, vertShaderSrcStr);
}

VboMesh* PolylineStyle::newMesh() const {
    return new Mesh(m_vertexLayout, m_drawMode);
}

PolylineStyle::Parameters PolylineStyle::parseRule(const DrawRule& _rule) const {
    Parameters p;

    uint32_t cap = 0, join = 0;

    _rule.get(StyleParamKey::extrude, p.extrude);
    _rule.get(StyleParamKey::color, p.color);
    _rule.get(StyleParamKey::cap, cap);
    _rule.get(StyleParamKey::join, join);
    _rule.get(StyleParamKey::order, p.order);

    p.cap = static_cast<CapTypes>(cap);
    p.join = static_cast<JoinTypes>(join);

    p.outlineOrder = p.order; // will offset from fill later

    if (_rule.get(StyleParamKey::outline_color, p.outlineColor) |
        _rule.get(StyleParamKey::outline_order, p.outlineOrder) |
        _rule.contains(StyleParamKey::outline_width) |
        _rule.get(StyleParamKey::outline_cap, cap) |
        _rule.get(StyleParamKey::outline_join, join)) {
        p.outlineOn = true;
        p.outlineCap = static_cast<CapTypes>(cap);
        p.outlineJoin = static_cast<JoinTypes>(join);
    }

    return p;
}

void PolylineStyle::buildPolygon(const Polygon& _poly, const DrawRule& _rule, const Properties& _props,
                                 VboMesh& _mesh, Tile& _tile) const {

    for (const auto& line : _poly) {
        buildLine(line, _rule, _props, _mesh, _tile);
    }
}

double widthMeterToPixel(int _zoom, double _tileSize, double _width) {
    // pixel per meter at z == 0
    double meterRes = _tileSize / (2.0 * MapProjection::HALF_CIRCUMFERENCE);
    // pixel per meter at zoom
    meterRes *= exp2(_zoom);

    return _width * meterRes;
}

bool evalStyleParamWidth(StyleParamKey _key, const DrawRule& _rule, const Tile& _tile,
                         float& width, float& dWdZ){

    int zoom  = _tile.getID().z;
    double tileSize = _tile.getProjection()->TileSize();

    // NB: 0.5 because 'width' will be extruded in both directions
    double tileRes = 0.5 / tileSize;

    auto& styleParam = _rule.findParameter(_key);
    if (styleParam.stops) {

        width = styleParam.stops->evalWidth(zoom);
        width *= tileRes;

        dWdZ = styleParam.stops->evalWidth(zoom + 1);
        dWdZ *= tileRes;
        // NB: Multiply by 2 for the outline to get the expected stroke pixel width.
        if (_key == StyleParamKey::outline_width) {
            width *= 2;
            dWdZ *= 2;
        }

        dWdZ -= width;

        return true;
    }

    if (styleParam.value.is<StyleParam::Width>()) {
        auto& widthParam = styleParam.value.get<StyleParam::Width>();

        width = widthParam.value;

        if (widthParam.isMeter()) {
            width = widthMeterToPixel(zoom, tileSize, width);
            width *= tileRes;
            dWdZ = width * 2;
        } else {
            width *= tileRes;
            dWdZ = width;
        }

        if (_key == StyleParamKey::outline_width) {
            width *= 2;
            dWdZ *= 2;
        }

        dWdZ -= width;

        return true;
    }

    LOGD("Invalid type for Width '%d'\n", styleParam.value.which());
    return false;
}

void PolylineStyle::buildLine(const Line& _line, const DrawRule& _rule, const Properties& _props,
                              VboMesh& _mesh, Tile& _tile) const {

    std::vector<PolylineVertex> vertices;

    Parameters params = parseRule(_rule);
    GLuint abgr = params.color;

    float dWdZ = 0.f;
    float width = 0.f;

    if (!evalStyleParamWidth(StyleParamKey::width, _rule, _tile, width, dWdZ)) {
        return;
    }

    if (width < FLT_EPSILON && dWdZ < FLT_EPSILON) { return; }

    if (Tangram::getDebugFlag(Tangram::DebugFlags::proxy_colors)) {
        abgr = abgr << (_tile.getID().z % 6);
    }

    float height = 0.0f;
    auto& extrude = params.extrude;

    if (extrude[0] != 0.0f || extrude[1] != 0.0f) {
        const static std::string key_height("height");

        height = _props.getNumeric(key_height) * _tile.getInverseScale();
        if (std::isnan(extrude[1])) {
            if (!std::isnan(extrude[0])) {
                height = extrude[0];
            }
        } else { height = extrude[1]; }
    }

    PolyLineBuilder builder {
        [&](const glm::vec3& coord, const glm::vec2& normal, const glm::vec2& uv) {
            glm::vec4 extrude = { normal.x, normal.y, width, dWdZ };
            vertices.push_back({ {coord.x, coord.y, height}, uv, extrude, abgr, (float)params.order });
        },
        [&](size_t sizeHint){ vertices.reserve(sizeHint); },
        params.cap,
        params.join
    };

    Builders::buildPolyLine(_line, builder);

    if (params.outlineOn) {

        GLuint abgrOutline = params.outlineColor;
        float outlineOrder = std::min(params.outlineOrder, params.order) - .5f;

        float widthOutline = 0.f;
        float dWdZOutline = 0.f;

        if (evalStyleParamWidth(StyleParamKey::outline_width, _rule, _tile, widthOutline, dWdZOutline) &&
            ((widthOutline > FLT_EPSILON && dWdZOutline >= 0) ||
             (dWdZOutline > FLT_EPSILON && widthOutline >= 0))) {

            widthOutline += width;
            dWdZOutline += dWdZ;

            if (params.outlineCap != params.cap || params.outlineJoin != params.join) {
                // need to re-triangulate with different cap and/or join
                builder.cap = params.outlineCap;
                builder.join = params.outlineJoin;
                Builders::buildPolyLine(_line, builder);
            } else {
                // re-use indices from original line
                size_t oldSize = builder.indices.size();
                size_t offset = vertices.size();
                builder.indices.reserve(2 * oldSize);

                for(size_t i = 0; i < oldSize; i++) {
                    builder.indices.push_back(offset + builder.indices[i]);
                }
                for (size_t i = 0; i < offset; i++) {
                    const auto& v = vertices[i];
                    glm::vec4 extrudeOutline = { v.extrude.x, v.extrude.y, widthOutline, dWdZOutline };
                    vertices.push_back({ v.pos, v.texcoord, extrudeOutline, abgrOutline, outlineOrder });
                }
            }
        }
    }

    auto& mesh = static_cast<Mesh&>(_mesh);
    mesh.addVertices(std::move(vertices), std::move(builder.indices));
}

}
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Wolf <claire@symbioticeda.com>
 *  Copyright (C) 2019  Dan Ravensloft <dan.ravensloft@gmail.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/celltypes.h"
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthIntelALMPass : public ScriptPass {
	SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {}

	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_intel_alm [options]\n");
		log("\n");
		log("This command runs synthesis for ALM-based Intel FPGAs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module\n");
		log("\n");
		log("    -family <family>\n");
		log("        target one of:\n");
		log("        \"cyclonev\"    - Cyclone V (default)\n");
		log("        \"cyclone10gx\" - Cyclone 10GX\n");
		log("\n");
		log("    -vqm <file>\n");
		log("        write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
		log("        output file is omitted if this parameter is not specified. Implies -quartus.\n");
		log("\n");
		log("    -noflatten\n");
		log("        do not flatten design before synthesis; useful for per-module area statistics\n");
		log("\n");
		log("    -quartus\n");
		log("        output a netlist using Quartus cells instead of MISTRAL_* cells\n");
		log("\n");
		log("    -dff\n");
		log("        pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -nolutram\n");
		log("        do not use LUT RAM cells in output netlist\n");
		log("\n");
		log("    -nobram\n");
		log("        do not use block RAM cells in output netlist\n");
		log("\n");
		log("    -nodsp\n");
		log("        do not map multipliers to MISTRAL_MUL cells\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_opt, family_opt, bram_type, vout_file;
	bool flatten, quartus, nolutram, nobram, dff, nodsp;

	void clear_flags() override
	{
		top_opt = "-auto-top";
		family_opt = "cyclonev";
		bram_type = "m10k";
		vout_file = "";
		flatten = true;
		quartus = false;
		nolutram = false;
		nobram = false;
		dff = false;
		nodsp = false;
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) override
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-family" && argidx + 1 < args.size()) {
				family_opt = args[++argidx];
				continue;
			}
			if (args[argidx] == "-top" && argidx + 1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-vqm" && argidx + 1 < args.size()) {
				quartus = true;
				vout_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx + 1 < args.size()) {
				size_t pos = args[argidx + 1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos + 1);
				continue;
			}
			if (args[argidx] == "-quartus") {
				quartus = true;
				continue;
			}
			if (args[argidx] == "-nolutram") {
				nolutram = true;
				continue;
			}
			if (args[argidx] == "-nobram") {
				nobram = true;
				continue;
			}
			if (args[argidx] == "-nodsp") {
				nodsp = true;
				continue;
			}
			if (args[argidx] == "-noflatten") {
				flatten = false;
				continue;
			}
			if (args[argidx] == "-dff") {
				dff = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This command only operates on fully selected designs!\n");

		if (family_opt == "cyclonev") {
			bram_type = "m10k";
		} else if (family_opt == "cyclone10gx") {
			bram_type = "m20k";
		} else {
			log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str());
		}

		log_header(design, "Executing SYNTH_INTEL_ALM pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	void script() override
	{
		if (help_mode) {
			family_opt = "<family>";
			bram_type = "<bram_type>";
		}

		if (check_label("begin")) {
			if (family_opt == "cyclonev")
				run(stringf("read_verilog -sv -lib +/intel_alm/%s/cells_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dsp_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s -icells +/intel_alm/common/abc9_model.v", family_opt.c_str()));

			// Misc and common cells
			run("read_verilog -lib +/intel/common/altpll_bb.v");
			run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
		}

		if (check_label("coarse")) {
			run("proc");
			if (flatten || help_mode)
				run("flatten", "(skip if -noflatten)");
			run("tribuf -logic");
			run("deminout");
			run("opt_expr");
			run("opt_clean");
			run("check");
			run("opt -nodffe -nosdff");
			run("fsm");
			run("opt");
			run("wreduce");
			run("peepopt");
			run("opt_clean");
			run("share");
			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
			run("opt_expr");
			run("opt_clean");
			if (help_mode) {
				run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
			} else if (!nodsp) {
				// Cyclone V supports 9x9 multiplication, Cyclone 10 GX does not.
				run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27  -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=19 -D DSP_NAME=__MUL27X27");
				run("chtype -set $mul t:$__soft_mul");
				if (family_opt == "cyclonev") {
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10 -D DSP_NAME=__MUL18X18");
					run("chtype -set $mul t:$__soft_mul");
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL9X9");
					run("chtype -set $mul t:$__soft_mul");
				} else if (family_opt == "cyclone10gx") {
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL18X18");
					run("chtype -set $mul t:$__soft_mul");
				}
			}
			run("alumacc");
			run("techmap -map +/intel_alm/common/arith_alm_map.v -map +/intel_alm/common/dsp_map.v");
			run("opt");
			run("memory -nomap");
			run("opt_clean");
		}

		if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
			run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
			if (help_mode || bram_type != "m10k")
				run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
		}

		if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
			run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)");
		}

		if (check_label("map_ffram")) {
			run("memory_map");
			run("opt -full");
		}

		if (check_label("map_ffs")) {
			run("techmap");
			run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0");
			run("techmap -map +/intel_alm/common/dff_map.v");
			run("opt -full -undriven -mux_undef");
			run("clean -purge");
		}

		if (check_label("map_luts")) {
			run("techmap -map +/intel_alm/common/abc9_map.v");
			run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : ""));
			run("techmap -map +/intel_alm/common/abc9_unmap.v");
			run("techmap -map +/intel_alm/common/alm_map.v");
			run("opt -fast");
			run("autoname");
			run("clean");
		}

		if (check_label("check")) {
			run("hierarchy -check");
			run("stat");
			run("check");
		}

		if (check_label("quartus")) {
			if (quartus || help_mode) {
				// Quartus ICEs if you have a wire which has `[]` in its name,
				// which Yosys produces when building memories out of flops.
				run("rename -hide w:*[* w:*]*");
				// VQM mode does not support 'x, so replace those with zero.
				run("setundef -zero");
				// VQM mode does not support multi-bit constant assignments
				// (e.g. 2'b00 is an error), so as a workaround use references
				// to constant driver cells, which Quartus accepts.
				run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q");
				// Rename from Yosys-internal MISTRAL_* cells to Quartus cells.
				run(stringf("techmap -D %s -map +/intel_alm/common/quartus_rename.v", family_opt.c_str()));
			}
		}

		if (check_label("vqm")) {
			if (!vout_file.empty() || help_mode) {
				run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "<file-name>" : vout_file.c_str()));
			}
		}
	}
} SynthIntelALMPass;

PRIVATE_NAMESPACE_END
<commit_msg>intel_alm: better map wide but shallow multiplies<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Claire Wolf <claire@symbioticeda.com>
 *  Copyright (C) 2019  Dan Ravensloft <dan.ravensloft@gmail.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/celltypes.h"
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthIntelALMPass : public ScriptPass {
	SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {}

	void help() override
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth_intel_alm [options]\n");
		log("\n");
		log("This command runs synthesis for ALM-based Intel FPGAs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module\n");
		log("\n");
		log("    -family <family>\n");
		log("        target one of:\n");
		log("        \"cyclonev\"    - Cyclone V (default)\n");
		log("        \"cyclone10gx\" - Cyclone 10GX\n");
		log("\n");
		log("    -vqm <file>\n");
		log("        write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
		log("        output file is omitted if this parameter is not specified. Implies -quartus.\n");
		log("\n");
		log("    -noflatten\n");
		log("        do not flatten design before synthesis; useful for per-module area statistics\n");
		log("\n");
		log("    -quartus\n");
		log("        output a netlist using Quartus cells instead of MISTRAL_* cells\n");
		log("\n");
		log("    -dff\n");
		log("        pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)\n");
		log("\n");
		log("    -run <from_label>:<to_label>\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("    -nolutram\n");
		log("        do not use LUT RAM cells in output netlist\n");
		log("\n");
		log("    -nobram\n");
		log("        do not use block RAM cells in output netlist\n");
		log("\n");
		log("    -nodsp\n");
		log("        do not map multipliers to MISTRAL_MUL cells\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_opt, family_opt, bram_type, vout_file;
	bool flatten, quartus, nolutram, nobram, dff, nodsp;

	void clear_flags() override
	{
		top_opt = "-auto-top";
		family_opt = "cyclonev";
		bram_type = "m10k";
		vout_file = "";
		flatten = true;
		quartus = false;
		nolutram = false;
		nobram = false;
		dff = false;
		nodsp = false;
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) override
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-family" && argidx + 1 < args.size()) {
				family_opt = args[++argidx];
				continue;
			}
			if (args[argidx] == "-top" && argidx + 1 < args.size()) {
				top_opt = "-top " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-vqm" && argidx + 1 < args.size()) {
				quartus = true;
				vout_file = args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx + 1 < args.size()) {
				size_t pos = args[argidx + 1].find(':');
				if (pos == std::string::npos)
					break;
				run_from = args[++argidx].substr(0, pos);
				run_to = args[argidx].substr(pos + 1);
				continue;
			}
			if (args[argidx] == "-quartus") {
				quartus = true;
				continue;
			}
			if (args[argidx] == "-nolutram") {
				nolutram = true;
				continue;
			}
			if (args[argidx] == "-nobram") {
				nobram = true;
				continue;
			}
			if (args[argidx] == "-nodsp") {
				nodsp = true;
				continue;
			}
			if (args[argidx] == "-noflatten") {
				flatten = false;
				continue;
			}
			if (args[argidx] == "-dff") {
				dff = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This command only operates on fully selected designs!\n");

		if (family_opt == "cyclonev") {
			bram_type = "m10k";
		} else if (family_opt == "cyclone10gx") {
			bram_type = "m20k";
		} else {
			log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str());
		}

		log_header(design, "Executing SYNTH_INTEL_ALM pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	void script() override
	{
		if (help_mode) {
			family_opt = "<family>";
			bram_type = "<bram_type>";
		}

		if (check_label("begin")) {
			if (family_opt == "cyclonev")
				run(stringf("read_verilog -sv -lib +/intel_alm/%s/cells_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dsp_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str()));
			run(stringf("read_verilog -specify -lib -D %s -icells +/intel_alm/common/abc9_model.v", family_opt.c_str()));

			// Misc and common cells
			run("read_verilog -lib +/intel/common/altpll_bb.v");
			run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
		}

		if (check_label("coarse")) {
			run("proc");
			if (flatten || help_mode)
				run("flatten", "(skip if -noflatten)");
			run("tribuf -logic");
			run("deminout");
			run("opt_expr");
			run("opt_clean");
			run("check");
			run("opt -nodffe -nosdff");
			run("fsm");
			run("opt");
			run("wreduce");
			run("peepopt");
			run("opt_clean");
			run("share");
			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
			run("opt_expr");
			run("opt_clean");
			if (help_mode) {
				run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
			} else if (!nodsp) {
				// Cyclone V supports 9x9 multiplication, Cyclone 10 GX does not.
				run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27  -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL27X27");
				run("chtype -set $mul t:$__soft_mul");
				run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=19 -D DSP_NAME=__MUL27X27");
				run("chtype -set $mul t:$__soft_mul");
				if (family_opt == "cyclonev") {
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL18X18");
					run("chtype -set $mul t:$__soft_mul");
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=10 -D DSP_NAME=__MUL18X18");
					run("chtype -set $mul t:$__soft_mul");
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL9X9");
					run("chtype -set $mul t:$__soft_mul");
				} else if (family_opt == "cyclone10gx") {
					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL18X18");
					run("chtype -set $mul t:$__soft_mul");
				}
			}
			run("alumacc");
			run("techmap -map +/intel_alm/common/arith_alm_map.v -map +/intel_alm/common/dsp_map.v");
			run("opt");
			run("memory -nomap");
			run("opt_clean");
		}

		if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
			run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
			if (help_mode || bram_type != "m10k")
				run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
		}

		if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
			run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)");
		}

		if (check_label("map_ffram")) {
			run("memory_map");
			run("opt -full");
		}

		if (check_label("map_ffs")) {
			run("techmap");
			run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0");
			run("techmap -map +/intel_alm/common/dff_map.v");
			run("opt -full -undriven -mux_undef");
			run("clean -purge");
		}

		if (check_label("map_luts")) {
			run("techmap -map +/intel_alm/common/abc9_map.v");
			run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : ""));
			run("techmap -map +/intel_alm/common/abc9_unmap.v");
			run("techmap -map +/intel_alm/common/alm_map.v");
			run("opt -fast");
			run("autoname");
			run("clean");
		}

		if (check_label("check")) {
			run("hierarchy -check");
			run("stat");
			run("check");
		}

		if (check_label("quartus")) {
			if (quartus || help_mode) {
				// Quartus ICEs if you have a wire which has `[]` in its name,
				// which Yosys produces when building memories out of flops.
				run("rename -hide w:*[* w:*]*");
				// VQM mode does not support 'x, so replace those with zero.
				run("setundef -zero");
				// VQM mode does not support multi-bit constant assignments
				// (e.g. 2'b00 is an error), so as a workaround use references
				// to constant driver cells, which Quartus accepts.
				run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q");
				// Rename from Yosys-internal MISTRAL_* cells to Quartus cells.
				run(stringf("techmap -D %s -map +/intel_alm/common/quartus_rename.v", family_opt.c_str()));
			}
		}

		if (check_label("vqm")) {
			if (!vout_file.empty() || help_mode) {
				run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "<file-name>" : vout_file.c_str()));
			}
		}
	}
} SynthIntelALMPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>#include "SkeletonIO.h"

#include <sprite2/Joint.h>
#include <sprite2/JointPose.h>
#include <sprite2/SkeletonPose.h>

namespace gum
{

/************************************************************************/
/* class JointPose                                                      */
/************************************************************************/

void SkeletonIO::Load(const Json::Value& val, s2::JointPose& pose)
{
	pose.trans.x = val["trans_x"].asDouble();
	pose.trans.y = val["trans_y"].asDouble();
	pose.rot = val["rot"].asDouble();
	pose.scale = val["scale"].asDouble();
}

void SkeletonIO::Store(Json::Value& val, const s2::JointPose& pose)
{
	val["trans_x"] = pose.trans.x;
	val["trans_y"] = pose.trans.y;
	val["rot"] = pose.rot;
	val["scale"] = pose.scale;
}

/************************************************************************/
/* class SkeletonPose                                                   */
/************************************************************************/

void SkeletonIO::Load(const Json::Value& val, s2::SkeletonPose& pose)
{
	std::vector<s2::JointPose> joints;
	joints.reserve(val["joint"].size());
	for (int i = 0, n = val["joint"].size(); i < n; ++i) {
		s2::JointPose joint;
		Load(val["joint"][i], joint);
		joints.push_back(joint);
	}
	pose.SetJointPose(joints);
}

void SkeletonIO::Store(Json::Value& val, const s2::SkeletonPose& pose)
{
	const std::vector<s2::JointPose>& joints = pose.GetJointPose();
	for (int i = 0, n = joints.size(); i < n; ++i) {
		Store(val["joint"][i], joints[i]);
	}
}

}<commit_msg>[CHANGED] no uniform scale<commit_after>#include "SkeletonIO.h"

#include <sprite2/Joint.h>
#include <sprite2/JointPose.h>
#include <sprite2/SkeletonPose.h>

namespace gum
{

/************************************************************************/
/* class JointPose                                                      */
/************************************************************************/

void SkeletonIO::Load(const Json::Value& val, s2::JointPose& pose)
{
	pose.trans.x	= val["trans_x"].asDouble();
	pose.trans.y	= val["trans_y"].asDouble();
	pose.rot		= val["rot"].asDouble();
	pose.scale.x	= val["scale_x"].asDouble();
	pose.scale.y	= val["scale_y"].asDouble();
}

void SkeletonIO::Store(Json::Value& val, const s2::JointPose& pose)
{
	val["trans_x"]	= pose.trans.x;
	val["trans_y"]	= pose.trans.y;
	val["rot"]		= pose.rot;
	val["scale_x"]	= pose.scale.x;
	val["scale_y"]	= pose.scale.y;
}

/************************************************************************/
/* class SkeletonPose                                                   */
/************************************************************************/

void SkeletonIO::Load(const Json::Value& val, s2::SkeletonPose& pose)
{
	std::vector<s2::JointPose> joints;
	joints.reserve(val["joint"].size());
	for (int i = 0, n = val["joint"].size(); i < n; ++i) {
		s2::JointPose joint;
		Load(val["joint"][i], joint);
		joints.push_back(joint);
	}
	pose.SetJointPose(joints);
}

void SkeletonIO::Store(Json::Value& val, const s2::SkeletonPose& pose)
{
	const std::vector<s2::JointPose>& joints = pose.GetJointPose();
	for (int i = 0, n = joints.size(); i < n; ++i) {
		Store(val["joint"][i], joints[i]);
	}
}

}<|endoftext|>


<commit_before>#include "iteration/initializer/set_fixed_terms.h"

#include <array>

#include "data/system.h"
#include "data/system/tests/bilinear_term_mock.h"
#include "iteration/updater/tests/fixed_updater_mock.h"
#include "test_helpers/gmock_wrapper.h"
#include "test_helpers/test_helper_functions.h"

namespace  {

using namespace bart;

using ::testing::NiceMock, ::testing::Ref, ::testing::Return;

class IterationInitializerSetFixedTermsTest : public ::testing::Test {
 protected:
  using InitializerType = iteration::initializer::SetFixedTerms;
  using MockFixedUpdaterType = iteration::updater::FixedUpdaterMock;
  using MockBilinearTermType = data::system::BilinearTermMock;

  IterationInitializerSetFixedTermsTest()
      : total_groups_(btest::RandomDouble(1, 5)),
        total_angles_(btest::RandomDouble(1, 5)) {}

  // Initializer to be tested
  std::unique_ptr<InitializerType> test_initializer_;

  // Supporting objects
  data::System test_system_;
  std::shared_ptr<data::system::MPISparseMatrix> mpi_matrix_ptr_;

  // Pointers for observing mocks owned by other objects
  MockBilinearTermType* bilinear_term_obs_ptr_ = nullptr;
  MockFixedUpdaterType* updater_obs_ptr_ = nullptr;

  // Random values for testing
  const int total_groups_;
  const int total_angles_;

  void SetUp() override;
};

void IterationInitializerSetFixedTermsTest::SetUp() {
  // Set up testing object
  auto mock_fixed_updater_ptr =
      std::make_unique<NiceMock<MockFixedUpdaterType>>();
  test_initializer_ =
      std::make_unique<InitializerType>(std::move(mock_fixed_updater_ptr),
                                                  total_groups_,
                                                  total_angles_);

  // Set up supporting objects
  auto mock_bilinear_term = std::make_unique<MockBilinearTermType>();
  test_system_.left_hand_side_ptr_ = std::move(mock_bilinear_term);
  mpi_matrix_ptr_ = std::make_shared<data::system::MPISparseMatrix>();

  // Set up observing pointers
  updater_obs_ptr_ =
      dynamic_cast<MockFixedUpdaterType*>(test_initializer_->fixed_updater_ptr());
  bilinear_term_obs_ptr_ =
      dynamic_cast<MockBilinearTermType*>(test_system_.left_hand_side_ptr_.get());
}

TEST_F(IterationInitializerSetFixedTermsTest, Constructor) {
  EXPECT_TRUE(updater_obs_ptr_ != nullptr);
  EXPECT_EQ(test_initializer_->total_angles(), total_angles_);
  EXPECT_EQ(test_initializer_->total_groups(), total_groups_);
}

TEST_F(IterationInitializerSetFixedTermsTest, ConstructorThrows) {
  // Constructor should throw if fixed updater ptr is null
  std::unique_ptr<MockFixedUpdaterType> null_fixed_updater = nullptr;
  EXPECT_ANY_THROW(
      InitializerType initializer(std::move(null_fixed_updater),
                                  total_groups_,
                                  total_angles_);
  );

  // Constructor should throw for bad groups and angle values
  std::array<int, 2> bad_values = {0, -1};

  for (int value : bad_values) {
    auto fixed_updater = std::make_unique<MockFixedUpdaterType>();
    EXPECT_ANY_THROW(
        InitializerType initializer(std::move(fixed_updater),
                                    value,
                                    total_angles_);
    );
    fixed_updater = std::make_unique<MockFixedUpdaterType>();
    EXPECT_ANY_THROW(
        InitializerType initializer(std::move(fixed_updater),
                                    total_groups_,
                                    value);
    );
  }
}

TEST_F(IterationInitializerSetFixedTermsTest, Initialize) {
  // Initializer should access all left hand side terms (all groups/angles)
  for (int group = 0; group < total_groups_; ++group) {
    for (int angle = 0; angle < total_angles_; ++angle) {
      EXPECT_CALL(*updater_obs_ptr_, UpdateFixedTerms(Ref(test_system_),
                                                      group, angle));
    }
  }

  test_initializer_->Initialize(test_system_);
}

} // namespace<commit_msg>removed extraneous objects and fixed spacing for tests for SetFixedTerms<commit_after>#include "iteration/initializer/set_fixed_terms.h"

#include <array>

#include "data/system.h"
#include "data/system/tests/bilinear_term_mock.h"
#include "iteration/updater/tests/fixed_updater_mock.h"
#include "test_helpers/gmock_wrapper.h"
#include "test_helpers/test_helper_functions.h"

namespace  {

using namespace bart;

using ::testing::NiceMock, ::testing::Ref, ::testing::Return;

class IterationInitializerSetFixedTermsTest : public ::testing::Test {
 protected:
  using InitializerType = iteration::initializer::SetFixedTerms;
  using MockFixedUpdaterType = iteration::updater::FixedUpdaterMock;
  using MockBilinearTermType = data::system::BilinearTermMock;

  IterationInitializerSetFixedTermsTest()
      : total_groups_(btest::RandomDouble(1, 5)),
        total_angles_(btest::RandomDouble(1, 5)) {}

  // Initializer to be tested
  std::unique_ptr<InitializerType> test_initializer_;

  // Supporting objects
  data::System test_system_;

  // Pointers for observing mocks owned by other objects
  MockFixedUpdaterType* updater_obs_ptr_ = nullptr;

  // Random values for testing
  const int total_groups_;
  const int total_angles_;

  void SetUp() override;
};

void IterationInitializerSetFixedTermsTest::SetUp() {
  // Set up testing object
  auto mock_fixed_updater_ptr =
      std::make_unique<NiceMock<MockFixedUpdaterType>>();
  test_initializer_ =
      std::make_unique<InitializerType>(std::move(mock_fixed_updater_ptr),
                                                  total_groups_,
                                                  total_angles_);

  // Set up supporting objects
  auto mock_bilinear_term = std::make_unique<MockBilinearTermType>();
  test_system_.left_hand_side_ptr_ = std::move(mock_bilinear_term);

  // Set up observing pointers
  updater_obs_ptr_ =
      dynamic_cast<MockFixedUpdaterType*>(test_initializer_->fixed_updater_ptr());
}

TEST_F(IterationInitializerSetFixedTermsTest, Constructor) {
  EXPECT_TRUE(updater_obs_ptr_ != nullptr);
  EXPECT_EQ(test_initializer_->total_angles(), total_angles_);
  EXPECT_EQ(test_initializer_->total_groups(), total_groups_);
}

TEST_F(IterationInitializerSetFixedTermsTest, ConstructorThrows) {
  // Constructor should throw if fixed updater ptr is null
  std::unique_ptr<MockFixedUpdaterType> null_fixed_updater = nullptr;
  EXPECT_ANY_THROW(InitializerType initializer(std::move(null_fixed_updater),
                                               total_groups_, total_angles_););

  // Constructor should throw for bad groups and angle values
  std::array<int, 2> bad_values = {0, -1};

  for (int value : bad_values) {
    auto fixed_updater = std::make_unique<MockFixedUpdaterType>();
    EXPECT_ANY_THROW(InitializerType initializer(std::move(fixed_updater),
                                                 value, total_angles_););
    fixed_updater = std::make_unique<MockFixedUpdaterType>();
    EXPECT_ANY_THROW(InitializerType initializer(std::move(fixed_updater),
                                                 total_groups_, value););
  }
}

TEST_F(IterationInitializerSetFixedTermsTest, Initialize) {
  // Initializer should access all left hand side terms (all groups/angles)
  for (int group = 0; group < total_groups_; ++group) {
    for (int angle = 0; angle < total_angles_; ++angle) {
      EXPECT_CALL(*updater_obs_ptr_, UpdateFixedTerms(Ref(test_system_),
                                                      group, angle));
    }
  }

  test_initializer_->Initialize(test_system_);
}

} // namespace<|endoftext|>


<commit_before>/*!
    \file file_lock.cpp
    \brief File-lock synchronization primitive implementation
    \author Ivan Shynkarenka
    \date 01.09.2016
    \copyright MIT License
*/

#include "threads/file_lock.h"

#include "errors/fatal.h"
#include "filesystem/exceptions.h"

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#elif defined(unix) || defined(__unix) || defined(__unix__)
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#endif

namespace CppCommon {

class FileLock::Impl
{
public:
    Impl(const Path& path) : _path(path)
    {
#if defined(_WIN32) || defined(_WIN64)
        std::wstring wpath = _path.to_wstring();

        // Retries in CreateFile, see http://support.microsoft.com/kb/316609
        const int attempts = 5;
        const int sleep = 250;
        for (int attempt = 0; attempt < attempts; ++attempt)
        {
            _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, nullptr);
            if (_file == INVALID_HANDLE_VALUE)
            {
                if (GetLastError() == ERROR_SHARING_VIOLATION)
                {
                    Sleep(sleep);
                    continue;
                }
                else
                {
                    _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, nullptr);
                    if (_file == INVALID_HANDLE_VALUE)
                    {
                        if (GetLastError() == ERROR_SHARING_VIOLATION)
                        {
                            Sleep(sleep);
                            continue;
                        }
                        else
                            break;
                    }
                    else
                    {
                        _owner = false;
                        return;
                    }
                }
            }
            else
            {
                _owner = true;
                return;
            }
        }
        throwex FileSystemException("Cannot create or open file-lock file!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        _file = open(_path.native().c_str(), O_CREAT | O_EXCL | O_RDWR, 0644);
        if (_file < 0)
        {
            if (errno == EEXIST)
            {
                _file = open(_path.native().c_str(), O_CREAT | O_RDWR, 0644);
                if (_file >= 0)
                {
                    _owner = false;
                    return;
                }
            }
        }
        else
        {
            _owner = true;
            return;
        }
        throwex FileSystemException("Cannot create or open file-lock! file").Attach(_path);
#endif
    }

    ~Impl()
    {
#if defined(_WIN32) || defined(_WIN64)
        if (!CloseHandle(_file))
            fatality(FileSystemException("Cannot close the file-lock handle!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            if (!DeleteFileW(_path.to_wstring().c_str()))
                fatality(FileSystemException("Cannot delete the file-lock file!").Attach(_path));
        }
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = close(_file);
        if (result != 0)
            fatality(FileSystemException("Cannot close the file-lock descriptor!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            result = unlink(_path.native().c_str());
            if (result != 0)
                fatality(FileSystemException("Cannot unlink the file-lock file!").Attach(_path));
        }
#endif
    }

    const Path& path() const noexcept { return _path; }

    bool TryLockRead()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        else
           return true;
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_SH | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        else
           return true;
#endif
    }

    bool TryLockWrite()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        else
           return true;
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_EX | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        else
           return true;
#endif
    }

    void LockRead()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, 0, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_SH);
        if (result != 0)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#endif
    }

    void LockWrite()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_EX);
        if (result != 0)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#endif
    }

    void UnlockRead()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#endif
    }

    void UnlockWrite()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#endif
    }

private:
    Path _path;
#if defined(_WIN32) || defined(_WIN64)
    HANDLE _file;
#elif defined(unix) || defined(__unix) || defined(__unix__)
    int _file;
#endif
    bool _owner;
};

FileLock::FileLock(const Path& path) : _pimpl(new Impl(path))
{
}

FileLock::~FileLock()
{
}

const Path& FileLock::path() const noexcept
{
    return _pimpl->path();
}

bool FileLock::TryLockRead()
{
    return _pimpl->TryLockRead();
}

bool FileLock::TryLockWrite()
{
    return _pimpl->TryLockWrite();
}

void FileLock::LockRead()
{
    _pimpl->LockRead();
}

void FileLock::LockWrite()
{
    _pimpl->LockWrite();
}

void FileLock::UnlockRead()
{
    _pimpl->UnlockRead();
}

void FileLock::UnlockWrite()
{
    _pimpl->UnlockWrite();
}

} // namespace CppCommon
<commit_msg>Bugfixing<commit_after>/*!
    \file file_lock.cpp
    \brief File-lock synchronization primitive implementation
    \author Ivan Shynkarenka
    \date 01.09.2016
    \copyright MIT License
*/

#include "threads/file_lock.h"

#include "errors/fatal.h"
#include "filesystem/exceptions.h"

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#elif defined(unix) || defined(__unix) || defined(__unix__)
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#endif

namespace CppCommon {

class FileLock::Impl
{
public:
    Impl(const Path& path) : _path(path)
    {
#if defined(_WIN32) || defined(_WIN64)
        std::wstring wpath = _path.to_wstring();

        // Retries in CreateFile, see http://support.microsoft.com/kb/316609
        const int attempts = 5;
        const int sleep = 250;
        for (int attempt = 0; attempt < attempts; ++attempt)
        {
            _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, nullptr);
            if (_file == INVALID_HANDLE_VALUE)
            {
                if (GetLastError() == ERROR_SHARING_VIOLATION)
                {
                    Sleep(sleep);
                    continue;
                }
                else
                {
                    _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, nullptr);
                    if (_file == INVALID_HANDLE_VALUE)
                    {
                        if (GetLastError() == ERROR_SHARING_VIOLATION)
                        {
                            Sleep(sleep);
                            continue;
                        }
                        else
                            break;
                    }
                    else
                    {
                        _owner = false;
                        return;
                    }
                }
            }
            else
            {
                _owner = true;
                return;
            }
        }
        throwex FileSystemException("Cannot create or open file-lock file!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        _file = open(_path.native().c_str(), O_CREAT | O_EXCL | O_RDWR, 0644);
        if (_file < 0)
        {
            if (errno == EEXIST)
            {
                _file = open(_path.native().c_str(), O_CREAT | O_RDWR, 0644);
                if (_file >= 0)
                {
                    _owner = false;
                    return;
                }
            }
        }
        else
        {
            _owner = true;
            return;
        }
        throwex FileSystemException("Cannot create or open file-lock! file").Attach(_path);
#endif
    }

    ~Impl()
    {
#if defined(_WIN32) || defined(_WIN64)
        if (!CloseHandle(_file))
            fatality(FileSystemException("Cannot close the file-lock handle!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            if (!DeleteFileW(_path.to_wstring().c_str()))
                fatality(FileSystemException("Cannot delete the file-lock file!").Attach(_path));
        }
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = close(_file);
        if (result != 0)
            fatality(FileSystemException("Cannot close the file-lock descriptor!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            result = unlink(_path.native().c_str());
            if (result != 0)
                fatality(FileSystemException("Cannot unlink the file-lock file!").Attach(_path));
        }
#endif
    }

    const Path& path() const noexcept { return _path; }

    bool TryLockRead()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        else
           return true;
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_SH | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        else
           return true;
#endif
    }

    bool TryLockWrite()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        else
           return true;
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_EX | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        else
           return true;
#endif
    }

    void LockRead()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, 0, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_SH);
        if (result != 0)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#endif
    }

    void LockWrite()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_EX);
        if (result != 0)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#endif
    }

    void UnlockRead()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#endif
    }

    void UnlockWrite()
    {
#if defined(_WIN32) || defined(_WIN64)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif defined(unix) || defined(__unix) || defined(__unix__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#endif
    }

private:
    Path _path;
#if defined(_WIN32) || defined(_WIN64)
    HANDLE _file;
#elif defined(unix) || defined(__unix) || defined(__unix__)
    int _file;
#endif
    bool _owner;
};

FileLock::FileLock(const Path& path) : _pimpl(new Impl(path))
{
}

FileLock::~FileLock()
{
}

const Path& FileLock::path() const noexcept
{
    return _pimpl->path();
}

bool FileLock::TryLockRead()
{
    return _pimpl->TryLockRead();
}

bool FileLock::TryLockWrite()
{
    return _pimpl->TryLockWrite();
}

void FileLock::LockRead()
{
    _pimpl->LockRead();
}

void FileLock::LockWrite()
{
    _pimpl->LockWrite();
}

void FileLock::UnlockRead()
{
    _pimpl->UnlockRead();
}

void FileLock::UnlockWrite()
{
    _pimpl->UnlockWrite();
}

} // namespace CppCommon
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFixedArrayTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>

#include "itkFixedArray.h"

#ifndef ITK_EXPLICIT_INSTANTIATION
// Explicit instantiation to make sure all methods are compiled.
template class itk::FixedArray<float, 3>;
#endif

void Set_c_Array(int x[3])
{
  x[0] = 1;
  x[1] = 2;
  x[2] = 3;
}

void Print_Array(itk::FixedArray<int, 3> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_c_ArrayConst(const int x[3], std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_Array5(itk::FixedArray<int, 5> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << ','
     << x[3] << ',' << x[4] << '}' << std::endl;
}

int itkFixedArrayTest(int, char* [] )
{
  // Test out many combinations of using c-style arrays and FixedArray

  int c_Array1[3] = {0,0,0};

  Set_c_Array(c_Array1);
  Print_Array(c_Array1, std::cout);
  Print_c_ArrayConst(c_Array1, std::cout);

  int c_Array2[3] = {0,0,0};
  Print_Array(c_Array2, std::cout);

  int array3Init[3] = {4,4,4};
  itk::FixedArray<int, 3> array3 = array3Init;
  Print_Array(array3, std::cout);
  Print_c_ArrayConst(array3.GetDataPointer(), std::cout);

  Set_c_Array(array3.GetDataPointer());
  Print_Array(array3, std::cout);

  itk::FixedArray<int, 3> array4;
  array4.Fill(0);
  Print_Array(array4, std::cout);

  // Test operator!= and operator==
  if ( array4 != array4 ) return EXIT_FAILURE; //should be equal
  if ( !(array4 == array4) ) return EXIT_FAILURE; //should be equal

  // Test Get/Set element
  const unsigned int n = 20;
  itk::FixedArray< unsigned int, n > array20;
  for(unsigned int i=0; i<n; i++)
    {
    array20.SetElement(i,i);
    }

  for(unsigned int k=0; k<n; k++)
    {
    if( array20.GetElement(k) != k )
      {
      std::cerr << "Set/Get element test failed" << std::endl;
      return EXIT_FAILURE;
      }
    }

  std::cout << "FixedArray<unsigned int, 20>::Iterator it = array20.Begin();" << std::endl;
  itk::FixedArray<unsigned int, 20>::Iterator it = array20.Begin();
  while (it != array20.End())
    {
    std::cout << *it << std::endl;
    ++it;
    }

  std::cout << "FixedArray<unsigned int, 20>::Iterator it = array20.End();" << std::endl;
  itk::FixedArray<unsigned int, 20>::Iterator bit = array20.End();
  while (--bit >= array20.Begin())
    {
    std::cout << *bit << std::endl;
    }

  std::cout << "FixedArray<unsigned int, 20>::ConstIterator it = array20.Begin();" << std::endl;
  itk::FixedArray<unsigned int, 20>::ConstIterator cit = array20.Begin();
  while (cit != array20.End())
    {
    std::cout << *cit << std::endl;
    ++cit;
    }

  // Try all index types
#define TRY_INDEX_CONST(T) {T in = 10; if (array20[in] != 10) {std::cerr << "index failed" << std::endl; return EXIT_FAILURE;}}
      TRY_INDEX_CONST(short);
      TRY_INDEX_CONST(unsigned short);
      TRY_INDEX_CONST(int);
      TRY_INDEX_CONST(unsigned int);
      TRY_INDEX_CONST(long);
      TRY_INDEX_CONST(unsigned long);
#define TRY_INDEX(T) {T in = 10; array20[in] = 10;}
      TRY_INDEX(short);
      TRY_INDEX(unsigned short);
      TRY_INDEX(int);
      TRY_INDEX(unsigned int);
      TRY_INDEX(long);
      TRY_INDEX(unsigned long);
  return EXIT_SUCCESS;
}
<commit_msg>ENH: cover the reverse iteartors.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFixedArrayTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>

#include "itkFixedArray.h"

#ifndef ITK_EXPLICIT_INSTANTIATION
// Explicit instantiation to make sure all methods are compiled.
template class itk::FixedArray<float, 3>;
#endif

void Set_c_Array(int x[3])
{
  x[0] = 1;
  x[1] = 2;
  x[2] = 3;
}

void Print_Array(itk::FixedArray<int, 3> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_c_ArrayConst(const int x[3], std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_Array5(itk::FixedArray<int, 5> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << ','
     << x[3] << ',' << x[4] << '}' << std::endl;
}

int itkFixedArrayTest(int, char* [] )
{
  // Test out many combinations of using c-style arrays and FixedArray

  int c_Array1[3] = {0,0,0};

  Set_c_Array(c_Array1);
  Print_Array(c_Array1, std::cout);
  Print_c_ArrayConst(c_Array1, std::cout);

  int c_Array2[3] = {0,0,0};
  Print_Array(c_Array2, std::cout);

  int array3Init[3] = {4,4,4};
  itk::FixedArray<int, 3> array3 = array3Init;
  Print_Array(array3, std::cout);
  Print_c_ArrayConst(array3.GetDataPointer(), std::cout);

  Set_c_Array(array3.GetDataPointer());
  Print_Array(array3, std::cout);

  itk::FixedArray<int, 3> array4;
  array4.Fill(0);
  Print_Array(array4, std::cout);

  // Test operator!= and operator==
  if ( array4 != array4 ) return EXIT_FAILURE; //should be equal
  if ( !(array4 == array4) ) return EXIT_FAILURE; //should be equal

  // Test Get/Set element
  const unsigned int n = 20;
  itk::FixedArray< unsigned int, n > array20;
  for(unsigned int i=0; i<n; i++)
    {
    array20.SetElement(i,i);
    }

  for(unsigned int k=0; k<n; k++)
    {
    if( array20.GetElement(k) != k )
      {
      std::cerr << "Set/Get element test failed" << std::endl;
      return EXIT_FAILURE;
      }
    }

  std::cout << "FixedArray<unsigned int, 20>::Iterator it = array20.Begin();" << std::endl;
  itk::FixedArray<unsigned int, 20>::Iterator it = array20.Begin();
  while (it != array20.End())
    {
    std::cout << *it << std::endl;
    ++it;
    }

  std::cout << "FixedArray<unsigned int, 20>::Iterator it = array20.End();" << std::endl;
  itk::FixedArray<unsigned int, 20>::Iterator bit = array20.End();
  while (--bit >= array20.Begin())
    {
    std::cout << *bit << std::endl;
    }

  std::cout << "FixedArray<unsigned int, 20>::ConstIterator it = array20.Begin();" << std::endl;
  itk::FixedArray<unsigned int, 20>::ConstIterator cit = array20.Begin();
  while (cit != array20.End())
    {
    std::cout << *cit << std::endl;
    ++cit;
    }

  std::cout << "FixedArray<unsigned int, 20>::ReverseIterator rit = array20.rBegin();" << std::endl;
  itk::FixedArray<unsigned int, 20>::ReverseIterator rit = array20.rBegin();
  while (rit != array20.rEnd())
    {
    std::cout << *rit << std::endl;
    ++rit;
    }

  std::cout << "FixedArray<unsigned int, 20>::ConstReverseIterator crit = array20.rBegin();" << std::endl;
  itk::FixedArray<unsigned int, 20>::ConstReverseIterator crit = array20.rBegin();
  while (crit != array20.rEnd())
    {
    std::cout << *crit << std::endl;
    ++crit;
    }

  // Try all index types
#define TRY_INDEX_CONST(T) {T in = 10; if (array20[in] != 10) {std::cerr << "index failed" << std::endl; return EXIT_FAILURE;}}
      TRY_INDEX_CONST(short);
      TRY_INDEX_CONST(unsigned short);
      TRY_INDEX_CONST(int);
      TRY_INDEX_CONST(unsigned int);
      TRY_INDEX_CONST(long);
      TRY_INDEX_CONST(unsigned long);
#define TRY_INDEX(T) {T in = 10; array20[in] = 10;}
      TRY_INDEX(short);
      TRY_INDEX(unsigned short);
      TRY_INDEX(int);
      TRY_INDEX(unsigned int);
      TRY_INDEX(long);
      TRY_INDEX(unsigned long);
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbCartographicRegion.h"

int otbCartoRegionNew(int argc, char * argv[])
{

  typedef   double                                Type;
  typedef   otb::CartographicRegion<Type>                TypedRegion;

  TypedRegion                     Cartoregion();

  return EXIT_SUCCESS;
}

<commit_msg>COMP: Suppress warning in CartoRegionNew testing<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbCartographicRegion.h"

int otbCartoRegionNew(int argc, char * argv[])
{

  typedef   double                                Type;
  typedef   otb::CartographicRegion<Type>                TypedRegion;

  TypedRegion                     Cartoregion;

  return EXIT_SUCCESS;
}

<|endoftext|>