<commit_before>/* Copyright (C) LinBox
 *
 *  Author: Zhendong Wan
 *
 *
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
  * LinBox is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 */

/*! @file   tests/test-smith-form-iliopoulos.C
 * @ingroup tests
 * @brief no doc.
 * @test no doc.
 */

//#include "linbox/field/ntl.h"
//#include "linbox/field/modular.h"
#include "linbox/field/PID-integer.h"
#include "linbox/field/PIR-ntl-ZZ_p.h"
#include "linbox/field/PIR-modular-int32.h"
//#include "linbox/integer.h"
#include "linbox/randiter/random-prime.h"
//#include "linbox/algorithms/last-invariant-factor.h"
#include "linbox/algorithms/smith-form-iliopoulos.h"
#include "linbox/matrix/matrix-domain.h"
//#include "linbox/algorithms/rational-solver.h"
//#include <time.h>
#include "linbox/util/commentator.h"
//#include "linbox/vector/stream.h"
#include "test-common.h"
#include "linbox/algorithms/matrix-hom.h"
#include "linbox/solutions/det.h"
#include <iostream>

#ifndef __LINBOX_HAVE_NTL
#error "you can't compile this test without NTL enabled. Please make sure you configured Linbox with --with-ntl=path/to/ntl"
#endif

using namespace LinBox;

template <class Ring>
bool testRead(const Ring& R, string file) {
	BlasMatrix<Ring> A(R);
	BlasMatrixDomain<Ring> BMD(R);
	std::ifstream data(file);
	A.read(data);
	size_t m = A.rowdim();
	size_t n = A.coldim();
	BlasMatrix<Ring> U(R, m, m), V(R, n, n), B(R, m, n);
	/* random unimodular
	BMD.randomNonsingular(U);
	BMD.randomNonsingular(V);
	*/
	for (size_t i = 0; i < m; ++i)
	{	for (size_t j = 0; j < m; ++j)
			U.setEntry(i, j, R.zero);
		U.setEntry(i, i, R.one);
	}
	for (size_t i = 0; i < n; ++i)
	{	for (size_t j = 0; j < n; ++j)
			V.setEntry(i, j, R.zero);
		V.setEntry(i, i, R.one);
	}
	BMD.copy(B, A);
	BMD.mulin_left(B,V);
	BMD.mulin_right(U,B);
	SmithFormIliopoulos::smithFormIn (B);
	return BMD.areEqual(A, B);
}

template <class Ring>
bool testRandom(const Ring& R, size_t n)
{
        bool pass = true;

        commentator().start ("Testing Iloipoulos elimination:", "testRandom");
	using namespace std;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);

	BlasMatrixDomain<Ring> BMD(R);
	BlasMatrix<Ring> D(R, n, n), L(R, n, n), U(R, n, n), A(R,n,n);

	// D is Smith Form
	const int m = 16;
	int p[m] = {1,1,1,1,1,1,2, 2, 2, 4, 3, 3, 3, 5, 7, 101};
	typename Ring::Element x, y;
	R.assign(x, R.one);
	if (n > 0) D.setEntry(0,0,x);
	for(size_t i = 1; i < n; ++i){
		R.init(y, p[rand()%m]);
		D.setEntry(i,i, R.mulin(x, y));
	}
	if (n > 0) D.setEntry(n-1,n-1, R.zero);

	// L and U are random unit triangular.
	for (size_t i = 0; i < n; ++ i) {
		for (size_t j = 0; j < i; ++ j) {
			L.setEntry(i,j, R.init(x, rand() % 10));
			U.setEntry(j,i, R.init(x, rand() % 10));
		}
		L.setEntry(i,i, R.one);
		U.setEntry(i,i, R.one);
	}

	// A is ULDU
	BMD.mul(A, U, L);
	BMD.mulin_left(A, D);
	BMD.mulin_left(A, U);

	D.write( report << "Smith form matrix:\n  " ) << endl;
	A.write( report << "input matrix:\n " ) << endl;
//	SmithFormIliopoulos::smithFormIn (A);
//	A.write( report << "smith of input matrix direct:\n " ) << endl;

	report << "Using PIRModular<int32_t>\n";
	typename Ring::Element d; R.init(d,16*101);//16*101*5*7*9);
	for (int i = 0; i < n-1; ++i) R.mulin(d, D.getEntry(x, i, i));
	R.write(report << "modulus: ", d) << endl;
	//det(d, D);
	//PIRModular<int32_t> Rd( (int32_t)(s % LINBOX_MAX_MODULUS));
	PIRModular<int32_t> Rp( (int32_t)d);
	BlasMatrix<PIRModular<int32_t> > Ap(Rp, n, n), Dp(Rp, n, n);
	MatrixHom::map (Ap, A);

	SmithFormIliopoulos::smithFormIn (Ap);

	Ap.write( report << "Computed Smith form: \n") << endl;
	MatrixHom::map (Dp, D);
	BlasMatrixDomain<PIRModular<int32_t> > BMDp(Rp);
	pass = pass and BMDp.areEqual(Dp, Ap);

	commentator().stop (MSG_STATUS (pass), (const char *) 0, "testRandom");
	return pass;

}

int main(int argc, char** argv)
{

        using namespace LinBox;

        bool pass = true;
        static size_t n = 2;
        static Argument args[] = {
                { 'n', "-n N", "Set order of test matrices to N.", TYPE_INT,     &n },
		END_OF_ARGUMENTS
        };
        parseArguments (argc, argv, args);

	commentator().start("Ilioloulos Smith Form test suite", "Ilioloulos");
        commentator().getMessageClass (INTERNAL_DESCRIPTION).setMaxDepth (5);

        PID_integer R; // Ring of integers
        //NTL_ZZ R;

        if (!testRandom(R, n)) pass = false;
//        if (!testRead(R, "data/Ismith.mat")) pass = false;

	commentator().stop("Ilioloulos Smith Form test suite");
        return pass ? 0 : -1;

}

// Local Variables:
// mode: C++
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 8
// End:
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
<commit_msg>unsigned<commit_after>/* Copyright (C) LinBox
 *
 *  Author: Zhendong Wan
 *
 *
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
  * LinBox is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 */

/*! @file   tests/test-smith-form-iliopoulos.C
 * @ingroup tests
 * @brief no doc.
 * @test no doc.
 */

//#include "linbox/field/ntl.h"
//#include "linbox/field/modular.h"
#include "linbox/field/PID-integer.h"
#include "linbox/field/PIR-ntl-ZZ_p.h"
#include "linbox/field/PIR-modular-int32.h"
//#include "linbox/integer.h"
#include "linbox/randiter/random-prime.h"
//#include "linbox/algorithms/last-invariant-factor.h"
#include "linbox/algorithms/smith-form-iliopoulos.h"
#include "linbox/matrix/matrix-domain.h"
//#include "linbox/algorithms/rational-solver.h"
//#include <time.h>
#include "linbox/util/commentator.h"
//#include "linbox/vector/stream.h"
#include "test-common.h"
#include "linbox/algorithms/matrix-hom.h"
#include "linbox/solutions/det.h"
#include <iostream>

#ifndef __LINBOX_HAVE_NTL
#error "you can't compile this test without NTL enabled. Please make sure you configured Linbox with --with-ntl=path/to/ntl"
#endif

using namespace LinBox;

template <class Ring>
bool testRead(const Ring& R, string file) {
	BlasMatrix<Ring> A(R);
	BlasMatrixDomain<Ring> BMD(R);
	std::ifstream data(file);
	A.read(data);
	size_t m = A.rowdim();
	size_t n = A.coldim();
	BlasMatrix<Ring> U(R, m, m), V(R, n, n), B(R, m, n);
	/* random unimodular
	BMD.randomNonsingular(U);
	BMD.randomNonsingular(V);
	*/
	for (size_t i = 0; i < m; ++i)
	{	for (size_t j = 0; j < m; ++j)
			U.setEntry(i, j, R.zero);
		U.setEntry(i, i, R.one);
	}
	for (size_t i = 0; i < n; ++i)
	{	for (size_t j = 0; j < n; ++j)
			V.setEntry(i, j, R.zero);
		V.setEntry(i, i, R.one);
	}
	BMD.copy(B, A);
	BMD.mulin_left(B,V);
	BMD.mulin_right(U,B);
	SmithFormIliopoulos::smithFormIn (B);
	return BMD.areEqual(A, B);
}

template <class Ring>
bool testRandom(const Ring& R, size_t n)
{
        bool pass = true;

        commentator().start ("Testing Iloipoulos elimination:", "testRandom");
	using namespace std;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);

	BlasMatrixDomain<Ring> BMD(R);
	BlasMatrix<Ring> D(R, n, n), L(R, n, n), U(R, n, n), A(R,n,n);

	// D is Smith Form
	const int m = 16;
	int p[m] = {1,1,1,1,1,1,2, 2, 2, 4, 3, 3, 3, 5, 7, 101};
	typename Ring::Element x, y;
	R.assign(x, R.one);
	if (n > 0) D.setEntry(0,0,x);
	for(size_t i = 1; i < n; ++i){
		R.init(y, p[rand()%m]);
		D.setEntry(i,i, R.mulin(x, y));
	}
	if (n > 0) D.setEntry(n-1,n-1, R.zero);

	// L and U are random unit triangular.
	for (size_t i = 0; i < n; ++ i) {
		for (size_t j = 0; j < i; ++ j) {
			L.setEntry(i,j, R.init(x, rand() % 10));
			U.setEntry(j,i, R.init(x, rand() % 10));
		}
		L.setEntry(i,i, R.one);
		U.setEntry(i,i, R.one);
	}

	// A is ULDU
	BMD.mul(A, U, L);
	BMD.mulin_left(A, D);
	BMD.mulin_left(A, U);

	D.write( report << "Smith form matrix:\n  " ) << endl;
	A.write( report << "input matrix:\n " ) << endl;
//	SmithFormIliopoulos::smithFormIn (A);
//	A.write( report << "smith of input matrix direct:\n " ) << endl;

	report << "Using PIRModular<int32_t>\n";
	typename Ring::Element d; R.init(d,16*101);//16*101*5*7*9);
	for (size_t i = 0; i < n-1; ++i) R.mulin(d, D.getEntry(x, i, i));
	R.write(report << "modulus: ", d) << endl;
	//det(d, D);
	//PIRModular<int32_t> Rd( (int32_t)(s % LINBOX_MAX_MODULUS));
	PIRModular<int32_t> Rp( (int32_t)d);
	BlasMatrix<PIRModular<int32_t> > Ap(Rp, n, n), Dp(Rp, n, n);
	MatrixHom::map (Ap, A);

	SmithFormIliopoulos::smithFormIn (Ap);

	Ap.write( report << "Computed Smith form: \n") << endl;
	MatrixHom::map (Dp, D);
	BlasMatrixDomain<PIRModular<int32_t> > BMDp(Rp);
	pass = pass and BMDp.areEqual(Dp, Ap);

	commentator().stop (MSG_STATUS (pass), (const char *) 0, "testRandom");
	return pass;

}

