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

#include "mesh.h"
#include "object.h"
#include "scene.h"

#include "blender_sync.h"
#include "blender_util.h"

#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"

#include "util_foreach.h"

CCL_NAMESPACE_BEGIN

/* Find/Add */

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
{
	if(std == Attribute::STD_NONE)
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(std))
			return true;

	return false;
}

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
{
	if(name == ustring())
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(name))
			return true;

	return false;
}

static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		mesh->verts.push_back(get_float3(v->co()));

	/* create vertex normals */
	Attribute *attr_N = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL);
	float3 *N = attr_N->data_float3();

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
		*N= get_float3(v->normal());

	/* create faces */
	BL::Mesh::faces_iterator f;
	vector<int> nverts;

	for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n = (vi[3] == 0)? 3: 4;
		int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
		int shader = used_shaders[mi];
		bool smooth = f->use_smooth();

		mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);

		if(n == 4)
			mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);

		nverts.push_back(n);
	}

	/* create generated coordinates. todo: we should actually get the orco
	   coordinates from modifiers, for now we use texspace loc/size which
	   is available in the api. */
	if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
		float3 loc = get_float3(b_mesh.texspace_location());
		float3 size = get_float3(b_mesh.texspace_size());

		if(size.x != 0.0f) size.x = 0.5f/size.x;
		if(size.y != 0.0f) size.y = 0.5f/size.y;
		if(size.z != 0.0f) size.z = 0.5f/size.z;

		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);

		float3 *fdata = attr->data_float3();
		BL::Mesh::vertices_iterator v;
		size_t i = 0;

		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
			fdata[i++] = get_float3(v->co())*size - loc;
	}

	/* create vertex color attributes */
	{
		BL::Mesh::tessface_vertex_colors_iterator l;

		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
			if(!mesh_need_attribute(scene, mesh, ustring(l->name().c_str())))
				continue;

			Attribute *attr = mesh->attributes.add(
				ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);

			BL::MeshColorLayer::data_iterator c;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
				fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
				fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
				fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));

				if(nverts[i] == 4) {
					fdata[3] = fdata[0];
					fdata[4] = fdata[2];
					fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
					fdata += 6;
				}
				else
					fdata += 3;
			}
		}
	}

	/* create uv map attributes */
	{
		BL::Mesh::tessface_uv_textures_iterator l;

		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
			Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
			ustring name = ustring(l->name().c_str());

			if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
				continue;

			Attribute *attr;

			if(l->active_render())
				attr = mesh->attributes.add(std, name);
			else
				attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);

			BL::MeshTextureFaceLayer::data_iterator t;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
				fdata[0] =  get_float3(t->uv1());
				fdata[1] =  get_float3(t->uv2());
				fdata[2] =  get_float3(t->uv3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(t->uv1());
					fdata[1] =  get_float3(t->uv3());
					fdata[2] =  get_float3(t->uv4());
					fdata += 3;
				}
			}
		}
	}
}

static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
{
	/* create subd mesh */
	SubdMesh sdmesh;

	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		sdmesh.add_vert(get_float3(v->co()));

	/* create faces */
	BL::Mesh::faces_iterator f;

	for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n= (vi[3] == 0)? 3: 4;
		//int shader = used_shaders[f->material_index()];

		if(n == 4)
			sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
		/*else
			sdmesh.add_face(vi[0], vi[1], vi[2]);*/
	}

	/* finalize subd mesh */
	sdmesh.link_boundary();

	/* subdivide */
	DiagSplit dsplit;
	dsplit.camera = NULL;
	dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");

	sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
}

/* Sync */

Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
{
	/* test if we can instance or if the object is modified */
	BL::ID b_ob_data = b_ob.data();
	BL::ID key = (object_is_modified(b_ob) || holdout)? b_ob: b_ob_data;

	/* find shader indices */
	vector<uint> used_shaders;

	BL::Object::material_slots_iterator slot;
	for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
		BL::Material material_override = render_layer.material_override;

		if(holdout)
			find_shader(PointerRNA_NULL, used_shaders, scene->default_holdout);
		else if(material_override)
			find_shader(material_override, used_shaders, scene->default_surface);
		else
			find_shader(slot->material(), used_shaders, scene->default_surface);
	}

	if(used_shaders.size() == 0)
		used_shaders.push_back(scene->default_surface);

	/* test if we need to sync */
	Mesh *mesh;

	if(!mesh_map.sync(&mesh, key)) {
		/* if transform was applied to mesh, need full update */
		if(object_updated && mesh->transform_applied);
		/* test if shaders changed, these can be object level so mesh
		   does not get tagged for recalc */
		else if(mesh->used_shaders != used_shaders);
		else {
			/* even if not tagged for recalc, we may need to sync anyway
			 * because the shader needs different mesh attributes */
			bool attribute_recalc = false;

			foreach(uint shader, mesh->used_shaders)
				if(scene->shaders[shader]->need_update_attributes)
					attribute_recalc = true;

			if(!attribute_recalc)
				return mesh;
		}
	}

	/* ensure we only sync instanced meshes once */
	if(mesh_synced.find(mesh) != mesh_synced.end())
		return mesh;

	mesh_synced.insert(mesh);

	/* create derived mesh */
	BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
	PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");

	vector<Mesh::Triangle> oldtriangle = mesh->triangles;

	mesh->clear();
	mesh->used_shaders = used_shaders;
	mesh->name = ustring(b_ob_data.name().c_str());

	if(b_mesh) {
		if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
			create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
		else
			create_mesh(scene, mesh, b_mesh, used_shaders);

		/* free derived mesh */
		object_remove_mesh(b_data, b_mesh);
	}

	/* displacement method */
	if(cmesh.data) {
		int method = RNA_enum_get(&cmesh, "displacement_method");

		if(method == 0 || !experimental)
			mesh->displacement_method = Mesh::DISPLACE_BUMP;
		else if(method == 1)
			mesh->displacement_method = Mesh::DISPLACE_TRUE;
		else
			mesh->displacement_method = Mesh::DISPLACE_BOTH;
	}

	/* tag update */
	bool rebuild = false;

	if(oldtriangle.size() != mesh->triangles.size())
		rebuild = true;
	else if(oldtriangle.size()) {
		if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
			rebuild = true;
	}

	mesh->tag_update(scene, rebuild);

	return mesh;
}

CCL_NAMESPACE_END

<commit_msg>last commit broke cycles, also add BMESH_TODO's for python scripts that need upgrading.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "mesh.h"
#include "object.h"
#include "scene.h"

#include "blender_sync.h"
#include "blender_util.h"

#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"

#include "util_foreach.h"

CCL_NAMESPACE_BEGIN

/* Find/Add */

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
{
	if(std == Attribute::STD_NONE)
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(std))
			return true;

	return false;
}

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
{
	if(name == ustring())
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(name))
			return true;

	return false;
}

static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		mesh->verts.push_back(get_float3(v->co()));

	/* create vertex normals */
	Attribute *attr_N = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL);
	float3 *N = attr_N->data_float3();

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
		*N= get_float3(v->normal());

	/* create faces */
	BL::Mesh::tessfaces_iterator f;
	vector<int> nverts;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n = (vi[3] == 0)? 3: 4;
		int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
		int shader = used_shaders[mi];
		bool smooth = f->use_smooth();

		mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);

		if(n == 4)
			mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);

		nverts.push_back(n);
	}

	/* create generated coordinates. todo: we should actually get the orco
	   coordinates from modifiers, for now we use texspace loc/size which
	   is available in the api. */
	if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
		float3 loc = get_float3(b_mesh.texspace_location());
		float3 size = get_float3(b_mesh.texspace_size());

		if(size.x != 0.0f) size.x = 0.5f/size.x;
		if(size.y != 0.0f) size.y = 0.5f/size.y;
		if(size.z != 0.0f) size.z = 0.5f/size.z;

		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);

		float3 *fdata = attr->data_float3();
		BL::Mesh::vertices_iterator v;
		size_t i = 0;

		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
			fdata[i++] = get_float3(v->co())*size - loc;
	}

	/* create vertex color attributes */
	{
		BL::Mesh::tessface_vertex_colors_iterator l;

		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
			if(!mesh_need_attribute(scene, mesh, ustring(l->name().c_str())))
				continue;

			Attribute *attr = mesh->attributes.add(
				ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);

			BL::MeshColorLayer::data_iterator c;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
				fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
				fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
				fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));

				if(nverts[i] == 4) {
					fdata[3] = fdata[0];
					fdata[4] = fdata[2];
					fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
					fdata += 6;
				}
				else
					fdata += 3;
			}
		}
	}

	/* create uv map attributes */
	{
		BL::Mesh::tessface_uv_textures_iterator l;

		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
			Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
			ustring name = ustring(l->name().c_str());

			if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
				continue;

			Attribute *attr;

			if(l->active_render())
				attr = mesh->attributes.add(std, name);
			else
				attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);

			BL::MeshTextureFaceLayer::data_iterator t;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
				fdata[0] =  get_float3(t->uv1());
				fdata[1] =  get_float3(t->uv2());
				fdata[2] =  get_float3(t->uv3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(t->uv1());
					fdata[1] =  get_float3(t->uv3());
					fdata[2] =  get_float3(t->uv4());
					fdata += 3;
				}
			}
		}
	}
}

static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
{
	/* create subd mesh */
	SubdMesh sdmesh;

	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		sdmesh.add_vert(get_float3(v->co()));

	/* create faces */
	BL::Mesh::tessfaces_iterator f;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n= (vi[3] == 0)? 3: 4;
		//int shader = used_shaders[f->material_index()];

		if(n == 4)
			sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
		/*else
			sdmesh.add_face(vi[0], vi[1], vi[2]);*/
	}

	/* finalize subd mesh */
	sdmesh.link_boundary();

	/* subdivide */
	DiagSplit dsplit;
	dsplit.camera = NULL;
	dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");

	sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
}

