<commit_before>#define CATCH_CONFIG_MAIN

#include "include/buildsys.h"
#include "interface/luainterface.h"

#include <catch2/catch.hpp>

using namespace buildsys;

class TopLevelTestsFixture
{
protected:
	std::string cwd{"lua_test_dir"};

public:
	TopLevelTestsFixture()
	{
		filesystem::create_directories(this->cwd);
	}
	~TopLevelTestsFixture()
	{
		filesystem::remove_all(this->cwd);
	}
};

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'name' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	// Call the name() function and check the result
	test_file << "assert(name() == 'test_namespace')";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'name' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	// Call the name() function with more than zero arguments and
	// check that it fails.
	test_file << "assert(name('blah') == 'test_namespace')";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(exception_caught);
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'keepstaging' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "keepstaging()";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.getSuppressRemoveStaging());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	// Should now be true
	REQUIRE(p.getSuppressRemoveStaging());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'keepstaging' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "keepstaging(true)";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.getSuppressRemoveStaging());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(exception_caught);
	// Should still be false
	REQUIRE(!p.getSuppressRemoveStaging());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'intercept' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "intercept()";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.getIntercept());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	// Should now be true
	REQUIRE(p.getIntercept());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'intercept' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "intercept(true)";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.getIntercept());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(exception_caught);
	// Should still be false
	REQUIRE(!p.getIntercept());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'hashoutput' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "hashoutput()";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.isHashingOutput());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	// Should now be true
	REQUIRE(p.isHashingOutput());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'hashoutput' function usage", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "hashoutput(true)";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.isHashingOutput());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(exception_caught);
	// Should still be false
	REQUIRE(!p.isHashingOutput());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'builddir' function usage (no parameter)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	// Call 'builddir()' and then test we can call a related builddir
	// function/variable that should now be available.
	test_file << "bd = builddir()\n";
	test_file << "test = bd.path";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.get_clean_before_build());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	// Should still be false
	REQUIRE(!p.get_clean_before_build());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'builddir' function usage (one boolean parameter)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	// Call 'builddir()' and then test we can call a related builddir
	// function/variable that should now be available.
	test_file << "bd = builddir(true)\n";
	test_file << "test = bd.path";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	// Should default to false
	REQUIRE(!p.get_clean_before_build());

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	// Should now be true
	REQUIRE(p.get_clean_before_build());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'builddir' function usage (two boolean parameters)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	// Call 'builddir()' and then test we can call a related builddir
	// function/variable that should now be available.
	test_file << "bd = builddir(true, true)\n";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(exception_caught);
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'builddir' function usage (single string parameter)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	// Call 'builddir()' and then test we can call a related builddir
	// function/variable that should now be available.
	test_file << "bd = builddir('test')\n";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(exception_caught);
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (get package prefixed feature)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "assert(feature('test_feature1') == 'value1')";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);
	li_get_feature_map()->setFeature("test_package:test_feature1", "value1", true);
	li_get_feature_map()->setFeature("test_feature1", "value2", true);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);

	std::stringstream buffer;
	p.buildDescription()->print(buffer);
	REQUIRE(buffer.str() == "FeatureValue test_feature1 value1\n");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (get non package prefixed feature)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "assert(feature('test_feature2') == 'value3')";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);
	li_get_feature_map()->setFeature("test_feature2", "value3", true);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	std::stringstream buffer;
	p.buildDescription()->print(buffer);
	REQUIRE(buffer.str() == "FeatureValue test_feature2 value3\n");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (get non existent feature)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "assert(feature('test_feature3') == nil)";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	std::stringstream buffer;
	p.buildDescription()->print(buffer);
	REQUIRE(buffer.str() == "FeatureNil test_feature3\n");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (set non existent feature)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "feature('test_feature4', 'value4')";
	test_file.close();

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	REQUIRE(li_get_feature_map()->getFeature("test_feature4") == "value4");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (set existent feature)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "feature('test_feature5', 'value5')";
	test_file.close();

	li_get_feature_map()->setFeature("test_feature5", "value10", true);

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	REQUIRE(li_get_feature_map()->getFeature("test_feature5") == "value10");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (force set existent feature)", "")
{
	std::string file_path = this->cwd + "/test_lua.lua";
	std::ofstream test_file;
	test_file.open(file_path);

	test_file << "feature('test_feature6', 'value6', true)";
	test_file.close();

	li_get_feature_map()->setFeature("test_feature6", "value12", true);

	NameSpace *ns = NameSpace::findNameSpace("test_namespace");
	Package p(ns, "test_package", file_path, file_path);

	Lua lua;
	interfaceSetup(&lua);
	li_set_package(&p);

	bool exception_caught = false;
	try {
		lua.processFile(file_path);
	} catch(CustomException &e) {
		exception_caught = true;
	}

	REQUIRE(!exception_caught);
	REQUIRE(li_get_feature_map()->getFeature("test_feature6") == "value6");
}
<commit_msg>interface/toplevel: Refactor to remove duplication from unit tests<commit_after>#define CATCH_CONFIG_MAIN

#include "include/buildsys.h"
#include "interface/luainterface.h"

#include <catch2/catch.hpp>

using namespace buildsys;

class TopLevelTestsFixture
{
protected:
	std::string cwd{"lua_test_dir"};
	NameSpace *ns{nullptr};

public:
	TopLevelTestsFixture()
	{
		filesystem::create_directories(this->cwd);
		this->ns = NameSpace::findNameSpace("test_namespace");
	}
	~TopLevelTestsFixture()
	{
		filesystem::remove_all(this->cwd);
	}
	/**
	 * Execute some lua code for a test package and namespace.
	 *
	 * @param p - The package to execute for.
	 * @param lua_code - The code to execute.
	 * @returns true if the code executes successfully, false if an exception occurs.
	 */
	bool execute_lua(Package &p, const std::string &lua_code)
	{
		std::string file_path = this->cwd + "/test_lua.lua";
		std::ofstream test_file;
		test_file.open(file_path);

		test_file << lua_code;
		test_file.close();

		Lua lua;
		interfaceSetup(&lua);
		li_set_package(&p);

		bool exception_caught = false;
		try {
			lua.processFile(file_path);
		} catch(CustomException &e) {
			exception_caught = true;
		}

		return !exception_caught;
	}
};

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'name' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Call the name() function and check the result
	REQUIRE(execute_lua(p, "assert(name() == 'test_namespace')"));
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'name' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Call the name() function with more than zero arguments and
	// check that it fails.
	REQUIRE(!execute_lua(p, "assert(name('blah') == 'test_namespace')"));
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'keepstaging' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.getSuppressRemoveStaging());

	REQUIRE(execute_lua(p, "keepstaging()"));

	// Should now be true
	REQUIRE(p.getSuppressRemoveStaging());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'keepstaging' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.getSuppressRemoveStaging());

	REQUIRE(!execute_lua(p, "keepstaging(true)"));

	// Should still be false
	REQUIRE(!p.getSuppressRemoveStaging());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'intercept' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.getIntercept());

	REQUIRE(execute_lua(p, "intercept()"));

	// Should now be true
	REQUIRE(p.getIntercept());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'intercept' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.getIntercept());

	REQUIRE(!execute_lua(p, "intercept(true)"));

	// Should still be false
	REQUIRE(!p.getIntercept());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'hashoutput' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.isHashingOutput());

	REQUIRE(execute_lua(p, "hashoutput()"));

	// Should now be true
	REQUIRE(p.isHashingOutput());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'hashoutput' function usage", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.isHashingOutput());

	REQUIRE(!execute_lua(p, "hashoutput(true)"));

	// Should still be false
	REQUIRE(!p.isHashingOutput());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'builddir' function usage (no parameter)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.get_clean_before_build());

	// Call 'builddir()' and then test we can call a related builddir
	// function/variable that should now be available.
	REQUIRE(execute_lua(p, "bd = builddir()\ntest = bd.path"));

	// Should still be false
	REQUIRE(!p.get_clean_before_build());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'builddir' function usage (one boolean parameter)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	// Should default to false
	REQUIRE(!p.get_clean_before_build());

	// Call 'builddir()' and then test we can call a related builddir
	// function/variable that should now be available.
	REQUIRE(execute_lua(p, "bd = builddir(true)\ntest = bd.path"));

	// Should now be true
	REQUIRE(p.get_clean_before_build());
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'builddir' function usage (two boolean parameters)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	REQUIRE(!execute_lua(p, "bd = builddir(true, true)"));
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test invalid 'builddir' function usage (single string parameter)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	REQUIRE(!execute_lua(p, "bd = builddir('test')"));
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (get package prefixed feature)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	li_get_feature_map()->setFeature("test_package:test_feature1", "value1", true);
	li_get_feature_map()->setFeature("test_feature1", "value2", true);

	REQUIRE(execute_lua(p, "assert(feature('test_feature1') == 'value1')"));

	std::stringstream buffer;
	p.buildDescription()->print(buffer);
	REQUIRE(buffer.str() == "FeatureValue test_feature1 value1\n");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (get non package prefixed feature)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	li_get_feature_map()->setFeature("test_feature2", "value3", true);

	REQUIRE(execute_lua(p, "assert(feature('test_feature2') == 'value3')"));

	std::stringstream buffer;
	p.buildDescription()->print(buffer);
	REQUIRE(buffer.str() == "FeatureValue test_feature2 value3\n");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (get non existent feature)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	REQUIRE(execute_lua(p, "assert(feature('test_feature3') == nil)"));

	std::stringstream buffer;
	p.buildDescription()->print(buffer);
	REQUIRE(buffer.str() == "FeatureNil test_feature3\n");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (set non existent feature)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	REQUIRE(execute_lua(p, "feature('test_feature4', 'value4')"));
	REQUIRE(li_get_feature_map()->getFeature("test_feature4") == "value4");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (set existent feature)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	li_get_feature_map()->setFeature("test_feature5", "value10", true);
	REQUIRE(execute_lua(p, "feature('test_feature5', 'value5')"));
	REQUIRE(li_get_feature_map()->getFeature("test_feature5") == "value10");
}

TEST_CASE_METHOD(TopLevelTestsFixture, "Test valid 'feature' function usage (force set existent feature)", "")
{
	Package p(this->ns, "test_package", ".", ".");

	li_get_feature_map()->setFeature("test_feature6", "value12", true);
	REQUIRE(execute_lua(p, "feature('test_feature6', 'value6', true)"));
	REQUIRE(li_get_feature_map()->getFeature("test_feature6") == "value6");
}
<|endoftext|>


<commit_before>/**
 *  Argument.cpp
 *
 *  Implementation for the Argument class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  type        Argument type
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument
 */
Argument::Argument(const char *name, Type type, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)(type == Type::Array || type == Type::Callable ? type : Type::Null);
#endif
    _info->class_name = NULL;
    _info->class_name_len = 0;
    _info->allow_null = false;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  classname   Name of the class
 *  @param  nullable    Can it be null?
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument?
 */
Argument::Argument(const char *name, const char *classname, bool nullable, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)Type::Object;
#endif
    _info->class_name = classname;
    _info->class_name_len = strlen(classname);
    _info->allow_null = nullable;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Copy constructor
 *  @param  argument
 */
Argument::Argument(const Argument &argument)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    *_info = *argument._info;

    // store if required
    _required = argument._required;
}

/**
 *  Move constructor
 *  @param  argument
 */
Argument::Argument(Argument &&argument)
{
    // copy memory pointer
    _info = argument._info;

    // forget in other object
    argument._info = nullptr;
}