int main(int argc, char** argv)
{

        using namespace LinBox;

        bool pass = true;
        static size_t n = 2;
        static Argument args[] = {
                { 'n', "-n N", "Set order of test matrices to N.", TYPE_INT,     &n },
		END_OF_ARGUMENTS
        };
        parseArguments (argc, argv, args);

	commentator().start("Ilioloulos Smith Form test suite", "Ilioloulos");
        commentator().getMessageClass (INTERNAL_DESCRIPTION).setMaxDepth (5);

        PID_integer R; // Ring of integers
        //NTL_ZZ R;

        if (!testRandom(R, n)) pass = false;
//        if (!testRead(R, "data/Ismith.mat")) pass = false;

	commentator().stop("Ilioloulos Smith Form test suite");
        return pass ? 0 : -1;

}

// Local Variables:
// mode: C++
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 8
// End:
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *  Copyright (C) 2019  The Symbiflow Authors
 *
 *  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.
 *
 *  ---
 *
 *   XDC commands
 *
 *   This plugin operates on the existing design and modifies its structure
 *   based on the content of the XDC (Xilinx Design Constraints) file.
 *   Since the XDC file consists of Tcl commands it is read using Yosys's
 *   Tcl interpreter and processed by the new XDC commands imported to the
 *   Tcl interpreter.
 */
#include <cassert>
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
#include "libs/json11/json11.hpp"
#include "../bank_tiles.h"

USING_YOSYS_NAMESPACE

PRIVATE_NAMESPACE_BEGIN

enum class SetPropertyOptions { INTERNAL_VREF };

const std::unordered_map<std::string, SetPropertyOptions> set_property_options_map  = {
	{"INTERNAL_VREF", SetPropertyOptions::INTERNAL_VREF}
};

void register_in_tcl_interpreter(const std::string& command) {
	Tcl_Interp* interp = yosys_get_tcl_interp();
	std::string tcl_script = stringf("proc %s args { return [yosys %s {*}$args] }", command.c_str(), command.c_str());
	Tcl_Eval(interp, tcl_script.c_str());
}

