<commit_before>//
//  Program Name - S6_2DArrays.cpp
//  Series: GetOnToC++ Step: 6
//
//  Purpose: This program illustrates 2D Arrays
//
//  Compile: g++  S6_2DArrays.cpp -o  S6_2DArrays
//  Execute: ./S6_2DArrays
//
//  Created by Narayan Mahadevan on 18/08/13.
//

#include <iostream>
using namespace std;

int matrix[10][10];
int main(){
	//Initializing 2D Array
	int counter = 0;
	for(int row = 0; row < 10; row++){
		for(int col = 0; col < 10; col++){
			matrix[row][col] = counter++;
		}
	}

	//Printing 2D array
	for(int row = 0; row < 10; row++){
		for(int col = 0; col < 10; col++){
			cout << matrix[row][col] << "	";
		}
		cout << endl;
	}
}
<commit_msg>Update S6_2DArrays.cpp<commit_after>//
//  Program Name - S6_2DArrays.cpp
//  Series: GetOnToC++ Step: 6
//
//  Purpose: This program illustrates 2D Arrays
//
//  Compile: g++  S6_2DArrays.cpp -o  S6_2DArrays
//  Execute: ./S6_2DArrays
//
//  Created by Narayan Mahadevan on 18/08/13.
//

#include <iostream>
using namespace std;
//Creating a two dimensional array
int matrix[10][10];
int main(){
	//Initializing 2D Array
	int counter = 0;
	for(int row = 0; row < 10; row++){ //For loop to traverse the rows
		for(int col = 0; col < 10; col++){ //For loop to traverse each column of each row
			matrix[row][col] = counter++; //Setting matrix[row][col] to counter
		}
	}

	//Printing 2D array
	for(int row = 0; row < 10; row++){ //For loop to traverse the rows
		for(int col = 0; col < 10; col++){ //For loop to traverse each column of each row
			cout << matrix[row][col] << "	"; //Printing the value of matrix[row][col]
		}
		cout << endl;
	}
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

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

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * RLP tool.
 */
#include <fstream>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include "../test/JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h>
using namespace std;
using namespace dev;
namespace js = json_spirit;

void help()
{
	cout
		<< "Usage rlp [OPTIONS] [ <file> | -- ]" << endl
		<< "Options:" << endl
		<< "    -r,--render  Render the given RLP. Options:" << endl
		<< "      --indent <string>  Use string as the level indentation (default '  ')." << endl
		<< "      --hex-ints  Render integers in hex." << endl
		<< "      --ascii-strings  Render data as C-style strings or hex depending on content being ASCII." << endl
		<< "      --force-string  Force all data to be rendered as C-style strings." << endl
		<< "      --force-escape  When rendering as C-style strings, force all characters to be escaped." << endl
		<< "      --force-hex  Force all data to be rendered as raw hex." << endl
		<< "    -l,--list-archive  List the items in the RLP list by hash and size." << endl
		<< "    -e,--extract-archive  Extract all items in the RLP list, named by hash." << endl
		<< "    -c,--create  Given a simplified JSON string, output the RLP." << endl
		<< "General options:" << endl
		<< "    -L,--lenience  Try not to bomb out early if possible." << endl
		<< "    -x,--hex,--base-16  Treat input RLP as hex encoded data." << endl
		<< "    --64,--base-64  Treat input RLP as base-64 encoded data." << endl
		<< "    -b,--bin,--base-256  Treat input RLP as raw binary data." << endl
		<< "    -h,--help  Print this help message and exit." << endl
		<< "    -V,--version  Show the version and exit." << endl
		;
	exit(0);
}

void version()
{
	cout << "rlp version " << dev::Version << endl;
	exit(0);
}

enum class Mode {
	ListArchive,
	ExtractArchive,
	Render,
	Create
};

enum class Encoding {
	Auto,
	Hex,
	Base64,
	Binary,
};

bool isAscii(string const& _s)
{
	// Always hex-encode anything beginning with 0x to avoid ambiguity.
	if (_s.size() >= 2 && _s.substr(0, 2) == "0x")
		return false;

	for (char c: _s)
		if (c < 32)
			return false;
	return true;
}

class RLPStreamer
{
public:
	struct Prefs
	{
		string indent = "  ";
		bool hexInts = false;
		bool hexPrefix = true;
		bool forceString = true;
		bool escapeAll = false;
		bool forceHex = false;
	};

	RLPStreamer(ostream& _out, Prefs _p): m_out(_out), m_prefs(_p) {}

	void output(RLP const& _d, unsigned _level = 0)
	{
		if (_d.isNull())
			m_out << "null";
		else if (_d.isInt())
			if (m_prefs.hexInts)
				m_out << (m_prefs.hexPrefix ? "0x" : "") << toHex(toCompactBigEndian(_d.toInt<bigint>(RLP::LaisezFaire), 1), 1);
			else
				m_out << _d.toInt<bigint>(RLP::LaisezFaire);
		else if (_d.isData())
			if (m_prefs.forceString || (!m_prefs.forceHex && isAscii(_d.toString())))
				m_out << escaped(_d.toString(), m_prefs.escapeAll);
			else
				m_out << (m_prefs.hexPrefix ? "0x" : "") << toHex(_d.data());
		else if (_d.isList())
		{
			m_out << "[";
			string newline = "\n";
			for (unsigned i = 0; i < _level + 1; ++i)
				newline += m_prefs.indent;
			int j = 0;
			for (auto i: _d)
			{
				m_out << (j++ ?
					(m_prefs.indent.empty() ? ", " : ("," + newline)) :
					(m_prefs.indent.empty() ? " " : newline));
				output(i, _level + 1);
			}
			newline = newline.substr(0, newline.size() - m_prefs.indent.size());
			m_out << (m_prefs.indent.empty() ? (j ? " ]" : "]") : (j ? newline + "]" : "]"));
		}
	}

private:
	std::ostream& m_out;
	Prefs m_prefs;
};

int main(int argc, char** argv)
{
	Encoding encoding = Encoding::Auto;
	Mode mode = Mode::Render;
	string inputFile = "--";
	bool lenience = false;
	RLPStreamer::Prefs prefs;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-h" || arg == "--help")
			help();
		else if (arg == "-r" || arg == "--render")
			mode = Mode::Render;
		else if (arg == "-c" || arg == "--create")
			mode = Mode::Create;
		else if ((arg == "-i" || arg == "--indent") && argc > i)
			prefs.indent = argv[++i];
		else if (arg == "--hex-ints")
			prefs.hexInts = true;
		else if (arg == "--ascii-strings")
			prefs.forceString = prefs.forceHex = false;
		else if (arg == "--force-string")
			prefs.forceString = true;
		else if (arg == "--force-hex")
			prefs.forceHex = true;
		else if (arg == "--force-escape")
			prefs.escapeAll = true;
		else if (arg == "-l" || arg == "--list-archive")
			mode = Mode::ListArchive;
		else if (arg == "-e" || arg == "--extract-archive")
			mode = Mode::ExtractArchive;
		else if (arg == "-L" || arg == "--lenience")
			lenience = true;
		else if (arg == "-V" || arg == "--version")
			version();
		else if (arg == "-x" || arg == "--hex" || arg == "--base-16")
			encoding = Encoding::Hex;
		else if (arg == "--64" || arg == "--base-64")
			encoding = Encoding::Base64;
		else if (arg == "-b" || arg == "--bin" || arg == "--base-256")
			encoding = Encoding::Binary;
		else
			inputFile = arg;
	}

	bytes in;
	if (inputFile == "--")
		for (int i = cin.get(); i != -1; i = cin.get())
			in.push_back((byte)i);
	else
		in = contents(inputFile);

	bytes b;

	if (mode != Mode::Create)
	{
		if (encoding == Encoding::Auto)
		{
			encoding = Encoding::Hex;
			for (char b: in)
				if (b != '\n' && b != ' ' && b != '\t')
				{
					if (encoding == Encoding::Hex && (b < '0' || b > '9' ) && (b < 'a' || b > 'f' ) && (b < 'A' || b > 'F' ))
					{
						cerr << "'" << b << "':" << (int)b << endl;
						encoding = Encoding::Base64;
					}
					if (encoding == Encoding::Base64 && (b < '0' || b > '9' ) && (b < 'a' || b > 'z' ) && (b < 'A' || b > 'Z' ) && b != '+' && b != '/')
					{
						encoding = Encoding::Binary;
						break;
					}
				}
		}
		switch (encoding)
		{
		case Encoding::Hex:
		{
			string s = asString(in);
			boost::algorithm::replace_all(s, " ", "");
			boost::algorithm::replace_all(s, "\n", "");
			boost::algorithm::replace_all(s, "\t", "");
			b = fromHex(s);
			break;
		}
		case Encoding::Base64:
		{
			string s = asString(in);
			boost::algorithm::replace_all(s, " ", "");
			boost::algorithm::replace_all(s, "\n", "");
			boost::algorithm::replace_all(s, "\t", "");
			b = fromBase64(s);
			break;
		}
		default:
			swap(b, in);
			break;
		}
	}

	try
	{
		RLP rlp(b);
		switch (mode)
		{
		case Mode::ListArchive:
		{
			if (!rlp.isList())
			{
				cout << "Error: Invalid format; RLP data is not a list." << endl;
				exit(1);
			}
			cout << rlp.itemCount() << " items:" << endl;
			for (auto i: rlp)
			{
				if (!i.isData())
				{
					cout << "Error: Invalid format; RLP list item is not data." << endl;
					if (!lenience)
						exit(1);
				}
				cout << "    " << i.size() << " bytes: " << sha3(i.data()) << endl;
			}
			break;
		}
		case Mode::ExtractArchive:
		{
			if (!rlp.isList())
			{
				cout << "Error: Invalid format; RLP data is not a list." << endl;
				exit(1);
			}
			cout << rlp.itemCount() << " items:" << endl;
			for (auto i: rlp)
			{
				if (!i.isData())
				{
					cout << "Error: Invalid format; RLP list item is not data." << endl;
					if (!lenience)
						exit(1);
				}
				ofstream fout;
				fout.open(toString(sha3(i.data())));
				fout.write(reinterpret_cast<char const*>(i.data().data()), i.data().size());
			}
			break;
		}
		case Mode::Render:
		{
			RLPStreamer s(cout, prefs);
			s.output(rlp);
			cout << endl;
			break;
		}
		case Mode::Create:
		{
			vector<js::mValue> v(1);
			try {
				js::read_string(asString(in), v[0]);
			}
			catch (...)
			{
				cerr << "Error: Invalid format; bad JSON." << endl;
				exit(1);
			}
			RLPStream out;
			while (!v.empty())
			{
				auto vb = v.back();
				v.pop_back();
				switch (vb.type())
				{
				case js::array_type:
				{
					js::mArray a = vb.get_array();
					out.appendList(a.size());
					for (int i = a.size() - 1; i >= 0; --i)
						v.push_back(a[i]);
					break;
				}
				case js::str_type:
				{
					string const& s = vb.get_str();
					if (s.size() >= 2 && s.substr(0, 2) == "0x")
						out << fromHex(s);
					else
					{
						// assume it's a normal JS escaped string.
						bytes ss;
						ss.reserve(s.size());
						for (unsigned i = 0; i < s.size(); ++i)
							if (s[i] == '\\' && i + 1 < s.size())
							{
								if (s[++i] == 'x' && i + 2 < s.size())
									ss.push_back(fromHex(s.substr(i, 2))[0]);
							}
							else if (s[i] != '\\')
								ss.push_back((byte)s[i]);
						out << ss;
					}
					break;
				}
				case js::int_type:
					out << vb.get_int();
					break;
				default:
					cerr << "ERROR: Unsupported type in JSON." << endl;
					if (!lenience)
						exit(1);
				}
			}
			switch (encoding)
			{
			case Encoding::Hex: case Encoding::Auto:
				cout << toHex(out.out()) << endl;
				break;
			case Encoding::Base64:
				cout << toBase64(&out.out()) << endl;
				break;
			case Encoding::Binary:
				cout.write((char const*)out.out().data(), out.out().size());
				break;
			}
			break;
		}
		default:;
		}
	}
	catch (...)
	{
		cerr << "Error: Invalid format; bad RLP." << endl;
		exit(1);
	}

	return 0;
}
<commit_msg>Improvements to RLP executable.<commit_after>/*
	This file is part of cpp-ethereum.

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

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * RLP tool.
 */
