<commit_before>//Copyright 2016 Adam G. Smith
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http ://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

#include <cstdio>
#include <ctype.h>
#include "solaire/serial/xml.hpp"

namespace solaire { namespace serial {

	struct element {
		typedef std::pair<std::string, std::string> attribute;

		std::vector<attribute> attributes;
		std::vector<element> children;
		std::string body;
		std::string name;
	};

	element from_xml_tree(std::istream& aStream) {
		//! \todo Implement
		return element();
	}

	void primative_value(const std::string& aValue, value_parser& aParser) {
		//! \todo Implement
	}

	inline void primative_value(const std::string& aName, const std::string& aValue, value_parser& aParser) {
		aParser.name(aName.c_str());
		primative_value(aValue, aParser);
	}

	inline void body_value(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		primative_value(aElement.name, aElement.body, aParser);
	}

	inline void attribute_value(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		primative_value(aElement.attributes[0].second, aParser);
	}

	void attribute_object(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_object();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.first, i.second, aParser);
		}
		aParser.end_object();
	}

	void attribute_array(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_array();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.second, aParser);
		}
		aParser.begin_array();
	}

	void child_object(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_object();
		for(const element& i : aElement.children) {
			aParser.name(i.name.c_str());
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.end_object();
	}

	void child_array(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_array();
		for(const element& i : aElement.children) {
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.begin_array();
	}

	void attribute_child_object(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_object();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.first, i.second, aParser);
		}
		for(const element& i : aElement.children) {
			aParser.name(i.name.c_str());
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.end_object();
	}

	void attribute_child_array(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_array();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.second, aParser);
		}
		for(const element& i : aElement.children) {
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.begin_array();
	}

	void pure_attribute(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		//! \todo attribute value / attribute array / attribute object
	}

	void pure_children(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		//! \todo children value / children array / children object
	}

	void mixed_attribute_children(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		//! \todo attribute_children value / attribut_childrene array / attribute_children object
	}

	void child_value(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {

		const bool body = ! aElement.body.empty();
		const bool attributes = ! aElement.attributes.empty();
		const bool children = ! aElement.children.empty();

		if(attributes || children) {
			if(body) {
				switch(aConflictMode)
				{
				case XML_CONFLICT_IGNORE_BODY :
					pure_attribute(aElement, aParser, aConflictMode);
					break;
				case XML_CONFLICT_IGNORE_ATTRIBUTES :
					body_value(aElement, aParser, aConflictMode);
					break;
				default: // XML_CONFLICT_ERROR
					throw std::runtime_error("solaire::serial::from_xml : Element with both body value and attributes (XML_CONFLICT_ERROR)");
				}
			}else {
				if(attributes && ! children) {
					pure_attribute(aElement, aParser, aConflictMode);
				}else if (children && ! attributes) {
					pure_children(aElement, aParser, aConflictMode);
				}else {
					mixed_attribute_children(aElement, aParser, aConflictMode);
				}
			}
		}else if(body) {
			body_value(aElement, aParser, aConflictMode);
		}else {
			aParser.value_void();
		}

		//if(aElement.body.empty()) {
			//if(aElement.children.empty()) {
				// No value
				//aParser.value_void();
			//}else {
			//	if(aElement.attributes.size() == 1 && aElement.attributes[0].first == "value") {
			//		// Attribute value
			//		primative_value(aElement.name, aElement.attributes[0].second, aParser);
			//	}else {
			//		if(aElement.attributes.empty()) {
			//			const std::string& name = aElement.children[0].name;
			//			if(name == "value" || name == "array" || name == "object") {
			//				// Children array
			//				aParser.begin_array();
			//				for(const element& i : aElement.children) child_value(aElement, aParser, aConflictMode);
			//				aParser.end_array();
			//			}else {
			//				// Children object
			//				aParser.begin_object();
			//				for(const element& i : aElement.children) {
			//					aParser.name(i.name.c_str());
			//					child_value(aElement, aParser, aConflictMode);
			//				}
			//				aParser.end_object();
			//			}
			//		}else {
			//			// Attribute / children object
			//			aParser.begin_object();
			//			for(const element::attribute& i : aElement.attributes) {
			//				primative_value(i.first, i.second, aParser);
			//			}
			//			for(const element& i : aElement.children) {
			//				aParser.name(i.name.c_str());
			//				from_xml(aElement, aParser, aConflictMode);
			//			}
			//			aParser.end_object();
			//		}
			//	}
			//}
		//}else {
			//if(aElement.children.empty()) {
			//	// Body value
			//	primative_value(aElement.name, aElement.body, aParser);
			//}else {

			//}
		//}
	}

	void from_xml(std::istream& aStream, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		child_value(from_xml_tree(aStream), aParser, aConflictMode);
	}

	// to_xml

	//! \todo Add header element

	to_xml::to_xml(std::ostream& aStream) :
		mStream(aStream)
	{}

	void to_xml::write_value(const char* const aValue) {
		state& tmp = mStateStack.back();
		++tmp.size;
		if(tmp.is_array) mName = "value";
		mStream << '<' << mName.c_str() << " value=\"" << aValue << "\"/>";
	}

	void to_xml::begin_array() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "array";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_array() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if (tmp.is_object) mName = "array";
		mStream << '</' << mName.c_str() << '>';
	}

	void to_xml::begin_object() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "object";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_object() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if(tmp.is_object) mName = "object";
		mStream << '<' << '/' << mName.c_str() << '>';
		//! \todo Write primative members as attributes
	}

	void to_xml::name(const char* aName) {
		mName = aName;
	}

	void to_xml::value_void() {
		write_value("void");
	}

	void to_xml::value_bool(const bool aValue) {
		write_value(aValue ? "true" : "false");
	}

	void to_xml::value_char(const char aValue) {
		const char tmp[2] = { aValue, '\0' };
		write_value(tmp);
	}

	void to_xml::value_unsigned(const uint64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%llu", aValue);
		write_value(buffer);
	}

	void to_xml::value_signed(const int64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lli", aValue);
		write_value(buffer);
	}

	void to_xml::value_float(const double aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lf", aValue);
		write_value(buffer);
	}

	void to_xml::value_pointer(void* const aValue) {
		char buffer[32];
		buffer[0] = '#';
		snprintf(buffer + 1, 31, "%llu", *reinterpret_cast<uint64_t* const*>(&aValue));
		write_value(buffer);
	}

	void to_xml::value_string(const char* const aValue) {
		write_value(aValue);
	}

}}<commit_msg>Removed old code<commit_after>//Copyright 2016 Adam G. Smith
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http ://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

#include <cstdio>
#include <ctype.h>
#include "solaire/serial/xml.hpp"

namespace solaire { namespace serial {

	struct element {
		typedef std::pair<std::string, std::string> attribute;

		std::vector<attribute> attributes;
		std::vector<element> children;
		std::string body;
		std::string name;
	};

	element from_xml_tree(std::istream& aStream) {
		//! \todo Implement
		return element();
	}

	void primative_value(const std::string& aValue, value_parser& aParser) {
		//! \todo Implement
	}

	inline void primative_value(const std::string& aName, const std::string& aValue, value_parser& aParser) {
		aParser.name(aName.c_str());
		primative_value(aValue, aParser);
	}

	inline void body_value(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		primative_value(aElement.name, aElement.body, aParser);
	}

	inline void attribute_value(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		primative_value(aElement.attributes[0].second, aParser);
	}

	void attribute_object(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_object();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.first, i.second, aParser);
		}
		aParser.end_object();
	}

	void attribute_array(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_array();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.second, aParser);
		}
		aParser.begin_array();
	}

	void child_object(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_object();
		for(const element& i : aElement.children) {
			aParser.name(i.name.c_str());
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.end_object();
	}

	void child_array(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_array();
		for(const element& i : aElement.children) {
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.begin_array();
	}

	void attribute_child_object(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_object();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.first, i.second, aParser);
		}
		for(const element& i : aElement.children) {
			aParser.name(i.name.c_str());
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.end_object();
	}

	void attribute_child_array(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		aParser.begin_array();
		for(const element::attribute& i : aElement.attributes) {
			primative_value(i.second, aParser);
		}
		for(const element& i : aElement.children) {
			child_value(aElement, aParser, aConflictMode);
		}
		aParser.begin_array();
	}

	void pure_attribute(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		//! \todo attribute value / attribute array / attribute object
	}

	void pure_children(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		//! \todo children value / children array / children object
	}

	void mixed_attribute_children(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		//! \todo attribute_children value / attribut_childrene array / attribute_children object
	}

	void child_value(const element& aElement, value_parser& aParser, const xml_conflict_mode aConflictMode) {

		const bool body = ! aElement.body.empty();
		const bool attributes = ! aElement.attributes.empty();
		const bool children = ! aElement.children.empty();

		if(attributes || children) {
			if(body) {
				switch(aConflictMode)
				{
				case XML_CONFLICT_IGNORE_BODY :
					pure_attribute(aElement, aParser, aConflictMode);
					break;
				case XML_CONFLICT_IGNORE_ATTRIBUTES :
					body_value(aElement, aParser, aConflictMode);
					break;
				default: // XML_CONFLICT_ERROR
					throw std::runtime_error("solaire::serial::from_xml : Element with both body value and attributes (XML_CONFLICT_ERROR)");
				}
			}else {
				if(attributes && ! children) {
					pure_attribute(aElement, aParser, aConflictMode);
				}else if (children && ! attributes) {
					pure_children(aElement, aParser, aConflictMode);
				}else {
					mixed_attribute_children(aElement, aParser, aConflictMode);
				}
			}
		}else if(body) {
			body_value(aElement, aParser, aConflictMode);
		}else {
			aParser.value_void();
		}
	}

	void from_xml(std::istream& aStream, value_parser& aParser, const xml_conflict_mode aConflictMode) {
		child_value(from_xml_tree(aStream), aParser, aConflictMode);
	}

	// to_xml

	//! \todo Add header element

	to_xml::to_xml(std::ostream& aStream) :
		mStream(aStream)
	{}

	void to_xml::write_value(const char* const aValue) {
		state& tmp = mStateStack.back();
		++tmp.size;
		if(tmp.is_array) mName = "value";
		mStream << '<' << mName.c_str() << " value=\"" << aValue << "\"/>";
	}

	void to_xml::begin_array() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "array";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_array() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if (tmp.is_object) mName = "array";
		mStream << '</' << mName.c_str() << '>';
	}

	void to_xml::begin_object() {
		if(mStateStack.empty() || mStateStack.back().is_array) mName = "object";
		state tmp;
		tmp.size = 0;
		tmp.is_object = 1;
		mStateStack.push_back(tmp);
		mStream << '<' << mName.c_str() << '>';
	}

	void to_xml::end_object() {
		const state tmp = mStateStack.back();
		mStateStack.pop_back();
		if(tmp.is_object) mName = "object";
		mStream << '<' << '/' << mName.c_str() << '>';
		//! \todo Write primative members as attributes
	}

	void to_xml::name(const char* aName) {
		mName = aName;
	}

	void to_xml::value_void() {
		write_value("void");
	}

	void to_xml::value_bool(const bool aValue) {
		write_value(aValue ? "true" : "false");
	}

	void to_xml::value_char(const char aValue) {
		const char tmp[2] = { aValue, '\0' };
		write_value(tmp);
	}

	void to_xml::value_unsigned(const uint64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%llu", aValue);
		write_value(buffer);
	}

	void to_xml::value_signed(const int64_t aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lli", aValue);
		write_value(buffer);
	}

	void to_xml::value_float(const double aValue) {
		char buffer[32];
		snprintf(buffer, 32, "%lf", aValue);
		write_value(buffer);
	}

	void to_xml::value_pointer(void* const aValue) {
		char buffer[32];
		buffer[0] = '#';
		snprintf(buffer + 1, 31, "%llu", *reinterpret_cast<uint64_t* const*>(&aValue));
		write_value(buffer);
	}

	void to_xml::value_string(const char* const aValue) {
		write_value(aValue);
	}

}}<|endoftext|>