struct GetPorts : public Pass {
	GetPorts() : Pass("get_ports", "Print matching ports") {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("   get_ports <port_name> \n");
		log("\n");
		log("Get matching ports\n");
		log("\n");
		log("Print the output to stdout too. This is useful when all Yosys is executed\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
	{
		std::string text;
		for (auto& arg : args) {
			text += arg + ' ';
		}
		if (!text.empty()) {
			text.resize(text.size()-1);
		}
		log("%s\n", text.c_str());
	}
};

struct GetIOBanks : public Pass {
	GetIOBanks(std::function<const BankTilesMap&()> get_bank_tiles)
		: Pass("get_iobanks", "Set IO Bank number")
		, get_bank_tiles(get_bank_tiles) {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("   get_iobanks <bank_number>\n");
		log("\n");
		log("Get IO Bank number\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design* ) YS_OVERRIDE {
		if (args.size() < 2) {
			log_cmd_error("%s: Missing bank number.\n", pass_name.c_str());
		}
		auto bank_tiles = get_bank_tiles();
		if (bank_tiles.count(std::atoi(args[1].c_str())) == 0) {
			log_cmd_error("%s:Bank number %s is not present in the target device.\n", args[1].c_str(), pass_name.c_str());
		}

                Tcl_Interp *interp = yosys_get_tcl_interp();
		Tcl_SetResult(interp, const_cast<char*>(args[1].c_str()), NULL);
		log("%s\n", args[1].c_str());
	}

	std::function<const BankTilesMap&()> get_bank_tiles;
};

struct SetProperty : public Pass {
	SetProperty(std::function<const BankTilesMap&()> get_bank_tiles)
		: Pass("set_property", "Set a given property")
		, get_bank_tiles(get_bank_tiles) {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    set_property PROPERTY VALUE OBJECT\n");
		log("\n");
		log("Set the given property to the specified value on an object\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design* design) YS_OVERRIDE {
		if (design->top_module() == nullptr) {
			log_cmd_error("No top module detected\n");
		}

		std::string option(args[1]);
		if (set_property_options_map.count(option) == 0) {
			log_warning("set_property: %s option is currently not supported\n", option.c_str());
			return;
		}

		switch (set_property_options_map.at(option)) {
			case SetPropertyOptions::INTERNAL_VREF:
				process_vref(std::vector<std::string>(args.begin() + 2, args.end()), design);
				break;
			default:
				assert(false);
		}
	}

	void process_vref(std::vector<std::string> args, RTLIL::Design* design) {
		if (args.size() < 2) {
			log_error("set_property INTERNAL_VREF: Incorrect number of arguments.\n");
		}
		int iobank = std::atoi(args[1].c_str());
		auto bank_tiles = get_bank_tiles();
		if (bank_tiles.count(iobank) == 0) {
			log_cmd_error("set_property INTERNAL_VREF: Invalid IO bank.\n");
		}

		int internal_vref = 1000 * std::atof(args[0].c_str());
		if (internal_vref != 600 &&
				internal_vref != 675 &&
				internal_vref != 750 &&
				internal_vref != 900) {
			log("set_property INTERNAL_VREF: Incorrect INTERNAL_VREF value\n");
			return;
		}

		// Create a new BANK module if it hasn't been created so far
		RTLIL::Module* top_module = design->top_module();
		if (!design->has(ID(BANK))) {
			std::string fasm_extra_modules_dir(proc_share_dirname() + "/plugins/fasm_extra_modules");
			Pass::call(design, "read_verilog " + fasm_extra_modules_dir + "/BANK.v");
		}

		// Set parameters on a new bank instance or update an existing one
		char bank_cell_name[16];
		snprintf(bank_cell_name, 16, "\\bank_cell_%d", iobank);
		RTLIL::Cell* bank_cell = top_module->cell(RTLIL::IdString(bank_cell_name));
		if (!bank_cell) {
			bank_cell = top_module->addCell(RTLIL::IdString(bank_cell_name), ID(BANK));
		}
		bank_cell->setParam(ID(FASM_EXTRA), RTLIL::Const("INTERNAL_VREF"));
		bank_cell->setParam(ID(NUMBER), RTLIL::Const(iobank));
		bank_cell->setParam(ID(INTERNAL_VREF), RTLIL::Const(internal_vref));
	}

	std::function<const BankTilesMap&()> get_bank_tiles;
};

struct ReadXdc : public Frontend {
	ReadXdc()
	       	: Frontend("xdc", "Read XDC file")
		, GetIOBanks(std::bind(&ReadXdc::get_bank_tiles, this))
		, SetProperty(std::bind(&ReadXdc::get_bank_tiles, this)) {}

	void help() YS_OVERRIDE {
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    read_xdc -part_json <part_json_filename> <filename>\n");
		log("\n");
		log("Read XDC file.\n");
		log("\n");
	}

	void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE {
                if (args.size() < 2) {
                        log_cmd_error("Missing script file.\n");
		}
                Tcl_Interp *interp = yosys_get_tcl_interp();
		size_t argidx = 1;
		if (args[argidx] == "-part_json" && argidx + 1 < args.size()) {
			bank_tiles = ::get_bank_tiles(args[++argidx]);
			argidx++;
		}
		extra_args(f, filename, args, argidx);
		std::string content{std::istreambuf_iterator<char>(*f), std::istreambuf_iterator<char>()};
		log("%s\n", content.c_str());
                if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) {
                        log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(interp));
		}
	}
	const BankTilesMap& get_bank_tiles() {
		return bank_tiles;
	}

	BankTilesMap bank_tiles;
	GetPorts GetPorts;
	GetIOBanks GetIOBanks;
	SetProperty SetProperty;
} ReadXdc;

struct GetBankTiles : public Pass {
	GetBankTiles()
	       	: Pass("get_bank_tiles", "Inspect IO Bank tiles") {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("   get_bank_tiles <part_json_file>\n");
		log("\n");
		log("Inspect IO Bank tiles for the specified part based on the provided JSON file.\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design* ) YS_OVERRIDE {
                if (args.size() < 2) {
                        log_cmd_error("Missing JSON file.\n");
		}
		// Check if the part has the specified bank
		auto bank_tiles = get_bank_tiles(args[1]);
		if (bank_tiles.size()) {
			log("Available bank tiles:\n");
			for (auto bank : bank_tiles) {
				log("Bank: %d, Tile: %s\n", bank.first, bank.second.c_str());
			}
			log("\n");
		} else {
			log("No bank tiles available.\n");
		}
	}
} GetBankTiles;

PRIVATE_NAMESPACE_END
<commit_msg>XDC: Clear bank_tiles if json_part not provided<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *  Copyright (C) 2019  The Symbiflow Authors
 *
 *  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.
 *
 *  ---
 *
 *   XDC commands
 *
 *   This plugin operates on the existing design and modifies its structure
 *   based on the content of the XDC (Xilinx Design Constraints) file.
 *   Since the XDC file consists of Tcl commands it is read using Yosys's
 *   Tcl interpreter and processed by the new XDC commands imported to the
 *   Tcl interpreter.
 */
#include <cassert>
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
#include "libs/json11/json11.hpp"
#include "../bank_tiles.h"

USING_YOSYS_NAMESPACE

PRIVATE_NAMESPACE_BEGIN

enum class SetPropertyOptions { INTERNAL_VREF };

const std::unordered_map<std::string, SetPropertyOptions> set_property_options_map  = {
	{"INTERNAL_VREF", SetPropertyOptions::INTERNAL_VREF}
};

void register_in_tcl_interpreter(const std::string& command) {
	Tcl_Interp* interp = yosys_get_tcl_interp();
	std::string tcl_script = stringf("proc %s args { return [yosys %s {*}$args] }", command.c_str(), command.c_str());
	Tcl_Eval(interp, tcl_script.c_str());
}

struct GetPorts : public Pass {
	GetPorts() : Pass("get_ports", "Print matching ports") {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("   get_ports <port_name> \n");
		log("\n");
		log("Get matching ports\n");
		log("\n");
		log("Print the output to stdout too. This is useful when all Yosys is executed\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
	{
		std::string text;
		for (auto& arg : args) {
			text += arg + ' ';
		}
		if (!text.empty()) {
			text.resize(text.size()-1);
		}
		log("%s\n", text.c_str());
	}
};

struct GetIOBanks : public Pass {
	GetIOBanks(std::function<const BankTilesMap&()> get_bank_tiles)
		: Pass("get_iobanks", "Set IO Bank number")
		, get_bank_tiles(get_bank_tiles) {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("   get_iobanks <bank_number>\n");
		log("\n");
		log("Get IO Bank number\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design* ) YS_OVERRIDE {
		if (args.size() < 2) {
			log_cmd_error("%s: Missing bank number.\n", pass_name.c_str());
		}
		auto bank_tiles = get_bank_tiles();
		if (bank_tiles.count(std::atoi(args[1].c_str())) == 0) {
			log_cmd_error("%s:Bank number %s is not present in the target device.\n", args[1].c_str(), pass_name.c_str());
		}

                Tcl_Interp *interp = yosys_get_tcl_interp();
		Tcl_SetResult(interp, const_cast<char*>(args[1].c_str()), NULL);
		log("%s\n", args[1].c_str());
	}

	std::function<const BankTilesMap&()> get_bank_tiles;
};

struct SetProperty : public Pass {
	SetProperty(std::function<const BankTilesMap&()> get_bank_tiles)
		: Pass("set_property", "Set a given property")
		, get_bank_tiles(get_bank_tiles) {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    set_property PROPERTY VALUE OBJECT\n");
		log("\n");
		log("Set the given property to the specified value on an object\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design* design) YS_OVERRIDE {
		if (design->top_module() == nullptr) {
			log_cmd_error("No top module detected\n");
		}

		std::string option(args[1]);
		if (set_property_options_map.count(option) == 0) {
			log_warning("set_property: %s option is currently not supported\n", option.c_str());
			return;
		}

		switch (set_property_options_map.at(option)) {
			case SetPropertyOptions::INTERNAL_VREF:
				process_vref(std::vector<std::string>(args.begin() + 2, args.end()), design);
				break;
			default:
				assert(false);
		}
	}

	void process_vref(std::vector<std::string> args, RTLIL::Design* design) {
		if (args.size() < 2) {
			log_error("set_property INTERNAL_VREF: Incorrect number of arguments.\n");
		}
		int iobank = std::atoi(args[1].c_str());
		auto bank_tiles = get_bank_tiles();
		if (bank_tiles.count(iobank) == 0) {
			log_cmd_error("set_property INTERNAL_VREF: Invalid IO bank.\n");
		}

		int internal_vref = 1000 * std::atof(args[0].c_str());
		if (internal_vref != 600 &&
				internal_vref != 675 &&
				internal_vref != 750 &&
				internal_vref != 900) {
			log("set_property INTERNAL_VREF: Incorrect INTERNAL_VREF value\n");
			return;
		}

		// Create a new BANK module if it hasn't been created so far
		RTLIL::Module* top_module = design->top_module();
		if (!design->has(ID(BANK))) {
			std::string fasm_extra_modules_dir(proc_share_dirname() + "/plugins/fasm_extra_modules");
			Pass::call(design, "read_verilog " + fasm_extra_modules_dir + "/BANK.v");
		}

		// Set parameters on a new bank instance or update an existing one
		char bank_cell_name[16];
		snprintf(bank_cell_name, 16, "\\bank_cell_%d", iobank);
		RTLIL::Cell* bank_cell = top_module->cell(RTLIL::IdString(bank_cell_name));
		if (!bank_cell) {
			bank_cell = top_module->addCell(RTLIL::IdString(bank_cell_name), ID(BANK));
		}
		bank_cell->setParam(ID(FASM_EXTRA), RTLIL::Const("INTERNAL_VREF"));
		bank_cell->setParam(ID(NUMBER), RTLIL::Const(iobank));
		bank_cell->setParam(ID(INTERNAL_VREF), RTLIL::Const(internal_vref));
	}

	std::function<const BankTilesMap&()> get_bank_tiles;
};

struct ReadXdc : public Frontend {
	ReadXdc()
	       	: Frontend("xdc", "Read XDC file")
		, GetIOBanks(std::bind(&ReadXdc::get_bank_tiles, this))
		, SetProperty(std::bind(&ReadXdc::get_bank_tiles, this)) {}

	void help() YS_OVERRIDE {
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    read_xdc -part_json <part_json_filename> <filename>\n");
		log("\n");
		log("Read XDC file.\n");
		log("\n");
	}

	void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE {
                if (args.size() < 2) {
                        log_cmd_error("Missing script file.\n");
		}
                Tcl_Interp *interp = yosys_get_tcl_interp();
		size_t argidx = 1;
		bank_tiles.clear();
		if (args[argidx] == "-part_json" && argidx + 1 < args.size()) {
			bank_tiles = ::get_bank_tiles(args[++argidx]);
			argidx++;
		}
		extra_args(f, filename, args, argidx);
		std::string content{std::istreambuf_iterator<char>(*f), std::istreambuf_iterator<char>()};
		log("%s\n", content.c_str());
                if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) {
                        log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(interp));
		}
	}
	const BankTilesMap& get_bank_tiles() {
		return bank_tiles;
	}

	BankTilesMap bank_tiles;
	GetPorts GetPorts;
	GetIOBanks GetIOBanks;
	SetProperty SetProperty;
} ReadXdc;

struct GetBankTiles : public Pass {
	GetBankTiles()
	       	: Pass("get_bank_tiles", "Inspect IO Bank tiles") {
		register_in_tcl_interpreter(pass_name);
	}

	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("   get_bank_tiles <part_json_file>\n");
		log("\n");
		log("Inspect IO Bank tiles for the specified part based on the provided JSON file.\n");
		log("\n");
	}

	void execute(std::vector<std::string> args, RTLIL::Design* ) YS_OVERRIDE {
                if (args.size() < 2) {
                        log_cmd_error("Missing JSON file.\n");
		}
		// Check if the part has the specified bank
		auto bank_tiles = get_bank_tiles(args[1]);
		if (bank_tiles.size()) {
			log("Available bank tiles:\n");
			for (auto bank : bank_tiles) {
				log("Bank: %d, Tile: %s\n", bank.first, bank.second.c_str());
			}
			log("\n");
		} else {
			log("No bank tiles available.\n");
		}
	}
} GetBankTiles;

PRIVATE_NAMESPACE_END
<|endoftext|>


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

 Module:       FGGain.cpp
 Author:
 Date started:

 ------------- Copyright (C) 2000 -------------

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU General Public License can also be found on
 the world wide web at http://www.gnu.org.

FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------

HISTORY
--------------------------------------------------------------------------------

********************************************************************************
COMMENTS, REFERENCES,  and NOTES
********************************************************************************

********************************************************************************
INCLUDES
*******************************************************************************/

#include "FGGain.h"

/*******************************************************************************
************************************ CODE **************************************
*******************************************************************************/

// *****************************************************************************
//  Function:   Constructor
//  Purpose:    Builds a Gain-type of FCS component.
//  Parameters: void
//  Comments:   Types are PURE_GAIN, SCHEDULED_GAIN, and AEROSURFACE_SCALE

FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
                                                   AC_cfg(AC_cfg)
{
  string token;
  string strScheduledBy;

  lookup = NULL;
  Schedule.clear();
  Gain = 1.000;
  Min = Max = 0;
  ScheduledBy = FG_NONE;

  Type = AC_cfg->GetValue("TYPE");
  Name = AC_cfg->GetValue("NAME");
  AC_cfg->GetNextConfigLine();

  while ((token = AC_cfg->GetValue()) != "/COMPONENT") {
    *AC_cfg >> token;
    if (token == "ID") {
      *AC_cfg >> ID;
      cout << "      ID: " << ID << endl;
    } else if (token == "INPUT") {
      token = AC_cfg->GetValue("INPUT");
      cout << "      INPUT: " << token << endl;
      if (token.find("FG_") != token.npos) {
        *AC_cfg >> token;
        InputIdx = fcs->GetState()->GetParameterIndex(token);
        InputType = itPilotAC;
      } else {
        *AC_cfg >> InputIdx;
        InputType = itFCS;
      }
    } else if (token == "GAIN") {
      *AC_cfg >> Gain;
      cout << "      GAIN: " << Gain << endl;
    } else if (token == "MIN") {
      *AC_cfg >> Min;
      cout << "      MIN: " << Min << endl;
    } else if (token == "MAX") {
      *AC_cfg >> Max;
      cout << "      MAX: " << Max << endl;
    } else if (token == "SCHEDULED_BY") {
      *AC_cfg >> strScheduledBy;
      ScheduledBy = fcs->GetState()->GetParameterIndex(strScheduledBy);
    } else if (token == "OUTPUT") {
      IsOutput = true;
      *AC_cfg >> sOutputIdx;
      OutputIdx = fcs->GetState()->GetParameterIndex(sOutputIdx);
      cout << "      OUTPUT: " << sOutputIdx << endl;
    } else {
      AC_cfg->ResetLineIndexToZero();
      lookup = new float[2];
      *AC_cfg >> lookup[0] >> lookup[1];
      Schedule.push_back(lookup);
    }
  }
}

// *****************************************************************************
//  Function:   Run
//  Purpose:
//  Parameters: void
//  Comments:

bool FGGain::Run(void )
{
  float SchedGain = 1.0;

  FGFCSComponent::Run(); // call the base class for initialization of Input

  if (Type == "PURE_GAIN") {

    Output = Gain * Input;

  } else if (Type == "SCHEDULED_GAIN") {

    float LookupVal = fcs->GetState()->GetParameter(ScheduledBy);
    unsigned int last = Schedule.size()-1;
    float lowVal = Schedule[0][0], hiVal = Schedule[last][0];
    float factor = 1.0;

    if (LookupVal <= lowVal) Output = Gain * Schedule[0][1];
    else if (LookupVal >= hiVal) Output = Gain * Schedule[last][1];
    else {
      for (unsigned int ctr = 1; ctr < last; ctr++) {
        if (LookupVal < Schedule[ctr][0]) {
          hiVal = Schedule[ctr][0];
          lowVal = Schedule[ctr-1][0];
          factor = (LookupVal - lowVal) / (hiVal - lowVal);
          SchedGain = Schedule[ctr-1][1] + factor*(Schedule[ctr][1] - Schedule[ctr-1][1]);
          Output = Gain * SchedGain * Input;
          break;
        }
      }
    }

  } else if (Type == "AEROSURFACE_SCALE") {

    if (Output >= 0.0) Output = Input * Max;
    else Output = Input * (-Min);

    Output *= Gain;
  }

  if (IsOutput) SetOutput();

  return true;
}

<commit_msg>Adjustments to parameter retrieval in FGGain<commit_after>/*******************************************************************************

 Module:       FGGain.cpp
 Author:
 Date started:

 ------------- Copyright (C) 2000 -------------

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU General Public License can also be found on
 the world wide web at http://www.gnu.org.

FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------

HISTORY
--------------------------------------------------------------------------------

********************************************************************************
COMMENTS, REFERENCES,  and NOTES
********************************************************************************

********************************************************************************
INCLUDES
*******************************************************************************/

#include "FGGain.h"

/*******************************************************************************
************************************ CODE **************************************
*******************************************************************************/

// *****************************************************************************
//  Function:   Constructor
//  Purpose:    Builds a Gain-type of FCS component.
//  Parameters: void
//  Comments:   Types are PURE_GAIN, SCHEDULED_GAIN, and AEROSURFACE_SCALE

FGGain::FGGain(FGFCS* fcs, FGConfigFile* AC_cfg) : FGFCSComponent(fcs),
                                                   AC_cfg(AC_cfg)
{
  string token;
  string strScheduledBy;

  lookup = NULL;
  Schedule.clear();
  Gain = 1.000;
  Min = Max = 0;
  ScheduledBy = FG_NONE;

  Type = AC_cfg->GetValue("TYPE");
  Name = AC_cfg->GetValue("NAME");
  AC_cfg->GetNextConfigLine();

  while ((token = AC_cfg->GetValue()) != "/COMPONENT") {
    *AC_cfg >> token;
    if (token == "ID") {
      *AC_cfg >> ID;
      cout << "      ID: " << ID << endl;
    } else if (token == "INPUT") {
      token = AC_cfg->GetValue("INPUT");
      cout << "      INPUT: " << token << endl;
      if (token.find("FG_") != token.npos) {
        *AC_cfg >> token;
        InputIdx = fcs->GetState()->GetParameterIndex(token);
        InputType = itPilotAC;
      } else {
        *AC_cfg >> InputIdx;
        InputType = itFCS;
      }
    } else if (token == "GAIN") {
      *AC_cfg >> Gain;
      cout << "      GAIN: " << Gain << endl;
    } else if (token == "MIN") {
      *AC_cfg >> Min;
      cout << "      MIN: " << Min << endl;
    } else if (token == "MAX") {
      *AC_cfg >> Max;
      cout << "      MAX: " << Max << endl;
    } else if (token == "SCHEDULED_BY") {
      token = AC_cfg->GetValue("SCHEDULED_BY");
      if (token.find("FG_") != token.npos) {
        *AC_cfg >> strScheduledBy;
        ScheduledBy = fcs->GetState()->GetParameterIndex(strScheduledBy);
        cout << "      Scheduled by parameter: " << token << endl;
      } else {
        *AC_cfg >> ScheduledBy;
        cout << "      Scheduled by FCS output: " << ScheduledBy << endl;
      }
    } else if (token == "OUTPUT") {
      IsOutput = true;
      *AC_cfg >> sOutputIdx;
      OutputIdx = fcs->GetState()->GetParameterIndex(sOutputIdx);
      cout << "      OUTPUT: " << sOutputIdx << endl;
    } else {
      AC_cfg->ResetLineIndexToZero();
      lookup = new float[2];
      *AC_cfg >> lookup[0] >> lookup[1];
      Schedule.push_back(lookup);
    }
  }
}

// *****************************************************************************
//  Function:   Run
//  Purpose:
//  Parameters: void
//  Comments:

bool FGGain::Run(void )
{
  float SchedGain = 1.0;

  FGFCSComponent::Run(); // call the base class for initialization of Input

  if (Type == "PURE_GAIN") {

    Output = Gain * Input;

  } else if (Type == "SCHEDULED_GAIN") {

    float LookupVal = fcs->GetState()->GetParameter(ScheduledBy);
    unsigned int last = Schedule.size()-1;
    float lowVal = Schedule[0][0], hiVal = Schedule[last][0];
    float factor = 1.0;

    if (LookupVal <= lowVal) Output = Gain * Schedule[0][1];
    else if (LookupVal >= hiVal) Output = Gain * Schedule[last][1];
    else {
      for (unsigned int ctr = 1; ctr < last; ctr++) {
        if (LookupVal < Schedule[ctr][0]) {
          hiVal = Schedule[ctr][0];
          lowVal = Schedule[ctr-1][0];
          factor = (LookupVal - lowVal) / (hiVal - lowVal);
          SchedGain = Schedule[ctr-1][1] + factor*(Schedule[ctr][1] - Schedule[ctr-1][1]);
          Output = Gain * SchedGain * Input;
          break;
        }
      }
    }

  } else if (Type == "AEROSURFACE_SCALE") {

    if (Output >= 0.0) Output = Input * Max;
    else Output = Input * (-Min);

    Output *= Gain;
  }

  if (IsOutput) SetOutput();

  return true;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX
#define INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX

#include <basebmp/bitmapdevice.hxx>
#include <basebmp/color.hxx>
#include <vcl/sysdata.hxx>

#include "salgdi.hxx"
#include "sallayout.hxx"

#ifdef IOS
#include "quartz/salgdi.h"
#include <premac.h>
#include <Foundation/Foundation.h>
#include <CoreGraphics/CoreGraphics.h>
#include <postmac.h>
#endif

class ServerFont;

#ifdef IOS
// To keep changes to the CoreText code shared with AOO to a minimum,
// let's continue calling the SalGraphics subclass "AquaSalGraphics" even if it
// is used by us also on iOS, where of course the term "Aqua" has no meaning at all.
// (Note that even on OS X, using the term "Aqua" is a misunderstanding or obsolete.)
#define SvpSalGraphics AquaSalGraphics
#endif

class SvpSalGraphics : public SalGraphics
{
#ifndef IOS
    basebmp::BitmapDeviceSharedPtr       m_aDevice;
    basebmp::BitmapDeviceSharedPtr       m_aOrigDevice;

    basebmp::BitmapDeviceSharedPtr       m_aClipMap;

    bool                                 m_bUseLineColor;
    basebmp::Color                       m_aLineColor;
    bool                                 m_bUseFillColor;
    basebmp::Color                       m_aFillColor;

    basebmp::DrawMode                    m_aDrawMode;

    // These fields are used only when we use FreeType to draw into a
    // headless backend, i.e. not on iOS.
    basebmp::Color                       m_aTextColor;
    ServerFont*                          m_pServerFont[ MAX_FALLBACK ];
    basebmp::Format                      m_eTextFmt;

protected:
    basegfx::B2IVector                   GetSize() { return m_aOrigDevice->getSize(); }

private:
    bool                                 m_bClipSetup;
    struct ClipUndoHandle {
        SvpSalGraphics                &m_rGfx;
        basebmp::BitmapDeviceSharedPtr m_aDevice;
        ClipUndoHandle( SvpSalGraphics *pGfx ) : m_rGfx( *pGfx ) {}
        ~ClipUndoHandle();
    };

public:
    void setDevice( basebmp::BitmapDeviceSharedPtr& rDevice );

#else
    friend class CTLayout;

    CGLayerRef                              mxLayer;
    // mirror AquaSalVirtualDevice::mbForeignContext for SvpSalGraphics objects related to such
    bool mbForeignContext;
    CGContextRef                         mrContext;
    class XorEmulation*                     mpXorEmulation;
    int                                     mnXorMode; // 0: off 1: on 2: invert only
    int                                     mnWidth;
    int                                     mnHeight;
    int                                  mnBitmapDepth;  // zero unless bitmap

    /// path representing current clip region
    CGMutablePathRef                        mxClipPath;

    /// Drawing colors
    /// pen color RGBA
    RGBAColor                               maLineColor;
    /// brush color RGBA
    RGBAColor                               maFillColor;

    // Device Font settings
    const CoreTextFontData*                 mpFontData;
    CoreTextStyle*                          mpTextStyle;
    RGBAColor                               maTextColor;
    /// allows text to be rendered without antialiasing
    bool                                    mbNonAntialiasedText;

    /// is this a printer graphics
    bool                                    mbPrinter;
    /// is this a virtual device graphics
    bool                                    mbVirDev;
#endif

protected:
    Region                               m_aClipRegion;

protected:
    virtual bool drawAlphaBitmap( const SalTwoRect&, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap );
    virtual bool drawTransformedBitmap(
        const basegfx::B2DPoint& rNull,
        const basegfx::B2DPoint& rX,
        const basegfx::B2DPoint& rY,
        const SalBitmap& rSourceBitmap,
        const SalBitmap* pAlphaBitmap);
    virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency );

public:
    SvpSalGraphics();
    virtual ~SvpSalGraphics();

    virtual void            GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY );
    virtual sal_uInt16      GetBitCount() const;
    virtual long            GetGraphicsWidth() const;

    virtual void            ResetClipRegion();
    virtual bool            setClipRegion( const Region& );

    virtual void            SetLineColor();
    virtual void            SetLineColor( SalColor nSalColor );
    virtual void            SetFillColor();
    virtual void            SetFillColor( SalColor nSalColor );

    virtual void            SetXORMode( bool bSet, bool );

    virtual void            SetROPLineColor( SalROPColor nROPColor );
    virtual void            SetROPFillColor( SalROPColor nROPColor );

    virtual void            SetTextColor( SalColor nSalColor );
    virtual sal_uInt16      SetFont( FontSelectPattern*, int nFallbackLevel );
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel );
    virtual const ImplFontCharMap* GetImplFontCharMap() const;
    virtual bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const;
    virtual void            GetDevFontList( PhysicalFontCollection* );
    virtual void ClearDevFontCache();
    virtual bool            AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName );
    virtual bool        CreateFontSubset( const OUString& rToFile,
                                              const PhysicalFontFace*,
                                              sal_GlyphId* pGlyphIds,
                                              sal_uInt8* pEncoding,
                                              sal_Int32* pWidths,
                                              int nGlyphs,
                                              FontSubsetInfo& rInfo
                                              );
    virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded );
    virtual const void*     GetEmbedFontData( const PhysicalFontFace*,
                                              const sal_Ucs* pUnicodes,
                                              sal_Int32* pWidths,
                                              FontSubsetInfo& rInfo,
                                              long* pDataLen );
    virtual void            FreeEmbedFontData( const void* pData, long nDataLen );
    virtual void            GetGlyphWidths( const PhysicalFontFace*,
                                            bool bVertical,
                                            Int32Vector& rWidths,
                                            Ucs2UIntMap& rUnicodeEnc );
    virtual bool            GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& );
    virtual bool            GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& );
    virtual SalLayout*      GetTextLayout( ImplLayoutArgs&, int nFallbackLevel );
    virtual void            DrawServerFontLayout( const ServerFontLayout& );
    virtual bool            supportsOperation( OutDevSupportType ) const;
    virtual void            drawPixel( long nX, long nY );
    virtual void            drawPixel( long nX, long nY, SalColor nSalColor );
    virtual void            drawLine( long nX1, long nY1, long nX2, long nY2 );
    virtual void            drawRect( long nX, long nY, long nWidth, long nHeight );
    virtual bool            drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency );
    virtual bool            drawPolyLine( const ::basegfx::B2DPolygon&,
                                          double fTransparency,
                                          const ::basegfx::B2DVector& rLineWidths,
                                          basegfx::B2DLineJoin,
                                          com::sun::star::drawing::LineCap);
    virtual void            drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry );
    virtual void            drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
    virtual void            drawPolyPolygon( sal_uInt32 nPoly,
                                             const sal_uInt32* pPoints,
                                             PCONSTSALPOINT* pPtAry );
    virtual bool        drawPolyLineBezier( sal_uInt32 nPoints,
                                                const SalPoint* pPtAry,
                                                const sal_uInt8* pFlgAry );
    virtual bool        drawPolygonBezier( sal_uInt32 nPoints,
                                               const SalPoint* pPtAry,
                                               const sal_uInt8* pFlgAry );
    virtual bool        drawPolyPolygonBezier( sal_uInt32 nPoly,
                                                   const sal_uInt32* pPoints,
                                                   const SalPoint* const* pPtAry,
                                                   const sal_uInt8* const* pFlgAry );

    virtual void            copyArea( long nDestX,
                                      long nDestY,
                                      long nSrcX,
                                      long nSrcY,
                                      long nSrcWidth,
                                      long nSrcHeight,
                                      sal_uInt16 nFlags );
    virtual void            copyBits( const SalTwoRect& rPosAry,
                                      SalGraphics* pSrcGraphics );
    virtual void            drawBitmap( const SalTwoRect& rPosAry,
                                        const SalBitmap& rSalBitmap );
    virtual void            drawBitmap( const SalTwoRect& rPosAry,
                                        const SalBitmap& rSalBitmap,
                                        SalColor nTransparentColor );
    virtual void            drawBitmap( const SalTwoRect& rPosAry,
                                        const SalBitmap& rSalBitmap,
                                        const SalBitmap& rTransparentBitmap );
    virtual void            drawMask( const SalTwoRect& rPosAry,
                                      const SalBitmap& rSalBitmap,
                                      SalColor nMaskColor );
    virtual SalBitmap*      getBitmap( long nX, long nY, long nWidth, long nHeight );
    virtual SalColor        getPixel( long nX, long nY );
    virtual void            invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags );
    virtual void            invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags );

    virtual bool        drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize );

    virtual SystemGraphicsData GetGraphicsData() const;
    virtual SystemFontData  GetSysFontData( int nFallbacklevel ) const;

