<commit_before>#include "World.h"
#include "ChemicalSelector.h"
#include "CreatureGrapher.h"
#include <cstring>
#include <fstream>
#include "Engine.h"
#include "Catalogue.h"
#include <QtGui>
#include <boost/format.hpp>

ChemicalSelector::ChemicalSelector(CreatureGrapher *p): QWidget(p), parent(p) {
	for (unsigned int i = 0; i < 256; i++) {
		chemselected[i] = false;
	}

	// read in interesting chemical info from game files
	if (engine.version < 3) {
		// c1/c2 are easy; c2e wants scary catalogue stuff.
		std::ifstream ifs(world.findFile("allchemicals.str").c_str());
		if (!ifs.good()) {
			ifs.close();
			throw creaturesException("Couldn't find allchemicals.str");
		}

		char n = ifs.get();
		char o = ifs.get();
		if (n != 0 || o != 1) {
			throw creaturesException("allchemicals.str is corrupt");
		}

		for (int i = 0; ifs.good(); i++) {
			int len = ifs.get();
			// file is only !good once you tried reading past the end
			if (!ifs.good()) break;

			if (len) {
				std::vector<char> name(len+1, '\0');
				ifs.read(&name[0], len);
				chemnames[i] = std::string(&name[0]);
			} else {
				chemnames[i] = boost::str(boost::format("<%d>") % i);
			}
		}
		ifs.close();
	} else {
		if (catalogue.hasTag("chemical_names")) {
			// c2e has chemical names in a catalogue file
			// TODO: there's some really dumb issues here, like chem 90 being '90' instead of 'Wounded' in c3/ds
			// TODO: one possibility is that C3 has a short_chemical_names tag without this kind of stupidity..
			const std::vector<std::string> &t = catalogue.getTag("chemical_names");
			for (unsigned int i = 0; i < t.size(); i++) {
				chemnames[i] = t[i];
			}
		}
	}

	if (engine.version == 2) {
		// c2 has a ChemGroups file with useful data.
		std::ifstream ifs(world.findFile("Applet Data/ChemGroups").c_str());
		if (!ifs.good()) {
			ifs.close();
			throw creaturesException("Couldn't find ChemGroups");
		}
		while (ifs.good()) {
			std::string line;
			getline(ifs, line);
			if (line[0] == '#') {
				continue;
			}
			size_t firstbar = line.find('|');
			if (firstbar == std::string::npos) break;
			std::string groupname = line.substr(0, firstbar);
			const char *cline = strchr(line.c_str(), '|');
			int chemid;
			while (sscanf(cline, "|%d", &chemid)) {
				chemgroups[groupname].push_back(chemid);
				cline = strchr(cline+1, '|');
				if (!cline) break;
			}
		}
		ifs.close();
	} else if (catalogue.hasTag("chemical graphing groups")) {
		// Creatures 3 has groups in the catalogue file
		const std::vector<std::string> &t = catalogue.getTag("chemical graphing groups");
		for (unsigned int i = 0; i < t.size(); i++) {
			std::string groupname = t[i];

			std::string tagname = boost::str(boost::format("chemical graphing group %d") % (int)(i + 1));
			if (catalogue.hasTag(tagname)) {
				const std::vector<std::string> &t = catalogue.getTag(tagname);
				for (unsigned int i = 0; i < t.size(); i++) {
					int chem = atoi(t[i].c_str());
					if (chem != 0)
						chemgroups[groupname].push_back(chem);
				}
			}
		}
	}

	grouplist = new QListWidget(this);
	if (chemgroups.size() == 0) grouplist->hide();
	connect(grouplist, SIGNAL(itemSelectionChanged()), this, SLOT(onGroupChange()));
	chemlist = new QListWidget(this);
	connect(chemlist, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onChemChange(QListWidgetItem*)));

	// add the implicit "All" group.
	for (std::map<unsigned int, std::string>::iterator i = chemnames.begin(); i != chemnames.end(); i++) {
		if (i->first != 0)
			chemgroups["All"].push_back(i->first);
	}

	for (std::map<std::string, std::vector<unsigned int> >::iterator i = chemgroups.begin();
	     i != chemgroups.end(); i++) { // i hate c++
	  new QListWidgetItem(i->first.c_str(), grouplist);
	}
	grouplist->setCurrentRow(0);

	QHBoxLayout *layout = new QHBoxLayout(this);
	layout->addWidget(grouplist, 1);
	layout->addWidget(chemlist, 1);
	setLayout(layout);
}

void ChemicalSelector::onGroupChange() {
	chemlist->clear();
	std::string groupname = grouplist->currentItem()->text().toStdString();
	for (std::vector<unsigned int>::iterator i = chemgroups[groupname].begin();
	     i != chemgroups[groupname].end(); i++) {
	  QListWidgetItem *item = new QListWidgetItem(chemnames[*i].c_str(), chemlist);
	  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
	  item->setCheckState(chemselected[*i] ? Qt::Checked : Qt::Unchecked);
	  item->setData(Qt::UserRole, *i);
	}
}

void ChemicalSelector::onChemChange(QListWidgetItem *item) {
	if (!item) return;

	unsigned int i = item->data(Qt::UserRole).toUInt();
	if (i == 0) return;

	bool newstate = (item->checkState() == Qt::Checked);
	if (chemselected[i] == newstate) return;

	chemselected[i] = newstate;
	emit onSelectionChange(i);
}

<commit_msg>Stop ChemicalSelector from throwing creaturesException on missing allchemicals.str<commit_after>#include "World.h"
#include "ChemicalSelector.h"
#include "CreatureGrapher.h"
#include <cstring>
#include <fstream>
#include <iostream>
#include "Engine.h"
#include "Catalogue.h"
#include <QtGui>
#include <boost/format.hpp>

ChemicalSelector::ChemicalSelector(CreatureGrapher *p): QWidget(p), parent(p) {
	for (unsigned int i = 0; i < 256; i++) {
		chemselected[i] = false;
	}

	// read in interesting chemical info from game files
	if (engine.version < 3) {
		// c1/c2 are easy; c2e wants scary catalogue stuff.
		std::ifstream ifs(world.findFile("allchemicals.str").c_str());
		if (!ifs.good()) {
			std::cout << "Couldn't find allchemicals.str" << std::endl;
		} else {
			char n = ifs.get();
			char o = ifs.get();
			if (n != 0 || o != 1) {
				std::cout << "allchemicals.str is corrupt (bad magic)" << std::endl;
			} else {
				for (int i = 0; ifs.good(); i++) {
					int len = ifs.get();
					// file is only !good once you tried reading past the end
					if (!ifs.good()) break;

					if (len) {
						std::vector<char> name(len+1, '\0');
						ifs.read(&name[0], len);
						chemnames[i] = std::string(&name[0]);
					}
				}
			}
		}
		ifs.close();
	} else {
		if (catalogue.hasTag("chemical_names")) {
			// c2e has chemical names in a catalogue file
			// TODO: there's some really dumb issues here, like chem 90 being '90' instead of 'Wounded' in c3/ds
			// TODO: one possibility is that C3 has a short_chemical_names tag without this kind of stupidity..
			const std::vector<std::string> &t = catalogue.getTag("chemical_names");
			for (unsigned int i = 0; i < t.size(); i++) {
				chemnames[i] = t[i];
			}
		}
	}

	if (engine.version == 2) {
		// c2 has a ChemGroups file with useful data.
		std::ifstream ifs(world.findFile("Applet Data/ChemGroups").c_str());
		if (!ifs.good()) {
			ifs.close();
			std::cout << "Couldn't find ChemGroups" << std::endl;
		} else {
			while (ifs.good()) {
				std::string line;
				getline(ifs, line);
				if (line[0] == '#') {
					continue;
				}
				size_t firstbar = line.find('|');
				if (firstbar == std::string::npos) break;
				std::string groupname = line.substr(0, firstbar);
				const char *cline = strchr(line.c_str(), '|');
				int chemid;
				while (sscanf(cline, "|%d", &chemid)) {
					chemgroups[groupname].push_back(chemid);
					cline = strchr(cline+1, '|');
					if (!cline) break;
				}
			}
			ifs.close();
		}
	} else if (catalogue.hasTag("chemical graphing groups")) {
		// Creatures 3 has groups in the catalogue file
		const std::vector<std::string> &t = catalogue.getTag("chemical graphing groups");
		for (unsigned int i = 0; i < t.size(); i++) {
			std::string groupname = t[i];

			std::string tagname = boost::str(boost::format("chemical graphing group %d") % (int)(i + 1));
			if (catalogue.hasTag(tagname)) {
				const std::vector<std::string> &t = catalogue.getTag(tagname);
				for (unsigned int i = 0; i < t.size(); i++) {
					int chem = atoi(t[i].c_str());
					if (chem != 0)
						chemgroups[groupname].push_back(chem);
				}
			}
		}
	}

	for (int i = 1; i < 255; i++) {
		if (chemnames.find(i) == chemnames.end())
			chemnames[i] = boost::str(boost::format("<%d>") % i);
	}

	grouplist = new QListWidget(this);
	if (chemgroups.size() == 0) grouplist->hide();
	connect(grouplist, SIGNAL(itemSelectionChanged()), this, SLOT(onGroupChange()));
	chemlist = new QListWidget(this);
	connect(chemlist, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onChemChange(QListWidgetItem*)));

	// add the implicit "All" group.
	for (std::map<unsigned int, std::string>::iterator i = chemnames.begin(); i != chemnames.end(); i++) {
		if (i->first != 0)
			chemgroups["All"].push_back(i->first);
	}

	for (std::map<std::string, std::vector<unsigned int> >::iterator i = chemgroups.begin();
	     i != chemgroups.end(); i++) { // i hate c++
	  new QListWidgetItem(i->first.c_str(), grouplist);
	}
	grouplist->setCurrentRow(0);

	QHBoxLayout *layout = new QHBoxLayout(this);
	layout->addWidget(grouplist, 1);
	layout->addWidget(chemlist, 1);
	setLayout(layout);
}

void ChemicalSelector::onGroupChange() {
	chemlist->clear();
	std::string groupname = grouplist->currentItem()->text().toStdString();
	for (std::vector<unsigned int>::iterator i = chemgroups[groupname].begin();
	     i != chemgroups[groupname].end(); i++) {
	  QListWidgetItem *item = new QListWidgetItem(chemnames[*i].c_str(), chemlist);
	  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
	  item->setCheckState(chemselected[*i] ? Qt::Checked : Qt::Unchecked);
	  item->setData(Qt::UserRole, *i);
	}
}

void ChemicalSelector::onChemChange(QListWidgetItem *item) {
	if (!item) return;

	unsigned int i = item->data(Qt::UserRole).toUInt();
	if (i == 0) return;

	bool newstate = (item->checkState() == Qt::Checked);
	if (chemselected[i] == newstate) return;

	chemselected[i] = newstate;
	emit onSelectionChange(i);
}