/* Sync */

Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
{
	/* test if we can instance or if the object is modified */
	BL::ID b_ob_data = b_ob.data();
	BL::ID key = (object_is_modified(b_ob) || holdout)? b_ob: b_ob_data;

	/* find shader indices */
	vector<uint> used_shaders;

	BL::Object::material_slots_iterator slot;
	for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
		BL::Material material_override = render_layer.material_override;

		if(holdout)
			find_shader(PointerRNA_NULL, used_shaders, scene->default_holdout);
		else if(material_override)
			find_shader(material_override, used_shaders, scene->default_surface);
		else
			find_shader(slot->material(), used_shaders, scene->default_surface);
	}

	if(used_shaders.size() == 0)
		used_shaders.push_back(scene->default_surface);

	/* test if we need to sync */
	Mesh *mesh;

	if(!mesh_map.sync(&mesh, key)) {
		/* if transform was applied to mesh, need full update */
		if(object_updated && mesh->transform_applied);
		/* test if shaders changed, these can be object level so mesh
		   does not get tagged for recalc */
		else if(mesh->used_shaders != used_shaders);
		else {
			/* even if not tagged for recalc, we may need to sync anyway
			 * because the shader needs different mesh attributes */
			bool attribute_recalc = false;

			foreach(uint shader, mesh->used_shaders)
				if(scene->shaders[shader]->need_update_attributes)
					attribute_recalc = true;

			if(!attribute_recalc)
				return mesh;
		}
	}

	/* ensure we only sync instanced meshes once */
	if(mesh_synced.find(mesh) != mesh_synced.end())
		return mesh;

	mesh_synced.insert(mesh);

	/* create derived mesh */
	BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
	PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");

	vector<Mesh::Triangle> oldtriangle = mesh->triangles;

	mesh->clear();
	mesh->used_shaders = used_shaders;
	mesh->name = ustring(b_ob_data.name().c_str());

	if(b_mesh) {
		if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
			create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
		else
			create_mesh(scene, mesh, b_mesh, used_shaders);

		/* free derived mesh */
		object_remove_mesh(b_data, b_mesh);
	}

	/* displacement method */
	if(cmesh.data) {
		int method = RNA_enum_get(&cmesh, "displacement_method");

		if(method == 0 || !experimental)
			mesh->displacement_method = Mesh::DISPLACE_BUMP;
		else if(method == 1)
			mesh->displacement_method = Mesh::DISPLACE_TRUE;
		else
			mesh->displacement_method = Mesh::DISPLACE_BOTH;
	}

	/* tag update */
	bool rebuild = false;

	if(oldtriangle.size() != mesh->triangles.size())
		rebuild = true;
	else if(oldtriangle.size()) {
		if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
			rebuild = true;
	}

	mesh->tag_update(scene, rebuild);

	return mesh;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>#ifndef HTOOL_CLUSTER_TREE_HPP
#define HTOOL_CLUSTER_TREE_HPP

#include "cluster.hpp"
#include <mpi.h>
#include <map>

namespace htool {

class Cluster_tree {
private:
  // Data
  std::vector<int> perm;
  std::vector<std::pair<int,int>> MasterOffset;
  Cluster root;
  int sizeWorld;
  int rankWorld;
  MPI_Comm comm;
  mutable std::map<std::string, std::string> infos;

  // Tag ranks
  void SetRanksRec(Cluster& t, const unsigned int depth, const unsigned int cnt);
  void SetRanks(Cluster& t);

public:
  // Full Constructor
  Cluster_tree(const std::vector<R3>& x0, const std::vector<double>& r0,const std::vector<int>& tab0, const std::vector<double>& g0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,r0,tab0,g0,perm),comm(comm0){this->build();}

  // Constructor without radius
  Cluster_tree(const std::vector<R3>& x0,const std::vector<int>& tab0, const std::vector<double>& g0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,tab0,g0,perm),comm(comm0){this->build();}

  // Constructor without mass
  Cluster_tree(const std::vector<R3>& x0, const std::vector<double>& r0,const std::vector<int>& tab0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,r0,tab0,perm),comm(comm0){this->build();}

  // Constructor without tab
  Cluster_tree(const std::vector<R3>& x0, const std::vector<double>& r0, const std::vector<double>& g0, MPI_Comm comm0=MPI_COMM_WORLD):perm(x0.size()),root(x0,r0,g0,perm),comm(comm0){this->build();}

  // Constructor without radius and mass
  Cluster_tree(const std::vector<R3>& x0, const std::vector<int>& tab0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,tab0,perm),comm(comm0){this->build();}

  // Constructor without radius, mass and tab
  Cluster_tree(const std::vector<R3>& x0, MPI_Comm comm0=MPI_COMM_WORLD):perm(x0.size()),root(x0,perm),comm(comm0){this->build();}

  // Build
  void build(){
    MPI_Comm_size(comm, &sizeWorld);
    MPI_Comm_rank(comm, &rankWorld);

    // TODO better handling of this case
    if (std::pow(2,root.get_min_depth())<sizeWorld){
      std::cout << "WARNING: too many procs for the cluster tree"<< std::endl;
      std::cout << "(min_deph,sizeworld): ("<<root.get_min_depth()<<","<<sizeWorld<<")"<< std::endl;
    }

    // Infos
    infos["max_depth"]=NbrToStr<int>(root.get_max_depth());
    infos["min_depth"]=NbrToStr<int>(root.get_min_depth());
    infos["master_depth"]=NbrToStr<int>(log2(sizeWorld));

    SetRanks(root);
    int max_size=MasterOffset[0].second;
    int min_size=MasterOffset[0].second;
    for (int i=0;i<MasterOffset.size();i++){
        if (MasterOffset[i].second<min_size)
            min_size=MasterOffset[i].second;
        if (MasterOffset[i].second>max_size)
            max_size=MasterOffset[i].second;
    }

    infos["master_max_size"]=NbrToStr<int>(max_size);
    infos["master_min_size"]=NbrToStr<int>(min_size);

  }

  // Getters
  int get_local_offset() const {return MasterOffset[rankWorld].first;}
  int get_local_size() const {return MasterOffset[rankWorld].second;}
  std::pair<int,int> get_masteroffset(int i)const {return MasterOffset[i];}
  const std::vector<int>& get_perm() const{return perm;};
  std::vector<std::pair<int,int>> get_masteroffset(){return MasterOffset;}
  int get_perm(int i) const{return perm[i];}
  const Cluster& get_root() const {return root;}
  std::vector<int>::const_iterator get_perm_start() const {return perm.begin();}

  // Permutations
  template<typename T>
  void cluster_to_global(const T* const in, T* const out);
  template<typename T>
  void global_to_cluster(const T* const in, T* const out);

  // Print
  void print(){root.print(perm);}

  // Output
  std::vector<int> get_labels(int visudep) const;
  void print_infos() const;
  void save_infos(const std::string& outputname, std::ios_base::openmode mode = std::ios_base::out) const;

};

// Rank tags
void Cluster_tree::SetRanksRec(Cluster& t, const unsigned int depth, const unsigned int cnt){
	if(t.get_depth()<depth){
		t.set_rank(-1);
		SetRanksRec(t.get_son(0), depth, 2*cnt);
		SetRanksRec(t.get_son(1), depth, 2*cnt+1);
	}
	else{
		t.set_rank(cnt-pow(2,depth));
		if (t.get_depth() == depth){
			MasterOffset[cnt-pow(2,depth)] = std::pair<int,int>(t.get_offset(),t.get_size());
		}
		if (!t.IsLeaf()){
			SetRanksRec(t.get_son(0), depth, cnt);
			SetRanksRec(t.get_son(1), depth, cnt);
		}
	}
}

void Cluster_tree::SetRanks(Cluster& t){
	int rankWorld, sizeWorld;
    MPI_Comm_size(comm, &sizeWorld);
    MPI_Comm_rank(comm, &rankWorld);
    MasterOffset.resize(sizeWorld);

	SetRanksRec(t, log2(sizeWorld), 1);
}

template<typename T>
void Cluster_tree::cluster_to_global(const T* const in, T* const out){
  for (int i = 0; i<perm.size();i++){
		out[perm[i]]=in[i];
	}
}
template<typename T>
void Cluster_tree::global_to_cluster(const T* const in, T* const out){
  for (int i = 0; i<perm.size();i++){
    out[i]=in[perm[i]];
  }
}

std::vector<int> Cluster_tree::get_labels(int visudep) const{
  std::vector<int> labels(perm.size());
  std::stack<const Cluster*> s_cluster;
	std::stack<int>      s_count;
  s_cluster.push(&root);
	s_count.push(0);
  while (!(s_cluster.empty())) {
		const Cluster* const curr = s_cluster.top();
		int count     = s_count.top();
		s_cluster.pop();
		s_count.pop();
    if(curr->get_depth()<visudep){
      assert( curr->IsLeaf()!=true ); // check if visudep is too high!
			s_cluster.push(&(curr->get_son(0)));
			s_count.push(2*count);
			s_cluster.push(&(curr->get_son(1)));
			s_count.push(2*count+1);
    }
    else{
      for(int i=curr->get_offset(); i<curr->get_offset()+curr->get_size(); i++){
        labels[ perm[i]] = count;
      }
    }
  }

  return labels;
}
void Cluster_tree::print_infos() const{
    if (rankWorld==0){
        for (std::map<std::string,std::string>::const_iterator it = infos.begin() ; it != infos.end() ; ++it){
            std::cout<<it->first<<"\t"<<it->second<<std::endl;
        }
    std::cout << std::endl;
    }
}

void Cluster_tree::save_infos(const std::string& outputname, std::ios_base::openmode mode ) const{
    if (rankWorld==0){
        std::ofstream outputfile(outputname, mode);
        if (outputfile){
            for (std::map<std::string,std::string>::const_iterator it = infos.begin() ; it != infos.end() ; ++it){
                outputfile<<it->first<<" : "<<it->second<<std::endl;
            }
            outputfile.close();
        }
        else{
            std::cout << "Unable to create "<<outputname<<std::endl;
        }
    }
}

} // namespace

#endif
<commit_msg>testing travis improving identation...<commit_after>#ifndef HTOOL_CLUSTER_TREE_HPP
#define HTOOL_CLUSTER_TREE_HPP

#include "cluster.hpp"
#include <mpi.h>
#include <map>

namespace htool {

class Cluster_tree {
private:
  // Data
  std::vector<int> perm;
  std::vector<std::pair<int,int>> MasterOffset;
  Cluster root;
  int sizeWorld;
  int rankWorld;
  MPI_Comm comm;
  mutable std::map<std::string, std::string> infos;

  // Tag ranks
  void SetRanksRec(Cluster& t, const unsigned int depth, const unsigned int cnt);
  void SetRanks(Cluster& t);

public:
    // Full Constructor
    Cluster_tree(const std::vector<R3>& x0, const std::vector<double>& r0,const std::vector<int>& tab0, const std::vector<double>& g0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,r0,tab0,g0,perm),comm(comm0){this->build();}