#include <fstream>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include "../test/JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h>
using namespace std;
using namespace dev;
namespace js = json_spirit;

void help()
{
	cout
		<< "Usage rlp [OPTIONS] [ <file> | -- ]" << endl
		<< "Options:" << endl
		<< "    -r,--render  Render the given RLP. Options:" << endl
		<< "      --indent <string>  Use string as the level indentation (default '  ')." << endl
		<< "      --hex-ints  Render integers in hex." << endl
		<< "      --string-ints  Render integers in the same way as strings." << endl
		<< "      --ascii-strings  Render data as C-style strings or hex depending on content being ASCII." << endl
		<< "      --force-string  Force all data to be rendered as C-style strings." << endl
		<< "      --force-escape  When rendering as C-style strings, force all characters to be escaped." << endl
		<< "      --force-hex  Force all data to be rendered as raw hex." << endl
		<< "    -l,--list-archive  List the items in the RLP list by hash and size." << endl
		<< "    -e,--extract-archive  Extract all items in the RLP list, named by hash." << endl
		<< "    -c,--create  Given a simplified JSON string, output the RLP." << endl
		<< "General options:" << endl
		<< "    -L,--lenience  Try not to bomb out early if possible." << endl
		<< "    -x,--hex,--base-16  Treat input RLP as hex encoded data." << endl
		<< "    --64,--base-64  Treat input RLP as base-64 encoded data." << endl
		<< "    -b,--bin,--base-256  Treat input RLP as raw binary data." << endl
		<< "    -h,--help  Print this help message and exit." << endl
		<< "    -V,--version  Show the version and exit." << endl
		;
	exit(0);
}

void version()
{
	cout << "rlp version " << dev::Version << endl;
	exit(0);
}

enum class Mode {
	ListArchive,
	ExtractArchive,
	Render,
	Create
};

enum class Encoding {
	Auto,
	Hex,
	Base64,
	Binary,
};

bool isAscii(string const& _s)
{
	// Always hex-encode anything beginning with 0x to avoid ambiguity.
	if (_s.size() >= 2 && _s.substr(0, 2) == "0x")
		return false;

	for (char c: _s)
		if (c < 32)
			return false;
	return true;
}

class RLPStreamer
{
public:
	struct Prefs
	{
		string indent;
		bool hexInts = false;
		bool stringInts = true;
		bool hexPrefix = true;
		bool forceString = false;
		bool escapeAll = false;
		bool forceHex = true;
	};

	RLPStreamer(ostream& _out, Prefs _p): m_out(_out), m_prefs(_p) {}

	void output(RLP const& _d, unsigned _level = 0)
	{
		if (_d.isNull())
			m_out << "null";
		else if (_d.isInt() && !m_prefs.stringInts)
			if (m_prefs.hexInts)
				m_out << (m_prefs.hexPrefix ? "0x" : "") << toHex(toCompactBigEndian(_d.toInt<bigint>(RLP::LaisezFaire), 1), 1);
			else
				m_out << _d.toInt<bigint>(RLP::LaisezFaire);
		else if (_d.isData() || (_d.isInt() && m_prefs.stringInts))
			if (m_prefs.forceString || (!m_prefs.forceHex && isAscii(_d.toString())))
				m_out << escaped(_d.toString(), m_prefs.escapeAll);
			else
				m_out << "\"" << (m_prefs.hexPrefix ? "0x" : "") << toHex(_d.toBytes()) << "\"";
		else if (_d.isList())
		{
			m_out << "[";
			string newline = "\n";
			for (unsigned i = 0; i < _level + 1; ++i)
				newline += m_prefs.indent;
			int j = 0;
			for (auto i: _d)
			{
				m_out << (j++ ?
					(m_prefs.indent.empty() ? ", " : ("," + newline)) :
					(m_prefs.indent.empty() ? " " : newline));
				output(i, _level + 1);
			}
			newline = newline.substr(0, newline.size() - m_prefs.indent.size());
			m_out << (m_prefs.indent.empty() ? (j ? " ]" : "]") : (j ? newline + "]" : "]"));
		}
	}

private:
	std::ostream& m_out;
	Prefs m_prefs;
};

int main(int argc, char** argv)
{
	Encoding encoding = Encoding::Auto;
	Mode mode = Mode::Render;
	string inputFile = "--";
	bool lenience = false;
	RLPStreamer::Prefs prefs;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-h" || arg == "--help")
			help();
		else if (arg == "-r" || arg == "--render")
			mode = Mode::Render;
		else if (arg == "-c" || arg == "--create")
			mode = Mode::Create;
		else if ((arg == "-i" || arg == "--indent") && argc > i)
			prefs.indent = argv[++i];
		else if (arg == "--hex-ints")
			prefs.hexInts = true;
		else if (arg == "--string-ints")
			prefs.stringInts = true;
		else if (arg == "--ascii-strings")
			prefs.forceString = prefs.forceHex = false;
		else if (arg == "--force-string")
			prefs.forceString = true;
		else if (arg == "--force-hex")
			prefs.forceHex = true, prefs.forceString = false;
		else if (arg == "--force-escape")
			prefs.escapeAll = true;
		else if (arg == "-n" || arg == "--nice")
			prefs.forceString = true, prefs.stringInts = false, prefs.forceHex = false, prefs.indent = "  ";
		else if (arg == "-l" || arg == "--list-archive")
			mode = Mode::ListArchive;
		else if (arg == "-e" || arg == "--extract-archive")
			mode = Mode::ExtractArchive;
		else if (arg == "-L" || arg == "--lenience")
			lenience = true;
		else if (arg == "-V" || arg == "--version")
			version();
		else if (arg == "-x" || arg == "--hex" || arg == "--base-16")
			encoding = Encoding::Hex;
		else if (arg == "--64" || arg == "--base-64")
			encoding = Encoding::Base64;
		else if (arg == "-b" || arg == "--bin" || arg == "--base-256")
			encoding = Encoding::Binary;
		else
			inputFile = arg;
	}

	bytes in;
	if (inputFile == "--")
		for (int i = cin.get(); i != -1; i = cin.get())
			in.push_back((byte)i);
	else
		in = contents(inputFile);

	bytes b;

	if (mode != Mode::Create)
	{
		if (encoding == Encoding::Auto)
		{
			encoding = Encoding::Hex;
			for (char b: in)
				if (b != '\n' && b != ' ' && b != '\t')
				{
					if (encoding == Encoding::Hex && (b < '0' || b > '9' ) && (b < 'a' || b > 'f' ) && (b < 'A' || b > 'F' ))
					{
						cerr << "'" << b << "':" << (int)b << endl;
						encoding = Encoding::Base64;
					}
					if (encoding == Encoding::Base64 && (b < '0' || b > '9' ) && (b < 'a' || b > 'z' ) && (b < 'A' || b > 'Z' ) && b != '+' && b != '/')
					{
						encoding = Encoding::Binary;
						break;
					}
				}
		}
		switch (encoding)
		{
		case Encoding::Hex:
		{
			string s = asString(in);
			boost::algorithm::replace_all(s, " ", "");
			boost::algorithm::replace_all(s, "\n", "");
			boost::algorithm::replace_all(s, "\t", "");
			b = fromHex(s);
			break;
		}
		case Encoding::Base64:
		{
			string s = asString(in);
			boost::algorithm::replace_all(s, " ", "");
			boost::algorithm::replace_all(s, "\n", "");
			boost::algorithm::replace_all(s, "\t", "");
			b = fromBase64(s);
			break;
		}
		default:
			swap(b, in);
			break;
		}
	}

	try
	{
		RLP rlp(b);
		switch (mode)
		{
		case Mode::ListArchive:
		{
			if (!rlp.isList())
			{
				cout << "Error: Invalid format; RLP data is not a list." << endl;
				exit(1);
			}
			cout << rlp.itemCount() << " items:" << endl;
			for (auto i: rlp)
			{
				if (!i.isData())
				{
					cout << "Error: Invalid format; RLP list item is not data." << endl;
					if (!lenience)
						exit(1);
				}
				cout << "    " << i.size() << " bytes: " << sha3(i.data()) << endl;
			}
			break;
		}
		case Mode::ExtractArchive:
		{
			if (!rlp.isList())
			{
				cout << "Error: Invalid format; RLP data is not a list." << endl;
				exit(1);
			}
			cout << rlp.itemCount() << " items:" << endl;
			for (auto i: rlp)
			{
				if (!i.isData())
				{
					cout << "Error: Invalid format; RLP list item is not data." << endl;
					if (!lenience)
						exit(1);
				}
				ofstream fout;
				fout.open(toString(sha3(i.data())));
				fout.write(reinterpret_cast<char const*>(i.data().data()), i.data().size());
			}
			break;
		}
		case Mode::Render:
		{
			RLPStreamer s(cout, prefs);
			s.output(rlp);
			cout << endl;
			break;
		}
		case Mode::Create:
		{
			vector<js::mValue> v(1);
			try {
				js::read_string(asString(in), v[0]);
			}
			catch (...)
			{
				cerr << "Error: Invalid format; bad JSON." << endl;
				exit(1);
			}
			RLPStream out;
			while (!v.empty())
			{
				auto vb = v.back();
				v.pop_back();
				switch (vb.type())
				{
				case js::array_type:
				{
					js::mArray a = vb.get_array();
					out.appendList(a.size());
					for (int i = a.size() - 1; i >= 0; --i)
						v.push_back(a[i]);
					break;
				}
				case js::str_type:
				{
					string const& s = vb.get_str();
					if (s.size() >= 2 && s.substr(0, 2) == "0x")
						out << fromHex(s);
					else
					{
						// assume it's a normal JS escaped string.
						bytes ss;
						ss.reserve(s.size());
						for (unsigned i = 0; i < s.size(); ++i)
							if (s[i] == '\\' && i + 1 < s.size())
							{
								if (s[++i] == 'x' && i + 2 < s.size())
									ss.push_back(fromHex(s.substr(i, 2))[0]);
							}
							else if (s[i] != '\\')
								ss.push_back((byte)s[i]);
						out << ss;
					}
					break;
				}
				case js::int_type:
					out << vb.get_int();
					break;
				default:
					cerr << "ERROR: Unsupported type in JSON." << endl;
					if (!lenience)
						exit(1);
				}
			}
			switch (encoding)
			{
			case Encoding::Hex: case Encoding::Auto:
				cout << toHex(out.out()) << endl;
				break;
			case Encoding::Base64:
				cout << toBase64(&out.out()) << endl;
				break;
			case Encoding::Binary:
				cout.write((char const*)out.out().data(), out.out().size());
				break;
			}
			break;
		}
		default:;
		}
	}
	catch (...)
	{
		cerr << "Error: Invalid format; bad RLP." << endl;
		exit(1);
	}

	return 0;
}
<|endoftext|>


<commit_before>#ifndef PERCEPTRON_H
#define PERCEPTRON_H

#include <sstream>
#include <vector>
#include <numeric>    // inner_product
#include <algorithm>  // transform
#include <functional> // plus, minus
#include <assert.h>
#include <cmath>      // sqrt
#include <initializer_list>
#include <iostream>   // cout
#include <iterator>   // begin, end

#include "randomgen.hh"
#include "classifier.hh"
#include "activation.hh"

using namespace std;

using epoch_parameter = function<double(int)>;

epoch_parameter const_epoch_parameter(double eta) {
    return [eta](int) { return eta; };
}

using Weights = vector<double>;

class APerceptron {
    /// induced local field of activation potential $v_k$, page 11
    virtual double inducedLocalField(const Input &x) = 0;
    /// neuron's output (activation function applied to the induced local field)
    virtual double output(const Input &x) = 0;
    /// neuron's weights; weights[0] is bias
    virtual Weights getWeights() const = 0;
};

// TODO: rename to LinearPerceptron
class StandalonePerceptron : public APerceptron, public BinaryClassifier {
private:
    // TODO: use weights[0] as bias
    double bias;
    Weights weights;
    const ActivationFunction &activationFunction;

    // TODO: implement via adjustWeights()
    void trainConverge_addSample(Input input, double output, double eta) {
        double y = this->output(input);
        double xfactor = eta * (output - y);
        bias += xfactor * 1.0;
        transform(
            weights.begin(), weights.end(), begin(input),
            weights.begin() /* output */,
            [&xfactor](double w_i, double x_i) { return w_i + xfactor * x_i; });
    }