<|endoftext|>


<commit_before>//
// Created by kanairen on 2016/06/13.
//

#import "Layer.h"

Layer::Layer(unsigned int n_data, unsigned int n_in, unsigned int n_out,
             float (*activation)(float), float (*grad_activation)(float)) :
        n_data(n_data), n_in(n_in), n_out(n_out), activation(activation),
        grad_activation(grad_activation),
        weights(vector<vector<float>>(n_out, vector<float>(n_in, 0.f))),
        biases(vector<float>(n_out, 0.f)),
        delta(vector<vector<float>>(n_out, vector<float>(n_data, 0.f))),
        u(vector<vector<float>>(n_out, vector<float>(n_data, 0.f))),
        z(vector<vector<float>>(n_out, vector<float>(n_data, 0.f))) {

    std::random_device rnd;
    std::mt19937 mt(rnd());
    std::uniform_real_distribution<> uniform(-sqrt(6. / (n_in + n_out)),
                                             sqrt(6. / (n_in + n_out)));
    for (int i = 0; i < n_out; ++i) {
        for (int j = 0; j < n_in; ++j) {
            weights[i][j] = uniform(mt);
        }
    }

}

const vector<vector<float>> &Layer::forward(vector<vector<float>> &input) {
    float out;
    if (input.size() != n_out) {

    }
    for (int i_data = 0; i_data < n_data; ++i_data) {
        for (int i_out = 0; i_out < n_out; ++i_out) {
            out = 0.f;
            for (int i_in = 0; i_in < n_in; ++i_in) {
                out += weights[i_out][i_in] * input[i_in][i_data] +
                       biases[i_out];
            }
            u[i_out][i_data] = out;
            z[i_out][i_data] = activation(out);
        }
    }
    return z;
}

<commit_msg>add Layerクラスに逆伝播を実装<commit_after>//
// Created by kanairen on 2016/06/13.
//

#import "Layer.h"

Layer::Layer(unsigned int n_data, unsigned int n_in, unsigned int n_out,
             float (*activation)(float), float (*grad_activation)(float)) :
        n_data(n_data), n_in(n_in), n_out(n_out), activation(activation),
        grad_activation(grad_activation),
        weights(vector<vector<float>>(n_out, vector<float>(n_in, 0.f))),
        biases(vector<float>(n_out, 0.f)),
        delta(vector<vector<float>>(n_out, vector<float>(n_data, 0.f))),
        u(vector<vector<float>>(n_out, vector<float>(n_data, 0.f))),
        z(vector<vector<float>>(n_out, vector<float>(n_data, 0.f))) {

    std::random_device rnd;
    std::mt19937 mt(rnd());
    std::uniform_real_distribution<> uniform(-sqrt(6. / (n_in + n_out)),
                                             sqrt(6. / (n_in + n_out)));
    for (int i = 0; i < n_out; ++i) {
        for (int j = 0; j < n_in; ++j) {
            weights[i][j] = uniform(mt);
        }
    }

}

const vector<vector<float>> &Layer::forward(vector<vector<float>> &input) {
    float out;
    if (input.size() != n_out) {

    }
    for (int i_data = 0; i_data < n_data; ++i_data) {
        for (int i_out = 0; i_out < n_out; ++i_out) {
            out = 0.f;
            for (int i_in = 0; i_in < n_in; ++i_in) {
                out += weights[i_out][i_in] * input[i_in][i_data] +
                       biases[i_out];
            }
            u[i_out][i_data] = out;
            z[i_out][i_data] = activation(out);
        }
    }
    return z;
}

void Layer::backward(const vector<vector<float>> &last_delta,
                     const vector<vector<float>> &prev_output,
                     const float learning_rate) {

    cout << "last_delta_size : " << last_delta.size() << endl;
    cout << "delta_size: " << delta.size() << endl;

    // 出力層のデルタとしてコピー
    std::copy(last_delta.begin(), last_delta.end(), delta.begin());

    float d;
    float sum_delta = 0.f;
    float max_delta = -MAXFLOAT;
    float min_delta = MAXFLOAT;
    for (int i_out = 0; i_out < n_out; ++i_out) {
        for (int i_data = 0; i_data < n_data; ++i_data) {
            d = delta[i_out][i_data];
            sum_delta += d;
            if (d > max_delta) {
                max_delta = d;
            }
            if (d < min_delta) {
                min_delta = d;
            }
        }
    }
    cout << "sum_delta : " << sum_delta << endl;
    cout << "max_delta : " << max_delta << endl;
    cout << "min_delta : " << min_delta << endl;

    // パラメタ更新
    update(prev_output, learning_rate);

}

void Layer::backward(const Layer &next,
                     const vector<vector<float>> &prev_output,
                     const float learning_rate) {
    const vector<vector<float>> &next_weights = next.weights;
    const vector<vector<float>> &next_delta = next.delta;
    const unsigned int next_n_out = next.n_out;
    float d;
    for (int i_data = 0; i_data < n_data; ++i_data) {
        for (int i_out = 0; i_out < n_out; ++i_out) {
            d = 0.f;
            for (int i_n_out = 0; i_n_out < next_n_out; ++i_n_out) {
                // デルタを導出
                d += grad_activation(u[i_out][i_data]) *
                     next_weights[i_n_out][i_out] * next_delta[i_n_out][i_data];
            }
            delta[i_out][i_data] = d;
        }
    }

    float sum_delta = 0.f;
    float max_delta = -MAXFLOAT;
    float min_delta = MAXFLOAT;
    for (int i_out = 0; i_out < n_out; ++i_out) {
        for (int i_data = 0; i_data < n_data; ++i_data) {
            d = delta[i_out][i_data];
            sum_delta += d;
            if (d > max_delta) {
                max_delta = d;
            }
            if (d < min_delta) {
                min_delta = d;
            }
        }
    }
    cout << "sum_delta : " << sum_delta << endl;
    cout << "max_delta : " << max_delta << endl;
    cout << "min_delta : " << min_delta << endl;

    // パラメタ更新
    update(prev_output, learning_rate);

}

void Layer::update(const vector<vector<float>> &prev_output,
                   const float learning_rate) {
    float dw, db;
    float sum_dw = 0;
    float max_dw = -MAXFLOAT;
    float min_dw = MAXFLOAT;
    for (int i_out = 0; i_out < n_out; ++i_out) {
        for (int i_in = 0; i_in < n_in; ++i_in) {
            dw = 0.f;
            db = 0.f;
            for (int i_data = 0; i_data < n_data; ++i_data) {
                dw += delta[i_out][i_data] * prev_output[i_out][i_data];
                db += delta[i_out][i_data];
                sum_dw += dw;
                if (dw > max_dw) {
                    max_dw = dw;
                }
                if (dw < min_dw) {
                    min_dw = dw;
                }
            }
            weights[i_out][i_in] -= learning_rate * dw / n_data;
        }
        biases[i_out] -= learning_rate * db / n_data;
    }
    cout << "sum_dw : " << sum_dw << endl;
    cout << "max_dw : " << max_dw << endl;
    cout << "min_dw : " << min_dw << endl;

}
<|endoftext|>


<commit_before>#include "util.hpp"

#include <utki/debug.hpp>
#include <utki/config.hpp>

#include "../Morda.hpp"

using namespace morda;

morda::Vec2r morda::makeVec2rFromSTOB(const stob::Node* chain){
	unsigned i;
	morda::Vec2r ret;

	float v = 0;
	for(i = 0; i != 2 && chain; ++i, chain = chain->next()){
		v = chain->asFloat();
		ret[i] = v;
	}

	for(; i != 2; ++i){
		ret[i] = v;
	}

	return ret;
}

Rectr morda::makeRectrFromSTOB(const stob::Node* chain){
	Vec2r p = makeVec2rFromSTOB(chain);
	for(unsigned i = 0; i != 2 && chain; ++i, chain = chain->next()){}
	Vec2r d = makeVec2rFromSTOB(chain);
	return Rectr(p, d);
}

Sidesr morda::makeSidesrFromSTOB(const stob::Node* chain){
	Vec2r p = makeVec2rFromSTOB(chain);
	for(unsigned i = 0; i != 2 && chain; ++i, chain = chain->next()){}
	Vec2r d = makeVec2rFromSTOB(chain);
	return Sidesr(p.x, p.y, d.x, d.y);
}

morda::Vec2r morda::dimVec2rFromSTOB(const stob::Node* chain){
	unsigned i;
	morda::Vec2r ret;

	float v = 0;
	for(i = 0; i != 2 && chain; ++i, chain = chain->next()){
		v = dimValueFromSTOB(*chain);
		ret[i] = v;
	}

	for(; i != 2; ++i){
		ret[i] = v;
	}

	return ret;
}

real morda::dimValueFromSTOB(const stob::Node& n){
	//check if millimeters
	if(n.length() >= 2 && n.value()[n.length() - 1] == 'm' && n.value()[n.length() - 2] == 'm'){
		return Morda::inst().units.mmToPx(n.asFloat());
	}else if(n.length() >= 2 && n.value()[n.length() - 1] == 't' && n.value()[n.length() - 2] == 'p'){ //check if in points
		return Morda::inst().units.ptToPx(n.asFloat());
	}

	return n.asFloat();
}

std::tuple<std::unique_ptr<stob::Node>, stob::Node*> morda::resolveIncludes(papki::File& fi, std::unique_ptr<stob::Node> begin){
	if(!begin){
		return std::make_tuple(nullptr, nullptr);
	}

	const char* DIncludeTag = "include";

	auto n = begin->thisOrNext(DIncludeTag);
	for(; n.node();){
		ASSERT(n.node())
		stob::Node* incPathNode = n.node()->child();
		if(!incPathNode){
			throw Exc("include tag without value encountered in resource script");
		}
		TRACE(<< "ResolveIncludes(): incPathNode->Value = " << incPathNode->value() << std::endl)

		fi.setPath(fi.dir() + incPathNode->value());
		std::unique_ptr<stob::Node> incNodes = stob::load(fi);

		//recursive call
		auto ri = resolveIncludes(fi, std::move(incNodes));

		stob::Node* lastChild = std::get<1>(ri);

		if(lastChild){
			//substitute includes
			if(!n.prev()){
				//include tag is the very first tag

				ASSERT(!lastChild->next())
				lastChild->insertNext(n.node()->chopNext());
				begin = std::move(std::get<0>(ri));
			}else{
				//include tag is not the first one

				n.prev()->removeNext();

				ASSERT(!lastChild->next())
				std::unique_ptr<stob::Node> tail = n.prev()->chopNext();
				n.prev()->setNext(std::move(std::get<0>(ri)));
				lastChild->setNext(std::move(tail));
			}
			n = lastChild->next(DIncludeTag);
		}else{
			n = n.node()->next(DIncludeTag);
		}
	}
	return std::make_tuple(std::move(begin), n.prev());
}