    // Constructor without radius
    Cluster_tree(const std::vector<R3>& x0,const std::vector<int>& tab0, const std::vector<double>& g0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,tab0,g0,perm),comm(comm0){this->build();}

    // Constructor without mass
    Cluster_tree(const std::vector<R3>& x0, const std::vector<double>& r0,const std::vector<int>& tab0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,r0,tab0,perm),comm(comm0){this->build();}

    // Constructor without tab
    Cluster_tree(const std::vector<R3>& x0, const std::vector<double>& r0, const std::vector<double>& g0, MPI_Comm comm0=MPI_COMM_WORLD):perm(x0.size()),root(x0,r0,g0,perm),comm(comm0){this->build();}

    // Constructor without radius and mass
    Cluster_tree(const std::vector<R3>& x0, const std::vector<int>& tab0, MPI_Comm comm0=MPI_COMM_WORLD):perm(tab0.size()),root(x0,tab0,perm),comm(comm0){this->build();}

    // Constructor without radius, mass and tab
    Cluster_tree(const std::vector<R3>& x0, MPI_Comm comm0=MPI_COMM_WORLD):perm(x0.size()),root(x0,perm),comm(comm0){this->build();}

    // Build
    void build(){
        MPI_Comm_size(comm, &sizeWorld);
        MPI_Comm_rank(comm, &rankWorld);

        // TODO better handling of this case
        if (std::pow(2,root.get_min_depth())<sizeWorld){
          std::cout << "WARNING: too many procs for the cluster tree"<< std::endl;
          std::cout << "(min_deph,sizeworld): ("<<root.get_min_depth()<<","<<sizeWorld<<")"<< std::endl;
        }

        // Infos
        infos["max_depth"]=NbrToStr<int>(root.get_max_depth());
        infos["min_depth"]=NbrToStr<int>(root.get_min_depth());
        infos["master_depth"]=NbrToStr<int>(log2(sizeWorld));

        SetRanks(root);
        int max_size=MasterOffset[0].second;
        int min_size=MasterOffset[0].second;
        for (int i=0;i<MasterOffset.size();i++){
            if (MasterOffset[i].second<min_size)
                min_size=MasterOffset[i].second;
            if (MasterOffset[i].second>max_size)
                max_size=MasterOffset[i].second;
        }

        infos["master_max_size"]=NbrToStr<int>(max_size);
        infos["master_min_size"]=NbrToStr<int>(min_size);

    }

    // Getters
    int get_local_offset() const {return MasterOffset[rankWorld].first;}
    int get_local_size() const {return MasterOffset[rankWorld].second;}
    std::pair<int,int> get_masteroffset(int i)const {return MasterOffset[i];}
    const std::vector<int>& get_perm() const{return perm;};
    std::vector<std::pair<int,int>> get_masteroffset(){return MasterOffset;}
    int get_perm(int i) const{return perm[i];}
    const Cluster& get_root() const {return root;}
    std::vector<int>::const_iterator get_perm_start() const {return perm.begin();}

    // Permutations
    template<typename T>
    void cluster_to_global(const T* const in, T* const out);
    template<typename T>
    void global_to_cluster(const T* const in, T* const out);

    // Print
    void print(){root.print(perm);}

    // Output
    std::vector<int> get_labels(int visudep) const;
    void print_infos() const;
    void save_infos(const std::string& outputname, std::ios_base::openmode mode = std::ios_base::out) const;

};

// Rank tags
void Cluster_tree::SetRanksRec(Cluster& t, const unsigned int depth, const unsigned int cnt){
	if(t.get_depth()<depth){
		t.set_rank(-1);
		SetRanksRec(t.get_son(0), depth, 2*cnt);
		SetRanksRec(t.get_son(1), depth, 2*cnt+1);
	}
	else{
		t.set_rank(cnt-pow(2,depth));
		if (t.get_depth() == depth){
			MasterOffset[cnt-pow(2,depth)] = std::pair<int,int>(t.get_offset(),t.get_size());
		}
		if (!t.IsLeaf()){
			SetRanksRec(t.get_son(0), depth, cnt);
			SetRanksRec(t.get_son(1), depth, cnt);
		}
	}
}

void Cluster_tree::SetRanks(Cluster& t){
	int rankWorld, sizeWorld;
    MPI_Comm_size(comm, &sizeWorld);
    MPI_Comm_rank(comm, &rankWorld);
    MasterOffset.resize(sizeWorld);

	SetRanksRec(t, log2(sizeWorld), 1);
}

template<typename T>
void Cluster_tree::cluster_to_global(const T* const in, T* const out){
  for (int i = 0; i<perm.size();i++){
		out[perm[i]]=in[i];
	}
}
template<typename T>
void Cluster_tree::global_to_cluster(const T* const in, T* const out){
  for (int i = 0; i<perm.size();i++){
    out[i]=in[perm[i]];
  }
}

std::vector<int> Cluster_tree::get_labels(int visudep) const{
  std::vector<int> labels(perm.size());
  std::stack<const Cluster*> s_cluster;
	std::stack<int>      s_count;
  s_cluster.push(&root);
	s_count.push(0);
  while (!(s_cluster.empty())) {
		const Cluster* const curr = s_cluster.top();
		int count     = s_count.top();
		s_cluster.pop();
		s_count.pop();
    if(curr->get_depth()<visudep){
      assert( curr->IsLeaf()!=true ); // check if visudep is too high!
			s_cluster.push(&(curr->get_son(0)));
			s_count.push(2*count);
			s_cluster.push(&(curr->get_son(1)));
			s_count.push(2*count+1);
    }
    else{
      for(int i=curr->get_offset(); i<curr->get_offset()+curr->get_size(); i++){
        labels[ perm[i]] = count;
      }
    }
  }

  return labels;
}
void Cluster_tree::print_infos() const{
    if (rankWorld==0){
        for (std::map<std::string,std::string>::const_iterator it = infos.begin() ; it != infos.end() ; ++it){
            std::cout<<it->first<<"\t"<<it->second<<std::endl;
        }
    std::cout << std::endl;
    }
}

void Cluster_tree::save_infos(const std::string& outputname, std::ios_base::openmode mode ) const{
    if (rankWorld==0){
        std::ofstream outputfile(outputname, mode);
        if (outputfile){
            for (std::map<std::string,std::string>::const_iterator it = infos.begin() ; it != infos.end() ; ++it){
                outputfile<<it->first<<" : "<<it->second<<std::endl;
            }
            outputfile.close();
        }
        else{
            std::cout << "Unable to create "<<outputname<<std::endl;
        }
    }
}

} // namespace

#endif
<|endoftext|>


<commit_before>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_SERVICE_TRAITS_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_SERVICE_TRAITS_HPP

#include "traits.hpp"
#include "single.hpp"
#include "injected.hpp"
#include "container_service.hpp"

namespace kgr {
namespace detail {

template<typename T>
using is_container_service = std::is_base_of<ContainerServiceTag, T>;

template<typename>
struct original;

template<typename T>
struct original<BaseInjected<T>&> {
	using type = T;
};

template<typename T>
struct original<Injected<T>&&> {
	using type = T;
};

template<typename T>
using original_t = typename original<T>::type;

template<std::size_t n, typename F>
using injected_argument_t = original_t<function_argument_t<n, F>>;

template<template<typename...> class Trait, typename T, typename... Args>
struct dependency_trait_helper {
	static std::true_type sink(...);

	template<typename U, typename... As, std::size_t... S>
	static decltype(sink(
		std::declval<enable_if_t<dependency_trait_helper<Trait, injected_argument_t<S, construct_function_t<U, As...>>>::type::value, int>>()...,
		std::declval<enable_if_t<Trait<injected_argument_t<S, construct_function_t<U, As...>>>::value, int>>()...
	)) test(seq<S...>);

	template<typename U, typename...>
	static enable_if_t<is_container_service<U>::value || std::is_abstract<U>::value, std::true_type> test_helper(int);

	template<typename...>
	static std::false_type test(...);

	template<typename...>
	static std::false_type test_helper(...);

	template<typename U, typename... As>
	static decltype(test<U, As...>(tuple_seq_minus<function_arguments_t<construct_function_t<U, As...>>, sizeof...(As)>{})) test_helper(int);

public:
	using type = decltype(test_helper<T, Args...>(0));
};

template<template<typename...> class Trait, typename T, typename... Args>
using dependency_trait = typename dependency_trait_helper<Trait, T, Args...>::type;

template<typename T, typename... Args>
struct is_service_constructible_helper {
private:
	static std::true_type sink(...);

	template<typename U, typename... As, std::size_t... S>
	static decltype(sink(
		std::declval<enable_if_t<is_service_instantiable<T, tuple_element_t<S, function_result_t<construct_function_t<U, As...>>>...>::value, int>>()
	)) test(seq<S...>);

	template<typename U, typename...>
	static enable_if_t<is_container_service<U>::value || std::is_abstract<U>::value, std::true_type> test_helper(int);

	template<typename...>
	static std::false_type test(...);

	template<typename...>
	static std::false_type test_helper(...);

	template<typename U, typename... As>
	static decltype(test<U, As...>(tuple_seq<function_result_t<construct_function_t<U, As...>>>{})) test_helper(int);

public:
	using type = decltype(test_helper<T, Args...>(0));
};

template<typename T, typename... Args>
using is_service_constructible = typename is_service_constructible_helper<T, Args...>::type;

template<typename T>
struct is_override_service_helper {
private:
	template<typename...>
	static std::false_type test(...);

	template<typename U, std::size_t... S, int_t<enable_if_t<is_service<meta_list_element_t<S, parent_types<U>>>::value>...> = 0>
	static std::true_type test(seq<S...>);

public:
	using type = decltype(test<T>(tuple_seq<parent_types<T>>{}));
};

template<typename T>
using is_override_service = typename is_override_service_helper<T>::type;

template<typename T>
struct is_override_convertible_helper {
private:
	template<typename...>
	static std::false_type test(...);