/**
 *  Destructor
 */
Argument::~Argument()
{
    if (_info) delete _info;
}

/**
 *  Fill an arg_info structure with data
 *  @param  info
 *  @internal
 */
void Argument::fill(struct _zend_arg_info *info) const
{
    // copy all data
    *info = *_info;
}

/**
 *  End of namespace
 */
}
<commit_msg>fixed initialization of forgotten structure fields<commit_after>/**
 *  Argument.cpp
 *
 *  Implementation for the Argument class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  type        Argument type
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument
 */
Argument::Argument(const char *name, Type type, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)(type == Type::Array || type == Type::Callable ? type : Type::Null);
#else
    _info->array_type_hint = type == Type::Array;
#endif
    _info->class_name = NULL;
    _info->class_name_len = 0;
    _info->allow_null = false;
    _info->pass_by_reference = byref;
    _info->return_reference = false;
    _info->required_num_args = 0;   // @todo is this correct?

    // store if required
    _required = required;
}

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  classname   Name of the class
 *  @param  nullable    Can it be null?
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument?
 */
Argument::Argument(const char *name, const char *classname, bool nullable, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)Type::Object;
#endif
    _info->class_name = classname;
    _info->class_name_len = strlen(classname);
    _info->allow_null = nullable;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Copy constructor
 *  @param  argument
 */
Argument::Argument(const Argument &argument)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    *_info = *argument._info;

    // store if required
    _required = argument._required;
}

/**
 *  Move constructor
 *  @param  argument
 */
Argument::Argument(Argument &&argument)
{
    // copy memory pointer
    _info = argument._info;

    // forget in other object
    argument._info = nullptr;
}

/**
 *  Destructor
 */
Argument::~Argument()
{
    if (_info) delete _info;
}

/**
 *  Fill an arg_info structure with data
 *  @param  info
 *  @internal
 */
void Argument::fill(struct _zend_arg_info *info) const
{
    // copy all data
    *info = *_info;
}

/**
 *  End of namespace
 */
}
<|endoftext|>


<commit_before>#include "basic_es.h"
#include "objective_function.h"
#include "population.h"
#include "atom.h"
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <set>
#include <algorithm>

using revolution::BasicEs;
using revolution::ObjectiveFunction;

/*--------------------------------------------------------------------------*/
namespace
{

const double PI = 3.14159265;

double normal_dist_num()
{
	static bool cache = false;
	static double cached = 0;

	if (cache)
	{
		cache = false;
		return cached;
	}

	double U = rand() / (1.0 * RAND_MAX);
	double V = rand() / (1.0 * RAND_MAX);
	double X = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V);
	double Y = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V);

	cache = true;
	cached = Y;
	return X;
}//~ normal_dist_num

/*--------------------------------------------------------------------------*/
class Atom : private revolution::Atom
{
public:
	explicit Atom(int n, int m)
		: revolution::Atom(n, m), strParams(n, 1.0)
	{

	}

	using revolution::Atom::operator[];
	using revolution::Atom::f;
	using revolution::Atom::dim;
	using revolution::Atom::obj;
	using revolution::Atom::initialize;
	using revolution::Atom::eval;

	double strategyParam(int index) const
	{
		return strParams.at(index);
	}

	void setStrategyParam(int index, double value)
	{
		strParams[index] = value;
	}

	void swap(Atom& rhs)
	{
		revolution::Atom::swap(rhs);
		strParams.swap(rhs.strParams);
	}

private:
	std::vector<double> strParams; // endogenous strategy params
};//~Atom for BasicEs

/*--------------------------------------------------------------------------*/
class Population : private revolution::Population<Atom>
{
public:
	Population(int mu, int lambda, int dim, int obj)
			: revolution::Population<Atom>(mu, lambda, dim, obj)
	{

	}

	using revolution::Population<Atom>::initialize;
	using revolution::Population<Atom>::mem_ref;
};//~ BasicEs::Population

/*--------------------------------------------------------------------------*/
void gen_random_indices(int max, std::set<int>& indices)
{
	while (indices.size() != max)
	{
		indices.insert(rand() % max);
	}
}

/*--------------------------------------------------------------------------*/
class Recombination
{
public:
	Recombination(int r, int dim) : rho(r), n(dim) {}

	void apply(const std::vector<Atom *>& p, Atom& temp) const// intermediate recombination (for the moment)
	{
		std::set<int> random_indices;
		gen_random_indices(rho, random_indices);
		for (int varIndex = 0; varIndex != n; ++varIndex)
		{
			double paramSum = 0.0;
			double strategySum = 0.0;
			Atom *atom = 0;
			for (std::set<int>::const_iterator i = random_indices.begin();
				i != random_indices.end(); ++i)
			{
				atom = p[*i];
				paramSum += atom->operator[](varIndex);
				strategySum += atom->strategyParam(varIndex);
			}
			paramSum /= rho;
			strategySum /= rho;
			temp[varIndex] = paramSum;
			temp.setStrategyParam(varIndex, strategySum);
		}
	}

private:
	const int rho;
	const int n;

};//~ Recombination

/*--------------------------------------------------------------------------*/
class Mutation
{
public:
	void apply(Atom& temp) const
	{
		static const int n = temp.dim();
		static const double t0= 1.0/(2.0 * sqrt(1.0*n));
		static const double t = 1.0/(sqrt(2.0 * sqrt(1.0*n)));

		double m0 = exp(t0 * normal_dist_num());
		double mi = 0;
		for (int varIndex = 0; varIndex != n; ++varIndex)
		{
			mi = temp.strategyParam(varIndex);
			mi *= exp(t*normal_dist_num());
			mi *= m0;
			temp.setStrategyParam(varIndex, mi);
			temp[varIndex] += mi * normal_dist_num();
		}
	}

};//~ Mutation

/*--------------------------------------------------------------------------*/
bool cmp_single_obj(const Atom* i, const Atom* j)
{
	return i->f(0) < j->f(0);
}

/*--------------------------------------------------------------------------*/
class Selection
{
public:
	explicit Selection(RVSelectionMode md)
		: mode(md) {}

	void apply(std::vector<Atom *>& pop, int mu, int lambda) const
	{
		if (mode == kRVSelectionModePlus)
		{
			std::partial_sort(
				pop.begin(), pop.begin()+mu, pop.end(), cmp_single_obj);
		} else if (mode == kRVSelectionModeComma)
		{
			abort();
		}
	}

private:
	RVSelectionMode mode;
};//~ Selection

}//~ unamed

/*--------------------------------------------------------------------------*/
class BasicEs::BasicEsPriv : private ::Population
{
public:
	BasicEsPriv(int m, int r, int l, RVSelectionMode mode, ObjectiveFunction *objf)
		:
		  ::Population(m, l, objf->dim(), objf->objectives()),
		  recombination(r, objf->dim()),
		  mutation(),
		  selection(mode),
		  objectiveFunction(objf),
		  mu(m), lambda(l),
		  temp(objf->dim(), objf->objectives()),
		  onGenFinished(0),
		  onGenFinishedData(0),
		  wrapperObj(0)
	{
		set_ref();
	}

	void setPopulationInitialValues(RVPopulationSetInitialValues fun, void *data)
	{
		initialize(fun, data);
	}

	void setOnGenerationFinished(RVGenerationFinished fun, void *data)
	{
		onGenFinished = fun;
		onGenFinishedData = data;
	}

	void start()
	{
		const int MAX_GEN = 100;
		for (int i = 0; i < MAX_GEN; ++i)
		{
			doEvolutionStep();
			if (onGenFinished) onGenFinished(wrapperObj, i+1, onGenFinishedData);
		}
	}

	double getDesignParameter(int parent, int paramIndex) const
	{
		return atom_ref[parent]->operator[](paramIndex);
	}

	void doEvolutionStep()
	{
		for (int i = 0; i < lambda; ++i)
		{
			recombination.apply(atom_ref, temp);
			mutation.apply(temp);
			temp.eval(*objectiveFunction);
			atom_ref[mu+i]->swap(temp);
		}
		selection.apply(atom_ref, mu, lambda);
	}

	double getObjective(int parent, int objIndex) const
	{
		return atom_ref[parent]->f(objIndex);
	}

	void setWrapperObject(RVBasicEvolutionStrategy *obj)
	{
		wrapperObj = obj;
	}

	void set_ref()
	{
		atom_ref = mem_ref();
	}

	::Atom temp;
	std::vector< ::Atom *> atom_ref;
	const ::Recombination recombination;
	const ::Selection selection;
	const ::Mutation mutation;
	ObjectiveFunction *objectiveFunction;
	const int mu;
	const int lambda;
	RVGenerationFinished onGenFinished;
	void *onGenFinishedData;
	RVBasicEvolutionStrategy *wrapperObj;
};//~BasicEs::BasicEsPriv

/*---------------------------------------------------------------------------*/
BasicEs::BasicEs(int m, int r, int la, RVSelectionMode sel, ObjectiveFunction *objf)
	: impl(new BasicEs::BasicEsPriv(m, r, la, sel, objf))
{

}

/*---------------------------------------------------------------------------*/
BasicEs::~BasicEs()
{
	delete impl;
	impl = 0;
}

/*--------------------------------------------------------------------------*/
void BasicEs::setPopulationInitialValues(RVPopulationSetInitialValues fun, void *data)
{
	impl->setPopulationInitialValues(fun, data);
}

/*--------------------------------------------------------------------------*/
void BasicEs::start()
{
	impl->start();
}

/*--------------------------------------------------------------------------*/
void BasicEs::setOnGenerationFinished(RVGenerationFinished fun, void *data)
{
	impl->setOnGenerationFinished(fun, data);
}

/*--------------------------------------------------------------------------*/
double BasicEs::getDesignParameter(int parent, int paramIndex) const
{
	return impl->getDesignParameter(parent, paramIndex);
}

/*--------------------------------------------------------------------------*/
double BasicEs::getObjective(int parent, int objIndex) const
{
	return impl->getObjective(parent, objIndex);
}

/*--------------------------------------------------------------------------*/
void BasicEs::setWrapperObject(RVBasicEvolutionStrategy *obj)
{
	impl->setWrapperObject(obj);
}

/*--------------------------------------------------------------------------*/
BasicEs* BasicEs::create(int mu, int rho, int lambda,RVSelectionMode mode, ObjectiveFunction *objf)
{
	bool invalidPopulation = mu < 0 || lambda < 0;
	bool invalidRecombinationConstant = rho < 0 || rho > mu;
	bool invalidSelectionMode = mode == kRVSelectionModeComma ? (lambda >= mu ? false : true) : false;

	if (invalidPopulation || invalidRecombinationConstant || invalidSelectionMode)
	{
		return 0;
	}
	return new BasicEs(mu, rho, lambda, mode, objf);
}
<commit_msg>comma operator<commit_after>#include "basic_es.h"
#include "objective_function.h"
#include "population.h"
#include "atom.h"
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <set>
#include <algorithm>

using revolution::BasicEs;
using revolution::ObjectiveFunction;

/*--------------------------------------------------------------------------*/
namespace
{

const double PI = 3.14159265;

double normal_dist_num()
{
	static bool cache = false;
	static double cached = 0;

	if (cache)
	{
		cache = false;
		return cached;
	}

	double U = rand() / (1.0 * RAND_MAX);
	double V = rand() / (1.0 * RAND_MAX);
	double X = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V);
	double Y = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V);

	cache = true;
	cached = Y;
	return X;
}//~ normal_dist_num