kolme::Vec2b morda::makeVec2bFromSTOB(const stob::Node* chain){
	unsigned i;
	kolme::Vec2b ret;

	bool v = false;
	for(i = 0; i != 2 && chain; ++i, chain = chain->next()){
		v = chain->asBool();
		ret[i] = v;
	}

	for(; i != 2; ++i){
		ret[i] = v;
	}

	return ret;
}

real morda::findDotsPerPt(kolme::Vec2ui resolution, kolme::Vec2ui screenSizeMm){

	//NOTE: for ordinary desktop displays the PT size should be equal to 1 pixel.
	//For high density displays it should be more than one pixel, depending on display ppi.
	//For handheld devices the size of PT should be determined from physical screen size and pixel resolution.

#if M_OS_NAME == M_OS_NAME_ANDROID
	return real(1);//TODO:
#elif M_OS_NAME == M_OS_NAME_IOS
	return real(1);//TODO:
#else
	return real(1);
#endif
}

float morda::dimValueFromLayoutStob(const stob::Node& n){
	if(n == "min"){
		return Widget::LayoutParams::min_c;
	}else if(n == "max"){
		return Widget::LayoutParams::max_c;
	}else if(n == "fill"){
		return Widget::LayoutParams::fill_c;
	}
	return dimValueFromSTOB(n);
}

const stob::Node* morda::getProperty(const stob::Node* chain, const char* property){
	if(!chain){
		return nullptr;
	}
	if(auto n = chain->thisOrNext(property).node()){
		return n->child();
	}
	return nullptr;
}

Texture2D morda::loadTexture(const papki::File& fi){
	Image image(fi);
//	TRACE(<< "ResTexture::Load(): image loaded" << std::endl)
	image.flipVertical();
	return Texture2D(image);
}

std::shared_ptr<Texture2D_n> morda::loadTexture_n(const papki::File& fi){
	Image image(fi);
//	TRACE(<< "ResTexture::Load(): image loaded" << std::endl)
	image.flipVertical();

	morda::Renderer::TexType_e tt;
	switch(image.numChannels()){
		case 1:
			tt = morda::Renderer::TexType_e::GREY;
			break;
		case 2:
			tt = morda::Renderer::TexType_e::GREYA;
			break;
		case 3:
			tt = morda::Renderer::TexType_e::RGB;
			break;
		case 4:
			tt = morda::Renderer::TexType_e::RGBA;
			break;
		default:
			ASSERT(false)
	}

	return morda::inst().renderer().createTexture2D(tt, image.dim(), image.buf());
}

void morda::applySimpleAlphaBlending(){
	Render::setBlendEnabled(true);
	Render::setBlendFunc(Render::BlendFactor_e::SRC_ALPHA, Render::BlendFactor_e::ONE_MINUS_SRC_ALPHA, Render::BlendFactor_e::ONE, Render::BlendFactor_e::ONE_MINUS_SRC_ALPHA);
}
<commit_msg>stuff<commit_after>#include "util.hpp"

#include <utki/debug.hpp>
#include <utki/config.hpp>

#include "../Morda.hpp"

using namespace morda;

morda::Vec2r morda::makeVec2rFromSTOB(const stob::Node* chain){
	unsigned i;
	morda::Vec2r ret;

	float v = 0;
	for(i = 0; i != 2 && chain; ++i, chain = chain->next()){
		v = chain->asFloat();
		ret[i] = v;
	}

	for(; i != 2; ++i){
		ret[i] = v;
	}

	return ret;
}

Rectr morda::makeRectrFromSTOB(const stob::Node* chain){
	Vec2r p = makeVec2rFromSTOB(chain);
	for(unsigned i = 0; i != 2 && chain; ++i, chain = chain->next()){}
	Vec2r d = makeVec2rFromSTOB(chain);
	return Rectr(p, d);
}

Sidesr morda::makeSidesrFromSTOB(const stob::Node* chain){
	Vec2r p = makeVec2rFromSTOB(chain);
	for(unsigned i = 0; i != 2 && chain; ++i, chain = chain->next()){}
	Vec2r d = makeVec2rFromSTOB(chain);
	return Sidesr(p.x, p.y, d.x, d.y);
}

morda::Vec2r morda::dimVec2rFromSTOB(const stob::Node* chain){
	unsigned i;
	morda::Vec2r ret;

	float v = 0;
	for(i = 0; i != 2 && chain; ++i, chain = chain->next()){
		v = dimValueFromSTOB(*chain);
		ret[i] = v;
	}

	for(; i != 2; ++i){
		ret[i] = v;
	}

	return ret;
}

real morda::dimValueFromSTOB(const stob::Node& n){
	//check if millimeters
	if(n.length() >= 2 && n.value()[n.length() - 1] == 'm' && n.value()[n.length() - 2] == 'm'){
		return Morda::inst().units.mmToPx(n.asFloat());
	}else if(n.length() >= 2 && n.value()[n.length() - 1] == 't' && n.value()[n.length() - 2] == 'p'){ //check if in points
		return Morda::inst().units.ptToPx(n.asFloat());
	}

	return n.asFloat();
}

std::tuple<std::unique_ptr<stob::Node>, stob::Node*> morda::resolveIncludes(papki::File& fi, std::unique_ptr<stob::Node> begin){
	if(!begin){
		return std::make_tuple(nullptr, nullptr);
	}

	const char* DIncludeTag = "include";

	auto n = begin->thisOrNext(DIncludeTag);
	for(; n.node();){
		ASSERT(n.node())
		stob::Node* incPathNode = n.node()->child();
		if(!incPathNode){
			throw Exc("include tag without value encountered in resource script");
		}
		TRACE(<< "ResolveIncludes(): incPathNode->Value = " << incPathNode->value() << std::endl)

		fi.setPath(fi.dir() + incPathNode->value());
		std::unique_ptr<stob::Node> incNodes = stob::load(fi);

		//recursive call
		auto ri = resolveIncludes(fi, std::move(incNodes));

		stob::Node* lastChild = std::get<1>(ri);

		if(lastChild){
			//substitute includes
			if(!n.prev()){
				//include tag is the very first tag

				ASSERT(!lastChild->next())
				lastChild->insertNext(n.node()->chopNext());
				begin = std::move(std::get<0>(ri));
			}else{
				//include tag is not the first one

				n.prev()->removeNext();

				ASSERT(!lastChild->next())
				std::unique_ptr<stob::Node> tail = n.prev()->chopNext();
				n.prev()->setNext(std::move(std::get<0>(ri)));
				lastChild->setNext(std::move(tail));
			}
			n = lastChild->next(DIncludeTag);
		}else{
			n = n.node()->next(DIncludeTag);
		}
	}
	return std::make_tuple(std::move(begin), n.prev());
}

kolme::Vec2b morda::makeVec2bFromSTOB(const stob::Node* chain){
	unsigned i;
	kolme::Vec2b ret;

	bool v = false;
	for(i = 0; i != 2 && chain; ++i, chain = chain->next()){
		v = chain->asBool();
		ret[i] = v;
	}

	for(; i != 2; ++i){
		ret[i] = v;
	}

	return ret;
}

real morda::findDotsPerPt(kolme::Vec2ui resolution, kolme::Vec2ui screenSizeMm){

	//NOTE: for ordinary desktop displays the PT size should be equal to 1 pixel.
	//For high density displays it should be more than one pixel, depending on display ppi.
	//For handheld devices the size of PT should be determined from physical screen size and pixel resolution.

#if M_OS_NAME == M_OS_NAME_ANDROID
	return real(1);//TODO:
#elif M_OS_NAME == M_OS_NAME_IOS
	return real(1);//TODO:
#else
	return real(1);
#endif
}

float morda::dimValueFromLayoutStob(const stob::Node& n){
	if(n == "min"){
		return Widget::LayoutParams::min_c;
	}else if(n == "max"){
		return Widget::LayoutParams::max_c;
	}else if(n == "fill"){
		return Widget::LayoutParams::fill_c;
	}
	return dimValueFromSTOB(n);
}

const stob::Node* morda::getProperty(const stob::Node* chain, const char* property){
	if(!chain){
		return nullptr;
	}
	if(auto n = chain->thisOrNext(property).node()){
		return n->child();
	}
	return nullptr;
}

Texture2D morda::loadTexture(const papki::File& fi){
	Image image(fi);
//	TRACE(<< "ResTexture::Load(): image loaded" << std::endl)
	image.flipVertical();
	return Texture2D(image);
}

std::shared_ptr<Texture2D_n> morda::loadTexture_n(const papki::File& fi){
	Image image(fi);
//	TRACE(<< "ResTexture::Load(): image loaded" << std::endl)
	image.flipVertical();

	morda::Renderer::TexType_e tt;
	switch(image.numChannels()){
		case 1:
			tt = morda::Renderer::TexType_e::GREY;
			break;
		case 2:
			tt = morda::Renderer::TexType_e::GREYA;
			break;
		case 3:
			tt = morda::Renderer::TexType_e::RGB;
			break;
		case 4:
			tt = morda::Renderer::TexType_e::RGBA;
			break;
		default:
			ASSERT(false)
			break;
	}

	return morda::inst().renderer().createTexture2D(tt, image.dim(), image.buf());
}

void morda::applySimpleAlphaBlending(){
	Render::setBlendEnabled(true);
	Render::setBlendFunc(Render::BlendFactor_e::SRC_ALPHA, Render::BlendFactor_e::ONE_MINUS_SRC_ALPHA, Render::BlendFactor_e::ONE, Render::BlendFactor_e::ONE_MINUS_SRC_ALPHA);
}
<|endoftext|>


<commit_before>#include "trainer.h"
#include "common/timer.h"
#include "common/logger.h"
#include "common/thread_pool.h"
#include "common/random.hpp"
#include "optimize/opt_gd.hpp"
#include "optimize/opt_cgd.hpp"
#include "optimize/opt_lbfgs.hpp"
#include "sampler.h"
#include "accumulator.h"

namespace ncv
{
        /////////////////////////////////////////////////////////////////////////////////////////