<commit_before>#include "./wrapped_re2.h"

#include <memory>
#include <vector>

#include <node_buffer.h>

using std::vector;

using v8::Array;
using v8::Integer;
using v8::Local;
using v8::String;

using node::Buffer;

NAN_METHOD(WrappedRE2::Exec) {
	NanScope();

	// unpack arguments

	WrappedRE2* re2 = ObjectWrap::Unwrap<WrappedRE2>(args.This());
	if (!re2) {
		NanReturnNull();
	}

	vector<char> buffer;

	char*  data;
	size_t size, lastIndex = 0;
	bool   isBuffer = false;

	if (args[0]->IsString()) {
		if (re2->global) {
			String::Value s(args[0]);
			if (re2->lastIndex > s.length()) {
				re2->lastIndex = 0;
				NanReturnNull();
			}
			Local<String> t(String::New(*s + re2->lastIndex));
			buffer.resize(t->Utf8Length() + 1);
			t->WriteUtf8(&buffer[0]);
		} else {
			Local<String> t(args[0]->ToString());
			buffer.resize(t->Utf8Length() + 1);
			t->WriteUtf8(&buffer[0]);
		}
		size = buffer.size() - 1;
		data = &buffer[0];
	} else if (Buffer::HasInstance(args[0])) {
		isBuffer = true;
		size = Buffer::Length(args[0]);
		if (re2->global) {
			if (re2->lastIndex > size) {
				re2->lastIndex = 0;
				NanReturnNull();
			}
			lastIndex = re2->lastIndex;
		}
		data = Buffer::Data(args[0]);
	} else {
		NanReturnNull();
	}

	// actual work

	vector<StringPiece> groups(re2->regexp.NumberOfCapturingGroups() + 1);

	if (!re2->regexp.Match(StringPiece(data, size), lastIndex, size, RE2::UNANCHORED, &groups[0], groups.size())) {
		if (re2->global) {
			re2->lastIndex = 0;
		}
		NanReturnNull();
	}

	// form a result

	Local<Array> result = NanNew<Array>();

	if (isBuffer) {
		for (size_t i = 0, n = groups.size(); i < n; ++i) {
			const StringPiece& item = groups[i];
			result->Set(NanNew<Integer>(i), NanNewBufferHandle(item.data(), item.size()));
		}
		result->Set(NanNew("index"), NanNew<Integer>(groups[0].data() - data));
	} else {
		for (size_t i = 0, n = groups.size(); i < n; ++i) {
			const StringPiece& item = groups[i];
			result->Set(NanNew<Integer>(i), NanNew<String>(item.data(), item.size()));
		}
		result->Set(NanNew("index"), NanNew<Integer>(getUtf16Length(data, groups[0].data())));
	}

	result->Set(NanNew("input"), args[0]);

	if (re2->global) {
		re2->lastIndex += isBuffer ? groups[0].data() - data + groups[0].size() :
			getUtf16Length(data, groups[0].data() + groups[0].size());
	}

	NanReturnValue(result);
}
<commit_msg>Bugfix: changed to an increment.<commit_after>#include "./wrapped_re2.h"

#include <memory>
#include <vector>

#include <node_buffer.h>

using std::vector;

using v8::Array;
using v8::Integer;
using v8::Local;
using v8::String;

using node::Buffer;

NAN_METHOD(WrappedRE2::Exec) {
	NanScope();

	// unpack arguments

	WrappedRE2* re2 = ObjectWrap::Unwrap<WrappedRE2>(args.This());
	if (!re2) {
		NanReturnNull();
	}

	vector<char> buffer;

	char*  data;
	size_t size, lastIndex = 0;
	bool   isBuffer = false;

	if (args[0]->IsString()) {
		if (re2->global) {
			String::Value s(args[0]);
			if (re2->lastIndex > s.length()) {
				re2->lastIndex = 0;
				NanReturnNull();
			}
			Local<String> t(String::New(*s + re2->lastIndex));
			buffer.resize(t->Utf8Length() + 1);
			t->WriteUtf8(&buffer[0]);
		} else {
			Local<String> t(args[0]->ToString());
			buffer.resize(t->Utf8Length() + 1);
			t->WriteUtf8(&buffer[0]);
		}
		size = buffer.size() - 1;
		data = &buffer[0];
	} else if (Buffer::HasInstance(args[0])) {
		isBuffer = true;
		size = Buffer::Length(args[0]);
		if (re2->global) {
			if (re2->lastIndex > size) {
				re2->lastIndex = 0;
				NanReturnNull();
			}
			lastIndex = re2->lastIndex;
		}
		data = Buffer::Data(args[0]);
	} else {
		NanReturnNull();
	}

	// actual work

	vector<StringPiece> groups(re2->regexp.NumberOfCapturingGroups() + 1);

	if (!re2->regexp.Match(StringPiece(data, size), lastIndex, size, RE2::UNANCHORED, &groups[0], groups.size())) {
		if (re2->global) {
			re2->lastIndex = 0;
		}
		NanReturnNull();
	}

	// form a result

	Local<Array> result = NanNew<Array>();

	if (isBuffer) {
		for (size_t i = 0, n = groups.size(); i < n; ++i) {
			const StringPiece& item = groups[i];
			result->Set(NanNew<Integer>(i), NanNewBufferHandle(item.data(), item.size()));
		}
		result->Set(NanNew("index"), NanNew<Integer>(groups[0].data() - data));
	} else {
		for (size_t i = 0, n = groups.size(); i < n; ++i) {
			const StringPiece& item = groups[i];
			result->Set(NanNew<Integer>(i), NanNew<String>(item.data(), item.size()));
		}
		result->Set(NanNew("index"), NanNew<Integer>(getUtf16Length(data, groups[0].data())));
	}

	result->Set(NanNew("input"), args[0]);

	if (re2->global) {
		re2->lastIndex += isBuffer ? groups[0].data() - data + groups[0].size() - lastIndex :
			getUtf16Length(data, groups[0].data() + groups[0].size());
	}

	NanReturnValue(result);
}
<|endoftext|>


<commit_before>#ifndef _GENETIC_H_INCLUDED_
#define _GENETIC_H_INCLUDED_

#include "neuron.hpp"
#include <random>

namespace neuron
{
    std::random_device gen;
    std::mt19937 mt(gen());
    std::uniform_real_distribution<double> dist(0.0, 1.0);

    double rand() {
        return dist(mt);
    }

    //returns random number between 0 to max
    double randMax(int max) {
        return rand() * max;
    }

    bool chance(double percent) {
        return percent < rand();
    }

    template <uint32_t SIZE>
    void random(Net<SIZE> & subject) {
        for (int c = 0; c < SIZE; ++c) {
            for (int r = 0; r < SIZE; ++r) {
                if (subject.hasSynapse(c, r)) {
                    subject[c][r] = randMax(2) - 1.;
                }
            }
        }
    }

    template <uint32_t SIZE>
    Net<SIZE> cross(const Net<SIZE> & mother, const Net<SIZE> & father) {
        const Net<SIZE> * parents[2] = {&mother, &father};
        Net<SIZE> child;

        int inheritence = 1;
        for (int c = 0; c < SIZE; ++c) {
            for (int r = 0; r < SIZE; ++r) {
                if (mother.hasSynapse(c, r)) {
                    // alternate parents
                    child[c][r] = (*parents[inheritence = !inheritence])[c][r];
                }
            }
        }

        return child;
    }

    template <uint32_t SIZE>
    void mutate(Net<SIZE> & subject, double rate) {
        for (int c = 0; c < SIZE; ++c) {
            for (int r = 0; r < SIZE; ++r) {
                if (subject.hasSynapse(c, r) && chance(rate)) {
                    subject[c][r] += rand() - .5;
                }
            }
        }
    }
}

#endif // _GENETIC_H_INCLUDED_
<commit_msg>Change mutation to be more random<commit_after>#ifndef _GENETIC_H_INCLUDED_
#define _GENETIC_H_INCLUDED_

#include "neuron.hpp"
#include <random>

namespace neuron
{
    std::random_device gen;
    std::mt19937 mt(gen());
    std::uniform_real_distribution<double> dist(0.0, 1.0);

    double rand() {
        return dist(mt);
    }

    //returns random number between 0 to max
    double randMax(int max) {
        return rand() * max;
    }

    bool chance(double percent) {
        return percent < rand();
    }

    template <uint32_t SIZE>
    void random(Net<SIZE> & subject) {
        for (int c = 0; c < SIZE; ++c) {
            for (int r = 0; r < SIZE; ++r) {
                if (subject.hasSynapse(c, r)) {
                    subject[c][r] = randMax(2) - 1.;
                }
            }
        }
    }

    template <uint32_t SIZE>
    Net<SIZE> cross(const Net<SIZE> & mother, const Net<SIZE> & father) {
        const Net<SIZE> * parents[2] = {&mother, &father};
        Net<SIZE> child;

        int inheritence = 1;
        for (int c = 0; c < SIZE; ++c) {
            for (int r = 0; r < SIZE; ++r) {
                if (mother.hasSynapse(c, r)) {
                    // alternate parents
                    child[c][r] = (*parents[inheritence = !inheritence])[c][r];
                }
            }
        }

        return child;
    }

    template <uint32_t SIZE>
    void mutate(Net<SIZE> & subject, double rate) {
        for (int c = 0; c < SIZE; ++c) {
            for (int r = 0; r < SIZE; ++r) {
                if (subject.hasSynapse(c, r) && chance(rate)) {
                    if (chance(0.5)) {
                        subject[c][r] += rand() - .5;
                    } else {
                        subject[c][r] = randMax(2) - 1.;
                    }
                }
            }
        }
    }
}

#endif // _GENETIC_H_INCLUDED_
<|endoftext|>


<commit_before>#include <iso646.h>

#include "cell.h"
#include "rtl_exec.h"
#include "socketx.h"

namespace rtl {

Cell net$tcpSocket()
{
#ifdef _WIN32
    static bool initialized = false;
    if (!initialized) {
        WSADATA wsa;
        WSAStartup(MAKEWORD(1, 1), &wsa);
        initialized = true;
    }
#endif
    Cell r;
    SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
    r.array_index_for_write(0) = Cell(number_from_sint32(static_cast<int32_t>(s)));
    return r;
}

Cell net$socket_accept(Cell &handle)
{
    SOCKET s = number_to_sint32(handle.number());
    sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    SOCKET r = accept(s, reinterpret_cast<sockaddr *>(&sin), &slen);
    if (r < 0) {
        perror("accept");
        return Cell();
    }
    Cell client;
    client.array_index_for_write(0) = Cell(number_from_sint32(static_cast<int32_t>(r)));
    return client;
}

void net$socket_close(Cell &handle)
{
    SOCKET s = number_to_sint32(handle.number());
    closesocket(s);
}

void net$socket_connect(Cell &handle, const std::string &host, Number port)
{
    SOCKET s = number_to_sint32(handle.number());
    int p = number_to_sint32(port);
    in_addr addr;
    addr.s_addr = inet_addr(host.c_str());
    if (addr.s_addr == INADDR_NONE) {
        struct hostent *he = gethostbyname(host.c_str());
        if (he == NULL) {
            return;
        }
        addr = *reinterpret_cast<in_addr *>(he->h_addr);
    }
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr = addr;
    sin.sin_port = htons(static_cast<uint16_t>(p));
    int r = connect(s, reinterpret_cast<sockaddr *>(&sin), sizeof(sin));
    if (r < 0) {
        perror("connect");
    }
}

void net$socket_listen(Cell &handle, Number port)
{
    SOCKET s = number_to_sint32(handle.number());
    int on = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(on), sizeof(on));
    int p = number_to_sint32(port);
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(static_cast<uint16_t>(p));
    int r = bind(s, reinterpret_cast<sockaddr *>(&sin), sizeof(sin));
    if (r < 0) {
        perror("bind");
        return;
    }
    r = listen(s, 5);
    if (r < 0) {
        perror("listen");
        return;
    }
}

