<commit_before>/*
    Dynamics/Kinematics modeling and simulation library.
    Copyright (C) 1999 by Michael Alexander Ewert

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "csphyzik/articula.h"
#include "csphyzik/world.h"
#include "csphyzik/rigidbod.h"
#include "csphyzik/debug.h"

static ctWorld *gcurrent_world = NULL;

void dydt(real t, const real y[], real dy[] )
{
//	assert_goto( gcurrent_world != NULL, "current world NULL in dydt\n", ASSERTFAIL );

	gcurrent_world->calc_delta_state( t, y, dy );

//ASSERTFAIL:

}

ctWorld::ctWorld()
{
	ctArticulatedBody::set_joint_friction( DEFAULT_JOINT_FRICTION );

	// default
	ode_to_math = new OdeRungaKutta4();

  max_state_size = DEFAULT_INIT_MAX_STATE_SIZE;
  y0 = new real[max_state_size];
  y1 = new real[max_state_size];
  y_save = new real[max_state_size];
  y_save_size = 0;
}

//!me delete _lists and ode
ctWorld::~ctWorld()
{
	if( ode_to_math ) delete ode_to_math;
	//!me lists delete here
  delete [] y0;
  delete [] y1;
  delete [] y_save;
}

void ctWorld::calc_delta_state( real t, const real y[], real dy[] )
{
	// move data from y array into all entities in this world
	reintegrate_state( y );

	// zero out force accumulator and what-not
	init_state();

	// solve forces and torques of bodies in this world
	solve( t );

	// load all delta step data from bodies into ydot
	load_delta_state( dy );

}

// zero out force accumulator and other transient variables
void ctWorld::init_state()
{
ctPhysicalEntity *pe;

	pe = body_list.get_first();
	while( pe ){
		pe->init_state();
		pe = body_list.get_next();
	}

}

void ctWorld::resize_state_vector( long new_size )
{
  delete [] y0;
  delete [] y1;
  delete [] y_save;
  max_state_size = new_size + STATE_RESIZE_EXTRA;
  y0 = new real[max_state_size];
  y1 = new real[max_state_size];
  y_save = new real[max_state_size];
}

// calculate new positions of world objects after time dt
errorcode ctWorld::evolve( real t0, real t1 )
{
long arr_size = 0;
ctPhysicalEntity *pe = body_list.get_first();

	while( pe ){
//		if( pe->uses_ODE() ){
			arr_size +=	pe->get_state_size();
//		}
		pe = body_list.get_next();
	}

	//!me slow.  change to having y0 and y1 as members of world that get resized as needed.
	gcurrent_world = this;

  if( arr_size > max_state_size ){
    resize_state_vector( arr_size );
  }

	load_state( y0 );

  // save this state for posible rewinding
  for( int i = 0; i < arr_size; i++ ){
    y_save[i] = y0[i];
  }
  y_save_size = arr_size;

	if( ode_to_math ){
		ode_to_math->calc_step( y0, y1, arr_size, t0, t1, dydt );
	}else{
		//!me boom!  no ode, so get out.
		return WORLD_ERR_NOODE;
	}

	reintegrate_state( y1 );

	gcurrent_world = NULL;

	return WORLD_NOERR;

}

errorcode ctWorld::rewind()
{
  //!me do a check here to make sure everything is ok.....
  //!me danger of rewinding when an object is deleted during evolve....
  reintegrate_state( y_save );
  return WORLD_NOERR;
}

// find and resolve collisions
void ctWorld::collide()
{

}

// resolve forces on all bodies
void ctWorld::solve( real t )
{
ctPhysicalEntity *pe;
ctForce *frc;

	// solve for forces affecting contents of world.  the order matters

	// first apply all environmental forces of this world to bodies
	frc = enviro_force_list.get_first();
	while( frc ){
		pe = body_list.get_first();
		while( pe ){
			pe->apply_given_F( *frc );
			pe = body_list.get_next();
		}

		frc = enviro_force_list.get_next();
	}

	pe = body_list.get_first();
	while( pe ){
		pe->solve(t);
		pe = body_list.get_next();
	}

}

// state to array
void ctWorld::load_state( real *state_array )
{
ctPhysicalEntity *pe;
long state_size;
	pe = body_list.get_first();
	while( pe ){
		//if( pe->uses_ODE() ){
			state_size = pe->set_state( state_array );
			state_array += state_size;
		//}
		pe = body_list.get_next();
	}

}

// array to state
void ctWorld::reintegrate_state( const real *state_array )
{
ctPhysicalEntity *pe;
long state_size;
	pe = body_list.get_first();
	while( pe ){
		//if( pe->uses_ODE() ){
			state_size = pe->get_state( state_array );
			state_array += state_size;
		//}
		pe = body_list.get_next();
	}

}

void ctWorld::load_delta_state( real *state_array )
{
ctPhysicalEntity *pe;
long state_size;
	pe = body_list.get_first();
	while( pe ){
		//if( pe->uses_ODE() ){
			state_size = pe->set_delta_state( state_array );
			state_array += state_size;
		//}
		pe = body_list.get_next();
	}

}

// add a rigidbody to this world
errorcode ctWorld::add_rigidbody( ctRigidBody *rb )
{
	if( rb ){
		body_list.add_link( rb );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

// add an articulated body to this world.
errorcode ctWorld::add_articulatedbodybase( ctArticulatedBody *ab )
{
	if( ab ){
		body_list.add_link( ab );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

errorcode ctWorld::add_enviro_force( ctForce *f )
{
	if( f ){
		enviro_force_list.add_link( f );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

errorcode ctWorld::delete_articulatedbody( ctArticulatedBody *pbase )
{
	if( pbase ){
		body_list.delete_link( pbase );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}
<commit_msg>added state data member. When state is REWOUND, then all ctPhysicalEntities with flags set as NO_REWIND will not be integrated until no longer in REWOUND state. REWOUND state expires when time passes time when REWOUND was called.<commit_after>/*
    Dynamics/Kinematics modeling and simulation library.
    Copyright (C) 1999 by Michael Alexander Ewert

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "csphyzik/articula.h"
#include "csphyzik/world.h"
#include "csphyzik/rigidbod.h"
#include "csphyzik/debug.h"

static ctWorld *gcurrent_world = NULL;

void dydt(real t, const real y[], real dy[] )
{
//	assert_goto( gcurrent_world != NULL, "current world NULL in dydt\n", ASSERTFAIL );

	gcurrent_world->calc_delta_state( t, y, dy );

//ASSERTFAIL:

}

ctWorld::ctWorld()
{
	ctArticulatedBody::set_joint_friction( DEFAULT_JOINT_FRICTION );

  fsm_state = CTWS_NORMAL;
	// default
	ode_to_math = new OdeRungaKutta4();

  max_state_size = DEFAULT_INIT_MAX_STATE_SIZE;
  y0 = new real[max_state_size];
  y1 = new real[max_state_size];
  y_save = new real[max_state_size];
  y_save_size = 0;
}

//!me delete _lists and ode
ctWorld::~ctWorld()
{
	if( ode_to_math ) delete ode_to_math;
	//!me lists delete here
  delete [] y0;
  delete [] y1;
  delete [] y_save;
}

void ctWorld::calc_delta_state( real t, const real y[], real dy[] )
{
	// move data from y array into all entities in this world
	reintegrate_state( y );

	// zero out force accumulator and what-not
	init_state();

	// solve forces and torques of bodies in this world
	solve( t );

	// load all delta step data from bodies into ydot
	load_delta_state( dy );

}

// zero out force accumulator and other transient variables
void ctWorld::init_state()
{
ctPhysicalEntity *pe;

	pe = body_list.get_first();
	while( pe ){
		pe->init_state();
		pe = body_list.get_next();
	}

}

void ctWorld::resize_state_vector( long new_size )
{
  delete [] y0;
  delete [] y1;
  delete [] y_save;
  max_state_size = new_size + STATE_RESIZE_EXTRA;
  y0 = new real[max_state_size];
  y1 = new real[max_state_size];
  y_save = new real[max_state_size];
}

// calculate new positions of world objects after time dt
errorcode ctWorld::evolve( real t0, real t1 )
{
long arr_size = 0;
ctPhysicalEntity *pe = body_list.get_first();

	while( pe ){
//		if( pe->uses_ODE() ){
			arr_size +=	pe->get_state_size();
//		}
		pe = body_list.get_next();
	}

	gcurrent_world = this;

  if( arr_size > max_state_size ){
    resize_state_vector( arr_size );
  }

	load_state( y0 );

  // save this state for posible rewinding
  for( int i = 0; i < arr_size; i++ ){
    y_save[i] = y0[i];
  }
  y_save_size = arr_size;

	if( ode_to_math ){
		ode_to_math->calc_step( y0, y1, arr_size, t0, t1, dydt );
	}else{
    if( fsm_state == CTWS_REWOUND && t1 >= rewound_from ){
      fsm_state = CTWS_NORMAL;
      rewound_from = 0;
    }
		//!me boom!  no ode, so get out.
		return WORLD_ERR_NOODE;
	}

	reintegrate_state( y1 );

	gcurrent_world = NULL;

  if( fsm_state == CTWS_REWOUND && t1 >= rewound_from ){
    fsm_state = CTWS_NORMAL;
    rewound_from = 0;
  }

	return WORLD_NOERR;

}

errorcode ctWorld::rewind( real t1, real t2 )
{
  fsm_state = CTWS_REWOUND;
  rewound_from = t2;
  reintegrate_state( y_save );
  return WORLD_NOERR;
}

// find and resolve collisions
void ctWorld::collide()
{

}

// resolve forces on all bodies
void ctWorld::solve( real t )
{
ctPhysicalEntity *pe;
ctForce *frc;

	// solve for forces affecting contents of world.  the order matters

	// first apply all environmental forces of this world to bodies
	frc = enviro_force_list.get_first();
	while( frc ){
		pe = body_list.get_first();
		while( pe ){
      if( !(fsm_state == CTWS_REWOUND && (pe->flags & CTF_NOREWIND)) )
			  pe->apply_given_F( *frc );
			pe = body_list.get_next();
		}

		frc = enviro_force_list.get_next();
	}

	pe = body_list.get_first();
	while( pe ){
    if( !(fsm_state == CTWS_REWOUND && (pe->flags & CTF_NOREWIND)) )
		  pe->solve(t);
		pe = body_list.get_next();
	}

}

// state to array
void ctWorld::load_state( real *state_array )
{
ctPhysicalEntity *pe;
long state_size;
	pe = body_list.get_first();
	while( pe ){
    if( fsm_state == CTWS_REWOUND && (pe->flags & CTF_NOREWIND) ){
      state_size = pe->get_state_size();
    }else{
			state_size = pe->set_state( state_array );
    }
	  state_array += state_size;
		pe = body_list.get_next();
	}

}

// array to state
void ctWorld::reintegrate_state( const real *state_array )
{
ctPhysicalEntity *pe;
long state_size;
	pe = body_list.get_first();
	while( pe ){
    if( fsm_state == CTWS_REWOUND && (pe->flags & CTF_NOREWIND) ){
      state_size = pe->get_state_size();
    }else{
			state_size = pe->get_state( state_array );
			state_array += state_size;
		}
		pe = body_list.get_next();
	}

}

void ctWorld::load_delta_state( real *state_array )
{
ctPhysicalEntity *pe;
long state_size;
	pe = body_list.get_first();
	while( pe ){
		if( fsm_state == CTWS_REWOUND && (pe->flags & CTF_NOREWIND) ){
      state_size = pe->get_state_size();
    }else{
			state_size = pe->set_delta_state( state_array );
			state_array += state_size;
		}
		pe = body_list.get_next();
	}

}

// add a physical entity to this world
//!me should consolodate these three methods, they do the same thing.
errorcode ctWorld::add_physicalentity( ctPhysicalEntity *pe )
{
	if( pe ){
		body_list.add_link( pe );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

// add a rigidbody to this world
errorcode ctWorld::add_rigidbody( ctRigidBody *rb )
{
	if( rb ){
		body_list.add_link( rb );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

// add an articulated body to this world.
errorcode ctWorld::add_articulatedbodybase( ctArticulatedBody *ab )
{
	if( ab ){
		body_list.add_link( ab );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

errorcode ctWorld::add_enviro_force( ctForce *f )
{
	if( f ){
		enviro_force_list.add_link( f );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

errorcode ctWorld::delete_articulatedbody( ctArticulatedBody *pbase )
{
	if( pbase ){
		body_list.delete_link( pbase );
		return WORLD_NOERR;
	}else{
		return WORLD_ERR_NULLPARAMETER;
	}
}

// apply the given function to all physical entities in the system.
void ctWorld::apply_fuction_to_body_list( void(*fcn)( ctPhysicalEntity *ppe ) )
{
ctPhysicalEntity *pe;

	pe = body_list.get_first();
	while( pe ){
		fcn( pe );
		pe = body_list.get_next();
	}

}<|endoftext|>


<commit_before>/*
    Dynamics/Kinematics modeling and simulation library.
    Copyright (C) 1999 by Michael Alexander Ewert and Noah Gibbs

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "csphyzik/ctvector.h"
#include "csphyzik/ctmatrix.h"
#include "csphyzik/qtrigid.h"
#include "csphyzik/ctquat.h"

ctQuatRigidBody::ctQuatRigidBody(ctVector3 x, real M) {
  mass = M;
  pos = x;
  mom[0] = mom[1] = mom[2] = 0.0;
  quat.r = 1.0; quat.x = quat.y = quat.z = 0.0;
  ang[0] = ang[1] = ang[2] = 0.0;

  F[0] = F[1] = F[2] = 0.0;
  T[0] = T[1] = T[2] = 0.0;

  precalculated = false;
}

int ctQuatRigidBody::get_state(real *sa) {
  pos[0] = sa[0];
  pos[1] = sa[1];
  pos[2] = sa[2];
  mom[0] = sa[3];
  mom[1] = sa[4];
  mom[2] = sa[5];
  quat.r = sa[6];
  quat.x = sa[7];
  quat.y = sa[8];
  quat.z = sa[9];
  ang[0] = sa[10];
  ang[1] = sa[11];
  ang[2] = sa[12];

  return get_state_size();
}

int ctQuatRigidBody::set_state(real *sa) {
  sa[0]  = pos[0];
  sa[1]  = pos[1];
  sa[2]  = pos[2];
  sa[3]  = mom[0];
  sa[4]  = mom[1];
  sa[5]  = mom[2];
  sa[6]  = quat.r;
  sa[7]  = quat.x;
  sa[8]  = quat.y;
  sa[9]  = quat.z;
  sa[10] = ang[0];
  sa[11] = ang[1];
  sa[12] = ang[2];

  Precalculate();

  return get_state_size();
}

void ctQuatRigidBody::Precalculate() {
  if(precalculated) return;
  quat.Normalize();
  R = quat.to_matrix();
  Iinv = R * Ibodyinv * R.get_transpose();
  omega = Iinv * ang;
  precalculated = true;
}
<commit_msg>Added the vital set_delta_state function, which I hadn't finished...<commit_after>/*
    Dynamics/Kinematics modeling and simulation library.
    Copyright (C) 1999 by Michael Alexander Ewert and Noah Gibbs

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "csphyzik/ctvector.h"
#include "csphyzik/ctmatrix.h"
#include "csphyzik/qtrigid.h"
#include "csphyzik/ctquat.h"

ctQuatRigidBody::ctQuatRigidBody(ctVector3 x, real M) {
  mass = M;
  pos = x;
  mom[0] = mom[1] = mom[2] = 0.0;
  quat.r = 1.0; quat.x = quat.y = quat.z = 0.0;
  ang[0] = ang[1] = ang[2] = 0.0;

  F[0] = F[1] = F[2] = 0.0;
  T[0] = T[1] = T[2] = 0.0;

  precalculated = false;
}

int ctQuatRigidBody::get_state(real *sa) {
  pos[0] = sa[0];
  pos[1] = sa[1];
  pos[2] = sa[2];
  mom[0] = sa[3];
  mom[1] = sa[4];
  mom[2] = sa[5];
  quat.r = sa[6];
  quat.x = sa[7];
  quat.y = sa[8];
  quat.z = sa[9];
  ang[0] = sa[10];
  ang[1] = sa[11];
  ang[2] = sa[12];

  return get_state_size();
}

int ctQuatRigidBody::set_state(real *sa) {
  sa[0]  = pos[0];
  sa[1]  = pos[1];
  sa[2]  = pos[2];
  sa[3]  = mom[0];
  sa[4]  = mom[1];
  sa[5]  = mom[2];
  sa[6]  = quat.r;
  sa[7]  = quat.x;
  sa[8]  = quat.y;
  sa[9]  = quat.z;
  sa[10] = ang[0];
  sa[11] = ang[1];
  sa[12] = ang[2];

  Precalculate();

  return get_state_size();
}

int ctQuatRigidBody::set_delta_state(real *sa) {
  Precalculate();  // just in case

  sa[0] = mom[0] / mass;
  sa[1] = mom[1] / mass;
  sa[2] = mom[2] / mass;
  sa[3] = F[0] / mass;
  sa[4] = F[1] / mass;
  sa[5] = F[2] / mass;

  ctQuaternion qdot(get_omega());
  qdot *= quat;
  qdot.r *= 0.5;
  sa[6] = qdot.r;
  sa[7] = qdot.x;
  sa[8] = qdot.y;
  sa[9] = qdot.z;

  sa[10] = T[0];
  sa[11] = T[1];
  sa[12] = T[2];
  return get_state_size();
}

void ctQuatRigidBody::Precalculate() {
  if(precalculated) return;
  quat.Normalize();
  R = quat.to_matrix();
  Iinv = R * Ibodyinv * R.get_transpose();
  omega = Iinv * ang;
  precalculated = true;
}
<|endoftext|>


<commit_before>#pragma once
#include "util.cpp"

/*
struct Cluster {
	int rx, cy, id;
	vector<pair<int, int>> cells;
};

struct Balloon {
	int id, cluster_id;
	vector<int> r, c, h;
};

struct Input {
	int r, c, a, l, v, b, t, rs, cs;
	vector<Cluster> clusters;
	vector<Ballon> balloon;
	vector<int> cell_x;
	vector<int> cell_y;
	vector<vector<vector<int>>> movement_x;
	vector<vector<vector<int>>> movement_y;
};

struct Coord {
	int r, c, h;
};

void bfs(Input &input, vector<Coord> path)	{

	while (!q.empty())	{
		Coord cur = q.front();
		path.insert()
		if (cur.r >= input.r || cur.r < 0)	{
			cur.r =
		}
	}
}*/