        trainer_state_t::trainer_state_t(size_t n_parameters)
                :       m_params(n_parameters),
                        m_tvalue(std::numeric_limits<scalar_t>::max()),
                        m_terror(std::numeric_limits<scalar_t>::max()),
                        m_vvalue(std::numeric_limits<scalar_t>::max()),
                        m_verror(std::numeric_limits<scalar_t>::max()),
                        m_lambda(std::numeric_limits<scalar_t>::max()),
                        m_fcalls(0),
                        m_gcalls(0)
        {
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        bool trainer_state_t::update(const vector_t& params,
                    scalar_t tvalue, scalar_t terror,
                    scalar_t vvalue, scalar_t verror,
                    scalar_t lambda, size_t fcalls, size_t gcalls)
        {
                if (verror < m_verror)
                {
                        m_params = params;
                        m_tvalue = tvalue;
                        m_terror = terror;
                        m_vvalue = vvalue;
                        m_verror = verror;
                        m_lambda = lambda;
                        m_fcalls = fcalls;
                        m_gcalls = gcalls;
                        return true;
                }

                else
                {
                        return false;
                }
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        bool trainer_state_t::update(const trainer_state_t& state)
        {
                return update(state.m_params,
                              state.m_tvalue, state.m_terror, state.m_vvalue, state.m_verror,
                              state.m_lambda, state.m_fcalls, state.m_gcalls);
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        opt_state_t batch_train(
                const task_t& task, const samples_t& tsamples, const samples_t& vsamples, size_t nthreads,
                const loss_t& loss, batch_optimizer optimizer, size_t epochs, size_t iterations, scalar_t epsilon,
                const vector_t& x0, accumulator_t& ldata, accumulator_t& gdata, trainer_state_t& state)
        {
                size_t iteration = 0;

                // construct the optimization problem
                const timer_t timer;

                auto fn_size = [&] ()
                {
                        return ldata.dimensions();
                };

                auto fn_fval = [&] (const vector_t& x)
                {
                        // training samples: loss value
                        ldata.reset(x);
                        ldata.update(task, tsamples, loss, nthreads);
                        const scalar_t tvalue = ldata.value();

                        return tvalue;
                };

                auto fn_fval_grad = [&] (const vector_t& x, vector_t& gx)
                {
                        // training samples: loss value & gradient
                        gdata.reset(x);
                        gdata.update(task, tsamples, loss, nthreads);
                        const scalar_t tvalue = gdata.value();
                        gx = gdata.vgrad();

                        return tvalue;
                };

                auto fn_wlog = [] (const string_t& message)
                {
                        log_warning() << message;
                };
                auto fn_elog = [] (const string_t& message)
                {
                        log_error() << message;
                };
                auto fn_ulog = [&] (const opt_state_t& result, const timer_t& timer)
                {
                        ++ iteration;

                        if ((iteration % iterations) == 0)
                        {
                                const scalar_t tvalue = gdata.value();
                                const scalar_t terror = gdata.error();

                                // validation samples: loss value
                                ldata.reset(result.x);
                                ldata.update(task, vsamples, loss, nthreads);
                                const scalar_t vvalue = ldata.value();
                                const scalar_t verror = ldata.error();

                                // update the optimum state
                                state.update(result.x, tvalue, terror, vvalue, verror,
                                             ldata.lambda(), result.n_fval_calls(), result.n_grad_calls());

                                log_info() << "[train = " << tvalue << "/" << terror
                                           << ", valid = " << vvalue << "/" << verror
                                           << ", grad = " << result.g.lpNorm<Eigen::Infinity>()
                                           << ", funs = " << result.n_fval_calls() << "/" << result.n_grad_calls()
                                           << ", lambda = " << ldata.lambda()
                                           << "] done in " << timer.elapsed() << ".";
                        }
                };

                // assembly optimization problem & optimize the model
                const opt_problem_t problem(fn_size, fn_fval, fn_fval_grad);

                const opt_opulog_t fn_ulog_ref = std::bind(fn_ulog, _1, std::ref(timer));

                switch (optimizer)
                {
                case batch_optimizer::LBFGS:
                        return optimize::lbfgs(problem, x0, epochs * iterations, epsilon,
                                               fn_wlog, fn_elog, fn_ulog_ref);

                case batch_optimizer::CGD:
                        return optimize::cgd_hs(problem, x0, epochs * iterations, epsilon,
                                                fn_wlog, fn_elog, fn_ulog_ref);

                case batch_optimizer::GD:
                default:
                        return optimize::gd(problem, x0, epochs * iterations, epsilon,
                                            fn_wlog, fn_elog, fn_ulog_ref);
                }
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        namespace detail
        {
                struct rnd_t
                {
                        rnd_t(random_t<size_t>& gen)
                                :       m_gen(gen)
                        {
                        }

                        size_t operator()(size_t i)
                        {
                                return m_gen() % i;
                        }

                        random_t<size_t>&  m_gen;
                };

                static void stochastic_train(
                        const task_t& task, const samples_t& tsamples_, const samples_t& vsamples, const loss_t& loss,
                        stochastic_optimizer type, size_t epochs, scalar_t alpha0, scalar_t beta,
                        const vector_t& x0, accumulator_t& ldata, accumulator_t& gdata, trainer_state_t& state,
                        thread_pool_t::mutex_t& mutex)
                {
                        samples_t tsamples = tsamples_;

                        random_t<size_t> xrng(0, tsamples.size());
                        rnd_t xrnd(xrng);

                        timer_t timer;

                        vector_t x = x0;
                        vector_t xparam = x;

                        vector_t xavg = x;
                        vector_t gavg(x.size());
                        gavg.setZero();

                        scalar_t alpha = alpha0;
                        scalar_t sumb = 1.0 / alpha;

                        for (size_t e = 0; e < epochs; e ++)
                        {
                                std::random_shuffle(tsamples.begin(), tsamples.end(), xrnd);

                                // one epoch: a pass through all training samples
                                switch (type)
                                {
                                case stochastic_optimizer::SG:
                                        for (size_t i = 0; i < tsamples.size(); i ++, alpha *= beta)
                                        {
                                                gdata.reset(x);
                                                gdata.update(task, tsamples[i], loss);

                                                x.noalias() -= alpha * gdata.vgrad();
                                        }
                                        xparam = x;
                                        break;

                                case stochastic_optimizer::SGA:
                                        for (size_t i = 0; i < tsamples.size(); i ++, alpha *= beta)
                                        {
                                                gdata.reset(x);
                                                gdata.update(task, tsamples[i], loss);

                                                const vector_t g = gdata.vgrad();

                                                const scalar_t b = 1.0 / alpha;
                                                gavg = (gavg * sumb + g * b) / (sumb + b);
                                                sumb = sumb + b;

                                                x.noalias() -= alpha * gavg;
                                        }
                                        xparam = xavg;
                                        break;

                                case stochastic_optimizer::SIA:
                                default:
                                        for (size_t i = 0; i < tsamples.size(); i ++, alpha *= beta)
                                        {
                                                gdata.reset(x);
                                                gdata.update(task, tsamples[i], loss);

                                                x.noalias() -= alpha * gdata.vgrad();

                                                const scalar_t b = 1.0 / alpha;
                                                xavg = (xavg * sumb + x * b) / (sumb + b);
                                                sumb = sumb + b;
                                        }
                                        xparam = x;
                                        break;
                                }

                                // evaluate training samples
                                ldata.reset(xparam);
                                ldata.update(task, tsamples, loss);
                                const scalar_t tvalue = ldata.value();
                                const scalar_t terror = ldata.error();

                                // evaluate validation samples
                                ldata.reset(xparam);
                                ldata.update(task, vsamples, loss);
                                const scalar_t vvalue = ldata.value();
                                const scalar_t verror = ldata.error();

                                // OK, update the optimum solution
                                const thread_pool_t::lock_t lock(mutex);

                                if (state.update(xparam, tvalue, terror, vvalue, verror,
                                                 ldata.lambda(), e * tsamples.size(), e * tsamples.size()))
                                {
                                        log_info()
                                        << "[train = " << tvalue << "/" << terror
                                        << ", valid = " << vvalue << "/" << verror
                                        << ", rate = " << alpha << "/" << alpha0
                                        << ", epoch = " << e << "/" << epochs
                                        << ", lambda = " << ldata.lambda()
                                        << "] done in " << timer.elapsed() << ".";
                                }
                        }
                }
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        opt_state_t stochastic_train(
                const task_t& task, const samples_t& tsamples, const samples_t& vsamples, size_t nthreads,
                const loss_t& loss, stochastic_optimizer optimizer, size_t epochs,
                const vector_t& x0, accumulator_t& ldata, accumulator_t& gdata, trainer_state_t& state)
        {
                // prepare workers
                thread_pool_t wpool(nthreads);
                thread_pool_t::mutex_t mutex;

                // tune the learning rate
                const scalar_t max_alpha = 1e-1;
                const scalar_t min_alpha = 1e-3;
                const scalar_t var_alpha = std::exp((std::log(max_alpha) - std::log(min_alpha))
                                           / std::min(size_t(8), wpool.n_workers()));

                const size_t iterations = epochs * tsamples.size();             // SGD iterations
                const scalar_t beta = std::pow(0.01, 1.0 / iterations);         // Learning rate decay rate

                for (scalar_t alpha0 = min_alpha; alpha0 <= max_alpha; alpha0 *= var_alpha)
                {
                        wpool.enqueue([=, &task, &tsamples, &vsamples, &loss, &x0, &ldata, &gdata, &state, &mutex]()
                        {
                                detail::stochastic_train(
                                        task, tsamples, vsamples, loss,
                                        optimizer, epochs, alpha0, beta,
                                        x0, ldata, gdata, state, mutex);
                        });
                }

                wpool.wait();

                // OK
                opt_state_t result(x0.size());
                result.x = state.m_params;
                result.f = state.m_tvalue;
                return result;
        }

        /////////////////////////////////////////////////////////////////////////////////////////
}

<commit_msg>log after each epoch<commit_after>#include "trainer.h"
#include "common/timer.h"
#include "common/logger.h"
#include "common/thread_pool.h"
#include "common/random.hpp"
#include "optimize/opt_gd.hpp"
#include "optimize/opt_cgd.hpp"
#include "optimize/opt_lbfgs.hpp"
#include "sampler.h"
#include "accumulator.h"

namespace ncv
{
        /////////////////////////////////////////////////////////////////////////////////////////

        trainer_state_t::trainer_state_t(size_t n_parameters)
                :       m_params(n_parameters),
                        m_tvalue(std::numeric_limits<scalar_t>::max()),
                        m_terror(std::numeric_limits<scalar_t>::max()),
                        m_vvalue(std::numeric_limits<scalar_t>::max()),
                        m_verror(std::numeric_limits<scalar_t>::max()),
                        m_lambda(std::numeric_limits<scalar_t>::max()),
                        m_fcalls(0),
                        m_gcalls(0)
        {
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        bool trainer_state_t::update(const vector_t& params,
                    scalar_t tvalue, scalar_t terror,
                    scalar_t vvalue, scalar_t verror,
                    scalar_t lambda, size_t fcalls, size_t gcalls)
        {
                if (verror < m_verror)
                {
                        m_params = params;
                        m_tvalue = tvalue;
                        m_terror = terror;
                        m_vvalue = vvalue;
                        m_verror = verror;
                        m_lambda = lambda;
                        m_fcalls = fcalls;
                        m_gcalls = gcalls;
                        return true;
                }

                else
                {
                        return false;
                }
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        bool trainer_state_t::update(const trainer_state_t& state)
        {
                return update(state.m_params,
                              state.m_tvalue, state.m_terror, state.m_vvalue, state.m_verror,
                              state.m_lambda, state.m_fcalls, state.m_gcalls);
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        opt_state_t batch_train(
                const task_t& task, const samples_t& tsamples, const samples_t& vsamples, size_t nthreads,
                const loss_t& loss, batch_optimizer optimizer, size_t epochs, size_t iterations, scalar_t epsilon,
                const vector_t& x0, accumulator_t& ldata, accumulator_t& gdata, trainer_state_t& state)
        {
                size_t iteration = 0;

                // construct the optimization problem
                const timer_t timer;

                auto fn_size = [&] ()
                {
                        return ldata.dimensions();
                };

                auto fn_fval = [&] (const vector_t& x)
                {
                        // training samples: loss value
                        ldata.reset(x);
                        ldata.update(task, tsamples, loss, nthreads);
                        const scalar_t tvalue = ldata.value();

                        return tvalue;
                };

                auto fn_fval_grad = [&] (const vector_t& x, vector_t& gx)
                {
                        // training samples: loss value & gradient
                        gdata.reset(x);
                        gdata.update(task, tsamples, loss, nthreads);
                        const scalar_t tvalue = gdata.value();
                        gx = gdata.vgrad();

                        return tvalue;
                };

                auto fn_wlog = [] (const string_t& message)
                {
                        log_warning() << message;
                };
                auto fn_elog = [] (const string_t& message)
                {
                        log_error() << message;
                };
                auto fn_ulog = [&] (const opt_state_t& result, const timer_t& timer)
                {
                        ++ iteration;

                        if ((iteration % iterations) == 0)
                        {
                                const scalar_t tvalue = gdata.value();
                                const scalar_t terror = gdata.error();

                                // validation samples: loss value
                                ldata.reset(result.x);
                                ldata.update(task, vsamples, loss, nthreads);
                                const scalar_t vvalue = ldata.value();
                                const scalar_t verror = ldata.error();

                                // update the optimum state
                                state.update(result.x, tvalue, terror, vvalue, verror,
                                             ldata.lambda(), result.n_fval_calls(), result.n_grad_calls());

                                log_info() << "[train = " << tvalue << "/" << terror
                                           << ", valid = " << vvalue << "/" << verror
                                           << ", grad = " << result.g.lpNorm<Eigen::Infinity>()
                                           << ", funs = " << result.n_fval_calls() << "/" << result.n_grad_calls()
                                           << ", lambda = " << ldata.lambda()
                                           << "] done in " << timer.elapsed() << ".";
                        }
                };

                // assembly optimization problem & optimize the model
                const opt_problem_t problem(fn_size, fn_fval, fn_fval_grad);

                const opt_opulog_t fn_ulog_ref = std::bind(fn_ulog, _1, std::ref(timer));

                switch (optimizer)
                {
                case batch_optimizer::LBFGS:
                        return optimize::lbfgs(problem, x0, epochs * iterations, epsilon,
                                               fn_wlog, fn_elog, fn_ulog_ref);

                case batch_optimizer::CGD:
                        return optimize::cgd_hs(problem, x0, epochs * iterations, epsilon,
                                                fn_wlog, fn_elog, fn_ulog_ref);

                case batch_optimizer::GD:
                default:
                        return optimize::gd(problem, x0, epochs * iterations, epsilon,
                                            fn_wlog, fn_elog, fn_ulog_ref);
                }
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        namespace detail
        {
                struct rnd_t
                {
                        rnd_t(random_t<size_t>& gen)
                                :       m_gen(gen)
                        {
                        }

                        size_t operator()(size_t i)
                        {
                                return m_gen() % i;
                        }

                        random_t<size_t>&  m_gen;
                };

                static void stochastic_train(
                        const task_t& task, const samples_t& tsamples_, const samples_t& vsamples, const loss_t& loss,
                        stochastic_optimizer type, size_t epochs, scalar_t alpha0, scalar_t beta,
                        const vector_t& x0, accumulator_t& ldata, accumulator_t& gdata, trainer_state_t& state,
                        thread_pool_t::mutex_t& mutex)
                {
                        samples_t tsamples = tsamples_;

                        random_t<size_t> xrng(0, tsamples.size());
                        rnd_t xrnd(xrng);

                        timer_t timer;

                        vector_t x = x0;
                        vector_t xparam = x;

                        vector_t xavg = x;
                        vector_t gavg(x.size());
                        gavg.setZero();

                        scalar_t alpha = alpha0;
                        scalar_t sumb = 1.0 / alpha;

                        for (size_t e = 0; e < epochs; e ++)
                        {
                                std::random_shuffle(tsamples.begin(), tsamples.end(), xrnd);

                                // one epoch: a pass through all training samples
                                switch (type)
                                {
                                case stochastic_optimizer::SG:
                                        for (size_t i = 0; i < tsamples.size(); i ++, alpha *= beta)
                                        {
                                                gdata.reset(x);
                                                gdata.update(task, tsamples[i], loss);

                                                x.noalias() -= alpha * gdata.vgrad();
                                        }
                                        xparam = x;
                                        break;

                                case stochastic_optimizer::SGA:
                                        for (size_t i = 0; i < tsamples.size(); i ++, alpha *= beta)
                                        {
                                                gdata.reset(x);
                                                gdata.update(task, tsamples[i], loss);

                                                const vector_t g = gdata.vgrad();

                                                const scalar_t b = 1.0 / alpha;
                                                gavg = (gavg * sumb + g * b) / (sumb + b);
                                                sumb = sumb + b;

                                                x.noalias() -= alpha * gavg;
                                        }
                                        xparam = xavg;
                                        break;

                                case stochastic_optimizer::SIA:
                                default:
                                        for (size_t i = 0; i < tsamples.size(); i ++, alpha *= beta)
                                        {
                                                gdata.reset(x);
                                                gdata.update(task, tsamples[i], loss);

                                                x.noalias() -= alpha * gdata.vgrad();

                                                const scalar_t b = 1.0 / alpha;
                                                xavg = (xavg * sumb + x * b) / (sumb + b);
                                                sumb = sumb + b;
                                        }
                                        xparam = x;
                                        break;
                                }

                                // evaluate training samples
                                ldata.reset(xparam);
                                ldata.update(task, tsamples, loss);
                                const scalar_t tvalue = ldata.value();
                                const scalar_t terror = ldata.error();

                                // evaluate validation samples
                                ldata.reset(xparam);
                                ldata.update(task, vsamples, loss);
                                const scalar_t vvalue = ldata.value();
                                const scalar_t verror = ldata.error();

                                // OK, update the optimum solution
                                const thread_pool_t::lock_t lock(mutex);

                                state.update(xparam, tvalue, terror, vvalue, verror,
                                             ldata.lambda(), e * tsamples.size(), e * tsamples.size());

                                log_info()
                                        << "[train = " << tvalue << "/" << terror
                                        << ", valid = " << vvalue << "/" << verror
                                        << ", rate = " << alpha << "/" << alpha0
                                        << ", epoch = " << e << "/" << epochs
                                        << ", lambda = " << ldata.lambda()
                                        << "] done in " << timer.elapsed() << ".";
                        }
                }
        }

        /////////////////////////////////////////////////////////////////////////////////////////

        opt_state_t stochastic_train(
                const task_t& task, const samples_t& tsamples, const samples_t& vsamples, size_t nthreads,
                const loss_t& loss, stochastic_optimizer optimizer, size_t epochs,
                const vector_t& x0, accumulator_t& ldata, accumulator_t& gdata, trainer_state_t& state)
        {
                // prepare workers
                thread_pool_t wpool(nthreads);
                thread_pool_t::mutex_t mutex;

                // tune the learning rate
                const scalar_t max_alpha = 1e-1;
                const scalar_t min_alpha = 1e-3;
                const scalar_t var_alpha = std::exp((std::log(max_alpha) - std::log(min_alpha))
                                           / std::min(size_t(8), wpool.n_workers()));

                const size_t iterations = epochs * tsamples.size();             // SGD iterations
                const scalar_t beta = std::pow(0.01, 1.0 / iterations);         // Learning rate decay rate

                for (scalar_t alpha0 = min_alpha; alpha0 <= max_alpha; alpha0 *= var_alpha)
                {
                        wpool.enqueue([=, &task, &tsamples, &vsamples, &loss, &x0, &ldata, &gdata, &state, &mutex]()
                        {
                                detail::stochastic_train(
                                        task, tsamples, vsamples, loss,
                                        optimizer, epochs, alpha0, beta,
                                        x0, ldata, gdata, state, mutex);
                        });
                }

                wpool.wait();

                // OK
                opt_state_t result(x0.size());
                result.x = state.m_params;
                result.f = state.m_tvalue;
                return result;
        }

        /////////////////////////////////////////////////////////////////////////////////////////
}

<|endoftext|>


<commit_before>#include "..\header\int\Level.h"
#include "..\header\int\Component.h"
#include "..\header\int\Texture.h"

float Level::FindHeight(const Vector3& position) const{
	Vector3 localPos = transform.GlobalToLocal(position);

	Vector2 gridPos = Vector2(localPos.x, localPos.z);

	float currHeight = localPos.y;
	int currDepth = INT_MIN;
	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		if(iter->depth > currDepth && BoundsContains(gridPos, iter->ulCorner, iter->brCorner)){
			currDepth = iter->depth;
			currHeight = iter->floorHeight;
		}
	}

	localPos.y = currHeight;
	return localPos.y;
}

//Is pt contained in the AABB formed by ul (upper left) and br (bottom right)
bool BoundsContains(const Vector2& pt, const Vector2& ul, const Vector2& br){
	return pt.x > ul.x && pt.y > ul.y
		&& pt.x < br.x && pt.y < br.y;
}

Vector3 Level::ResolveCollisions(const Vector3& from, const Vector3& to) const{
	Vector3 localFrom = transform.GlobalToLocal(from);
	Vector3 localTo   = transform.GlobalToLocal(to);

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Vector3 edge1 = Vector3(iter->start.x, iter->height, iter->start.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 edge2 = Vector3(iter->end.x, 0, iter->end.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 normal = CrossProduct(edge1, edge2).Normalized();

		float toDist = DotProduct(localTo - Vector3(iter->start.x, 0, iter->start.y), normal);
		//cout << "ToDist: " << toDist << "  FromDist: " << fromDist << endl;
		if(toDist > -0.1f && toDist < 0.1f){
			Vector2 floorProjection = Vector2(localFrom.x, localFrom.z);
			Vector2 wallDiff = floorProjection - iter->start;
			Vector2 wallVec = (iter->end - iter->start);
			float overlap = DotProduct(wallDiff, wallVec);

			if(overlap < (iter->end - iter->start).MagnitudeSquared() && overlap > 0){
				Vector3 collisionPlane = Vector3(iter->start.x, 0, iter->start.y) + normal * (toDist > 0 ? 0.1f : -0.1f);
				Vector3 toProject = localTo - collisionPlane;
				Vector3 projection = VectorProject(toProject, normal);
				Vector3 result = (toProject - projection) + collisionPlane;

				localTo = result;
			}
		}
	}

	return localTo;
}

void Level::SetRenderingCompMesh(RenderingComp& rend, const string& texture){
	rend.entity = -1;

	vector<Vector3> verts;
	vector<Vector2> uvs;

	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		Floor floor = *iter;
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.brCorner.y));

		uvs.push_back(Vector2(0,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Wall wall = *iter;

		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.start.x, wall.height, wall.start.y));
		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));

		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));
		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.end.x,   0,           wall.end.y));

		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	rend.vertCount = verts.size();

	glGenBuffers(1, &rend.verticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.verticesVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3)*verts.size(), &(verts[0]), GL_STATIC_DRAW);