std::string net$socket_recv(Cell &handle, Number count)
{
    SOCKET s = number_to_sint32(handle.number());
    int n = number_to_sint32(count);
    std::string buf(n, '\0');
    int r = recv(s, const_cast<char *>(buf.data()), n, 0);
    if (r < 0) {
        perror("recv");
        return "";
    }
    buf.resize(r);
    return buf;
}

void net$socket_send(Cell &handle, const std::string &data)
{
    SOCKET s = number_to_sint32(handle.number());
    send(s, data.data(), static_cast<int>(data.length()), 0);
}

bool net$socket_select(Cell *read, Cell *write, Cell *error, Number timeout_seconds)
{
    fd_set rfds, wfds, efds;
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&efds);
    int nfds = 0;

    std::vector<Cell> &ra = read->array_for_write();
    for (auto s: ra) {
        int fd = number_to_sint32(s.array_for_write()[0].number());
        FD_SET(fd, &rfds);
        if (fd+1 > nfds) {
            nfds = fd+1;
        }
    }

    std::vector<Cell> &wa = write->array_for_write();
    for (auto s: wa) {
        int fd = number_to_sint32(s.array_for_write()[0].number());
        FD_SET(fd, &wfds);
        if (fd+1 > nfds) {
            nfds = fd+1;
        }
    }

    std::vector<Cell> &ea = error->array_for_write();
    for (auto s: ea) {
        int fd = number_to_sint32(s.array_for_write()[0].number());
        FD_SET(fd, &efds);
        if (fd+1 > nfds) {
            nfds = fd+1;
        }
    }

    struct timeval actual_tv;
    struct timeval *tv = NULL;
    if (not number_is_negative(timeout_seconds)) {
        actual_tv.tv_sec = number_to_sint32(number_trunc(timeout_seconds));
        actual_tv.tv_usec = number_to_sint32(number_modulo(number_multiply(timeout_seconds, number_from_sint32(1000000)), number_from_sint32(1000000)));
        tv = &actual_tv;
    }
    int r = select(nfds, &rfds, &wfds, &efds, tv);
    if (r < 0) {
        throw RtlException(Exception_net$SocketException, "");
    }
    if (r == 0) {
        ra.clear();
        wa.clear();
        ea.clear();
        return false;
    }

    for (auto i = ra.end(); i != ra.begin(); ) {
        --i;
        if (not FD_ISSET(number_to_sint32(i->array_for_write()[0].number()), &rfds)) {
            ra.erase(i);
        }
    }

    for (auto i = wa.end(); i != wa.begin(); ) {
        --i;
        if (not FD_ISSET(number_to_sint32(i->array_for_write()[0].number()), &wfds)) {
            wa.erase(i);
        }
    }

    for (auto i = ea.end(); i != ea.begin(); ) {
        --i;
        if (not FD_ISSET(number_to_sint32(i->array_for_write()[0].number()), &efds)) {
            ea.erase(i);
        }
    }

    return true;
}

}
<commit_msg>Use forward iterators properly<commit_after>#include <iso646.h>

#include "cell.h"
#include "rtl_exec.h"
#include "socketx.h"

namespace rtl {

Cell net$tcpSocket()
{
#ifdef _WIN32
    static bool initialized = false;
    if (!initialized) {
        WSADATA wsa;
        WSAStartup(MAKEWORD(1, 1), &wsa);
        initialized = true;
    }
#endif
    Cell r;
    SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
    r.array_index_for_write(0) = Cell(number_from_sint32(static_cast<int32_t>(s)));
    return r;
}

Cell net$socket_accept(Cell &handle)
{
    SOCKET s = number_to_sint32(handle.number());
    sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    SOCKET r = accept(s, reinterpret_cast<sockaddr *>(&sin), &slen);
    if (r < 0) {
        perror("accept");
        return Cell();
    }
    Cell client;
    client.array_index_for_write(0) = Cell(number_from_sint32(static_cast<int32_t>(r)));
    return client;
}

void net$socket_close(Cell &handle)
{
    SOCKET s = number_to_sint32(handle.number());
    closesocket(s);
}

void net$socket_connect(Cell &handle, const std::string &host, Number port)
{
    SOCKET s = number_to_sint32(handle.number());
    int p = number_to_sint32(port);
    in_addr addr;
    addr.s_addr = inet_addr(host.c_str());
    if (addr.s_addr == INADDR_NONE) {
        struct hostent *he = gethostbyname(host.c_str());
        if (he == NULL) {
            return;
        }
        addr = *reinterpret_cast<in_addr *>(he->h_addr);
    }
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr = addr;
    sin.sin_port = htons(static_cast<uint16_t>(p));
    int r = connect(s, reinterpret_cast<sockaddr *>(&sin), sizeof(sin));
    if (r < 0) {
        perror("connect");
    }
}

void net$socket_listen(Cell &handle, Number port)
{
    SOCKET s = number_to_sint32(handle.number());
    int on = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(on), sizeof(on));
    int p = number_to_sint32(port);
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(static_cast<uint16_t>(p));
    int r = bind(s, reinterpret_cast<sockaddr *>(&sin), sizeof(sin));
    if (r < 0) {
        perror("bind");
        return;
    }
    r = listen(s, 5);
    if (r < 0) {
        perror("listen");
        return;
    }
}

std::string net$socket_recv(Cell &handle, Number count)
{
    SOCKET s = number_to_sint32(handle.number());
    int n = number_to_sint32(count);
    std::string buf(n, '\0');
    int r = recv(s, const_cast<char *>(buf.data()), n, 0);
    if (r < 0) {
        perror("recv");
        return "";
    }
    buf.resize(r);
    return buf;
}

void net$socket_send(Cell &handle, const std::string &data)
{
    SOCKET s = number_to_sint32(handle.number());
    send(s, data.data(), static_cast<int>(data.length()), 0);
}

bool net$socket_select(Cell *read, Cell *write, Cell *error, Number timeout_seconds)
{
    fd_set rfds, wfds, efds;
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&efds);
    int nfds = 0;

    std::vector<Cell> &ra = read->array_for_write();
    for (auto s: ra) {
        int fd = number_to_sint32(s.array_for_write()[0].number());
        FD_SET(fd, &rfds);
        if (fd+1 > nfds) {
            nfds = fd+1;
        }
    }

    std::vector<Cell> &wa = write->array_for_write();
    for (auto s: wa) {
        int fd = number_to_sint32(s.array_for_write()[0].number());
        FD_SET(fd, &wfds);
        if (fd+1 > nfds) {
            nfds = fd+1;
        }
    }

    std::vector<Cell> &ea = error->array_for_write();
    for (auto s: ea) {
        int fd = number_to_sint32(s.array_for_write()[0].number());
        FD_SET(fd, &efds);
        if (fd+1 > nfds) {
            nfds = fd+1;
        }
    }

    struct timeval actual_tv;
    struct timeval *tv = NULL;
    if (not number_is_negative(timeout_seconds)) {
        actual_tv.tv_sec = number_to_sint32(number_trunc(timeout_seconds));
        actual_tv.tv_usec = number_to_sint32(number_modulo(number_multiply(timeout_seconds, number_from_sint32(1000000)), number_from_sint32(1000000)));
        tv = &actual_tv;
    }
    int r = select(nfds, &rfds, &wfds, &efds, tv);
    if (r < 0) {
        throw RtlException(Exception_net$SocketException, "");
    }
    if (r == 0) {
        ra.clear();
        wa.clear();
        ea.clear();
        return false;
    }

    for (auto i = ra.begin(); i != ra.end(); ) {
        if (FD_ISSET(number_to_sint32(i->array_for_write()[0].number()), &rfds)) {
            ++i;
        } else {
            ra.erase(i);
        }
    }

    for (auto i = wa.begin(); i != wa.end(); ) {
        if (FD_ISSET(number_to_sint32(i->array_for_write()[0].number()), &wfds)) {
            ++i;
        } else {
            wa.erase(i);
        }
    }

    for (auto i = ea.begin(); i != ea.end(); ) {
        if (FD_ISSET(number_to_sint32(i->array_for_write()[0].number()), &efds)) {
            ++i;
        } else {
            ea.erase(i);
        }
    }

    return true;
}

}
<|endoftext|>


<commit_before>// LAF OS Library
// Copyright (C) 2020  Igara Studio S.A.
// Copyright (C) 2016-2017  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "os/win/pen.h"

#include "base/convert_to.h"
#include "base/debug.h"
#include "base/fs.h"
#include "base/log.h"
#include "base/sha1.h"
#include "base/string.h"

#include <iostream>

namespace os {

namespace {

typedef UINT (API* WTInfoW_Func)(UINT, UINT, LPVOID);
typedef HCTX (API* WTOpenW_Func)(HWND, LPLOGCONTEXTW, BOOL);
typedef BOOL (API* WTClose_Func)(HCTX);
typedef BOOL (API* WTPacket_Func)(HCTX, UINT, LPVOID);
typedef int (API* WTQueueSizeGet_Func)(HCTX);
typedef BOOL (API* WTQueueSizeSet_Func)(HCTX, int);

WTInfoW_Func WTInfo;
WTOpenW_Func WTOpen;
WTClose_Func WTClose;
WTPacket_Func WTPacket;
WTQueueSizeGet_Func WTQueueSizeGet;
WTQueueSizeSet_Func WTQueueSizeSet;

} // anonymous namespace

PenAPI::PenAPI()
  : m_wintabLib(nullptr)
{
}

PenAPI::~PenAPI()
{
  if (!m_wintabLib)
    return;

  base::unload_dll(m_wintabLib);
  m_wintabLib = nullptr;
}

HCTX PenAPI::open(HWND hwnd)
{
  if (!m_wintabLib && !loadWintab())
    return nullptr;

  // Log Wintab ID
  {
    UINT nchars = WTInfo(WTI_INTERFACE, IFC_WINTABID, nullptr);
    if (nchars > 0 && nchars < 1024) {
      std::vector<WCHAR> buf(nchars+1, 0);
      WTInfo(WTI_INTERFACE, IFC_WINTABID, &buf[0]);
      LOG("PEN: Wintab ID \"%s\"\n", base::to_utf8(&buf[0]).c_str());
    }
  }

  // Log Wintab version for debugging purposes
  {
    WORD specVer = 0;
    WORD implVer = 0;
    UINT options = 0;
    WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specVer);
    WTInfo(WTI_INTERFACE, IFC_IMPLVERSION, &implVer);
    WTInfo(WTI_INTERFACE, IFC_CTXOPTIONS, &options);
    LOG("PEN: Wintab spec v%d.%d impl v%d.%d options 0x%x\n",
        (specVer & 0xff00) >> 8, (specVer & 0xff),
        (implVer & 0xff00) >> 8, (implVer & 0xff), options);
  }

  LOGCONTEXTW logctx;
  memset(&logctx, 0, sizeof(LOGCONTEXTW));
  UINT infoRes = WTInfo(WTI_DEFSYSCTX, 0, &logctx);

  // TODO Sometimes we receive infoRes=88 from WTInfo and logctx.lcOptions=0
  //      while sizeof(LOGCONTEXTW) is 212
  ASSERT(infoRes == sizeof(LOGCONTEXTW));
  ASSERT(logctx.lcOptions & CXO_SYSTEM);

#if 0 // We shouldn't bypass WTOpen() if the return value from
      // WTInfo() isn't the expected one, WTOpen() should just fail
      // anyway.
  if (infoRes != sizeof(LOGCONTEXTW)) {
    LOG(ERROR)
      << "PEN: Not supported WTInfo:\n"
      << "     Expected context size: " << sizeof(LOGCONTEXTW) << "\n"
      << "     Actual context size: " << infoRes << "\n"
      << "     Options: " << logctx.lcOptions << ")\n";
    return nullptr;
  }
#endif