void pathfinding(Input& input, int balloon, int r, int c, int delta) {
	//TODO fill me
	//queue<Coord> q;
	//Coord start;
	int rr = input.balloons[balloon].r.back();
	int cc = input.balloons[balloon].c.back();
	//int hh = input.balloons[balloon].h.back();

	//q.push(start);

	input.balloons[balloon].h.push_back(1);

	input.balloons[balloon].r.push_back(r+input.movement_r[rr][cc][1]);
	input.balloons[balloon].c.push_back(c+input.movement_c[rr][cc][1]);
	//bfs(input,q);
}
<commit_msg>pathfinding implemented not tested<commit_after>#pragma once
#include "util.cpp"
#include <set>

struct Coord {
	int r, c, h;
};

bool operator < (const Coord &a, const Coord &b)	{
	if (a.r != b.r)
		return a.r < b.r;
	return a.c < b.c;
}

void check_cell(Input &input, Coord cur, vector<Coord>& path, vector<int>& prev, set<Coord>& visited, vector<int>& dist, int idx)	{

	cur.r += input.movement_r[cur.r][cur.c][cur.h];
	cur.c += input.movement_r[cur.r][cur.c][cur.h];

	if (visited.find(cur) != visited.end())
		return;

	path.push_back(cur);
	prev.push_back(idx);
	dist.push_back(dist[idx]+1);
	visited.insert(cur);
}

void bfs(Input &input, vector<Coord>& path, vector<int>& prev)	{

	set<Coord> visited;
	vector<int> dist;
	int idx = 0;
	dist.push_back(idx);
	visited.insert(path[idx]);

	while (idx < path.size())	{
		Coord cur = path[idx];

		if (dist[idx] > 5)
			break;

		cur.c = (cur.c + input.c) % input.c;

		// out of bounds -> stay there
		if (cur.r >= input.r || cur.r < 0)	{
			path.push_back(cur);
			prev.push_back(idx);
			dist.push_back(dist[idx]+1);
		}

		// try changing the altitude
		else	{
			check_cell(input,cur,path,prev,visited,dist,idx);

			if (cur.h > 1)
			{
				cur.h--;
				check_cell(input,cur,path,prev,visited,dist,idx);
				cur.h++;
			}

			if (cur.h < input.a)
			{
				cur.h++;
				check_cell(input,cur,path,prev,visited,dist,idx);
				cur.h--;
			}
		}
	}
}

void pathfinding(Input& input, int balloon, int r, int c, int delta) {
	//TODO fill me
	vector<Coord> path;
	vector<int> prev;

	// add starting cell
	Coord start;
	start.r = input.balloons[balloon].r.back();
	start.c = input.balloons[balloon].c.back();
	start.h = input.balloons[balloon].h.back();

	path.push_back(start);
	prev.push_back(-1);

	//run bfs
	bfs(input,path,prev);

	// choose the closest end point
	Coord end;
	double mind = 1e9, curd;
	int idx_min;
	for (int i = 0; i < path.size(); i++)
	{
		curd = ((double)path[i].r-r)*((double)path[i].r-r) + ((double)path[i].c-c)*((double)path[i].c-c);
		if (curd < mind)
		{
			idx_min = i;
			mind = curd;
		}
	}

	// build reversed path to the closest cell
	vector<Coord> reversed_path;
	for (int i = idx_min; i != 0; i = prev[i])
		reversed_path.push_back(path[i]);

	for (int i = reversed_path.size()-1; i >= 0; i--)
	{
		input.balloons[balloon].h.push_back(reversed_path[i].h);
		input.balloons[balloon].r.push_back(reversed_path[i].r);
		input.balloons[balloon].c.push_back(reversed_path[i].c);

		if (input.balloons[balloon].h.size() > input.t)
			break;
	}
}
<|endoftext|>


<commit_before>#pragma once
#include "util.cpp"
#include <set>
#include <cmath>

struct Coord {
	int r, c, h;
};

bool operator < (const Coord &a, const Coord &b)	{
	if (a.r != b.r)
		return a.r < b.r;
	else if (a.c != b.c)
		return a.c < b.c;
	else
		return a.h < b.h;
}

double compute_distance(double r1, double c1, double r2, double c2, double c)	{
	double dr = abs(r1-r2);
	double dc = min(abs(c1-c2),c-abs(c1-c2));
	return sqrt(dr*dr+dc*dc);
}

void check_cell(Input &input, Coord cur, vector<Coord>& path, vector<int>& prev, set<Coord>& visited, vector<int>& dist, int idx)	{

	//cerr << "adding balloon: " << cur.r << ' ' << cur.c << ' ' << cur.h << endl;

	int dr = input.movement_r[cur.r][cur.c][cur.h];
	int dc = input.movement_c[cur.r][cur.c][cur.h];
	cur.r += dr;
	cur.c += dc;
	cur.c = (cur.c + input.c) % input.c;

	//cerr << "done\n";

	if (visited.find(cur) != visited.end())
		return;
	path.push_back(cur);
	prev.push_back(idx);
	dist.push_back(dist[idx]+1);
	visited.insert(cur);
}

void bfs(Input &input, vector<Coord>& path, vector<int>& prev)	{

	set<Coord> visited;
	vector<int> dist;
	int idx = 0;
	dist.push_back(idx);
	visited.insert(path[idx]);

	while (idx < path.size())	{
		Coord cur = path[idx];

		//cerr << "current balloon: " << cur.r << ' ' << cur.c << ' ' << cur.h << endl;

		if (dist[idx] > 5)
			break;

		// out of bounds -> stay there
		if (cur.r >= input.r || cur.r < 0)	{
			path.push_back(cur);
			prev.push_back(idx);
			dist.push_back(dist[idx]+1);
		}

		// try changing the altitude
		else	{
			check_cell(input,cur,path,prev,visited,dist,idx);

			if (cur.h > 1)
			{
				cur.h--;
				check_cell(input,cur,path,prev,visited,dist,idx);
				cur.h++;
			}

			if (cur.h < input.a)
			{
				cur.h++;
				check_cell(input,cur,path,prev,visited,dist,idx);
				cur.h--;
			}
		}
		idx++;
	}
}