	template<typename U, std::size_t... S, int_t<enable_if_t<is_explicitly_convertible<ServiceType<U>, ServiceType<meta_list_element_t<S, parent_types<U>>>>::value>...> = 0>
	static std::true_type test(seq<S...>);

public:
	using type = decltype(test<T>(tuple_seq<parent_types<T>>{}));
};

template<typename T>
using is_override_convertible = typename is_override_convertible_helper<T>::type;

template<typename T, typename... Args>
using is_single_no_args = std::integral_constant<bool,
	!is_single<T>::value || sizeof...(Args) == 0
>;

template<typename T>
struct is_default_overrides_abstract_helper {
private:
	template<typename>
	static std::false_type test(...);

	template<typename U, enable_if_t<has_default<U>::value && std::is_abstract<U>::value, int> = 0>
	static is_overriden_by<U, default_type<U>> test(int);

	template<typename U, enable_if_t<!has_default<U>::value, int> = 0>
	static std::true_type test(int);

public:
	using type = decltype(test<T>(0));
};

template<typename T>
using is_default_overrides_abstract = typename is_default_overrides_abstract_helper<T>::type;

template<typename T>
struct is_default_convertible_helper {
private:
	template<typename>
	static std::false_type test(...);

	template<typename U, enable_if_t<has_default<U>::value, int> = 0>
	static is_explicitly_convertible<ServiceType<default_type<U>>, ServiceType<U>> test(int);

	template<typename U, enable_if_t<!has_default<U>::value, int> = 0>
	static std::true_type test(int);

public:
	using type = decltype(test<T>(0));
};

template<typename T>
using is_default_convertible = typename is_default_convertible_helper<T>::type;

template<typename T, typename... Args>
using is_default_service_valid = std::integral_constant<bool,
	((has_default<T>::value && std::is_abstract<T>::value) ||
	!(has_default<T>::value || std::is_abstract<T>::value)) &&
	is_default_overrides_abstract<T>::value &&
	is_default_convertible<T>::value
>;

template<typename T, typename... Args>
using is_service_valid = std::integral_constant<bool,
	is_service<T>::value &&
	is_single_no_args<T, Args...>::value &&
	dependency_trait<is_service, T, Args...>::value &&
	is_service_constructible<T, Args...>::value &&
	dependency_trait<is_service_constructible, T, Args...>::value &&
	is_default_service_valid<T>::value &&
	dependency_trait<is_override_convertible, T, Args...>::value &&
	is_override_convertible<T>::value
>;

} // namespace detail
} // namespace kgr

#endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_SERVICE_TRAITS_HPP
<commit_msg>fixed compilation with msvc<commit_after>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_SERVICE_TRAITS_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_SERVICE_TRAITS_HPP

#include "traits.hpp"
#include "single.hpp"
#include "injected.hpp"
#include "container_service.hpp"

namespace kgr {
namespace detail {

template<typename T>
using is_container_service = std::is_base_of<ContainerServiceTag, T>;

template<typename>
struct original;

template<typename T>
struct original<BaseInjected<T>&> {
	using type = T;
};

template<typename T>
struct original<Injected<T>&&> {
	using type = T;
};

template<typename T>
using original_t = typename original<T>::type;

template<std::size_t n, typename F>
using injected_argument_t = original_t<function_argument_t<n, F>>;

template<template<typename...> class Trait, typename T, typename... Args>
struct dependency_trait_helper {
	static std::true_type sink(...);

	template<typename U, typename... As, std::size_t... S>
	static decltype(sink(
		std::declval<enable_if_t<dependency_trait_helper<Trait, injected_argument_t<S, construct_function_t<U, As...>>>::type::value, int>>()...,
		std::declval<enable_if_t<Trait<injected_argument_t<S, construct_function_t<U, As...>>>::value, int>>()...
	)) test(seq<S...>);

	template<typename U, typename...>
	static enable_if_t<is_container_service<U>::value || std::is_abstract<U>::value, std::true_type> test_helper(int);

	template<typename...>
	static std::false_type test(...);

	template<typename...>
	static std::false_type test_helper(...);

	template<typename U, typename... As>
	static decltype(test<U, As...>(tuple_seq_minus<function_arguments_t<construct_function_t<U, As...>>, sizeof...(As)>{})) test_helper(int);

public:
	using type = decltype(test_helper<T, Args...>(0));
};

template<template<typename...> class Trait, typename T, typename... Args>
using dependency_trait = typename dependency_trait_helper<Trait, T, Args...>::type;

template<typename T, typename... Args>
struct is_service_constructible_helper {
private:
	static std::true_type sink(...);

	template<typename U, typename... As, std::size_t... S>
	static is_service_instantiable<T, tuple_element_t<S, function_result_t<construct_function_t<U, As...>>>...> test(seq<S...>);

	template<typename U, typename...>
	static enable_if_t<is_container_service<U>::value || std::is_abstract<U>::value, std::true_type> test_helper(int);

	template<typename...>
	static std::false_type test(...);

	template<typename...>
	static std::false_type test_helper(...);

	template<typename U, typename... As>
	static decltype(test<U, As...>(tuple_seq<function_result_t<construct_function_t<U, As...>>>{})) test_helper(int);

public:
	using type = decltype(test_helper<T, Args...>(0));
};

template<typename T, typename... Args>
using is_service_constructible = typename is_service_constructible_helper<T, Args...>::type;

template<typename T>
struct is_override_service_helper {
private:
	template<typename...>
	static std::false_type test(...);

	template<typename U, std::size_t... S, int_t<enable_if_t<is_service<meta_list_element_t<S, parent_types<U>>>::value>...> = 0>
	static std::true_type test(seq<S...>);

public:
	using type = decltype(test<T>(tuple_seq<parent_types<T>>{}));
};

template<typename T>
using is_override_service = typename is_override_service_helper<T>::type;

template<typename T>
struct is_override_convertible_helper {
private:
	// This is a workaround for msvc. Expansion in very complex expression
	// leaves the compiler without clues about what's going on.
	template<std::size_t I, typename U>
	struct expander {
		using type = is_explicitly_convertible<ServiceType<U>, ServiceType<meta_list_element_t<I, parent_types<U>>>>;
	};

	template<typename...>
	static std::false_type test(...);

	template<typename U, std::size_t... S, int_t<enable_if_t<expander<S, U>::type::value>...> = 0 >
	static std::true_type test(seq<S...>);

public:
	using type = decltype(test<T>(tuple_seq<parent_types<T>>{}));
};

template<typename T>
using is_override_convertible = typename is_override_convertible_helper<T>::type;

template<typename T, typename... Args>
using is_single_no_args = std::integral_constant<bool,
	!is_single<T>::value || meta_list_empty<meta_list<Args...>>::value
>;

template<typename T>
struct is_default_overrides_abstract_helper {
private:
	template<typename>
	static std::false_type test(...);

	template<typename U, enable_if_t<has_default<U>::value && std::is_abstract<U>::value, int> = 0>
	static is_overriden_by<U, default_type<U>> test(int);

	template<typename U, enable_if_t<!has_default<U>::value, int> = 0>
	static std::true_type test(int);

public:
	using type = decltype(test<T>(0));
};

template<typename T>
using is_default_overrides_abstract = typename is_default_overrides_abstract_helper<T>::type;

template<typename T>
struct is_default_convertible_helper {
private:
	template<typename>
	static std::false_type test(...);

	template<typename U, enable_if_t<has_default<U>::value, int> = 0>
	static is_explicitly_convertible<ServiceType<default_type<U>>, ServiceType<U>> test(int);

	template<typename U, enable_if_t<!has_default<U>::value, int> = 0>
	static std::true_type test(int);

public:
	using type = decltype(test<T>(0));
};

template<typename T>
using is_default_convertible = typename is_default_convertible_helper<T>::type;

template<typename T, typename... Args>
using is_default_service_valid = std::integral_constant<bool,
	((has_default<T>::value && std::is_abstract<T>::value) ||
	!(has_default<T>::value || std::is_abstract<T>::value)) &&
	is_default_overrides_abstract<T>::value &&
	is_default_convertible<T>::value
>;

template<typename T, typename... Args>
using is_service_valid = std::integral_constant<bool,
	is_service<T>::value &&
	is_single_no_args<T, Args...>::value &&
	dependency_trait<is_service, T, Args...>::value &&
	is_service_constructible<T, Args...>::value &&
	dependency_trait<is_service_constructible, T, Args...>::value &&
	is_default_service_valid<T>::value &&
	dependency_trait<is_override_convertible, T, Args...>::value &&
	is_override_convertible<T>::value
>;

} // namespace detail
} // namespace kgr

#endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_SERVICE_TRAITS_HPP
<|endoftext|>


<commit_before>#include "Filter.h"
#include <vector>

using namespace std;

Filter::Filter(float length = 0.65) {
	int i;

	// Saiten-Koeffizienten
	this->l = length;
	this->Ts = 60.97;
	this->rho = 1140;
	this->A = 0.5188e-6;
	this->E = 5.4e9;
	this->I = 0.171e-12;
	this->d1 = 8e-5;
	this->d3 = -1.4e-5;

	// Abtastpunkt
	this->xa = 0.1;

	// Abtastrate und Samplelänge
	this->T = 44100;
	this->seconds = 1;
	this->samples = seconds*T;
	this->filters = 30;

	// Blockverarbeitungs-Länge
	this->blocksize = 100;

	this->createMatrices();

	MCA = MC.multiply(MA);

#if DEBUG == 2
	cout << "MA";
	cout << MA.toString();
	cout << "MCA";
	cout << MCA.toString();
	cout << "MC";
	cout << MC.toString();
#endif

	for(i = 0; i < this->samples; i++) {
#if DEBUG == 0
		cout << this->MCA.multiply(this->Mstate).get(0,0) << ", ";
#endif
		this->Mstate = this->MA.multiply(this->Mstate);
	}
}