    void trainBatch_addBatch(LabeledDataset batch, double eta) {
        for (auto sample : batch) {
            double d = sample.label[0]; // desired output
            Input x = sample.data;
            bias += eta * 1.0 * d;
            transform(begin(x), end(x), weights.begin(), weights.begin(),
                      [d, eta](double x_i, double w_i) {
                          return w_i + eta * x_i * d;
                      });
        }
    }

public:
    StandalonePerceptron(int n, const ActivationFunction &af = defaultSignum)
        : bias(0), weights(n), activationFunction(af) {}

    virtual double inducedLocalField(const Input &x) {
        assert(x.size() == weights.size());
        return inner_product(weights.begin(), weights.end(), begin(x), bias);
    }

    virtual double output(const Input &x) {
        return activationFunction(inducedLocalField(x));
    }

    virtual bool classify(const Input &x) { return output(x) > 0; }

    /// perceptron convergence algorithm (Table 1.1)
    void trainConverge(const LabeledDataset &trainSet, int epochs,
                       double eta = 1.0) {
        return trainConverge(trainSet, epochs, const_epoch_parameter(eta));
    }

    /// perceptron convergence algorithm (Table 1.1)
    void trainConverge(const LabeledDataset &trainSet, int epochs,
                       epoch_parameter eta) {
        assert(trainSet.outputDim() == 1);
        for (int epoch = 0; epoch < epochs; ++epoch) {
            double etaval = eta(epoch);
            for (auto sample : trainSet) {
                trainConverge_addSample(sample.data, sample.label[0], etaval);
            }
        }
    }

    /// batch-training algorithm (Sec 1.6, Eq. 1.42)
    void trainBatch(const LabeledDataset &trainSet, int epochs, double eta = 1.0) {
        return trainBatch(trainSet, epochs, const_epoch_parameter(eta));
    }

    /// batch-training algorithm (Sec 1.6, Eq. 1.42)
    void trainBatch(const LabeledDataset &trainSet, int epochs,
                    epoch_parameter eta) {
        assert(trainSet.outputDim() == 1);
        assert(trainSet.inputDim() == weights.size());
        // \nabla J(w) = \sum_{\vec{x}(n) \in H} ( - \vec{x}(n) d(n) ) (1.40)
        // w(n+1) = w(n) - eta(n) \nabla J(w) (1.42)
        for (int epoch = 0; epoch < epochs; ++epoch) {
            double etaval = eta(epoch);
            // a new batch
            LabeledDataset misclassifiedSet;
            for (auto sample : trainSet) {
               if (output(sample.data) * sample.label[0] <= 0) {
                  misclassifiedSet.append(sample);
               }
            }
            // sum cost gradient over the entire bactch
            trainBatch_addBatch(misclassifiedSet, etaval);
        }
    }

    virtual vector<double> getWeights() const {
        vector<double> biasAndWeights(weights);
        biasAndWeights.insert(biasAndWeights.begin(), bias);
        return biasAndWeights;
    }

    // TODO: move to non-member function
    string fmt() {
        ostringstream ss;
        for (auto it : getWeights()) {
            ss << " " << it;
        }
        return ss.str();
    }
};

ostream &operator<<(ostream &out, const vector<double> &xs);

#if 0

/**
 A basic perceptron, without built-in training facilities, with
 reasonable defaults to be used within `PerceptronsLayers`.
 */
class BasicPerceptron : public APerceptron {
private:
    Weights weights; // weights[0] is bias
    const ActivationFunction &activationFunction;

    // remember the last input and internal parameters to use them
    // again in the back-propagation step
    double lastInducedLocalField;  // v_j = \sum w_i y_i
    double lastActivationValue;    // y_j = \phi (v_j)
    double lastActivationGradient; // y_j = \phi^\prime (v_j)
    double lastLocalGradient;      // delta_j = \phi^\prime(v_j) e_j

public:
    BasicPerceptron(int n, const ActivationFunction &af = defaultTanh)
        : weights(n + 1), activationFunction(af) {}

    // one-sided Xavier initialization
    // see http://andyljones.tumblr.com/post/110998971763/
    void init(unique_ptr<rng_type> &rng) {
        int n_in = weights.size()-1;
        double sigma = n_in > 0 ? sqrt(1.0/n_in) : 1.0;
        uniform_real_distribution<double> nd(-sigma, sigma);
        generate(weights.begin(), weights.end(), [&nd, &rng] {
                    double w = nd(*rng.get());
                    return w;
                 });
    }

    virtual double inducedLocalField(const Input &x) {
        double bias = weights[0];
        auto weights_2nd = next(weights.begin());
        return inner_product(weights_2nd, weights.end(), x.begin(), bias);
    }

    virtual double output(const Input &x) {
        double v = inducedLocalField(x);
        lastInducedLocalField = v;
        lastActivationValue = activationFunction(v);
        lastActivationGradient = activationFunction.derivative(v);
        return lastActivationValue;
    }

    virtual Weights getWeights() const {
        return weights;
    }

    void adjustWeights(Weights deltaW) {
        assert(deltaW.size() == weights.size());
        for (size_t i = 0; i < weights.size(); ++i) {
            weights[i] += deltaW[i];
        }
    }

    struct BPResult {
        Weights weightCorrection;
        double localGradient;
    };

    // Page 134. Equation (4.27) defines weight correction
    //
    // $$ \Delta w_{ji} (n) =
    //    \eta
    //      \times
    //    \delta_j (n)
    //      \times
    //    y_{i} (n) $$
    //
    // where $w_{ji}$ is the synaptic weight connecting neuron $i$ to neuron $j$,
    // $\eta$ is learning rate, $delta_j (n)$ is the local [error] gradient,
    // $y_{i}$ is the input signal of the neuron $i$, $n$ is the epoch number
    //
    // The local gradient is the product of the activation function derivative
    // and the error signal.
    //
    // Return a vector of weight corrections and the local gradient value.
    //
    // The method should be called _after_ `forwardPass`
    BPResult backwardPass(const Input &inputs, double errorSignal,
                          double learningRate) {
        assert(inputs.size() + 1 == weights.size());
        size_t nInputs = weights.size();
        double localGradient = lastActivationGradient * errorSignal;
        double multiplier = learningRate * localGradient;
        Weights delta_W(nInputs, multiplier);
        for (size_t i = 0; i < inputs.size(); ++i) {
            delta_W[i + 1] *= inputs[i];
        }
        lastLocalGradient = localGradient;
        return BPResult{delta_W, localGradient};
    }
};

/// A fully connected layer of perceptrons.
class PerceptronsLayer {
private:
    unsigned int nInputs;
    unsigned int nNeurons;
    vector<BasicPerceptron> neurons;
    Output lastOutput;

public:
    PerceptronsLayer(unsigned int nInputs = 0, unsigned int nOutputs = 0,
                     const ActivationFunction &af = defaultTanh)
        : nInputs(nInputs), nNeurons(nOutputs),
          neurons(nOutputs, BasicPerceptron(nInputs, af)),
          lastOutput(nOutputs) {}

    void init(unique_ptr<rng_type> &rng) {
        for (size_t i = 0; i < neurons.size(); ++i) {
            neurons[i].init(rng);
        }
    }

    void adjustWeights(vector<Weights> weightDeltas) {
        assert(nNeurons == weightDeltas.size());
        for (size_t i = 0; i < neurons.size(); ++i) {
            neurons[i].adjustWeights(weightDeltas[i]);
        }
    }

    // Pages 132-133.
    // Return a vector of outputs.
    Output forwardPass(const Input &inputs) {
        for (auto i = 0u; i < nNeurons; ++i) {
            lastOutput[i] = neurons[i].output(inputs);
        }
        return lastOutput;
    }

    struct BPResult {
        Output propagatedErrorSignals;
        vector<Weights> weightCorrections;
    };

    // Page 134. Calculate back-propagated error signal and corrections to
    // synaptic weights.
    //
    // $$ e_j = \sum_k \delta_k w_{kj} $$
    //
    // where $e_j$ is an error propagated from all downstream neurons to the
    // neuron $j$, $\delta_k$ is the local gradient of the downstream neurons
    // $k$, $w_{kj}$ is the synaptic weight of the $j$-th input of the
    // downstream neuron $k$.
    //
    // The method should be called _after_ `forwardPass`
    BPResult backwardPass(const Input &inputs, const Output &errorSignals,
                          double learningRate) {
        assert(errorSignals.size() == neurons.size());
        auto eta = learningRate;
        vector<Weights> weightDeltas(0);
        Weights propagatedErrorSignals(nInputs, 0.0);
        for (auto k = 0u; k < nNeurons; ++k) {
            auto error_k = errorSignals[k];
            auto r = neurons[k].backwardPass(inputs, error_k, eta);
            Weights delta_Wk = r.weightCorrection;
            double delta_k = r.localGradient;
            Weights Wk = neurons[k].getWeights();
            for (auto j = 0u; j < nInputs; ++j) {
                propagatedErrorSignals[j] += delta_k * Wk[j + 1];
            }
            weightDeltas.push_back(delta_Wk);
        }
        return BPResult{propagatedErrorSignals, weightDeltas};
    }

    friend ostream &operator<<(ostream &out, const PerceptronsLayer &net);
};

/// Multiple layers of perceptrons stack one upon another.
// TODO: rename to MultilayerPerceptron
class PerceptronsNetwork {
private:
    vector<PerceptronsLayer> layers;
    vector<Input> layersInputs;

public:
    PerceptronsNetwork(initializer_list<unsigned int> shape,
                       const ActivationFunction &af = defaultTanh)
        : layers(0), layersInputs(0) {
        auto pIn = shape.begin();
        auto pOut = next(pIn);
        for (; pOut != shape.end(); ++pIn, ++pOut) {
            PerceptronsLayer layer(*pIn, *pOut, af);
            layers.push_back(layer);
        }
    }

    void init(unique_ptr<rng_type> &rng) {
        for (auto i = 0u; i < layers.size(); ++i) {
            layers[i].init(rng);
        }
    }

    Output forwardPass(const Input &inputs) {
        layersInputs.clear();
        layersInputs.push_back(inputs);
        for (auto i = 0u; i < layers.size(); ++i) {
            auto in = layersInputs[i];
            auto out = layers[i].forwardPass(in);
            layersInputs.push_back(out);
        }
        return layersInputs[layers.size()];
    }

    PerceptronsLayer::BPResult
    backwardPass(const Output &errorSignals, double learningRate) {
        Output err(errorSignals);
        PerceptronsLayer::BPResult r;

        for (int i = layers.size()-1; i >= 0; --i) {
            auto layerIn = layersInputs[i];
            r = layers[i].backwardPass(layerIn, err, learningRate);
            layers[i].adjustWeights(r.weightCorrections);
            err = r.propagatedErrorSignals;
        }
        return r;
    }

    friend ostream &operator<<(ostream &out, const PerceptronsNetwork &net);
};

ostream &operator<<(ostream &out, const PerceptronsLayer &layer) {
    size_t n = layer.neurons.size();
    for (size_t j = 0; j < n; ++j) {
        if (j == 0) {
            out << "[";
        } else {
            out << " ";
        }
        out << layer.neurons[j].getWeights();
        if (j >= n - 1) {
            out << "]";
        } else {
            out << ",\n";
        }
    }
    return out;
}

ostream &operator<<(ostream &out, const PerceptronsNetwork &net) {
    for (PerceptronsLayer l : net.layers) {
        out << l << "\n";
    }
    return out;
}

ostream &operator<<(ostream &out, const vector<double> &xs) {
    int n = xs.size();
    out << "[ ";
    for (int i = 0; i < n - 1; ++i) {
        out << xs[i] << ", ";
    }
    out << xs[n - 1] << " ]";
    return out;
}

#endif

#endif /* PERCEPTRON_H */
<commit_msg>use adjustWeights() method of APerceptron in single perceptron training<commit_after>#ifndef PERCEPTRON_H
#define PERCEPTRON_H

#include <sstream>
#include <vector>
#include <numeric>    // inner_product
#include <algorithm>  // transform
#include <functional> // plus, minus
#include <assert.h>
#include <cmath>      // sqrt
#include <initializer_list>
#include <iostream>   // cout
#include <iterator>   // begin, end

#include "randomgen.hh"
#include "classifier.hh"
#include "activation.hh"