void pathfinding(Input& input, int balloon, double r, double c, double delta) {
	//TODO fill me
	//run bfs
	while (input.balloons[balloon].h.size() <= input.t &&
		compute_distance(input.balloons[balloon].r.back(),input.balloons[balloon].c.back(),r,c,input.c) > delta)
	{
		vector<Coord> path; path.clear();
		vector<int> prev; prev.clear();
		// add starting cell
		Coord start;

		start.r = input.balloons[balloon].r.back();
		start.c = input.balloons[balloon].c.back();
		start.h = input.balloons[balloon].h.back();

		path.push_back(start);
		prev.push_back(-1);

		bfs(input,path,prev);

		// choose the closest end point
		double mind = 1e9, curd;
		int idx_min = 0;
		for (int i = 1; i < path.size(); i++)
		{
			curd = compute_distance(path[i].r,path[i].c,r,c,input.c);
			if (curd < mind || (idx_min == 0 && input.balloons[balloon].h.size() == 1))
			{
				idx_min = i;
				mind = curd;
			}
		}

		//cerr << path.size() << endl;
		vector<Coord> reversed_path;
		for (int i = idx_min; i != 0; i = prev[i])
			reversed_path.push_back(path[i]);

		/*
		cerr << "flying from: " << start.r << ' ' << start.c << ' ' << start.h << endl;
		cerr << "to target: " << r << ' ' << c << endl;
		cerr << "path\n";
		for (int i = reversed_path.size()-1; i >= 0; i--)
			cerr << reversed_path[i].r << ' ' << reversed_path[i].c << ' ' << reversed_path[i].h << endl;
		cerr << "end of path\n";//*/

		for (int i = reversed_path.size()-1; i >= 0; i--)
		{
			input.balloons[balloon].h.push_back(reversed_path[i].h);
			input.balloons[balloon].r.push_back(reversed_path[i].r);
			input.balloons[balloon].c.push_back(reversed_path[i].c);

			if (input.balloons[balloon].h.size() > input.t)
				break;
		}

		//double endr = input.balloons[balloon].r.back();
		//double endc = input.balloons[balloon].c.back();
		//dist_to_dest = compute_distance(endr,endc,r,c);
	}

	for (int i = 0; i < input.balloons[balloon].r.size()-1; i++)
	{
		int rc = input.balloons[balloon].r[i];
		int rn = input.balloons[balloon].r[i+1];

		int cc = input.balloons[balloon].c[i];
		int cn = input.balloons[balloon].c[i+1];

		if (abs(cc-cn) > input.c - abs(cc-cn))
			cerr << rc << ' ' << cc << ' ' << 0 << ' ' << 0 << ' ' << input.balloons[balloon].cluster_id / ((double)input.clusters.size()) << endl;

		else
			cerr << rc << ' ' << cc << ' ' << rn-rc << ' ' << cn-cc << ' ' << input.balloons[balloon].cluster_id / ((double)input.clusters.size()) << endl;
	}
	cerr << endl;
}
<commit_msg>pathfinding with visualization<commit_after>#pragma once
#include "util.cpp"
#include <set>
#include <cmath>

struct Coord {
	int r, c, h;
};

bool operator < (const Coord &a, const Coord &b)	{
	if (a.r != b.r)
		return a.r < b.r;
	else if (a.c != b.c)
		return a.c < b.c;
	else
		return a.h < b.h;
}

double compute_distance(double r1, double c1, double r2, double c2, double c)	{
	double dr = abs(r1-r2);
	double dc = min(abs(c1-c2),c-abs(c1-c2));
	return sqrt(dr*dr+dc*dc);
}

void check_cell(Input &input, Coord cur, vector<Coord>& path, vector<int>& prev, set<Coord>& visited, vector<int>& dist, int idx)	{

	//cerr << "adding balloon: " << cur.r << ' ' << cur.c << ' ' << cur.h << endl;

	int dr = input.movement_r[cur.r][cur.c][cur.h];
	int dc = input.movement_c[cur.r][cur.c][cur.h];
	cur.r += dr;
	cur.c += dc;
	cur.c = (cur.c + input.c) % input.c;

	//cerr << "done\n";

	if (visited.find(cur) != visited.end())
		return;
	path.push_back(cur);
	prev.push_back(idx);
	dist.push_back(dist[idx]+1);
	visited.insert(cur);
}

void bfs(Input &input, vector<Coord>& path, vector<int>& prev)	{

	set<Coord> visited;
	vector<int> dist;
	int idx = 0;
	dist.push_back(idx);
	visited.insert(path[idx]);

	while (idx < path.size())	{
		Coord cur = path[idx];

		//cerr << "current balloon: " << cur.r << ' ' << cur.c << ' ' << cur.h << endl;

		if (dist[idx] > 5)
			break;

		// out of bounds -> stay there
		if (cur.r >= input.r || cur.r < 0)	{
			path.push_back(cur);
			prev.push_back(idx);
			dist.push_back(dist[idx]+1);
		}

		// try changing the altitude
		else	{
			check_cell(input,cur,path,prev,visited,dist,idx);

			if (cur.h > 1)
			{
				cur.h--;
				check_cell(input,cur,path,prev,visited,dist,idx);
				cur.h++;
			}

			if (cur.h < input.a)
			{
				cur.h++;
				check_cell(input,cur,path,prev,visited,dist,idx);
				cur.h--;
			}
		}
		idx++;
	}
}

void pathfinding(Input& input, int balloon, double r, double c, double delta) {
	//TODO fill me
	//run bfs
	while (input.balloons[balloon].h.size() <= input.t &&
		compute_distance(input.balloons[balloon].r.back(),input.balloons[balloon].c.back(),r,c,input.c) > delta)
	{
		vector<Coord> path; path.clear();
		vector<int> prev; prev.clear();
		// add starting cell
		Coord start;

		start.r = input.balloons[balloon].r.back();
		start.c = input.balloons[balloon].c.back();
		start.h = input.balloons[balloon].h.back();

		path.push_back(start);
		prev.push_back(-1);

		bfs(input,path,prev);

		// choose the closest end point
		double mind = 1e9, curd;
		int idx_min = 0;
		for (int i = 1; i < path.size(); i++)
		{
			curd = compute_distance(path[i].r,path[i].c,r,c,input.c);
			if (curd < mind || (idx_min == 0 && input.balloons[balloon].h.size() == 1))
			{
				idx_min = i;
				mind = curd;
			}
		}

		//cerr << path.size() << endl;
		vector<Coord> reversed_path;
		for (int i = idx_min; i != 0; i = prev[i])
			reversed_path.push_back(path[i]);

		/*
		cerr << "flying from: " << start.r << ' ' << start.c << ' ' << start.h << endl;
		cerr << "to target: " << r << ' ' << c << endl;
		cerr << "path\n";
		for (int i = reversed_path.size()-1; i >= 0; i--)
			cerr << reversed_path[i].r << ' ' << reversed_path[i].c << ' ' << reversed_path[i].h << endl;
		cerr << "end of path\n";//*/

		for (int i = reversed_path.size()-1; i >= 0; i--)
		{
			input.balloons[balloon].h.push_back(reversed_path[i].h);
			input.balloons[balloon].r.push_back(reversed_path[i].r);
			input.balloons[balloon].c.push_back(reversed_path[i].c);

			if (input.balloons[balloon].h.size() > input.t)
				break;
		}

		//double endr = input.balloons[balloon].r.back();
		//double endc = input.balloons[balloon].c.back();
		//dist_to_dest = compute_distance(endr,endc,r,c);
	}

	/*for (int i = 0; i < input.balloons[balloon].r.size()-1; i++)
	{
		int rc = input.balloons[balloon].r[i];
		int rn = input.balloons[balloon].r[i+1];

		int cc = input.balloons[balloon].c[i];
		int cn = input.balloons[balloon].c[i+1];

		if (abs(cc-cn) > input.c - abs(cc-cn))
			cerr << rc << ' ' << cc << ' ' << 0 << ' ' << 0 << ' ' << input.balloons[balloon].cluster_id / ((double)input.clusters.size()) << endl;

		else
			cerr << rc << ' ' << cc << ' ' << rn-rc << ' ' << cn-cc << ' ' << input.balloons[balloon].cluster_id / ((double)input.clusters.size()) << endl;
	}
	cerr << endl;*/
}
<|endoftext|>


<commit_before>#include <renderer.h>
#include <rasterizer.h>
#include <s1516.h>

#include <stdio.h>

#define FLYTHROUGH_CAMERA_IMPLEMENTATION
#include <flythrough_camera.h>

#include <Windows.h>
#include <DirectXMath.h>
#include <GL/gl.h>

#include <imgui.h>
#include <imgui_impl_win32_gl.h>

#pragma comment(lib, "OpenGL32.lib")

LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (ImGui_ImplWin32GL_WndProcHandler(hWnd, message, wParam, lParam))
        return true;

    switch (message)
    {
    case WM_CLOSE:
        ExitProcess(0);
        return 0;
    case WM_SYSCOMMAND:
        if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
            return 0;
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

HDC g_hDC;

void init_window(int32_t width, int32_t height)
{
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.cbSize = sizeof(wc);
    wc.style = CS_OWNDC;
    wc.lpfnWndProc = MyWndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    wc.lpszClassName = TEXT("WindowClass");
    RegisterClassEx(&wc);

    RECT wr = { 0, 0, width, height };
    AdjustWindowRect(&wr, 0, FALSE);
    HWND hWnd = CreateWindowEx(
        0, TEXT("WindowClass"),
        TEXT("BasicGL"),
        WS_OVERLAPPEDWINDOW,
        0, 0, wr.right - wr.left, wr.bottom - wr.top,
        0, 0, GetModuleHandle(NULL), 0);

    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    g_hDC = GetDC(hWnd);

    int chosenPixelFormat = ChoosePixelFormat(g_hDC, &pfd);
    SetPixelFormat(g_hDC, chosenPixelFormat, &pfd);

    HGLRC hGLRC = wglCreateContext(g_hDC);
    wglMakeCurrent(g_hDC, hGLRC);

    ShowWindow(hWnd, SW_SHOWNORMAL);

    ImGui_ImplWin32GL_Init(hWnd);
}

int main()
{
    int fbwidth = 1024;
    int fbheight = 768;

    SetProcessDPIAware();
    init_window(fbwidth, fbheight);

    renderer_t* rd = new_renderer(fbwidth, fbheight);

    scene_t* sc = new_scene();
    uint32_t first_model_id, num_added_models;
    scene_add_models(sc, "assets/cube/cube.obj", "assets/cube/", &first_model_id, &num_added_models);
    for (uint32_t model_id = first_model_id; model_id < first_model_id + num_added_models; model_id++)
    {
        uint32_t instance_id;
        scene_add_instance(sc, model_id, &instance_id);
    }

    // compute projection matrix with DirectXMath because lazy
    {
        DirectX::XMMATRIX proj = DirectX::XMMatrixPerspectiveFovLH(DirectX::XMConvertToRadians(70.0f), (float)fbwidth / fbheight, 0.01f, 10.0f);
        DirectX::XMFLOAT4X4 proj4x4;
        DirectX::XMStoreFloat4x4(&proj4x4, proj);

        int32_t fx_proj[16];
        for (int32_t i = 0; i < 16; i++)
        {
            fx_proj[i] = s1516_flt(*((float*)proj4x4.m + i));
        }
        scene_set_projection(sc, fx_proj);
    }

    float eye[3] = { 0.0f, 0.0f, 3.0f };
    float look[3] = { 0.0f, 0.0f, -1.0f };
    const float up[3] = { 0.0f, 1.0f, 0.0f };

    LARGE_INTEGER then, now, freq;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&then);

    POINT oldcursor;
    GetCursorPos(&oldcursor);

    uint8_t* rgba8_pixels = (uint8_t*)malloc(fbwidth * fbheight * 4);
    assert(rgba8_pixels);

    // readback framebuffer contents
    framebuffer_t* fb = renderer_get_framebuffer(rd);

    while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000))
    {
        MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        ImGui_ImplWin32GL_NewFrame();

        ImGui::ShowTestWindow();

        QueryPerformanceCounter(&now);
        float delta_time_sec = (float)(now.QuadPart - then.QuadPart) / freq.QuadPart;

        POINT cursor;
        GetCursorPos(&cursor);

        // only move and rotate camera when right mouse button is pressed
        float activated = (GetAsyncKeyState(VK_RBUTTON) & 0x8000) ? 1.0f : 0.0f;

        float view[16];
        flythrough_camera_update(
            eye, look, up, view,
            delta_time_sec,
            10.0f * ((GetAsyncKeyState(VK_LSHIFT) & 0x8000) ? 2.0f : 1.0f) * activated,
            0.5f * activated,
            80.0f,
            cursor.x - oldcursor.x, cursor.y - oldcursor.y,
            GetAsyncKeyState('W') & 0x8000, GetAsyncKeyState('A') & 0x8000, GetAsyncKeyState('S') & 0x8000, GetAsyncKeyState('D') & 0x8000,
            GetAsyncKeyState(VK_SPACE) & 0x8000, GetAsyncKeyState(VK_LCONTROL) & 0x8000,
            FLYTHROUGH_CAMERA_LEFT_HANDED_BIT);

        int32_t view_s1516[16];
        for (int32_t i = 0; i < 16; i++)
        {
            view_s1516[i] = s1516_flt(view[i]);
        }
        scene_set_view(sc, view_s1516);

        renderer_render_scene(rd, sc);

        framebuffer_t* fb = renderer_get_framebuffer(rd);
        framebuffer_pack_row_major(fb, 0, 0, fbwidth, fbheight, pixelformat_r8g8b8a8_unorm, rgba8_pixels);
        // flip the rows to appease the OpenGL gods
        for (int32_t row = 0; row < fbheight / 2; row++)
        {
            for (int32_t col = 0; col < fbwidth; col++)
            {
                uint32_t tmp = *(uint32_t*)&rgba8_pixels[(row * fbwidth + col) * 4];
                *(uint32_t*)&rgba8_pixels[(row * fbwidth + col) * 4] = *(uint32_t*)&rgba8_pixels[((fbheight - row - 1) * fbwidth + col) * 4];
                *(uint32_t*)&rgba8_pixels[((fbheight - row - 1) * fbwidth + col) * 4] = tmp;
            }
        }
        glDrawPixels(fbwidth, fbheight, GL_RGBA, GL_UNSIGNED_BYTE, rgba8_pixels);

        ImGui::Render();

        SwapBuffers(g_hDC);

        then = now;
        oldcursor = cursor;
    }

    free(rgba8_pixels);

    delete_scene(sc);
    delete_renderer(rd);

    return 0;
}<commit_msg>switch window title<commit_after>#include <renderer.h>
#include <rasterizer.h>
#include <s1516.h>