void Filter::createMatrices() {
	int i, mu;
	double gamma, sigma;
	double omega;
	double a, b, c1, c0;

	this->MC.resize(1, 2 * this->filters);
	this->MA.resize(2 * this->filters, 2 * this->filters);
	this->Mstate.resize(2 * this->filters, 1);

	for(i = 0; i < this->filters; i++) {
		mu = i+1;
		gamma = mu * ( M_PI / this->l );
		sigma = (1 / (2 * this->rho * this->A) ) * (this->d3 * pow(gamma,2) - this->d1);
		omega = sqrt(
				  (
					(
						( (this->E * this->I) / (this->rho * this->A) )
						- ( pow(this->d3, 2) / pow(2 * this->rho * this->A, 2) )
					) * pow(gamma, 4)
				  )
				+ ( (this->Ts / (this->rho * this->A) ) * pow(gamma, 2) )
				// + ( pow(this->d1 / (2 * this->rho * this->A), 2) )
			);

		a = sin(mu * M_PI * this->xa / this->l);

		b = this->T * sin(omega * 1 / this->T) / (omega * 1 / this->T);
		c1 = -2 * exp(sigma * 1 / this->T) * cos(omega * 1 / this->T);
		c0 = exp( 2 * sigma * 1 / this->T);

#if DEBUG == 1
		cout << i << " " << mu << " sigma " << sigma << endl;
		cout << "      omega " << omega << endl;
#endif

		this->MC.set(0, 2*i  , 0);
		this->MC.set(0, 2*i+1, a);

		this->MA.set(2*i  , 2*i  , 0);
		this->MA.set(2*i  , 2*i+1, -c0);
		this->MA.set(2*i+1, 2*i  , 1);
		this->MA.set(2*i+1, 2*i+1, -c1);

		this->Mstate.set(2*i  , 0, 1);
		this->Mstate.set(2*i+1, 0, 0);

	}
}
<commit_msg>Libsndfile header<commit_after>#include "Filter.h"
#include <vector>
#include <sndfile.hh>

using namespace std;

Filter::Filter(float length = 0.65) {
	int i;

	// Saiten-Koeffizienten
	this->l = length;
	this->Ts = 60.97;
	this->rho = 1140;
	this->A = 0.5188e-6;
	this->E = 5.4e9;
	this->I = 0.171e-12;
	this->d1 = 8e-5;
	this->d3 = -1.4e-5;

	// Abtastpunkt
	this->xa = 0.1;

	// Abtastrate und Samplelänge
	this->T = 44100;
	this->seconds = 1;
	this->samples = seconds*T;
	this->filters = 30;

	// Blockverarbeitungs-Länge
	this->blocksize = 100;

	this->createMatrices();

	MCA = MC.multiply(MA);

#if DEBUG == 2
	cout << "MA";
	cout << MA.toString();
	cout << "MCA";
	cout << MCA.toString();
	cout << "MC";
	cout << MC.toString();
#endif

	for(i = 0; i < this->samples; i++) {
#if DEBUG == 0
		cout << this->MCA.multiply(this->Mstate).get(0,0) << ", ";
#endif
		this->Mstate = this->MA.multiply(this->Mstate);
	}
}

void Filter::createMatrices() {
	int i, mu;
	double gamma, sigma;
	double omega;
	double a, b, c1, c0;

	this->MC.resize(1, 2 * this->filters);
	this->MA.resize(2 * this->filters, 2 * this->filters);
	this->Mstate.resize(2 * this->filters, 1);

	for(i = 0; i < this->filters; i++) {
		mu = i+1;
		gamma = mu * ( M_PI / this->l );
		sigma = (1 / (2 * this->rho * this->A) ) * (this->d3 * pow(gamma,2) - this->d1);
		omega = sqrt(
				  (
					(
						( (this->E * this->I) / (this->rho * this->A) )
						- ( pow(this->d3, 2) / pow(2 * this->rho * this->A, 2) )
					) * pow(gamma, 4)
				  )
				+ ( (this->Ts / (this->rho * this->A) ) * pow(gamma, 2) )
				// + ( pow(this->d1 / (2 * this->rho * this->A), 2) )
			);

		a = sin(mu * M_PI * this->xa / this->l);

		b = this->T * sin(omega * 1 / this->T) / (omega * 1 / this->T);
		c1 = -2 * exp(sigma * 1 / this->T) * cos(omega * 1 / this->T);
		c0 = exp( 2 * sigma * 1 / this->T);

#if DEBUG == 1
		cout << i << " " << mu << " sigma " << sigma << endl;
		cout << "      omega " << omega << endl;
#endif

		this->MC.set(0, 2*i  , 0);
		this->MC.set(0, 2*i+1, a);

		this->MA.set(2*i  , 2*i  , 0);
		this->MA.set(2*i  , 2*i+1, -c0);
		this->MA.set(2*i+1, 2*i  , 1);
		this->MA.set(2*i+1, 2*i+1, -c1);

		this->Mstate.set(2*i  , 0, 1);
		this->Mstate.set(2*i+1, 0, 0);

	}
}
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
/*!
 * \file MCLS_DomainTraits.hpp
 * \author Stuart R. Slattery
 * \brief Domain traits definition.
 */
//---------------------------------------------------------------------------//

#ifndef MCLS_DOMAINTRAITS_HPP
#define MCLS_DOMAINTRAITS_HPP

#include <Teuchos_RCP.hpp>
#include <Teuchos_Comm.hpp>
#include <Teuchos_ArrayView.hpp>
#include <Teuchos_Array.hpp>

namespace MCLS
{

//---------------------------------------------------------------------------//
/*!
 * \class UndefinedDomainTraits
 * \brief Class for undefined domain traits.
 *
 * Will throw a compile-time error if these traits are not specialized.
 */
template<class Domain>
struct UndefinedDomainTraits
{
    static inline void notDefined()
    {
	return Domain::this_type_is_missing_a_specialization();
    }
};

//---------------------------------------------------------------------------//
/*!
 * \class DomainTraits
 * \brief Traits for Monte Carlo transport domains.
 *
 * DomainTraits defines an interface for parallel distributed domains.
 */
template<class Domain>
class DomainTraits
{
  public:

    //@{
    //! Typedefs.
    typedef Domain                                      domain_type;
    typedef typename Domain::ordinal_type               ordinal_type;
    typedef typename Domain::history_type               history_type;
    typedef typename Domain::tally_type                 tally_type;
    typedef typename Domain::bank_type                  bank_type;
    typedef Teuchos::Comm<int>                          Comm;
    //@}

    /*!
     * \brief Create a reference-counted pointer to a new domain defined over
     * the given communicator by unpacking
     * a data buffer.
     */
    static Teuchos::RCP<Domain>
    createFromBuffer(
	const Teuchos::RCP<const Comm>& comm,
	const Teuchos::ArrayView<char>& buffer )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::null;
    }

    /*!
     * \brief Pack a domain into a buffer.
     */
    static Teuchos::Array<char> pack( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::Array<char>(0);
    }

    /*!
     * \brief Get the size of domain in packed bytes.
     */
    static std::size_t getPackedBytes( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::Array<char>(0);
    }

    /*!
     * \brief Process a history through a transition in the local domain to a
     * new state
     */
    static inline void processTransition(
	const Domain& domain, history_type& history )
    {
	UndefinedDomainTraits<Domain>::notDefined();
    }

    /*!
     * \brief Get the tally associated with this domain.
     */
    static Teuchos::RCP<tally_type> domainTally( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::null;
    }

    /*!
     * \brief Determine if a given state is in the local domain.
     */
    static bool isLocalState( const Domain& domain, const ordinal_type state )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return false;
    }

    /*!
     * \brief Get the number of neighbors from which this domain will
     * receive.
     */
    static int numReceiveNeighbors( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Given a local neighbor ID, return the proc rank of that
     * neighbor.
     */
    static int receiveNeighborRank( const Domain& domain, int neighbor_id )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Get the number of neighbors to which this domain will send.
     */
    static int numSendNeighbors( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Given a local neighbor ID, return the proc rank of that
     * neighbor.
     */
    static int sendNeighborRank( const Domain& domain, int neighbor_id )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Given a state on the boundary or this domain, return the ID of
     * the owning neighbor.
     */
    static int owningNeighbor( const Domain& domain, const ordinal_type state )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }
};

//---------------------------------------------------------------------------//

} // end namespace MCLS

#endif // end MCLS_DOMAINTRAITS_HPP

//---------------------------------------------------------------------------//
// end MCLS_DomainTraits.hpp
//---------------------------------------------------------------------------//

<commit_msg>fixed typos in domain traits<commit_after>//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
/*!
 * \file MCLS_DomainTraits.hpp
 * \author Stuart R. Slattery
 * \brief Domain traits definition.
 */
//---------------------------------------------------------------------------//

#ifndef MCLS_DOMAINTRAITS_HPP
#define MCLS_DOMAINTRAITS_HPP

#include <Teuchos_RCP.hpp>
#include <Teuchos_Comm.hpp>
#include <Teuchos_ArrayView.hpp>
#include <Teuchos_Array.hpp>

namespace MCLS
{

//---------------------------------------------------------------------------//
/*!
 * \class UndefinedDomainTraits
 * \brief Class for undefined domain traits.
 *
 * Will throw a compile-time error if these traits are not specialized.
 */
template<class Domain>
struct UndefinedDomainTraits
{
    static inline void notDefined()
    {
	return Domain::this_type_is_missing_a_specialization();
    }
};

//---------------------------------------------------------------------------//
/*!
 * \class DomainTraits
 * \brief Traits for Monte Carlo transport domains.
 *
 * DomainTraits defines an interface for parallel distributed domains.
 */
template<class Domain>
class DomainTraits
{
  public:

    //@{
    //! Typedefs.
    typedef Domain                                      domain_type;
    typedef typename Domain::ordinal_type               ordinal_type;
    typedef typename Domain::history_type               history_type;
    typedef typename Domain::tally_type                 tally_type;
    typedef typename Domain::bank_type                  bank_type;
    typedef Teuchos::Comm<int>                          Comm;
    //@}

    /*!
     * \brief Create a reference-counted pointer to a new domain defined over
     * the given communicator by unpacking a data buffer.
     */
    static Teuchos::RCP<Domain>
    createFromBuffer( const Teuchos::RCP<const Comm>& comm,
		      const Teuchos::ArrayView<char>& buffer )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::null;
    }

    /*!
     * \brief Pack a domain into a buffer.
     */
    static Teuchos::Array<char> pack( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::Array<char>(0);
    }

    /*!
     * \brief Get the size of domain in packed bytes.
     */
    static std::size_t getPackedBytes( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Process a history through a transition in the local domain to a
     * new state
     */
    static inline void processTransition(
	const Domain& domain, history_type& history )
    {
	UndefinedDomainTraits<Domain>::notDefined();
    }

    /*!
     * \brief Get the tally associated with this domain.
     */
    static Teuchos::RCP<tally_type> domainTally( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return Teuchos::null;
    }

    /*!
     * \brief Determine if a given state is in the local domain.
     */
    static bool isLocalState( const Domain& domain, const ordinal_type state )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return false;
    }