/*--------------------------------------------------------------------------*/
class Atom : private revolution::Atom
{
public:
	explicit Atom(int n, int m)
		: revolution::Atom(n, m), strParams(n, 1.0)
	{

	}

	using revolution::Atom::operator[];
	using revolution::Atom::f;
	using revolution::Atom::dim;
	using revolution::Atom::obj;
	using revolution::Atom::initialize;
	using revolution::Atom::eval;

	double strategyParam(int index) const
	{
		return strParams.at(index);
	}

	void setStrategyParam(int index, double value)
	{
		strParams[index] = value;
	}

	void swap(Atom& rhs)
	{
		revolution::Atom::swap(rhs);
		strParams.swap(rhs.strParams);
	}

private:
	std::vector<double> strParams; // endogenous strategy params
};//~Atom for BasicEs

/*--------------------------------------------------------------------------*/
class Population : private revolution::Population<Atom>
{
public:
	Population(int mu, int lambda, int dim, int obj)
			: revolution::Population<Atom>(mu, lambda, dim, obj)
	{

	}

	using revolution::Population<Atom>::initialize;
	using revolution::Population<Atom>::mem_ref;
};//~ BasicEs::Population

/*--------------------------------------------------------------------------*/
void gen_random_indices(int max, std::set<int>& indices)
{
	while (indices.size() != max)
	{
		indices.insert(rand() % max);
	}
}

/*--------------------------------------------------------------------------*/
class Recombination
{
public:
	Recombination(int r, int dim) : rho(r), n(dim) {}

	void apply(const std::vector<Atom *>& p, Atom& temp) const// intermediate recombination (for the moment)
	{
		std::set<int> random_indices;
		gen_random_indices(rho, random_indices);
		for (int varIndex = 0; varIndex != n; ++varIndex)
		{
			double paramSum = 0.0;
			double strategySum = 0.0;
			Atom *atom = 0;
			for (std::set<int>::const_iterator i = random_indices.begin();
				i != random_indices.end(); ++i)
			{
				atom = p[*i];
				paramSum += atom->operator[](varIndex);
				strategySum += atom->strategyParam(varIndex);
			}
			paramSum /= rho;
			strategySum /= rho;
			temp[varIndex] = paramSum;
			temp.setStrategyParam(varIndex, strategySum);
		}
	}

private:
	const int rho;
	const int n;

};//~ Recombination

/*--------------------------------------------------------------------------*/
class Mutation
{
public:
	void apply(Atom& temp) const
	{
		static const int n = temp.dim();
		static const double t0= 1.0/(2.0 * sqrt(1.0*n));
		static const double t = 1.0/(sqrt(2.0 * sqrt(1.0*n)));

		double m0 = exp(t0 * normal_dist_num());
		double mi = 0;
		for (int varIndex = 0; varIndex != n; ++varIndex)
		{
			mi = temp.strategyParam(varIndex);
			mi *= exp(t*normal_dist_num());
			mi *= m0;
			temp.setStrategyParam(varIndex, mi);
			temp[varIndex] += mi * normal_dist_num();
		}
	}

};//~ Mutation

/*--------------------------------------------------------------------------*/
bool cmp_single_obj(const Atom* i, const Atom* j)
{
	return i->f(0) < j->f(0);
}

/*--------------------------------------------------------------------------*/
class Selection
{
public:
	explicit Selection(RVSelectionMode md)
		: mode(md) {}

	void apply(std::vector<Atom *>& pop, int mu, int lambda) const
	{
		if (mode == kRVSelectionModePlus)
		{
			std::partial_sort(
				pop.begin(), pop.begin()+mu, pop.end(), cmp_single_obj);
		} else if (mode == kRVSelectionModeComma)
		{
            std::partial_sort(pop.begin()+mu, pop.begin()+mu+mu, pop.end(), cmp_single_obj);
            for (std::vector<Atom *>::size_type sz = mu, i = 0;
                sz != 2*mu; ++sz, ++i)
            {
                std::swap(pop[i], pop[sz]);
            }
		}
	}

private:
	RVSelectionMode mode;
};//~ Selection

}//~ unamed

/*--------------------------------------------------------------------------*/
class BasicEs::BasicEsPriv : private ::Population
{
public:
	BasicEsPriv(int m, int r, int l, RVSelectionMode mode, ObjectiveFunction *objf)
		:
		  ::Population(m, l, objf->dim(), objf->objectives()),
		  recombination(r, objf->dim()),
		  mutation(),
		  selection(mode),
		  objectiveFunction(objf),
		  mu(m), lambda(l),
		  temp(objf->dim(), objf->objectives()),
		  onGenFinished(0),
		  onGenFinishedData(0),
		  wrapperObj(0)
	{
		set_ref();
	}

	void setPopulationInitialValues(RVPopulationSetInitialValues fun, void *data)
	{
		initialize(fun, data);
	}

	void setOnGenerationFinished(RVGenerationFinished fun, void *data)
	{
		onGenFinished = fun;
		onGenFinishedData = data;
	}

	void start()
	{
		const int MAX_GEN = 1000;
		for (int i = 0; i < MAX_GEN; ++i)
		{
			doEvolutionStep();
			if (onGenFinished) onGenFinished(wrapperObj, i+1, onGenFinishedData);
		}
	}

	double getDesignParameter(int parent, int paramIndex) const
	{
		return atom_ref[parent]->operator[](paramIndex);
	}

	void doEvolutionStep()
	{
		for (int i = 0; i < lambda; ++i)
		{
			recombination.apply(atom_ref, temp);
			mutation.apply(temp);
			temp.eval(*objectiveFunction);
			atom_ref[mu+i]->swap(temp);
		}
		selection.apply(atom_ref, mu, lambda);
	}

	double getObjective(int parent, int objIndex) const
	{
		return atom_ref[parent]->f(objIndex);
	}

	void setWrapperObject(RVBasicEvolutionStrategy *obj)
	{
		wrapperObj = obj;
	}

	void set_ref()
	{
		atom_ref = mem_ref();
	}

	::Atom temp;
	std::vector< ::Atom *> atom_ref;
	const ::Recombination recombination;
	const ::Selection selection;
	const ::Mutation mutation;
	ObjectiveFunction *objectiveFunction;
	const int mu;
	const int lambda;
	RVGenerationFinished onGenFinished;
	void *onGenFinishedData;
	RVBasicEvolutionStrategy *wrapperObj;
};//~BasicEs::BasicEsPriv

/*---------------------------------------------------------------------------*/
BasicEs::BasicEs(int m, int r, int la, RVSelectionMode sel, ObjectiveFunction *objf)
	: impl(new BasicEs::BasicEsPriv(m, r, la, sel, objf))
{

}

/*---------------------------------------------------------------------------*/
BasicEs::~BasicEs()
{
	delete impl;
	impl = 0;
}

/*--------------------------------------------------------------------------*/
void BasicEs::setPopulationInitialValues(RVPopulationSetInitialValues fun, void *data)
{
	impl->setPopulationInitialValues(fun, data);
}

/*--------------------------------------------------------------------------*/
void BasicEs::start()
{
	impl->start();
}

/*--------------------------------------------------------------------------*/
void BasicEs::setOnGenerationFinished(RVGenerationFinished fun, void *data)
{
	impl->setOnGenerationFinished(fun, data);
}

/*--------------------------------------------------------------------------*/
double BasicEs::getDesignParameter(int parent, int paramIndex) const
{
	return impl->getDesignParameter(parent, paramIndex);
}

/*--------------------------------------------------------------------------*/
double BasicEs::getObjective(int parent, int objIndex) const
{
	return impl->getObjective(parent, objIndex);
}

/*--------------------------------------------------------------------------*/
void BasicEs::setWrapperObject(RVBasicEvolutionStrategy *obj)
{
	impl->setWrapperObject(obj);
}

/*--------------------------------------------------------------------------*/
BasicEs* BasicEs::create(int mu, int rho, int lambda,RVSelectionMode mode, ObjectiveFunction *objf)
{
	bool invalidPopulation = mu < 0 || lambda < 0;
	bool invalidRecombinationConstant = rho < 0 || rho > mu;
	bool invalidSelectionMode = mode == kRVSelectionModeComma ? (lambda >= mu ? false : true) : false;

	if (invalidPopulation || invalidRecombinationConstant || invalidSelectionMode)
	{
		return 0;
	}
	return new BasicEs(mu, rho, lambda, mode, objf);
}
<|endoftext|>


<commit_before>/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <string.h>
#include <strings.h>
#include <stdio.h>

#include "MeshGroup.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
#include "utils/string.h"

#include "settings/SettingRegistry.h" // loadExtruderJSONsettings

namespace cura
{

FILE* binaryMeshBlob = nullptr;

/* Custom fgets function to support Mac line-ends in Ascii STL files. OpenSCAD produces this when used on Mac */
void* fgets_(char* ptr, size_t len, FILE* f)
{
    while(len && fread(ptr, 1, 1, f) > 0)
    {
        if (*ptr == '\n' || *ptr == '\r')
        {
            *ptr = '\0';
            return ptr;
        }
        ptr++;
        len--;
    }
    return nullptr;
}

MeshGroup::MeshGroup(SettingsBaseVirtual* settings_base)
: SettingsBase(settings_base)
, extruder_count(-1)
{}

MeshGroup::~MeshGroup()
{
    for (unsigned int extruder = 0; extruder < MAX_EXTRUDERS; extruder++)
    {
        if (extruders[extruder])
        {
            delete extruders[extruder];
        }
    }
}

int MeshGroup::getExtruderCount()
{
    if (extruder_count == -1)
    {
        extruder_count = getSettingAsCount("machine_extruder_count");
    }
    return extruder_count;
}

ExtruderTrain* MeshGroup::createExtruderTrain(unsigned int extruder_nr)
{
    if (!extruders[extruder_nr])
    {
        extruders[extruder_nr] = new ExtruderTrain(this, extruder_nr);
        int err = SettingRegistry::getInstance()->loadExtruderJSONsettings(extruder_nr, extruders[extruder_nr]);
        if (err)
        {
            logError("Couldn't load extruder.def.json for extruder %i\n", extruder_nr);
            std::exit(1);
        }
    }
    return extruders[extruder_nr];
}

ExtruderTrain* MeshGroup::getExtruderTrain(unsigned int extruder_nr)
{
    assert(extruders[extruder_nr]);
    return extruders[extruder_nr];
}

const ExtruderTrain* MeshGroup::getExtruderTrain(unsigned int extruder_nr) const
{
    assert(extruders[extruder_nr]);
    return extruders[extruder_nr];
}

Point3 MeshGroup::min() const
{
    if (meshes.size() < 1)
    {
        return Point3(0, 0, 0);
    }
    Point3 ret = meshes[0].min();
    for(unsigned int i=1; i<meshes.size(); i++)
    {
        Point3 v = meshes[i].min();
        ret.x = std::min(ret.x, v.x);
        ret.y = std::min(ret.y, v.y);
        ret.z = std::min(ret.z, v.z);
    }
    return ret;
}

Point3 MeshGroup::max() const
{
    if (meshes.size() < 1)
    {
        return Point3(0, 0, 0);
    }
    Point3 ret = meshes[0].max();
    for(unsigned int i=1; i<meshes.size(); i++)
    {
        Point3 v = meshes[i].max();
        ret.x = std::max(ret.x, v.x);
        ret.y = std::max(ret.y, v.y);
        ret.z = std::max(ret.z, v.z);
    }
    return ret;
}

void MeshGroup::clear()
{
    for(Mesh& m : meshes)
    {
        m.clear();
    }
}

void MeshGroup::finalize()
{
    extruder_count = getSettingAsCount("machine_extruder_count");

    for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++)
    {
        createExtruderTrain(extruder_nr); // create it if it didn't exist yet

        if (getSettingAsIndex("adhesion_extruder_nr") == extruder_nr
            || (getSettingBoolean("support_enable") && getSettingAsIndex("support_infill_extruder_nr") == extruder_nr)
            || (getSettingBoolean("support_enable") && getSettingAsIndex("support_extruder_nr_layer_0") == extruder_nr)
            || (getSettingBoolean("support_enable") && getSettingBoolean("support_interface_enable") && getSettingAsIndex("support_interface_extruder_nr") == extruder_nr)
            )
        {
            getExtruderTrain(extruder_nr)->setIsUsed(true);
        }
    }