#ifdef IOS
    void                SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext, int = 0 );

    bool CheckContext();
    CGContextRef GetContext();
    bool GetRawFontData( const PhysicalFontFace* pFontData,
                         std::vector<unsigned char>& rBuffer,
                         bool* pJustCFF );
    void                RefreshRect( const CGRect& ) { };
    void                RefreshRect(float lX, float lY, float lWidth, float lHeight);
    void                SetState();
    void                UnsetState();
    void                InvalidateContext();
    bool                IsPenVisible() const    { return maLineColor.IsVisible(); }
    bool                IsBrushVisible() const  { return maFillColor.IsVisible(); }
    void                ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels
    CGPoint*                makeCGptArray(sal_uLong nPoints, const SalPoint*  pPtAry);
    bool IsFlipped() const { return false; }
    void ApplyXorContext();
    void Pattern50Fill();
#endif
};

#endif // INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Return two accidentally removed member functions<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX
#define INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX

#include <basebmp/bitmapdevice.hxx>
#include <basebmp/color.hxx>
#include <vcl/sysdata.hxx>

#include "salgdi.hxx"
#include "sallayout.hxx"

#ifdef IOS
#include "quartz/salgdi.h"
#include <premac.h>
#include <Foundation/Foundation.h>
#include <CoreGraphics/CoreGraphics.h>
#include <postmac.h>
#endif