    /*!
     * \brief Get the number of neighbors from which this domain will
     * receive.
     */
    static int numReceiveNeighbors( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Given a local neighbor ID, return the proc rank of that
     * neighbor.
     */
    static int receiveNeighborRank( const Domain& domain, int neighbor_id )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Get the number of neighbors to which this domain will send.
     */
    static int numSendNeighbors( const Domain& domain )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Given a local neighbor ID, return the proc rank of that
     * neighbor.
     */
    static int sendNeighborRank( const Domain& domain, int neighbor_id )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }

    /*!
     * \brief Given a state on the boundary or this domain, return the ID of
     * the owning neighbor.
     */
    static int owningNeighbor( const Domain& domain, const ordinal_type state )
    {
	UndefinedDomainTraits<Domain>::notDefined();
	return 0;
    }
};

//---------------------------------------------------------------------------//

} // end namespace MCLS

#endif // end MCLS_DOMAINTRAITS_HPP

//---------------------------------------------------------------------------//
// end MCLS_DomainTraits.hpp
//---------------------------------------------------------------------------//

<|endoftext|>


<commit_before>#ifndef OPENGM_LEARNING_WEIGHTS
#define OPENGM_LEARNING_WEIGHTS

namespace opengm{
namespace learning{

   template<class T>
   class Weights{
   public:
      typedef T ValueType;

      Weights(const size_t numberOfParameters=0)
      : weights_(numberOfParameters){

      }

      ValueType getWeight(const size_t pi)const{
         OPENGM_ASSERT_OP(pi,<,weights_.size());
         return weights_[pi];
      }

      void setWeight(const size_t pi,const ValueType value){
         OPENGM_ASSERT_OP(pi,<,weights_.size());
         weights_[pi]=value;
      }

      ValueType operator[](const size_t pi)const{
         return getWeight(pi);
      }

      size_t numberOfWeights()const{
         return weights_.size();
      }

   private:

      std::vector<ValueType> weights_;
   };
} // namespace learning
} // namespace opengm

#endif /* OPENGM_LEARNING_WEIGHTS */
<commit_msg>fixed operator[] for opengm::Weights<commit_after>#ifndef OPENGM_LEARNING_WEIGHTS
#define OPENGM_LEARNING_WEIGHTS

namespace opengm{
namespace learning{

   template<class T>
   class Weights{
   public:
      typedef T ValueType;

      Weights(const size_t numberOfParameters=0)
      : weights_(numberOfParameters){

      }

      ValueType getWeight(const size_t pi)const{
         OPENGM_ASSERT_OP(pi,<,weights_.size());
         return weights_[pi];
      }

      void setWeight(const size_t pi,const ValueType value){
         OPENGM_ASSERT_OP(pi,<,weights_.size());
         weights_[pi]=value;
      }

      const ValueType& operator[](const size_t pi)const{
         return weights_[pi];
      }

      ValueType& operator[](const size_t pi) {
         return weights_[pi];
      }

      size_t numberOfWeights()const{
         return weights_.size();
      }

   private:

      std::vector<ValueType> weights_;
   };
} // namespace learning
} // namespace opengm

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


<commit_before>
#pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcrypto/SHA3.h>
#include <libethcore/Params.h>
#include <libevm/ExtVMFace.h>

#include "Utils.h"

extern "C"
{
	#ifdef _MSC_VER
		#define EXPORT __declspec(dllexport)
	#else
		#define EXPORT
	#endif

	using namespace dev;
	using namespace dev::eth;
	using jit::i256;

	EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value)
	{
		auto index = llvm2eth(*_index);
		auto value = _env->store(index); // Interface uses native endianness
		*o_value = eth2llvm(value);
	}

	EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value)
	{
		auto index = llvm2eth(*_index);
		auto value = llvm2eth(*_value);

		if (value == 0 && _env->store(index) != 0)	// If delete
			_env->sub.refunds += c_sstoreRefundGas;	// Increase refund counter

		_env->setStore(index, value);	// Interface uses native endianness
	}

	EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value)
	{
		auto u = _env->balance(right160(*_address));
		*o_value = eth2llvm(u);
	}

	EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
	{
		*o_hash = _env->blockhash(llvm2eth(*_number));
	}

	EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
	{
		auto endowment = llvm2eth(*_endowment);
		if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
		{
			u256 gas = *io_gas;
			h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, {}), h256::AlignRight);
			*io_gas = static_cast<int64_t>(gas);
			*o_address = address;
		}
		else
			*o_address = {};
	}

	EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
	{
		auto value = llvm2eth(*_value);
		auto receiveAddress = right160(*_receiveAddress);
		auto codeAddress = right160(*_codeAddress);
		const auto isCall = receiveAddress == codeAddress; // OPT: The same address pointer can be used if not CODECALL

		*io_gas -= _callGas;
		if (*io_gas < 0)
			return false;

		if (isCall && !_env->exists(receiveAddress))
			*io_gas -= static_cast<int64_t>(c_callNewAccountGas); // no underflow, *io_gas non-negative before

		if (value > 0) // value transfer
		{
			/*static*/ assert(c_callValueTransferGas > c_callStipend && "Overflow possible");
			*io_gas -= static_cast<int64_t>(c_callValueTransferGas); // no underflow
			_callGas += static_cast<int64_t>(c_callStipend); // overflow possibility, but in the same time *io_gas < 0
		}

		if (*io_gas < 0)
			return false;

		auto ret = false;
		auto callGas = u256{_callGas};
		if (_env->balance(_env->myAddress) >= value && _env->depth < 1024)
			ret = _env->call(receiveAddress, value, {_inBeg, _inSize}, callGas, {_outBeg, _outSize}, {}, {}, codeAddress);

		*io_gas += static_cast<int64_t>(callGas); // it is never more than initial _callGas
		return ret;
	}

	EXPORT void env_sha3(byte* _begin, uint64_t _size, h256* o_hash)
	{
		auto hash = sha3({_begin, _size});
		*o_hash = hash;
	}

	EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size)
	{
		auto addr = right160(*_addr256);
		auto& code = _env->codeAt(addr);
		*o_size = code.size();
		return code.data();
	}

	EXPORT void env_log(ExtVMFace* _env, byte* _beg, uint64_t _size, h256* _topic1, h256* _topic2, h256* _topic3, h256* _topic4)
	{
		dev::h256s topics;

		if (_topic1)
			topics.push_back(*_topic1);

		if (_topic2)
			topics.push_back(*_topic2);

		if (_topic3)
			topics.push_back(*_topic3);

		if (_topic4)
			topics.push_back(*_topic4);

		_env->log(std::move(topics), {_beg, _size});
	}
}

<commit_msg>Move assembly related files to libevmasm and Params.h/.cpp to libevmcore.<commit_after>
#pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcrypto/SHA3.h>
#include <libevmcore/Params.h>
#include <libevm/ExtVMFace.h>

#include "Utils.h"

extern "C"
{
	#ifdef _MSC_VER
		#define EXPORT __declspec(dllexport)
	#else
		#define EXPORT
	#endif

	using namespace dev;
	using namespace dev::eth;
	using jit::i256;

	EXPORT void env_sload(ExtVMFace* _env, i256* _index, i256* o_value)
	{
		auto index = llvm2eth(*_index);
		auto value = _env->store(index); // Interface uses native endianness
		*o_value = eth2llvm(value);
	}

	EXPORT void env_sstore(ExtVMFace* _env, i256* _index, i256* _value)
	{
		auto index = llvm2eth(*_index);
		auto value = llvm2eth(*_value);

		if (value == 0 && _env->store(index) != 0)	// If delete
			_env->sub.refunds += c_sstoreRefundGas;	// Increase refund counter

		_env->setStore(index, value);	// Interface uses native endianness
	}

	EXPORT void env_balance(ExtVMFace* _env, h256* _address, i256* o_value)
	{
		auto u = _env->balance(right160(*_address));
		*o_value = eth2llvm(u);
	}

	EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
	{
		*o_hash = _env->blockhash(llvm2eth(*_number));
	}

	EXPORT void env_create(ExtVMFace* _env, int64_t* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
	{
		auto endowment = llvm2eth(*_endowment);
		if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
		{
			u256 gas = *io_gas;
			h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, {}), h256::AlignRight);
			*io_gas = static_cast<int64_t>(gas);
			*o_address = address;
		}
		else
			*o_address = {};
	}

	EXPORT bool env_call(ExtVMFace* _env, int64_t* io_gas, int64_t _callGas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
	{
		auto value = llvm2eth(*_value);
		auto receiveAddress = right160(*_receiveAddress);
		auto codeAddress = right160(*_codeAddress);
		const auto isCall = receiveAddress == codeAddress; // OPT: The same address pointer can be used if not CODECALL

		*io_gas -= _callGas;
		if (*io_gas < 0)
			return false;

		if (isCall && !_env->exists(receiveAddress))
			*io_gas -= static_cast<int64_t>(c_callNewAccountGas); // no underflow, *io_gas non-negative before

		if (value > 0) // value transfer
		{
			/*static*/ assert(c_callValueTransferGas > c_callStipend && "Overflow possible");
			*io_gas -= static_cast<int64_t>(c_callValueTransferGas); // no underflow
			_callGas += static_cast<int64_t>(c_callStipend); // overflow possibility, but in the same time *io_gas < 0
		}

		if (*io_gas < 0)
			return false;

		auto ret = false;
		auto callGas = u256{_callGas};
		if (_env->balance(_env->myAddress) >= value && _env->depth < 1024)
			ret = _env->call(receiveAddress, value, {_inBeg, _inSize}, callGas, {_outBeg, _outSize}, {}, {}, codeAddress);

		*io_gas += static_cast<int64_t>(callGas); // it is never more than initial _callGas
		return ret;
	}

	EXPORT void env_sha3(byte* _begin, uint64_t _size, h256* o_hash)
	{
		auto hash = sha3({_begin, _size});
		*o_hash = hash;
	}

	EXPORT byte const* env_extcode(ExtVMFace* _env, h256* _addr256, uint64_t* o_size)
	{
		auto addr = right160(*_addr256);
		auto& code = _env->codeAt(addr);
		*o_size = code.size();
		return code.data();
	}

	EXPORT void env_log(ExtVMFace* _env, byte* _beg, uint64_t _size, h256* _topic1, h256* _topic2, h256* _topic3, h256* _topic4)
	{
		dev::h256s topics;

		if (_topic1)
			topics.push_back(*_topic1);

		if (_topic2)
			topics.push_back(*_topic2);

		if (_topic3)
			topics.push_back(*_topic3);

		if (_topic4)
			topics.push_back(*_topic4);

		_env->log(std::move(topics), {_beg, _size});
	}
}