  logctx.lcOptions |=
    CXO_MESSAGES |
    CXO_CSRMESSAGES;
  logctx.lcPktData = PACKETDATA;
  logctx.lcPktMode = PACKETMODE;
  logctx.lcMoveMask = PACKETDATA;

  AXIS pressure;
  infoRes = WTInfo(WTI_DEVICES, DVC_NPRESSURE, &pressure);
  ASSERT(infoRes == sizeof(AXIS));
  if (infoRes == sizeof(AXIS)) {
    m_minPressure = pressure.axMin;
    m_maxPressure = pressure.axMax;
    LOG("PEN: Min/max pressure values [%d,%d]\n", pressure.axMin, pressure.axMax);
  }

  LOG("PEN: Opening context, options 0x%x\n", logctx.lcOptions);
  HCTX ctx = WTOpen(hwnd, &logctx, TRUE);
  if (!ctx) {
    LOG("PEN: Error attaching pen to display\n");
    return nullptr;
  }

  // Make the queue bigger as recommended by Wacom docs:
  //
  //   "To prevent your queue from overflowing, increase the size of
  //    your context's queue with the WTQueueSizeSet() function to a
  //    value between 32 and 128. Memory for packet queues is a limited
  //    resource, so be sure check that your call to WTQueueSizeSet()
  //    succeeds. If WTQueueSizeSet() fails, request a smaller queue
  //    size."
  //
  // https://developer-docs.wacom.com/display/DevDocs/Window+Developers+FAQ
  int q = WTQueueSizeGet(ctx);
  LOG("PEN: Original queue size=%d\n", q);
  if (q < 128) {
    for (int r=128; r>=q; r-=8) {
      if (WTQueueSizeSet(ctx, r))
        break;
    }
  }
  q = WTQueueSizeGet(ctx);
  LOG("PEN: New queue size=%d\n", q);

  LOG("PEN: Pen attached to display, new context %p\n", ctx);
  return ctx;
}

void PenAPI::close(HCTX ctx)
{
  LOG("PEN: Closing context %p\n", ctx);
  if (ctx) {
    ASSERT(m_wintabLib);
    LOG("PEN: Pen detached from window\n");
    WTClose(ctx);
  }
}

bool PenAPI::packet(HCTX ctx, UINT serial, LPVOID packet)
{
  return (WTPacket(ctx, serial, packet) ? true: false);
}

bool PenAPI::loadWintab()
{
  ASSERT(!m_wintabLib);

  m_wintabLib = base::load_dll("wintab32.dll");
  if (!m_wintabLib) {
    LOG(ERROR) << "PEN: wintab32.dll is not present\n";
    return false;
  }

  if (isBuggyDll()) {
    base::unload_dll(m_wintabLib);
    m_wintabLib = nullptr;
    return false;
  }

  WTInfo = base::get_dll_proc<WTInfoW_Func>(m_wintabLib, "WTInfoW");
  WTOpen = base::get_dll_proc<WTOpenW_Func>(m_wintabLib, "WTOpenW");
  WTClose = base::get_dll_proc<WTClose_Func>(m_wintabLib, "WTClose");
  WTPacket = base::get_dll_proc<WTPacket_Func>(m_wintabLib, "WTPacket");
  WTQueueSizeGet = base::get_dll_proc<WTQueueSizeGet_Func>(m_wintabLib, "WTQueueSizeGet");
  WTQueueSizeSet = base::get_dll_proc<WTQueueSizeSet_Func>(m_wintabLib, "WTQueueSizeSet");
  if (!WTInfo || !WTOpen || !WTClose || !WTPacket ||
      !WTQueueSizeGet || !WTQueueSizeSet) {
    LOG(ERROR) << "PEN: wintab32.dll does not contain all required functions\n";
    return false;
  }

  LOG("PEN: Wintab library loaded\n");
  return true;
}

bool PenAPI::isBuggyDll()
{
  ASSERT(m_wintabLib);

  WCHAR wpath[MAX_PATH];
  memset(wpath, 0, sizeof(wpath));
  GetModuleFileNameW((HMODULE)m_wintabLib, wpath, sizeof(wpath) / sizeof(WCHAR));

  // Ugly hack to bypass the buggy WALTOP International Corp .dll that
  // hangs Aseprite completely when we call its WTInfo function.
  std::string path = base::to_utf8(wpath);
  if (base::is_file(path)) {
    std::string checksum =
      base::convert_to<std::string>(base::Sha1::calculateFromFile(path));
    LOG("PEN: SHA1 <%s> of <%s>\n", checksum.c_str(), path.c_str());
    if (checksum == "a3ba0d9c0f5d8b9f4070981b243a80579f8be105")
      return true;
  }
  return false;
}

} // namespace os
<commit_msg>[win] Log more information about the wintab context<commit_after>// LAF OS Library
// Copyright (C) 2020  Igara Studio S.A.
// Copyright (C) 2016-2017  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "os/win/pen.h"

#include "base/convert_to.h"
#include "base/debug.h"
#include "base/fs.h"
#include "base/log.h"
#include "base/sha1.h"
#include "base/string.h"

#include <iostream>

namespace os {

namespace {

typedef UINT (API* WTInfoW_Func)(UINT, UINT, LPVOID);
typedef HCTX (API* WTOpenW_Func)(HWND, LPLOGCONTEXTW, BOOL);
typedef BOOL (API* WTClose_Func)(HCTX);
typedef BOOL (API* WTPacket_Func)(HCTX, UINT, LPVOID);
typedef int (API* WTQueueSizeGet_Func)(HCTX);
typedef BOOL (API* WTQueueSizeSet_Func)(HCTX, int);

WTInfoW_Func WTInfo;
WTOpenW_Func WTOpen;
WTClose_Func WTClose;
WTPacket_Func WTPacket;
WTQueueSizeGet_Func WTQueueSizeGet;
WTQueueSizeSet_Func WTQueueSizeSet;

} // anonymous namespace

PenAPI::PenAPI()
  : m_wintabLib(nullptr)
{
}

PenAPI::~PenAPI()
{
  if (!m_wintabLib)
    return;

  base::unload_dll(m_wintabLib);
  m_wintabLib = nullptr;
}

HCTX PenAPI::open(HWND hwnd)
{
  if (!m_wintabLib && !loadWintab())
    return nullptr;

  // Log Wintab ID
  {
    UINT nchars = WTInfo(WTI_INTERFACE, IFC_WINTABID, nullptr);
    if (nchars > 0 && nchars < 1024) {
      std::vector<WCHAR> buf(nchars+1, 0);
      WTInfo(WTI_INTERFACE, IFC_WINTABID, &buf[0]);
      LOG("PEN: Wintab ID \"%s\"\n", base::to_utf8(&buf[0]).c_str());
    }
  }

  // Log Wintab version for debugging purposes
  {
    WORD specVer = 0;
    WORD implVer = 0;
    UINT options = 0;
    WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specVer);
    WTInfo(WTI_INTERFACE, IFC_IMPLVERSION, &implVer);
    WTInfo(WTI_INTERFACE, IFC_CTXOPTIONS, &options);
    LOG("PEN: Wintab spec v%d.%d impl v%d.%d options 0x%x\n",
        (specVer & 0xff00) >> 8, (specVer & 0xff),
        (implVer & 0xff00) >> 8, (implVer & 0xff), options);
  }

  LOGCONTEXTW logctx;
  memset(&logctx, 0, sizeof(LOGCONTEXTW));
  UINT infoRes = WTInfo(WTI_DEFSYSCTX, 0, &logctx);

  // TODO Sometimes we receive infoRes=88 from WTInfo and logctx.lcOptions=0
  //      while sizeof(LOGCONTEXTW) is 212
  ASSERT(infoRes == sizeof(LOGCONTEXTW));
  ASSERT(logctx.lcOptions & CXO_SYSTEM);

#if 0 // We shouldn't bypass WTOpen() if the return value from
      // WTInfo() isn't the expected one, WTOpen() should just fail
      // anyway.
  if (infoRes != sizeof(LOGCONTEXTW)) {
    LOG(ERROR)
      << "PEN: Not supported WTInfo:\n"
      << "     Expected context size: " << sizeof(LOGCONTEXTW) << "\n"
      << "     Actual context size: " << infoRes << "\n"
      << "     Options: " << logctx.lcOptions << ")\n";
    return nullptr;
  }
#endif

  LOG("PEN: Context pktRate=%d in=%d,%d,%d,%d out=%d,%d,%d,%d sys=%d,%d,%d,%d\n",
      logctx.lcPktRate,
      logctx.lcInOrgX, logctx.lcInOrgY, logctx.lcInExtX, logctx.lcInExtY,
      logctx.lcOutOrgX, logctx.lcOutOrgY, logctx.lcOutExtX, logctx.lcOutExtY,
      logctx.lcSysOrgX, logctx.lcSysOrgY, logctx.lcSysExtX, logctx.lcSysExtY);

  logctx.lcOptions |=
    CXO_MESSAGES |
    CXO_CSRMESSAGES;
  logctx.lcPktData = PACKETDATA;
  logctx.lcPktMode = PACKETMODE;
  logctx.lcMoveMask = PACKETDATA;

  AXIS pressure;
  infoRes = WTInfo(WTI_DEVICES, DVC_NPRESSURE, &pressure);
  ASSERT(infoRes == sizeof(AXIS));
  if (infoRes == sizeof(AXIS)) {
    m_minPressure = pressure.axMin;
    m_maxPressure = pressure.axMax;
    LOG("PEN: Min/max pressure values [%d,%d]\n", pressure.axMin, pressure.axMax);
  }

  LOG("PEN: Opening context, options 0x%x\n", logctx.lcOptions);
  HCTX ctx = WTOpen(hwnd, &logctx, TRUE);
  if (!ctx) {
    LOG("PEN: Error attaching pen to display\n");
    return nullptr;
  }

  // Make the queue bigger as recommended by Wacom docs:
  //
  //   "To prevent your queue from overflowing, increase the size of
  //    your context's queue with the WTQueueSizeSet() function to a
  //    value between 32 and 128. Memory for packet queues is a limited
  //    resource, so be sure check that your call to WTQueueSizeSet()
  //    succeeds. If WTQueueSizeSet() fails, request a smaller queue
  //    size."
  //
  // https://developer-docs.wacom.com/display/DevDocs/Window+Developers+FAQ
  int q = WTQueueSizeGet(ctx);
  LOG("PEN: Original queue size=%d\n", q);
  if (q < 128) {
    for (int r=128; r>=q; r-=8) {
      if (WTQueueSizeSet(ctx, r))
        break;
    }
  }
  q = WTQueueSizeGet(ctx);
  LOG("PEN: New queue size=%d\n", q);

  LOG("PEN: Pen attached to display, new context %p\n", ctx);
  return ctx;
}

void PenAPI::close(HCTX ctx)
{
  LOG("PEN: Closing context %p\n", ctx);
  if (ctx) {
    ASSERT(m_wintabLib);
    LOG("PEN: Pen detached from window\n");
    WTClose(ctx);
  }
}

bool PenAPI::packet(HCTX ctx, UINT serial, LPVOID packet)
{
  return (WTPacket(ctx, serial, packet) ? true: false);
}