using namespace std;

using epoch_parameter = function<double(int)>;

epoch_parameter const_epoch_parameter(double eta) {
    return [eta](int) { return eta; };
}

using Weights = vector<double>;

class APerceptron {
    /// induced local field of activation potential $v_k$, page 11, eq (4)
    ///
    /// $$ v_k = \sum_{j = 0}^{m} w_{kj} x_j, $$
    ///
    /// where $w_{kj}$ is the weight of the $j$-th input of the neuron $k$,
    /// and $x_j$ is the $j$-th input.
    virtual double inducedLocalField(const Input &x) = 0;
    /// neuron's output, page 12, eq (5)
    ///
    /// $$ y_k = \varphi (v_k) $$
    ///
    /// @return the value activation function applied to the induced local field
    virtual double output(const Input &x) = 0;
    /// get neuron's weights; weights[0] ($w_{k0}$) is bias
    virtual Weights getWeights() const = 0;
    /// add weight correction to the neuron's weights
    virtual Weights adjustWeights(const Weights weightCorrection) = 0;
};

// TODO: rename to LinearPerceptron
class StandalonePerceptron : public APerceptron, public BinaryClassifier {
private:
    // TODO: use weights[0] as bias
    double bias;
    Weights weights;
    const ActivationFunction &activationFunction;

    void trainConverge_addSample(Input input, double output, double eta) {
        double y = this->output(input);
        double xfactor = eta * (output - y);
        Weights deltaW(weights.size() + 1);
        deltaW[0] = xfactor * 1.0; // bias
        for (size_t i = 0; i < input.size(); ++i) {
            deltaW[i+1] = xfactor * input[i];
        }
        adjustWeights(deltaW);
    }

    void trainBatch_addBatch(LabeledDataset batch, double eta) {
        for (auto sample : batch) {
            double desired = sample.label[0]; // desired output
            Input input = sample.data;
            Weights deltaW(weights.size() + 1);
            deltaW[0] = eta * 1.0 * desired; // bias
            for (size_t i = 0; i < input.size(); ++i) {
                deltaW[i+1] = eta * input[i] * desired;
            }
            adjustWeights(deltaW);
        }
    }

public:
    StandalonePerceptron(int n, const ActivationFunction &af = defaultSignum)
        : bias(0), weights(n), activationFunction(af) {}

    virtual double inducedLocalField(const Input &x) {
        assert(x.size() == weights.size());
        return inner_product(weights.begin(), weights.end(), begin(x), bias);
    }

    virtual double output(const Input &x) {
        return activationFunction(inducedLocalField(x));
    }

    virtual vector<double> getWeights() const {
        vector<double> biasAndWeights(weights);
        biasAndWeights.insert(biasAndWeights.begin(), bias);
        return biasAndWeights;
    }

    virtual Weights adjustWeights(const Weights weightCorrection) {
        assert(weights.size() == weightCorrection.size()-1);
        assert(weightCorrection.size() > 0);
        bias += weightCorrection[0];
        auto second = ++weightCorrection.begin();
        transform(second, weightCorrection.end(), weights.begin(),
                  weights.begin(), [](double w_i, double delta_w) {
                    return w_i + delta_w;
                  });
        return getWeights();
    }

    virtual bool classify(const Input &x) { return output(x) > 0; }

    /// perceptron convergence algorithm (Table 1.1)
    void trainConverge(const LabeledDataset &trainSet, int epochs,
                       double eta = 1.0) {
        return trainConverge(trainSet, epochs, const_epoch_parameter(eta));
    }

    /// perceptron convergence algorithm (Table 1.1)
    void trainConverge(const LabeledDataset &trainSet, int epochs,
                       epoch_parameter eta) {
        assert(trainSet.outputDim() == 1);
        for (int epoch = 0; epoch < epochs; ++epoch) {
            double etaval = eta(epoch);
            for (auto sample : trainSet) {
                trainConverge_addSample(sample.data, sample.label[0], etaval);
            }
        }
    }

    /// batch-training algorithm (Sec 1.6, Eq. 1.42)
    void trainBatch(const LabeledDataset &trainSet, int epochs, double eta = 1.0) {
        return trainBatch(trainSet, epochs, const_epoch_parameter(eta));
    }

    /// batch-training algorithm (Sec 1.6, Eq. 1.42)
    void trainBatch(const LabeledDataset &trainSet, int epochs,
                    epoch_parameter eta) {
        assert(trainSet.outputDim() == 1);
        assert(trainSet.inputDim() == weights.size());
        // \nabla J(w) = \sum_{\vec{x}(n) \in H} ( - \vec{x}(n) d(n) ) (1.40)
        // w(n+1) = w(n) - eta(n) \nabla J(w) (1.42)
        for (int epoch = 0; epoch < epochs; ++epoch) {
            double etaval = eta(epoch);
            // a new batch
            LabeledDataset misclassifiedSet;
            for (auto sample : trainSet) {
               if (output(sample.data) * sample.label[0] <= 0) {
                  misclassifiedSet.append(sample);
               }
            }
            // sum cost gradient over the entire bactch
            trainBatch_addBatch(misclassifiedSet, etaval);
        }
    }

    // TODO: move to non-member function
    string fmt() {
        ostringstream ss;
        for (auto it : getWeights()) {
            ss << " " << it;
        }
        return ss.str();
    }
};

ostream &operator<<(ostream &out, const vector<double> &xs);

#if 0

/**
 A basic perceptron, without built-in training facilities, with
 reasonable defaults to be used within `PerceptronsLayers`.
 */
class BasicPerceptron : public APerceptron {
private:
    Weights weights; // weights[0] is bias
    const ActivationFunction &activationFunction;

    // remember the last input and internal parameters to use them
    // again in the back-propagation step
    double lastInducedLocalField;  // v_j = \sum w_i y_i
    double lastActivationValue;    // y_j = \phi (v_j)
    double lastActivationGradient; // y_j = \phi^\prime (v_j)
    double lastLocalGradient;      // delta_j = \phi^\prime(v_j) e_j

public:
    BasicPerceptron(int n, const ActivationFunction &af = defaultTanh)
        : weights(n + 1), activationFunction(af) {}

    // one-sided Xavier initialization
    // see http://andyljones.tumblr.com/post/110998971763/
    void init(unique_ptr<rng_type> &rng) {
        int n_in = weights.size()-1;
        double sigma = n_in > 0 ? sqrt(1.0/n_in) : 1.0;
        uniform_real_distribution<double> nd(-sigma, sigma);
        generate(weights.begin(), weights.end(), [&nd, &rng] {
                    double w = nd(*rng.get());
                    return w;
                 });
    }

    virtual double inducedLocalField(const Input &x) {
        double bias = weights[0];
        auto weights_2nd = next(weights.begin());
        return inner_product(weights_2nd, weights.end(), x.begin(), bias);
    }

    virtual double output(const Input &x) {
        double v = inducedLocalField(x);
        lastInducedLocalField = v;
        lastActivationValue = activationFunction(v);
        lastActivationGradient = activationFunction.derivative(v);
        return lastActivationValue;
    }

    virtual Weights getWeights() const {
        return weights;
    }

    void adjustWeights(Weights deltaW) {
        assert(deltaW.size() == weights.size());
        for (size_t i = 0; i < weights.size(); ++i) {
            weights[i] += deltaW[i];
        }
    }

    struct BPResult {
        Weights weightCorrection;
        double localGradient;
    };

    // Page 134. Equation (4.27) defines weight correction
    //
    // $$ \Delta w_{ji} (n) =
    //    \eta
    //      \times
    //    \delta_j (n)
    //      \times
    //    y_{i} (n) $$
    //
    // where $w_{ji}$ is the synaptic weight connecting neuron $i$ to neuron $j$,
    // $\eta$ is learning rate, $delta_j (n)$ is the local [error] gradient,
    // $y_{i}$ is the input signal of the neuron $i$, $n$ is the epoch number
    //
    // The local gradient is the product of the activation function derivative
    // and the error signal.
    //
    // Return a vector of weight corrections and the local gradient value.
    //
    // The method should be called _after_ `forwardPass`
    BPResult backwardPass(const Input &inputs, double errorSignal,
                          double learningRate) {
        assert(inputs.size() + 1 == weights.size());
        size_t nInputs = weights.size();
        double localGradient = lastActivationGradient * errorSignal;
        double multiplier = learningRate * localGradient;
        Weights delta_W(nInputs, multiplier);
        for (size_t i = 0; i < inputs.size(); ++i) {
            delta_W[i + 1] *= inputs[i];
        }
        lastLocalGradient = localGradient;
        return BPResult{delta_W, localGradient};
    }
};

/// A fully connected layer of perceptrons.
class PerceptronsLayer {
private:
    unsigned int nInputs;
    unsigned int nNeurons;
    vector<BasicPerceptron> neurons;
    Output lastOutput;

public:
    PerceptronsLayer(unsigned int nInputs = 0, unsigned int nOutputs = 0,
                     const ActivationFunction &af = defaultTanh)
        : nInputs(nInputs), nNeurons(nOutputs),
          neurons(nOutputs, BasicPerceptron(nInputs, af)),
          lastOutput(nOutputs) {}

    void init(unique_ptr<rng_type> &rng) {
        for (size_t i = 0; i < neurons.size(); ++i) {
            neurons[i].init(rng);
        }
    }

    void adjustWeights(vector<Weights> weightDeltas) {
        assert(nNeurons == weightDeltas.size());
        for (size_t i = 0; i < neurons.size(); ++i) {
            neurons[i].adjustWeights(weightDeltas[i]);
        }
    }

    // Pages 132-133.
    // Return a vector of outputs.
    Output forwardPass(const Input &inputs) {
        for (auto i = 0u; i < nNeurons; ++i) {
            lastOutput[i] = neurons[i].output(inputs);
        }
        return lastOutput;
    }

    struct BPResult {
        Output propagatedErrorSignals;
        vector<Weights> weightCorrections;
    };

    // Page 134. Calculate back-propagated error signal and corrections to
    // synaptic weights.
    //
    // $$ e_j = \sum_k \delta_k w_{kj} $$
    //
    // where $e_j$ is an error propagated from all downstream neurons to the
    // neuron $j$, $\delta_k$ is the local gradient of the downstream neurons
    // $k$, $w_{kj}$ is the synaptic weight of the $j$-th input of the
    // downstream neuron $k$.
    //
    // The method should be called _after_ `forwardPass`
    BPResult backwardPass(const Input &inputs, const Output &errorSignals,
                          double learningRate) {
        assert(errorSignals.size() == neurons.size());
        auto eta = learningRate;
        vector<Weights> weightDeltas(0);
        Weights propagatedErrorSignals(nInputs, 0.0);
        for (auto k = 0u; k < nNeurons; ++k) {
            auto error_k = errorSignals[k];
            auto r = neurons[k].backwardPass(inputs, error_k, eta);
            Weights delta_Wk = r.weightCorrection;
            double delta_k = r.localGradient;
            Weights Wk = neurons[k].getWeights();
            for (auto j = 0u; j < nInputs; ++j) {
                propagatedErrorSignals[j] += delta_k * Wk[j + 1];
            }
            weightDeltas.push_back(delta_Wk);
        }
        return BPResult{propagatedErrorSignals, weightDeltas};
    }

    friend ostream &operator<<(ostream &out, const PerceptronsLayer &net);
};

/// Multiple layers of perceptrons stack one upon another.
// TODO: rename to MultilayerPerceptron
class PerceptronsNetwork {
private:
    vector<PerceptronsLayer> layers;
    vector<Input> layersInputs;

public:
    PerceptronsNetwork(initializer_list<unsigned int> shape,
                       const ActivationFunction &af = defaultTanh)
        : layers(0), layersInputs(0) {
        auto pIn = shape.begin();
        auto pOut = next(pIn);
        for (; pOut != shape.end(); ++pIn, ++pOut) {
            PerceptronsLayer layer(*pIn, *pOut, af);
            layers.push_back(layer);
        }
    }

    void init(unique_ptr<rng_type> &rng) {
        for (auto i = 0u; i < layers.size(); ++i) {
            layers[i].init(rng);
        }
    }

    Output forwardPass(const Input &inputs) {
        layersInputs.clear();
        layersInputs.push_back(inputs);
        for (auto i = 0u; i < layers.size(); ++i) {
            auto in = layersInputs[i];
            auto out = layers[i].forwardPass(in);
            layersInputs.push_back(out);
        }
        return layersInputs[layers.size()];
    }