	glGenBuffers(1, &rend.uvsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.uvsVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2)*uvs.size(), &(uvs[0]), GL_STATIC_DRAW);

	rend.texObject = new Texture(GL_TEXTURE_2D, texture);
	rend.texObject->Load();
	rend.texture = rend.texObject->textureObj;

	string shader = "data/shader";
	string vertShader;
	string fragShader;
	if(! (ReadFile(shader + ".vs", vertShader) && ReadFile(shader + ".fs", fragShader))){
		cout << "Error reading files: " << shader << ".vs and " << shader << ".fs" << endl;
		return;
	}

	rend.shaderProgram = glCreateProgram();
	AddShader(rend.shaderProgram, vertShader.c_str(), GL_VERTEX_SHADER);
	AddShader(rend.shaderProgram, fragShader.c_str(), GL_FRAGMENT_SHADER);

	glLinkProgram(rend.shaderProgram);

	GLint Success;
	glGetProgramiv(rend.shaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		char ErrorLog[1024];
		glGetProgramInfoLog(rend.shaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
	}

	glValidateProgram(rend.shaderProgram);
}

<commit_msg>Walls can now be jumped over.<commit_after>#include "..\header\int\Level.h"
#include "..\header\int\Component.h"
#include "..\header\int\Texture.h"