bool PenAPI::loadWintab()
{
  ASSERT(!m_wintabLib);

  m_wintabLib = base::load_dll("wintab32.dll");
  if (!m_wintabLib) {
    LOG(ERROR) << "PEN: wintab32.dll is not present\n";
    return false;
  }

  if (isBuggyDll()) {
    base::unload_dll(m_wintabLib);
    m_wintabLib = nullptr;
    return false;
  }

  WTInfo = base::get_dll_proc<WTInfoW_Func>(m_wintabLib, "WTInfoW");
  WTOpen = base::get_dll_proc<WTOpenW_Func>(m_wintabLib, "WTOpenW");
  WTClose = base::get_dll_proc<WTClose_Func>(m_wintabLib, "WTClose");
  WTPacket = base::get_dll_proc<WTPacket_Func>(m_wintabLib, "WTPacket");
  WTQueueSizeGet = base::get_dll_proc<WTQueueSizeGet_Func>(m_wintabLib, "WTQueueSizeGet");
  WTQueueSizeSet = base::get_dll_proc<WTQueueSizeSet_Func>(m_wintabLib, "WTQueueSizeSet");
  if (!WTInfo || !WTOpen || !WTClose || !WTPacket ||
      !WTQueueSizeGet || !WTQueueSizeSet) {
    LOG(ERROR) << "PEN: wintab32.dll does not contain all required functions\n";
    return false;
  }

  LOG("PEN: Wintab library loaded\n");
  return true;
}

bool PenAPI::isBuggyDll()
{
  ASSERT(m_wintabLib);

  WCHAR wpath[MAX_PATH];
  memset(wpath, 0, sizeof(wpath));
  GetModuleFileNameW((HMODULE)m_wintabLib, wpath, sizeof(wpath) / sizeof(WCHAR));

  // Ugly hack to bypass the buggy WALTOP International Corp .dll that
  // hangs Aseprite completely when we call its WTInfo function.
  std::string path = base::to_utf8(wpath);
  if (base::is_file(path)) {
    std::string checksum =
      base::convert_to<std::string>(base::Sha1::calculateFromFile(path));
    LOG("PEN: SHA1 <%s> of <%s>\n", checksum.c_str(), path.c_str());
    if (checksum == "a3ba0d9c0f5d8b9f4070981b243a80579f8be105")
      return true;
  }
  return false;
}

} // namespace os
<|endoftext|>


<commit_before>/*
╔════════════════════════════════════════╗
║               Prefix Sum               ║
║         Written by Omid Jafari         ║
║          http://omidjafari.ir          ║
╚════════════════════════════════════════╝
*/
#include <iostream>
#include <mpi.h>

using namespace std;

#define LIST_SIZE 8
#define PROCS 4

void main(int argc, char **argv)
{
	int rank;
	int nums[LIST_SIZE];
	int chunk[LIST_SIZE/PROCS] = { 0 };
	int step = 1;
	int localsum = 0;
	int recv = 0;
	int result = 0;
	MPI_Status status;

	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);

	// Produce the initial array
	if (rank == 0) {
		cout << "Initial array: ";
		for (int i = 0; i < LIST_SIZE; i++) {
			nums[i] = i + 1;
			cout << nums[i] << " ";
		}
		cout << endl;
	}

	// Scatter the initial array to all procs
	MPI_Scatter(nums, LIST_SIZE / PROCS, MPI_INT, chunk, LIST_SIZE / PROCS, MPI_INT, 0, MPI_COMM_WORLD);

	// Calculate the sum of each local chunk
	for (int i = 0; i < LIST_SIZE / PROCS; i++)
		result = localsum += chunk[i];

	// Communitcations
	while (step < PROCS)
	{
		if (rank + step < PROCS)
			MPI_Send(&localsum, 1, MPI_INT, rank + step, 1, MPI_COMM_WORLD);

		if (rank - step >= 0) {
			MPI_Recv(&recv, 1, MPI_INT, rank - step, 1, MPI_COMM_WORLD, &status);
			result += recv;
		}

		step++;
	}

	cout << "I'm " << rank << " and my sum is " << result << endl;

	MPI_Finalize();
}
<commit_msg>Delete prefix-sum.cpp<commit_after><|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <google_smart_card_common/logging/logging.h>

#include <algorithm>
#include <cctype>
#include <chrono>
#include <iostream>
#include <thread>
#include <utility>

#ifdef __native_client__
#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/module.h>
#include <ppapi/cpp/var.h>
#include <ppapi/cpp/var_dictionary.h>
#endif  // __native_client__

namespace google_smart_card {

namespace {

#ifdef __native_client__
constexpr char kTypeMessageKey[] = "type";
constexpr char kMessageType[] = "log_message";
constexpr char kDataMessageKey[] = "data";
constexpr char kDataLogLevelMessageKey[] = "log_level";
constexpr char kDataTextMessageKey[] = "text";
#endif  // __native_client__

bool ShouldLogWithSeverity(LogSeverity severity) {
#ifdef NDEBUG
  return severity > LogSeverity::kDebug;
#else
  (void)severity;  // this suppresses the "unused parameter" error
  return true;
#endif
}

std::string StringifyLogSeverity(LogSeverity severity) {
  switch (severity) {
    case LogSeverity::kDebug:
      return "DEBUG";
    case LogSeverity::kInfo:
      return "INFO";
    case LogSeverity::kWarning:
      return "WARNING";
    case LogSeverity::kError:
      return "ERROR";
    case LogSeverity::kFatal:
      return "FATAL";
    default:
      // This should be never reached, but it's easier to provide a safe
      // default here.
      return "";
  }
}

void EmitLogMessageToStderr(LogSeverity severity,
                            const std::string& message_text) {
  // Prepare the whole message in advance, so that we don't mess with other
  // threads writing to std::cerr too.
  std::ostringstream stream;
  stream << "[";
#ifdef __native_client__
  stream << "NaCl module ";
#endif  // __native_client__
  stream << StringifyLogSeverity(severity) << "] " << message_text << std::endl;

  std::cerr << stream.str();
  std::cerr.flush();
}

#ifdef __native_client__

std::string GetGoogLogLevelByLogSeverity(LogSeverity severity) {
  switch (severity) {
    case LogSeverity::kDebug:
      return "FINE";
    case LogSeverity::kInfo:
      return "INFO";
    case LogSeverity::kWarning:
      return "WARNING";
    case LogSeverity::kError:
      return "WARNING";
    case LogSeverity::kFatal:
      return "SEVERE";
    default:
      // This should be never reached, but it's easier to provide a safe
      // default here.
      return "FINE";
  }
}

std::string CleanupLogMessageTextForVar(const std::string& message_text) {
  // Note that even though this duplicates the CleanupStringForVar function
  // functionality, it's not used here, because the logging implementation
  // intentionally has no dependencies on any other code in this project.
  const char kPlaceholder = '_';
  std::string result = message_text;
  std::replace_if(
      result.begin(), result.end(),
      [](char c) { return !std::isprint(static_cast<unsigned char>(c)); },
      kPlaceholder);
  return result;
}

void EmitLogMessageToJavaScript(LogSeverity severity,
                                const std::string& message_text) {
  pp::VarDictionary message_data;
  message_data.Set(kDataLogLevelMessageKey,
                   GetGoogLogLevelByLogSeverity(severity));
  message_data.Set(kDataTextMessageKey,
                   CleanupLogMessageTextForVar(message_text));
  pp::VarDictionary message;
  message.Set(kTypeMessageKey, kMessageType);
  message.Set(kDataMessageKey, message_data);

  const pp::Module* const pp_module = pp::Module::Get();
  if (pp_module) {
    const pp::Module::InstanceMap pp_instance_map =
        pp_module->current_instances();
    for (const std::pair<PP_Instance, pp::Instance*>& instance_map_item :
         pp_instance_map) {
      pp::Instance* const instance = instance_map_item.second;
      if (instance)
        instance->PostMessage(message);
    }
  }
}

#endif  // __native_client__

void EmitLogMessage(LogSeverity severity, const std::string& message_text) {
  EmitLogMessageToStderr(severity, message_text);
#ifdef __native_client__
  EmitLogMessageToJavaScript(severity, message_text);
#endif  // __native_client__
}

}  // namespace

namespace internal {

LogMessage::LogMessage(LogSeverity severity) : severity_(severity) {}

LogMessage::~LogMessage() {
  if (ShouldLogWithSeverity(severity_)) {
    EmitLogMessage(severity_, stream_.str());
    if (severity_ == LogSeverity::kFatal) {
      // Wait for some time before crashing, to leave a chance for the log
      // message with the crash reason to be delivered to the JavaScript side.
      // This is not a 100%-reliable solution, but the logging functionality in
      // the fatal error case is best-effort anyway.
      std::this_thread::sleep_for(std::chrono::seconds(1));
      std::abort();
    }
  }
}

std::ostringstream& LogMessage::stream() {
  return stream_;
}

std::string MakeCheckFailedMessage(const std::string& stringified_condition,
                                   const std::string& file,
                                   int line,
                                   const std::string& function) {
  std::ostringstream stream;
  stream << "Check \"" << stringified_condition << "\" failed. File \"" << file
         << "\", line " << line << ", function \"" << function << "\"";
  return stream.str();
}

std::string MakeNotreachedMessage(const std::string& file,
                                  int line,
                                  const std::string& function) {
  std::ostringstream stream;
  stream << "NOTREACHED reached in file \"" << file << "\", line " << line
         << ", function \"" << function << "\"";
  return stream.str();
}

}  // namespace internal

}  // namespace google_smart_card
<commit_msg>Don't sleep before abort() in coverage builds (#641)<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <google_smart_card_common/logging/logging.h>

#include <algorithm>
#include <cctype>
#include <chrono>
#include <iostream>
#include <thread>
#include <utility>

#ifdef __native_client__
#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/module.h>
#include <ppapi/cpp/var.h>
#include <ppapi/cpp/var_dictionary.h>
#endif  // __native_client__