<|endoftext|>


<commit_before>
#include "Runtime.h"

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IntrinsicInst.h>

#include <libevm/VM.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

llvm::StructType* RuntimeData::getType()
{
	static llvm::StructType* type = nullptr;
	if (!type)
	{
		llvm::Type* elems[] =
		{
			llvm::ArrayType::get(Type::Word, _size),
			Type::BytePtr,
			Type::BytePtr,
			Type::BytePtr
		};
		type = llvm::StructType::create(elems, "Runtime");
	}
	return type;
}

namespace
{
llvm::Twine getName(RuntimeData::Index _index)
{
	switch (_index)
	{
	default:						return "data";
	case RuntimeData::Gas:			return "gas";
	case RuntimeData::Address:		return "address";
	case RuntimeData::Caller:		return "caller";
	case RuntimeData::Origin:		return "origin";
	case RuntimeData::CallValue:	return "callvalue";
	case RuntimeData::CallDataSize:	return "calldatasize";
	case RuntimeData::GasPrice:		return "gasprice";
	case RuntimeData::PrevHash:		return "prevhash";
	case RuntimeData::CoinBase:		return "coinbase";
	case RuntimeData::TimeStamp:	return "timestamp";
	case RuntimeData::Number:		return "number";
	case RuntimeData::Difficulty:	return "difficulty";
	case RuntimeData::GasLimit:		return "gaslimit";
	case RuntimeData::CodeSize:		return "codesize";
	}
}
}

Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf):
	m_ext(_ext)
{
	set(RuntimeData::Gas, _gas);
	set(RuntimeData::Address, fromAddress(_ext.myAddress));
	set(RuntimeData::Caller, fromAddress(_ext.caller));
	set(RuntimeData::Origin, fromAddress(_ext.origin));
	set(RuntimeData::CallValue, _ext.value);
	set(RuntimeData::CallDataSize, _ext.data.size());
	set(RuntimeData::GasPrice, _ext.gasPrice);
	set(RuntimeData::PrevHash, _ext.previousBlock.hash);
	set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress));
	set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp);
	set(RuntimeData::Number, _ext.currentBlock.number);
	set(RuntimeData::Difficulty, _ext.currentBlock.difficulty);
	set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit);
	set(RuntimeData::CodeSize, _ext.code.size());   // TODO: Use constant
	m_data.callData = _ext.data.data();
	m_data.code = _ext.code.data();
	m_data.jmpBuf = _jmpBuf;
}

void Runtime::set(RuntimeData::Index _index, u256 _value)
{
	m_data.elems[_index] = eth2llvm(_value);
}

u256 Runtime::getGas() const
{
	return llvm2eth(m_data.elems[RuntimeData::Gas]);
}

bytesConstRef Runtime::getReturnData() const
{
	// TODO: Handle large indexes
	auto offset = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset]));
	auto size = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize]));

	assert(offset + size <= m_memory.size());
	// TODO: Handle invalid data access by returning empty ref
	return {m_memory.data() + offset, size};
}

RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
{
	m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt");
	llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()};
	m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp);

	// Export data
	auto mainFunc = getMainFunction();
	llvm::Value* dataPtr = &mainFunc->getArgumentList().back();
	m_builder.CreateStore(dataPtr, m_dataPtr);
}

llvm::Value* RuntimeManager::getRuntimePtr()
{
	if (auto mainFunc = getMainFunction())
		return mainFunc->arg_begin()->getNextNode();    // Runtime is the second parameter of main function
	return m_builder.CreateLoad(m_dataPtr, "rt");
}

llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)
{
	llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)};
	return m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr");
}

llvm::Value* RuntimeManager::get(RuntimeData::Index _index)
{
	return m_builder.CreateLoad(getPtr(_index), getName(_index));
}

void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value)
{
	m_builder.CreateStore(_value, getPtr(_index));
}

void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size)
{
	set(RuntimeData::ReturnDataOffset, _offset);
	set(RuntimeData::ReturnDataSize, _size);
}

void RuntimeManager::raiseException(ReturnCode _returnCode)
{
	m_builder.CreateCall2(m_longjmp, getJmpBuf(), Constant::get(_returnCode));
}

llvm::Value* RuntimeManager::get(Instruction _inst)
{
	switch (_inst)
	{
	default: assert(false); return nullptr;
	case Instruction::GAS:			return get(RuntimeData::Gas);
	case Instruction::ADDRESS:		return get(RuntimeData::Address);
	case Instruction::CALLER:		return get(RuntimeData::Caller);
	case Instruction::ORIGIN:		return get(RuntimeData::Origin);
	case Instruction::CALLVALUE:	return get(RuntimeData::CallValue);
	case Instruction::CALLDATASIZE:	return get(RuntimeData::CallDataSize);
	case Instruction::GASPRICE:		return get(RuntimeData::GasPrice);
	case Instruction::PREVHASH:		return get(RuntimeData::PrevHash);
	case Instruction::COINBASE:		return get(RuntimeData::CoinBase);
	case Instruction::TIMESTAMP:	return get(RuntimeData::TimeStamp);
	case Instruction::NUMBER:		return get(RuntimeData::Number);
	case Instruction::DIFFICULTY:	return get(RuntimeData::Difficulty);
	case Instruction::GASLIMIT:		return get(RuntimeData::GasLimit);
	case Instruction::CODESIZE:		return get(RuntimeData::CodeSize);
	}
}

llvm::Value* RuntimeManager::getCallData()
{
	auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 1, "calldataPtr");
	return getBuilder().CreateLoad(ptr, "calldata");
}

llvm::Value* RuntimeManager::getCode()
{
	auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 2, "codePtr");
	return getBuilder().CreateLoad(ptr, "code");
}

llvm::Value* RuntimeManager::getJmpBuf()
{
	auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 3, "jmpbufPtr");
	return getBuilder().CreateLoad(ptr, "jmpbuf");
}

llvm::Value* RuntimeManager::getGas()
{
	return get(RuntimeData::Gas);
}

void RuntimeManager::setGas(llvm::Value* _gas)
{
	llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(RuntimeData::Gas)};
	auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "gasPtr");
	m_builder.CreateStore(_gas, ptr);
}

}
}
}
<commit_msg>unused var removed<commit_after>
#include "Runtime.h"

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IntrinsicInst.h>

#include <libevm/VM.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

llvm::StructType* RuntimeData::getType()
{
	static llvm::StructType* type = nullptr;
	if (!type)
	{
		llvm::Type* elems[] =
		{
			llvm::ArrayType::get(Type::Word, _size),
			Type::BytePtr,
			Type::BytePtr,
			Type::BytePtr
		};
		type = llvm::StructType::create(elems, "Runtime");
	}
	return type;
}

namespace
{
llvm::Twine getName(RuntimeData::Index _index)
{
	switch (_index)
	{
	default:						return "data";
	case RuntimeData::Gas:			return "gas";
	case RuntimeData::Address:		return "address";
	case RuntimeData::Caller:		return "caller";
	case RuntimeData::Origin:		return "origin";
	case RuntimeData::CallValue:	return "callvalue";
	case RuntimeData::CallDataSize:	return "calldatasize";
	case RuntimeData::GasPrice:		return "gasprice";
	case RuntimeData::PrevHash:		return "prevhash";
	case RuntimeData::CoinBase:		return "coinbase";
	case RuntimeData::TimeStamp:	return "timestamp";
	case RuntimeData::Number:		return "number";
	case RuntimeData::Difficulty:	return "difficulty";
	case RuntimeData::GasLimit:		return "gaslimit";
	case RuntimeData::CodeSize:		return "codesize";
	}
}
}

Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf):
	m_ext(_ext)
{
	set(RuntimeData::Gas, _gas);
	set(RuntimeData::Address, fromAddress(_ext.myAddress));
	set(RuntimeData::Caller, fromAddress(_ext.caller));
	set(RuntimeData::Origin, fromAddress(_ext.origin));
	set(RuntimeData::CallValue, _ext.value);
	set(RuntimeData::CallDataSize, _ext.data.size());
	set(RuntimeData::GasPrice, _ext.gasPrice);
	set(RuntimeData::PrevHash, _ext.previousBlock.hash);
	set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress));
	set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp);
	set(RuntimeData::Number, _ext.currentBlock.number);
	set(RuntimeData::Difficulty, _ext.currentBlock.difficulty);
	set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit);
	set(RuntimeData::CodeSize, _ext.code.size());   // TODO: Use constant
	m_data.callData = _ext.data.data();
	m_data.code = _ext.code.data();
	m_data.jmpBuf = _jmpBuf;
}

void Runtime::set(RuntimeData::Index _index, u256 _value)
{
	m_data.elems[_index] = eth2llvm(_value);
}

u256 Runtime::getGas() const
{
	return llvm2eth(m_data.elems[RuntimeData::Gas]);
}

bytesConstRef Runtime::getReturnData() const
{
	// TODO: Handle large indexes
	auto offset = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset]));
	auto size = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize]));

	assert(offset + size <= m_memory.size());
	// TODO: Handle invalid data access by returning empty ref
	return {m_memory.data() + offset, size};
}

RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
{
	m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt");
	m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp);

	// Export data
	auto mainFunc = getMainFunction();
	llvm::Value* dataPtr = &mainFunc->getArgumentList().back();
	m_builder.CreateStore(dataPtr, m_dataPtr);
}

llvm::Value* RuntimeManager::getRuntimePtr()
{
	if (auto mainFunc = getMainFunction())
		return mainFunc->arg_begin()->getNextNode();    // Runtime is the second parameter of main function
	return m_builder.CreateLoad(m_dataPtr, "rt");
}

llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)
{
	llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)};
	return m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr");
}

llvm::Value* RuntimeManager::get(RuntimeData::Index _index)
{
	return m_builder.CreateLoad(getPtr(_index), getName(_index));
}

void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value)
{
	m_builder.CreateStore(_value, getPtr(_index));
}