    PerceptronsLayer::BPResult
    backwardPass(const Output &errorSignals, double learningRate) {
        Output err(errorSignals);
        PerceptronsLayer::BPResult r;

        for (int i = layers.size()-1; i >= 0; --i) {
            auto layerIn = layersInputs[i];
            r = layers[i].backwardPass(layerIn, err, learningRate);
            layers[i].adjustWeights(r.weightCorrections);
            err = r.propagatedErrorSignals;
        }
        return r;
    }

    friend ostream &operator<<(ostream &out, const PerceptronsNetwork &net);
};

ostream &operator<<(ostream &out, const PerceptronsLayer &layer) {
    size_t n = layer.neurons.size();
    for (size_t j = 0; j < n; ++j) {
        if (j == 0) {
            out << "[";
        } else {
            out << " ";
        }
        out << layer.neurons[j].getWeights();
        if (j >= n - 1) {
            out << "]";
        } else {
            out << ",\n";
        }
    }
    return out;
}

ostream &operator<<(ostream &out, const PerceptronsNetwork &net) {
    for (PerceptronsLayer l : net.layers) {
        out << l << "\n";
    }
    return out;
}

ostream &operator<<(ostream &out, const vector<double> &xs) {
    int n = xs.size();
    out << "[ ";
    for (int i = 0; i < n - 1; ++i) {
        out << xs[i] << ", ";
    }
    out << xs[n - 1] << " ]";
    return out;
}

#endif

#endif /* PERCEPTRON_H */
<|endoftext|>


<commit_before>#include "base.hpp"
#include "ButtonStatus.hpp"
#include "Client.hpp"
#include "CommonData.hpp"
#include "Config.hpp"
#include "Core.hpp"
#include "RemapClass.hpp"
#include "remap.hpp"
#include "util/CallBackWrapper.hpp"
#include "util/EventInputQueue.hpp"
#include "util/EventOutputQueue.hpp"
#include "util/EventWatcher.hpp"
#include "util/KeyboardRepeat.hpp"
#include "util/ListHookedConsumer.hpp"
#include "util/ListHookedKeyboard.hpp"
#include "util/ListHookedPointing.hpp"
#include "util/NumHeldDownKeys.hpp"
#include "util/PressDownKeys.hpp"
#include "util/TimerWrapper.hpp"
#include "RemapFunc/HoldingKeyToKey.hpp"
#include "RemapFunc/KeyOverlaidModifier.hpp"
#include "VirtualKey.hpp"

#include <sys/errno.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOTimerEventSource.h>

namespace org_pqrs_KeyRemap4MacBook {
  namespace Core {
    namespace {
      IOWorkLoop* workLoop = NULL;
      TimerWrapper timer_refresh;

      // ------------------------------------------------------------
      enum {
        REFRESH_DEVICE_INTERVAL = 3000,
      };

      void
      refreshHookedDevice(OSObject* owner, IOTimerEventSource* sender)
      {
        IOLockWrapper::ScopedLock lk(timer_refresh.getlock());

        ListHookedKeyboard::instance().refresh_callback();
        ListHookedConsumer::instance().refresh_callback();
        ListHookedPointing::instance().refresh_callback();

        timer_refresh.setTimeoutMS(REFRESH_DEVICE_INTERVAL);
      }
    }

    void
    start(void)
    {
      EventWatcher::initialize();
      PressDownKeys::initialize();
      FlagStatus::initialize();
      ButtonStatus::initialize();
      KeyRemap4MacBook_client::initialize();
      CommonData::initialize();

      ListHookedKeyboard::instance().initialize();
      ListHookedConsumer::instance().initialize();
      ListHookedPointing::instance().initialize();

      workLoop = IOWorkLoop::workLoop();
      if (! workLoop) {
        IOLOG_ERROR("IOWorkLoop::workLoop failed\n");
      } else {
        timer_refresh.initialize(workLoop, NULL, refreshHookedDevice);
        timer_refresh.setTimeoutMS(REFRESH_DEVICE_INTERVAL);

        RemapClassManager::initialize(*workLoop);
        KeyboardRepeat::initialize(*workLoop);
        EventInputQueue::initialize(*workLoop);
        VirtualKey::initialize(*workLoop);
        EventOutputQueue::initialize(*workLoop);
        RemapFunc::HoldingKeyToKey::static_initialize(*workLoop);
        RemapFunc::KeyOverlaidModifier::static_initialize(*workLoop);
      }

      sysctl_register();
    }

    void
    stop(void)
    {
      sysctl_unregister();

      timer_refresh.terminate();
      ListHookedKeyboard::instance().terminate();
      ListHookedConsumer::instance().terminate();
      ListHookedPointing::instance().terminate();
      RemapClassManager::terminate();
      KeyboardRepeat::terminate();
      EventInputQueue::terminate();
      VirtualKey::terminate();
      EventOutputQueue::terminate();
      RemapFunc::HoldingKeyToKey::static_terminate();
      RemapFunc::KeyOverlaidModifier::static_terminate();

      if (workLoop) {
        workLoop->release();
        workLoop = NULL;
      }

      CommonData::terminate();
      KeyRemap4MacBook_client::terminate();
      EventWatcher::terminate();
      PressDownKeys::terminate();
    }

    // ======================================================================
    bool
    notifierfunc_hookKeyboard(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_hookKeyboard newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIDevice, newService);
      if (! device) return false;
      if (! OSDynamicCast(IOHIKeyboard, device)) return false;

      ListHookedKeyboard::instance().push_back(new ListHookedKeyboard::Item(device));
      ListHookedConsumer::instance().push_back(new ListHookedConsumer::Item(device));
      return true;
    }

    bool
    notifierfunc_unhookKeyboard(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_unhookKeyboard newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIDevice, newService);
      if (! device) return false;
      if (! OSDynamicCast(IOHIKeyboard, device)) return false;

      ListHookedKeyboard::instance().erase(device);
      ListHookedConsumer::instance().erase(device);
      return true;
    }

    bool
    notifierfunc_hookPointing(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_hookPointing newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIDevice, newService);
      if (! device) return false;
      if (! OSDynamicCast(IOHIPointing, device)) return false;

      ListHookedPointing::instance().push_back(new ListHookedPointing::Item(device));
      return true;
    }

    bool
    notifierfunc_unhookPointing(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_unhookPointing newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIDevice, newService);
      if (! device) return false;
      if (! OSDynamicCast(IOHIPointing, device)) return false;

      ListHookedPointing::instance().erase(device);
      return true;
    }

    // ======================================================================
    void
    remap_KeyboardEventCallback(Params_KeyboardEventCallBack& params)
    {
      params.log();

      // ------------------------------------------------------------
      RemapParams remapParams(params);

      // ------------------------------------------------------------
      FlagStatus::set(params.key, params.flags);

      RemapClassManager::remap_key(remapParams);

      // ------------------------------------------------------------
      if (! remapParams.isremapped) {
        params.flags = FlagStatus::makeFlags();
        KeyboardRepeat::set(params);
        EventOutputQueue::FireKey::fire(params);
      }

      if (NumHeldDownKeys::iszero()) {
        NumHeldDownKeys::reset();
        KeyboardRepeat::cancel();
        EventWatcher::reset();
        FlagStatus::reset();
        ButtonStatus::reset();
        EventOutputQueue::FireModifiers::fire(FlagStatus::makeFlags());
        EventOutputQueue::FireRelativePointer::fire();
        PressDownKeys::clear();
      }
    }

    void
    remap_KeyboardSpecialEventCallback(Params_KeyboardSpecialEventCallback& params)
    {
      params.log();

      RemapConsumerParams remapParams(params);

      // ------------------------------------------------------------
      RemapClassManager::remap_consumer(remapParams);

      // ----------------------------------------
      if (! remapParams.isremapped) {
        params.flags = FlagStatus::makeFlags();
        KeyboardRepeat::set(params);
        EventOutputQueue::FireConsumer::fire(params);
      }
    }

    void
    remap_RelativePointerEventCallback(Params_RelativePointerEventCallback& params)
    {
      params.log();

      RemapPointingParams_relative remapParams(params);

      ButtonStatus::set(params.ex_button, params.ex_isbuttondown);

      RemapClassManager::remap_pointing(remapParams);

      // ------------------------------------------------------------
      if (! remapParams.isremapped) {
        EventOutputQueue::FireRelativePointer::fire(ButtonStatus::makeButtons(), params.dx, params.dy);
      }
    }

    void
    remap_ScrollWheelEventCallback(Params_ScrollWheelEventCallback& params)
    {
      params.log();
      EventOutputQueue::FireScrollWheel::fire(params);
    }
  }
}
<commit_msg>update Core.cpp around ListHooked*<commit_after>#include "base.hpp"
#include "ButtonStatus.hpp"
#include "Client.hpp"
#include "CommonData.hpp"
#include "Config.hpp"
#include "Core.hpp"
#include "RemapClass.hpp"
#include "remap.hpp"
#include "util/CallBackWrapper.hpp"
#include "util/EventInputQueue.hpp"
#include "util/EventOutputQueue.hpp"
#include "util/EventWatcher.hpp"
#include "util/KeyboardRepeat.hpp"
#include "util/ListHookedConsumer.hpp"
#include "util/ListHookedKeyboard.hpp"
#include "util/ListHookedPointing.hpp"
#include "util/NumHeldDownKeys.hpp"
#include "util/PressDownKeys.hpp"
#include "util/TimerWrapper.hpp"
#include "RemapFunc/HoldingKeyToKey.hpp"
#include "RemapFunc/KeyOverlaidModifier.hpp"
#include "VirtualKey.hpp"

#include <sys/errno.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOTimerEventSource.h>

namespace org_pqrs_KeyRemap4MacBook {
  namespace Core {
    namespace {
      IOWorkLoop* workLoop = NULL;
      TimerWrapper timer_refresh;

      // ------------------------------------------------------------
      enum {
        REFRESH_DEVICE_INTERVAL = 3000,
      };

      void
      refreshHookedDevice(OSObject* owner, IOTimerEventSource* sender)
      {
        IOLockWrapper::ScopedLock lk(timer_refresh.getlock());

        ListHookedKeyboard::instance().refresh_callback();
        ListHookedConsumer::instance().refresh_callback();
        ListHookedPointing::instance().refresh_callback();

        timer_refresh.setTimeoutMS(REFRESH_DEVICE_INTERVAL);
      }
    }

    void
    start(void)
    {
      EventWatcher::initialize();
      PressDownKeys::initialize();
      FlagStatus::initialize();
      ButtonStatus::initialize();
      KeyRemap4MacBook_client::initialize();
      CommonData::initialize();

      ListHookedKeyboard::instance().initialize();
      ListHookedConsumer::instance().initialize();
      ListHookedPointing::instance().initialize();

      workLoop = IOWorkLoop::workLoop();
      if (! workLoop) {
        IOLOG_ERROR("IOWorkLoop::workLoop failed\n");
      } else {
        timer_refresh.initialize(workLoop, NULL, refreshHookedDevice);
        timer_refresh.setTimeoutMS(REFRESH_DEVICE_INTERVAL);

        RemapClassManager::initialize(*workLoop);
        KeyboardRepeat::initialize(*workLoop);
        EventInputQueue::initialize(*workLoop);
        VirtualKey::initialize(*workLoop);
        EventOutputQueue::initialize(*workLoop);
        RemapFunc::HoldingKeyToKey::static_initialize(*workLoop);
        RemapFunc::KeyOverlaidModifier::static_initialize(*workLoop);
      }

      sysctl_register();
    }

    void
    stop(void)
    {
      sysctl_unregister();

      timer_refresh.terminate();
      ListHookedKeyboard::instance().terminate();
      ListHookedConsumer::instance().terminate();
      ListHookedPointing::instance().terminate();
      RemapClassManager::terminate();
      KeyboardRepeat::terminate();
      EventInputQueue::terminate();
      VirtualKey::terminate();
      EventOutputQueue::terminate();
      RemapFunc::HoldingKeyToKey::static_terminate();
      RemapFunc::KeyOverlaidModifier::static_terminate();

      if (workLoop) {
        workLoop->release();
        workLoop = NULL;
      }

      CommonData::terminate();
      KeyRemap4MacBook_client::terminate();
      EventWatcher::terminate();
      PressDownKeys::terminate();
    }