class ServerFont;

#ifdef IOS
// To keep changes to the CoreText code shared with AOO to a minimum,
// let's continue calling the SalGraphics subclass "AquaSalGraphics" even if it
// is used by us also on iOS, where of course the term "Aqua" has no meaning at all.
// (Note that even on OS X, using the term "Aqua" is a misunderstanding or obsolete.)
#define SvpSalGraphics AquaSalGraphics
#endif

class SvpSalGraphics : public SalGraphics
{
#ifndef IOS
    basebmp::BitmapDeviceSharedPtr       m_aDevice;
    basebmp::BitmapDeviceSharedPtr       m_aOrigDevice;

    basebmp::BitmapDeviceSharedPtr       m_aClipMap;

    bool                                 m_bUseLineColor;
    basebmp::Color                       m_aLineColor;
    bool                                 m_bUseFillColor;
    basebmp::Color                       m_aFillColor;

    basebmp::DrawMode                    m_aDrawMode;

    // These fields are used only when we use FreeType to draw into a
    // headless backend, i.e. not on iOS.
    basebmp::Color                       m_aTextColor;
    ServerFont*                          m_pServerFont[ MAX_FALLBACK ];
    basebmp::Format                      m_eTextFmt;

protected:
    basegfx::B2IVector                   GetSize() { return m_aOrigDevice->getSize(); }

private:
    bool                                 m_bClipSetup;
    struct ClipUndoHandle {
        SvpSalGraphics                &m_rGfx;
        basebmp::BitmapDeviceSharedPtr m_aDevice;
        ClipUndoHandle( SvpSalGraphics *pGfx ) : m_rGfx( *pGfx ) {}
        ~ClipUndoHandle();
    };
    bool isClippedSetup( const basegfx::B2IBox &aRange, ClipUndoHandle &rUndo );
    void ensureClip();

public:
    void setDevice( basebmp::BitmapDeviceSharedPtr& rDevice );

#else
    friend class CTLayout;

    CGLayerRef                              mxLayer;
    // mirror AquaSalVirtualDevice::mbForeignContext for SvpSalGraphics objects related to such
    bool mbForeignContext;
    CGContextRef                         mrContext;
    class XorEmulation*                     mpXorEmulation;
    int                                     mnXorMode; // 0: off 1: on 2: invert only
    int                                     mnWidth;
    int                                     mnHeight;
    int                                  mnBitmapDepth;  // zero unless bitmap

    /// path representing current clip region
    CGMutablePathRef                        mxClipPath;

    /// Drawing colors
    /// pen color RGBA
    RGBAColor                               maLineColor;
    /// brush color RGBA
    RGBAColor                               maFillColor;

    // Device Font settings
    const CoreTextFontData*                 mpFontData;
    CoreTextStyle*                          mpTextStyle;
    RGBAColor                               maTextColor;
    /// allows text to be rendered without antialiasing
    bool                                    mbNonAntialiasedText;

    /// is this a printer graphics
    bool                                    mbPrinter;
    /// is this a virtual device graphics
    bool                                    mbVirDev;
#endif

protected:
    Region                               m_aClipRegion;

protected:
    virtual bool drawAlphaBitmap( const SalTwoRect&, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap );
    virtual bool drawTransformedBitmap(
        const basegfx::B2DPoint& rNull,
        const basegfx::B2DPoint& rX,
        const basegfx::B2DPoint& rY,
        const SalBitmap& rSourceBitmap,
        const SalBitmap* pAlphaBitmap);
    virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency );

public:
    SvpSalGraphics();
    virtual ~SvpSalGraphics();

    virtual void            GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY );
    virtual sal_uInt16      GetBitCount() const;
    virtual long            GetGraphicsWidth() const;

    virtual void            ResetClipRegion();
    virtual bool            setClipRegion( const Region& );

    virtual void            SetLineColor();
    virtual void            SetLineColor( SalColor nSalColor );
    virtual void            SetFillColor();
    virtual void            SetFillColor( SalColor nSalColor );

    virtual void            SetXORMode( bool bSet, bool );

    virtual void            SetROPLineColor( SalROPColor nROPColor );
    virtual void            SetROPFillColor( SalROPColor nROPColor );

    virtual void            SetTextColor( SalColor nSalColor );
    virtual sal_uInt16      SetFont( FontSelectPattern*, int nFallbackLevel );
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel );
    virtual const ImplFontCharMap* GetImplFontCharMap() const;
    virtual bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const;
    virtual void            GetDevFontList( PhysicalFontCollection* );
    virtual void ClearDevFontCache();
    virtual bool            AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName );
    virtual bool        CreateFontSubset( const OUString& rToFile,
                                              const PhysicalFontFace*,
                                              sal_GlyphId* pGlyphIds,
                                              sal_uInt8* pEncoding,
                                              sal_Int32* pWidths,
                                              int nGlyphs,
                                              FontSubsetInfo& rInfo
                                              );
    virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded );
    virtual const void*     GetEmbedFontData( const PhysicalFontFace*,
                                              const sal_Ucs* pUnicodes,
                                              sal_Int32* pWidths,
                                              FontSubsetInfo& rInfo,
                                              long* pDataLen );
    virtual void            FreeEmbedFontData( const void* pData, long nDataLen );
    virtual void            GetGlyphWidths( const PhysicalFontFace*,
                                            bool bVertical,
                                            Int32Vector& rWidths,
                                            Ucs2UIntMap& rUnicodeEnc );
    virtual bool            GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& );
    virtual bool            GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& );
    virtual SalLayout*      GetTextLayout( ImplLayoutArgs&, int nFallbackLevel );
    virtual void            DrawServerFontLayout( const ServerFontLayout& );
    virtual bool            supportsOperation( OutDevSupportType ) const;
    virtual void            drawPixel( long nX, long nY );
    virtual void            drawPixel( long nX, long nY, SalColor nSalColor );
    virtual void            drawLine( long nX1, long nY1, long nX2, long nY2 );
    virtual void            drawRect( long nX, long nY, long nWidth, long nHeight );
    virtual bool            drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency );
    virtual bool            drawPolyLine( const ::basegfx::B2DPolygon&,
                                          double fTransparency,
                                          const ::basegfx::B2DVector& rLineWidths,
                                          basegfx::B2DLineJoin,
                                          com::sun::star::drawing::LineCap);
    virtual void            drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry );
    virtual void            drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
    virtual void            drawPolyPolygon( sal_uInt32 nPoly,
                                             const sal_uInt32* pPoints,
                                             PCONSTSALPOINT* pPtAry );
    virtual bool        drawPolyLineBezier( sal_uInt32 nPoints,
                                                const SalPoint* pPtAry,
                                                const sal_uInt8* pFlgAry );
    virtual bool        drawPolygonBezier( sal_uInt32 nPoints,
                                               const SalPoint* pPtAry,
                                               const sal_uInt8* pFlgAry );
    virtual bool        drawPolyPolygonBezier( sal_uInt32 nPoly,
                                                   const sal_uInt32* pPoints,
                                                   const SalPoint* const* pPtAry,
                                                   const sal_uInt8* const* pFlgAry );

    virtual void            copyArea( long nDestX,
                                      long nDestY,
                                      long nSrcX,
                                      long nSrcY,
                                      long nSrcWidth,
                                      long nSrcHeight,
                                      sal_uInt16 nFlags );
    virtual void            copyBits( const SalTwoRect& rPosAry,
                                      SalGraphics* pSrcGraphics );
    virtual void            drawBitmap( const SalTwoRect& rPosAry,
                                        const SalBitmap& rSalBitmap );
    virtual void            drawBitmap( const SalTwoRect& rPosAry,
                                        const SalBitmap& rSalBitmap,
                                        SalColor nTransparentColor );
    virtual void            drawBitmap( const SalTwoRect& rPosAry,
                                        const SalBitmap& rSalBitmap,
                                        const SalBitmap& rTransparentBitmap );
    virtual void            drawMask( const SalTwoRect& rPosAry,
                                      const SalBitmap& rSalBitmap,
                                      SalColor nMaskColor );
    virtual SalBitmap*      getBitmap( long nX, long nY, long nWidth, long nHeight );
    virtual SalColor        getPixel( long nX, long nY );
    virtual void            invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags );
    virtual void            invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags );

    virtual bool        drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize );

    virtual SystemGraphicsData GetGraphicsData() const;
    virtual SystemFontData  GetSysFontData( int nFallbacklevel ) const;

#ifdef IOS
    void                SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext, int = 0 );

    bool CheckContext();
    CGContextRef GetContext();
    bool GetRawFontData( const PhysicalFontFace* pFontData,
                         std::vector<unsigned char>& rBuffer,
                         bool* pJustCFF );
    void                RefreshRect( const CGRect& ) { };
    void                RefreshRect(float lX, float lY, float lWidth, float lHeight);
    void                SetState();
    void                UnsetState();
    void                InvalidateContext();
    bool                IsPenVisible() const    { return maLineColor.IsVisible(); }
    bool                IsBrushVisible() const  { return maFillColor.IsVisible(); }
    void                ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels
    CGPoint*                makeCGptArray(sal_uLong nPoints, const SalPoint*  pPtAry);
    bool IsFlipped() const { return false; }
    void ApplyXorContext();
    void Pattern50Fill();
#endif
};

#endif // INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>
#include <stdlib.h>     /* srand, rand */

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

#include <unsupported/Eigen/SparseExtra>

#ifdef _OPENMP
#include <omp.h>
#else
#include <tbb/tbb.h>
#endif

#include "bpmf.h"

using namespace std;
using namespace Eigen;

const int num_feat = 32;

const int alpha = 2;
const int nsims = 20;
const int burnin = 5;

double mean_rating = .0;