namespace google_smart_card {

namespace {

#ifdef __native_client__
constexpr char kTypeMessageKey[] = "type";
constexpr char kMessageType[] = "log_message";
constexpr char kDataMessageKey[] = "data";
constexpr char kDataLogLevelMessageKey[] = "log_level";
constexpr char kDataTextMessageKey[] = "text";
#endif  // __native_client__

bool ShouldLogWithSeverity(LogSeverity severity) {
#ifdef NDEBUG
  return severity > LogSeverity::kDebug;
#else
  (void)severity;  // this suppresses the "unused parameter" error
  return true;
#endif
}

std::string StringifyLogSeverity(LogSeverity severity) {
  switch (severity) {
    case LogSeverity::kDebug:
      return "DEBUG";
    case LogSeverity::kInfo:
      return "INFO";
    case LogSeverity::kWarning:
      return "WARNING";
    case LogSeverity::kError:
      return "ERROR";
    case LogSeverity::kFatal:
      return "FATAL";
    default:
      // This should be never reached, but it's easier to provide a safe
      // default here.
      return "";
  }
}

void EmitLogMessageToStderr(LogSeverity severity,
                            const std::string& message_text) {
  // Prepare the whole message in advance, so that we don't mess with other
  // threads writing to std::cerr too.
  std::ostringstream stream;
  stream << "[";
#ifdef __native_client__
  stream << "NaCl module ";
#endif  // __native_client__
  stream << StringifyLogSeverity(severity) << "] " << message_text << std::endl;

  std::cerr << stream.str();
  std::cerr.flush();
}

#ifdef __native_client__

std::string GetGoogLogLevelByLogSeverity(LogSeverity severity) {
  switch (severity) {
    case LogSeverity::kDebug:
      return "FINE";
    case LogSeverity::kInfo:
      return "INFO";
    case LogSeverity::kWarning:
      return "WARNING";
    case LogSeverity::kError:
      return "WARNING";
    case LogSeverity::kFatal:
      return "SEVERE";
    default:
      // This should be never reached, but it's easier to provide a safe
      // default here.
      return "FINE";
  }
}

std::string CleanupLogMessageTextForVar(const std::string& message_text) {
  // Note that even though this duplicates the CleanupStringForVar function
  // functionality, it's not used here, because the logging implementation
  // intentionally has no dependencies on any other code in this project.
  const char kPlaceholder = '_';
  std::string result = message_text;
  std::replace_if(
      result.begin(), result.end(),
      [](char c) { return !std::isprint(static_cast<unsigned char>(c)); },
      kPlaceholder);
  return result;
}

void EmitLogMessageToJavaScript(LogSeverity severity,
                                const std::string& message_text) {
  pp::VarDictionary message_data;
  message_data.Set(kDataLogLevelMessageKey,
                   GetGoogLogLevelByLogSeverity(severity));
  message_data.Set(kDataTextMessageKey,
                   CleanupLogMessageTextForVar(message_text));
  pp::VarDictionary message;
  message.Set(kTypeMessageKey, kMessageType);
  message.Set(kDataMessageKey, message_data);

  const pp::Module* const pp_module = pp::Module::Get();
  if (pp_module) {
    const pp::Module::InstanceMap pp_instance_map =
        pp_module->current_instances();
    for (const std::pair<PP_Instance, pp::Instance*>& instance_map_item :
         pp_instance_map) {
      pp::Instance* const instance = instance_map_item.second;
      if (instance)
        instance->PostMessage(message);
    }
  }
}

#endif  // __native_client__

void EmitLogMessage(LogSeverity severity, const std::string& message_text) {
  EmitLogMessageToStderr(severity, message_text);
#ifdef __native_client__
  EmitLogMessageToJavaScript(severity, message_text);
#endif  // __native_client__
}

}  // namespace

namespace internal {

LogMessage::LogMessage(LogSeverity severity) : severity_(severity) {}

LogMessage::~LogMessage() {
  if (ShouldLogWithSeverity(severity_)) {
    EmitLogMessage(severity_, stream_.str());
    if (severity_ == LogSeverity::kFatal) {
#if defined(__EMSCRIPTEN__) || defined(__native_client__)
      // Wait for some time before crashing, to leave a chance for the log
      // message with the crash reason to be delivered to the JavaScript side.
      // This is not a 100%-reliable solution, but the logging functionality in
      // the fatal error case is best-effort anyway.
      std::this_thread::sleep_for(std::chrono::seconds(1));
#endif
      std::abort();
    }
  }
}

std::ostringstream& LogMessage::stream() {
  return stream_;
}

std::string MakeCheckFailedMessage(const std::string& stringified_condition,
                                   const std::string& file,
                                   int line,
                                   const std::string& function) {
  std::ostringstream stream;
  stream << "Check \"" << stringified_condition << "\" failed. File \"" << file
         << "\", line " << line << ", function \"" << function << "\"";
  return stream.str();
}

std::string MakeNotreachedMessage(const std::string& file,
                                  int line,
                                  const std::string& function) {
  std::ostringstream stream;
  stream << "NOTREACHED reached in file \"" << file << "\", line " << line
         << ", function \"" << function << "\"";
  return stream.str();
}

}  // namespace internal

}  // namespace google_smart_card
<|endoftext|>


<commit_before>/*
 * ProbingPT.cpp
 *
 *  Created on: 3 Nov 2015
 *      Author: hieu
 */
#include <boost/foreach.hpp>
#include "ProbingPT.h"
#include "../System.h"
#include "../Scores.h"
#include "../Phrase.h"
#include "../legacy/InputFileStream.h"
#include "../legacy/ProbingPT/probing_hash_utils.hh"
#include "../FF/FeatureFunctions.h"
#include "../Search/Manager.h"
#include "../legacy/FactorCollection.h"
#include "../legacy/ProbingPT/quering.hh"
#include "../legacy/Util2.h"

using namespace std;

namespace Moses2
{

ProbingPT::ProbingPT(size_t startInd, const std::string &line)
:PhraseTable(startInd, line)
{
	  ReadParameters();
}

ProbingPT::~ProbingPT()
{
  delete m_engine;
}

void ProbingPT::Load(System &system)
{
  m_engine = new QueryEngine(m_path.c_str());

  m_unkId = 456456546456;

  FactorCollection &vocab = system.GetVocab();

  // source vocab
  const std::map<uint64_t, std::string> &sourceVocab = m_engine->getSourceVocab();
  std::map<uint64_t, std::string>::const_iterator iterSource;
  for (iterSource = sourceVocab.begin(); iterSource != sourceVocab.end(); ++iterSource) {
	const string &wordStr = iterSource->second;
	const Factor *factor = vocab.AddFactor(wordStr, system);

	uint64_t probingId = iterSource->first;
	size_t factorId = factor->GetId();

	if (factorId >= m_sourceVocab.size()) {
		m_sourceVocab.resize(factorId + 1, m_unkId);
	}
	m_sourceVocab[factorId] = probingId;
  }

  // target vocab
  InputFileStream targetVocabStrme(m_path + "/TargetVocab.dat");
  string line;
  while (getline(targetVocabStrme, line)) {
	  vector<string> toks = Tokenize(line, "\t");
	  assert(toks.size());
  	  const Factor *factor = vocab.AddFactor(toks[0], system);
  	  uint32_t probingId = Scan<uint32_t>(toks[1]);

  	  if (probingId >= m_targetVocab.size()) {
  		m_targetVocab.resize(probingId + 1, NULL);
  	  }
  	  m_targetVocab[probingId] = factor;
  }

  // memory mapped file to tps
  string filePath = m_path + "/TargetColl.dat";
  file.open(filePath.c_str());
  if (!file.is_open()) {
    throw "Couldn't open file ";
  }

  data = file.data();

  size_t size = file.size();

  // cache
  CreateCache(system);
}

void ProbingPT::Lookup(const Manager &mgr, InputPaths &inputPaths) const
{
  BOOST_FOREACH(InputPath *path, inputPaths) {
	TargetPhrases *tpsPtr;
	tpsPtr = Lookup(mgr, mgr.GetPool(), *path);
	path->AddTargetPhrases(*this, tpsPtr);
  }
}

TargetPhrases* ProbingPT::Lookup(const Manager &mgr,
		MemPool &pool,
		InputPath &inputPath) const
{
	/*
	if (inputPath.prefixPath && inputPath.prefixPath->GetTargetPhrases(*this) == NULL) {
		// assume all paths have prefixes, except rules with 1 word source
		return NULL;
	}
	else {
		const Phrase &sourcePhrase = inputPath.subPhrase;
		std::pair<TargetPhrases*, uint64_t> tpsAndKey = CreateTargetPhrase(pool, mgr.system, sourcePhrase);
		return tpsAndKey.first;
	}
	*/
	const Phrase &sourcePhrase = inputPath.subPhrase;

	// get hash for source phrase
	std::pair<bool, uint64_t> keyStruct = GetSourceProbingId(sourcePhrase);
	if (!keyStruct.first) {
	  return NULL;
	}

	// check in cache
	Cache::const_iterator iter = m_cache.find(keyStruct.second);
	if (iter != m_cache.end()) {
		TargetPhrases *tps = iter->second;
		return tps;
	}

	// query pt
	TargetPhrases *tps = CreateTargetPhrase(pool, mgr.system, sourcePhrase, keyStruct.second);
	return tps;
}

std::pair<bool, uint64_t> ProbingPT::GetSourceProbingId(const Phrase &sourcePhrase) const
{
  std::pair<bool, uint64_t> ret;

  // create a target phrase from the 1st word of the source, prefix with 'ProbingPT:'
  size_t sourceSize = sourcePhrase.GetSize();
  assert(sourceSize);

  uint64_t probingSource[sourceSize];
  ConvertToProbingSourcePhrase(sourcePhrase, ret.first, probingSource);
  if (!ret.first) {
	// source phrase contains a word unknown in the pt.
	// We know immediately there's no translation for it
  }
  else {
	  ret.second = m_engine->getKey(probingSource, sourceSize);
  }

  return ret;

}

TargetPhrases *ProbingPT::CreateTargetPhrase(
		  MemPool &pool,
		  const System &system,
		  const Phrase &sourcePhrase,
		  uint64_t key) const
{
  TargetPhrases *tps = NULL;

  //Actual lookup
  std::pair<bool, uint64_t> query_result; // 1st=found, 2nd=target file offset
  query_result = m_engine->query(key);

  if (query_result.first) {
	  const char *offset = data + query_result.second;
	  uint64_t *numTP = (uint64_t*) offset;

	  tps = new (pool.Allocate<TargetPhrases>()) TargetPhrases(pool, *numTP);

	  offset += sizeof(uint64_t);
	  for (size_t i = 0; i < *numTP; ++i) {
		  TargetPhrase *tp = CreateTargetPhrase(pool, system, offset);
		  assert(tp);
		  const FeatureFunctions &ffs = system.featureFunctions;
		  ffs.EvaluateInIsolation(pool, system, sourcePhrase, *tp);

		  tps->AddTargetPhrase(*tp);

	  }

	  tps->SortAndPrune(m_tableLimit);
	  system.featureFunctions.EvaluateAfterTablePruning(pool, *tps, sourcePhrase);
	  //cerr << *tps << endl;
  }

  return tps;
}

TargetPhrase *ProbingPT::CreateTargetPhrase(
		  MemPool &pool,
		  const System &system,
		  const char *&offset) const
{
	TargetPhraseInfo *tpInfo = (TargetPhraseInfo*) offset;
    TargetPhrase *tp = new (pool.Allocate<TargetPhrase>()) TargetPhrase(pool, *this, system, tpInfo->numWords);

	offset += sizeof(TargetPhraseInfo);

	// scores
	SCORE *scores = (SCORE*) offset;

  size_t totalNumScores = m_engine->num_scores + m_engine->num_lex_scores;

  if (m_engine->logProb) {
	    // set pt score for rule
	    tp->GetScores().PlusEquals(system, *this, scores);

	    // save scores for other FF, eg. lex RO. Just give the offset
	    if (m_engine->num_lex_scores) {
		  tp->scoreProperties = scores + m_engine->num_scores;
	    }
  }
  else {
	  // log score 1st
	  SCORE logScores[totalNumScores];
	  for (size_t i = 0; i < totalNumScores; ++i) {
		  logScores[i] = FloorScore(TransformScore(scores[i]));
	  }

      // set pt score for rule
	  tp->GetScores().PlusEquals(system, *this, logScores);

      // save scores for other FF, eg. lex RO.
	  tp->scoreProperties = pool.Allocate<SCORE>(m_engine->num_lex_scores);
	  for (size_t i = 0; i < m_engine->num_lex_scores; ++i) {
		  tp->scoreProperties[i] = logScores[i + m_engine->num_scores];
	  }
  }

  offset += sizeof(SCORE) * totalNumScores;

  // words
  for (size_t i = 0; i < tpInfo->numWords; ++i) {
	  uint32_t *probingId = (uint32_t*) offset;

	  const Factor *factor = GetTargetFactor(*probingId);
	  assert(factor);

	  Word &word = (*tp)[i];
	  word[0] = factor;

	  offset += sizeof(uint32_t);
  }

  // properties TODO

  return tp;
}

void ProbingPT::ConvertToProbingSourcePhrase(const Phrase &sourcePhrase, bool &ok, uint64_t probingSource[]) const
{

  size_t size = sourcePhrase.GetSize();
  for (size_t i = 0; i < size; ++i) {
    const Factor *factor = sourcePhrase[i][0];
    uint64_t probingId = GetSourceProbingId(factor);
    if (probingId == m_unkId) {
      ok = false;
      return;
    } else {
      probingSource[i] = probingId;
    }
  }

  ok = true;
}

void ProbingPT::CreateCache(System &system)
{
	if (m_maxCacheSize == 0) {
		return;
	}

	string filePath = m_path + "/cache";
	InputFileStream strme(filePath);

	string line;
	getline(strme, line);
	//float totalCount = Scan<float>(line);

	MemPool &pool = system.GetSystemPool();
	FactorCollection &vocab = system.GetVocab();

	size_t lineCount = 0;
	while (getline(strme, line) && lineCount < m_maxCacheSize) {
		vector<string> toks = Tokenize(line, "\t");
		assert(toks.size() == 2);
		PhraseImpl *sourcePhrase = PhraseImpl::CreateFromString(pool, vocab, system, toks[1]);

		std::pair<bool, uint64_t> retStruct = GetSourceProbingId(*sourcePhrase);
		if (!retStruct.first) {
		  return;
		}

		TargetPhrases *tps = CreateTargetPhrase(pool, system, *sourcePhrase, retStruct.second);
		assert(tps);

		m_cache[retStruct.second] = tps;
	}

}

}