    // ======================================================================
    bool
    notifierfunc_hookKeyboard(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_hookKeyboard newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
      if (! device) return false;

      ListHookedKeyboard::instance().push_back(new ListHookedKeyboard::Item(device));
      ListHookedConsumer::instance().push_back(new ListHookedConsumer::Item(device));
      return true;
    }

    bool
    notifierfunc_unhookKeyboard(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_unhookKeyboard newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
      if (! device) return false;

      ListHookedKeyboard::instance().erase(device);
      ListHookedConsumer::instance().erase(device);
      return true;
    }

    bool
    notifierfunc_hookPointing(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_hookPointing newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
      if (! device) return false;

      ListHookedPointing::instance().push_back(new ListHookedPointing::Item(device));
      return true;
    }

    bool
    notifierfunc_unhookPointing(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLOG_INFO("notifierfunc_unhookPointing newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
      if (! device) return false;

      ListHookedPointing::instance().erase(device);
      return true;
    }

    // ======================================================================
    void
    remap_KeyboardEventCallback(Params_KeyboardEventCallBack& params)
    {
      params.log();

      // ------------------------------------------------------------
      RemapParams remapParams(params);

      // ------------------------------------------------------------
      FlagStatus::set(params.key, params.flags);

      RemapClassManager::remap_key(remapParams);

      // ------------------------------------------------------------
      if (! remapParams.isremapped) {
        params.flags = FlagStatus::makeFlags();
        KeyboardRepeat::set(params);
        EventOutputQueue::FireKey::fire(params);
      }

      if (NumHeldDownKeys::iszero()) {
        NumHeldDownKeys::reset();
        KeyboardRepeat::cancel();
        EventWatcher::reset();
        FlagStatus::reset();
        ButtonStatus::reset();
        EventOutputQueue::FireModifiers::fire(FlagStatus::makeFlags());
        EventOutputQueue::FireRelativePointer::fire();
        PressDownKeys::clear();
      }
    }

    void
    remap_KeyboardSpecialEventCallback(Params_KeyboardSpecialEventCallback& params)
    {
      params.log();

      RemapConsumerParams remapParams(params);

      // ------------------------------------------------------------
      RemapClassManager::remap_consumer(remapParams);

      // ----------------------------------------
      if (! remapParams.isremapped) {
        params.flags = FlagStatus::makeFlags();
        KeyboardRepeat::set(params);
        EventOutputQueue::FireConsumer::fire(params);
      }
    }

    void
    remap_RelativePointerEventCallback(Params_RelativePointerEventCallback& params)
    {
      params.log();

      RemapPointingParams_relative remapParams(params);

      ButtonStatus::set(params.ex_button, params.ex_isbuttondown);

      RemapClassManager::remap_pointing(remapParams);

      // ------------------------------------------------------------
      if (! remapParams.isremapped) {
        EventOutputQueue::FireRelativePointer::fire(ButtonStatus::makeButtons(), params.dx, params.dy);
      }
    }

    void
    remap_ScrollWheelEventCallback(Params_ScrollWheelEventCallback& params)
    {
      params.log();
      EventOutputQueue::FireScrollWheel::fire(params);
    }
  }
}
<|endoftext|>


<commit_before>//#undef NDEBUG
#include <cassert>
#include <cstddef>
#include <stdio.h>

#include "ctlr/ctlr.h"
#include "benchmark/benchmark.h"

static uint32_t counter;
static struct ctlr_dev_t* dev;

static void clobber()
{
	asm volatile("" : : : "memory");
}
static void escape(void *p)
{
	asm volatile("" : : "g"(p) : "memory");
}

void perf_event_empty(struct ctlr_dev_t* dev,
                      uint32_t num_events,
                      struct ctlr_event_t** events,
                      void *userdata)
{
	counter++;
}

void perf_event_switch(struct ctlr_dev_t* dev,
                       uint32_t num_events,
                       struct ctlr_event_t** events,
                       void *userdata)
{
	for(uint32_t i = 0; i < num_events; i++) {
		struct ctlr_event_t *e = events[i];
		switch(e->type) {
		case CTLR_EVENT_BUTTON:
			break;
		case CTLR_EVENT_ENCODER:
			break;
		case CTLR_EVENT_GRID:
			break;
		default:
			break;
		};
	}
	counter++;
}

void ctlr_dev_empty(benchmark::State& state)
{
	dev = ctlr_dev_connect(CTLR_DEV_NI_MASCHINE_MIKRO_MK2, perf_event_empty, 0, 0);
	counter = 0;
	while (state.KeepRunning()) {
		ctlr_dev_poll(dev);
	}
	ctlr_dev_disconnect(dev);
}

void ctlr_dev_switch(benchmark::State& state)
{
	dev = ctlr_dev_connect(CTLR_DEV_NI_MASCHINE_MIKRO_MK2, perf_event_switch, 0, 0);
	counter = 0;
	while (state.KeepRunning()) {
		ctlr_dev_poll(dev);
	}
	ctlr_dev_disconnect(dev);
}

BENCHMARK(ctlr_dev_empty);
BENCHMARK(ctlr_dev_switch);

BENCHMARK_MAIN()
<commit_msg>remove unused old code<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2012-2020 Daniele Bartolini and individual contributors.
 * License: https://github.com/dbartolini/crown/blob/master/LICENSE
 */

#include "core/math/math.h"
#include "core/math/types.h"
#include "core/types.h"
#include <math.h>
#include <stdio.h> // snprintf

namespace crown
{
bool fequal(f32 a, f32 b, f32 epsilon)
{
	return b <= (a + epsilon)
		&& b >= (a - epsilon)
		;
}

f32 ffract(f32 a)
{
	return a - floorf(a);
}

f32 fabs(f32 a)
{
	return ::fabsf(a);
}

f32 fsin(f32 a)
{
	return sinf(a);
}

f32 fcos(f32 a)
{
	return cosf(a);
}

f32 facos(f32 a)
{
	return ::acosf(a);
}

f32 ftan(f32 a)
{
	return tanf(a);
}

f32 fsqrt(f32 a)
{
	return sqrtf(a);
}

f32 frad(f32 deg)
{
	return deg * PI / 180.0f;
}

f32 fdeg(f32 rad)
{
	return rad * 180.0f / PI;
}

f32 lerp(const f32 p0, const f32 p1, f32 t)
{
	return (1.0f - t) * p0 + t * p1;
}

f32 cosine(const f32 p0, const f32 p1, f32 t)
{
	const f32 f = t * PI;
	const f32 g = (1.0f - fcos(f)) * 0.5f;

	return p0 + g * (p1 - p0);
}

f32 cubic(const f32 p0, const f32 p1, f32 t)
{
	const f32 tt  = t * t;
	const f32 ttt = tt * t;

	return p0 * (2.0f * ttt - 3.0f * tt + 1.0f) + p1 * (3.0f * tt  - 2.0f * ttt);
}

f32 bezier(const f32 p0, const f32 p1, const f32 p2, const f32 p3, f32 t)
{
	const f32 u   = 1.0f - t;
	const f32 tt  = t * t ;
	const f32 uu  = u * u;
	const f32 uuu = uu * u;
	const f32 ttt = tt * t;

	const f32 tmp = (uuu * p0)
		+ (3.0f * uu * t * p1)
		+ (3.0f * u * tt * p2)
		+ (ttt * p3);

	return tmp;
}

f32 catmull_rom(const f32 p0, const f32 p1, const f32 p2, const f32 p3, f32 t)
{
	const f32 tt  = t * t;
	const f32 ttt = tt * t;

	const f32 tmp = (2.0f * p1)
		+ (-p0 + p2) * t
		+ ((2.0f * p0) - (5.0f * p1) + (4.0f * p2) - p3) * tt
		+ (-p0 + (3.0f * p1) + (-3.0f * p2) + p3) * ttt;

	return tmp * 0.5f;
}

const char* to_string(const Vector3& v, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len, "%.4f %.4f %.4f", v.x, v.y, v.z);
	return buf;
}

const char* to_string(const Vector4& v, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len, "%.4f, %.4f, %.4f, %.4f", v.x, v.y, v.z, v.w);
	return buf;
}

const char* to_string(const Quaternion& q, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len, "%.4f %.4f %.4f %.4f", q.x, q.y, q.z, q.w);
	return buf;
}

const char* to_string(const Matrix4x4& m, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len,
		"%.4f, %.4f, %.4f, %.4f\n"
		"%.4f, %.4f, %.4f, %.4f\n"
		"%.4f, %.4f, %.4f, %.4f\n"
		"%.4f, %.4f, %.4f, %.4f"
		, m.x.x, m.x.y, m.x.z, m.y.w
		, m.y.x, m.y.y, m.y.z, m.y.w
		, m.z.x, m.z.y, m.z.z, m.z.w
		, m.t.x, m.t.y, m.t.z, m.t.w
		);
	return buf;
}

} // namespace crown
<commit_msg>core: cleanup<commit_after>/*
 * Copyright (c) 2012-2020 Daniele Bartolini and individual contributors.
 * License: https://github.com/dbartolini/crown/blob/master/LICENSE
 */

#include "core/math/math.h"
#include "core/math/types.h"
#include "core/types.h"
#include <math.h>
#include <stdio.h> // snprintf

namespace crown
{
bool fequal(f32 a, f32 b, f32 epsilon)
{
	return b <= (a + epsilon)
		&& b >= (a - epsilon)
		;
}

f32 ffract(f32 a)
{
	return a - floorf(a);
}

f32 fabs(f32 a)
{
	return ::fabsf(a);
}

f32 fsin(f32 a)
{
	return sinf(a);
}

f32 fcos(f32 a)
{
	return cosf(a);
}

f32 facos(f32 a)
{
	return ::acosf(a);
}

f32 ftan(f32 a)
{
	return tanf(a);
}

f32 fsqrt(f32 a)
{
	return sqrtf(a);
}

f32 frad(f32 deg)
{
	return deg * PI / 180.0f;
}

f32 fdeg(f32 rad)
{
	return rad * 180.0f / PI;
}

f32 lerp(const f32 p0, const f32 p1, f32 t)
{
	return (1.0f - t) * p0 + t * p1;
}

f32 cosine(const f32 p0, const f32 p1, f32 t)
{
	const f32 f = t * PI;
	const f32 g = (1.0f - fcos(f)) * 0.5f;

	return p0 + g * (p1 - p0);
}

f32 cubic(const f32 p0, const f32 p1, f32 t)
{
	const f32 tt  = t * t;
	const f32 ttt = tt * t;

	return p0 * (2.0f * ttt - 3.0f * tt + 1.0f) + p1 * (3.0f * tt  - 2.0f * ttt);
}

f32 bezier(const f32 p0, const f32 p1, const f32 p2, const f32 p3, f32 t)
{
	const f32 u   = 1.0f - t;
	const f32 tt  = t * t ;
	const f32 uu  = u * u;
	const f32 uuu = uu * u;
	const f32 ttt = tt * t;

	const f32 tmp = (uuu * p0)
		+ (3.0f * uu * t * p1)
		+ (3.0f * u * tt * p2)
		+ (ttt * p3);

	return tmp;
}

f32 catmull_rom(const f32 p0, const f32 p1, const f32 p2, const f32 p3, f32 t)
{
	const f32 tt  = t * t;
	const f32 ttt = tt * t;

	const f32 tmp = (2.0f * p1)
		+ (-p0 + p2) * t
		+ ((2.0f * p0) - (5.0f * p1) + (4.0f * p2) - p3) * tt
		+ (-p0 + (3.0f * p1) + (-3.0f * p2) + p3) * ttt;

	return tmp * 0.5f;
}

const char* to_string(const Vector3& v, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len, "( %.4f, %.4f, %.4f )", v.x, v.y, v.z);
	return buf;
}

const char* to_string(const Vector4& v, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len, "( %.4f, %.4f, %.4f, %.4f )", v.x, v.y, v.z, v.w);
	return buf;
}

const char* to_string(const Quaternion& q, char* buf, u32 buf_len)
{
	snprintf(buf, buf_len, "( %.4f, %.4f, %.4f, %.4f )", q.x, q.y, q.z, q.w);
	return buf;
}