float Level::FindHeight(const Vector3& position) const{
	Vector3 localPos = transform.GlobalToLocal(position);

	Vector2 gridPos = Vector2(localPos.x, localPos.z);

	float currHeight = localPos.y;
	int currDepth = INT_MIN;
	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		if(iter->depth > currDepth && BoundsContains(gridPos, iter->ulCorner, iter->brCorner)){
			currDepth = iter->depth;
			currHeight = iter->floorHeight;
		}
	}

	localPos.y = currHeight;
	return localPos.y;
}

//Is pt contained in the AABB formed by ul (upper left) and br (bottom right)
bool BoundsContains(const Vector2& pt, const Vector2& ul, const Vector2& br){
	return pt.x > ul.x && pt.y > ul.y
		&& pt.x < br.x && pt.y < br.y;
}

Vector3 Level::ResolveCollisions(const Vector3& from, const Vector3& to) const{
	Vector3 localFrom = transform.GlobalToLocal(from);
	Vector3 localTo   = transform.GlobalToLocal(to);

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Vector3 edge1 = Vector3(iter->start.x, iter->height, iter->start.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 edge2 = Vector3(iter->end.x, 0, iter->end.y) - Vector3(iter->start.x, 0, iter->start.y);
		Vector3 normal = CrossProduct(edge1, edge2).Normalized();

		float toDist = DotProduct(localTo - Vector3(iter->start.x, 0, iter->start.y), normal);
		//cout << "ToDist: " << toDist << "  FromDist: " << fromDist << endl;
		if(toDist > -0.1f && toDist < 0.1f){
			Vector2 floorProjection = Vector2(localFrom.x, localFrom.z);
			Vector2 wallDiff = floorProjection - iter->start;
			Vector2 wallVec = (iter->end - iter->start);
			float overlap = DotProduct(wallDiff, wallVec);

			if(overlap < (iter->end - iter->start).MagnitudeSquared() && overlap > 0 && localFrom.y <= iter->height + /*player height*/0.1f){
				Vector3 collisionPlane = Vector3(iter->start.x, 0, iter->start.y) + normal * (toDist > 0 ? 0.1f : -0.1f);
				Vector3 toProject = localTo - collisionPlane;
				Vector3 projection = VectorProject(toProject, normal);
				Vector3 result = (toProject - projection) + collisionPlane;

				localTo = result;
			}
		}
	}

	return localTo;
}

void Level::SetRenderingCompMesh(RenderingComp& rend, const string& texture){
	rend.entity = -1;

	vector<Vector3> verts;
	vector<Vector2> uvs;

	for(auto iter = floors.begin(); iter != floors.end(); iter++){
		Floor floor = *iter;
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.ulCorner.x, floor.floorHeight, floor.brCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.ulCorner.y));
		verts.push_back(Vector3(floor.brCorner.x, floor.floorHeight, floor.brCorner.y));

		uvs.push_back(Vector2(0,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	for(auto iter = walls.begin(); iter != walls.end(); iter++){
		Wall wall = *iter;

		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.start.x, wall.height, wall.start.y));
		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));

		verts.push_back(Vector3(wall.end.x,   wall.height, wall.end.y));
		verts.push_back(Vector3(wall.start.x, 0,           wall.start.y));
		verts.push_back(Vector3(wall.end.x,   0,           wall.end.y));

		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(1,0));
		uvs.push_back(Vector2(0,1));
		uvs.push_back(Vector2(1,1));
	}

	rend.vertCount = verts.size();

	glGenBuffers(1, &rend.verticesVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.verticesVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3)*verts.size(), &(verts[0]), GL_STATIC_DRAW);

	glGenBuffers(1, &rend.uvsVBO);
	glBindBuffer(GL_ARRAY_BUFFER, rend.uvsVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2)*uvs.size(), &(uvs[0]), GL_STATIC_DRAW);

	rend.texObject = new Texture(GL_TEXTURE_2D, texture);
	rend.texObject->Load();
	rend.texture = rend.texObject->textureObj;

	string shader = "data/shader";
	string vertShader;
	string fragShader;
	if(! (ReadFile(shader + ".vs", vertShader) && ReadFile(shader + ".fs", fragShader))){
		cout << "Error reading files: " << shader << ".vs and " << shader << ".fs" << endl;
		return;
	}

	rend.shaderProgram = glCreateProgram();
	AddShader(rend.shaderProgram, vertShader.c_str(), GL_VERTEX_SHADER);
	AddShader(rend.shaderProgram, fragShader.c_str(), GL_FRAGMENT_SHADER);

	glLinkProgram(rend.shaderProgram);

	GLint Success;
	glGetProgramiv(rend.shaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		char ErrorLog[1024];
		glGetProgramInfoLog(rend.shaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
	}

	glValidateProgram(rend.shaderProgram);
}

<|endoftext|>


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

/**
 * stream_input_descriptor_response_imp.cpp
 *
 * STREAM INPUT descriptor response implementation
 */

#include <vector>
#include "util.h"
#include "avdecc_error.h"
#include "enumeration.h"
#include "log_imp.h"
#include "adp.h"
#include "end_station_imp.h"
#include "system_tx_queue.h"
#include "acmp_controller_state_machine.h"
#include "aecp_controller_state_machine.h"
#include "stream_input_descriptor_response_imp.h"