#include <stdio.h>

#define FLYTHROUGH_CAMERA_IMPLEMENTATION
#include <flythrough_camera.h>

#include <Windows.h>
#include <DirectXMath.h>
#include <GL/gl.h>

#include <imgui.h>
#include <imgui_impl_win32_gl.h>

#pragma comment(lib, "OpenGL32.lib")

LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (ImGui_ImplWin32GL_WndProcHandler(hWnd, message, wParam, lParam))
        return true;

    switch (message)
    {
    case WM_CLOSE:
        ExitProcess(0);
        return 0;
    case WM_SYSCOMMAND:
        if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
            return 0;
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

HDC g_hDC;

void init_window(int32_t width, int32_t height)
{
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.cbSize = sizeof(wc);
    wc.style = CS_OWNDC;
    wc.lpfnWndProc = MyWndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    wc.lpszClassName = TEXT("WindowClass");
    RegisterClassEx(&wc);

    RECT wr = { 0, 0, width, height };
    AdjustWindowRect(&wr, 0, FALSE);
    HWND hWnd = CreateWindowEx(
        0, TEXT("WindowClass"),
        TEXT("viewer"),
        WS_OVERLAPPEDWINDOW,
        0, 0, wr.right - wr.left, wr.bottom - wr.top,
        0, 0, GetModuleHandle(NULL), 0);

    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    g_hDC = GetDC(hWnd);

    int chosenPixelFormat = ChoosePixelFormat(g_hDC, &pfd);
    SetPixelFormat(g_hDC, chosenPixelFormat, &pfd);

    HGLRC hGLRC = wglCreateContext(g_hDC);
    wglMakeCurrent(g_hDC, hGLRC);

    ShowWindow(hWnd, SW_SHOWNORMAL);

    ImGui_ImplWin32GL_Init(hWnd);
}

int main()
{
    int fbwidth = 1024;
    int fbheight = 768;

    SetProcessDPIAware();
    init_window(fbwidth, fbheight);

    renderer_t* rd = new_renderer(fbwidth, fbheight);

    scene_t* sc = new_scene();
    uint32_t first_model_id, num_added_models;
    scene_add_models(sc, "assets/cube/cube.obj", "assets/cube/", &first_model_id, &num_added_models);
    for (uint32_t model_id = first_model_id; model_id < first_model_id + num_added_models; model_id++)
    {
        uint32_t instance_id;
        scene_add_instance(sc, model_id, &instance_id);
    }

    // compute projection matrix with DirectXMath because lazy
    {
        DirectX::XMMATRIX proj = DirectX::XMMatrixPerspectiveFovLH(DirectX::XMConvertToRadians(70.0f), (float)fbwidth / fbheight, 0.01f, 10.0f);
        DirectX::XMFLOAT4X4 proj4x4;
        DirectX::XMStoreFloat4x4(&proj4x4, proj);

        int32_t fx_proj[16];
        for (int32_t i = 0; i < 16; i++)
        {
            fx_proj[i] = s1516_flt(*((float*)proj4x4.m + i));
        }
        scene_set_projection(sc, fx_proj);
    }

    float eye[3] = { 0.0f, 0.0f, 3.0f };
    float look[3] = { 0.0f, 0.0f, -1.0f };
    const float up[3] = { 0.0f, 1.0f, 0.0f };

    LARGE_INTEGER then, now, freq;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&then);

    POINT oldcursor;
    GetCursorPos(&oldcursor);

    uint8_t* rgba8_pixels = (uint8_t*)malloc(fbwidth * fbheight * 4);
    assert(rgba8_pixels);

    // readback framebuffer contents
    framebuffer_t* fb = renderer_get_framebuffer(rd);

    while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000))
    {
        MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        ImGui_ImplWin32GL_NewFrame();

        ImGui::ShowTestWindow();

        QueryPerformanceCounter(&now);
        float delta_time_sec = (float)(now.QuadPart - then.QuadPart) / freq.QuadPart;

        POINT cursor;
        GetCursorPos(&cursor);

        // only move and rotate camera when right mouse button is pressed
        float activated = (GetAsyncKeyState(VK_RBUTTON) & 0x8000) ? 1.0f : 0.0f;

        float view[16];
        flythrough_camera_update(
            eye, look, up, view,
            delta_time_sec,
            10.0f * ((GetAsyncKeyState(VK_LSHIFT) & 0x8000) ? 2.0f : 1.0f) * activated,
            0.5f * activated,
            80.0f,
            cursor.x - oldcursor.x, cursor.y - oldcursor.y,
            GetAsyncKeyState('W') & 0x8000, GetAsyncKeyState('A') & 0x8000, GetAsyncKeyState('S') & 0x8000, GetAsyncKeyState('D') & 0x8000,
            GetAsyncKeyState(VK_SPACE) & 0x8000, GetAsyncKeyState(VK_LCONTROL) & 0x8000,
            FLYTHROUGH_CAMERA_LEFT_HANDED_BIT);

        int32_t view_s1516[16];
        for (int32_t i = 0; i < 16; i++)
        {
            view_s1516[i] = s1516_flt(view[i]);
        }
        scene_set_view(sc, view_s1516);

        renderer_render_scene(rd, sc);

        framebuffer_t* fb = renderer_get_framebuffer(rd);
        framebuffer_pack_row_major(fb, 0, 0, fbwidth, fbheight, pixelformat_r8g8b8a8_unorm, rgba8_pixels);
        // flip the rows to appease the OpenGL gods
        for (int32_t row = 0; row < fbheight / 2; row++)
        {
            for (int32_t col = 0; col < fbwidth; col++)
            {
                uint32_t tmp = *(uint32_t*)&rgba8_pixels[(row * fbwidth + col) * 4];
                *(uint32_t*)&rgba8_pixels[(row * fbwidth + col) * 4] = *(uint32_t*)&rgba8_pixels[((fbheight - row - 1) * fbwidth + col) * 4];
                *(uint32_t*)&rgba8_pixels[((fbheight - row - 1) * fbwidth + col) * 4] = tmp;
            }
        }
        glDrawPixels(fbwidth, fbheight, GL_RGBA, GL_UNSIGNED_BYTE, rgba8_pixels);

        ImGui::Render();

        SwapBuffers(g_hDC);

        then = now;
        oldcursor = cursor;
    }

    free(rgba8_pixels);

    delete_scene(sc);
    delete_renderer(rd);

    return 0;
}<|endoftext|>


<commit_before>#include <string.h>
#include "I2PEndian.h"
#include "Log.h"
#include "RouterContext.h"
#include "I2NPProtocol.h"
#include "Tunnel.h"
#include "Transports.h"
#include "TransitTunnel.h"

namespace i2p
{
namespace tunnel
{
	TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
	    const uint8_t * nextIdent, uint32_t nextTunnelID,
		const uint8_t * layerKey,const uint8_t * ivKey):
			m_TunnelID (receiveTunnelID),  m_NextTunnelID (nextTunnelID),
			m_NextIdent (nextIdent), m_NumTransmittedBytes (0)
	{
		m_Encryption.SetKeys (layerKey, ivKey);
	}

	void TransitTunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg)
	{
		m_Encryption.Encrypt (tunnelMsg->GetPayload () + 4);
	}

	void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
	{
		EncryptTunnelMsg (tunnelMsg);

		LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID);
		*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
		FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);

		i2p::transports.SendMessage (m_NextIdent, tunnelMsg);
		m_NumTransmittedBytes += tunnelMsg->GetLength ();
	}

	void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)
	{
		LogPrint ("We are not a gateway for transit tunnel ", m_TunnelID);
		i2p::DeleteI2NPMessage (msg);
	}

	void TransitTunnelGateway::SendTunnelDataMsg (i2p::I2NPMessage * msg)
	{
		TunnelMessageBlock block;
		block.deliveryType = eDeliveryTypeLocal;
		block.data = msg;
		std::unique_lock<std::mutex> l(m_SendMutex);
		m_Gateway.SendTunnelDataMsg (block);
	}

	void TransitTunnelEndpoint::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
	{
		EncryptTunnelMsg (tunnelMsg);

		LogPrint ("TransitTunnel endpoint for ", GetTunnelID ());
		m_Endpoint.HandleDecryptedTunnelDataMsg (tunnelMsg);
	}

	TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
		const uint8_t * nextIdent, uint32_t nextTunnelID,
	    const uint8_t * layerKey,const uint8_t * ivKey,
		bool isGateway, bool isEndpoint)
	{
		if (isEndpoint)
		{
			LogPrint ("TransitTunnel endpoint: ", receiveTunnelID, " created");
			return new TransitTunnelEndpoint (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
		}
		else if (isGateway)
		{
			LogPrint ("TransitTunnel gateway: ", receiveTunnelID, " created");
			return new TransitTunnelGateway (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
		}
		else
		{
			LogPrint ("TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created");
			return new TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
		}
	}
}
}
<commit_msg>fixed race condition<commit_after>#include <string.h>
#include "I2PEndian.h"
#include "Log.h"
#include "RouterContext.h"
#include "I2NPProtocol.h"
#include "Tunnel.h"
#include "Transports.h"
#include "TransitTunnel.h"