    for (const Mesh& mesh : meshes)
    {
        getExtruderTrain(mesh.getSettingAsIndex("extruder_nr"))->setIsUsed(true);
    }

    //If the machine settings have been supplied, offset the given position vertices to the center of vertices (0,0,0) is at the bed center.
    Point3 meshgroup_offset(0, 0, 0);
    if (!getSettingBoolean("machine_center_is_zero"))
    {
        meshgroup_offset.x = getSettingInMicrons("machine_width") / 2;
        meshgroup_offset.y = getSettingInMicrons("machine_depth") / 2;
    }

    // If a mesh position was given, put the mesh at this position in 3D space.
    for(Mesh& mesh : meshes)
    {
        Point3 mesh_offset(mesh.getSettingInMicrons("mesh_position_x"), mesh.getSettingInMicrons("mesh_position_y"), mesh.getSettingInMicrons("mesh_position_z"));
        if (mesh.getSettingBoolean("center_object"))
        {
            Point3 object_min = mesh.min();
            Point3 object_max = mesh.max();
            Point3 object_size = object_max - object_min;
            mesh_offset += Point3(-object_min.x - object_size.x / 2, -object_min.y - object_size.y / 2, -object_min.z);
        }
        mesh.offset(mesh_offset + meshgroup_offset);
    }
}

bool loadMeshSTL_ascii(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rt");
    char buffer[1024];
    FPoint3 vertex;
    int n = 0;
    Point3 v0(0,0,0), v1(0,0,0), v2(0,0,0);
    while(fgets_(buffer, sizeof(buffer), f))
    {
        if (sscanf(buffer, " vertex %f %f %f", &vertex.x, &vertex.y, &vertex.z) == 3)
        {
            n++;
            switch(n)
            {
            case 1:
                v0 = matrix.apply(vertex);
                break;
            case 2:
                v1 = matrix.apply(vertex);
                break;
            case 3:
                v2 = matrix.apply(vertex);
                mesh->addFace(v0, v1, v2);
                n = 0;
                break;
            }
        }
    }
    fclose(f);
    mesh->finish();
    return true;
}