typedef SparseMatrix<double> SparseMatrixD;
SparseMatrixD M, Mt, P;

typedef Matrix<double, num_feat, 1> VectorNd;
typedef Matrix<double, num_feat, num_feat> MatrixNNd;
typedef Matrix<double, num_feat, Dynamic> MatrixNXd;

VectorNd mu_u;
VectorNd mu_m;
MatrixNNd Lambda_u;
MatrixNNd Lambda_m;
MatrixNXd sample_u;
MatrixNXd sample_m;

// parameters of Inv-Whishart distribution (see paper for details)
MatrixNNd WI_u;
const int b0_u = 2;
const int df_u = num_feat;
VectorNd mu0_u;

MatrixNNd WI_m;
const int b0_m = 2;
const int df_m = num_feat;
VectorNd mu0_m;

void init() {
    mean_rating = M.sum() / M.nonZeros();
    Lambda_u.setIdentity();
    Lambda_m.setIdentity();

    sample_u = MatrixNXd(num_feat,M.rows());
    sample_m = MatrixNXd(num_feat,M.cols());
    sample_u.setZero();
    sample_m.setZero();

    // parameters of Inv-Whishart distribution (see paper for details)
    WI_u.setIdentity();
    mu0_u.setZero();

    WI_m.setIdentity();
    mu0_m.setZero();
}

pair<double,double> eval_probe_vec(const MatrixNXd &sample_m, const MatrixNXd &sample_u, double mean_rating)
{
    unsigned n = P.nonZeros();
    unsigned correct = 0;
    double diff = .0;
    for (int k=0; k<P.outerSize(); ++k)
        for (SparseMatrix<double>::InnerIterator it(P,k); it; ++it) {
            double prediction = sample_m.col(it.col()).dot(sample_u.col(it.row())) + mean_rating;
            //cout << "prediction: " << prediction - mean_rating << " + " << mean_rating << " = " << prediction << endl;
            //cout << "actual: " << it.value() << endl;
            correct += (it.value() < log10(200)) == (prediction < log10(200));
            diff += abs(it.value() - prediction);
        }

    return std::make_pair((double)correct / n, diff / n);
}

double randn(double) {
  static mt19937 rng;
  static normal_distribution<> nd;
  return nd(rng);
}

void sample_movie(MatrixNXd &s, int mm, const SparseMatrixD &mat, double mean_rating,
    const MatrixNXd &samples, int alpha, const VectorNd &mu_u, const MatrixNNd &Lambda_u)
{
    int i = 0;
    MatrixNNd MM; MM.setZero();
    VectorNd rr; rr.setZero();
    for (SparseMatrixD::InnerIterator it(mat,mm); it; ++it, ++i) {
        // cout << "M[" << it.row() << "," << it.col() << "] = " << it.value() << endl;
        auto col = samples.col(it.row());
        MM += col * col.transpose();
        rr += col * ((it.value() - mean_rating) * alpha);
    }

    auto MMs = alpha * MM;
    MatrixNNd covar = (Lambda_u + MMs).inverse();
    auto U = Lambda_u * mu_u;
    auto mu = covar * (rr + U);

    MatrixNNd chol = covar.llt().matrixL();
    auto r = VectorXd::NullaryExpr(num_feat, ptr_fun(randn));
    s.col(mm) = chol * r + mu;

#ifdef TEST_SAMPLE
      cout << "movie " << mm << ":" << result.cols() << " x" << result.rows() << endl;
      cout << "mean rating " << mean_rating << endl;
      cout << "E = [" << E << "]" << endl;
      cout << "rr = [" << rr << "]" << endl;
      cout << "MM = [" << MM << "]" << endl;
      cout << "Lambda_u = [" << Lambda_u << "]" << endl;
      cout << "covar = [" << covar << "]" << endl;
      cout << "mu = [" << mu << "]" << endl;
      cout << "chol = [" << chol << "]" << endl;
      cout << "rand = [" << r <<"]" <<  endl;
      cout << "result = [" << result << "]" << endl;
#endif

}

#ifdef TEST_SAMPLE
void test() {
    MatrixNXd sample_u(M.rows());
    MatrixNXd sample_m(M.cols());

    mu_m.setZero();
    Lambda_m.setIdentity();
    sample_u.setConstant(2.0);
    Lambda_m *= 0.5;
    sample_m.col(0) = sample_movie(0, M, mean_rating, sample_u, alpha, mu_m, Lambda_m);
}

#else

void run() {
    auto start = tick();

    std::cout << "Sampling" << endl;
    for(int i=0; i<nsims; ++i) {

      // Sample from movie hyperparams
      tie(mu_m, Lambda_m) = CondNormalWishart(sample_m, mu0_m, b0_m, WI_m, df_m);

      // Sample from user hyperparams
      tie(mu_u, Lambda_u) = CondNormalWishart(sample_u, mu0_u, b0_u, WI_u, df_u);

      const int num_m = M.cols();
      const int num_u = M.rows();
#ifdef _OPENMP
#pragma omp parallel for
      for(int mm=0; mm<num_m; ++mm) {
        sample_movie(sample_m, mm, M, mean_rating, sample_u, alpha, mu_m, Lambda_m);
      }
#pragma omp parallel for
      for(int uu=0; uu<num_u; ++uu) {
        sample_movie(sample_u, uu, Mt, mean_rating, sample_m, alpha, mu_u, Lambda_u);
      }
#else
      tbb::parallel_for(0, num_m, [](int mm) {
        sample_movie(sample_m, mm, M, mean_rating, sample_u, alpha, mu_m, Lambda_m);
      });

      tbb::parallel_for(0, num_u, [](int uu) {
         sample_movie(sample_u, uu, Mt, mean_rating, sample_m, alpha, mu_u, Lambda_u);
       });
#endif

      auto eval = eval_probe_vec(sample_m, sample_u, mean_rating);
      double norm_u = sample_u.norm();
      double norm_m = sample_m.norm();
      auto end = tick();
      auto elapsed = end - start;
      double samples_per_sec = (i + 1) * (M.rows() + M.cols()) / elapsed;

      printf("Iteration %d:\t num_correct: %3.2f%%\tavg_diff: %3.2f\tFU(%6.2f)\tFM(%6.2f)\tSamples/sec: %6.2f\n",
              i, 100*eval.first, eval.second, norm_u, norm_m, samples_per_sec);
    }
}

#endif

int main(int argc, char *argv[])
{
    assert(argv[1] && argv[2] && "filename missing");
    Eigen::initParallel();

    loadMarket(M, argv[1]);
    Mt = M.transpose();
    loadMarket(P, argv[2]);

    assert(M.nonZeros() > P.nonZeros());

    init();
#ifdef TEST_SAMPLE
    test();
#else
    run();
#endif

    return 0;
}
<commit_msg>c++: fix missing include<commit_after>
#include <stdlib.h>     /* srand, rand */

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <random>

#include <unsupported/Eigen/SparseExtra>

#ifdef _OPENMP
#include <omp.h>
#else
#include <tbb/tbb.h>
#endif

#include "bpmf.h"

using namespace std;
using namespace Eigen;

const int num_feat = 32;

const int alpha = 2;
const int nsims = 20;
const int burnin = 5;

double mean_rating = .0;

typedef SparseMatrix<double> SparseMatrixD;
SparseMatrixD M, Mt, P;

typedef Matrix<double, num_feat, 1> VectorNd;
typedef Matrix<double, num_feat, num_feat> MatrixNNd;
typedef Matrix<double, num_feat, Dynamic> MatrixNXd;

VectorNd mu_u;
VectorNd mu_m;
MatrixNNd Lambda_u;
MatrixNNd Lambda_m;
MatrixNXd sample_u;
MatrixNXd sample_m;

// parameters of Inv-Whishart distribution (see paper for details)
MatrixNNd WI_u;
const int b0_u = 2;
const int df_u = num_feat;
VectorNd mu0_u;

MatrixNNd WI_m;
const int b0_m = 2;
const int df_m = num_feat;
VectorNd mu0_m;

void init() {
    mean_rating = M.sum() / M.nonZeros();
    Lambda_u.setIdentity();
    Lambda_m.setIdentity();

    sample_u = MatrixNXd(num_feat,M.rows());
    sample_m = MatrixNXd(num_feat,M.cols());
    sample_u.setZero();
    sample_m.setZero();

    // parameters of Inv-Whishart distribution (see paper for details)
    WI_u.setIdentity();
    mu0_u.setZero();

    WI_m.setIdentity();
    mu0_m.setZero();
}

pair<double,double> eval_probe_vec(const MatrixNXd &sample_m, const MatrixNXd &sample_u, double mean_rating)
{
    unsigned n = P.nonZeros();
    unsigned correct = 0;
    double diff = .0;
    for (int k=0; k<P.outerSize(); ++k)
        for (SparseMatrix<double>::InnerIterator it(P,k); it; ++it) {
            double prediction = sample_m.col(it.col()).dot(sample_u.col(it.row())) + mean_rating;
            //cout << "prediction: " << prediction - mean_rating << " + " << mean_rating << " = " << prediction << endl;
            //cout << "actual: " << it.value() << endl;
            correct += (it.value() < log10(200)) == (prediction < log10(200));
            diff += abs(it.value() - prediction);
        }

    return std::make_pair((double)correct / n, diff / n);
}

double randn(double) {
  static mt19937 rng;
  static normal_distribution<> nd;
  return nd(rng);
}

void sample_movie(MatrixNXd &s, int mm, const SparseMatrixD &mat, double mean_rating,
    const MatrixNXd &samples, int alpha, const VectorNd &mu_u, const MatrixNNd &Lambda_u)
{
    int i = 0;
    MatrixNNd MM; MM.setZero();
    VectorNd rr; rr.setZero();
    for (SparseMatrixD::InnerIterator it(mat,mm); it; ++it, ++i) {
        // cout << "M[" << it.row() << "," << it.col() << "] = " << it.value() << endl;
        auto col = samples.col(it.row());
        MM += col * col.transpose();
        rr += col * ((it.value() - mean_rating) * alpha);
    }

    auto MMs = alpha * MM;
    MatrixNNd covar = (Lambda_u + MMs).inverse();
    auto U = Lambda_u * mu_u;
    auto mu = covar * (rr + U);

    MatrixNNd chol = covar.llt().matrixL();
    auto r = VectorXd::NullaryExpr(num_feat, ptr_fun(randn));
    s.col(mm) = chol * r + mu;

#ifdef TEST_SAMPLE
      cout << "movie " << mm << ":" << result.cols() << " x" << result.rows() << endl;
      cout << "mean rating " << mean_rating << endl;
      cout << "E = [" << E << "]" << endl;
      cout << "rr = [" << rr << "]" << endl;
      cout << "MM = [" << MM << "]" << endl;
      cout << "Lambda_u = [" << Lambda_u << "]" << endl;
      cout << "covar = [" << covar << "]" << endl;
      cout << "mu = [" << mu << "]" << endl;
      cout << "chol = [" << chol << "]" << endl;
      cout << "rand = [" << r <<"]" <<  endl;
      cout << "result = [" << result << "]" << endl;
#endif

}

#ifdef TEST_SAMPLE
void test() {
    MatrixNXd sample_u(M.rows());
    MatrixNXd sample_m(M.cols());

    mu_m.setZero();
    Lambda_m.setIdentity();
    sample_u.setConstant(2.0);
    Lambda_m *= 0.5;
    sample_m.col(0) = sample_movie(0, M, mean_rating, sample_u, alpha, mu_m, Lambda_m);
}