namespace i2p
{
namespace tunnel
{
	TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
	    const uint8_t * nextIdent, uint32_t nextTunnelID,
		const uint8_t * layerKey,const uint8_t * ivKey):
			m_TunnelID (receiveTunnelID),  m_NextTunnelID (nextTunnelID),
			m_NextIdent (nextIdent), m_NumTransmittedBytes (0)
	{
		m_Encryption.SetKeys (layerKey, ivKey);
	}

	void TransitTunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg)
	{
		m_Encryption.Encrypt (tunnelMsg->GetPayload () + 4);
	}

	void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
	{
		EncryptTunnelMsg (tunnelMsg);

		LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID);
		m_NumTransmittedBytes += tunnelMsg->GetLength ();
		*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
		FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);

		i2p::transports.SendMessage (m_NextIdent, tunnelMsg);
	}

	void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)
	{
		LogPrint ("We are not a gateway for transit tunnel ", m_TunnelID);
		i2p::DeleteI2NPMessage (msg);
	}

	void TransitTunnelGateway::SendTunnelDataMsg (i2p::I2NPMessage * msg)
	{
		TunnelMessageBlock block;
		block.deliveryType = eDeliveryTypeLocal;
		block.data = msg;
		std::unique_lock<std::mutex> l(m_SendMutex);
		m_Gateway.SendTunnelDataMsg (block);
	}

	void TransitTunnelEndpoint::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
	{
		EncryptTunnelMsg (tunnelMsg);

		LogPrint ("TransitTunnel endpoint for ", GetTunnelID ());
		m_Endpoint.HandleDecryptedTunnelDataMsg (tunnelMsg);
	}

	TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
		const uint8_t * nextIdent, uint32_t nextTunnelID,
	    const uint8_t * layerKey,const uint8_t * ivKey,
		bool isGateway, bool isEndpoint)
	{
		if (isEndpoint)
		{
			LogPrint ("TransitTunnel endpoint: ", receiveTunnelID, " created");
			return new TransitTunnelEndpoint (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
		}
		else if (isGateway)
		{
			LogPrint ("TransitTunnel gateway: ", receiveTunnelID, " created");
			return new TransitTunnelGateway (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
		}
		else
		{
			LogPrint ("TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created");
			return new TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
		}
	}
}
}
<|endoftext|>


<commit_before>#include <immintrin.h>
#include "Distance.hpp"

namespace cctag {
namespace numerical {

// Compute (point-polar) distance between a point and an ellipse represented by its 3x3 matrix.
// TODO@lilian: f is always equal to 1, remove it
// NOTE: Q IS SYMMTERIC!; Eigen stores matrices column-wise by default.
float distancePointEllipseScalar(const Eigen::Vector3f& p, const Eigen::Matrix3f& Q, const float f )
{
  using Vector6f = Eigen::Matrix<float, 6, 1>;
  Vector6f aux( 6 );

  float x = p.x();
  float y = p.y();

  aux( 0 ) = x*x;
  aux( 1 ) = 2 * x * y;
  aux( 2 ) = 2* x;
  aux( 3 ) = y * y;
  aux( 4 ) = 2* y;
  aux( 5 ) = 1;

  float tmp1  = p( 0 ) * Q( 0, 0 ) + p( 1 ) * Q( 0, 1 ) + p( 2 ) * Q( 0, 2 );
  float tmp2  = p( 0 ) * Q( 0, 1 ) + p( 1 ) * Q( 1, 1 ) + p( 2 ) * Q( 1, 2 );
  float denom = tmp1 * tmp1 + tmp2 * tmp2;

  Vector6f qL(6);
  qL( 0 ) = Q( 0, 0 ) ; qL( 1 ) = Q( 0, 1 ) ; qL( 2 ) = Q( 0, 2 ) ;
  qL( 3 ) = Q( 1, 1 ) ; qL( 4 ) = Q( 1, 2 ) ;
  qL( 5 ) = Q( 2, 2 );
  return boost::math::pow<2>( aux.dot(qL) ) / denom;
}

// Packed computation, 8 points at a time
__m256 distance_point_ellipse_avx2(const Eigen::Matrix3f& Q, __m256 x, __m256 y, __m256 w)
{
  __m256 denom, dot;
  {
    __m256 q01 = _mm256_broadcast_ss(&Q(0,1));

    __m256 tmp11 = _mm256_mul_ps(x, _mm256_broadcast_ss(&Q(0,0)));
    __m256 tmp12 = _mm256_mul_ps(y, q01);
    __m256 tmp13 = _mm256_mul_ps(w, _mm256_broadcast_ss(&Q(0,2)));
    __m256 tmp1  = _mm256_add_ps(tmp11, _mm256_add_ps(tmp12, tmp13));

    __m256 tmp21 = _mm256_mul_ps(x, q01);
    __m256 tmp22 = _mm256_mul_ps(y, _mm256_broadcast_ss(&Q(1,1)));
    __m256 tmp23 = _mm256_mul_ps(w, _mm256_broadcast_ss(&Q(1,2)));
    __m256 tmp2  = _mm256_add_ps(tmp21, _mm256_add_ps(tmp22, tmp23));

    tmp1 = _mm256_mul_ps(tmp1, tmp1);
    tmp2 = _mm256_mul_ps(tmp2, tmp2);
    denom = _mm256_add_ps(tmp1, tmp2);
  }

  // Dot product of aux with qL
  {
    __m256 twox = _mm256_mul_ps(x, _mm256_set1_ps(2.f));
    __m256 twoy = _mm256_mul_ps(x, _mm256_set1_ps(2.f));

    dot =  _mm256_mul_ps(                                   // dot = x*x * Q(0,0)
      _mm256_broadcast_ss(&Q(0,0)), _mm256_mul_ps(x, x));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += 2*x*y * Q(0,1)
      _mm256_broadcast_ss(&Q(0,1)), _mm256_mul_ps(twox, y)));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += 2*x * Q(0,2)
      _mm256_broadcast_ss(&Q(0,2)), twox));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += y*y * Q(1,1)
      _mm256_broadcast_ss(&Q(1,1)), _mm256_mul_ps(y, y)));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += 2*y * Q(1,2)
      _mm256_broadcast_ss(&Q(1,2)), twoy));
    dot = _mm256_add_ps(dot,                                // dot += 1 * Q(2,2)
      _mm256_broadcast_ss(&Q(2,2)));
  }

  return _mm256_div_ps(dot, denom);
}

// Returns mask of valid distances based on n (valid range 1..7)
std::pair<__m256, __m256> distance_point_ellipse_avx2(const Eigen::Matrix3f& Q, const Eigen::Vector3f* pts, const size_t n)
{
  static_assert(sizeof(pts[0]) == 12, "Invalid Vector3f size");
  static const __m256i index = _mm256_set_epi32(21, 18, 15, 12,  9,  6,  3,  0);
  static const __m256i masks[8] =
  {
    _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0, -1, -1, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0, -1, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0,  0, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0,  0,  0, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0,  0,  0,  0, -1)
  };

  if (n<1 || n>8)
    throw std::logic_error("distance_point_ellipse_avx2: invalid count");

  // We use 1 for masked-out values so we avoid division by zero
  __m256 ones = _mm256_set1_ps(1.f);
  __m256 mask = _mm256_castsi256_ps(_mm256_load_si256(&masks[8-n]));

  __m256 x = _mm256_mask_i32gather_ps(ones, &pts[0](0), index, mask, 4);
  __m256 y = _mm256_mask_i32gather_ps(ones, &pts[0](1), index, mask, 4);
  __m256 w = _mm256_mask_i32gather_ps(ones, &pts[0](2), index, mask, 4);
}

void distancePointEllipse( std::vector<float>& dist, const std::vector<Eigen::Vector3f>& pts, const geometry::Ellipse& q, const float f )
{
  const size_t n = pts.size();
  dist.resize( n );
  tbb::parallel_for(size_t(0), n, [&dist,&pts,&q,f](size_t i) {
    dist[i] = distancePointEllipseScalar( pts[i], q.matrix(), f );
  });
}

}
}

<commit_msg>Bugfix in AVX2 distance.<commit_after>#include <immintrin.h>
#include "Distance.hpp"

namespace cctag {
namespace numerical {

// Compute (point-polar) distance between a point and an ellipse represented by its 3x3 matrix.
// TODO@lilian: f is always equal to 1, remove it
// NOTE: Q IS SYMMTERIC!; Eigen stores matrices column-wise by default.
float distancePointEllipseScalar(const Eigen::Vector3f& p, const Eigen::Matrix3f& Q, const float f )
{
  using Vector6f = Eigen::Matrix<float, 6, 1>;
  Vector6f aux( 6 );

  float x = p.x();
  float y = p.y();

  aux( 0 ) = x*x;
  aux( 1 ) = 2 * x * y;
  aux( 2 ) = 2* x;
  aux( 3 ) = y * y;
  aux( 4 ) = 2* y;
  aux( 5 ) = 1;

  float tmp1  = p( 0 ) * Q( 0, 0 ) + p( 1 ) * Q( 0, 1 ) + p( 2 ) * Q( 0, 2 );
  float tmp2  = p( 0 ) * Q( 0, 1 ) + p( 1 ) * Q( 1, 1 ) + p( 2 ) * Q( 1, 2 );
  float denom = tmp1 * tmp1 + tmp2 * tmp2;

  Vector6f qL(6);
  qL( 0 ) = Q( 0, 0 ) ; qL( 1 ) = Q( 0, 1 ) ; qL( 2 ) = Q( 0, 2 ) ;
  qL( 3 ) = Q( 1, 1 ) ; qL( 4 ) = Q( 1, 2 ) ;
  qL( 5 ) = Q( 2, 2 );
  return boost::math::pow<2>( aux.dot(qL) ) / denom;
}

// Packed computation, 8 points at a time
__m256 distance_point_ellipse_avx2(const Eigen::Matrix3f& Q, __m256 x, __m256 y, __m256 w)
{
  __m256 denom, dot;
  {
    __m256 q01 = _mm256_broadcast_ss(&Q(0,1));

    __m256 tmp11 = _mm256_mul_ps(x, _mm256_broadcast_ss(&Q(0,0)));
    __m256 tmp12 = _mm256_mul_ps(y, q01);
    __m256 tmp13 = _mm256_mul_ps(w, _mm256_broadcast_ss(&Q(0,2)));
    __m256 tmp1  = _mm256_add_ps(tmp11, _mm256_add_ps(tmp12, tmp13));

    __m256 tmp21 = _mm256_mul_ps(x, q01);
    __m256 tmp22 = _mm256_mul_ps(y, _mm256_broadcast_ss(&Q(1,1)));
    __m256 tmp23 = _mm256_mul_ps(w, _mm256_broadcast_ss(&Q(1,2)));
    __m256 tmp2  = _mm256_add_ps(tmp21, _mm256_add_ps(tmp22, tmp23));

    tmp1 = _mm256_mul_ps(tmp1, tmp1);
    tmp2 = _mm256_mul_ps(tmp2, tmp2);
    denom = _mm256_add_ps(tmp1, tmp2);
  }

  // Dot product of aux with qL
  {
    __m256 twox = _mm256_mul_ps(x, _mm256_set1_ps(2.f));
    __m256 twoy = _mm256_mul_ps(y, _mm256_set1_ps(2.f));

    dot =  _mm256_mul_ps(                                   // dot = x*x * Q(0,0)
      _mm256_broadcast_ss(&Q(0,0)), _mm256_mul_ps(x, x));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += 2*x*y * Q(0,1)
      _mm256_broadcast_ss(&Q(0,1)), _mm256_mul_ps(twox, y)));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += 2*x * Q(0,2)
      _mm256_broadcast_ss(&Q(0,2)), twox));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += y*y * Q(1,1)
      _mm256_broadcast_ss(&Q(1,1)), _mm256_mul_ps(y, y)));
    dot = _mm256_add_ps(dot, _mm256_mul_ps(                 // dot += 2*y * Q(1,2)
      _mm256_broadcast_ss(&Q(1,2)), twoy));
    dot = _mm256_add_ps(dot,                                // dot += 1 * Q(2,2)
      _mm256_broadcast_ss(&Q(2,2)));
  }

  dot = _mm256_mul_ps(dot, dot);
  return _mm256_div_ps(dot, denom);
}