namespace avdecc_lib
{
stream_input_descriptor_response_imp::stream_input_descriptor_response_imp(const uint8_t * frame, size_t frame_len, ssize_t pos) : descriptor_response_base_imp(frame, frame_len, pos)
{
    memset(&stream_input_flags, 0, sizeof(struct stream_input_desc_stream_flags));
    stream_flags_init();
    store_supported_stream_fmts();
}

stream_input_descriptor_response_imp::~stream_input_descriptor_response_imp() {}

void stream_input_descriptor_response_imp::stream_flags_init()
{
    stream_input_flags.clock_sync_source = stream_flags() & 0x01;
    stream_input_flags.class_a = stream_flags() >> 1 & 0x01;
    stream_input_flags.class_b = stream_flags() >> 2 & 0x01;
    stream_input_flags.supports_encrypted = stream_flags() >> 3 & 0x01;
    stream_input_flags.primary_backup_supported = stream_flags() >> 4 & 0x01;
    stream_input_flags.primary_backup_valid = stream_flags() >> 5 & 0x01;
    stream_input_flags.secondary_backup_supported = stream_flags() >> 6 & 0x01;
    stream_input_flags.secondary_backup_valid = stream_flags() >> 7 & 0x01;
    stream_input_flags.tertiary_backup_supported = stream_flags() >> 8 & 0x01;
    stream_input_flags.tertiary_backup_valid = stream_flags() >> 9 & 0x01;
}

uint8_t * STDCALL stream_input_descriptor_response_imp::object_name()
{
    return (uint8_t *)&buffer[position + JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_OBJECT_NAME];
}

uint16_t STDCALL stream_input_descriptor_response_imp::localized_description()
{
    return jdksavdecc_descriptor_stream_get_localized_description(buffer, position);
}

uint16_t STDCALL stream_input_descriptor_response_imp::clock_domain_index()
{
    return jdksavdecc_descriptor_stream_get_clock_domain_index(buffer, position);
}

uint16_t stream_input_descriptor_response_imp::stream_flags()
{
    return jdksavdecc_descriptor_stream_get_stream_flags(buffer, position);
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_clock_sync_source()
{
    return stream_input_flags.clock_sync_source;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_class_a()
{
    return stream_input_flags.class_a;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_class_b()
{
    return stream_input_flags.class_b;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_supports_encrypted()
{
    return stream_input_flags.supports_encrypted;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_primary_backup_supported()
{
    return stream_input_flags.primary_backup_supported;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_primary_backup_valid()
{
    return stream_input_flags.primary_backup_valid;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_secondary_backup_supported()
{
    return stream_input_flags.secondary_backup_supported;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_secondary_backup_valid()
{
    return stream_input_flags.secondary_backup_valid;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_tertiary_backup_supported()
{
    return stream_input_flags.tertiary_backup_supported;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_tertiary_backup_valid()
{
    return stream_input_flags.tertiary_backup_valid;
}

const char * STDCALL stream_input_descriptor_response_imp::current_format_name()
{
    uint64_t current_format;
    current_format = jdksavdecc_uint64_get(&buffer[position +
                                                   JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_CURRENT_FORMAT],
                                           0);
    return utility::ieee1722_format_value_to_name(current_format);
}

uint64_t STDCALL stream_input_descriptor_response_imp::current_format_value()
{
    uint64_t current_format;
    return current_format = jdksavdecc_uint64_get(&buffer[position +
                                                          JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_CURRENT_FORMAT],
                                                  0);
}

uint16_t stream_input_descriptor_response_imp::formats_offset()
{
    assert(jdksavdecc_descriptor_stream_get_formats_offset(buffer, position) == 132);
    return jdksavdecc_descriptor_stream_get_formats_offset(buffer, position);
}

uint16_t STDCALL stream_input_descriptor_response_imp::number_of_formats()
{
    return jdksavdecc_descriptor_stream_get_number_of_formats(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backup_talker_entity_id_0()
{
    uint64_t backup_talker_entity_id_0;
    return backup_talker_entity_id_0 = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKUP_TALKER_ENTITY_ID_0],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backup_talker_unique_0()
{
    return jdksavdecc_descriptor_stream_get_backup_talker_unique_id_0(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backup_talker_entity_id_1()
{
    uint64_t backup_talker_entity_id_1;
    return backup_talker_entity_id_1 = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKUP_TALKER_ENTITY_ID_1],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backup_talker_unique_1()
{
    return jdksavdecc_descriptor_stream_get_backup_talker_unique_id_1(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backup_talker_entity_id_2()
{
    uint64_t backup_talker_entity_id_2;
    return backup_talker_entity_id_2 = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKUP_TALKER_ENTITY_ID_2],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backup_talker_unique_2()
{
    return jdksavdecc_descriptor_stream_get_backup_talker_unique_id_2(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backedup_talker_entity_id()
{
    uint64_t backedup_talker_entity_id;
    return backedup_talker_entity_id = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKEDUP_TALKER_ENTITY_ID],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backedup_talker_unique()
{
    return jdksavdecc_descriptor_stream_get_backedup_talker_unique(buffer, position);
}

uint16_t STDCALL stream_input_descriptor_response_imp::avb_interface_index()
{
    return jdksavdecc_descriptor_stream_get_avb_interface_index(buffer, position);
}

uint32_t STDCALL stream_input_descriptor_response_imp::buffer_length()
{
    return jdksavdecc_descriptor_stream_get_buffer_length(buffer, position);
}

void stream_input_descriptor_response_imp::store_supported_stream_fmts()
{
    uint64_t offset = 0;
    for (int i = 0; i < number_of_formats(); i++)
    {
        stream_fmts_vec.push_back(jdksavdecc_uint64_get(&buffer[position + formats_offset() + offset], 0));
        offset += 0x8;
    }
}

uint64_t STDCALL stream_input_descriptor_response_imp::get_supported_stream_fmt_by_index(size_t supported_stream_fmt_index)
{
    return stream_fmts_vec.at(supported_stream_fmt_index);
}
}
<commit_msg>milan uses 136 for formats offset; just assert if it's not zero to support milan and possible future format offset values<commit_after>/*
 * Licensed under the MIT License (MIT)
 *
 * Copyright (c) 2013 AudioScience Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * stream_input_descriptor_response_imp.cpp
 *
 * STREAM INPUT descriptor response implementation
 */

#include <vector>
#include "util.h"
#include "avdecc_error.h"
#include "enumeration.h"
#include "log_imp.h"
#include "adp.h"
#include "end_station_imp.h"
#include "system_tx_queue.h"
#include "acmp_controller_state_machine.h"
#include "aecp_controller_state_machine.h"
#include "stream_input_descriptor_response_imp.h"

namespace avdecc_lib
{
stream_input_descriptor_response_imp::stream_input_descriptor_response_imp(const uint8_t * frame, size_t frame_len, ssize_t pos) : descriptor_response_base_imp(frame, frame_len, pos)
{
    memset(&stream_input_flags, 0, sizeof(struct stream_input_desc_stream_flags));
    stream_flags_init();
    store_supported_stream_fmts();
}

stream_input_descriptor_response_imp::~stream_input_descriptor_response_imp() {}

void stream_input_descriptor_response_imp::stream_flags_init()
{
    stream_input_flags.clock_sync_source = stream_flags() & 0x01;
    stream_input_flags.class_a = stream_flags() >> 1 & 0x01;
    stream_input_flags.class_b = stream_flags() >> 2 & 0x01;
    stream_input_flags.supports_encrypted = stream_flags() >> 3 & 0x01;
    stream_input_flags.primary_backup_supported = stream_flags() >> 4 & 0x01;
    stream_input_flags.primary_backup_valid = stream_flags() >> 5 & 0x01;
    stream_input_flags.secondary_backup_supported = stream_flags() >> 6 & 0x01;
    stream_input_flags.secondary_backup_valid = stream_flags() >> 7 & 0x01;
    stream_input_flags.tertiary_backup_supported = stream_flags() >> 8 & 0x01;
    stream_input_flags.tertiary_backup_valid = stream_flags() >> 9 & 0x01;
}

uint8_t * STDCALL stream_input_descriptor_response_imp::object_name()
{
    return (uint8_t *)&buffer[position + JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_OBJECT_NAME];
}

uint16_t STDCALL stream_input_descriptor_response_imp::localized_description()
{
    return jdksavdecc_descriptor_stream_get_localized_description(buffer, position);
}

uint16_t STDCALL stream_input_descriptor_response_imp::clock_domain_index()
{
    return jdksavdecc_descriptor_stream_get_clock_domain_index(buffer, position);
}

uint16_t stream_input_descriptor_response_imp::stream_flags()
{
    return jdksavdecc_descriptor_stream_get_stream_flags(buffer, position);
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_clock_sync_source()
{
    return stream_input_flags.clock_sync_source;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_class_a()
{
    return stream_input_flags.class_a;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_class_b()
{
    return stream_input_flags.class_b;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_supports_encrypted()
{
    return stream_input_flags.supports_encrypted;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_primary_backup_supported()
{
    return stream_input_flags.primary_backup_supported;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_primary_backup_valid()
{
    return stream_input_flags.primary_backup_valid;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_secondary_backup_supported()
{
    return stream_input_flags.secondary_backup_supported;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_secondary_backup_valid()
{
    return stream_input_flags.secondary_backup_valid;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_tertiary_backup_supported()
{
    return stream_input_flags.tertiary_backup_supported;
}

bool STDCALL stream_input_descriptor_response_imp::stream_flags_tertiary_backup_valid()
{
    return stream_input_flags.tertiary_backup_valid;
}

const char * STDCALL stream_input_descriptor_response_imp::current_format_name()
{
    uint64_t current_format;
    current_format = jdksavdecc_uint64_get(&buffer[position +
                                                   JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_CURRENT_FORMAT],
                                           0);
    return utility::ieee1722_format_value_to_name(current_format);
}

uint64_t STDCALL stream_input_descriptor_response_imp::current_format_value()
{
    uint64_t current_format;
    return current_format = jdksavdecc_uint64_get(&buffer[position +
                                                          JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_CURRENT_FORMAT],
                                                  0);
}

uint16_t stream_input_descriptor_response_imp::formats_offset()
{
    assert(jdksavdecc_descriptor_stream_get_formats_offset(buffer, position));
    return jdksavdecc_descriptor_stream_get_formats_offset(buffer, position);
}

uint16_t STDCALL stream_input_descriptor_response_imp::number_of_formats()
{
    return jdksavdecc_descriptor_stream_get_number_of_formats(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backup_talker_entity_id_0()
{
    uint64_t backup_talker_entity_id_0;
    return backup_talker_entity_id_0 = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKUP_TALKER_ENTITY_ID_0],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backup_talker_unique_0()
{
    return jdksavdecc_descriptor_stream_get_backup_talker_unique_id_0(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backup_talker_entity_id_1()
{
    uint64_t backup_talker_entity_id_1;
    return backup_talker_entity_id_1 = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKUP_TALKER_ENTITY_ID_1],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backup_talker_unique_1()
{
    return jdksavdecc_descriptor_stream_get_backup_talker_unique_id_1(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backup_talker_entity_id_2()
{
    uint64_t backup_talker_entity_id_2;
    return backup_talker_entity_id_2 = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKUP_TALKER_ENTITY_ID_2],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backup_talker_unique_2()
{
    return jdksavdecc_descriptor_stream_get_backup_talker_unique_id_2(buffer, position);
}

uint64_t STDCALL stream_input_descriptor_response_imp::backedup_talker_entity_id()
{
    uint64_t backedup_talker_entity_id;
    return backedup_talker_entity_id = jdksavdecc_uint64_get(&buffer[position +
                                                                     JDKSAVDECC_DESCRIPTOR_STREAM_OFFSET_BACKEDUP_TALKER_ENTITY_ID],
                                                             0);
}

uint16_t STDCALL stream_input_descriptor_response_imp::backedup_talker_unique()
{
    return jdksavdecc_descriptor_stream_get_backedup_talker_unique(buffer, position);
}

uint16_t STDCALL stream_input_descriptor_response_imp::avb_interface_index()
{
    return jdksavdecc_descriptor_stream_get_avb_interface_index(buffer, position);
}

uint32_t STDCALL stream_input_descriptor_response_imp::buffer_length()
{
    return jdksavdecc_descriptor_stream_get_buffer_length(buffer, position);
}

void stream_input_descriptor_response_imp::store_supported_stream_fmts()
{
    uint64_t offset = 0;
    for (int i = 0; i < number_of_formats(); i++)
    {
        stream_fmts_vec.push_back(jdksavdecc_uint64_get(&buffer[position + formats_offset() + offset], 0));
        offset += 0x8;
    }
}

uint64_t STDCALL stream_input_descriptor_response_imp::get_supported_stream_fmt_by_index(size_t supported_stream_fmt_index)
{
    return stream_fmts_vec.at(supported_stream_fmt_index);
}
}
<|endoftext|>


<commit_before>#include "CMergeShapes.h"

/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2013-11-11 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CMergeShapes.h"

#include "CBooleanOperTools.h"
#include "BRepSewingToBRepBuilderShapeAdapter.h"
#include "tiglcommonfunctions.h"

#include <cassert>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Solid.hxx>
#include <Precision.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <gp_Pnt.hxx>

#include <BRepBuilderAPI_Sewing.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>

#include <vector>

CMergeShapes::CMergeShapes(const CNamedShape &shape, const CNamedShape &tool)
    : _source(shape), _tool(tool)
{
    _hasPerformed = false;
}

CMergeShapes::~CMergeShapes()
{
}

CMergeShapes::operator CNamedShape()
{
    return NamedShape();
}

void CMergeShapes::Perform()
{
    if(!_hasPerformed) {
        CNamedShape& s1 = _source;
        CNamedShape& s2 = _tool;
        std::vector<TopoDS_Shape> v1, v2;

        // check input shapes
        if(s1.Shape().IsNull() && !s2.Shape().IsNull()) {
            _resultshape = s2;
            _hasPerformed = true;
            return;
        }
        else if(!s1.Shape().IsNull() && s2.Shape().IsNull()) {
            _resultshape = s1;
            _hasPerformed = true;
            return;
        }
        else if(s1.Shape().IsNull() && s2.Shape().IsNull()) {
            _resultshape = CNamedShape();
            _hasPerformed = true;
            return;
        }

        // both shapes are valid
        BRepBuilderAPI_Sewing sewer;

        TopTools_IndexedMapOfShape m1, m2;
        TopExp::MapShapes(s1.Shape(), TopAbs_FACE, m1);
        TopExp::MapShapes(s2.Shape(), TopAbs_FACE, m2);

        assert(m1.Extent() == m2.Extent());

        // remove common faces
        for(int iface = 1; iface <= m1.Extent(); ++iface){
            const TopoDS_Face& f1 = TopoDS::Face(m1(iface));
            const TopoDS_Face& f2 = TopoDS::Face(m2(iface));

            gp_Pnt p1 = GetCentralFacePoint(f1);
            gp_Pnt p2 = GetCentralFacePoint(f2);

            if(p1.Distance(p2) > Precision::Confusion()){
                v1.push_back(f1);
                v2.push_back(f2);
            }
        }
        std::vector<TopoDS_Shape>::const_iterator it;
        for(it = v1.begin(); it != v1.end(); ++it){
            sewer.Add(*it);
        }
        for(it = v2.begin(); it != v2.end(); ++it){
            sewer.Add(*it);
        }

        sewer.Perform();
        TopoDS_Shape shell = sewer.SewedShape();
        TopoDS_Shape solid = BRepBuilderAPI_MakeSolid(TopoDS::Shell(shell)).Solid();

        CNamedShape result(solid, "SEW_FUSE");
        BRepSewingToBRepBuilderShapeAdapter adapter(sewer);
        CBooleanOperTools::MapFaceNamesAfterBOP(adapter, s1, result);
        CBooleanOperTools::MapFaceNamesAfterBOP(adapter, s2, result);

        _resultshape = result;

        _hasPerformed = true;
    }
}

const CNamedShape &CMergeShapes::NamedShape()
{
    Perform();
    return _resultshape;
}
<commit_msg>Improved CMergeShapes in case of multiple shells<commit_after>#include "CMergeShapes.h"

/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2013-11-11 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CMergeShapes.h"

#include "CBooleanOperTools.h"
#include "BRepSewingToBRepBuilderShapeAdapter.h"
#include "tiglcommonfunctions.h"

#include <cassert>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Solid.hxx>
#include <Precision.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <gp_Pnt.hxx>

#include <BRepBuilderAPI_Sewing.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>

#include <vector>

CMergeShapes::CMergeShapes(const CNamedShape &shape, const CNamedShape &tool)
    : _source(shape), _tool(tool)
{
    _hasPerformed = false;
}

CMergeShapes::~CMergeShapes()
{
}

CMergeShapes::operator CNamedShape()
{
    return NamedShape();
}

void CMergeShapes::Perform()
{
    if(!_hasPerformed) {
        CNamedShape& s1 = _source;
        CNamedShape& s2 = _tool;
        std::vector<TopoDS_Shape> v1, v2;

        // check input shapes
        if(s1.Shape().IsNull() && !s2.Shape().IsNull()) {
            _resultshape = s2;
            _hasPerformed = true;
            return;
        }
        else if(!s1.Shape().IsNull() && s2.Shape().IsNull()) {
            _resultshape = s1;
            _hasPerformed = true;
            return;
        }
        else if(s1.Shape().IsNull() && s2.Shape().IsNull()) {
            _resultshape = CNamedShape();
            _hasPerformed = true;
            return;
        }

        // both shapes are valid
        BRepBuilderAPI_Sewing sewer;

        TopTools_IndexedMapOfShape m1, m2;
        TopExp::MapShapes(s1.Shape(), TopAbs_FACE, m1);
        TopExp::MapShapes(s2.Shape(), TopAbs_FACE, m2);

        assert(m1.Extent() == m2.Extent());

        // remove common faces
        for(int iface = 1; iface <= m1.Extent(); ++iface){
            const TopoDS_Face& f1 = TopoDS::Face(m1(iface));
            const TopoDS_Face& f2 = TopoDS::Face(m2(iface));

            gp_Pnt p1 = GetCentralFacePoint(f1);
            gp_Pnt p2 = GetCentralFacePoint(f2);

            if(p1.Distance(p2) > Precision::Confusion()){
                v1.push_back(f1);
                v2.push_back(f2);
            }
        }
        std::vector<TopoDS_Shape>::const_iterator it;
        for(it = v1.begin(); it != v1.end(); ++it){
            sewer.Add(*it);
        }
        for(it = v2.begin(); it != v2.end(); ++it){
            sewer.Add(*it);
        }

        sewer.Perform();
        // create solid of out sewed shape
        TopTools_IndexedMapOfShape map;
        TopExp::MapShapes(sewer.SewedShape(), TopAbs_SHELL, map);
        BRepBuilderAPI_MakeSolid solidMaker;
        for(int ishell = 1; ishell <= map.Extent(); ++ishell) {
            solidMaker.Add(TopoDS::Shell(map(ishell)));
        }
        TopoDS_Shape solid = solidMaker.Solid();

        // map names to shape
        CNamedShape result(solid, "SEW_FUSE");
        BRepSewingToBRepBuilderShapeAdapter adapter(sewer);
        CBooleanOperTools::MapFaceNamesAfterBOP(adapter, s1, result);
        CBooleanOperTools::MapFaceNamesAfterBOP(adapter, s2, result);

        _resultshape = result;

        _hasPerformed = true;
    }
}

const CNamedShape &CMergeShapes::NamedShape()
{
    Perform();
    return _resultshape;
}
<|endoftext|>


<commit_before>//
// Created by kanairen on 2016/06/14.
//

#include "Model.h"

const vector<vector<float>> &Model::forward(
        const vector<vector<float>> &inputs) {
    const vector<vector<float>> *output = &inputs;
    for (Layer &layer : layers) {
        output = &(layer.forward(*output));
    }
    return *output;
}

void Model::backward(const vector<vector<float>> &inputs,
                     const vector<vector<float>> &last_delta,
                     float learning_rate) {

    layers.back().backward(last_delta, layers[layers.size() - 2].get_z(),
                           learning_rate);
    for (int i = layers.size() - 2; i > 0; --i) {
        layers[i].backward(layers[i + 1], layers[i - 1].get_z(), learning_rate);
    }
    layers[0].backward(layers[1], inputs, learning_rate);
}

void Model::softmax(const vector<vector<float>> &outputs,
                    vector<vector<float>> &y) {

    if (outputs.size() != y.size() && outputs[0].size() != y[0].size()) {
        std::cerr << "error :  Model::softmax()" << endl;
        exit(1);
    }

    float u, sum_exp, max_output;
    for (int j = 0; j < outputs[0].size(); ++j) {

        // 最大出力値を求める
        max_output = -MAXFLOAT;
        for (int i = 0; i < outputs.size(); ++i) {
            if (outputs[i][j] > max_output) {
                max_output = outputs[i][j];
            }
        }

        // softmax関数の分子・分母を求める
        sum_exp = 0.f;
        for (int i = 0; i < outputs.size(); ++i) {
            u = expf(outputs[i][j] - max_output);
            y[i][j] = u;
            sum_exp += u;
        }

        // softmax関数の出力値を求める
        for (int i = 0; i < outputs.size(); ++i) {
            y[i][j] /= sum_exp;
        }

    }
}

void Model::argmax(const vector<vector<float>> &y, vector<int> &predict) {

    if (y[0].size() != predict.size()) {
        std::cerr << "error :  Model::argmax()" << endl;
        exit(1);
    }

    float max, tmp;
    int max_idx;
    for (int i = 0; i < y[0].size(); ++i) {
        max = y[0][i];
        max_idx = 0;
        for (int j = 1; j < y.size(); ++j) {
            tmp = y[j][i];
            if (tmp > max) {
                max = tmp;
                max_idx = j;
            }
        }
        predict[i] = max_idx;
    }

}

float Model::error(const vector<int> &predict, const vector<int> &answer) {

    if (predict.size() != answer.size()) {
        std::cerr << "error :  Model::error()" << endl;
        exit(1);
    }

    float num_error = 0.f;
    for (int i = 0; i < predict.size(); ++i) {
        if (predict[i] != answer[i]) {
            num_error += 1;
        }
    }

    return num_error / predict.size();

}<commit_msg>modify Layer::backward()内の逆伝播処理を変更<commit_after>//
// Created by kanairen on 2016/06/14.
//

#include "Model.h"

const vector<vector<float>> &Model::forward(
        const vector<vector<float>> &inputs) {
    const vector<vector<float>> *output = &inputs;
    for (Layer &layer : layers) {
        output = &(layer.forward(*output));
    }
    return *output;
}

void Model::backward(const vector<vector<float>> &inputs,
                     const vector<vector<float>> &last_delta,
                     float learning_rate) {

    const vector<vector<float>> *prev_output;
    for (int i = layers.size() - 1; i >= 0; --i) {

        prev_output = (i == 0) ? &inputs : &layers[i - 1].get_z();

        if (i == layers.size() - 1) {
            layers[i].backward(last_delta, *prev_output, learning_rate);
        } else {
            layers[i].backward(layers[i + 1], *prev_output, learning_rate);
        }

    }

}

void Model::softmax(const vector<vector<float>> &outputs,
                    vector<vector<float>> &y) {

    if (outputs.size() != y.size() && outputs[0].size() != y[0].size()) {
        std::cerr << "error :  Model::softmax()" << endl;
        exit(1);
    }

    float u, sum_exp, max_output;
    for (int j = 0; j < outputs[0].size(); ++j) {

        // 最大出力値を求める
        max_output = -MAXFLOAT;
        for (int i = 0; i < outputs.size(); ++i) {
            if (outputs[i][j] > max_output) {
                max_output = outputs[i][j];
            }
        }

        // softmax関数の分子・分母を求める
        sum_exp = 0.f;
        for (int i = 0; i < outputs.size(); ++i) {
            u = expf(outputs[i][j] - max_output);
            y[i][j] = u;
            sum_exp += u;
        }

        // softmax関数の出力値を求める
        for (int i = 0; i < outputs.size(); ++i) {
            y[i][j] /= sum_exp;
        }

    }
}

void Model::argmax(const vector<vector<float>> &y, vector<int> &predict) {

    if (y[0].size() != predict.size()) {
        std::cerr << "error :  Model::argmax()" << endl;
        exit(1);
    }

    float max, tmp;
    int max_idx;
    for (int i = 0; i < y[0].size(); ++i) {
        max = y[0][i];
        max_idx = 0;
        for (int j = 1; j < y.size(); ++j) {
            tmp = y[j][i];
            if (tmp > max) {
                max = tmp;
                max_idx = j;
            }
        }
        predict[i] = max_idx;
    }

}

float Model::error(const vector<int> &predict, const vector<int> &answer) {

    if (predict.size() != answer.size()) {
        std::cerr << "error :  Model::error()" << endl;
        exit(1);
    }

    float num_error = 0.f;
    for (int i = 0; i < predict.size(); ++i) {
        if (predict[i] != answer[i]) {
            num_error += 1;
        }
    }

    return num_error / predict.size();

}<|endoftext|>