bool loadMeshSTL_binary(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rb");

    fseek(f, 0L, SEEK_END);
    long long file_size = ftell(f); //The file size is the position of the cursor after seeking to the end.
    rewind(f); //Seek back to start.
    size_t face_count = (file_size - 80 - sizeof(uint32_t)) / 50; //Subtract the size of the header. Every face uses exactly 50 bytes.

    char buffer[80];
    //Skip the header
    if (fread(buffer, 80, 1, f) != 1)
    {
        fclose(f);
        return false;
    }

    uint32_t reported_face_count;
    //Read the face count. We'll use it as a sort of redundancy code to check for file corruption.
    if (fread(&reported_face_count, sizeof(uint32_t), 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    if (reported_face_count != face_count)
    {
        logWarning("Face count reported by file (%s) is not equal to actual face count (%s). File could be corrupt!\n", std::to_string(reported_face_count).c_str(), std::to_string(face_count).c_str());
    }

    //For each face read:
    //float(x,y,z) = normal, float(X,Y,Z)*3 = vertexes, uint16_t = flags
    // Every Face is 50 Bytes: Normal(3*float), Vertices(9*float), 2 Bytes Spacer
    mesh->faces.reserve(face_count);
    mesh->vertices.reserve(face_count);
    for (unsigned int i = 0; i < face_count; i++)
    {
        if (fread(buffer, 50, 1, f) != 1)
        {
            fclose(f);
            return false;
        }
        float *v= ((float*)buffer)+3;

        Point3 v0 = matrix.apply(FPoint3(v[0], v[1], v[2]));
        Point3 v1 = matrix.apply(FPoint3(v[3], v[4], v[5]));
        Point3 v2 = matrix.apply(FPoint3(v[6], v[7], v[8]));
        mesh->addFace(v0, v1, v2);
    }
    fclose(f);
    mesh->finish();
    return true;
}

bool loadMeshSTL(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "r");
    if (f == nullptr)
    {
        return false;
    }

    //Skip any whitespace at the beginning of the file.
    unsigned long long num_whitespace = 0; //Number of whitespace characters.
    unsigned char whitespace;
    if (fread(&whitespace, 1, 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    while(isspace(whitespace))
    {
        num_whitespace++;
        if (fread(&whitespace, 1, 1, f) != 1)
        {
            fclose(f);
            return false;
        }
    }
    fseek(f, num_whitespace, SEEK_SET); //Seek to the place after all whitespace (we may have just read too far).

    char buffer[6];
    if (fread(buffer, 5, 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    fclose(f);

    buffer[5] = '\0';
    if (stringcasecompare(buffer, "solid") == 0)
    {
        bool load_success = loadMeshSTL_ascii(mesh, filename, matrix);
        if (!load_success)
            return false;

        // This logic is used to handle the case where the file starts with
        // "solid" but is a binary file.
        if (mesh->faces.size() < 1)
        {
            mesh->clear();
            return loadMeshSTL_binary(mesh, filename, matrix);
        }
        return true;
    }
    return loadMeshSTL_binary(mesh, filename, matrix);
}

bool loadMeshIntoMeshGroup(MeshGroup* meshgroup, const char* filename, const FMatrix3x3& transformation, SettingsBaseVirtual* object_parent_settings)
{
    TimeKeeper load_timer;

    const char* ext = strrchr(filename, '.');
    if (ext && (strcmp(ext, ".stl") == 0 || strcmp(ext, ".STL") == 0))
    {
        Mesh mesh = object_parent_settings ? Mesh(object_parent_settings) : Mesh(meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
        if(loadMeshSTL(&mesh,filename,transformation)) //Load it! If successful...
        {
            meshgroup->meshes.push_back(mesh);
            log("loading '%s' took %.3f seconds\n",filename,load_timer.restart());
            return true;
        }
    }
    return false;
}

}//namespace cura
<commit_msg>fix: retrieve support_enable per mesh (CURA-2492)<commit_after>/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <string.h>
#include <strings.h>
#include <stdio.h>

#include "MeshGroup.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
#include "utils/string.h"

#include "settings/SettingRegistry.h" // loadExtruderJSONsettings

namespace cura
{

FILE* binaryMeshBlob = nullptr;

/* Custom fgets function to support Mac line-ends in Ascii STL files. OpenSCAD produces this when used on Mac */
void* fgets_(char* ptr, size_t len, FILE* f)
{
    while(len && fread(ptr, 1, 1, f) > 0)
    {
        if (*ptr == '\n' || *ptr == '\r')
        {
            *ptr = '\0';
            return ptr;
        }
        ptr++;
        len--;
    }
    return nullptr;
}

MeshGroup::MeshGroup(SettingsBaseVirtual* settings_base)
: SettingsBase(settings_base)
, extruder_count(-1)
{}

MeshGroup::~MeshGroup()
{
    for (unsigned int extruder = 0; extruder < MAX_EXTRUDERS; extruder++)
    {
        if (extruders[extruder])
        {
            delete extruders[extruder];
        }
    }
}

int MeshGroup::getExtruderCount()
{
    if (extruder_count == -1)
    {
        extruder_count = getSettingAsCount("machine_extruder_count");
    }
    return extruder_count;
}

ExtruderTrain* MeshGroup::createExtruderTrain(unsigned int extruder_nr)
{
    if (!extruders[extruder_nr])
    {
        extruders[extruder_nr] = new ExtruderTrain(this, extruder_nr);
        int err = SettingRegistry::getInstance()->loadExtruderJSONsettings(extruder_nr, extruders[extruder_nr]);
        if (err)
        {
            logError("Couldn't load extruder.def.json for extruder %i\n", extruder_nr);
            std::exit(1);
        }
    }
    return extruders[extruder_nr];
}

ExtruderTrain* MeshGroup::getExtruderTrain(unsigned int extruder_nr)
{
    assert(extruders[extruder_nr]);
    return extruders[extruder_nr];
}

const ExtruderTrain* MeshGroup::getExtruderTrain(unsigned int extruder_nr) const
{
    assert(extruders[extruder_nr]);
    return extruders[extruder_nr];
}

Point3 MeshGroup::min() const
{
    if (meshes.size() < 1)
    {
        return Point3(0, 0, 0);
    }
    Point3 ret = meshes[0].min();
    for(unsigned int i=1; i<meshes.size(); i++)
    {
        Point3 v = meshes[i].min();
        ret.x = std::min(ret.x, v.x);
        ret.y = std::min(ret.y, v.y);
        ret.z = std::min(ret.z, v.z);
    }
    return ret;
}

Point3 MeshGroup::max() const
{
    if (meshes.size() < 1)
    {
        return Point3(0, 0, 0);
    }
    Point3 ret = meshes[0].max();
    for(unsigned int i=1; i<meshes.size(); i++)
    {
        Point3 v = meshes[i].max();
        ret.x = std::max(ret.x, v.x);
        ret.y = std::max(ret.y, v.y);
        ret.z = std::max(ret.z, v.z);
    }
    return ret;
}

void MeshGroup::clear()
{
    for(Mesh& m : meshes)
    {
        m.clear();
    }
}

void MeshGroup::finalize()
{
    extruder_count = getSettingAsCount("machine_extruder_count");

    for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++)
    {
        createExtruderTrain(extruder_nr); // create it if it didn't exist yet

        if (getSettingAsIndex("adhesion_extruder_nr") == extruder_nr)
        {
            getExtruderTrain(extruder_nr)->setIsUsed(true);
            continue;
        }

        for (const Mesh& mesh : meshes)
        {
            if (mesh.getSettingBoolean("support_enable")
                && (
                    getSettingAsIndex("support_infill_extruder_nr") == extruder_nr
                    || getSettingAsIndex("support_extruder_nr_layer_0") == extruder_nr
                    || (getSettingBoolean("support_interface_enable") && getSettingAsIndex("support_interface_extruder_nr") == extruder_nr)
                    )
                )
            {
                getExtruderTrain(extruder_nr)->setIsUsed(true);
                break;
            }
        }
    }

    for (const Mesh& mesh : meshes)
    {
        getExtruderTrain(mesh.getSettingAsIndex("extruder_nr"))->setIsUsed(true);
    }

    //If the machine settings have been supplied, offset the given position vertices to the center of vertices (0,0,0) is at the bed center.
    Point3 meshgroup_offset(0, 0, 0);
    if (!getSettingBoolean("machine_center_is_zero"))
    {
        meshgroup_offset.x = getSettingInMicrons("machine_width") / 2;
        meshgroup_offset.y = getSettingInMicrons("machine_depth") / 2;
    }

    // If a mesh position was given, put the mesh at this position in 3D space.
    for(Mesh& mesh : meshes)
    {
        Point3 mesh_offset(mesh.getSettingInMicrons("mesh_position_x"), mesh.getSettingInMicrons("mesh_position_y"), mesh.getSettingInMicrons("mesh_position_z"));
        if (mesh.getSettingBoolean("center_object"))
        {
            Point3 object_min = mesh.min();
            Point3 object_max = mesh.max();
            Point3 object_size = object_max - object_min;
            mesh_offset += Point3(-object_min.x - object_size.x / 2, -object_min.y - object_size.y / 2, -object_min.z);
        }
        mesh.offset(mesh_offset + meshgroup_offset);
    }
}

bool loadMeshSTL_ascii(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rt");
    char buffer[1024];
    FPoint3 vertex;
    int n = 0;
    Point3 v0(0,0,0), v1(0,0,0), v2(0,0,0);
    while(fgets_(buffer, sizeof(buffer), f))
    {
        if (sscanf(buffer, " vertex %f %f %f", &vertex.x, &vertex.y, &vertex.z) == 3)
        {
            n++;
            switch(n)
            {
            case 1:
                v0 = matrix.apply(vertex);
                break;
            case 2:
                v1 = matrix.apply(vertex);
                break;
            case 3:
                v2 = matrix.apply(vertex);
                mesh->addFace(v0, v1, v2);
                n = 0;
                break;
            }
        }
    }
    fclose(f);
    mesh->finish();
    return true;
}

bool loadMeshSTL_binary(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "rb");

    fseek(f, 0L, SEEK_END);
    long long file_size = ftell(f); //The file size is the position of the cursor after seeking to the end.
    rewind(f); //Seek back to start.
    size_t face_count = (file_size - 80 - sizeof(uint32_t)) / 50; //Subtract the size of the header. Every face uses exactly 50 bytes.

    char buffer[80];
    //Skip the header
    if (fread(buffer, 80, 1, f) != 1)
    {
        fclose(f);
        return false;
    }

    uint32_t reported_face_count;
    //Read the face count. We'll use it as a sort of redundancy code to check for file corruption.
    if (fread(&reported_face_count, sizeof(uint32_t), 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    if (reported_face_count != face_count)
    {
        logWarning("Face count reported by file (%s) is not equal to actual face count (%s). File could be corrupt!\n", std::to_string(reported_face_count).c_str(), std::to_string(face_count).c_str());
    }

    //For each face read:
    //float(x,y,z) = normal, float(X,Y,Z)*3 = vertexes, uint16_t = flags
    // Every Face is 50 Bytes: Normal(3*float), Vertices(9*float), 2 Bytes Spacer
    mesh->faces.reserve(face_count);
    mesh->vertices.reserve(face_count);
    for (unsigned int i = 0; i < face_count; i++)
    {
        if (fread(buffer, 50, 1, f) != 1)
        {
            fclose(f);
            return false;
        }
        float *v= ((float*)buffer)+3;

        Point3 v0 = matrix.apply(FPoint3(v[0], v[1], v[2]));
        Point3 v1 = matrix.apply(FPoint3(v[3], v[4], v[5]));
        Point3 v2 = matrix.apply(FPoint3(v[6], v[7], v[8]));
        mesh->addFace(v0, v1, v2);
    }
    fclose(f);
    mesh->finish();
    return true;
}

bool loadMeshSTL(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
    FILE* f = fopen(filename, "r");
    if (f == nullptr)
    {
        return false;
    }

    //Skip any whitespace at the beginning of the file.
    unsigned long long num_whitespace = 0; //Number of whitespace characters.
    unsigned char whitespace;
    if (fread(&whitespace, 1, 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    while(isspace(whitespace))
    {
        num_whitespace++;
        if (fread(&whitespace, 1, 1, f) != 1)
        {
            fclose(f);
            return false;
        }
    }
    fseek(f, num_whitespace, SEEK_SET); //Seek to the place after all whitespace (we may have just read too far).

    char buffer[6];
    if (fread(buffer, 5, 1, f) != 1)
    {
        fclose(f);
        return false;
    }
    fclose(f);

    buffer[5] = '\0';
    if (stringcasecompare(buffer, "solid") == 0)
    {
        bool load_success = loadMeshSTL_ascii(mesh, filename, matrix);
        if (!load_success)
            return false;

        // This logic is used to handle the case where the file starts with
        // "solid" but is a binary file.
        if (mesh->faces.size() < 1)
        {
            mesh->clear();
            return loadMeshSTL_binary(mesh, filename, matrix);
        }
        return true;
    }
    return loadMeshSTL_binary(mesh, filename, matrix);
}

bool loadMeshIntoMeshGroup(MeshGroup* meshgroup, const char* filename, const FMatrix3x3& transformation, SettingsBaseVirtual* object_parent_settings)
{
    TimeKeeper load_timer;

    const char* ext = strrchr(filename, '.');
    if (ext && (strcmp(ext, ".stl") == 0 || strcmp(ext, ".STL") == 0))
    {
        Mesh mesh = object_parent_settings ? Mesh(object_parent_settings) : Mesh(meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
        if(loadMeshSTL(&mesh,filename,transformation)) //Load it! If successful...
        {
            meshgroup->meshes.push_back(mesh);
            log("loading '%s' took %.3f seconds\n",filename,load_timer.restart());
            return true;
        }
    }
    return false;
}

}//namespace cura
<|endoftext|>


<commit_before>class Solution {
public:
  bool isValid(string s) {
    stack<char> S;
    for (int i = 0; i < s.size(); ++i) {
      char ch = s[i];
      if (ch == ')' || ch == '}' || ch == ']') {
        if (!S.empty()) {
          char top = S.top();
          if (top == '(' && ch == ')' || top == '{' && ch == '}' || top == '[' && ch == ']') {
            S.pop();
          } else {
              return false;
          }
        } else {
          return false;
        }
      } else {
        S.push(ch);
      }
    }
    return S.empty();
  }
};<commit_msg>added solutions<commit_after>class Solution {
public:
    bool isValid(string s) {
        stack<char> symbolStack;

        for (int i = 0; i < s.length(); ++i) {
            char symbol = s[i];
            char topSymbol = ' ';
            if (!symbolStack.empty()) {
              topSymbol = symbolStack.top();
            }
            switch (symbol) {
              case '(':
              case '{':
              case '[':
                symbolStack.push(symbol);
                break;
              case ')':
              case '}':
              case ']':
                if (isMatch(topSymbol, symbol)) {
                  symbolStack.pop();
                } else {
                  return false;
                }
                break;
            }
        }

        return symbolStack.empty();
    }

    bool isMatch(char left, char right) {
      return left == '(' && right == ')' || left == '[' && right == ']'
        || left == '{' && right == '}';
    }
};<|endoftext|>


<commit_before>// Copyright (c) 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE source in the root of the Project.

#include <boost/python.hpp>
#include <boost/optional.hpp>

#include <nix.hpp>

#include <accessors.hpp>
#include <transmorgify.hpp>

//we want only the newest and freshest API
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <numpy/arrayobject.h>
#include <numpy/ndarrayobject.h>

#include <PyEntity.hpp>

#include <stdexcept>

namespace nixpy {

// Data

static nix::DataType pyDtypeToNixDtype(const PyArray_Descr *dtype)
{
    if (dtype == nullptr) {
        return nix::DataType::Nothing;
    }

    if (dtype->byteorder != '=' && dtype->byteorder != '|') {
        //TODO: Handle case where specified byteorder *is*
        //the native byteorder (via BOOST_BIG_ENDIAN macros)
        return nix::DataType::Nothing;
    }

    switch (dtype->kind) {

    case 'u':
        switch (dtype->elsize) {
        case 1: return nix::DataType::UInt8;
        case 2: return nix::DataType::UInt16;
        case 4: return nix::DataType::UInt32;
        case 8: return nix::DataType::UInt64;
        }
        break;

    case 'i':
        switch (dtype->elsize) {
        case 1: return nix::DataType::Int8;
        case 2: return nix::DataType::Int16;
        case 4: return nix::DataType::Int32;
        case 8: return nix::DataType::Int64;
        }
        break;

    case 'f':
        switch (dtype->elsize) {
        case 4: return nix::DataType::Float;
        case 8: return nix::DataType::Double;
        }
        break;

    case 'V':
        return nix::DataType::Opaque;
        //we are ignoring the size information here
        //since we only support NATIVE_OPAQUE in H5
        //maybe we should throw an exception instead
        break;

    default:
        break;
    }
    return nix::DataType::Nothing;
}

static std::string nixDtypeToPyDtypeStr(nix::DataType nix_dtype)
{
    switch (nix_dtype) {
    case nix::DataType::UInt8:  return "<u1";
    case nix::DataType::UInt16: return "<u2";
    case nix::DataType::UInt32: return "<u4";
    case nix::DataType::UInt64: return "<u8";
    case nix::DataType::Int8:   return "<i1";
    case nix::DataType::Int16:  return "<i2";
    case nix::DataType::Int32:  return "<i4";
    case nix::DataType::Int64:  return "<i8";
    case nix::DataType::Float:  return "<f4";
    case nix::DataType::Double: return "<f8";
    case nix::DataType::Opaque: return "|V1";
    default:                    return "";
    }
}

static nix::DataType arrayDescAsDtype(PyArrayObject *array) {
    nix::DataType nix_dtype = pyDtypeToNixDtype(PyArray_DESCR(array));

    if (nix_dtype == nix::DataType::Nothing) {
        throw std::invalid_argument("Unsupported dtype for data");
    }

    return nix_dtype;
}

static PyArrayObject *makeArray(PyObject *data, int requirements) {
    if (! PyArray_Check(data)) {
        throw std::invalid_argument("Data not a NumPy array");
    }

    PyArrayObject *array = reinterpret_cast<PyArrayObject *>(data);
    PyArray_Descr *descr = PyArray_DESCR(array);

    if (requirements & NPY_ARRAY_ALIGNED && descr->kind == 'V') {
       //workaround a strange behaviour of numpy 1.9 to return
       //is_aligned == FALSE for void datatypes with an alignment
       //requirement == 1
       if (descr->alignment == 1) {
          requirements &= ~NPY_ARRAY_ALIGNED;
       }
    }

     if (! PyArray_CHKFLAGS(array, requirements)) {
        throw std::invalid_argument("array does not meet requirements");
    }

     return array;
}

static nix::NDSize arrayShapeAsNDSize(PyArrayObject *array) {
    int array_rank = PyArray_NDIM(array);
    npy_intp *array_shape = PyArray_SHAPE(array);

    nix::NDSize data_shape(array_rank);
    for (int i = 0; i < array_rank; i++) {
        data_shape[i] = array_shape[i];
    }

    return data_shape;
}

static void arrayEnsureShapeAndCount(PyArrayObject *array,
                                     nix::NDSize    &count,
                                     nix::NDSize    &offset) {

    if (! count) {
        count = arrayShapeAsNDSize(array);
    }

    if (! offset) {
        offset = nix::NDSize(count.size(), 0);
    }
}

static void readData(nix::DataSet& da, PyObject *data, nix::NDSize count, nix::NDSize offset) {

    PyArrayObject *array = makeArray(data, NPY_ARRAY_CARRAY);

    nix::DataType nix_dtype = arrayDescAsDtype(array);

    arrayEnsureShapeAndCount(array, count, offset);
    da.getData(nix_dtype, PyArray_DATA(array), count, offset);
}

static void writeData(nix::DataSet& da, PyObject *data, nix::NDSize count, nix::NDSize offset) {

    PyArrayObject *array = makeArray(data, NPY_ARRAY_CARRAY_RO);

    nix::DataType nix_dtype = arrayDescAsDtype(array);

    arrayEnsureShapeAndCount(array, count, offset);
    da.setData(nix_dtype, PyArray_DATA(array), count, offset);
}

static std::string getDataType(const nix::DataSet& da)
{
    nix::DataType nix_dtype = da.dataType();
    return nixDtypeToPyDtypeStr(nix_dtype);
}

//

struct dtype_transmogrify {
    typedef boost::python::converter::rvalue_from_python_stage1_data py_s1_data;
    typedef boost::python::converter::rvalue_from_python_storage<nix::DataType> py_storage;

       // PyObject* -> nix::DataType
    static void register_from_python() {
        boost::python::converter::registry::push_back(is_convertible,
                                                      construct,
                                                      boost::python::type_id<nix::DataType>());
    }

    static void* is_convertible(PyObject *obj) {
        namespace bp = boost::python;

        PyArray_Descr* py_dtype = nullptr;

        if (! PyArray_DescrConverter(obj, &py_dtype)) {
            // PyArray_DescrConverter will have set an TypeError
            // exception if this occurs, clear it
            PyErr_Clear();
            return nullptr;
        }

        Py_DECREF(py_dtype);
        return obj;
    }

    static void construct(PyObject *obj, py_s1_data *data) {
        namespace bp = boost::python;

        void *raw = static_cast<void *>(reinterpret_cast<py_storage *>(data)->storage.bytes);

        PyArray_Descr* py_dtype = nullptr;
        //should work, because we checked with is_convertible
        PyArray_DescrConverter(obj, &py_dtype);

        nix::DataType * const dtype_ptr = static_cast<nix::DataType *>(raw);
        *dtype_ptr = pyDtypeToNixDtype(py_dtype);
        data->convertible = raw;
    }

};

struct DataSetWrapper : public nix::DataSet, public boost::python::wrapper<nix::DataSet> {

    void ioRead(nix::DataType dtype,
                void *data,
                const nix::NDSize &count,
                const nix::NDSize &offset) const override {
        this->get_override("ioRead")(dtype, data, count, offset);
    }

     void ioWrite(nix::DataType dtype,
                  const void *data,
                  const nix::NDSize &count,
                  const nix::NDSize &offset) override {
        this->get_override("ioWrite")(dtype, data, count, offset);
     }
     virtual void dataExtent(const nix::NDSize &extent) override {
        this->get_override("dataExtent")(extent);
     }

     virtual nix::NDSize dataExtent() const override {
        return this->get_override("dataExtent")();
     };

     virtual nix::DataType dataType() const override {
        return this->get_override("dataType")();
     }
};

NIXPY_DO_EXPORT_RETTYPE PyDataSet::do_export() {
    using namespace boost::python;

    // For numpy to work
    import_array();

    class_<DataSetWrapper, boost::noncopyable>("DataSet")
        .def("_write_data", writeData)
        .def("_read_data", readData)
        .def("_get_dtype", getDataType)
        .add_property("data_extent",
                      GETTER(nix::NDSize, nix::DataSet, dataExtent),
                      SETTER(nix::NDSize&, nix::DataSet, dataExtent),
                      doc::data_array_data_extent)
        .add_property("data_type", &nix::DataSet::dataType,
                      doc::data_array_data_type);

    class_<nix::DataView, bases<nix::DataSet>>("DataView", boost::python::no_init);

    dtype_transmogrify::register_from_python();

    return NIXPY_DO_EXPORT_RETVAL;
}

} // nixpy::
<commit_msg>[DataSet] cast void * to char *<commit_after>// Copyright (c) 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE source in the root of the Project.

#include <boost/python.hpp>
#include <boost/optional.hpp>

#include <nix.hpp>

#include <accessors.hpp>
#include <transmorgify.hpp>

//we want only the newest and freshest API
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <numpy/arrayobject.h>
#include <numpy/ndarrayobject.h>

#include <PyEntity.hpp>

#include <stdexcept>

namespace nixpy {

// Data

static nix::DataType pyDtypeToNixDtype(const PyArray_Descr *dtype)
{
    if (dtype == nullptr) {
        return nix::DataType::Nothing;
    }

    if (dtype->byteorder != '=' && dtype->byteorder != '|') {
        //TODO: Handle case where specified byteorder *is*
        //the native byteorder (via BOOST_BIG_ENDIAN macros)
        return nix::DataType::Nothing;
    }

    switch (dtype->kind) {

    case 'u':
        switch (dtype->elsize) {
        case 1: return nix::DataType::UInt8;
        case 2: return nix::DataType::UInt16;
        case 4: return nix::DataType::UInt32;
        case 8: return nix::DataType::UInt64;
        }
        break;

    case 'i':
        switch (dtype->elsize) {
        case 1: return nix::DataType::Int8;
        case 2: return nix::DataType::Int16;
        case 4: return nix::DataType::Int32;
        case 8: return nix::DataType::Int64;
        }
        break;

    case 'f':
        switch (dtype->elsize) {
        case 4: return nix::DataType::Float;
        case 8: return nix::DataType::Double;
        }
        break;

    case 'V':
        return nix::DataType::Opaque;
        //we are ignoring the size information here
        //since we only support NATIVE_OPAQUE in H5
        //maybe we should throw an exception instead
        break;

    default:
        break;
    }
    return nix::DataType::Nothing;
}

static std::string nixDtypeToPyDtypeStr(nix::DataType nix_dtype)
{
    switch (nix_dtype) {
    case nix::DataType::UInt8:  return "<u1";
    case nix::DataType::UInt16: return "<u2";
    case nix::DataType::UInt32: return "<u4";
    case nix::DataType::UInt64: return "<u8";
    case nix::DataType::Int8:   return "<i1";
    case nix::DataType::Int16:  return "<i2";
    case nix::DataType::Int32:  return "<i4";
    case nix::DataType::Int64:  return "<i8";
    case nix::DataType::Float:  return "<f4";
    case nix::DataType::Double: return "<f8";
    case nix::DataType::Opaque: return "|V1";
    default:                    return "";
    }
}

static nix::DataType arrayDescAsDtype(PyArrayObject *array) {
    nix::DataType nix_dtype = pyDtypeToNixDtype(PyArray_DESCR(array));

    if (nix_dtype == nix::DataType::Nothing) {
        throw std::invalid_argument("Unsupported dtype for data");
    }

    return nix_dtype;
}

static PyArrayObject *makeArray(PyObject *data, int requirements) {
    if (! PyArray_Check(data)) {
        throw std::invalid_argument("Data not a NumPy array");
    }

    PyArrayObject *array = reinterpret_cast<PyArrayObject *>(data);
    PyArray_Descr *descr = PyArray_DESCR(array);

    if (requirements & NPY_ARRAY_ALIGNED && descr->kind == 'V') {
       //workaround a strange behaviour of numpy 1.9 to return
       //is_aligned == FALSE for void datatypes with an alignment
       //requirement == 1
       if (descr->alignment == 1) {
          requirements &= ~NPY_ARRAY_ALIGNED;
       }
    }

     if (! PyArray_CHKFLAGS(array, requirements)) {
        throw std::invalid_argument("array does not meet requirements");
    }

     return array;
}

static nix::NDSize arrayShapeAsNDSize(PyArrayObject *array) {
    int array_rank = PyArray_NDIM(array);
    npy_intp *array_shape = PyArray_SHAPE(array);

    nix::NDSize data_shape(array_rank);
    for (int i = 0; i < array_rank; i++) {
        data_shape[i] = array_shape[i];
    }

    return data_shape;
}

static void arrayEnsureShapeAndCount(PyArrayObject *array,
                                     nix::NDSize    &count,
                                     nix::NDSize    &offset) {

    if (! count) {
        count = arrayShapeAsNDSize(array);
    }

    if (! offset) {
        offset = nix::NDSize(count.size(), 0);
    }
}

static void readData(nix::DataSet& da, PyObject *data, nix::NDSize count, nix::NDSize offset) {

    PyArrayObject *array = makeArray(data, NPY_ARRAY_CARRAY);

    nix::DataType nix_dtype = arrayDescAsDtype(array);

    arrayEnsureShapeAndCount(array, count, offset);
    da.getData(nix_dtype, PyArray_DATA(array), count, offset);
}

static void writeData(nix::DataSet& da, PyObject *data, nix::NDSize count, nix::NDSize offset) {

    PyArrayObject *array = makeArray(data, NPY_ARRAY_CARRAY_RO);

    nix::DataType nix_dtype = arrayDescAsDtype(array);

    arrayEnsureShapeAndCount(array, count, offset);
    da.setData(nix_dtype, PyArray_DATA(array), count, offset);
}

static std::string getDataType(const nix::DataSet& da)
{
    nix::DataType nix_dtype = da.dataType();
    return nixDtypeToPyDtypeStr(nix_dtype);
}

//

struct dtype_transmogrify {
    typedef boost::python::converter::rvalue_from_python_stage1_data py_s1_data;
    typedef boost::python::converter::rvalue_from_python_storage<nix::DataType> py_storage;

       // PyObject* -> nix::DataType
    static void register_from_python() {
        boost::python::converter::registry::push_back(is_convertible,
                                                      construct,
                                                      boost::python::type_id<nix::DataType>());
    }

    static void* is_convertible(PyObject *obj) {
        namespace bp = boost::python;

        PyArray_Descr* py_dtype = nullptr;

        if (! PyArray_DescrConverter(obj, &py_dtype)) {
            // PyArray_DescrConverter will have set an TypeError
            // exception if this occurs, clear it
            PyErr_Clear();
            return nullptr;
        }

        Py_DECREF(py_dtype);
        return obj;
    }

    static void construct(PyObject *obj, py_s1_data *data) {
        namespace bp = boost::python;

        void *raw = static_cast<void *>(reinterpret_cast<py_storage *>(data)->storage.bytes);

        PyArray_Descr* py_dtype = nullptr;
        //should work, because we checked with is_convertible
        PyArray_DescrConverter(obj, &py_dtype);

        nix::DataType * const dtype_ptr = static_cast<nix::DataType *>(raw);
        *dtype_ptr = pyDtypeToNixDtype(py_dtype);
        data->convertible = raw;
    }

};

struct DataSetWrapper : public nix::DataSet, public boost::python::wrapper<nix::DataSet> {

    void ioRead(nix::DataType dtype,
                void *data,
                const nix::NDSize &count,
                const nix::NDSize &offset) const {
        const boost::python::override fn = this->get_override("ioRead");
        fn(dtype, static_cast<char*>(data), std::ref(count), std::ref(offset));
    }

     void ioWrite(nix::DataType dtype,
                  const void *data,
                  const nix::NDSize &count,
                  const nix::NDSize &offset) {
        const boost::python::override fn = this->get_override("ioWrite");
        fn(dtype, static_cast<const char*>(data), std::ref(count), std::ref(offset));
     }
     virtual void dataExtent(const nix::NDSize &extent) override {
        this->get_override("dataExtent")(extent);
     }

     virtual nix::NDSize dataExtent() const override {
        return this->get_override("dataExtent")();
     };

     virtual nix::DataType dataType() const override {
        return this->get_override("dataType")();
     }
};

NIXPY_DO_EXPORT_RETTYPE PyDataSet::do_export() {
    using namespace boost::python;

    // For numpy to work
    import_array();

    class_<DataSetWrapper, boost::noncopyable>("DataSet")
        .def("_write_data", writeData)
        .def("_read_data", readData)
        .def("_get_dtype", getDataType)
        .add_property("data_extent",
                      GETTER(nix::NDSize, nix::DataSet, dataExtent),
                      SETTER(nix::NDSize&, nix::DataSet, dataExtent),
                      doc::data_array_data_extent)
        .add_property("data_type", &nix::DataSet::dataType,
                      doc::data_array_data_type);

    class_<nix::DataView, bases<nix::DataSet>>("DataView", boost::python::no_init);

    dtype_transmogrify::register_from_python();

    return NIXPY_DO_EXPORT_RETVAL;
}

} // nixpy::
<|endoftext|>


<commit_before>/*

REALMATRIX.cc -- routines for REALMATRIX class

Copyright (C) 2001-2004 Norbert Mueller

This file is part of the iRRAM Library.

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

The iRRAM 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 Library General Public
License for more details.

You should have received a copy of the GNU Library General Public License
along with the iRRAM Library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/

#include <stdlib.h>
#include "iRRAM/core.h"

namespace iRRAM {
/**************************************************************************/
#define ELEMENT(x,i,j) x.values[(i)*x.maxcolumn+j]

REALMATRIX::REALMATRIX(unsigned int rows,unsigned int columns)
{
//fprintf(stderr," +- Kreiere 1m: %x\n",this);
  if ( (rows == 0)||  (columns == 0 ) ) {
     fprintf(stderr,"Error in dimensioning real matrix of size [%d,%d]\n",
         rows,columns);
     exit(1);
     }
  maxrow=rows;maxcolumn=columns;
  values=new REAL[rows*columns];
};

REALMATRIX eye (unsigned int rows) {
  REALMATRIX prod(rows,rows); REAL one=1;
  for (unsigned int i=0;i<rows;i++)ELEMENT(prod,i,i)=one;
  return prod;
}

REALMATRIX zeroes  (unsigned int rows,
                    unsigned int columns) {
  REAL zero=0;
  REALMATRIX result(rows,columns);
  for (unsigned int i=0;i<rows;i++)
  for (unsigned int j=0;j<columns;j++)
	ELEMENT(result,i,j)=zero;
  return result;
}

REALMATRIX ones    (unsigned int rows,
                    unsigned int columns) {
  REALMATRIX result(rows,columns);
  REAL one=1;
  for (unsigned int i=0;i<rows;i++)
  for (unsigned int j=0;j<columns;j++)
	ELEMENT(result,i,j)=one;
  return result;
}

REALMATRIX& REALMATRIX::operator = (const REALMATRIX& y) {
  if ( maxrow * maxcolumn != y.maxrow*y.maxcolumn) {
     delete []values;
     values=new REAL[y.maxrow*y.maxcolumn];
     }
  maxrow = y.maxrow;
  maxcolumn = y.maxcolumn;
  unsigned int size=maxrow*maxcolumn;
  for (unsigned int i=0;i<size;i++) values[i]=y.values[i];
  return(*this);
}

REALMATRIX operator + (const REALMATRIX& x, const REALMATRIX& y) {
  REALMATRIX sum(x.maxrow,x.maxcolumn);

  if ( x.maxrow != y.maxrow || x.maxcolumn != y.maxcolumn) {
     fprintf(stderr,"Error in adding real matrices of different sizes \n");
     exit(1);
     }
  unsigned int size=x.maxrow*x.maxcolumn;
  for (unsigned int i=0; i<size;i++) sum.values[i]=x.values[i]+y.values[i];
  return sum;
}

REALMATRIX operator - (const REALMATRIX& x, const REALMATRIX& y) {
  REALMATRIX sum(x.maxrow,x.maxcolumn);

  if ( x.maxrow != y.maxrow || x.maxcolumn != y.maxcolumn) {
     fprintf(stderr,"Error in adding real matrices of different sizes \n");
     exit(1);
     }
  unsigned int size=x.maxrow*x.maxcolumn;
  for (unsigned int i=0; i<size;i++) sum.values[i]=x.values[i]-y.values[i];
  return sum;
}

REALMATRIX operator * (const REALMATRIX& x ,const REALMATRIX& y) {
  REALMATRIX prod(x.maxrow,y.maxcolumn);

  if ( x.maxcolumn != y.maxrow) {
     fprintf(stderr,"Error in multiplying real matrices of different sizes \n");
     exit(1);
     }
  for (unsigned int i=0; i<x.maxrow;i++) {
  for (unsigned int j=0; j<y.maxcolumn;j++) {
    ELEMENT(prod,i,j)=ELEMENT(x,i,0)*ELEMENT(y,0,j);
    for (unsigned int k=1; k<x.maxcolumn;k++) {
      ELEMENT(prod,i,j)=ELEMENT(prod,i,j)+ELEMENT(x,i,k)*ELEMENT(y,k,j);
    } } }
  return prod;
}

REALMATRIX operator / (const REALMATRIX& x,const REALMATRIX& y) {
  REALMATRIX rside=x,lside=y,result;
  return solve(lside,rside,1);
}

REALMATRIX solve
       (REALMATRIX& lside,
        REALMATRIX& rside,
        int               use_pivot) {
continous_begin ();
  REALMATRIX result(rside.maxrow,rside.maxcolumn);
  REAL faktor;
  int testsize,pivotsize,pivot,pivotsave;
  std::vector<int> perm (lside.maxrow);

  if ( lside.maxrow != rside.maxrow) {
     fprintf(stderr,"Error, incompatible real matrices\n");
     exit(1);
     }
  for (unsigned int i=0; i<lside.maxrow;i++) perm[i]=i;
  for (unsigned int i=0; i < lside.maxrow; i++) {
    pivot=i;
    if (use_pivot) {
      pivotsize=upperbound(ELEMENT(lside,perm[i],i));
      for (unsigned int j=i+1; j < lside.maxcolumn; j++) {
        testsize=upperbound(ELEMENT(lside,perm[j],i));
        if (testsize>pivotsize) {
          pivot=j;
          pivotsize=testsize;
        }
        else if ( testsize < pivotsize && use_pivot == 1) break ;
      }
      pivotsave=perm[pivot];
      perm[pivot]=perm[i];
      perm[i]=pivotsave;
    }
    for (unsigned int j=i+1; j < lside.maxcolumn; j++) {
      faktor=ELEMENT(lside,perm[j],i)/ELEMENT(lside,perm[i],i);
      for (unsigned int k=0; k< rside.maxcolumn; k++)
         ELEMENT(rside,perm[j],k)=ELEMENT(rside,perm[j],k)
                   -faktor*ELEMENT(rside,perm[i],k);
      for (unsigned int l=i; l< lside.maxcolumn; l++)
         ELEMENT(lside,perm[j],l)=ELEMENT(lside,perm[j],l)
                   -faktor*ELEMENT(lside,perm[i],l);
    }
  }

  for (int i=rside.maxrow-1; i >= 0; i--) {
     faktor=1/ELEMENT(lside,perm[i],i);
     for (unsigned int k=0; k< rside.maxcolumn; k++) {
   ELEMENT(result,i,k)=ELEMENT(rside,perm[i],k)*faktor;
   for (int j=0; j < i; j++)
     ELEMENT(rside,perm[j],k)=ELEMENT(rside,perm[j],k)
       -ELEMENT(lside,perm[j],i)* ELEMENT(result,i,k);
  } }
continous_end ();
  return result;
}

REALMATRIX::~REALMATRIX() {
//fprintf(stderr," +- Destructor 1m: %x\n",this);
  delete []values;
};

REALMATRIX::REALMATRIX(){
  maxrow=0;maxcolumn=0;values=NULL;
};

REALMATRIX::REALMATRIX(const REALMATRIX& y){
  maxrow=y.maxrow;maxcolumn=y.maxcolumn;
  unsigned int size=maxrow*maxcolumn;
  values = new REAL[size];
  for (unsigned int i=0; i < size; i++) values[i]=y.values[i];
};

REAL&  REALMATRIX::element (unsigned int i, unsigned int j) const {
  if ((i>= maxrow) || (j>= maxcolumn) ) {
     fprintf(stderr,"Illegal indices [%d,%d] for real matrix [%d,%d]\n",
           i,j,maxrow,maxcolumn);
     exit(1);
     }
  return values[i*maxcolumn+j];
};

REAL&  REALMATRIX::operator () (unsigned int i, unsigned int j) const {
  if ((i>= maxrow) || (j>= maxcolumn) ) {
     fprintf(stderr,"Illegal indices [%d,%d] for real matrix [%d,%d]\n",
           i,j,maxrow,maxcolumn);
     exit(1);
     }
  return values[i*maxcolumn+j];
};

REALMATRIX operator * (const REALMATRIX& x, const REAL& y) {
  REALMATRIX prod(x.maxrow,x.maxcolumn);
  for (unsigned int i=0; i<x.maxcolumn;i++) {
  for (unsigned int j=0; j<x.maxrow;j++) {
      ELEMENT(prod,i,j)=ELEMENT(x,i,j)*y;
    } }
  return prod;
}

REALMATRIX operator / (const REALMATRIX& x, const REAL& y) {
  REALMATRIX prod(x.maxrow,x.maxcolumn);
  for (unsigned int i=0; i<x.maxcolumn;i++) {
  for (unsigned int j=0; j<x.maxrow;j++) {
      ELEMENT(prod,i,j)=ELEMENT(x,i,j)/y;
    } }
  return prod;
}

int bound (const REALMATRIX& x, const int k){
  for (unsigned int i=0;i<x.maxcolumn;i++)
  for (unsigned int j=0;j<x.maxrow;j++)
	if ( ! bound(ELEMENT(x,i,j),k) ) return 0;
  return 1;
}

void REALMATRIX::adderror (sizetype error)
{
  for (unsigned int i=0;i<(*this).maxcolumn;i++)
  for (unsigned int j=0;j<(*this).maxrow;j++)
      ELEMENT((*this),i,j).adderror(error);
}

void REALMATRIX::seterror (sizetype error)
{
  for (unsigned int i=0;i<(*this).maxcolumn;i++)
  for (unsigned int j=0;j<(*this).maxrow;j++)
      ELEMENT((*this),i,j).seterror(error);
}

void REALMATRIX::geterror (sizetype& error) const
{
  unsigned int i,j;
  sizetype lerror;
  ELEMENT((*this),0,0).geterror(error);
  for (i=0;i<(*this).maxcolumn;i++)
  for (j=0;j<(*this).maxrow;j++) {
      ELEMENT((*this),i,j).geterror(lerror);
      sizetype_max(error,error,lerror);
  }
}

REAL       maxnorm (const REALMATRIX& x){
  REAL m=abs(x.values[0]);
  unsigned int size=x.maxrow*x.maxcolumn;
  for (unsigned int i=1; i<size;i++) m=maximum(m,abs(x.values[i]));
  return m;
}

REAL       rowsumnorm (const REALMATRIX& x){
  REAL m=0;
  REAL sum;
  for (unsigned int i=0;i<x.maxrow;i++) {
    sum=0;
    for (unsigned int j=0;j<x.maxcolumn;j++) sum=sum+abs(x(i,j));
    m=maximum(m,sum);
  }
  return m;
}

REAL       colsumnorm (const REALMATRIX& x){
  REAL m=0;
  REAL sum;
  for (unsigned int j=0;j<x.maxcolumn;j++) {
    sum=0;
    for (unsigned int i=0;i<x.maxrow;i++) sum=sum+abs(x(i,j));
    m=maximum(m,sum);
  }
  return m;
}
} // namespace iRRAM
<commit_msg>replace "continous_begin"/"continous_end" by "single_valued", -Wpedantic: removed unneeded ";"<commit_after>/*

REALMATRIX.cc -- routines for REALMATRIX class

Copyright (C) 2001-2004 Norbert Mueller

This file is part of the iRRAM Library.

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

The iRRAM 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 Library General Public
License for more details.

You should have received a copy of the GNU Library General Public License
along with the iRRAM Library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/

#include <stdlib.h>
#include "iRRAM/core.h"

namespace iRRAM {
/**************************************************************************/
#define ELEMENT(x,i,j) x.values[(i)*x.maxcolumn+j]

REALMATRIX::REALMATRIX(unsigned int rows,unsigned int columns)
{
//fprintf(stderr," +- Kreiere 1m: %x\n",this);
  if ( (rows == 0)||  (columns == 0 ) ) {
     fprintf(stderr,"Error in dimensioning real matrix of size [%d,%d]\n",
         rows,columns);
     exit(1);
     }
  maxrow=rows;maxcolumn=columns;
  values=new REAL[rows*columns];
}

REALMATRIX eye (unsigned int rows) {
  REALMATRIX prod(rows,rows); REAL one=1;
  for (unsigned int i=0;i<rows;i++)ELEMENT(prod,i,i)=one;
  return prod;
}

REALMATRIX zeroes  (unsigned int rows,
                    unsigned int columns) {
  REAL zero=0;
  REALMATRIX result(rows,columns);
  for (unsigned int i=0;i<rows;i++)
  for (unsigned int j=0;j<columns;j++)
	ELEMENT(result,i,j)=zero;
  return result;
}

REALMATRIX ones    (unsigned int rows,
                    unsigned int columns) {
  REALMATRIX result(rows,columns);
  REAL one=1;
  for (unsigned int i=0;i<rows;i++)
  for (unsigned int j=0;j<columns;j++)
	ELEMENT(result,i,j)=one;
  return result;
}

REALMATRIX& REALMATRIX::operator = (const REALMATRIX& y) {
  if ( maxrow * maxcolumn != y.maxrow*y.maxcolumn) {
     delete []values;
     values=new REAL[y.maxrow*y.maxcolumn];
     }
  maxrow = y.maxrow;
  maxcolumn = y.maxcolumn;
  unsigned int size=maxrow*maxcolumn;
  for (unsigned int i=0;i<size;i++) values[i]=y.values[i];
  return(*this);
}

REALMATRIX operator + (const REALMATRIX& x, const REALMATRIX& y) {
  REALMATRIX sum(x.maxrow,x.maxcolumn);

  if ( x.maxrow != y.maxrow || x.maxcolumn != y.maxcolumn) {
     fprintf(stderr,"Error in adding real matrices of different sizes \n");
     exit(1);
     }
  unsigned int size=x.maxrow*x.maxcolumn;
  for (unsigned int i=0; i<size;i++) sum.values[i]=x.values[i]+y.values[i];
  return sum;
}

REALMATRIX operator - (const REALMATRIX& x, const REALMATRIX& y) {
  REALMATRIX sum(x.maxrow,x.maxcolumn);

  if ( x.maxrow != y.maxrow || x.maxcolumn != y.maxcolumn) {
     fprintf(stderr,"Error in adding real matrices of different sizes \n");
     exit(1);
     }
  unsigned int size=x.maxrow*x.maxcolumn;
  for (unsigned int i=0; i<size;i++) sum.values[i]=x.values[i]-y.values[i];
  return sum;
}

REALMATRIX operator * (const REALMATRIX& x ,const REALMATRIX& y) {
  REALMATRIX prod(x.maxrow,y.maxcolumn);

  if ( x.maxcolumn != y.maxrow) {
     fprintf(stderr,"Error in multiplying real matrices of different sizes \n");
     exit(1);
     }
  for (unsigned int i=0; i<x.maxrow;i++) {
  for (unsigned int j=0; j<y.maxcolumn;j++) {
    ELEMENT(prod,i,j)=ELEMENT(x,i,0)*ELEMENT(y,0,j);
    for (unsigned int k=1; k<x.maxcolumn;k++) {
      ELEMENT(prod,i,j)=ELEMENT(prod,i,j)+ELEMENT(x,i,k)*ELEMENT(y,k,j);
    } } }
  return prod;
}

REALMATRIX operator / (const REALMATRIX& x,const REALMATRIX& y) {
  REALMATRIX rside=x,lside=y,result;
  return solve(lside,rside,1);
}

REALMATRIX solve
       (REALMATRIX& lside,
        REALMATRIX& rside,
        int               use_pivot) {
  single_valued code(true);
  REALMATRIX result(rside.maxrow,rside.maxcolumn);
  REAL faktor;
  int testsize,pivotsize,pivot,pivotsave;
  std::vector<int> perm (lside.maxrow);

  if ( lside.maxrow != rside.maxrow) {
     fprintf(stderr,"Error, incompatible real matrices\n");
     exit(1);
     }
  for (unsigned int i=0; i<lside.maxrow;i++) perm[i]=i;
  for (unsigned int i=0; i < lside.maxrow; i++) {
    pivot=i;
    if (use_pivot) {
      pivotsize=upperbound(ELEMENT(lside,perm[i],i));
      for (unsigned int j=i+1; j < lside.maxcolumn; j++) {
        testsize=upperbound(ELEMENT(lside,perm[j],i));
        if (testsize>pivotsize) {
          pivot=j;
          pivotsize=testsize;
        }
        else if ( testsize < pivotsize && use_pivot == 1) break ;
      }
      pivotsave=perm[pivot];
      perm[pivot]=perm[i];
      perm[i]=pivotsave;
    }
    for (unsigned int j=i+1; j < lside.maxcolumn; j++) {
      faktor=ELEMENT(lside,perm[j],i)/ELEMENT(lside,perm[i],i);
      for (unsigned int k=0; k< rside.maxcolumn; k++)
         ELEMENT(rside,perm[j],k)=ELEMENT(rside,perm[j],k)
                   -faktor*ELEMENT(rside,perm[i],k);
      for (unsigned int l=i; l< lside.maxcolumn; l++)
         ELEMENT(lside,perm[j],l)=ELEMENT(lside,perm[j],l)
                   -faktor*ELEMENT(lside,perm[i],l);
    }
  }

  for (int i=rside.maxrow-1; i >= 0; i--) {
     faktor=1/ELEMENT(lside,perm[i],i);
     for (unsigned int k=0; k< rside.maxcolumn; k++) {
   ELEMENT(result,i,k)=ELEMENT(rside,perm[i],k)*faktor;
   for (int j=0; j < i; j++)
     ELEMENT(rside,perm[j],k)=ELEMENT(rside,perm[j],k)
       -ELEMENT(lside,perm[j],i)* ELEMENT(result,i,k);
  } }
  return result;
}

REALMATRIX::~REALMATRIX() {
//fprintf(stderr," +- Destructor 1m: %x\n",this);
  delete []values;
}

REALMATRIX::REALMATRIX(){
  maxrow=0;maxcolumn=0;values=NULL;
}

REALMATRIX::REALMATRIX(const REALMATRIX& y){
  maxrow=y.maxrow;maxcolumn=y.maxcolumn;
  unsigned int size=maxrow*maxcolumn;
  values = new REAL[size];
  for (unsigned int i=0; i < size; i++) values[i]=y.values[i];
}

REAL&  REALMATRIX::element (unsigned int i, unsigned int j) const {
  if ((i>= maxrow) || (j>= maxcolumn) ) {
     fprintf(stderr,"Illegal indices [%d,%d] for real matrix [%d,%d]\n",
           i,j,maxrow,maxcolumn);
     exit(1);
     }
  return values[i*maxcolumn+j];
}

REAL&  REALMATRIX::operator () (unsigned int i, unsigned int j) const {
  if ((i>= maxrow) || (j>= maxcolumn) ) {
     fprintf(stderr,"Illegal indices [%d,%d] for real matrix [%d,%d]\n",
           i,j,maxrow,maxcolumn);
     exit(1);
     }
  return values[i*maxcolumn+j];
}

REALMATRIX operator * (const REALMATRIX& x, const REAL& y) {
  REALMATRIX prod(x.maxrow,x.maxcolumn);
  for (unsigned int i=0; i<x.maxcolumn;i++) {
  for (unsigned int j=0; j<x.maxrow;j++) {
      ELEMENT(prod,i,j)=ELEMENT(x,i,j)*y;
    } }
  return prod;
}

REALMATRIX operator / (const REALMATRIX& x, const REAL& y) {
  REALMATRIX prod(x.maxrow,x.maxcolumn);
  for (unsigned int i=0; i<x.maxcolumn;i++) {
  for (unsigned int j=0; j<x.maxrow;j++) {
      ELEMENT(prod,i,j)=ELEMENT(x,i,j)/y;
    } }
  return prod;
}

int bound (const REALMATRIX& x, const int k){
  for (unsigned int i=0;i<x.maxcolumn;i++)
  for (unsigned int j=0;j<x.maxrow;j++)
	if ( ! bound(ELEMENT(x,i,j),k) ) return 0;
  return 1;
}

void REALMATRIX::adderror (sizetype error)
{
  for (unsigned int i=0;i<(*this).maxcolumn;i++)
  for (unsigned int j=0;j<(*this).maxrow;j++)
      ELEMENT((*this),i,j).adderror(error);
}

void REALMATRIX::seterror (sizetype error)
{
  for (unsigned int i=0;i<(*this).maxcolumn;i++)
  for (unsigned int j=0;j<(*this).maxrow;j++)
      ELEMENT((*this),i,j).seterror(error);
}

void REALMATRIX::geterror (sizetype& error) const
{
  unsigned int i,j;
  sizetype lerror;
  ELEMENT((*this),0,0).geterror(error);
  for (i=0;i<(*this).maxcolumn;i++)
  for (j=0;j<(*this).maxrow;j++) {
      ELEMENT((*this),i,j).geterror(lerror);
      sizetype_max(error,error,lerror);
  }
}

REAL       maxnorm (const REALMATRIX& x){
  REAL m=abs(x.values[0]);
  unsigned int size=x.maxrow*x.maxcolumn;
  for (unsigned int i=1; i<size;i++) m=maximum(m,abs(x.values[i]));
  return m;
}

REAL       rowsumnorm (const REALMATRIX& x){
  REAL m=0;
  REAL sum;
  for (unsigned int i=0;i<x.maxrow;i++) {
    sum=0;
    for (unsigned int j=0;j<x.maxcolumn;j++) sum=sum+abs(x(i,j));
    m=maximum(m,sum);
  }
  return m;
}

REAL       colsumnorm (const REALMATRIX& x){
  REAL m=0;
  REAL sum;
  for (unsigned int j=0;j<x.maxcolumn;j++) {
    sum=0;
    for (unsigned int i=0;i<x.maxrow;i++) sum=sum+abs(x(i,j));
    m=maximum(m,sum);
  }
  return m;
}
} // namespace iRRAM
<|endoftext|>