// Returns mask of valid distances based on n (valid range 1..7)
std::pair<__m256, __m256> distance_point_ellipse_avx2(const Eigen::Matrix3f& Q, const Eigen::Vector3f* pts, const size_t n)
{
  static_assert(sizeof(pts[0]) == 12, "Invalid Vector3f size");
  static const __m256i index = _mm256_set_epi32(21, 18, 15, 12,  9,  6,  3,  0);
  static const __m256i masks[8] =
  {
    _mm256_set_epi32(-1, -1, -1, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0, -1, -1, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0, -1, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0, -1, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0, -1, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0,  0, -1, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0,  0,  0, -1, -1),
    _mm256_set_epi32( 0,  0,  0,  0,  0,  0,  0, -1)
  };

  if (n<1 || n>8)
    throw std::logic_error("distance_point_ellipse_avx2: invalid count");

  // We use 1 for masked-out values so we avoid division by zero
  __m256 ones = _mm256_set1_ps(1.f);
  __m256 mask = _mm256_castsi256_ps(_mm256_load_si256(&masks[8-n]));

  __m256 x = _mm256_mask_i32gather_ps(ones, &pts[0](0), index, mask, 4);
  __m256 y = _mm256_mask_i32gather_ps(ones, &pts[0](1), index, mask, 4);
  __m256 w = _mm256_mask_i32gather_ps(ones, &pts[0](2), index, mask, 4);
  __m256 d = distance_point_ellipse_avx2(Q, x, y, w);

  return std::make_pair(d, mask);
}

void distancePointEllipse( std::vector<float>& dist, const std::vector<Eigen::Vector3f>& pts, const geometry::Ellipse& q, const float f )
{
  size_t n = pts.size();

  dist.resize(n);

  for (size_t i = 0; i < n; i += 8) {
    auto distance = distance_point_ellipse_avx2(q.matrix(), &pts[i], std::min(size_t(8), n-i));
    __m256 d = std::get<0>(distance);
    __m256 m = std::get<1>(distance);
    _mm256_maskstore_ps(&dist[i], _mm256_castps_si256(m), d);
  }

#if false   // NB: distance with avx may very in absolute value by several integral units
  // check
  for (size_t i = 0; i < pts.size(); ++i) {
    float d = distancePointEllipseScalar(pts[i], q.matrix(), f);
    if (std::fabs(d-dist[i]) > 1) {
      tbb::mutex::scoped_lock lock(m);
      std::clog << "distance failed: AVX2: " << dist[i] << "; scalar: " << d
        << "\nMATRIX:\n" << q.matrix()
        << "\nPOINT:\n" << pts[i]
        << std::endl;
      std::abort();
    }
  }
#endif

  //tbb::parallel_for(size_t(0), n, [&dist,&pts,&q,f](size_t i) {
  //  dist[i] = distancePointEllipseScalar( pts[i], q.matrix(), f );
  //});
}

}
}

<|endoftext|>


<commit_before>#include <chrono>
#include <cmath>
#include <iostream>
#include <vector>
#include "model.hpp"
#include "CartesianGrid.hpp"
#include "Observer.hpp"
#include "Photon.hpp"
#include "Random.hpp"
#include "Directions.hpp"
#include "IDust.hpp"
#include "Sources.hpp"

int run(int argc, char *argv[])
{
    auto const initTime = std::chrono::high_resolution_clock::now();

    std::vector<Observer> observers;

    // read the model parameters
    Model& model = Model::instance(&observers, argc == 2 ? argv[1] : "parameters.json");
    IGridCPtr grid = model.grid();
    SourcesPtr sources = model.sources();
    Random ran{ model.createRandomGenerator() };

    std::cout << "Matter mass:\t" << grid->computeMatterMass() << "\t Solar Masses" << std::endl;
    sources->writeObserversOpticalDepths(grid, &observers);

    auto startTime = std::chrono::high_resolution_clock::now();

    // Scattered photon loop
    if (model.fMonteCarlo())
    {
        for (;;)
        {
            Photon ph{ sources->emitPhoton(&ran) };

            if (ph.termination())
            {
                break;
            }

            // Find optical depth, tau1, to edge of grid
            double tau1 = grid->findOpticalDepth(ph);
            if (tau1 < model.taumin())
            {
                continue;
            }
            double w = 1.0 - std::exp(-tau1);
            ph.weight() = w;

            // Force photon to scatter at optical depth tau before edge of grid
            double tau = -std::log(1.0 - ran.Get() * w);
            // Find scattering location of tau
            grid->movePhotonAtDepth(ph, tau, 0.0);
            // Photon scatters in grid until it exits (tflag=1) or number
            // of scatterings exceeds a set value (nscatt)
            int tflag = 0;
            while (!tflag)
            {
                ph.weight() *= model.dust()->albedo();
                // Do peeling off and project weighted photons into image
                for (Observer &observer : observers)
                {
                    grid->peeloff(ph, observer, model.dust());
                }

                if (ph.nscat() >= model.nscat())
                {
                    break;
                }

                // Scatter photon into new direction and update Stokes parameters
                ph.Stokes(model.dust(), Direction3d(), 0.0, false, &ran);
                ph.nscat() += 1;

                // Find next scattering location
                tflag = grid->movePhotonAtRandomDepth(ph, &ran);
            }
        }
    } else {
        // Set up directions grid
        Directions sdir( model.SecondaryDirectionsLevel(), model.useHEALPixGrid() );
        startTime = std::chrono::high_resolution_clock::now();

        // Loop over scattering dots
        if (model.NumOfPrimaryScatterings() > 0)
        {
            for (;;)
            {
                Photon ph0{sources->emitPhoton(&ran)};

                if (ph0.termination())
                {
                    break;
                }

                // Find optical depth, tau1, to edge of grid
                double tau1 = grid->findOpticalDepth(ph0);
                if (tau1 < model.taumin())
                {
                    continue;
                }

                double const w = (1.0 - exp(-tau1)) / model.NumOfPrimaryScatterings();

                double tauold = 0.0, tau = 0.0;
                Vector3d spos = ph0.pos();
                std::uint64_t sCellId = ph0.cellId();

                for (std::uint64_t s = 0; s != model.NumOfPrimaryScatterings(); ++s)
                {
                    Photon ph(spos, sCellId, ph0.dir(), ph0.weight() * w, 1);
                    // Force photon to scatter at optical depth tau before edge of grid
                    tauold = tau;
                    tau = -log(1.0 - 0.5 * w * (2 * s + 1));

                    // Find scattering location of tau
                    grid->movePhotonAtDepth(ph, tau, tauold);
                    spos = ph.pos();
                    sCellId = ph.cellId();

                    // Photon scatters in grid until it exits (tflag=1) or number
                    // of scatterings exceeds a set value (nscatt)

                    // Photons scattering
                    ph.weight() *= model.dust()->albedo();

                    for (Observer &observer : observers)
                    {
                        grid->peeloff(ph, observer, model.dust());
                    }

                    if (ph.nscat() < model.nscat()) ph.Scatt(model, sdir, grid, observers, &ran);
                }
            }
        }
        else
        {
            double const sqrtPiN = std::sqrt(PI / sources->num_photons());
            double const base = 1. + 2. * sqrtPiN / (1 - sqrtPiN);
            // pessimistic estimation of scattering number, as we use it only for minimal optical depth estimation
            double const nScatteringsRev = std::log(base) / std::log(std::sqrt(3.) * grid->max());
            double const minWeight = 1. - std::exp(-model.taumin() * nScatteringsRev);

            for (;;)
            {
                Photon ph0{sources->emitPhoton(&ran)};

                if (ph0.termination())
                {
                    break;
                }

                Vector3d spos = ph0.pos();

                // skip empty inner regions
                grid->movePhotonAtDepth(ph0, std::numeric_limits<double>::epsilon(), 0.0);
                double oldR = std::max(model.defaultStarRadius(), (spos - ph0.pos()).norm());

                while (grid->inside(ph0) && ph0.weight() > minWeight)
                {
                    Photon ph{ ph0 };

                    // estimate tau
                    double const r = oldR * base;
                    Vector3d oldpos = ph0.pos();
                    double const tau = grid->movePhotonAtDistance(ph0, r - oldR);
                    ph0.weight() *= std::exp(-tau);

                    // Photons scattering
                    if (tau > model.taumin() * nScatteringsRev)
                    {
                        // Find scattering location of tau
                        double const tauScattering = -log(0.5 + 0.5 * exp(-tau));
                        grid->movePhotonAtDepth(ph, tauScattering, 0.0);

                        ph.weight() *= model.dust()->albedo() * (1.0 - std::exp(-tau));

                        for (Observer &observer : observers)
                        {
                            grid->peeloff(ph, observer, model.dust(), oldpos, ph0.pos());
                        }

                        if (ph.nscat() < model.nscat()) ph.Scatt(model, sdir, grid, observers, &ran);
                    }
                    oldR = r;
                }
            }
        }
    }

    sources->directPhotons(grid, &observers);

    std::cout << "Finishing..." << std::endl;

    // Normalize images
    for(std::uint64_t cnt=0; cnt!=observers.size(); ++cnt)
    {
        observers[cnt].normalize(sources->num_photons());
    }

    // put results into output files
    for (std::uint64_t cnt = 0; cnt != observers.size(); ++cnt)
    {
        observers[cnt].writeToMapFiles(model.writeScatterings(), model.nscat());
    }

    // put general information into file
    std::ofstream observersResultFile("observers.dat");
    for (std::uint64_t cnt = 0; cnt != observers.size(); ++cnt)
    {
        observers[cnt].write(observersResultFile);
    }
    observersResultFile.close();

    ran.save();

    auto const endTime = std::chrono::high_resolution_clock::now();
    std::cout.precision(4);
    std::cout << "Initialization time:\t" << std::chrono::duration_cast<std::chrono::milliseconds>(startTime - initTime).count() * 0.001 << "s\n"
              << "Computation time:\t" << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() * 0.001 << "s" << std::endl;

    {
        std::ofstream timefile("time.txt");
        timefile.precision(4);

        timefile << "Initialization time:    "
                 << std::chrono::duration_cast<std::chrono::milliseconds>(startTime - initTime).count() * 0.001 << "s\n"
                 << "Computation time:       "
                 << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() * 0.001 << "s"
                 << std::endl;

        timefile.close();
    }

    return 0;
}

int main(int argc, char *argv[])
{
    try
    {
        return run(argc, argv);
    }
    catch (std::exception const& ex) {
        std::cerr << "Terminated after throwing an exception:\n" << ex.what() << std::endl;
    }
    return 0;
}
<commit_msg>Increase observers.dat precision<commit_after>#include <chrono>
#include <cmath>
#include <iostream>
#include <vector>
#include "model.hpp"
#include "CartesianGrid.hpp"
#include "Observer.hpp"
#include "Photon.hpp"
#include "Random.hpp"
#include "Directions.hpp"
#include "IDust.hpp"
#include "Sources.hpp"