#else

void run() {
    auto start = tick();

    std::cout << "Sampling" << endl;
    for(int i=0; i<nsims; ++i) {

      // Sample from movie hyperparams
      tie(mu_m, Lambda_m) = CondNormalWishart(sample_m, mu0_m, b0_m, WI_m, df_m);

      // Sample from user hyperparams
      tie(mu_u, Lambda_u) = CondNormalWishart(sample_u, mu0_u, b0_u, WI_u, df_u);

      const int num_m = M.cols();
      const int num_u = M.rows();
#ifdef _OPENMP
#pragma omp parallel for
      for(int mm=0; mm<num_m; ++mm) {
        sample_movie(sample_m, mm, M, mean_rating, sample_u, alpha, mu_m, Lambda_m);
      }
#pragma omp parallel for
      for(int uu=0; uu<num_u; ++uu) {
        sample_movie(sample_u, uu, Mt, mean_rating, sample_m, alpha, mu_u, Lambda_u);
      }
#else
      tbb::parallel_for(0, num_m, [](int mm) {
        sample_movie(sample_m, mm, M, mean_rating, sample_u, alpha, mu_m, Lambda_m);
      });

      tbb::parallel_for(0, num_u, [](int uu) {
         sample_movie(sample_u, uu, Mt, mean_rating, sample_m, alpha, mu_u, Lambda_u);
       });
#endif

      auto eval = eval_probe_vec(sample_m, sample_u, mean_rating);
      double norm_u = sample_u.norm();
      double norm_m = sample_m.norm();
      auto end = tick();
      auto elapsed = end - start;
      double samples_per_sec = (i + 1) * (M.rows() + M.cols()) / elapsed;

      printf("Iteration %d:\t num_correct: %3.2f%%\tavg_diff: %3.2f\tFU(%6.2f)\tFM(%6.2f)\tSamples/sec: %6.2f\n",
              i, 100*eval.first, eval.second, norm_u, norm_m, samples_per_sec);
    }
}

#endif