const char* to_string(const Matrix4x4& m, char* buf, u32 buf_len)
{
	char bufx[256];
	char bufy[256];
	char bufz[256];
	char bufw[256];
	snprintf(buf, buf_len,
		"( %s, %s, %s, %s )"
		, to_string(m.x, bufx, sizeof(bufx))
		, to_string(m.y, bufy, sizeof(bufy))
		, to_string(m.z, bufz, sizeof(bufz))
		, to_string(m.t, bufw, sizeof(bufw))
		);
	return buf;
}

} // namespace crown
<|endoftext|>


<commit_before>/*!
 * \file dense_matrix_product.cpp
 * \brief Function used to carry out a dense matrix multiplication.
 * \author E. van der Weide
 * \version 4.3.0 "Cardinal"
 *
 * SU2 Lead Developers: Dr. Francisco Palacios (Francisco.D.Palacios@boeing.com).
 *                      Dr. Thomas D. Economon (economon@stanford.edu).
 *
 * SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
 *                 Prof. Piero Colonna's group at Delft University of Technology.
 *                 Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
 *                 Prof. Alberto Guardone's group at Polytechnic University of Milan.
 *                 Prof. Rafael Palacios' group at Imperial College London.
 *
 * Copyright (C) 2012-2016 SU2, the open-source CFD code.
 *
 * SU2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * SU2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
 */

#include "../include/dense_matrix_product.hpp"
#include <cstring>

using namespace std;

#if !defined(HAVE_LIBXSMM) && !defined(HAVE_CBLAS) && !defined(HAVE_MKL)

/*--- Create an unnamed namespace to keep the functions for the
      native implementation of the matrix product local. ---*/
namespace {

/* Macros for accessing submatrices of a matmul using the leading dimension. */
#define A(i, j) a[(j)*lda + (i)]
#define B(i, j) b[(j)*ldb + (i)]
#define C(i, j) c[(j)*ldc + (i)]

/* Naive gemm implementation to handle arbitrary sized matrices. */
void gemm_arbitrary(int m, int n, int k, const su2double *a, int lda,
                    const su2double *b, int ldb, su2double *c, int ldc) {

  /* The order of these loops is tuned for column-major matrices. */
  for (int p = 0; p < k; p++) {
    for (int j = 0; j < n; j++) {
      for (int i = 0; i < m; i++) {
        C(i, j) += A(i, p) * B(p, j);
      }
    }
  }
}

/* Local implementation of the matrix multiplication. */
void su2_gemm(const int m,        const int n,        const int k,
              const su2double *a, const su2double *b, su2double *c) {

  /* Initialize the elements of c to zero. */
  memset(c, 0, m*n*sizeof(su2double));

  /* Set the leading dimensions of the three matrices. */
  const int lda = m;
  const int ldb = k;
  const int ldc = m;

  /* Call gemm_arbitrary to do the actual job. */
  gemm_arbitrary(m, n, k, a, lda, b, ldb, c, ldc);
}

#undef C
#undef B
#undef A

} /* namespace */

#endif

/*--- The actual function to carry out the dense matrix product. ---*/

void DenseMatrixProduct(const int M,        const int N,        const int K,
                        const su2double *A, const su2double *B, su2double *C) {

#ifdef HAVE_LIBXSMM

  /* The gemm function of libxsmm is used to carry out the multiplication.
     Note that libxsmm_gemm expects the matrices in column major order. That's
     why the calling sequence is different from cblas_dgemm. */
  libxsmm_gemm(NULL, NULL, N, M, K, NULL, B, NULL, A, NULL, NULL, C, NULL);

#elif defined (HAVE_CBLAS) || defined(HAVE_MKL)

  /* The standard blas routine dgemm is used for the multiplication. */
  cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K,
              1.0, A, K, B, N, 0.0, C, N);
#else

  /* Native implementation of the matrix product. This optimized implementation
     assumes that the matrices are in column major order. This can be
     accomplished by swapping N and M and A and B. This implementation is based
     on https://github.com/flame/how-to-optimize-gemm. */
  su2_gemm(N, M, K, B, A, C);

#endif
}
<commit_msg>Splitting of the matrix multiplication into blocks.<commit_after>/*!
 * \file dense_matrix_product.cpp
 * \brief Function used to carry out a dense matrix multiplication.
 * \author E. van der Weide
 * \version 4.3.0 "Cardinal"
 *
 * SU2 Lead Developers: Dr. Francisco Palacios (Francisco.D.Palacios@boeing.com).
 *                      Dr. Thomas D. Economon (economon@stanford.edu).
 *
 * SU2 Developers: Prof. Juan J. Alonso's group at Stanford University.
 *                 Prof. Piero Colonna's group at Delft University of Technology.
 *                 Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
 *                 Prof. Alberto Guardone's group at Polytechnic University of Milan.
 *                 Prof. Rafael Palacios' group at Imperial College London.
 *
 * Copyright (C) 2012-2016 SU2, the open-source CFD code.
 *
 * SU2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * SU2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
 */

#include "../include/dense_matrix_product.hpp"
#include <cstring>

using namespace std;

#if !defined(HAVE_LIBXSMM) && !defined(HAVE_CBLAS) && !defined(HAVE_MKL)

/*--- Create an unnamed namespace to keep the functions for the
      native implementation of the matrix product local. ---*/
namespace {

/* Macros for accessing submatrices of a matmul using the leading dimension. */
#define A(i, j) a[(j)*lda + (i)]
#define B(i, j) b[(j)*ldb + (i)]
#define C(i, j) c[(j)*ldc + (i)]

/* Naive gemm implementation to handle arbitrary sized matrices. */
void gemm_arbitrary(int m, int n, int k, const su2double *a, int lda,
                    const su2double *b, int ldb, su2double *c, int ldc) {

  /* The order of these loops is tuned for column-major matrices. */
  for (int p = 0; p < k; p++) {
    for (int j = 0; j < n; j++) {
      for (int i = 0; i < m; i++) {
        C(i, j) += A(i, p) * B(p, j);
      }
    }
  }
}

/* Blocking parameters for the outer kernel.  We multiply mc x kc blocks of A
   with kc x nc panels of B (this approach is referred to as `gebp` in the
   literature). */
constexpr int mc = 256;
constexpr int kc = 128;
constexpr int nc = 128;

/* Compute a portion of C one block at a time.  Handle ragged edges with calls
   to a slow but general function. */
void gemm_inner(int m, int n, int k, const su2double *a, int lda,
                const su2double *b, int ldb, su2double *c, int ldc) {

  /* Carry out the multiplication for this block. At the
     moment simply a call to gemm_arbitrary. */
  gemm_arbitrary(m, n, k, a, lda, b, ldb, c, ldc);
}

/* Local implementation of the matrix multiplication. */
void su2_gemm(const int m,        const int n,        const int k,
              const su2double *a, const su2double *b, su2double *c) {

  /* Initialize the elements of c to zero. */
  memset(c, 0, m*n*sizeof(su2double));

  /* Set the leading dimensions of the three matrices. */
  const int lda = m;
  const int ldb = k;
  const int ldc = m;

  /* The full matrix multiplication is split in several blocks.
     Loop over these blocks. */
  for(int p=0; p<k; p+=kc) {
    int pb = min(k-p, kc);
    for(int j=0; j<n; j+=nc) {
      int jb = min(n-j, nc);
      for(int i=0; i<m; i+=mc) {
        int ib = min(m-i, mc);

        /* Carry out the multiplication for this block. */
        gemm_inner(ib, jb, pb, &A(i, p), lda, &B(p, j), ldb, &C(i, j), ldc);
      }
    }
  }
}

#undef C
#undef B
#undef A

} /* namespace */

#endif

/*--- The actual function to carry out the dense matrix product. ---*/

void DenseMatrixProduct(const int M,        const int N,        const int K,
                        const su2double *A, const su2double *B, su2double *C) {

#ifdef HAVE_LIBXSMM

  /* The gemm function of libxsmm is used to carry out the multiplication.
     Note that libxsmm_gemm expects the matrices in column major order. That's
     why the calling sequence is different from cblas_dgemm. */
    libxsmm_gemm(NULL, NULL, N, M, K, NULL, B, NULL, A, NULL, NULL, C, NULL);

#elif defined (HAVE_CBLAS) || defined(HAVE_MKL)

  /* The standard blas routine dgemm is used for the multiplication. */
  cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K,
              1.0, A, K, B, N, 0.0, C, N);
#else

  /* Native implementation of the matrix product. This optimized implementation
     assumes that the matrices are in column major order. This can be
     accomplished by swapping N and M and A and B. This implementation is based
     on https://github.com/flame/how-to-optimize-gemm. */
  su2_gemm(N, M, K, B, A, C);

#endif
}
<|endoftext|>


<commit_before>/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)

#include "talk/session/media/externalhmac.h"

#include <stdlib.h>  // For malloc/free.

#ifdef SRTP_RELATIVE_PATH
#include "srtp.h"  // NOLINT
#else
#include "third_party/libsrtp/include/srtp.h"
#endif  // SRTP_RELATIVE_PATH

#include "talk/base/logging.h"

// The debug module for authentiation
debug_module_t mod_external_hmac = {
  0,                            // Debugging is off by default
  (char*)"external-hmac-sha-1"  // Printable name for module
};

extern auth_type_t external_hmac;

// Begin test case 0 */
uint8_t
external_hmac_test_case_0_key[20] = {
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b
};

uint8_t
external_hmac_test_case_0_data[8] = {
  0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65   // "Hi There"
};

uint8_t
external_hmac_fake_tag[10] = {
  0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd
};

auth_test_case_t
external_hmac_test_case_0 = {
  20,                                // Octets in key
  external_hmac_test_case_0_key,     // Key
  8,                                 // Octets in data
  external_hmac_test_case_0_data,    // Data
  10,                                // Octets in tag
  external_hmac_fake_tag,            // Tag
  NULL                               // Pointer to next testcase
};

err_status_t
external_hmac_alloc(auth_t** a, int key_len, int out_len) {
  uint8_t* pointer;

  // Check key length - note that we don't support keys larger
  // than 20 bytes yet
  if (key_len > 20)
    return err_status_bad_param;

  // Check output length - should be less than 20 bytes/
  if (out_len > 20)
    return err_status_bad_param;

  // Allocate memory for auth and hmac_ctx_t structures.
  pointer = reinterpret_cast<uint8_t*>(
      malloc(sizeof(external_hmac_ctx_t) + sizeof(auth_t)));
  if (pointer == NULL)
    return err_status_alloc_fail;

  // Set pointers
  *a = (auth_t *)pointer;
  (*a)->type = &external_hmac;
  (*a)->state = pointer + sizeof(auth_t);
  (*a)->out_len = out_len;
  (*a)->key_len = key_len;
  (*a)->prefix_len = 0;

  // Increment global count of all hmac uses.
  external_hmac.ref_count++;

  return err_status_ok;
}

err_status_t
external_hmac_dealloc(auth_t* a) {
  // Zeroize entire state
  memset((uint8_t *)a, sizeof(external_hmac_ctx_t) + sizeof(auth_t));

  // Free memory
  free(a);

  // Decrement global count of all hmac uses.
  external_hmac.ref_count--;

  return err_status_ok;
}

err_status_t
external_hmac_init(external_hmac_ctx_t* state,
                   const uint8_t* key, int key_len) {
  if (key_len > HMAC_KEY_LENGTH)
    return err_status_bad_param;

  memset(state->key, 0, key_len);
  memcpy(state->key, key, key_len);
  state->key_length = key_len;
  return err_status_ok;
}

err_status_t
external_hmac_start(external_hmac_ctx_t* state) {
  return err_status_ok;
}

err_status_t
external_hmac_update(external_hmac_ctx_t* state, const uint8_t* message,
                     int msg_octets) {
  return err_status_ok;
}

err_status_t
external_hmac_compute(external_hmac_ctx_t* state, const void* message,
                      int msg_octets, int tag_len, uint8_t* result) {
  memcpy(result, external_hmac_fake_tag, tag_len);
  return err_status_ok;
}

char external_hmac_description[] = "external hmac sha-1 authentication";

 // auth_type_t external_hmac is the hmac metaobject