<commit_msg>debug cache<commit_after>/*
 * ProbingPT.cpp
 *
 *  Created on: 3 Nov 2015
 *      Author: hieu
 */
#include <boost/foreach.hpp>
#include "ProbingPT.h"
#include "../System.h"
#include "../Scores.h"
#include "../Phrase.h"
#include "../legacy/InputFileStream.h"
#include "../legacy/ProbingPT/probing_hash_utils.hh"
#include "../FF/FeatureFunctions.h"
#include "../Search/Manager.h"
#include "../legacy/FactorCollection.h"
#include "../legacy/ProbingPT/quering.hh"
#include "../legacy/Util2.h"

using namespace std;

namespace Moses2
{

ProbingPT::ProbingPT(size_t startInd, const std::string &line)
:PhraseTable(startInd, line)
{
	  ReadParameters();
}

ProbingPT::~ProbingPT()
{
  delete m_engine;
}

void ProbingPT::Load(System &system)
{
  m_engine = new QueryEngine(m_path.c_str());

  m_unkId = 456456546456;

  FactorCollection &vocab = system.GetVocab();

  // source vocab
  const std::map<uint64_t, std::string> &sourceVocab = m_engine->getSourceVocab();
  std::map<uint64_t, std::string>::const_iterator iterSource;
  for (iterSource = sourceVocab.begin(); iterSource != sourceVocab.end(); ++iterSource) {
	const string &wordStr = iterSource->second;
	const Factor *factor = vocab.AddFactor(wordStr, system);

	uint64_t probingId = iterSource->first;
	size_t factorId = factor->GetId();

	if (factorId >= m_sourceVocab.size()) {
		m_sourceVocab.resize(factorId + 1, m_unkId);
	}
	m_sourceVocab[factorId] = probingId;
  }

  // target vocab
  InputFileStream targetVocabStrme(m_path + "/TargetVocab.dat");
  string line;
  while (getline(targetVocabStrme, line)) {
	  vector<string> toks = Tokenize(line, "\t");
	  assert(toks.size());
  	  const Factor *factor = vocab.AddFactor(toks[0], system);
  	  uint32_t probingId = Scan<uint32_t>(toks[1]);

  	  if (probingId >= m_targetVocab.size()) {
  		m_targetVocab.resize(probingId + 1, NULL);
  	  }
  	  m_targetVocab[probingId] = factor;
  }

  // memory mapped file to tps
  string filePath = m_path + "/TargetColl.dat";
  file.open(filePath.c_str());
  if (!file.is_open()) {
    throw "Couldn't open file ";
  }

  data = file.data();

  size_t size = file.size();

  // cache
  CreateCache(system);
}

void ProbingPT::Lookup(const Manager &mgr, InputPaths &inputPaths) const
{
  BOOST_FOREACH(InputPath *path, inputPaths) {
	TargetPhrases *tpsPtr;
	tpsPtr = Lookup(mgr, mgr.GetPool(), *path);
	path->AddTargetPhrases(*this, tpsPtr);
  }
}

TargetPhrases* ProbingPT::Lookup(const Manager &mgr,
		MemPool &pool,
		InputPath &inputPath) const
{
	/*
	if (inputPath.prefixPath && inputPath.prefixPath->GetTargetPhrases(*this) == NULL) {
		// assume all paths have prefixes, except rules with 1 word source
		return NULL;
	}
	else {
		const Phrase &sourcePhrase = inputPath.subPhrase;
		std::pair<TargetPhrases*, uint64_t> tpsAndKey = CreateTargetPhrase(pool, mgr.system, sourcePhrase);
		return tpsAndKey.first;
	}
	*/
	const Phrase &sourcePhrase = inputPath.subPhrase;

	// get hash for source phrase
	std::pair<bool, uint64_t> keyStruct = GetSourceProbingId(sourcePhrase);
	if (!keyStruct.first) {
	  return NULL;
	}

	// check in cache
	Cache::const_iterator iter = m_cache.find(keyStruct.second);
	if (iter != m_cache.end()) {
    	    cerr << "cache 1\n";
		TargetPhrases *tps = iter->second;
		return tps;
	}
        else {
          cerr << "cache 0\n";
        }

	// query pt
	TargetPhrases *tps = CreateTargetPhrase(pool, mgr.system, sourcePhrase, keyStruct.second);
	return tps;
}

std::pair<bool, uint64_t> ProbingPT::GetSourceProbingId(const Phrase &sourcePhrase) const
{
  std::pair<bool, uint64_t> ret;

  // create a target phrase from the 1st word of the source, prefix with 'ProbingPT:'
  size_t sourceSize = sourcePhrase.GetSize();
  assert(sourceSize);

  uint64_t probingSource[sourceSize];
  ConvertToProbingSourcePhrase(sourcePhrase, ret.first, probingSource);
  if (!ret.first) {
	// source phrase contains a word unknown in the pt.
	// We know immediately there's no translation for it
  }
  else {
	  ret.second = m_engine->getKey(probingSource, sourceSize);
  }

  return ret;

}

TargetPhrases *ProbingPT::CreateTargetPhrase(
		  MemPool &pool,
		  const System &system,
		  const Phrase &sourcePhrase,
		  uint64_t key) const
{
  TargetPhrases *tps = NULL;

  //Actual lookup
  std::pair<bool, uint64_t> query_result; // 1st=found, 2nd=target file offset
  query_result = m_engine->query(key);

  if (query_result.first) {
	  const char *offset = data + query_result.second;
	  uint64_t *numTP = (uint64_t*) offset;

	  tps = new (pool.Allocate<TargetPhrases>()) TargetPhrases(pool, *numTP);

	  offset += sizeof(uint64_t);
	  for (size_t i = 0; i < *numTP; ++i) {
		  TargetPhrase *tp = CreateTargetPhrase(pool, system, offset);
		  assert(tp);
		  const FeatureFunctions &ffs = system.featureFunctions;
		  ffs.EvaluateInIsolation(pool, system, sourcePhrase, *tp);

		  tps->AddTargetPhrase(*tp);

	  }

	  tps->SortAndPrune(m_tableLimit);
	  system.featureFunctions.EvaluateAfterTablePruning(pool, *tps, sourcePhrase);
	  //cerr << *tps << endl;
  }

  return tps;
}

TargetPhrase *ProbingPT::CreateTargetPhrase(
		  MemPool &pool,
		  const System &system,
		  const char *&offset) const
{
	TargetPhraseInfo *tpInfo = (TargetPhraseInfo*) offset;
    TargetPhrase *tp = new (pool.Allocate<TargetPhrase>()) TargetPhrase(pool, *this, system, tpInfo->numWords);

	offset += sizeof(TargetPhraseInfo);

	// scores
	SCORE *scores = (SCORE*) offset;

  size_t totalNumScores = m_engine->num_scores + m_engine->num_lex_scores;

  if (m_engine->logProb) {
	    // set pt score for rule
	    tp->GetScores().PlusEquals(system, *this, scores);

	    // save scores for other FF, eg. lex RO. Just give the offset
	    if (m_engine->num_lex_scores) {
		  tp->scoreProperties = scores + m_engine->num_scores;
	    }
  }
  else {
	  // log score 1st
	  SCORE logScores[totalNumScores];
	  for (size_t i = 0; i < totalNumScores; ++i) {
		  logScores[i] = FloorScore(TransformScore(scores[i]));
	  }

      // set pt score for rule
	  tp->GetScores().PlusEquals(system, *this, logScores);

      // save scores for other FF, eg. lex RO.
	  tp->scoreProperties = pool.Allocate<SCORE>(m_engine->num_lex_scores);
	  for (size_t i = 0; i < m_engine->num_lex_scores; ++i) {
		  tp->scoreProperties[i] = logScores[i + m_engine->num_scores];
	  }
  }

  offset += sizeof(SCORE) * totalNumScores;

  // words
  for (size_t i = 0; i < tpInfo->numWords; ++i) {
	  uint32_t *probingId = (uint32_t*) offset;

	  const Factor *factor = GetTargetFactor(*probingId);
	  assert(factor);

	  Word &word = (*tp)[i];
	  word[0] = factor;

	  offset += sizeof(uint32_t);
  }

  // properties TODO

  return tp;
}

void ProbingPT::ConvertToProbingSourcePhrase(const Phrase &sourcePhrase, bool &ok, uint64_t probingSource[]) const
{

  size_t size = sourcePhrase.GetSize();
  for (size_t i = 0; i < size; ++i) {
    const Factor *factor = sourcePhrase[i][0];
    uint64_t probingId = GetSourceProbingId(factor);
    if (probingId == m_unkId) {
      ok = false;
      return;
    } else {
      probingSource[i] = probingId;
    }
  }

  ok = true;
}

void ProbingPT::CreateCache(System &system)
{
	if (m_maxCacheSize == 0) {
		return;
	}

	string filePath = m_path + "/cache";
	InputFileStream strme(filePath);

	string line;
	getline(strme, line);
	//float totalCount = Scan<float>(line);

	MemPool &pool = system.GetSystemPool();
	FactorCollection &vocab = system.GetVocab();

	size_t lineCount = 0;
	while (getline(strme, line) && lineCount < m_maxCacheSize) {
		vector<string> toks = Tokenize(line, "\t");
		assert(toks.size() == 2);
		PhraseImpl *sourcePhrase = PhraseImpl::CreateFromString(pool, vocab, system, toks[1]);

		std::pair<bool, uint64_t> retStruct = GetSourceProbingId(*sourcePhrase);
		if (!retStruct.first) {
		  return;
		}

		TargetPhrases *tps = CreateTargetPhrase(pool, system, *sourcePhrase, retStruct.second);
		assert(tps);

		m_cache[retStruct.second] = tps;
	}

}

}

<|endoftext|>


<commit_before>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#include <crossbow/program_options.hpp>
#include <crossbow/logger.hpp>

#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <string>
#include <iostream>
#include <cassert>
#include <fstream>

#include "Client.hpp"

using namespace crossbow::program_options;
using namespace boost::asio;
using err_code = boost::system::error_code;

std::vector<std::string> split(const std::string& str, const char delim) {
    std::stringstream ss(str);
    std::string item;
    std::vector<std::string> result;
    while (std::getline(ss, item, delim)) {
        if (item.empty()) continue;
        result.push_back(std::move(item));
    }
    return result;
}