int main(int argc, char *argv[])
{
    assert(argv[1] && argv[2] && "filename missing");
    Eigen::initParallel();

    loadMarket(M, argv[1]);
    Mt = M.transpose();
    loadMarket(P, argv[2]);

    assert(M.nonZeros() > P.nonZeros());

    init();
#ifdef TEST_SAMPLE
    test();
#else
    run();
#endif

    return 0;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include "./types.h"
#include "utils/logger.h"

namespace {
bool IsTypeInvalid(rpc::Enum<rpc::policy_table_interface_base::RequestType> request) { return !request.is_valid(); }
}

namespace rpc {
namespace policy_table_interface_base {

CREATE_LOGGERPTR_GLOBAL(logger_, "PolicyTableValidation")

void RemoveInvalidTypes(RequestTypes& types) {
 types.erase(
       std::remove_if(types.begin(), types.end(), &IsTypeInvalid),
       types.end());
}

bool PolicyBase::Validate() const {
  return true;
}

bool ApplicationPoliciesSection::Validate() const {
  ApplicationPolicies::iterator it_default_policy =
      apps.find(kDefaultApp);
  ApplicationPolicies::iterator it_pre_data_policy =
      apps.find(kPreDataConsentApp);

  // Default and PreData policies are mandatory
  if (apps.end() == it_default_policy || apps.end() == it_pre_data_policy) {
    LOG4CXX_ERROR(logger_, "Default or preData policy is not present.");
    return false;
  }

  // Device policy is mandatory
  if (!device.is_initialized()) {
    LOG4CXX_ERROR(logger_, "Device policy is not present.");
    return false;
  }

  PolicyTableType pt_type = GetPolicyTableType();
  if (PT_PRELOADED != pt_type && PT_UPDATE != pt_type) {
    return true;
  }

  if (!it_default_policy->second.RequestType.is_valid()) {
    LOG4CXX_WARN(logger_,
                 "Default policy RequestTypes are not valid. Will be cleaned.");
    RemoveInvalidTypes(*it_default_policy->second.RequestType);
    // If preloaded does not have valid default types - validation fails
    // Otherwise default will be empty, i.e. all types allowed
    if (PT_PRELOADED == pt_type) {
      if (it_default_policy->second.RequestType->empty()) {
        LOG4CXX_ERROR(
              logger_,
              "Default policy RequestTypes empty after clean-up. Exiting.");
        return false;
      }
    }
  }

  ApplicationPolicies::iterator iter = apps.begin();
  ApplicationPolicies::iterator end_iter = apps.end();

  while(iter != end_iter) {
    ApplicationParams& app_params = (*iter).second;
    bool is_request_type_ommited = !app_params.RequestType.is_initialized();
    bool is_request_type_valid = app_params.RequestType.is_valid();
    bool is_request_type_empty = app_params.RequestType->empty();

    if (PT_PRELOADED == pt_type) {
      if (!is_request_type_valid) {
        LOG4CXX_WARN(
              logger_,
              "App policy RequestTypes are not valid. Will be cleaned.");
        RemoveInvalidTypes(*app_params.RequestType);
        if (app_params.RequestType->empty()) {
          LOG4CXX_ERROR(
                logger_,
                "App policy RequestTypes empty after clean-up. Exiting.");
          return false;
        }
      }
    } else {
      if (is_request_type_ommited) {
        LOG4CXX_WARN(logger_, "App policy RequestTypes ommited."
                              " Will be replaced with default.");
        app_params.RequestType = apps[kDefaultApp].RequestType;
        continue;
      }
      if (!is_request_type_valid) {
        LOG4CXX_WARN(
              logger_,
              "App policy RequestTypes are invalid. Will be cleaned.");
        RemoveInvalidTypes(*app_params.RequestType);
        if (app_params.RequestType->empty()) {
          LOG4CXX_WARN(logger_, "App policy RequestTypes empty after clean-up."
                                " Will be replaced with default.");
          app_params.RequestType = apps[kDefaultApp].RequestType;
          continue;
        }
      }
      if (is_request_type_empty) {
        LOG4CXX_WARN(logger_, "App policy RequestTypes empty.");
      }
    }
    ++iter;
  }

  return true;
}

bool ApplicationParams::Validate() const {
  return true;
}
bool RpcParameters::Validate() const {
  return true;
}
bool Rpcs::Validate() const {
  return true;
}

bool ModuleConfig::Validate() const {

  if (PT_PRELOADED == GetPolicyTableType()) {

    if (vehicle_make.is_initialized()) {
      return false;
    }
    if (vehicle_year.is_initialized()) {
      return false;
    }
    if (vehicle_model.is_initialized()) {
      return false;
    }
  }
  return true;
}

bool MessageString::Validate() const {
  return true;
}

bool MessageLanguages::Validate() const {
  if (PT_SNAPSHOT == GetPolicyTableType()) {
    return false;
  }
  return true;
}

bool ConsumerFriendlyMessages::Validate() const {
  if (PT_SNAPSHOT == GetPolicyTableType()) {
    return false;
  }
  return true;
}

bool ModuleMeta::Validate() const {
  return true;
}

bool AppLevel::Validate() const {
  if (PT_PRELOADED == GetPolicyTableType() ||
      PT_UPDATE == GetPolicyTableType()) {
    return false;
  }
  return true;
}

bool UsageAndErrorCounts::Validate() const {
  if (PT_PRELOADED == GetPolicyTableType() ||
      PT_UPDATE == GetPolicyTableType()) {
   return false;
  }
  return true;
}
bool DeviceParams::Validate() const {
  return true;
}
bool PolicyTable::Validate() const {
  if (PT_PRELOADED == GetPolicyTableType() ||
      PT_UPDATE == GetPolicyTableType()) {
    if (device_data.is_initialized()) {
      return false;
    }
  }
  return true;
}
bool Table::Validate() const {
  return true;
}
}  // namespace policy_table_interface_base
}  // namespace rpc

<commit_msg>Fixed RequestType validation.<commit_after>#include <algorithm>
#include "./types.h"
#include "utils/logger.h"

namespace {
bool IsTypeInvalid(rpc::Enum<rpc::policy_table_interface_base::RequestType> request) { return !request.is_valid(); }
}

namespace rpc {
namespace policy_table_interface_base {

CREATE_LOGGERPTR_GLOBAL(logger_, "PolicyTableValidation")

void RemoveInvalidTypes(RequestTypes& types) {
 types.erase(
       std::remove_if(types.begin(), types.end(), &IsTypeInvalid),
       types.end());
}

bool PolicyBase::Validate() const {
  return true;
}

bool ApplicationPoliciesSection::Validate() const {
  ApplicationPolicies::iterator it_default_policy =
      apps.find(kDefaultApp);
  ApplicationPolicies::iterator it_pre_data_policy =
      apps.find(kPreDataConsentApp);

  // Default and PreData policies are mandatory
  if (apps.end() == it_default_policy || apps.end() == it_pre_data_policy) {
    LOG4CXX_ERROR(logger_, "Default or preData policy is not present.");
    return false;
  }

  // Device policy is mandatory
  if (!device.is_initialized()) {
    LOG4CXX_ERROR(logger_, "Device policy is not present.");
    return false;
  }

  PolicyTableType pt_type = GetPolicyTableType();
  if (PT_PRELOADED != pt_type && PT_UPDATE != pt_type) {
    return true;
  }

  if (!it_default_policy->second.RequestType.is_valid()) {
    LOG4CXX_WARN(logger_,
                 "Default policy RequestTypes are not valid. Will be cleaned.");
    RemoveInvalidTypes(*it_default_policy->second.RequestType);
    // If preloaded does not have valid default types - validation fails
    // Otherwise default will be empty, i.e. all types allowed
    if (PT_PRELOADED == pt_type) {
      if (it_default_policy->second.RequestType->empty()) {
        LOG4CXX_ERROR(
              logger_,
              "Default policy RequestTypes empty after clean-up. Exiting.");
        return false;
      }
    }
  }

  ApplicationPolicies::iterator iter = apps.begin();
  ApplicationPolicies::iterator end_iter = apps.end();

  while(iter != end_iter) {
    ApplicationParams& app_params = (*iter).second;
    bool is_request_type_ommited = !app_params.RequestType.is_initialized();
    bool is_request_type_valid = app_params.RequestType.is_valid();
    bool is_request_type_empty = app_params.RequestType->empty();

    if (PT_PRELOADED == pt_type) {
      if (!is_request_type_valid) {
        LOG4CXX_WARN(
              logger_,
              "App policy RequestTypes are not valid. Will be cleaned.");
        RemoveInvalidTypes(*app_params.RequestType);
        if (app_params.RequestType->empty()) {
          LOG4CXX_ERROR(
                logger_,
                "App policy RequestTypes empty after clean-up. Exiting.");
          return false;
        }
      }
    } else {
      if (is_request_type_ommited) {
        LOG4CXX_WARN(logger_, "App policy RequestTypes ommited."
                              " Will be replaced with default.");
        app_params.RequestType = apps[kDefaultApp].RequestType;
        ++iter;
        continue;
      }
      if (!is_request_type_valid) {
        LOG4CXX_WARN(
              logger_,
              "App policy RequestTypes are invalid. Will be cleaned.");
        RemoveInvalidTypes(*app_params.RequestType);
        if (app_params.RequestType->empty()) {
          LOG4CXX_WARN(logger_, "App policy RequestTypes empty after clean-up."
                                " Will be replaced with default.");
          app_params.RequestType = apps[kDefaultApp].RequestType;
          ++iter;
          continue;
        }
      }
      if (is_request_type_empty) {
        LOG4CXX_WARN(logger_, "App policy RequestTypes empty.");
      }
    }
    ++iter;
  }

  return true;
}

bool ApplicationParams::Validate() const {
  return true;
}
bool RpcParameters::Validate() const {
  return true;
}
bool Rpcs::Validate() const {
  return true;
}

bool ModuleConfig::Validate() const {

  if (PT_PRELOADED == GetPolicyTableType()) {

    if (vehicle_make.is_initialized()) {
      return false;
    }
    if (vehicle_year.is_initialized()) {
      return false;
    }
    if (vehicle_model.is_initialized()) {
      return false;
    }
  }
  return true;
}

bool MessageString::Validate() const {
  return true;
}

bool MessageLanguages::Validate() const {
  if (PT_SNAPSHOT == GetPolicyTableType()) {
    return false;
  }
  return true;
}

bool ConsumerFriendlyMessages::Validate() const {
  if (PT_SNAPSHOT == GetPolicyTableType()) {
    return false;
  }
  return true;
}

bool ModuleMeta::Validate() const {
  return true;
}

bool AppLevel::Validate() const {
  if (PT_PRELOADED == GetPolicyTableType() ||
      PT_UPDATE == GetPolicyTableType()) {
    return false;
  }
  return true;
}

bool UsageAndErrorCounts::Validate() const {
  if (PT_PRELOADED == GetPolicyTableType() ||
      PT_UPDATE == GetPolicyTableType()) {
   return false;
  }
  return true;
}
bool DeviceParams::Validate() const {
  return true;
}
bool PolicyTable::Validate() const {
  if (PT_PRELOADED == GetPolicyTableType() ||
      PT_UPDATE == GetPolicyTableType()) {
    if (device_data.is_initialized()) {
      return false;
    }
  }
  return true;
}
bool Table::Validate() const {
  return true;
}
}  // namespace policy_table_interface_base
}  // namespace rpc

<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <list>
#include <chrono>
#include <sstream>

#include <string.h>

#ifndef _WIN32
#include <unistd.h>
#include <sys/select.h>
#include <sys/wait.h>
#endif

#include "plugin.h"
#include "term_network.h"
#include "term_data_handler.h"
#include "term_context.h"
#include "term_buffer.h"
#include "term_window.h"

#include "PortableThread.h"

#include "term_data_handler_impl.h"
#include "term_data_handler_impl_decl.h"

#include "read_termdata.h"

#include "string_utils.h"

const char * kPathSeparator =
#if defined _WIN32 || defined __CYGWIN__
    "\\";
#else
    "/";
#endif

static
bool load_cap_str(const std::string & termcap_dir,
                  const std::string & term_name,
                  std::string & term_entry) {
    std::string file_path = termcap_dir;
    file_path.append(kPathSeparator).append(term_name).append(".dat");

    return get_entry(file_path, term_name, term_entry);
}

void TermDataHandlerImpl::LoadNativeDataHandler() {
    std::string termcap_dir = GetPluginContext()->GetAppConfig()->GetEntry("/term/termcap_dir", "data");
    std::string term_name = GetPluginContext()->GetAppConfig()->GetEntry("/term/term_name", "xterm-256color");
    bool use_generic = GetPluginContext()->GetAppConfig()->GetEntryBool("/term/use_generic_cap", "true");

    std::stringstream ss;

    std::string term_entry;
    if (use_generic) {
        if (load_cap_str(termcap_dir, "generic-cap", term_entry))
            ss << term_entry;
    }

    if (!load_cap_str(termcap_dir, term_name, term_entry)) {
        if (load_cap_str(termcap_dir, "xterm-256color", term_entry)) {
            ss << term_entry;
        }
    } else {
        ss << term_entry;
    }

    m_Cap = parse_cap(ss.str());
    m_State = m_Cap->control_data_start_state;
    m_ParseContext = std::make_shared<ControlDataParserContext>();
}

void TermDataHandlerImpl::ProcessSingleCharNative(const char * ch) {
    if (!ch) {
        if (!m_State)
            return;

        HandleCap(false, 0);

        return;
    }

    auto next_state = m_State->handle(m_ParseContext, *ch);
    CapNameMapValue cap_tuple;

    if (!next_state || m_State->get_cap(m_ParseContext->params, cap_tuple)) {
        HandleCap(true, *ch);

        if (next_state) next_state->reset();

        next_state = m_State->handle(m_ParseContext, *ch);

        if (next_state) {
            m_State = next_state;
            if (*ch == 0x1B) {
                m_ControlData.push_back('\\');
                m_ControlData.push_back('E');
            } else {
                m_ControlData.push_back(*ch);
            }
        } else {
            output_char(m_DataContext, *ch, false);
        }

        return;
    }

    m_State = next_state;

    if (*ch == 0x1B) {
        m_ControlData.push_back('\\');
        m_ControlData.push_back('E');
    } else {
        m_ControlData.push_back(*ch);
    }
}

void TermDataHandlerImpl::HandleCap(bool check_unknown, char c) {
    CapNameMapValue cap_tuple;
    (void)c;

    auto result = m_State->get_cap(m_ParseContext->params, cap_tuple);

    if (result) {
        bool inc_param = std::get<1>(cap_tuple);

        if (inc_param) {
            for(auto & p : m_ParseContext->params) {
                if (p.has_int_value && p.int_value > 0)
                    p.int_value--;
            }
        }

        handle_cap(m_DataContext,
                   std::get<0>(cap_tuple),
                   m_ParseContext->params);

        if (m_CapStateStack.size() > 0) {
            std::tie(m_State,
                     m_ParseContext->params,
                     m_ControlData) = m_CapStateStack.front();
            m_CapStateStack.pop_front();
        } else {
            m_State = m_Cap->control_data_start_state;
            m_ParseContext->params.clear();
            m_ControlData.clear();
        }
    } else if (check_unknown && m_ControlData.size() > 0) {
        m_CapStateStack.push_front(std::make_tuple(m_State,
                                                   m_ParseContext->params,
                                                   m_ControlData));

        m_State = m_Cap->control_data_start_state;
        m_ParseContext->params.clear();
        m_ControlData.clear();
    }
}
<commit_msg>ignore unkown cap<commit_after>#include <iostream>
#include <vector>
#include <list>
#include <chrono>
#include <sstream>

#include <string.h>

#ifndef _WIN32
#include <unistd.h>
#include <sys/select.h>
#include <sys/wait.h>
#endif

#include "plugin.h"
#include "term_network.h"
#include "term_data_handler.h"
#include "term_context.h"
#include "term_buffer.h"
#include "term_window.h"

#include "PortableThread.h"

#include "term_data_handler_impl.h"
#include "term_data_handler_impl_decl.h"

#include "read_termdata.h"

#include "string_utils.h"

const char * kPathSeparator =
#if defined _WIN32 || defined __CYGWIN__
    "\\";
#else
    "/";
#endif

static
bool load_cap_str(const std::string & termcap_dir,
                  const std::string & term_name,
                  std::string & term_entry) {
    std::string file_path = termcap_dir;
    file_path.append(kPathSeparator).append(term_name).append(".dat");

    return get_entry(file_path, term_name, term_entry);
}

void TermDataHandlerImpl::LoadNativeDataHandler() {
    std::string termcap_dir = GetPluginContext()->GetAppConfig()->GetEntry("/term/termcap_dir", "data");
    std::string term_name = GetPluginContext()->GetAppConfig()->GetEntry("/term/term_name", "xterm-256color");
    bool use_generic = GetPluginContext()->GetAppConfig()->GetEntryBool("/term/use_generic_cap", "true");

    std::stringstream ss;

    std::string term_entry;
    if (use_generic) {
        if (load_cap_str(termcap_dir, "generic-cap", term_entry))
            ss << term_entry;
    }

    if (!load_cap_str(termcap_dir, term_name, term_entry)) {
        if (load_cap_str(termcap_dir, "xterm-256color", term_entry)) {
            ss << term_entry;
        }
    } else {
        ss << term_entry;
    }

    m_Cap = parse_cap(ss.str());
    m_State = m_Cap->control_data_start_state;
    m_ParseContext = std::make_shared<ControlDataParserContext>();
}

void TermDataHandlerImpl::ProcessSingleCharNative(const char * ch) {
    if (!ch) {
        if (!m_State)
            return;

        HandleCap(false, 0);

        return;
    }

    bool state_checked = false;

handle_state:
    auto next_state = m_State->handle(m_ParseContext, *ch);
    CapNameMapValue cap_tuple;

    if (!next_state || m_State->get_cap(m_ParseContext->params, cap_tuple)) {
        HandleCap(true, *ch);

        if (next_state) next_state->reset();

        next_state = m_State->handle(m_ParseContext, *ch);

        if (next_state) {
            m_State = next_state;
            if (*ch == 0x1B) {
                m_ControlData.push_back('\\');
                m_ControlData.push_back('E');
            } else {
                m_ControlData.push_back(*ch);
            }
        } else {
            if (*ch == 0x1B) {
                assert(!state_checked);
                state_checked = true;

                std::cout << "unknown/not defined cap found:";
                std::copy(m_ControlData.begin(),
                          m_ControlData.end(),
                          std::ostream_iterator<char>(std::cout, ""));
                std::cout << std::endl;

                m_State = m_Cap->control_data_start_state;
                m_ParseContext->params.clear();
                m_ControlData.clear();

                goto handle_state;
            }

            output_char(m_DataContext, *ch, false);
        }

        return;
    }

    m_State = next_state;

    if (*ch == 0x1B) {
        m_ControlData.push_back('\\');
        m_ControlData.push_back('E');
    } else {
        m_ControlData.push_back(*ch);
    }
}

void TermDataHandlerImpl::HandleCap(bool check_unknown, char c) {
    CapNameMapValue cap_tuple;
    (void)c;

    auto result = m_State->get_cap(m_ParseContext->params, cap_tuple);

    if (result) {
        bool inc_param = std::get<1>(cap_tuple);

        if (inc_param) {
            for(auto & p : m_ParseContext->params) {
                if (p.has_int_value && p.int_value > 0)
                    p.int_value--;
            }
        }

        handle_cap(m_DataContext,
                   std::get<0>(cap_tuple),
                   m_ParseContext->params);

        if (m_CapStateStack.size() > 0) {
            std::tie(m_State,
                     m_ParseContext->params,
                     m_ControlData) = m_CapStateStack.front();
            m_CapStateStack.pop_front();
        } else {
            m_State = m_Cap->control_data_start_state;
            m_ParseContext->params.clear();
            m_ControlData.clear();
        }
    } else if (check_unknown && m_ControlData.size() > 0) {
        m_CapStateStack.push_front(std::make_tuple(m_State,
                                                   m_ParseContext->params,
                                                   m_ControlData));

        m_State = m_Cap->control_data_start_state;
        m_ParseContext->params.clear();
        m_ControlData.clear();
    }
}
<|endoftext|>