auth_type_t
external_hmac  = {
  (auth_alloc_func)      external_hmac_alloc,
  (auth_dealloc_func)    external_hmac_dealloc,
  (auth_init_func)       external_hmac_init,
  (auth_compute_func)    external_hmac_compute,
  (auth_update_func)     external_hmac_update,
  (auth_start_func)      external_hmac_start,
  (char *)               external_hmac_description,
  (int)                  0,  /* instance count */
  (auth_test_case_t *)   &external_hmac_test_case_0,
  (debug_module_t *)     &mod_external_hmac,
  (auth_type_id_t)       EXTERNAL_HMAC_SHA1
};

err_status_t
external_crypto_init() {
  err_status_t status = crypto_kernel_replace_auth_type(
      &external_hmac, EXTERNAL_HMAC_SHA1);
  if (status) {
    LOG(LS_ERROR) << "Error in replacing default auth module, error: "
                  << status;
    return err_status_fail;
  }
  return err_status_ok;
}

#endif  // defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)
<commit_msg>Fixing incorrect memset.<commit_after>/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)

#include "talk/session/media/externalhmac.h"

#include <stdlib.h>  // For malloc/free.

#ifdef SRTP_RELATIVE_PATH
#include "srtp.h"  // NOLINT
#else
#include "third_party/libsrtp/include/srtp.h"
#endif  // SRTP_RELATIVE_PATH

#include "talk/base/logging.h"

// The debug module for authentiation
debug_module_t mod_external_hmac = {
  0,                            // Debugging is off by default
  (char*)"external-hmac-sha-1"  // Printable name for module
};

extern auth_type_t external_hmac;

// Begin test case 0 */
uint8_t
external_hmac_test_case_0_key[20] = {
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b
};

uint8_t
external_hmac_test_case_0_data[8] = {
  0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65   // "Hi There"
};

uint8_t
external_hmac_fake_tag[10] = {
  0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd
};

auth_test_case_t
external_hmac_test_case_0 = {
  20,                                // Octets in key
  external_hmac_test_case_0_key,     // Key
  8,                                 // Octets in data
  external_hmac_test_case_0_data,    // Data
  10,                                // Octets in tag
  external_hmac_fake_tag,            // Tag
  NULL                               // Pointer to next testcase
};

err_status_t
external_hmac_alloc(auth_t** a, int key_len, int out_len) {
  uint8_t* pointer;

  // Check key length - note that we don't support keys larger
  // than 20 bytes yet
  if (key_len > 20)
    return err_status_bad_param;

  // Check output length - should be less than 20 bytes/
  if (out_len > 20)
    return err_status_bad_param;

  // Allocate memory for auth and hmac_ctx_t structures.
  pointer = reinterpret_cast<uint8_t*>(
      malloc(sizeof(external_hmac_ctx_t) + sizeof(auth_t)));
  if (pointer == NULL)
    return err_status_alloc_fail;

  // Set pointers
  *a = (auth_t *)pointer;
  (*a)->type = &external_hmac;
  (*a)->state = pointer + sizeof(auth_t);
  (*a)->out_len = out_len;
  (*a)->key_len = key_len;
  (*a)->prefix_len = 0;

  // Increment global count of all hmac uses.
  external_hmac.ref_count++;

  return err_status_ok;
}

err_status_t
external_hmac_dealloc(auth_t* a) {
  // Zeroize entire state
  memset((uint8_t *)a, 0, sizeof(external_hmac_ctx_t) + sizeof(auth_t));

  // Free memory
  free(a);

  // Decrement global count of all hmac uses.
  external_hmac.ref_count--;

  return err_status_ok;
}

err_status_t
external_hmac_init(external_hmac_ctx_t* state,
                   const uint8_t* key, int key_len) {
  if (key_len > HMAC_KEY_LENGTH)
    return err_status_bad_param;

  memset(state->key, 0, key_len);
  memcpy(state->key, key, key_len);
  state->key_length = key_len;
  return err_status_ok;
}

err_status_t
external_hmac_start(external_hmac_ctx_t* state) {
  return err_status_ok;
}

err_status_t
external_hmac_update(external_hmac_ctx_t* state, const uint8_t* message,
                     int msg_octets) {
  return err_status_ok;
}

err_status_t
external_hmac_compute(external_hmac_ctx_t* state, const void* message,
                      int msg_octets, int tag_len, uint8_t* result) {
  memcpy(result, external_hmac_fake_tag, tag_len);
  return err_status_ok;
}

char external_hmac_description[] = "external hmac sha-1 authentication";

 // auth_type_t external_hmac is the hmac metaobject

auth_type_t
external_hmac  = {
  (auth_alloc_func)      external_hmac_alloc,
  (auth_dealloc_func)    external_hmac_dealloc,
  (auth_init_func)       external_hmac_init,
  (auth_compute_func)    external_hmac_compute,
  (auth_update_func)     external_hmac_update,
  (auth_start_func)      external_hmac_start,
  (char *)               external_hmac_description,
  (int)                  0,  /* instance count */
  (auth_test_case_t *)   &external_hmac_test_case_0,
  (debug_module_t *)     &mod_external_hmac,
  (auth_type_id_t)       EXTERNAL_HMAC_SHA1
};

err_status_t
external_crypto_init() {
  err_status_t status = crypto_kernel_replace_auth_type(
      &external_hmac, EXTERNAL_HMAC_SHA1);
  if (status) {
    LOG(LS_ERROR) << "Error in replacing default auth module, error: "
                  << status;
    return err_status_fail;
  }
  return err_status_ok;
}

#endif  // defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH)
<|endoftext|>


<commit_before>/********************************************************************
* Description: inivar.c
*   prints to stdout the INI file result of a variable-in-section
*   search, useful for scripts that want to pick things out of INI files.
*
*   syntax:  inivar -var <variable> {-sec
} {<-ini inifile>}
*
*   Uses emc.ini as default. <variable> needs to be supplied. If

*   is omitted, first instance of <variable> will be looked for in any
*   section. Otherwise only a match of the variable in
 will
*   be returned.
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
*
* Last change:
********************************************************************/

#include <stdio.h>		/* printf(), fprintf(), FILE, fopen(),*/
#include <stdlib.h>		/* exit() */
#include <string.h>		/* strcmp(), strcpy() */

#include "config.h"
#include "inifile.hh"

int main(int argc, char *argv[])
{
    int t;
    int num = 1;
    char _variable[LINELEN] = "";
    char *variable = 0;
    char _section[LINELEN] = "";
    char *section = 0;
    char path[LINELEN] = "emc.ini";
    const char *inistring;
    int retval;

    /* process command line args, indexing argv[] from [1] */
    for (t = 1; t < argc; t++) {
	if (!strcmp(argv[t], "-ini")) {
	    if (t == argc - 1) {
		/* no arg following -ini, so abort */
		fprintf(stderr,
		    "%s: ini file not specified after -ini\n", argv[0]);
		exit(1);
	    } else {
		strncpy(path, argv[t + 1], LINELEN);
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-var")) {
	    if (t == argc - 1) {
		/* no arg following -var, so abort */
		fprintf(stderr,
		    "%s: variable name not specified after -var\n", argv[0]);
		exit(1);
	    } else {
		strncpy(_variable, argv[t + 1], LINELEN);
		variable = _variable;
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-sec")) {
	    if (t == argc - 1) {
		/* no arg following -sec, so abort */
		fprintf(stderr,
		    "%s: section name not specified after -sec\n", argv[0]);
		exit(1);
	    } else {
		strncpy(_section, argv[t + 1], LINELEN);
		section = _section;
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-num")) {
	    if (t == argc - 1) {
		/* no arg following -num, so abort */
		fprintf(stderr,
		    "%s: line not specified after -num\n", argv[0]);
		exit(1);
	    } else {
		if (sscanf(argv[t + 1], "%i", &num) != 1) {
		    fprintf(stderr,
			"%s: invalid number after -num\n", argv[0]);
		    exit(1);
		}
		t++;		/* step over following arg */
	    }
	} else{
	    /* invalid argument */
	    fprintf(stderr,
		"%s: -var <variable> {-sec
} {<-ini inifile>} [-num <nth item>]\n",
		argv[0]);
	    exit(1);
	}
    }

    /* check that variable was supplied */
    if (0 == variable) {
	fprintf(stderr, "%s: no variable supplied\n", argv[0]);
	exit(1);
    }

    IniFile inifile;
    /* open the inifile */
    inifile.Open(path);
    if (inifile.IsOpen() == false) {
	fprintf(stderr, "%s: can't open %s\n", argv[0], path);
	exit(-1);
    }

    inistring = inifile.Find(variable, section, num);
    if (inistring != NULL) {
	printf("%s\n", inistring);
	retval = 0;
    } else {
	fprintf(stderr, "Can not find -sec %s -var %s -num %i \n", section, variable, num);
	retval = 1;
    }

    exit(retval);
}
<commit_msg>inivar: do tilde expansion on request<commit_after>/********************************************************************
* Description: inivar.c
*   prints to stdout the INI file result of a variable-in-section
*   search, useful for scripts that want to pick things out of INI files.
*
*   syntax:  inivar -var <variable> {-sec
} {<-ini inifile>}
*
*   Uses emc.ini as default. <variable> needs to be supplied. If

*   is omitted, first instance of <variable> will be looked for in any
*   section. Otherwise only a match of the variable in
 will
*   be returned.
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
*
* Last change:
********************************************************************/

#include <stdio.h>		/* printf(), fprintf(), FILE, fopen(),*/
#include <stdlib.h>		/* exit() */
#include <string.h>		/* strcmp(), strcpy() */
#include <limits.h>

#include "config.h"
#include "inifile.hh"

int main(int argc, char *argv[])
{
    int t;
    int num = 1;
    char _variable[LINELEN] = "";
    char *variable = 0;
    char _section[LINELEN] = "";
    char *section = 0;
    char path[LINELEN] = "emc.ini";
    const char *inistring;
    int retval;
    bool tildeexpand=false;

    /* process command line args, indexing argv[] from [1] */
    for (t = 1; t < argc; t++) {
	if (!strcmp(argv[t], "-ini")) {
	    if (t == argc - 1) {
		/* no arg following -ini, so abort */
		fprintf(stderr,
		    "%s: ini file not specified after -ini\n", argv[0]);
		exit(1);
	    } else {
		strncpy(path, argv[t + 1], LINELEN);
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-var")) {
	    if (t == argc - 1) {
		/* no arg following -var, so abort */
		fprintf(stderr,
		    "%s: variable name not specified after -var\n", argv[0]);
		exit(1);
	    } else {
		strncpy(_variable, argv[t + 1], LINELEN);
		variable = _variable;
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-sec")) {
	    if (t == argc - 1) {
		/* no arg following -sec, so abort */
		fprintf(stderr,
		    "%s: section name not specified after -sec\n", argv[0]);
		exit(1);
	    } else {
		strncpy(_section, argv[t + 1], LINELEN);
		section = _section;
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-num")) {
	    if (t == argc - 1) {
		/* no arg following -num, so abort */
		fprintf(stderr,
		    "%s: line not specified after -num\n", argv[0]);
		exit(1);
	    } else {
		if (sscanf(argv[t + 1], "%i", &num) != 1) {
		    fprintf(stderr,
			"%s: invalid number after -num\n", argv[0]);
		    exit(1);
		}
		t++;		/* step over following arg */
	    }
	} else if (!strcmp(argv[t], "-tildeexpand")) {
	    tildeexpand = !tildeexpand;
	} else{
	    /* invalid argument */
	    fprintf(stderr,
		"%s: -var <variable> {-sec
} {<-ini inifile>} [-num <nth item>]\n",
		argv[0]);
	    exit(1);
	}
    }

    /* check that variable was supplied */
    if (0 == variable) {
	fprintf(stderr, "%s: no variable supplied\n", argv[0]);
	exit(1);
    }

    IniFile inifile;
    /* open the inifile */
    inifile.Open(path);
    if (inifile.IsOpen() == false) {
	fprintf(stderr, "%s: can't open %s\n", argv[0], path);
	exit(-1);
    }

    inistring = inifile.Find(variable, section, num);
    if (inistring != NULL) {
	if(tildeexpand)
	{
	    char expanded[PATH_MAX];
	    inifile.TildeExpansion(inistring, expanded, sizeof(expanded));
	    printf("%s\n", expanded);
	} else {
	    printf("%s\n", inistring);
	}
	retval = 0;
    } else {
	fprintf(stderr, "Can not find -sec %s -var %s -num %i \n", section, variable, num);
	retval = 1;
    }

    exit(retval);
}
<|endoftext|>