int main(int argc, const char** argv) {
    bool help = false;
    bool populate = false;
    int16_t numWarehouses = 1;
    crossbow::string host;
    std::string port("8713");
    std::string logLevel("DEBUG");
    std::string outFile("out.csv");
    size_t numClients = 1;
    unsigned time = 5*60;
    bool exit = false;
    auto opts = create_options("tpcc_server",
            value<'h'>("help", &help, tag::description{"print help"})
            , value<'H'>("host", &host, tag::description{"Comma-separated list of hosts"})
            , value<'l'>("log-level", &logLevel, tag::description{"The log level"})
            , value<'c'>("num-clients", &numClients, tag::description{"Number of Clients to run per host"})
            , value<'P'>("populate", &populate, tag::description{"Populate the database"})
            , value<'W'>("num-warehouses", &numWarehouses, tag::description{"Number of warehouses"})
            , value<'t'>("time", &time, tag::description{"Duration of the benchmark in seconds"})
            , value<'o'>("out", &outFile, tag::description{"Path to the output file"})
            , value<-1>("exit", &exit, tag::description{"Quit server"})
            );
    try {
        parse(opts, argc, argv);
    } catch (argument_not_found& e) {
        std::cerr << e.what() << std::endl << std::endl;
        print_help(std::cout, opts);
        return 1;
    }
    if (help) {
        print_help(std::cout, opts);
        return 0;
    }
    if (host.empty()) {
        std::cerr << "No host\n";
        return 1;
    }
    auto startTime = tpcc::Clock::now();
    auto endTime = startTime + std::chrono::seconds(time);
    crossbow::logger::logger->config.level = crossbow::logger::logLevelFromString(logLevel);
    try {
        auto hosts = split(host.c_str(), ',');
        io_service service;
        auto sumClients = hosts.size() * numClients;
        std::vector<tpcc::Client> clients;
        clients.reserve(sumClients);
        auto wareHousesPerClient = numWarehouses / sumClients;
        for (decltype(sumClients) i = 0; i < sumClients; ++i) {
            if (i >= unsigned(numWarehouses)) break;
            clients.emplace_back(service, numWarehouses, int16_t(wareHousesPerClient * i + 1), int16_t(wareHousesPerClient * (i + 1)), endTime);
        }
        for (size_t i = 0; i < hosts.size(); ++i) {
            auto h = hosts[i];
            auto addr = split(h, ':');
            assert(addr.size() <= 2);
            auto p = addr.size() == 2 ? addr[1] : port;
            ip::tcp::resolver resolver(service);
            ip::tcp::resolver::iterator iter;
            if (host == "") {
                iter = resolver.resolve(ip::tcp::resolver::query(port));
            } else {
                iter = resolver.resolve(ip::tcp::resolver::query(h, port));
            }
            for (unsigned j = 0; j < numClients; ++j) {
                LOG_INFO("Connected to client " + crossbow::to_string(i*numClients + j));
                boost::asio::connect(clients[i*numClients + j].socket(), iter);
            }
        }

        {
            auto t = std::time(nullptr);
            std::string dateString(20, '\0');
            auto len = std::strftime(&dateString.front(), 20, "%T", std::localtime(&t));
            dateString.resize(len);
            LOG_INFO("Starting client at %1%", dateString);
        }

        if (exit) {
            for (auto& client : clients) {
                auto& cmds = client.commands();
                cmds.execute<tpcc::Command::EXIT>([](const err_code& ec){
                    if (ec) {
                        std::cerr << "ERROR: " << ec.message() << std::endl;
                    }
                });
                goto END;
            }
        }

        if (populate) {
            auto& cmds = clients[0].commands();
            cmds.execute<tpcc::Command::CREATE_SCHEMA>(
                    [&clients](const err_code& ec,
                        const std::tuple<bool, crossbow::string>& res){
                if (ec) {
                    LOG_ERROR(ec.message());
                    return;
                }
                if (!std::get<0>(res)) {
                    LOG_ERROR(std::get<1>(res));
                    return;
                }

                auto& cmds = clients[0].commands();
                cmds.execute<tpcc::Command::POPULATE_ITEMS>([&clients](const err_code& ec, const std::tuple<bool, crossbow::string>& res){
                    if (ec) {
                        LOG_ERROR(ec.message());
                        return;
                    }
                    if (!std::get<0>(res)) {
                        LOG_ERROR(std::get<1>(res));
                        return;
                    }

                    for (auto& client : clients) {
                        client.populate();
                    }
                });
            });
        } else {
            for (decltype(clients.size()) i = 0; i < clients.size(); ++i) {
                auto& client = clients[i];
                client.run();
            }
        }
END:
        service.run();
        LOG_INFO("Done, writing results");
        std::ofstream out(outFile.c_str());
        out << "start,end,transaction,success,error\n";
        for (const auto& client : clients) {
            const auto& queue = client.log();
            for (const auto& e : queue) {
                crossbow::string tName;
                switch (e.transaction) {
                case tpcc::Command::POPULATE_WAREHOUSE:
                    tName = "Populate";
                    break;
                case tpcc::Command::POPULATE_ITEMS:
                    tName = "Populate";
                    break;
                case tpcc::Command::CREATE_SCHEMA:
                    tName = "Schema Create";
                    break;
                case tpcc::Command::STOCK_LEVEL:
                    tName = "Stock Level";
                    break;
                case tpcc::Command::DELIVERY:
                    tName = "Delivery";
                    break;
                case tpcc::Command::NEW_ORDER:
                    tName = "New Order";
                    break;
                case tpcc::Command::ORDER_STATUS:
                    tName = "Order Status";
                    break;
                case tpcc::Command::PAYMENT:
                    tName = "Payment";
                    break;
                case tpcc::Command::EXIT:
                    assert(false);
                    break;
                }
                out << std::chrono::duration_cast<std::chrono::milliseconds>(e.start - startTime).count() << ','
                    << std::chrono::duration_cast<std::chrono::milliseconds>(e.end - startTime).count() << ','
                    << tName << ','
                    << (e.success ? "true" : "false") << ','
                    << e.error << std::endl;
            }
        }
        std::cout << '\a';
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
}
<commit_msg>Use port given in command line<commit_after>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#include <crossbow/program_options.hpp>
#include <crossbow/logger.hpp>

#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <string>
#include <iostream>
#include <cassert>
#include <fstream>

#include "Client.hpp"

using namespace crossbow::program_options;
using namespace boost::asio;
using err_code = boost::system::error_code;

std::vector<std::string> split(const std::string& str, const char delim) {
    std::stringstream ss(str);
    std::string item;
    std::vector<std::string> result;
    while (std::getline(ss, item, delim)) {
        if (item.empty()) continue;
        result.push_back(std::move(item));
    }
    return result;
}

int main(int argc, const char** argv) {
    bool help = false;
    bool populate = false;
    int16_t numWarehouses = 1;
    crossbow::string host;
    std::string port("8713");
    std::string logLevel("DEBUG");
    std::string outFile("out.csv");
    size_t numClients = 1;
    unsigned time = 5*60;
    bool exit = false;
    auto opts = create_options("tpcc_server",
            value<'h'>("help", &help, tag::description{"print help"})
            , value<'H'>("host", &host, tag::description{"Comma-separated list of hosts"})
            , value<'l'>("log-level", &logLevel, tag::description{"The log level"})
            , value<'c'>("num-clients", &numClients, tag::description{"Number of Clients to run per host"})
            , value<'P'>("populate", &populate, tag::description{"Populate the database"})
            , value<'W'>("num-warehouses", &numWarehouses, tag::description{"Number of warehouses"})
            , value<'t'>("time", &time, tag::description{"Duration of the benchmark in seconds"})
            , value<'o'>("out", &outFile, tag::description{"Path to the output file"})
            , value<-1>("exit", &exit, tag::description{"Quit server"})
            );
    try {
        parse(opts, argc, argv);
    } catch (argument_not_found& e) {
        std::cerr << e.what() << std::endl << std::endl;
        print_help(std::cout, opts);
        return 1;
    }
    if (help) {
        print_help(std::cout, opts);
        return 0;
    }
    if (host.empty()) {
        std::cerr << "No host\n";
        return 1;
    }
    auto startTime = tpcc::Clock::now();
    auto endTime = startTime + std::chrono::seconds(time);
    crossbow::logger::logger->config.level = crossbow::logger::logLevelFromString(logLevel);
    try {
        auto hosts = split(host.c_str(), ',');
        io_service service;
        auto sumClients = hosts.size() * numClients;
        std::vector<tpcc::Client> clients;
        clients.reserve(sumClients);
        auto wareHousesPerClient = numWarehouses / sumClients;
        for (decltype(sumClients) i = 0; i < sumClients; ++i) {
            if (i >= unsigned(numWarehouses)) break;
            clients.emplace_back(service, numWarehouses, int16_t(wareHousesPerClient * i + 1), int16_t(wareHousesPerClient * (i + 1)), endTime);
        }
        for (size_t i = 0; i < hosts.size(); ++i) {
            auto h = hosts[i];
            auto addr = split(h, ':');
            assert(addr.size() <= 2);
            auto p = addr.size() == 2 ? addr[1] : port;
            ip::tcp::resolver resolver(service);
            ip::tcp::resolver::iterator iter;
            if (host == "") {
                iter = resolver.resolve(ip::tcp::resolver::query(port));
            } else {
                iter = resolver.resolve(ip::tcp::resolver::query(addr[0], port));
            }
            for (unsigned j = 0; j < numClients; ++j) {
                LOG_INFO("Connected to client " + crossbow::to_string(i*numClients + j));
                boost::asio::connect(clients[i*numClients + j].socket(), iter);
            }
        }

        {
            auto t = std::time(nullptr);
            std::string dateString(20, '\0');
            auto len = std::strftime(&dateString.front(), 20, "%T", std::localtime(&t));
            dateString.resize(len);
            LOG_INFO("Starting client at %1%", dateString);
        }

        if (exit) {
            for (auto& client : clients) {
                auto& cmds = client.commands();
                cmds.execute<tpcc::Command::EXIT>([](const err_code& ec){
                    if (ec) {
                        std::cerr << "ERROR: " << ec.message() << std::endl;
                    }
                });
                goto END;
            }
        }

        if (populate) {
            auto& cmds = clients[0].commands();
            cmds.execute<tpcc::Command::CREATE_SCHEMA>(
                    [&clients](const err_code& ec,
                        const std::tuple<bool, crossbow::string>& res){
                if (ec) {
                    LOG_ERROR(ec.message());
                    return;
                }
                if (!std::get<0>(res)) {
                    LOG_ERROR(std::get<1>(res));
                    return;
                }

                auto& cmds = clients[0].commands();
                cmds.execute<tpcc::Command::POPULATE_ITEMS>([&clients](const err_code& ec, const std::tuple<bool, crossbow::string>& res){
                    if (ec) {
                        LOG_ERROR(ec.message());
                        return;
                    }
                    if (!std::get<0>(res)) {
                        LOG_ERROR(std::get<1>(res));
                        return;
                    }

                    for (auto& client : clients) {
                        client.populate();
                    }
                });
            });
        } else {
            for (decltype(clients.size()) i = 0; i < clients.size(); ++i) {
                auto& client = clients[i];
                client.run();
            }
        }
END:
        service.run();
        LOG_INFO("Done, writing results");
        std::ofstream out(outFile.c_str());
        out << "start,end,transaction,success,error\n";
        for (const auto& client : clients) {
            const auto& queue = client.log();
            for (const auto& e : queue) {
                crossbow::string tName;
                switch (e.transaction) {
                case tpcc::Command::POPULATE_WAREHOUSE:
                    tName = "Populate";
                    break;
                case tpcc::Command::POPULATE_ITEMS:
                    tName = "Populate";
                    break;
                case tpcc::Command::CREATE_SCHEMA:
                    tName = "Schema Create";
                    break;
                case tpcc::Command::STOCK_LEVEL:
                    tName = "Stock Level";
                    break;
                case tpcc::Command::DELIVERY:
                    tName = "Delivery";
                    break;
                case tpcc::Command::NEW_ORDER:
                    tName = "New Order";
                    break;
                case tpcc::Command::ORDER_STATUS:
                    tName = "Order Status";
                    break;
                case tpcc::Command::PAYMENT:
                    tName = "Payment";
                    break;
                case tpcc::Command::EXIT:
                    assert(false);
                    break;
                }
                out << std::chrono::duration_cast<std::chrono::milliseconds>(e.start - startTime).count() << ','
                    << std::chrono::duration_cast<std::chrono::milliseconds>(e.end - startTime).count() << ','
                    << tName << ','
                    << (e.success ? "true" : "false") << ','
                    << e.error << std::endl;
            }
        }
        std::cout << '\a';
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
}
<|endoftext|>