void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size)
{
	set(RuntimeData::ReturnDataOffset, _offset);
	set(RuntimeData::ReturnDataSize, _size);
}

void RuntimeManager::raiseException(ReturnCode _returnCode)
{
	m_builder.CreateCall2(m_longjmp, getJmpBuf(), Constant::get(_returnCode));
}

llvm::Value* RuntimeManager::get(Instruction _inst)
{
	switch (_inst)
	{
	default: assert(false); return nullptr;
	case Instruction::GAS:			return get(RuntimeData::Gas);
	case Instruction::ADDRESS:		return get(RuntimeData::Address);
	case Instruction::CALLER:		return get(RuntimeData::Caller);
	case Instruction::ORIGIN:		return get(RuntimeData::Origin);
	case Instruction::CALLVALUE:	return get(RuntimeData::CallValue);
	case Instruction::CALLDATASIZE:	return get(RuntimeData::CallDataSize);
	case Instruction::GASPRICE:		return get(RuntimeData::GasPrice);
	case Instruction::PREVHASH:		return get(RuntimeData::PrevHash);
	case Instruction::COINBASE:		return get(RuntimeData::CoinBase);
	case Instruction::TIMESTAMP:	return get(RuntimeData::TimeStamp);
	case Instruction::NUMBER:		return get(RuntimeData::Number);
	case Instruction::DIFFICULTY:	return get(RuntimeData::Difficulty);
	case Instruction::GASLIMIT:		return get(RuntimeData::GasLimit);
	case Instruction::CODESIZE:		return get(RuntimeData::CodeSize);
	}
}

llvm::Value* RuntimeManager::getCallData()
{
	auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 1, "calldataPtr");
	return getBuilder().CreateLoad(ptr, "calldata");
}

llvm::Value* RuntimeManager::getCode()
{
	auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 2, "codePtr");
	return getBuilder().CreateLoad(ptr, "code");
}

llvm::Value* RuntimeManager::getJmpBuf()
{
	auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 3, "jmpbufPtr");
	return getBuilder().CreateLoad(ptr, "jmpbuf");
}

llvm::Value* RuntimeManager::getGas()
{
	return get(RuntimeData::Gas);
}

void RuntimeManager::setGas(llvm::Value* _gas)
{
	llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(RuntimeData::Gas)};
	auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "gasPtr");
	m_builder.CreateStore(_gas, ptr);
}

}
}
}
<|endoftext|>


<commit_before>#include "gui/root.h"

#include "render/spriterender.h"

#include "gui/load.h"
#include "gui/skin.h"

Root::Root(const Sizef& size)
    : size_(size)
{
}

Root::~Root()
{
}

bool
Root::Load(
    FileSystem*        fs,
    FontCache*         font,
    const std::string& path,
    TextureCache*      cache)
{
  const bool result = ::Load(this, fs, font, path, cache);
  if(result)
  {
    container_.DoLayout(Rectf::FromWidthHeight(size_));
  }
  return result;
}

void
Root::SetInputMouse(const vec2f& pos, bool down)
{
  state_.mouse      = pos;
  state_.mouse_down = down;
}

void
Root::Step(float dt)
{
  state_.Begin();
  container_.Step(dt);
  state_.End();
}

void
Root::Render(SpriteRenderer* sp) const
{
  container_.Render(sp);

  auto image = state_.hot != nullptr ? hover_image : cursor_image;

  if(image)
  {
    sp->DrawSprite(*image, state_.mouse, DrawData{}.Anchor(vec2f{0, 1}));
  }
}
<commit_msg>fixed anchor removal<commit_after>#include "gui/root.h"

#include "render/spriterender.h"

#include "gui/load.h"
#include "gui/skin.h"

Root::Root(const Sizef& size)
    : size_(size)
{
}

Root::~Root()
{
}

bool
Root::Load(
    FileSystem*        fs,
    FontCache*         font,
    const std::string& path,
    TextureCache*      cache)
{
  const bool result = ::Load(this, fs, font, path, cache);
  if(result)
  {
    container_.DoLayout(Rectf::FromWidthHeight(size_));
  }
  return result;
}

void
Root::SetInputMouse(const vec2f& pos, bool down)
{
  state_.mouse      = pos;
  state_.mouse_down = down;
}

void
Root::Step(float dt)
{
  state_.Begin();
  container_.Step(dt);
  state_.End();
}

void
Root::Render(SpriteRenderer* sp) const
{
  container_.Render(sp);

  auto image = state_.hot != nullptr ? hover_image : cursor_image;

  if(image)
  {
    sp->DrawSprite(
        *image,
        Rectf::FromPositionAnchorWidthAndHeight(
            state_.mouse, vec2f{0, 1}, image->GetWidth(), image->GetHeight()));
  }
}
<|endoftext|>


<commit_before>#include "robobo.h"

int main(int argc, char** argv) {
	std::string workingDir = argv[0];
	workingDir = workingDir.substr(0, workingDir.find_last_of('/'));
	std::string confDir = workingDir;
	std::string confName = "robobo.conf";
	unsigned short debugLevel = 0;
	bool logDump = false;
	if (argc > 1) {
		unsigned int i = 0;
		while (++i < argc) {
			std::string currArg = argv[i];
			if (currArg == "--help" || currArg == "-h" || currArg == "-?") {
				std::cout << "RoBoBo IRC Bot Help" << std::endl;
				std::cout << std::endl;
				std::cout << "Start the bot without any parameters to start it normally." << std::endl;
				std::cout << "--help: Displays this help notice" << std::endl;
				std::cout << "--version: Displays bot version" << std::endl;
				std::cout << "--debug: Starts the bot in debug mode (foreground, sends information to standard output)" << std::endl;
				std::cout << "\tSpecify level 1, 2, or 3 after it for more information" << std::endl;
				std::cout << "--confname: Specifies the name of the configuration file (default: robobo.conf)" << std::endl;
				std::cout << "--confdir: Specifies the directory of the configuration file (default: same as executable)" << std::endl;
				return 0;
			}
			if (currArg == "--version" || currArg == "-v") {
				std::cout << "RoBoBo IRC Bot, version 3.0.0 Development" << std::endl;
				return 0;
			}
			if (currArg == "--debug" || currArg == "-d") {
				i++;
				if (i >= argc)
					debugLevel = 1;
				else {
					std::istringstream specifiedDebug (argv[i]);
					specifiedDebug >> debugLevel;
				}
				continue;
			}
			if (currArg == "--log" || currArg == "-l") {
				logDump = true;
				continue;
			}
			if (currArg == "--confname") {
				i++;
				if (i >= argc)
					std::cerr << "An error occurred parsing command line arguments: --confname was not given a parameter, using default" << std::endl;
				else
					confName = argv[i];
				continue;
			}
			if (currArg == "--confdir") {
				i++;
				if (i >= argc)
					std::cerr << "An error occurred parsing command line arguments: --confdir was not given a parameter, using default" << std::endl;
				else
					confDir = argv[i];
				continue;
			}
			// In the case that we receive an unrecognized command line input, return an error but continue
			std::cerr << "An error occurred parsing command line arguments: unknown argument " << argv[i] << std::endl;
		}
	}
	// We're done parsing command line arguments; it's time to start!
	// The bot instance starts by reading and parsing the configuration file so it knows what to do
	Base botInstance (workingDir, confDir, confName, debugLevel);
	// Initialize message queue thread
	botInstance.startQueueThread();
	// And then we start doing everything
	botInstance.loadModules();
	botInstance.connectServers();
	botInstance.checkModules();
	// If we make it to this point, the bot is shutting down
	botInstance.unloadEverything();
}<commit_msg>I changed my mind slightly about the startup process.<commit_after>#include "robobo.h"

int main(int argc, char** argv) {
	std::string workingDir = argv[0];
	workingDir = workingDir.substr(0, workingDir.find_last_of('/'));
	std::string confDir = workingDir;
	std::string confName = "robobo.conf";
	unsigned short debugLevel = 0;
	bool logDump = false;
	if (argc > 1) {
		unsigned int i = 0;
		while (++i < argc) {
			std::string currArg = argv[i];
			if (currArg == "--help" || currArg == "-h" || currArg == "-?") {
				std::cout << "RoBoBo IRC Bot Help" << std::endl;
				std::cout << std::endl;
				std::cout << "Start the bot without any parameters to start it normally." << std::endl;
				std::cout << "--help: Displays this help notice" << std::endl;
				std::cout << "--version: Displays bot version" << std::endl;
				std::cout << "--debug: Starts the bot in debug mode (foreground, sends information to standard output)" << std::endl;
				std::cout << "\tSpecify level 1, 2, or 3 after it for more information" << std::endl;
				std::cout << "--confname: Specifies the name of the configuration file (default: robobo.conf)" << std::endl;
				std::cout << "--confdir: Specifies the directory of the configuration file (default: same as executable)" << std::endl;
				return 0;
			}
			if (currArg == "--version" || currArg == "-v") {
				std::cout << "RoBoBo IRC Bot, version 3.0.0 Development" << std::endl;
				return 0;
			}
			if (currArg == "--debug" || currArg == "-d") {
				i++;
				if (i >= argc)
					debugLevel = 1;
				else {
					std::istringstream specifiedDebug (argv[i]);
					specifiedDebug >> debugLevel;
				}
				continue;
			}
			if (currArg == "--log" || currArg == "-l") {
				logDump = true;
				continue;
			}
			if (currArg == "--confname") {
				i++;
				if (i >= argc)
					std::cerr << "An error occurred parsing command line arguments: --confname was not given a parameter, using default" << std::endl;
				else
					confName = argv[i];
				continue;
			}
			if (currArg == "--confdir") {
				i++;
				if (i >= argc)
					std::cerr << "An error occurred parsing command line arguments: --confdir was not given a parameter, using default" << std::endl;
				else
					confDir = argv[i];
				continue;
			}
			// In the case that we receive an unrecognized command line input, return an error but continue
			std::cerr << "An error occurred parsing command line arguments: unknown argument " << argv[i] << std::endl;
		}
	}
	// We're done parsing command line arguments; it's time to start!
	Base botInstance (workingDir, confDir, confName, debugLevel);
	botInstance.readConfiguration();
	botInstance.startQueueThread();
	botInstance.loadModules();
	botInstance.connectServers();
	botInstance.checkModules();
	// If checkModules returns, the bot is shutting down, so kill all the things
	botInstance.unloadEverything();
}<|endoftext|>