int run(int argc, char *argv[])
{
    auto const initTime = std::chrono::high_resolution_clock::now();

    std::vector<Observer> observers;

    // read the model parameters
    Model& model = Model::instance(&observers, argc == 2 ? argv[1] : "parameters.json");
    IGridCPtr grid = model.grid();
    SourcesPtr sources = model.sources();
    Random ran{ model.createRandomGenerator() };

    std::cout << "Matter mass:\t" << grid->computeMatterMass() << "\t Solar Masses" << std::endl;
    sources->writeObserversOpticalDepths(grid, &observers);

    auto startTime = std::chrono::high_resolution_clock::now();

    // Scattered photon loop
    if (model.fMonteCarlo())
    {
        for (;;)
        {
            Photon ph{ sources->emitPhoton(&ran) };

            if (ph.termination())
            {
                break;
            }

            // Find optical depth, tau1, to edge of grid
            double tau1 = grid->findOpticalDepth(ph);
            if (tau1 < model.taumin())
            {
                continue;
            }
            double w = 1.0 - std::exp(-tau1);
            ph.weight() = w;

            // Force photon to scatter at optical depth tau before edge of grid
            double tau = -std::log(1.0 - ran.Get() * w);
            // Find scattering location of tau
            grid->movePhotonAtDepth(ph, tau, 0.0);
            // Photon scatters in grid until it exits (tflag=1) or number
            // of scatterings exceeds a set value (nscatt)
            int tflag = 0;
            while (!tflag)
            {
                ph.weight() *= model.dust()->albedo();
                // Do peeling off and project weighted photons into image
                for (Observer &observer : observers)
                {
                    grid->peeloff(ph, observer, model.dust());
                }

                if (ph.nscat() >= model.nscat())
                {
                    break;
                }

                // Scatter photon into new direction and update Stokes parameters
                ph.Stokes(model.dust(), Direction3d(), 0.0, false, &ran);
                ph.nscat() += 1;

                // Find next scattering location
                tflag = grid->movePhotonAtRandomDepth(ph, &ran);
            }
        }
    } else {
        // Set up directions grid
        Directions sdir( model.SecondaryDirectionsLevel(), model.useHEALPixGrid() );
        startTime = std::chrono::high_resolution_clock::now();

        // Loop over scattering dots
        if (model.NumOfPrimaryScatterings() > 0)
        {
            for (;;)
            {
                Photon ph0{sources->emitPhoton(&ran)};

                if (ph0.termination())
                {
                    break;
                }

                // Find optical depth, tau1, to edge of grid
                double tau1 = grid->findOpticalDepth(ph0);
                if (tau1 < model.taumin())
                {
                    continue;
                }

                double const w = (1.0 - exp(-tau1)) / model.NumOfPrimaryScatterings();

                double tauold = 0.0, tau = 0.0;
                Vector3d spos = ph0.pos();
                std::uint64_t sCellId = ph0.cellId();

                for (std::uint64_t s = 0; s != model.NumOfPrimaryScatterings(); ++s)
                {
                    Photon ph(spos, sCellId, ph0.dir(), ph0.weight() * w, 1);
                    // Force photon to scatter at optical depth tau before edge of grid
                    tauold = tau;
                    tau = -log(1.0 - 0.5 * w * (2 * s + 1));

                    // Find scattering location of tau
                    grid->movePhotonAtDepth(ph, tau, tauold);
                    spos = ph.pos();
                    sCellId = ph.cellId();

                    // Photon scatters in grid until it exits (tflag=1) or number
                    // of scatterings exceeds a set value (nscatt)

                    // Photons scattering
                    ph.weight() *= model.dust()->albedo();

                    for (Observer &observer : observers)
                    {
                        grid->peeloff(ph, observer, model.dust());
                    }

                    if (ph.nscat() < model.nscat()) ph.Scatt(model, sdir, grid, observers, &ran);
                }
            }
        }
        else
        {
            double const sqrtPiN = std::sqrt(PI / sources->num_photons());
            double const base = 1. + 2. * sqrtPiN / (1 - sqrtPiN);
            // pessimistic estimation of scattering number, as we use it only for minimal optical depth estimation
            double const nScatteringsRev = std::log(base) / std::log(std::sqrt(3.) * grid->max());
            double const minWeight = 1. - std::exp(-model.taumin() * nScatteringsRev);

            for (;;)
            {
                Photon ph0{sources->emitPhoton(&ran)};

                if (ph0.termination())
                {
                    break;
                }

                Vector3d spos = ph0.pos();

                // skip empty inner regions
                grid->movePhotonAtDepth(ph0, std::numeric_limits<double>::epsilon(), 0.0);
                double oldR = std::max(model.defaultStarRadius(), (spos - ph0.pos()).norm());

                while (grid->inside(ph0) && ph0.weight() > minWeight)
                {
                    Photon ph{ ph0 };

                    // estimate tau
                    double const r = oldR * base;
                    Vector3d oldpos = ph0.pos();
                    double const tau = grid->movePhotonAtDistance(ph0, r - oldR);
                    ph0.weight() *= std::exp(-tau);

                    // Photons scattering
                    if (tau > model.taumin() * nScatteringsRev)
                    {
                        // Find scattering location of tau
                        double const tauScattering = -log(0.5 + 0.5 * exp(-tau));
                        grid->movePhotonAtDepth(ph, tauScattering, 0.0);

                        ph.weight() *= model.dust()->albedo() * (1.0 - std::exp(-tau));

                        for (Observer &observer : observers)
                        {
                            grid->peeloff(ph, observer, model.dust(), oldpos, ph0.pos());
                        }

                        if (ph.nscat() < model.nscat()) ph.Scatt(model, sdir, grid, observers, &ran);
                    }
                    oldR = r;
                }
            }
        }
    }

    sources->directPhotons(grid, &observers);

    std::cout << "Finishing..." << std::endl;

    // Normalize images
    for(std::uint64_t cnt=0; cnt!=observers.size(); ++cnt)
    {
        observers[cnt].normalize(sources->num_photons());
    }

    // put results into output files
    for (std::uint64_t cnt = 0; cnt != observers.size(); ++cnt)
    {
        observers[cnt].writeToMapFiles(model.writeScatterings(), model.nscat());
    }

    // put general information into file
    std::ofstream observersResultFile("observers.dat");
    observersResultFile.precision(14);
    for (std::uint64_t cnt = 0; cnt != observers.size(); ++cnt)
    {
        observers[cnt].write(observersResultFile);
    }
    observersResultFile.close();

    ran.save();

    auto const endTime = std::chrono::high_resolution_clock::now();
    std::cout.precision(4);
    std::cout << "Initialization time:\t" << std::chrono::duration_cast<std::chrono::milliseconds>(startTime - initTime).count() * 0.001 << "s\n"
              << "Computation time:\t" << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() * 0.001 << "s" << std::endl;

    {
        std::ofstream timefile("time.txt");
        timefile.precision(4);

        timefile << "Initialization time:    "
                 << std::chrono::duration_cast<std::chrono::milliseconds>(startTime - initTime).count() * 0.001 << "s\n"
                 << "Computation time:       "
                 << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() * 0.001 << "s"
                 << std::endl;

        timefile.close();
    }

    return 0;
}

int main(int argc, char *argv[])
{
    try
    {
        return run(argc, argv);
    }
    catch (std::exception const& ex) {
        std::cerr << "Terminated after throwing an exception:\n" << ex.what() << std::endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>/* cdbg_unitig_reporter.hh -- async reporters
 *
 * Copyright (C) 2018 Camille Scott
 * All rights reserved.
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE file for details.
 */

#ifndef BOINK_CDBG_UNITIG_REPORTER_HH
#define BOINK_CDBG_UNITIG_REPORTER_HH

#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>

#include "utils/stringutils.h"

#include "boink/boink.hh"
#include "boink/cdbg/cdbg.hh"
#include "boink/cdbg/compactor.hh"
#include "boink/event_types.hh"
#include "boink/reporting/reporters.hh"
#include "boink/reporting/report_types.hh"

#include "sparsepp/spp.h"

namespace boink {
namespace reporting {

template <class GraphType>
class cDBGUnitigReporter : public SingleFileReporter {
private:

    std::shared_ptr<cdbg::cDBG<GraphType>>        cdbg;
    std::vector<size_t>                           bins;

public:

    cDBGUnitigReporter(std::shared_ptr<cdbg::cDBG<GraphType>> cdbg,
                       const std::string&                     filename,
                       std::vector<size_t>                    bins)
        : SingleFileReporter       (filename, "cDBGUnitigReporter"),
          cdbg                     (cdbg),
          bins                     (bins)
    {
        _cerr(this->THREAD_NAME << " reporting at MEDIUM interval.");
        this->msg_type_whitelist.insert(events::MSG_TIME_INTERVAL);

        _output_stream << "read_n";

        for (size_t bin = 0; bin < bins.size() - 1; bin++) {
            _output_stream << ", " << bins[bin] << "-" << bins[bin+1];
        }
        _output_stream << ", " << bins.back() << "-Inf";

        _output_stream << std::endl;
    }

    virtual void handle_msg(std::shared_ptr<events::Event> event) {
         if (event->msg_type == events::MSG_TIME_INTERVAL) {
            auto _event = static_cast<events::TimeIntervalEvent*>(event.get());
            if (_event->level == events::TimeIntervalEvent::MEDIUM ||
                _event->level == events::TimeIntervalEvent::END) {

                auto bin_sums = this->compute_bins();
                auto row      = utils::StringUtils::join(bin_sums, ", ");
                _output_stream << _event->t << ","
                               << row << ","
                               << std::endl;
            }
        }
    }

    std::vector<size_t> compute_bins() {
        auto time_start = std::chrono::system_clock::now();
        auto lock       = cdbg->lock_nodes();
        _cerr("Summing unitig length bins...");

        std::vector<size_t> bin_sums(bins.size(), 0);

        for (auto it = cdbg->unodes_begin(); it != cdbg->unodes_end(); ++it) {
            auto seq_len = it->second->sequence.length();
            for (size_t bin_num = 0; bin_num < bins.size() - 1; bin_num++) {
                if (seq_len >= bins[bin_num] && seq_len < bins[bin_num+1]) {
                    bin_sums[bin_num] += seq_len;
                    break;
                }
            }
            if (seq_len > bins.back()) {
                bins[bins.size() - 1] += seq_len;
            }
        }

        auto time_elapsed = std::chrono::system_clock::now() - time_start;
        _cerr("Finished summing unitig length bins. Elapsed time: " <<
              std::chrono::duration<double>(time_elapsed).count());

        return bin_sums;
    }
};

}
}
#endif
<commit_msg>Remove trailing comma in unitig bp reporter<commit_after>/* cdbg_unitig_reporter.hh -- async reporters
 *
 * Copyright (C) 2018 Camille Scott
 * All rights reserved.
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE file for details.
 */

#ifndef BOINK_CDBG_UNITIG_REPORTER_HH
#define BOINK_CDBG_UNITIG_REPORTER_HH

#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>

#include "utils/stringutils.h"

#include "boink/boink.hh"
#include "boink/cdbg/cdbg.hh"
#include "boink/cdbg/compactor.hh"
#include "boink/event_types.hh"
#include "boink/reporting/reporters.hh"
#include "boink/reporting/report_types.hh"

#include "sparsepp/spp.h"

namespace boink {
namespace reporting {

template <class GraphType>
class cDBGUnitigReporter : public SingleFileReporter {
private:

    std::shared_ptr<cdbg::cDBG<GraphType>>        cdbg;
    std::vector<size_t>                           bins;

public:

    cDBGUnitigReporter(std::shared_ptr<cdbg::cDBG<GraphType>> cdbg,
                       const std::string&                     filename,
                       std::vector<size_t>                    bins)
        : SingleFileReporter       (filename, "cDBGUnitigReporter"),
          cdbg                     (cdbg),
          bins                     (bins)
    {
        _cerr(this->THREAD_NAME << " reporting at MEDIUM interval.");
        this->msg_type_whitelist.insert(events::MSG_TIME_INTERVAL);

        _output_stream << "read_n";

        for (size_t bin = 0; bin < bins.size() - 1; bin++) {
            _output_stream << ", " << bins[bin] << "-" << bins[bin+1];
        }
        _output_stream << ", " << bins.back() << "-Inf";

        _output_stream << std::endl;
    }

    virtual void handle_msg(std::shared_ptr<events::Event> event) {
         if (event->msg_type == events::MSG_TIME_INTERVAL) {
            auto _event = static_cast<events::TimeIntervalEvent*>(event.get());
            if (_event->level == events::TimeIntervalEvent::MEDIUM ||
                _event->level == events::TimeIntervalEvent::END) {

                auto bin_sums = this->compute_bins();
                auto row      = utils::StringUtils::join(bin_sums, ", ");
                _output_stream << _event->t << ","
                               << row
                               << std::endl;
            }
        }
    }

    std::vector<size_t> compute_bins() {
        auto time_start = std::chrono::system_clock::now();
        auto lock       = cdbg->lock_nodes();
        _cerr("Summing unitig length bins...");

        std::vector<size_t> bin_sums(bins.size(), 0);

        for (auto it = cdbg->unodes_begin(); it != cdbg->unodes_end(); ++it) {
            auto seq_len = it->second->sequence.length();
            for (size_t bin_num = 0; bin_num < bins.size() - 1; bin_num++) {
                if (seq_len >= bins[bin_num] && seq_len < bins[bin_num+1]) {
                    bin_sums[bin_num] += seq_len;
                    break;
                }
            }
            if (seq_len > bins.back()) {
                bins[bins.size() - 1] += seq_len;
            }
        }

        auto time_elapsed = std::chrono::system_clock::now() - time_start;
        _cerr("Finished summing unitig length bins. Elapsed time: " <<
              std::chrono::duration<double>(time_elapsed).count());

        return bin_sums;
    }
};

}
}
#endif
<|endoftext|>


<commit_before>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_genparams_from_file.hpp
 * @brief       iris unit test parameter generator from file
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2015-2017, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_GENPARAMS_FROM_FILE_HPP_81CDA6E7_945B_4F72_873B_104264DF7132_
#define INCG_IRIS_IUTEST_GENPARAMS_FROM_FILE_HPP_81CDA6E7_945B_4F72_873B_104264DF7132_

#if IUTEST_HAS_CSVPARAMS

namespace iutest {
namespace detail
{

/**
 * @brief   csv ファイルからのパラメータ生成器
 * @tparam T    = パラメータ型
*/
template<typename T>
class iuCsvFileParamsGenerator : public iuValuesInParamsGenerator<T>
{
    typedef ::std::vector<T> params_t;
public:
    /**
     * @brief   コンストラクタ
     * @param [in]  path        = ファイルパス
     * @param [in]  delimiter   = 区切り文字
    */
    explicit iuCsvFileParamsGenerator(const ::std::string& path, char delimiter = ',')
        : iuValuesInParamsGenerator<T>(ReadParams(path, delimiter))
    {
    }

private:
    bool ToParam(const ::std::string& data, T& param)
    {
        ::std::istringstream strm(data);
        if( strm >> param )
        {
            return true;
        }
        return false;
    }

private:
    void AppendParams(params_t& params, const ::std::string& data)
    {
        if( StringIsBlank(data) )
        {
            return;
        }
        T param;
        if( !ToParam(data, param) )
        {
            return;
        }
        params.push_back(param);
    }
    params_t ReadParams(const ::std::string& path, char delimiter = ',')
    {
        params_t params;
        IFile* fp = detail::IFileSystem::New();
        if( fp != NULL )
        {
            if( fp->Open(path.c_str(), IFile::OpenRead) )
            {
                const ::std::string dataset = fp->ReadAll();
                ::std::string::size_type prev = 0;
                ::std::string::size_type pos = 0;
                while( pos = dataset.find(delimiter, prev), pos != ::std::string::npos )
                {
                    const ::std::string data = dataset.substr(prev, pos - prev);
                    AppendParams(params, data);
                    ++pos;
                    prev = pos;
                }
                AppendParams(params, dataset.substr(prev));
            }
            else
            {
                fprintf(stderr, "Unable to open file \"%s\".\n", path.c_str());
                fflush(stderr);
            }
            detail::IFileSystem::Free(fp);
        }
        IUTEST_CHECK_(!params.empty());
        return params;
    }
};

template<>inline bool iuCsvFileParamsGenerator<float>::ToParam(const ::std::string& data, float& param)
{
#if IUTEST_HAS_CXX11
    param = std::stof(data);
    return true;
#else
    ::std::istringstream strm(data);
    if( !(strm >> param) )
    {
        param = static_cast<float>(atof(data.c_str()));
    }
    return true;
#endif
}

}   // end of namespace detail
}   // end of namespace iutest

#endif

#endif // INCG_IRIS_IUTEST_GENPARAMS_FROM_FILE_HPP_81CDA6E7_945B_4F72_873B_104264DF7132_
<commit_msg>fix cpplint<commit_after>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        iutest_genparams_from_file.hpp
 * @brief       iris unit test parameter generator from file
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2015-2017, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_GENPARAMS_FROM_FILE_HPP_81CDA6E7_945B_4F72_873B_104264DF7132_
#define INCG_IRIS_IUTEST_GENPARAMS_FROM_FILE_HPP_81CDA6E7_945B_4F72_873B_104264DF7132_

#if IUTEST_HAS_CSVPARAMS

namespace iutest {
namespace detail
{

/**
 * @brief   csv ファイルからのパラメータ生成器
 * @tparam T    = パラメータ型
*/
template<typename T>
class iuCsvFileParamsGenerator : public iuValuesInParamsGenerator<T>
{
    typedef ::std::vector<T> params_t;
public:
    /**
     * @brief   コンストラクタ
     * @param [in]  path        = ファイルパス
     * @param [in]  delimiter   = 区切り文字
    */
    explicit iuCsvFileParamsGenerator(const ::std::string& path, char delimiter = ',')
        : iuValuesInParamsGenerator<T>(ReadParams(path, delimiter))
    {
    }

private:
    bool ToParam(const ::std::string& data, T& param)
    {
        ::std::istringstream strm(data);
        if( strm >> param )
        {
            return true;
        }
        return false;
    }

private:
    void AppendParams(params_t& params, const ::std::string& data)
    {
        if( StringIsBlank(data) )
        {
            return;
        }
        T param;
        if( !ToParam(data, param) )
        {
            return;
        }
        params.push_back(param);
    }
    params_t ReadParams(const ::std::string& path, char delimiter = ',')
    {
        params_t params;
        IFile* fp = detail::IFileSystem::New();
        if( fp != NULL )
        {
            if( fp->Open(path.c_str(), IFile::OpenRead) )
            {
                const ::std::string dataset = fp->ReadAll();
                ::std::string::size_type prev = 0;
                ::std::string::size_type pos = 0;
                while( pos = dataset.find(delimiter, prev), pos != ::std::string::npos )
                {
                    const ::std::string data = dataset.substr(prev, pos - prev);
                    AppendParams(params, data);
                    ++pos;
                    prev = pos;
                }
                AppendParams(params, dataset.substr(prev));
            }
            else
            {
                fprintf(stderr, "Unable to open file \"%s\".\n", path.c_str());
                fflush(stderr);
            }
            detail::IFileSystem::Free(fp);
        }
        IUTEST_CHECK_(!params.empty());
        return params;
    }
};

template<>inline bool iuCsvFileParamsGenerator<float>::ToParam(const ::std::string& data, float& param)
{
#if IUTEST_HAS_CXX11
    param = std::stof(data);
    return true;
#else
    ::std::istringstream strm(data);
    if( !(strm >> param) )
    {
        param = static_cast<float>(atof(data.c_str()));
    }
    return true;
#endif
}

}   // end of namespace detail
}   // end of namespace iutest

#endif

#endif // INCG_IRIS_IUTEST_GENPARAMS_FROM_FILE_HPP_81CDA6E7_945B_4F72_873B_104264DF7132_
<|endoftext|>


<commit_before>// Copyright (c) 2019 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP

#include <cassert>
#include <ostream>
#include <string>

#include "parse_tree.hpp"

namespace TAO_PEGTL_NAMESPACE::parse_tree
{
   namespace internal
   {
      inline void escape( std::ostream& os, const std::string_view s )
      {
         static const char* h = "0123456789abcdef";

         const char* p = s.data();
         const char* l = p;
         const char* const e = s.data() + s.size();
         while( p != e ) {
            const unsigned char c = *p;
            if( c == '\\' ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\\";
            }
            else if( c == '"' ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\"";
            }
            else if( c < 32 ) {
               os.write( l, p - l );
               l = ++p;
               switch( c ) {
                  case '\b':
                     os << "\\b";
                     break;
                  case '\f':
                     os << "\\f";
                     break;
                  case '\n':
                     os << "\\n";
                     break;
                  case '\r':
                     os << "\\r";
                     break;
                  case '\t':
                     os << "\\t";
                     break;
                  default:
                     os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ];
               }
            }
            else if( c == 127 ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\u007f";
            }
            else {
               ++p;
            }
         }
         os.write( l, p - l );
      }

      void print_dot_node( std::ostream& os, const parse_tree::node& n, const std::string_view s )
      {
         os << "  x" << &n << " [ label=\"";
         escape( os, s );
         if( n.has_content() ) {
            os << "\\n";
            escape( os, n.string_view() );
         }
         os << "\" ]\n";
         if( !n.children.empty() ) {
            os << "  x" << &n << " -> { ";
            for( auto& up : n.children ) {
               os << "x" << up.get() << ( ( up == n.children.back() ) ? " }\n" : ", " );
            }
            for( auto& up : n.children ) {
               print_dot_node( os, *up, up->type );
            }
         }
      }

   }  // namespace internal

   void print_dot( std::ostream& os, const parse_tree::node& n )
   {
      os << "digraph parse_tree\n{\n";
      internal::print_dot_node( os, n, n.is_root() ? "ROOT": n.type );
      os << "}\n";
   }

}  // namespace TAO_PEGTL_NAMESPACE::parse_tree

#endif
<commit_msg>clang-format<commit_after>// Copyright (c) 2019 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP

#include <cassert>
#include <ostream>
#include <string>

#include "parse_tree.hpp"

namespace TAO_PEGTL_NAMESPACE::parse_tree
{
   namespace internal
   {
      inline void escape( std::ostream& os, const std::string_view s )
      {
         static const char* h = "0123456789abcdef";

         const char* p = s.data();
         const char* l = p;
         const char* const e = s.data() + s.size();
         while( p != e ) {
            const unsigned char c = *p;
            if( c == '\\' ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\\";
            }
            else if( c == '"' ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\\"";
            }
            else if( c < 32 ) {
               os.write( l, p - l );
               l = ++p;
               switch( c ) {
                  case '\b':
                     os << "\\b";
                     break;
                  case '\f':
                     os << "\\f";
                     break;
                  case '\n':
                     os << "\\n";
                     break;
                  case '\r':
                     os << "\\r";
                     break;
                  case '\t':
                     os << "\\t";
                     break;
                  default:
                     os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ];
               }
            }
            else if( c == 127 ) {
               os.write( l, p - l );
               l = ++p;
               os << "\\u007f";
            }
            else {
               ++p;
            }
         }
         os.write( l, p - l );
      }

      void print_dot_node( std::ostream& os, const parse_tree::node& n, const std::string_view s )
      {
         os << "  x" << &n << " [ label=\"";
         escape( os, s );
         if( n.has_content() ) {
            os << "\\n";
            escape( os, n.string_view() );
         }
         os << "\" ]\n";
         if( !n.children.empty() ) {
            os << "  x" << &n << " -> { ";
            for( auto& up : n.children ) {
               os << "x" << up.get() << ( ( up == n.children.back() ) ? " }\n" : ", " );
            }
            for( auto& up : n.children ) {
               print_dot_node( os, *up, up->type );
            }
         }
      }

   }  // namespace internal

   void print_dot( std::ostream& os, const parse_tree::node& n )
   {
      os << "digraph parse_tree\n{\n";
      internal::print_dot_node( os, n, n.is_root() ? "ROOT" : n.type );
      os << "}\n";
   }

}  // namespace TAO_PEGTL_NAMESPACE::parse_tree

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include "PresentDistribution.hpp"

void run_part_one() {
    unsigned long presents = 0;
    unsigned long house = 1;
    do {
        house++;
        presents = presents_in_house(house);
    } while (presents < 34000000);
    std::cout << house << std::endl;
}
void run_part_two() {
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "--part_two") {
            run_part_two();
        } else {
            std::cout << "Usage: day20 [--part_two]" << std::endl;
            return -1;
        }
    } else {
        run_part_one();
    }
}
<commit_msg>added runtime code for day 20 part two<commit_after>#include <iostream>
#include <string>

#include "PresentDistribution.hpp"

void run_part_one() {
    unsigned long presents = 0;
    unsigned long house = 1;
    do {
        house++;
        presents = presents_in_house(house);
    } while (presents < 34000000);
    std::cout << house << std::endl;
}
void run_part_two() {
    unsigned long presents = 0;
    unsigned long house = 1;
    do {
        house++;
        presents = presents_in_house2(house);
    } while (presents < 34000000);
    std::cout << house << std::endl;
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "--part_two") {
            run_part_two();
        } else {
            std::cout << "Usage: day20 [--part_two]" << std::endl;
            return -1;
        }
    } else {
        run_part_one();
    }
}
<|endoftext|>