<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: lightSettings.C,v 1.18 2005/02/15 12:35:51 amoll Exp $
//

#include <BALL/VIEW/DIALOGS/lightSettings.h>
#include <BALL/VIEW/WIDGETS/scene.h>

#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qlabel.h>
#include <qbuttongroup.h>
#include <qradiobutton.h>
#include <qslider.h>

namespace BALL
{
	namespace VIEW
	{

LightSettings::LightSettings(QWidget* parent, const char* name, WFlags fl)
  : LightSettingsData(parent, name, fl),
		PreferencesEntry(),
		ignore_(false),
		current_light_(-1)
{
	if (parent == 0 || !RTTI::isKindOf<Scene>(*parent))
	{
		Log.error() << "LightSettings dialog must be created with a Scene as parent!" << std::endl;
		return;
	}

	stage_ = (dynamic_cast<Scene*>(parent))->getStage();
	if (stage_ == 0)
	{
		Log.error() << "LightSettings dialog was created with a Scene as parent, which has no Stage!" << std::endl;
		return;
	}

	relative_to_camera->setChecked(true);
	updateFromStage();
	insertEntry(this, "Lighting");
}

void LightSettings::updateFromStage()
	throw()
{
	lights_.clear();
	List<LightSource>::ConstIterator it = stage_->getLightSources().begin();
	for (; it != stage_->getLightSources().end(); it++)
	{
		lights_.push_back(*it);
	}

	update();
}

void LightSettings::update()
	throw()
{
	if (!lights_.size())
	{
		clearFields_();
		return;
	}

	if (lights_.size() != lights_list->count())
	{
		clearFields_();

		for (Position light_nr = 0; light_nr < lights_.size(); light_nr++)
		{
			lights_list->insertItem((String("Light ") + String(light_nr + 1)).c_str());
		}
	}

	if (getCurrentLightNumber_() == -1)
	{
		ignore_ = true;
		lights_list->setSelected(lights_.size() - 1, true);
		ignore_ = false;
		return;
	}

	getValues_();
	ignore_ = false;
}

void LightSettings::addLightPressed()
{
	if (lights_.size() >= 8) return;

	saveSettingsToLight_();

	LightSource light;
	light.setIntensity(0.8);
	light.setType(LightSource::POSITIONAL);

	// position light 20 space units behind camera position
	const Camera& camera = stage_->getCamera();
	Vector3 pos = camera.getViewVector();
	pos.normalize();
	pos *= -20;
	pos += camera.getViewPoint();

	// create a kind of headlight
	Vector3 up = camera.getLookUpVector();
	up.normalize();
	up *= 4;
 	pos += up;

	light.setPosition(pos);
	light.setDirection(camera.getViewPoint());

	lights_.push_back(light);
	update();
}

void LightSettings::colorPressed()
{
	chooseColor(color_sample);
}

void LightSettings::defaultsPressed()
{
	lights_.clear();
	lights_list->clear();
	addLightPressed();
}

// store settings for last selected light
void LightSettings::saveSettingsToLight_()
	throw()
{
	if (current_light_ == -1) return;

	LightSource& light = lights_[current_light_];
	light.setColor(color_sample->backgroundColor());

	try
	{
		Vector3 pos = getPosition_();
		Vector3 dir = getDirection_();
		bool relative = !not_relative->isChecked();
		light.setRelativeToCamera(relative);

		// position and direction
		if (relative)
		{
			pos = stage_->calculateAbsoluteCoordinates(pos);
			dir = stage_->calculateAbsoluteCoordinates(dir);
		}
		light.setPosition(pos);
		light.setDirection(dir);

		light.setIntensity((float)(intensity->value()) / 100.0);

		/////////////////////////////////////////////////////
		// type of light
		if (light_type->selected() == ambient)
		{
			light.setType(LightSource::AMBIENT);
			return;
		}

		if (light_type->selected() == point)
		{
			light.setType(LightSource::POSITIONAL);
			return;
		}

		light.setType(LightSource::DIRECTIONAL);

	}
	catch (Exception::GeneralException e)
	{
		Log.error() << "Invalid values in LightSettingsDialog" << std::endl;
		Log.error() << e;
	}
}

void LightSettings::lightSelected()
{
	if (!ignore_) saveSettingsToLight_();
	current_light_ = getCurrentLightNumber_();
	getValues_();
}

void LightSettings::removeLightPressed()
{
	Index current = getCurrentLightNumber_();
	if (current == -1) return;

	vector<LightSource>::iterator it = lights_.begin();
	for (Index i = 0; it != lights_.end() && i < current; it++)
	{
		i++;
	}
	lights_.erase(it);
	update();
}

void LightSettings::typeSelected()
{
	bool is_ambient = (light_type->selected() == ambient);

	relative_to_camera->setEnabled(!is_ambient);
	      not_relative->setEnabled(!is_ambient);

	position_x->setEnabled(!is_ambient);
	position_y->setEnabled(!is_ambient);
	position_z->setEnabled(!is_ambient);

	direction_x->setEnabled(!is_ambient);
	direction_y->setEnabled(!is_ambient);
	direction_z->setEnabled(!is_ambient);
}

void LightSettings::getValues_()
	throw()
{
	Index current = getCurrentLightNumber_();
	if (current == -1) return;

	setControlsEnabled_(true);

	LightSource& light = lights_[current];

	color_sample->setBackgroundColor(light.getColor().getQColor());

	Vector3 pos = light.getPosition();
	Vector3 dir = light.getDirection();

	if (light.isRelativeToCamera())
	{
		pos = stage_->calculateRelativeCoordinates(pos);
		dir = stage_->calculateRelativeCoordinates(dir);
	}

	setPosition_(pos);
	setDirection_(dir);

	bool is_ambient = (light.getType() == LightSource::AMBIENT);

	position_x->setEnabled(!is_ambient);
	position_y->setEnabled(!is_ambient);
	position_z->setEnabled(!is_ambient);
	direction_x->setEnabled(!is_ambient);
	direction_y->setEnabled(!is_ambient);
	direction_z->setEnabled(!is_ambient);
	relative_to_camera->setEnabled(!is_ambient);
	not_relative->setEnabled(!is_ambient);

	if (light.isRelativeToCamera())
	{
		relative->setChecked(true);
	}
	else
	{
		not_relative->setChecked(true);
	}

	light_type->setButton(light.getType());
	intensity->setValue((Index)(light.getIntensity() * 100.0));
}

void LightSettings::clearFields_()
	throw()
{
	lights_list->clear();
	position_x->clear();
	position_y->clear();
	position_z->clear();
	direction_x->clear();
	direction_y->clear();
	direction_z->clear();
	setControlsEnabled_(false);
}

void LightSettings::setControlsEnabled_(bool state)
{
	remove_lights_button->setEnabled(state);
	position_x->setEnabled(state);
	position_y->setEnabled(state);
	position_z->setEnabled(state);
	direction_x->setEnabled(state);
	direction_y->setEnabled(state);
	direction_z->setEnabled(state);
	intensity->setEnabled(state);
	intensity->setValue(0);
	remove_lights_button->setEnabled(state);
	relative_to_camera->setEnabled(state);
	not_relative->setEnabled(state);
	color_button->setEnabled(state);
	light_type->setEnabled(state);
}

void LightSettings::apply()
	throw()
{
	saveSettingsToLight_();
	stage_->clearLightSources();
	for (Position p = 0; p < lights_.size(); p++)
	{
		stage_->addLightSource(lights_[p]);
	}
}

void LightSettings::intensityChanged()
{
	intensity_label->setText(String(intensity->value()).c_str());
}

void LightSettings::setDefaultValues(bool /*all*/)
	throw()
{
	defaultsPressed();
	color_sample->setBackgroundColor(white);
	lights_list->setCurrentItem(0);
}

void LightSettings::positionTypeChanged()
{
	if (getCurrentLightNumber_() == -1 || ignore_)
	{
		return;
	}

	try
	{
		Vector3 pos = getPosition_();
		Vector3 dir = getDirection_();

		if (relative->isChecked())
		{
			Vector3 diff = dir - pos;
			pos = stage_->calculateRelativeCoordinates(pos);
			dir = stage_->calculateRelativeCoordinates(diff);
		}
		else
		{
			pos = stage_->calculateAbsoluteCoordinates(pos);
			dir = pos +
						stage_->calculateAbsoluteCoordinates(dir);
		}

		setPosition_(pos);
		setDirection_(dir);
	}
	catch(...)
	{
	}
}

void LightSettings::setPosition_(const Vector3& v)
{
	position_x->setText(createFloatString(v.x, 1).c_str());
	position_y->setText(createFloatString(v.y, 1).c_str());
	position_z->setText(createFloatString(v.z, 1).c_str());
}

void LightSettings::setDirection_(const Vector3& v)
{
	direction_x->setText(createFloatString(v.x, 1).c_str());
	direction_y->setText(createFloatString(v.y, 1).c_str());
	direction_z->setText(createFloatString(v.z, 1).c_str());
}

Vector3 LightSettings::getPosition_()
	throw(Exception::InvalidFormat)
{
	return Vector3(String(position_x->text().ascii()).toFloat(),
				 			   String(position_y->text().ascii()).toFloat(),
			  				 String(position_z->text().ascii()).toFloat());
}

Vector3 LightSettings::getDirection_()
	throw(Exception::InvalidFormat)
{
	return Vector3(String(direction_x->text().ascii()).toFloat(),
				 			   String(direction_y->text().ascii()).toFloat(),
			  				 String(direction_z->text().ascii()).toFloat());
}

Index LightSettings::getCurrentLightNumber_() const
{
	return lights_list->currentItem();
}

} } // NAMESPACE
<commit_msg>no message<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: lightSettings.C,v 1.19 2005/02/15 13:34:52 amoll Exp $
//

#include <BALL/VIEW/DIALOGS/lightSettings.h>
#include <BALL/VIEW/WIDGETS/scene.h>

#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qlabel.h>
#include <qbuttongroup.h>
#include <qradiobutton.h>
#include <qslider.h>

namespace BALL
{
	namespace VIEW
	{

LightSettings::LightSettings(QWidget* parent, const char* name, WFlags fl)
  : LightSettingsData(parent, name, fl),
		PreferencesEntry(),
		ignore_(false),
		current_light_(-1)
{
	if (parent == 0 || !RTTI::isKindOf<Scene>(*parent))
	{
		Log.error() << "LightSettings dialog must be created with a Scene as parent!" << std::endl;
		return;
	}

	stage_ = (dynamic_cast<Scene*>(parent))->getStage();
	if (stage_ == 0)
	{
		Log.error() << "LightSettings dialog was created with a Scene as parent, which has no Stage!" << std::endl;
		return;
	}

	relative_to_camera->setChecked(true);
	updateFromStage();
	insertEntry(this, "Lighting");
}

void LightSettings::updateFromStage()
	throw()
{
	lights_.clear();
	List<LightSource>::ConstIterator it = stage_->getLightSources().begin();
	for (; it != stage_->getLightSources().end(); it++)
	{
		lights_.push_back(*it);
	}

	update();
}

void LightSettings::update()
	throw()
{
	if (!lights_.size())
	{
		clearFields_();
		return;
	}

	if (lights_.size() != lights_list->count())
	{
		clearFields_();

		for (Position light_nr = 0; light_nr < lights_.size(); light_nr++)
		{
			lights_list->insertItem((String("Light ") + String(light_nr + 1)).c_str());
		}
	}

	if (getCurrentLightNumber_() == -1)
	{
		ignore_ = true;
		lights_list->setSelected(lights_.size() - 1, true);
		ignore_ = false;
		return;
	}

	getValues_();
	ignore_ = false;
}

void LightSettings::addLightPressed()
{
	if (lights_.size() >= 8) return;

	saveSettingsToLight_();

	LightSource light;
	light.setIntensity(0.8);
	light.setType(LightSource::POSITIONAL);

	// position light 20 space units behind camera position
	const Camera& camera = stage_->getCamera();
	Vector3 pos = camera.getViewVector();
	pos.normalize();
	pos *= -20;
	pos += camera.getViewPoint();

	// create a kind of headlight
	Vector3 up = camera.getLookUpVector();
	up.normalize();
	up *= 4;
 	pos += up;

	light.setPosition(pos);
	light.setDirection(camera.getViewPoint());

	lights_.push_back(light);
	update();
}

void LightSettings::colorPressed()
{
	chooseColor(color_sample);
}

void LightSettings::defaultsPressed()
{
	lights_list->clear();
	lights_.clear();
	addLightPressed();
}

// store settings for last selected light
void LightSettings::saveSettingsToLight_()
	throw()
{
	if (current_light_ == -1 ||
			current_light_ >= lights_.size()) return;

	LightSource& light = lights_[current_light_];
	light.setColor(color_sample->backgroundColor());

	try
	{
		Vector3 pos = getPosition_();
		Vector3 dir = getDirection_();
		bool relative = !not_relative->isChecked();
		light.setRelativeToCamera(relative);

		// position and direction
		if (relative)
		{
			pos = stage_->calculateAbsoluteCoordinates(pos);
			dir = stage_->calculateAbsoluteCoordinates(dir);
		}
		light.setPosition(pos);
		light.setDirection(dir);

		light.setIntensity((float)(intensity->value()) / 100.0);

		/////////////////////////////////////////////////////
		// type of light
		if (light_type->selected() == ambient)
		{
			light.setType(LightSource::AMBIENT);
			return;
		}

		if (light_type->selected() == point)
		{
			light.setType(LightSource::POSITIONAL);
			return;
		}

		light.setType(LightSource::DIRECTIONAL);

	}
	catch (Exception::GeneralException e)
	{
		Log.error() << "Invalid values in LightSettingsDialog" << std::endl;
		Log.error() << e;
	}
}

void LightSettings::lightSelected()
{
	if (!ignore_) saveSettingsToLight_();
	current_light_ = getCurrentLightNumber_();
	getValues_();
}

void LightSettings::removeLightPressed()
{
	Index current = getCurrentLightNumber_();
	if (current == -1) return;

	vector<LightSource>::iterator it = lights_.begin();
	for (Index i = 0; it != lights_.end() && i < current; it++)
	{
		i++;
	}
	lights_.erase(it);
	update();
}

void LightSettings::typeSelected()
{
	bool is_ambient = (light_type->selected() == ambient);

	relative_to_camera->setEnabled(!is_ambient);
	      not_relative->setEnabled(!is_ambient);

	position_x->setEnabled(!is_ambient);
	position_y->setEnabled(!is_ambient);
	position_z->setEnabled(!is_ambient);

	direction_x->setEnabled(!is_ambient);
	direction_y->setEnabled(!is_ambient);
	direction_z->setEnabled(!is_ambient);
}

void LightSettings::getValues_()
	throw()
{
	Index current = getCurrentLightNumber_();
	if (current == -1) return;

	setControlsEnabled_(true);

	LightSource& light = lights_[current];

	color_sample->setBackgroundColor(light.getColor().getQColor());

	Vector3 pos = light.getPosition();
	Vector3 dir = light.getDirection();

	if (light.isRelativeToCamera())
	{
		pos = stage_->calculateRelativeCoordinates(pos);
		dir = stage_->calculateRelativeCoordinates(dir);
	}

	setPosition_(pos);
	setDirection_(dir);

	bool is_ambient = (light.getType() == LightSource::AMBIENT);

	position_x->setEnabled(!is_ambient);
	position_y->setEnabled(!is_ambient);
	position_z->setEnabled(!is_ambient);
	direction_x->setEnabled(!is_ambient);
	direction_y->setEnabled(!is_ambient);
	direction_z->setEnabled(!is_ambient);
	relative_to_camera->setEnabled(!is_ambient);
	not_relative->setEnabled(!is_ambient);

	if (light.isRelativeToCamera())
	{
		relative->setChecked(true);
	}
	else
	{
		not_relative->setChecked(true);
	}

	light_type->setButton(light.getType());
	intensity->setValue((Index)(light.getIntensity() * 100.0));
}

void LightSettings::clearFields_()
	throw()
{
	lights_list->clear();
	position_x->clear();
	position_y->clear();
	position_z->clear();
	direction_x->clear();
	direction_y->clear();
	direction_z->clear();
	setControlsEnabled_(false);
}

void LightSettings::setControlsEnabled_(bool state)
{
	remove_lights_button->setEnabled(state);
	position_x->setEnabled(state);
	position_y->setEnabled(state);
	position_z->setEnabled(state);
	direction_x->setEnabled(state);
	direction_y->setEnabled(state);
	direction_z->setEnabled(state);
	intensity->setEnabled(state);
	intensity->setValue(0);
	remove_lights_button->setEnabled(state);
	relative_to_camera->setEnabled(state);
	not_relative->setEnabled(state);
	color_button->setEnabled(state);
	light_type->setEnabled(state);
}

void LightSettings::apply()
	throw()
{
	saveSettingsToLight_();
	stage_->clearLightSources();
	for (Position p = 0; p < lights_.size(); p++)
	{
		stage_->addLightSource(lights_[p]);
	}
}

void LightSettings::intensityChanged()
{
	intensity_label->setText(String(intensity->value()).c_str());
}

void LightSettings::setDefaultValues(bool /*all*/)
	throw()
{
	defaultsPressed();
	color_sample->setBackgroundColor(white);
	lights_list->setCurrentItem(0);
}

void LightSettings::positionTypeChanged()
{
	if (getCurrentLightNumber_() == -1 || ignore_)
	{
		return;
	}

	try
	{
		Vector3 pos = getPosition_();
		Vector3 dir = getDirection_();

		if (relative->isChecked())
		{
			Vector3 diff = dir - pos;
			pos = stage_->calculateRelativeCoordinates(pos);
			dir = stage_->calculateRelativeCoordinates(diff);
		}
		else
		{
			pos = stage_->calculateAbsoluteCoordinates(pos);
			dir = pos +
						stage_->calculateAbsoluteCoordinates(dir);
		}

		setPosition_(pos);
		setDirection_(dir);
	}
	catch(...)
	{
	}
}

void LightSettings::setPosition_(const Vector3& v)
{
	position_x->setText(createFloatString(v.x, 1).c_str());
	position_y->setText(createFloatString(v.y, 1).c_str());
	position_z->setText(createFloatString(v.z, 1).c_str());
}

void LightSettings::setDirection_(const Vector3& v)
{
	direction_x->setText(createFloatString(v.x, 1).c_str());
	direction_y->setText(createFloatString(v.y, 1).c_str());
	direction_z->setText(createFloatString(v.z, 1).c_str());
}

Vector3 LightSettings::getPosition_()
	throw(Exception::InvalidFormat)
{
	return Vector3(String(position_x->text().ascii()).toFloat(),
				 			   String(position_y->text().ascii()).toFloat(),
			  				 String(position_z->text().ascii()).toFloat());
}

Vector3 LightSettings::getDirection_()
	throw(Exception::InvalidFormat)
{
	return Vector3(String(direction_x->text().ascii()).toFloat(),
				 			   String(direction_y->text().ascii()).toFloat(),
			  				 String(direction_z->text().ascii()).toFloat());
}

Index LightSettings::getCurrentLightNumber_() const
{
	return lights_list->currentItem();
}

} } // NAMESPACE
<|endoftext|>


<commit_before>#include "script/python/MathModule.h"
#include "math/Vector.h"
#include "math/Matrix.h"
#include "math/Quaternion.h"
#include "math/Rotation.h"

// Vector2 Python Helper Functions
void vector2_setitem(Vector2& v, int index, float value)
{
	int MAX = 2;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float vector2_getitem(Vector2&v, int index)
{
	int MAX = 2;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Vector3 Python Helper Functions
void vector3_setitem(Vector3& v, int index, float value)
{
	int MAX = 3;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float vector3_getitem(Vector3&v, int index)
{
	int MAX = 3;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Vector4 Python Helper Functions
void vector4_setitem(Vector4& v, int index, float value)
{
	int MAX = 4;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float vector4_getitem(Vector4&v, int index)
{
	int MAX = 4;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Matrix3 Python Helper Functions
void matrix3_setitem(Matrix3& v, int index, float value)
{
	int MAX = 9;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float matrix3_getitem(Matrix3&v, int index)
{
	int MAX = 9;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Matrix4 Python Helper Functions
void matrix4_setitem(Matrix4& v, int index, float value)
{
	int MAX = 16;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float matrix4_getitem(Matrix4&v, int index)
{
	int MAX = 16;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Quaternion function wrappers

Quaternion (Quaternion::*RotateAxisVF)(Vector3,float) = &Quaternion::RotateAxis;
Quaternion (Quaternion::*RotateAxisAA)(AxisAngle) = &Quaternion::RotateAxis;
Quaternion (Quaternion::*RotateEulerFFF)(float,float,float) = &Quaternion::RotateEuler;
Quaternion (Quaternion::*RotateEulerE)(Euler) = &Quaternion::RotateEuler;

// Expose Math Classes to Python
void initMath()
{
	// make math package
	object mathModule( handle<>( borrowed( PyImport_AddModule("epsilon.math") ) ) );
	scope().attr("math") = mathModule;

	scope mathScope = mathModule;

	class_<Vector2>("Vector2", init< optional<float> >())
			.def(init<Vector2>())
			.def(init<float,float>())

		.def_readwrite("x", &Vector2::x)
		.def_readwrite("y", &Vector2::y)

		.def("__str__", &Vector2::ToString)

		.def("__getitem__", &vector2_getitem)
		.def("__setitem__", &vector2_setitem)

		.def(self == self)
		.def(self != self)

		.def(self + self)
		.def(self - self)

		.def(self * self)

		.def(self * float())
		.def(float() * self)
		.def(self / float())

		.def(self += self)
		.def(self -= self)
		.def(self /= float())

		.def("length",&Vector2::Length)
		.def("length_squared", &Vector2::LengthSquared)
		.def("dot", &Vector2::Dot)
		.def("normalise", &Vector2::Normalise)
		.def("normalised", &Vector2::Normalised)

		.def("cross", &Vector2::Cross)
		.def("reflect", &Vector2::Reflect)
		.def("angle", &Vector2::Angle)
		.def("project", &Vector2::Project)

		.def("compute_extremes", &Vector2::ComputeExtremes, return_value_policy<manage_new_object>())
		;

	class_<Vector3>("Vector3", init< optional<float> >())
			.def(init<Vector3>())
			.def(init<float,float,float>())

		.def_readwrite("x", &Vector3::x)
		.def_readwrite("y", &Vector3::y)
		.def_readwrite("z", &Vector3::z)

		.def("__str__", &Vector3::ToString)

		.def("__getitem__", &vector3_getitem)
		.def("__setitem__", &vector3_setitem)

		.def(self == self)
		.def(self != self)

		.def(self + self)
		.def(self - self)

		.def(self * self)

		.def(self * float())
		.def(float() * self)
		.def(self / float())

		.def(self += self)
		.def(self -= self)
		.def(self /= float())

		.def("length",&Vector3::Length)
		.def("length_squared", &Vector3::LengthSquared)
		.def("dot", &Vector3::Dot)
		.def("normalise", &Vector3::Normalise)
		.def("normalised", &Vector3::Normalised)

		.def("cross", &Vector3::Cross)
		.def("unit_cross", &Vector3::UnitCross)
		.def("reflect", &Vector3::Reflect)
		.def("rotate_around", &Vector3::RotateAround)
		.def("distance", &Vector3::Distance)
		.def("angle", &Vector3::Angle)
		.def("project", &Vector3::Project)

		.def("compute_extremes", &Vector3::ComputeExtremes, return_value_policy<manage_new_object>())

		.def_readonly("UP", Vector3::UP)
		.def_readonly("RIGHT", &Vector3::RIGHT)
		.def_readonly("FORWARD", &Vector3::FORWARD)
		.def_readonly("DOWN", &Vector3::DOWN)
		.def_readonly("LEFT", &Vector3::LEFT)
		.def_readonly("BACKWARD", &Vector3::BACKWARD)

		.def_readonly("ZERO", &Vector3::ZERO)
		.def_readonly("ONE", &Vector3::ONE)
		.def_readonly("IDENTITY", &Vector3::IDENTITY)

		.def_readonly("UNIT_Z", &Vector3::UNIT_Z)
		.def_readonly("UNIT_Y", &Vector3::UNIT_Y)
		.def_readonly("UNIT_X", &Vector3::UNIT_X)
		;

	class_<Vector4>("Vector4", init< optional<float> >())
			.def(init<Vector4>())
			.def(init<float,float,float,float>())

		.def_readwrite("x", &Vector4::x)
		.def_readwrite("y", &Vector4::y)
		.def_readwrite("z", &Vector4::z)
		.def_readwrite("w", &Vector4::w)

		.def("__str__", &Vector4::ToString)

		.def("__getitem__", &vector4_getitem)
		.def("__setitem__", &vector4_setitem)

		.def(self == self)
		.def(self != self)

		.def(self + self)
		.def(self - self)

		.def(self * self)

		.def(self * float())
		.def(float() * self)
		.def(self / float())

		.def(self += self)
		.def(self -= self)
		.def(self /= float())

		.def("length",&Vector4::Length)
		.def("length_squared", &Vector4::LengthSquared)
		.def("dot", &Vector4::Dot)
		.def("normalise", &Vector4::Normalise)
		.def("normalised", &Vector4::Normalised)

		.def("compute_extremes", &Vector4::ComputeExtremes, return_value_policy<manage_new_object>())
		;

	class_<AxisAngle>("AxisAngle", init<Vector3, float>());

	class_<Euler>("Euler", init<float, float, float>());

	class_<Matrix3>("Matrix3")
		.def(init<Matrix3>())
		.def(init<float, float, float, float, float, float, float, float, float>())

		.def("__str__", &Matrix3::ToString)

		.def("__getitem__", &matrix3_getitem)
		.def("__setitem__", &matrix3_setitem)

		.def(self == self)
		.def(self != self)

		.def(self *= self)

		.def(self * self)
		.def(self * Vector3())

		.def("scale", &Matrix3::Scale)
		.def("translate", &Matrix3::Translate)
		.def("rotate", &Matrix3::Rotate)

		.def("create_scale", &Matrix3::CreateScale)
		.def("create_translation", &Matrix3::CreateTranslation)
		.def("create_rotation", &Matrix3::CreateRotation)

		.def("determinant", &Matrix3::Determinant)
		.def("inverse", &Matrix3::Inverse)
	;

	class_<Matrix4>("Matrix4")
		.def(init<Matrix4>())

		.def("__str__", &Matrix4::ToString)

		.def("__getitem__", &matrix4_getitem)
		.def("__setitem__", &matrix4_setitem)

		.def(self == self)
		.def(self != self)

		.def(self *= self)

		.def(self * self)
		.def(self * Vector3())

		.def("transform", &Matrix4::Transform)
		.def("scale", &Matrix4::Scale)
		.def("translate", &Matrix4::Translate)

		.def("rotate_x", &Matrix4::RotateX)
		.def("rotate_y", &Matrix4::RotateY)
		.def("rotate_z", &Matrix4::RotateZ)

		.def("rotate_axis", &Matrix4::RotateAxis)
		.def("rotate_euler", &Matrix4::RotateEuler)
		.def("rotate_triple_axis", &Matrix4::RotateTripleAxis)

		.def("transpose", &Matrix4::Transpose)
		.def("transposed", &Matrix4::Transposed)

		.def("create_scale", &Matrix4::CreateScale)
		.def("create_translation", &Matrix4::CreateTranslation)
		.def("create_rotate_x", &Matrix4::CreateRotateX)
		.def("create_rotate_y", &Matrix4::CreateRotateY)
		.def("create_rotate_z", &Matrix4::CreateRotateZ)
		.def("create_rotate_axis", &Matrix4::CreateRotateAxis)
		.def("create_rotate_euler", &Matrix4::CreateRotateEuler)
		.def("create_rotate_triple_axis", &Matrix4::CreateRotateTripleAxis)
		.def("create_rotate_quaternion", &Matrix4::CreateRotateQuaternion)
		.def("create_lookat", &Matrix4::CreateLookAt)
		.def("create_perspective", &Matrix4::CreatePerspective)

		.def("determinant", &Matrix4::Determinant)
		.def("inverse", &Matrix4::Inverse)
		.def("get_translation", &Matrix4::GetTranslation)
		.def("get_scale", &Matrix4::GetScale)
		.def("get_rotation", &Matrix4::GetRotation)
	;

	class_<Quaternion>("Quaternion")
		.def(init<Quaternion>())
		.def(init<float, float, float, float>())
		.def(init<Vector3, float>())
		.def(init<float, float, float>())
		.def(init<Matrix4>())

		.def(self == self)
		.def(self != self)

		.def(self * self)
		.def(self * Vector3())
		.def(self *= self)

		.def("length", &Quaternion::Length)
		.def("length_squared", &Quaternion::LengthSquared)
		.def("normalise", &Quaternion::Normalise)
		.def("normalised", &Quaternion::Normalised)
		.def("conjugate", &Quaternion::Conjugate)
		.def("conjugated", &Quaternion::Conjugated)
		.def("inverse", &Quaternion::Inverse)

		// Using Custom Overload handlers
		.def("rotate_axis", RotateAxisVF)
		.def("rotate_axis", RotateAxisAA)
		.def("rotate_euler", RotateEulerFFF)
		.def("rotate_euler", RotateEulerE)

		.def("rotate_matrix", &Quaternion::RotateMatrix)

		.def("rotate", &Quaternion::Rotate)
		.def("get_angle_axis", &Quaternion::GetAngleAxis)
		.def("get_euler", &Quaternion::GetEuler)
		.def("get_matrix", &Quaternion::GetMatrix)
		.def("interpolate", &Quaternion::Interpolate)

		.def_readonly("IDENTITY", &Quaternion::IDENTITY)
		.def_readonly("ZERO", &Quaternion::ZERO)
	;
}<commit_msg>M Fixed python Vector3 UP const<commit_after>#include "script/python/MathModule.h"
#include "math/Vector.h"
#include "math/Matrix.h"
#include "math/Quaternion.h"
#include "math/Rotation.h"

// Vector2 Python Helper Functions
void vector2_setitem(Vector2& v, int index, float value)
{
	int MAX = 2;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float vector2_getitem(Vector2&v, int index)
{
	int MAX = 2;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Vector3 Python Helper Functions
void vector3_setitem(Vector3& v, int index, float value)
{
	int MAX = 3;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float vector3_getitem(Vector3&v, int index)
{
	int MAX = 3;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Vector4 Python Helper Functions
void vector4_setitem(Vector4& v, int index, float value)
{
	int MAX = 4;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float vector4_getitem(Vector4&v, int index)
{
	int MAX = 4;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Matrix3 Python Helper Functions
void matrix3_setitem(Matrix3& v, int index, float value)
{
	int MAX = 9;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float matrix3_getitem(Matrix3&v, int index)
{
	int MAX = 9;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Matrix4 Python Helper Functions
void matrix4_setitem(Matrix4& v, int index, float value)
{
	int MAX = 16;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        v[index] = value;
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

float matrix4_getitem(Matrix4&v, int index)
{
	int MAX = 16;
	if ( index < 0 )
		index += MAX;
    if (index >= 0 && index < MAX) {
        return v[index];
    }
    else {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        throw_error_already_set();
    }
}

// Quaternion function wrappers

Quaternion (Quaternion::*RotateAxisVF)(Vector3,float) = &Quaternion::RotateAxis;
Quaternion (Quaternion::*RotateAxisAA)(AxisAngle) = &Quaternion::RotateAxis;
Quaternion (Quaternion::*RotateEulerFFF)(float,float,float) = &Quaternion::RotateEuler;
Quaternion (Quaternion::*RotateEulerE)(Euler) = &Quaternion::RotateEuler;

// Expose Math Classes to Python
void initMath()
{
	// make math package
	object mathModule( handle<>( borrowed( PyImport_AddModule("epsilon.math") ) ) );
	scope().attr("math") = mathModule;

	scope mathScope = mathModule;

	class_<Vector2>("Vector2", init< optional<float> >())
			.def(init<Vector2>())
			.def(init<float,float>())

		.def_readwrite("x", &Vector2::x)
		.def_readwrite("y", &Vector2::y)

		.def("__str__", &Vector2::ToString)

		.def("__getitem__", &vector2_getitem)
		.def("__setitem__", &vector2_setitem)

		.def(self == self)
		.def(self != self)

		.def(self + self)
		.def(self - self)

		.def(self * self)

		.def(self * float())
		.def(float() * self)
		.def(self / float())

		.def(self += self)
		.def(self -= self)
		.def(self /= float())

		.def("length",&Vector2::Length)
		.def("length_squared", &Vector2::LengthSquared)
		.def("dot", &Vector2::Dot)
		.def("normalise", &Vector2::Normalise)
		.def("normalised", &Vector2::Normalised)

		.def("cross", &Vector2::Cross)
		.def("reflect", &Vector2::Reflect)
		.def("angle", &Vector2::Angle)
		.def("project", &Vector2::Project)

		.def("compute_extremes", &Vector2::ComputeExtremes, return_value_policy<manage_new_object>())
		;

	class_<Vector3>("Vector3", init< optional<float> >())
			.def(init<Vector3>())
			.def(init<float,float,float>())

		.def_readwrite("x", &Vector3::x)
		.def_readwrite("y", &Vector3::y)
		.def_readwrite("z", &Vector3::z)

		.def("__str__", &Vector3::ToString)

		.def("__getitem__", &vector3_getitem)
		.def("__setitem__", &vector3_setitem)

		.def(self == self)
		.def(self != self)

		.def(self + self)
		.def(self - self)

		.def(self * self)

		.def(self * float())
		.def(float() * self)
		.def(self / float())

		.def(self += self)
		.def(self -= self)
		.def(self /= float())

		.def("length",&Vector3::Length)
		.def("length_squared", &Vector3::LengthSquared)
		.def("dot", &Vector3::Dot)
		.def("normalise", &Vector3::Normalise)
		.def("normalised", &Vector3::Normalised)

		.def("cross", &Vector3::Cross)
		.def("unit_cross", &Vector3::UnitCross)
		.def("reflect", &Vector3::Reflect)
		.def("rotate_around", &Vector3::RotateAround)
		.def("distance", &Vector3::Distance)
		.def("angle", &Vector3::Angle)
		.def("project", &Vector3::Project)

		.def("compute_extremes", &Vector3::ComputeExtremes, return_value_policy<manage_new_object>())

		.def_readonly("UP", &Vector3::UP)
		.def_readonly("RIGHT", &Vector3::RIGHT)
		.def_readonly("FORWARD", &Vector3::FORWARD)
		.def_readonly("DOWN", &Vector3::DOWN)
		.def_readonly("LEFT", &Vector3::LEFT)
		.def_readonly("BACKWARD", &Vector3::BACKWARD)

		.def_readonly("ZERO", &Vector3::ZERO)
		.def_readonly("ONE", &Vector3::ONE)
		.def_readonly("IDENTITY", &Vector3::IDENTITY)

		.def_readonly("UNIT_Z", &Vector3::UNIT_Z)
		.def_readonly("UNIT_Y", &Vector3::UNIT_Y)
		.def_readonly("UNIT_X", &Vector3::UNIT_X)
		;

	class_<Vector4>("Vector4", init< optional<float> >())
			.def(init<Vector4>())
			.def(init<float,float,float,float>())

		.def_readwrite("x", &Vector4::x)
		.def_readwrite("y", &Vector4::y)
		.def_readwrite("z", &Vector4::z)
		.def_readwrite("w", &Vector4::w)

		.def("__str__", &Vector4::ToString)

		.def("__getitem__", &vector4_getitem)
		.def("__setitem__", &vector4_setitem)

		.def(self == self)
		.def(self != self)

		.def(self + self)
		.def(self - self)

		.def(self * self)

		.def(self * float())
		.def(float() * self)
		.def(self / float())

		.def(self += self)
		.def(self -= self)
		.def(self /= float())

		.def("length",&Vector4::Length)
		.def("length_squared", &Vector4::LengthSquared)
		.def("dot", &Vector4::Dot)
		.def("normalise", &Vector4::Normalise)
		.def("normalised", &Vector4::Normalised)

		.def("compute_extremes", &Vector4::ComputeExtremes, return_value_policy<manage_new_object>())
		;

	class_<AxisAngle>("AxisAngle", init<Vector3, float>());

	class_<Euler>("Euler", init<float, float, float>());

	class_<Matrix3>("Matrix3")
		.def(init<Matrix3>())
		.def(init<float, float, float, float, float, float, float, float, float>())

		.def("__str__", &Matrix3::ToString)

		.def("__getitem__", &matrix3_getitem)
		.def("__setitem__", &matrix3_setitem)

		.def(self == self)
		.def(self != self)

		.def(self *= self)

		.def(self * self)
		.def(self * Vector3())

		.def("scale", &Matrix3::Scale)
		.def("translate", &Matrix3::Translate)
		.def("rotate", &Matrix3::Rotate)

		.def("create_scale", &Matrix3::CreateScale)
		.def("create_translation", &Matrix3::CreateTranslation)
		.def("create_rotation", &Matrix3::CreateRotation)

		.def("determinant", &Matrix3::Determinant)
		.def("inverse", &Matrix3::Inverse)
	;

	class_<Matrix4>("Matrix4")
		.def(init<Matrix4>())

		.def("__str__", &Matrix4::ToString)

		.def("__getitem__", &matrix4_getitem)
		.def("__setitem__", &matrix4_setitem)

		.def(self == self)
		.def(self != self)

		.def(self *= self)

		.def(self * self)
		.def(self * Vector3())

		.def("transform", &Matrix4::Transform)
		.def("scale", &Matrix4::Scale)
		.def("translate", &Matrix4::Translate)

		.def("rotate_x", &Matrix4::RotateX)
		.def("rotate_y", &Matrix4::RotateY)
		.def("rotate_z", &Matrix4::RotateZ)

		.def("rotate_axis", &Matrix4::RotateAxis)
		.def("rotate_euler", &Matrix4::RotateEuler)
		.def("rotate_triple_axis", &Matrix4::RotateTripleAxis)

		.def("transpose", &Matrix4::Transpose)
		.def("transposed", &Matrix4::Transposed)

		.def("create_scale", &Matrix4::CreateScale)
		.def("create_translation", &Matrix4::CreateTranslation)
		.def("create_rotate_x", &Matrix4::CreateRotateX)
		.def("create_rotate_y", &Matrix4::CreateRotateY)
		.def("create_rotate_z", &Matrix4::CreateRotateZ)
		.def("create_rotate_axis", &Matrix4::CreateRotateAxis)
		.def("create_rotate_euler", &Matrix4::CreateRotateEuler)
		.def("create_rotate_triple_axis", &Matrix4::CreateRotateTripleAxis)
		.def("create_rotate_quaternion", &Matrix4::CreateRotateQuaternion)
		.def("create_lookat", &Matrix4::CreateLookAt)
		.def("create_perspective", &Matrix4::CreatePerspective)

		.def("determinant", &Matrix4::Determinant)
		.def("inverse", &Matrix4::Inverse)
		.def("get_translation", &Matrix4::GetTranslation)
		.def("get_scale", &Matrix4::GetScale)
		.def("get_rotation", &Matrix4::GetRotation)
	;

	class_<Quaternion>("Quaternion")
		.def(init<Quaternion>())
		.def(init<float, float, float, float>())
		.def(init<Vector3, float>())
		.def(init<float, float, float>())
		.def(init<Matrix4>())

		.def(self == self)
		.def(self != self)

		.def(self * self)
		.def(self * Vector3())
		.def(self *= self)

		.def("length", &Quaternion::Length)
		.def("length_squared", &Quaternion::LengthSquared)
		.def("normalise", &Quaternion::Normalise)
		.def("normalised", &Quaternion::Normalised)
		.def("conjugate", &Quaternion::Conjugate)
		.def("conjugated", &Quaternion::Conjugated)
		.def("inverse", &Quaternion::Inverse)

		// Using Custom Overload handlers
		.def("rotate_axis", RotateAxisVF)
		.def("rotate_axis", RotateAxisAA)
		.def("rotate_euler", RotateEulerFFF)
		.def("rotate_euler", RotateEulerE)

		.def("rotate_matrix", &Quaternion::RotateMatrix)

		.def("rotate", &Quaternion::Rotate)
		.def("get_angle_axis", &Quaternion::GetAngleAxis)
		.def("get_euler", &Quaternion::GetEuler)
		.def("get_matrix", &Quaternion::GetMatrix)
		.def("interpolate", &Quaternion::Interpolate)

		.def_readonly("IDENTITY", &Quaternion::IDENTITY)
		.def_readonly("ZERO", &Quaternion::ZERO)
	;
}<|endoftext|>


<commit_before>#pragma once
#include <bts/blockchain/types.hpp>
#include <bts/blockchain/withdraw_types.hpp>
#include <bts/blockchain/transaction.hpp>

namespace bts { namespace blockchain {

    struct dice_record
    {
        dice_record()
        :id(0),account_id(0), amount(0), odds(1){}

        bool is_null()const;

        dice_record make_null()const;

        dice_id_type        id;
        account_id_type     account_id;
        share_type          amount;
        uint32_t            odds;
    };
    typedef fc::optional<dice_record> odice_record;

} } // bts::blockchain

FC_REFLECT( bts::blockchain::dice_record,
           (id)(account_id)(amount)(odds)
           )<commit_msg>fix segametaion fault, should no be 0<commit_after>#pragma once
#include <bts/blockchain/types.hpp>
#include <bts/blockchain/withdraw_types.hpp>
#include <bts/blockchain/transaction.hpp>

namespace bts { namespace blockchain {

    struct dice_record
    {
        dice_record()
        :id(dice_id_type()),account_id(0), amount(0), odds(1){}

        bool is_null()const;

        dice_record make_null()const;

        dice_id_type        id;
        account_id_type     account_id;
        share_type          amount;
        uint32_t            odds;
    };
    typedef fc::optional<dice_record> odice_record;

} } // bts::blockchain

FC_REFLECT( bts::blockchain::dice_record,
           (id)(account_id)(amount)(odds)
           )<|endoftext|>


<commit_before>#include <algorithm>
#include <cstring>
#include <limits>
#include <memory>

#include <android/log.h>

#include <boost/format.hpp>
#include <boost/utility.hpp>

#include <tbb/blocked_range2d.h>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>

#include "body_parts_recognizer.h"
#include "gles_helper.h"
#include "rgbd_image.h"
#include "sources.h"
#include "stopwatch.h"

const Depth BACKGROUND_DEPTH = std::numeric_limits<Depth>::max();

struct DepthImage
{
private:

  unsigned width, height;
  std::vector<Depth> depths;

public:

  DepthImage(const RGBDImage & image)
    : width(image.width), height(image.height), depths(width * height)
  {
    for (std::size_t i = 0; i < depths.size(); ++i)
      depths[i] = image.pixels[i].d == 0 ? BACKGROUND_DEPTH : image.pixels[i].d; // we consider 0 to be invalid depth
  }

  void
  applyThreshold(int threshold)
  {
    Depth min_depth = *std::min_element(depths.begin (), depths.end ());

    for (std::size_t i = 0; i < depths.size (); ++i)
      depths[i] = depths[i] <= min_depth + threshold ? depths[i] : BACKGROUND_DEPTH;
  }

  Depth
  getDepth(int x, int y) const
  {
    if (x < 0 || x >= int (width) || y < 0 || y >= int (height))
      return BACKGROUND_DEPTH;

    return depths[x + width * y];
  }

  unsigned getWidth() const { return width; }
  unsigned getHeight() const { return height; }
};

struct DecisionTreeCPU
{
  tbb::task_scheduler_init tbb_init;

  struct Offsets
  {
    boost::int16_t du1, dv1, du2, dv2;
  };

  struct Node
  {
    Offsets offsets;
    boost::int16_t threshold;
  };

  boost::uint16_t depth;
  std::vector<Node> nodes;
  std::vector<Label> leaves;

  DecisionTreeCPU(const char * data)
  {
    std::memcpy (&depth, data, sizeof depth);
    data += sizeof depth;

    nodes.resize ((1 << depth) - 1);
    std::memcpy (&nodes.front (), data, nodes.size () * sizeof (Node));
    data += nodes.size () * sizeof (Node);

    leaves.resize (1 << depth);
    std::memcpy (&leaves.front (), data, leaves.size () * sizeof (Label));
    data += leaves.size () * sizeof (Label);
  }

  Label
  walk(const DepthImage & image, int x, int y) const
  {
    unsigned nid = 0;
    Depth d0 = image.getDepth(x, y);
    float scale = 1000.0f / d0;

    for(int node_depth = 0; node_depth < depth; ++node_depth)
    {
      const Node & node = nodes[nid];

      Depth d1 = image.getDepth (x + node.offsets.du1 * scale, y + node.offsets.dv1 * scale);
      Depth d2 = image.getDepth (x + node.offsets.du2 * scale, y + node.offsets.dv2 * scale);

      int feature = int (d1) - int (d2);

      if (feature > node.threshold)
        nid = nid * 2 + 2;
      else
        nid = nid * 2 + 1;
    }

    return leaves[nid - nodes.size()];
  }

  struct WalkHelper
  {
  private:
    const DecisionTreeCPU & tree;
    const DepthImage & image;
    std::vector<Label> & labels;

  public:
    WalkHelper(const DecisionTreeCPU & tree, const DepthImage & image, std::vector<Label> & labels)
      : tree(tree), image(image), labels(labels)
    {
    }

    void
    operator () (const tbb::blocked_range2d<unsigned> & range) const
    {
      for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
        for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
          labels[x + y * image.getWidth()] = image.getDepth(x, y) == BACKGROUND_DEPTH ?
                Labels::Background : tree.walk(image, x, y);
    }
  };

  void
  eval(const DepthImage & image, std::vector<Label> & labels) const
  {
#if 0
    for (unsigned x = 0; x < image.getWidth(); ++x)
      for (unsigned y = 0; y < image.getHeight(); ++y)
        labels[x + y * image.getWidth()] = image.getDepth(x, y) == BACKGROUND_DEPTH ?
              Labels::Background : walk(image, x, y);
#else
    tbb::parallel_for(
          tbb::blocked_range2d<unsigned>(0, image.getHeight(), 0, image.getWidth()),
          WalkHelper(*this, image, labels)
    );
#endif
  }
};

struct DecisionTreeGPU : boost::noncopyable
{
private:
  std::auto_ptr<GlesHelper> helper;
  GLuint depth_image_tex, labels_tex;

public:
  DecisionTreeGPU(const char * data)
  {
    const int tree_width = 2048;
    boost::uint16_t tree_depth;
    std::memcpy (&tree_depth, data, sizeof tree_depth);
    data += sizeof tree_depth;
    const int nodes_height = (1 << tree_depth) / tree_width;

    const char * fs_source = reinterpret_cast<const char *> (source_tree_walk_fsh);
    std::string fs_macros =
        (boost::format("#define TREE_DEPTH %1%\n#define NODES_HEIGHT %2%\n") % tree_depth % nodes_height).str();
    std::vector<const char *> fs_sources;
    fs_sources.push_back(fs_macros.c_str());
    fs_sources.push_back(fs_source);

    helper.reset(new GlesHelper(fs_sources));

    std::vector<unsigned char> offsets1_buffer, offsets2_buffer, thresholds_buffer;
    offsets1_buffer.resize(4 * tree_width * tree_width);
    offsets2_buffer.resize(4 * tree_width * tree_width);
    thresholds_buffer.resize(4 * tree_width * tree_width);

    for (int i = 0; i < (1 << tree_depth) - 1; ++i)
    {
      std::memcpy(&offsets1_buffer[4 * i], data, 4);
      std::memcpy(&offsets2_buffer[4 * i], data + 4, 4);
      std::memcpy(&thresholds_buffer[4 * i], data + 8, 2);
      data += 10;
    }

    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &offsets1_buffer.front()),
          "offsets1");
    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &offsets2_buffer.front()),
          "offsets2");
    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &thresholds_buffer.front()),
          "thresholds");

    std::vector<unsigned char> leaves_buffer(4 * tree_width * tree_width);

    for (unsigned i = 0; i < (1 << 20); ++i)
    {
      std::memcpy(&leaves_buffer[4 * i], data, 1);
      data += 1;
    }

    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &leaves_buffer.front()),
          "leaves");

    depth_image_tex = helper->addTexture();
    helper->bindTextureToUniform(depth_image_tex, "depth_image");

    labels_tex = helper->addTexture();
    helper->bindTextureToOutput(labels_tex);
  }

  void
  eval(const DepthImage & image, std::vector<Label> & labels) const
  {
    std::vector<unsigned char> depth_image_buffer(4 * image.getWidth() * image.getHeight());

    for (std::size_t i = 0; i < image.getWidth() * image.getHeight(); ++i)
    {
      Depth d = image.getDepth(i % image.getWidth(), i / image.getWidth());
      *reinterpret_cast<Depth *> (&depth_image_buffer[4 * i]) = d;
    }

    helper->setTextureData(depth_image_tex,
                           image.getWidth(), image.getHeight(), &depth_image_buffer.front());

    helper->setTextureData(labels_tex,
                           image.getWidth(), image.getHeight(), NULL);

    helper->setUniform("image_width", image.getWidth());
    helper->setUniform("image_height", image.getHeight());

    std::vector<unsigned char> labels_buffer(depth_image_buffer.size());

    helper->run(image.getWidth(), image.getHeight(), &labels_buffer.front());

    for (std::size_t i = 0; i < image.getWidth() * image.getHeight(); ++i)
      labels[i] = labels_buffer[4 * i];
  }
};

int maxElementNoTie(int num, int * elements)
{
  int max_element = 0;
  int max = elements[max_element];

  for (int i = 1; i < num; ++i)
  {
    int val = elements[i];
    if (max < val) { max_element = i; max = val; }
    else if (max == val) { max_element = -1; }
  }

  return max_element;
}

BodyPartsRecognizer::BodyPartsRecognizer(std::size_t num_trees, const char * trees[])
{
  this->trees.resize(num_trees);

  for (std::size_t i = 0; i < num_trees; ++i)
    this->trees[i].reset(new Tree(trees[i]));
}

struct ConsensusHelper
{
private:
  const std::vector<std::vector<Label> > & multi_labels;
  std::vector<Label> & labels;
  const DepthImage & depth_image;

public:
  ConsensusHelper(
      const std::vector<std::vector<Label> > & multi_labels,
      std::vector<Label> & labels,
      const DepthImage & depth_image
  )
    : multi_labels(multi_labels), labels(labels), depth_image(depth_image)
  {
  }

  void operator ()(const tbb::blocked_range2d<unsigned> & range) const
  {
    for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
      for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
      {
        int bins[Labels::NUM_LABELS] = { 0 };
        std::size_t i = x + y * depth_image.getWidth();

        for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
          ++bins[multi_labels[ti][i]];

        int consensus = maxElementNoTie(Labels::NUM_LABELS, bins);

        if (consensus == -1)
        {
          std::fill (bins, bins + Labels::NUM_LABELS, 0);
          Depth d = depth_image.getDepth (x, y);

          for (int off_x = -1; off_x <= 1; ++off_x)
            for (int off_y = -1; off_y <= 1; ++off_y)
            {
              Depth off_d = depth_image.getDepth (x + off_x, y + off_y);

              if (std::abs (d - off_d) < 50)
                for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
                  ++bins[multi_labels[ti][i]];
            }

          labels[i] = std::max_element (bins, bins + Labels::NUM_LABELS) - bins;
        }
        else
        {
          labels[i] = consensus;
        }
      }
  }
};

void
BodyPartsRecognizer::recognize(const RGBDImage & image, std::vector<Label> & labels)
{
  labels.clear ();
  labels.resize (image.width * image.height);

  DepthImage depth_image (image);

  Stopwatch watch_threshold;

  depth_image.applyThreshold (500);

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Thresholding: %d ms", watch_threshold.elapsedMs());

  std::vector<std::vector<Label> > multi_labels (trees.size ());

  for (std::size_t ti = 0; ti < trees.size (); ++ti)
  {
    Stopwatch watch_evaluation;

    multi_labels[ti].resize (labels.size ());
    trees[ti]->eval (depth_image, multi_labels[ti]);

    __android_log_print(ANDROID_LOG_INFO, "BPR", "Evaluating tree %d: %d ms", ti, watch_evaluation.elapsedMs());
  }

  Stopwatch watch_consensus;

#if 0
  for (std::size_t i = 0; i < labels.size (); ++i)
  {
    int bins[Labels::NUM_LABELS] = { 0 };

    for (std::size_t ti = 0; ti < trees.size (); ++ti)
      ++bins[multi_labels[ti][i]];

    int consensus = maxElementNoTie(Labels::NUM_LABELS, bins);

    if (consensus == -1)
    {
      std::fill (bins, bins + Labels::NUM_LABELS, 0);
      unsigned x = i % image.width, y = i / image.width;
      Depth d = depth_image.getDepth (x, y);

      for (int off_x = -1; off_x <= 1; ++off_x)
        for (int off_y = -1; off_y <= 1; ++off_y)
        {
          Depth off_d = depth_image.getDepth (x + off_x, y + off_y);

          if (std::abs (d - off_d) < 50)
            for (std::size_t ti = 0; ti < trees.size (); ++ti)
              ++bins[multi_labels[ti][i]];
        }

      labels[i] = std::max_element (bins, bins + Labels::NUM_LABELS) - bins;
    }
    else
    {
      labels[i] = consensus;
    }
  }
#else
  tbb::parallel_for(
        tbb::blocked_range2d<unsigned>(0, depth_image.getHeight(), 0, depth_image.getWidth()),
        ConsensusHelper(multi_labels, labels, depth_image)
  );
#endif

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Finding consensus: %d ms", watch_consensus.elapsedMs());
}
<commit_msg>Deleted more commented out chunks.<commit_after>#include <algorithm>
#include <cstring>
#include <limits>
#include <memory>

#include <android/log.h>

#include <boost/format.hpp>
#include <boost/utility.hpp>

#include <tbb/blocked_range2d.h>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>

#include "body_parts_recognizer.h"
#include "gles_helper.h"
#include "rgbd_image.h"
#include "sources.h"
#include "stopwatch.h"

const Depth BACKGROUND_DEPTH = std::numeric_limits<Depth>::max();

struct DepthImage
{
private:

  unsigned width, height;
  std::vector<Depth> depths;

public:

  DepthImage(const RGBDImage & image)
    : width(image.width), height(image.height), depths(width * height)
  {
    for (std::size_t i = 0; i < depths.size(); ++i)
      depths[i] = image.pixels[i].d == 0 ? BACKGROUND_DEPTH : image.pixels[i].d; // we consider 0 to be invalid depth
  }

  void
  applyThreshold(int threshold)
  {
    Depth min_depth = *std::min_element(depths.begin (), depths.end ());

    for (std::size_t i = 0; i < depths.size (); ++i)
      depths[i] = depths[i] <= min_depth + threshold ? depths[i] : BACKGROUND_DEPTH;
  }

  Depth
  getDepth(int x, int y) const
  {
    if (x < 0 || x >= int (width) || y < 0 || y >= int (height))
      return BACKGROUND_DEPTH;

    return depths[x + width * y];
  }

  unsigned getWidth() const { return width; }
  unsigned getHeight() const { return height; }
};

struct DecisionTreeCPU
{
  tbb::task_scheduler_init tbb_init;

  struct Offsets
  {
    boost::int16_t du1, dv1, du2, dv2;
  };

  struct Node
  {
    Offsets offsets;
    boost::int16_t threshold;
  };

  boost::uint16_t depth;
  std::vector<Node> nodes;
  std::vector<Label> leaves;

  DecisionTreeCPU(const char * data)
  {
    std::memcpy (&depth, data, sizeof depth);
    data += sizeof depth;

    nodes.resize ((1 << depth) - 1);
    std::memcpy (&nodes.front (), data, nodes.size () * sizeof (Node));
    data += nodes.size () * sizeof (Node);

    leaves.resize (1 << depth);
    std::memcpy (&leaves.front (), data, leaves.size () * sizeof (Label));
    data += leaves.size () * sizeof (Label);
  }

  Label
  walk(const DepthImage & image, int x, int y) const
  {
    unsigned nid = 0;
    Depth d0 = image.getDepth(x, y);
    float scale = 1000.0f / d0;

    for(int node_depth = 0; node_depth < depth; ++node_depth)
    {
      const Node & node = nodes[nid];

      Depth d1 = image.getDepth (x + node.offsets.du1 * scale, y + node.offsets.dv1 * scale);
      Depth d2 = image.getDepth (x + node.offsets.du2 * scale, y + node.offsets.dv2 * scale);

      int feature = int (d1) - int (d2);

      if (feature > node.threshold)
        nid = nid * 2 + 2;
      else
        nid = nid * 2 + 1;
    }

    return leaves[nid - nodes.size()];
  }

  struct WalkHelper
  {
  private:
    const DecisionTreeCPU & tree;
    const DepthImage & image;
    std::vector<Label> & labels;

  public:
    WalkHelper(const DecisionTreeCPU & tree, const DepthImage & image, std::vector<Label> & labels)
      : tree(tree), image(image), labels(labels)
    {
    }

    void
    operator () (const tbb::blocked_range2d<unsigned> & range) const
    {
      for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
        for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
          labels[x + y * image.getWidth()] = image.getDepth(x, y) == BACKGROUND_DEPTH ?
                Labels::Background : tree.walk(image, x, y);
    }
  };

  void
  eval(const DepthImage & image, std::vector<Label> & labels) const
  {
    tbb::parallel_for(
          tbb::blocked_range2d<unsigned>(0, image.getHeight(), 0, image.getWidth()),
          WalkHelper(*this, image, labels)
    );
  }
};

struct DecisionTreeGPU : boost::noncopyable
{
private:
  std::auto_ptr<GlesHelper> helper;
  GLuint depth_image_tex, labels_tex;

public:
  DecisionTreeGPU(const char * data)
  {
    const int tree_width = 2048;
    boost::uint16_t tree_depth;
    std::memcpy (&tree_depth, data, sizeof tree_depth);
    data += sizeof tree_depth;
    const int nodes_height = (1 << tree_depth) / tree_width;

    const char * fs_source = reinterpret_cast<const char *> (source_tree_walk_fsh);
    std::string fs_macros =
        (boost::format("#define TREE_DEPTH %1%\n#define NODES_HEIGHT %2%\n") % tree_depth % nodes_height).str();
    std::vector<const char *> fs_sources;
    fs_sources.push_back(fs_macros.c_str());
    fs_sources.push_back(fs_source);

    helper.reset(new GlesHelper(fs_sources));

    std::vector<unsigned char> offsets1_buffer, offsets2_buffer, thresholds_buffer;
    offsets1_buffer.resize(4 * tree_width * tree_width);
    offsets2_buffer.resize(4 * tree_width * tree_width);
    thresholds_buffer.resize(4 * tree_width * tree_width);

    for (int i = 0; i < (1 << tree_depth) - 1; ++i)
    {
      std::memcpy(&offsets1_buffer[4 * i], data, 4);
      std::memcpy(&offsets2_buffer[4 * i], data + 4, 4);
      std::memcpy(&thresholds_buffer[4 * i], data + 8, 2);
      data += 10;
    }

    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &offsets1_buffer.front()),
          "offsets1");
    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &offsets2_buffer.front()),
          "offsets2");
    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &thresholds_buffer.front()),
          "thresholds");

    std::vector<unsigned char> leaves_buffer(4 * tree_width * tree_width);

    for (unsigned i = 0; i < (1 << 20); ++i)
    {
      std::memcpy(&leaves_buffer[4 * i], data, 1);
      data += 1;
    }

    helper->bindTextureToUniform(
          helper->addTexture(tree_width, tree_width, &leaves_buffer.front()),
          "leaves");

    depth_image_tex = helper->addTexture();
    helper->bindTextureToUniform(depth_image_tex, "depth_image");

    labels_tex = helper->addTexture();
    helper->bindTextureToOutput(labels_tex);
  }

  void
  eval(const DepthImage & image, std::vector<Label> & labels) const
  {
    std::vector<unsigned char> depth_image_buffer(4 * image.getWidth() * image.getHeight());

    for (std::size_t i = 0; i < image.getWidth() * image.getHeight(); ++i)
    {
      Depth d = image.getDepth(i % image.getWidth(), i / image.getWidth());
      *reinterpret_cast<Depth *> (&depth_image_buffer[4 * i]) = d;
    }

    helper->setTextureData(depth_image_tex,
                           image.getWidth(), image.getHeight(), &depth_image_buffer.front());

    helper->setTextureData(labels_tex,
                           image.getWidth(), image.getHeight(), NULL);

    helper->setUniform("image_width", image.getWidth());
    helper->setUniform("image_height", image.getHeight());

    std::vector<unsigned char> labels_buffer(depth_image_buffer.size());

    helper->run(image.getWidth(), image.getHeight(), &labels_buffer.front());

    for (std::size_t i = 0; i < image.getWidth() * image.getHeight(); ++i)
      labels[i] = labels_buffer[4 * i];
  }
};

int maxElementNoTie(int num, int * elements)
{
  int max_element = 0;
  int max = elements[max_element];

  for (int i = 1; i < num; ++i)
  {
    int val = elements[i];
    if (max < val) { max_element = i; max = val; }
    else if (max == val) { max_element = -1; }
  }

  return max_element;
}

BodyPartsRecognizer::BodyPartsRecognizer(std::size_t num_trees, const char * trees[])
{
  this->trees.resize(num_trees);

  for (std::size_t i = 0; i < num_trees; ++i)
    this->trees[i].reset(new Tree(trees[i]));
}

struct ConsensusHelper
{
private:
  const std::vector<std::vector<Label> > & multi_labels;
  std::vector<Label> & labels;
  const DepthImage & depth_image;

public:
  ConsensusHelper(
      const std::vector<std::vector<Label> > & multi_labels,
      std::vector<Label> & labels,
      const DepthImage & depth_image
  )
    : multi_labels(multi_labels), labels(labels), depth_image(depth_image)
  {
  }

  void operator ()(const tbb::blocked_range2d<unsigned> & range) const
  {
    for (unsigned y = range.rows().begin(); y < range.rows().end(); ++y)
      for (unsigned x = range.cols().begin(); x < range.cols().end(); ++x)
      {
        int bins[Labels::NUM_LABELS] = { 0 };
        std::size_t i = x + y * depth_image.getWidth();

        for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
          ++bins[multi_labels[ti][i]];

        int consensus = maxElementNoTie(Labels::NUM_LABELS, bins);

        if (consensus == -1)
        {
          std::fill (bins, bins + Labels::NUM_LABELS, 0);
          Depth d = depth_image.getDepth (x, y);

          for (int off_x = -1; off_x <= 1; ++off_x)
            for (int off_y = -1; off_y <= 1; ++off_y)
            {
              Depth off_d = depth_image.getDepth (x + off_x, y + off_y);

              if (std::abs (d - off_d) < 50)
                for (std::size_t ti = 0; ti < multi_labels.size (); ++ti)
                  ++bins[multi_labels[ti][i]];
            }

          labels[i] = std::max_element (bins, bins + Labels::NUM_LABELS) - bins;
        }
        else
        {
          labels[i] = consensus;
        }
      }
  }
};

void
BodyPartsRecognizer::recognize(const RGBDImage & image, std::vector<Label> & labels)
{
  labels.clear ();
  labels.resize (image.width * image.height);

  DepthImage depth_image (image);

  Stopwatch watch_threshold;

  depth_image.applyThreshold (500);

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Thresholding: %d ms", watch_threshold.elapsedMs());

  std::vector<std::vector<Label> > multi_labels (trees.size ());

  for (std::size_t ti = 0; ti < trees.size (); ++ti)
  {
    Stopwatch watch_evaluation;

    multi_labels[ti].resize (labels.size ());
    trees[ti]->eval (depth_image, multi_labels[ti]);

    __android_log_print(ANDROID_LOG_INFO, "BPR", "Evaluating tree %d: %d ms", ti, watch_evaluation.elapsedMs());
  }

  Stopwatch watch_consensus;

  tbb::parallel_for(
        tbb::blocked_range2d<unsigned>(0, depth_image.getHeight(), 0, depth_image.getWidth()),
        ConsensusHelper(multi_labels, labels, depth_image)
  );

  __android_log_print(ANDROID_LOG_INFO, "BPR", "Finding consensus: %d ms", watch_consensus.elapsedMs());
}
<|endoftext|>


<commit_before>#include <SofaValidation/Monitor.h>
using sofa::component::misc::Monitor;
#include <SofaBaseMechanics/MechanicalObject.h>
using sofa::component::container::MechanicalObject;
#include <SofaTest/Sofa_test.h>

#include <SofaSimulationGraph/DAGSimulation.h>
#include <sofa/simulation/Simulation.h>
using sofa::core::objectmodel::BaseObject;
using sofa::simulation::Simulation;
using sofa::simulation::Node;

#include <SofaSimulationCommon/SceneLoaderXML.h>
using sofa::simulation::SceneLoaderXML;
using sofa::core::ExecParams;

#include <fstream>
#include <streambuf>
#include <string>
#include <cstdio>

namespace sofa
{
struct MonitorTest : public Monitor<Rigid3>
{
    void testInit(MechanicalObject<Rigid3>* mo)
    {
        const Rigid3::VecCoord& i1 = *m_X;
        const Rigid3::VecCoord& i2 = mo->x.getValue();

        EXPECT_TRUE(i1.size() == i2.size());
        for (size_t i = 0; i < i1.size(); ++i) EXPECT_EQ(i1[i], i2[i]);
    }

    void testModif(MechanicalObject<Rigid3>* mo)
    {
        helper::vector<unsigned int> idx = d_indices.getValue();
        const Rigid3::VecCoord& i1 = *m_X;
        const Rigid3::VecCoord& i2 = mo->x.getValue();
        const Rigid3::VecDeriv& f1 = *m_F;
        const Rigid3::VecDeriv& f2 = mo->f.getValue();
        const Rigid3::VecDeriv& v1 = *m_V;
        const Rigid3::VecDeriv& v2 = mo->v.getValue();

        EXPECT_TRUE(idx.size() <= i2.size());
        for (size_t i = 0; i < idx.size(); ++i) EXPECT_EQ(i1[idx[i]], i2[idx[i]]);

        for (size_t i = 0; i < idx.size(); ++i) EXPECT_EQ(f1[idx[i]], f2[idx[i]]);

        for (size_t i = 0; i < idx.size(); ++i) EXPECT_EQ(v1[idx[i]], v2[idx[i]]);
    }
};

struct Monitor_test : public sofa::Sofa_test<>
{
    sofa::simulation::Node::SPtr root;
    sofa::simulation::SceneLoaderXML loader;
    MonitorTest* monitor;
    MechanicalObject<Rigid3>::SPtr mo;

    Monitor_test() {}

    void testInit()
    {
        // Checks that monitor gets the correct values at init
        monitor->testInit(mo.get());
    }

    std::string readWholeFile(const std::string& fileName)
    {
        std::ifstream t(fileName);
        std::string str;
        EXPECT_TRUE(t.is_open());
        t.seekg(0, std::ios::end);
        str.reserve(t.tellg());
        t.seekg(0, std::ios::beg);

        str.assign((std::istreambuf_iterator<char>(t)),
                   std::istreambuf_iterator<char>());
        return str;
    }

    void testModif()
    {
        std::string str_x =
                "# Gnuplot File : positions of 1 particle(s) Monitored\n# 1st Column : "
                "time, others : particle(s) number 0 \n1	-3.5 -12.4182 -3.5 0 0 "
                "0 1	\n2	-3.5 -29.4438 -3.5 0 0 0 1	\n3	-3.5 -53.8398 "
                "-3.5 0 0 0 1	\n4	-3.5 -84.9362 -3.5 0 0 0 1	\n5	-3.5 "
                "-122.124 -3.5 0 0 0 1	\n6	-3.5 -164.849 -3.5 0 0 0 1	"
                "\n7	"
                "-3.5 -212.608 -3.5 0 0 0 1	\n8	-3.5 -264.944 -3.5 0 0 0 "
                "1	"
                "\n9	-3.5 -321.44 -3.5 0 0 0 1	\n10	-3.5 -381.718 -3.5 0 0 "
                "0 1	\n";
        std::string str_f =
                "# Gnuplot File : forces of 1 particle(s) Monitored\n# 1st Column : "
                "time, others : particle(s) number 0 \n1	0 -0.363333 0 0 0 "
                "0	"
                "\n2	0 -0.363333 0 0 0 0	\n3	0 -0.363333 0 0 0 0	"
                "\n4	"
                "0 -0.363333 0 0 0 0	\n5	0 -0.363333 0 0 0 0	\n6	0 "
                "-0.363333 0 0 0 0	\n7	0 -0.363333 0 0 0 0	\n8	0 "
                "-0.363333 0 0 0 0	\n9	0 -0.363333 0 0 0 0	\n10	0 "
                "-0.363333 0 0 0 0	\n";
        std::string str_v =
                "# Gnuplot File : velocities of 1 particle(s) Monitored\n# 1st Column "
                ": time, others : particle(s) number 0 \n1	0 -8.91818 0 0 0 "
                "0	"
                "\n2	0 -17.0256 0 0 0 0	\n3	0 -24.396 0 0 0 0	"
                "\n4	"
                "0 -31.0964 0 0 0 0	\n5	0 -37.1876 0 0 0 0	\n6	0 "
                "-42.7251 0 0 0 0	\n7	0 -47.7592 0 0 0 0	\n8	0 "
                "-52.3356 0 0 0 0	\n9	0 -56.496 0 0 0 0	\n10	0 "
                "-60.2782 0 0 0 0	\n";

        // make a few steps before checkinf if values are correctly updated in
        // Monitor
        for (int i = 0; i < 10; ++i)
            simulation::getSimulation()->animate(root.get(), 1.0);

        monitor->testModif(mo.get());

        std::string s_x = readWholeFile(monitor->d_fileName.getFullPath() + "_x.txt");
        std::string s_f = readWholeFile(monitor->d_fileName.getFullPath() + "_f.txt");
        std::string s_v = readWholeFile(monitor->d_fileName.getFullPath() + "_v.txt");
        EXPECT_EQ(s_x, str_x);
        EXPECT_EQ(s_f, str_f);
        EXPECT_EQ(s_v, str_v);
        std::remove(std::string(monitor->d_fileName.getFullPath() + "_x.txt").c_str());
        std::remove(std::string(monitor->d_fileName.getFullPath() + "_f.txt").c_str());
        std::remove(std::string(monitor->d_fileName.getFullPath() + "_v.txt").c_str());
    }
    void SetUp()
    {
        std::string scene =
                "<Node name='root' gravity='0 -9.81 0'>"
                "<DefaultAnimationLoop/>"
                "<Node name='node'>"
                "<EulerImplicit rayleighStiffness='0' printLog='false'/>"
                "<CGLinearSolver iterations='100' threshold='0.00000001' "
                "tolerance='1e-5'/>"
                "<MeshGmshLoader name='loader' filename='mesh/smCube27.msh' "
                "createSubelements='true' />"
                "<MechanicalObject template='Rigid3d' src='@loader' name='MO' />"
                "<Monitor template='Rigid3d' name='monitor' listening='1' indices='0' "
                "ExportPositions='true' ExportVelocities='true' ExportForces='true' />"
                "<UniformMass totalmass='1' />"
                "</Node>"
                "</Node>";

        root = SceneLoaderXML::loadFromMemory("MonitorTest", scene.c_str(),
                                              scene.size());
        root->init(sofa::core::ExecParams::defaultInstance());

        std::string s = "/node/monitor";
        Monitor<Rigid3>* ptr = NULL;
        ptr = root->get<Monitor<Rigid3> >(s);
        EXPECT_FALSE(ptr == NULL);

        monitor = reinterpret_cast<MonitorTest*>(ptr);
        EXPECT_FALSE(monitor == 0);

        root->get<MechanicalObject<Rigid3> >(mo, "/node/MO");
        EXPECT_FALSE(mo == 0);
    }

    void TearDown()
    {
    }
};

/// Checks whether the video is well loaded and 1st frame retrieved at init()
TEST_F(Monitor_test, testInit) { this->testInit(); }
TEST_F(Monitor_test, testModif) { this->testModif(); }

}  // namespace sofa
<commit_msg>[SofaValidation] FIX Monitor_test failure<commit_after>#include <SofaValidation/Monitor.h>
using sofa::component::misc::Monitor;
#include <SofaBaseMechanics/MechanicalObject.h>
using sofa::component::container::MechanicalObject;
#include <SofaTest/Sofa_test.h>

#include <SofaSimulationGraph/DAGSimulation.h>
#include <sofa/simulation/Simulation.h>
using sofa::core::objectmodel::BaseObject;
using sofa::simulation::Simulation;
using sofa::simulation::Node;

#include <SofaSimulationCommon/SceneLoaderXML.h>
using sofa::simulation::SceneLoaderXML;
using sofa::core::ExecParams;

#include <fstream>
#include <streambuf>
#include <string>
#include <cstdio>

namespace sofa
{
struct MonitorTest : public Monitor<Rigid3>
{
    void testInit(MechanicalObject<Rigid3>* mo)
    {
        const Rigid3::VecCoord& i1 = *m_X;
        const Rigid3::VecCoord& i2 = mo->x.getValue();

        EXPECT_TRUE(i1.size() == i2.size());
        for (size_t i = 0; i < i1.size(); ++i) EXPECT_EQ(i1[i], i2[i]);
    }

    void testModif(MechanicalObject<Rigid3>* mo)
    {
        helper::vector<unsigned int> idx = d_indices.getValue();
        const Rigid3::VecCoord& i1 = *m_X;
        const Rigid3::VecCoord& i2 = mo->x.getValue();
        const Rigid3::VecDeriv& f1 = *m_F;
        const Rigid3::VecDeriv& f2 = mo->f.getValue();
        const Rigid3::VecDeriv& v1 = *m_V;
        const Rigid3::VecDeriv& v2 = mo->v.getValue();

        EXPECT_TRUE(idx.size() <= i2.size());
        for (size_t i = 0; i < idx.size(); ++i) EXPECT_EQ(i1[idx[i]], i2[idx[i]]);

        for (size_t i = 0; i < idx.size(); ++i) EXPECT_EQ(f1[idx[i]], f2[idx[i]]);

        for (size_t i = 0; i < idx.size(); ++i) EXPECT_EQ(v1[idx[i]], v2[idx[i]]);
    }
};

struct Monitor_test : public sofa::Sofa_test<>
{
    sofa::simulation::Node::SPtr root;
    sofa::simulation::SceneLoaderXML loader;
    MonitorTest* monitor;
    MechanicalObject<Rigid3>::SPtr mo;

    Monitor_test() {}

    void testInit()
    {
        // Checks that monitor gets the correct values at init
        monitor->testInit(mo.get());
    }

    std::string readWholeFile(const std::string& fileName)
    {
        std::ifstream t(fileName);
        std::string str;
        EXPECT_TRUE(t.is_open());
        t.seekg(0, std::ios::end);
        str.reserve(t.tellg());
        t.seekg(0, std::ios::beg);

        str.assign((std::istreambuf_iterator<char>(t)),
                   std::istreambuf_iterator<char>());
        return str;
    }

    void testModif()
    {
        std::string str_x =
                "# Gnuplot File : positions of 1 particle(s) Monitored\n# 1st Column : "
                "time, others : particle(s) number 0 \n1	-3.5 -12.4182 -3.5 0 0 "
                "0 1	\n2	-3.5 -29.4438 -3.5 0 0 0 1	\n3	-3.5 -53.8398 "
                "-3.5 0 0 0 1	\n4	-3.5 -84.9362 -3.5 0 0 0 1	\n5	-3.5 "
                "-122.124 -3.5 0 0 0 1	\n6	-3.5 -164.849 -3.5 0 0 0 1	"
                "\n7	"
                "-3.5 -212.608 -3.5 0 0 0 1	\n8	-3.5 -264.944 -3.5 0 0 0 "
                "1	"
                "\n9	-3.5 -321.44 -3.5 0 0 0 1	\n10	-3.5 -381.718 -3.5 0 0 "
                "0 1	\n";
        std::string str_f =
                "# Gnuplot File : forces of 1 particle(s) Monitored\n# 1st Column : "
                "time, others : particle(s) number 0 \n1	0 -0.363333 0 0 0 "
                "0	"
                "\n2	0 -0.363333 0 0 0 0	\n3	0 -0.363333 0 0 0 0	"
                "\n4	"
                "0 -0.363333 0 0 0 0	\n5	0 -0.363333 0 0 0 0	\n6	0 "
                "-0.363333 0 0 0 0	\n7	0 -0.363333 0 0 0 0	\n8	0 "
                "-0.363333 0 0 0 0	\n9	0 -0.363333 0 0 0 0	\n10	0 "
                "-0.363333 0 0 0 0	\n";
        std::string str_v =
                "# Gnuplot File : velocities of 1 particle(s) Monitored\n# 1st Column "
                ": time, others : particle(s) number 0 \n1	0 -8.91818 0 0 0 "
                "0	"
                "\n2	0 -17.0256 0 0 0 0	\n3	0 -24.396 0 0 0 0	"
                "\n4	"
                "0 -31.0964 0 0 0 0	\n5	0 -37.1876 0 0 0 0	\n6	0 "
                "-42.7251 0 0 0 0	\n7	0 -47.7592 0 0 0 0	\n8	0 "
                "-52.3356 0 0 0 0	\n9	0 -56.496 0 0 0 0	\n10	0 "
                "-60.2782 0 0 0 0	\n";

        // make a few steps before checkinf if values are correctly updated in
        // Monitor
        for (int i = 0; i < 10; ++i)
            simulation::getSimulation()->animate(root.get(), 1.0);

        monitor->testModif(mo.get());

        std::string s_x = readWholeFile(monitor->d_fileName.getFullPath() + "_x.txt");
        std::string s_f = readWholeFile(monitor->d_fileName.getFullPath() + "_f.txt");
        std::string s_v = readWholeFile(monitor->d_fileName.getFullPath() + "_v.txt");
        EXPECT_EQ(s_x, str_x);
        EXPECT_EQ(s_f, str_f);
        EXPECT_EQ(s_v, str_v);
        std::remove(std::string(monitor->d_fileName.getFullPath() + "_x.txt").c_str());
        std::remove(std::string(monitor->d_fileName.getFullPath() + "_f.txt").c_str());
        std::remove(std::string(monitor->d_fileName.getFullPath() + "_v.txt").c_str());
    }
    void SetUp()
    {
        std::string scene =
                "<Node name='root' gravity='0 -9.81 0'>"
                "<DefaultAnimationLoop/>"
                "<Node name='node'>"
                "<EulerImplicit rayleighStiffness='0' printLog='false' rayleighMass='0.1'/>"
                "<CGLinearSolver iterations='100' threshold='0.00000001' "
                "tolerance='1e-5'/>"
                "<MeshGmshLoader name='loader' filename='mesh/smCube27.msh' "
                "createSubelements='true' />"
                "<MechanicalObject template='Rigid3d' src='@loader' name='MO' />"
                "<Monitor template='Rigid3d' name='monitor' listening='1' indices='0' "
                "ExportPositions='true' ExportVelocities='true' ExportForces='true' />"
                "<UniformMass totalmass='1' />"
                "</Node>"
                "</Node>";

        root = SceneLoaderXML::loadFromMemory("MonitorTest", scene.c_str(),
                                              scene.size());
        root->init(sofa::core::ExecParams::defaultInstance());

        std::string s = "/node/monitor";
        Monitor<Rigid3>* ptr = NULL;
        ptr = root->get<Monitor<Rigid3> >(s);
        EXPECT_FALSE(ptr == NULL);

        monitor = reinterpret_cast<MonitorTest*>(ptr);
        EXPECT_FALSE(monitor == 0);

        root->get<MechanicalObject<Rigid3> >(mo, "/node/MO");
        EXPECT_FALSE(mo == 0);
    }

    void TearDown()
    {
    }
};

/// Checks whether the video is well loaded and 1st frame retrieved at init()
TEST_F(Monitor_test, testInit) { this->testInit(); }
TEST_F(Monitor_test, testModif) { this->testModif(); }

}  // namespace sofa
<|endoftext|>


<commit_before>#include <math.h>
#include <stdlib.h>

#include "network_model_analytical.h"
#include "network_model_analytical_params.h"
#include "message_types.h"
#include "config.h"
#include "core.h"
#include "performance_model.h"
#include "transport.h"
#include "lock.h"

#define IS_NAN(x) (!((x < 0.0) || (x >= 0.0)))

using namespace std;

NetworkModelAnalytical::NetworkModelAnalytical(Network *net, EStaticNetwork net_type)
      : NetworkModel(net)
      , _bytesSent(0)
      , _cyclesProc(0)
      , _cyclesLatency(0)
      , _cyclesContention(0)
      , _globalUtilization(0)
      , _localUtilizationLastUpdate(0)
      , _localUtilizationFlitsSent(0)
      , m_enabled(true)
{
   getNetwork()->registerCallback(MCP_UTILIZATION_UPDATE_TYPE,
                                  receiveMCPUpdate,
                                  this);

   // Create network parameters
   m_params.Tw2 = 1; // single cycle between nodes in 2d mesh
   m_params.s = 1; // single cycle switching time
   m_params.n = 1; // 2-d mesh network
   m_params.W = 32; // 32-bit wide channels
   m_params.update_interval = 100000;
   m_params.proc_cost = (net_type == STATIC_NETWORK_MEMORY) ? 0 : 100;
}

NetworkModelAnalytical::~NetworkModelAnalytical()
{
   getNetwork()->unregisterCallback(MCP_UTILIZATION_UPDATE_TYPE);
}

void NetworkModelAnalytical::routePacket(const NetPacket &pkt,
      std::vector<Hop> &nextHops)
{
   // basic magic network routing, with two additions
   // (1) compute latency of packet
   // (2) update utilization

   PerformanceModel *perf = getNetwork()->getCore()->getPerformanceModel();

   Hop h;
   h.dest = pkt.receiver;

   UInt64 network_latency = computeLatency(pkt);
   LOG_PRINT ("Network Latency = %llu", network_latency);
   h.time = pkt.time + network_latency;

   nextHops.push_back(h);

   if (m_params.proc_cost > 0)
      perf->queueDynamicInstruction(new DynamicInstruction(m_params.proc_cost));
   _cyclesProc += m_params.proc_cost;

   updateUtilization();

   _bytesSent += pkt.length;
}

UInt64 NetworkModelAnalytical::computeLatency(const NetPacket &packet)
{
   if (!m_enabled)
      return 0;

   // We model a unidirectional network with end-around connections
   // using the network model in "Limits on Interconnect Performance"
   // (by Anant). Currently, this ignores communication locality and
   // sets static values for all parameters. We also assume uniform
   // packet distribution, so we do not take the packet destination
   // into account.
   //
   // We combine the contention model (eq. 12) with the model for
   // limited bisection width (sec. 4.2).

   // TODO: Fix (if necessary) distance calculation for uneven
   // topologies, i.e. 8-node 2d mesh or 10-node 3d mesh.

   // TODO: Confirm model for latency computed based on actual number
   // of network hops.

   // Retrieve parameters
   double Tw2 = m_params.Tw2;
   double s = m_params.s;
   int n = m_params.n;
   double W = m_params.W;
   double p = _globalUtilization;
   assert(!IS_NAN(_globalUtilization));

   // This lets us derive the latency, ignoring contention

   int N;                    // number of nodes in the network
   double k;                 // length of mesh in one dimension
   double kd;                // number of hops per dimension
   double time_per_hop;      // time spent in one hop through the network
   double B;                 // number of flits for packet
   double hops_in_network;   // number of nodes visited
   double Tb;                // latency, without contention

   N = Config::getSingleton()->getTotalCores();
   k = pow(N, 1./n);                  // pg 5
   kd = k/2.;                         // pg 5 (note this will be
   // different for different network configurations...say,
   // bidirectional networks)
   time_per_hop = s + pow(k, n/2.-1.);  // pg 6
   B = ceil(packet.length * 8. / W);

   // Compute the number of hops based on src, dest
   // Based on this eqn:
   // node number = x1 + x2 k + x3 k^2 + ... + xn k^(n-1)
   int network_distance = 0;
   int src = packet.sender;
   int dest = packet.receiver;
   int ki = (int)k;
   for (int i = 0; i < n; i++)
   {
      div_t q1, q2;
      q1 = div(src, ki);
      q2 = div(dest, ki);
      // This models a unidirectional network distance
      // Should use abs() for bidirectional.
      if (q1.rem > q2.rem)
         network_distance += ki - (q1.rem - q2.rem);
      else
         network_distance += q2.rem - q1.rem;
      src = q1.quot;
      dest = q2.quot;
   }
   hops_in_network = network_distance + B; // B flits must be sent
   // (with wormhole routing, this adds B hops)

   Tb = Tw2 * time_per_hop * hops_in_network; // pg 5

   // Now to model contention... (sec 3.2)
   double w;                 // delay due to contention

   w  = p * B / (1. - p);
   w *= (kd-1.)/(kd*kd);
   w *= 1.+1./((double)n);

   if (w < 0) w = 0; // correct negative contention values for small
   // networks

   double hops_with_contention;
   double Tc;                // latency, with contention
   hops_with_contention = network_distance * (1. + w) + B;
   Tc = Tw2 * time_per_hop * hops_with_contention;

   // Computation finished...
   _lock.acquire();

   UInt64 Tci = (UInt64)(ceil(Tc));
   _cyclesLatency += Tci;
   _cyclesContention += (UInt64)(Tc - Tb);

   // ** update utilization counter **
   // we must account for the usage throughout the mesh
   // which means that we must include the # of hops
   _localUtilizationFlitsSent += (UInt64)(B * hops_in_network);

   _lock.release();

   return Tci;
}

void NetworkModelAnalytical::outputSummary(ostream &out)
{
   out << "    bytes sent: " << _bytesSent << endl;
   out << "    cycles spent proc: " << _cyclesProc << endl;
   out << "    cycles spent latency: " << _cyclesLatency << endl;
   out << "    cycles spent contention: " << _cyclesContention << endl;
}

struct UtilizationMessage
{
   double ut;
   NetworkModelAnalytical *model;
};

struct UtilizationMCPMessage
{
   int msg_type;
   UtilizationMessage msg;
};

// we send and receive updates asynchronously for performance and
// because the MCP is unable to reply to itself.

void NetworkModelAnalytical::updateUtilization()
{
   // ** send updates

   // don't lock because this is all approximate anyway
   UInt64 core_time = getNetwork()->getCore()->getPerformanceModel()->getCycleCount();
   UInt64 elapsed_time = core_time - _localUtilizationLastUpdate;

   if (elapsed_time < m_params.update_interval)
      return;

   _lock.acquire();

   // FIXME: This assumes one cycle per flit, might not be accurate.
   double local_utilization = ((double)_localUtilizationFlitsSent) / ((double)elapsed_time);

   _localUtilizationLastUpdate = core_time;
   _localUtilizationFlitsSent = 0;

   // build packet
   UtilizationMCPMessage m;
   m.msg_type = MCP_MESSAGE_UTILIZATION_UPDATE;
   m.msg.ut = local_utilization;
   m.msg.model = this;

   NetPacket update;
   update.sender = getNetwork()->getCore()->getId();
   update.receiver = Config::getSingleton()->getMCPCoreNum();
   update.length = sizeof(m);
   update.type = MCP_SYSTEM_TYPE;
   update.data = &m;

   getNetwork()->netSend(update);

   _lock.release();
}

void NetworkModelAnalytical::receiveMCPUpdate(void *obj, NetPacket response)
{
   assert(response.length == sizeof(UtilizationMessage));

   UtilizationMessage *pr = (UtilizationMessage*) response.data;

   pr->model->_lock.acquire();
   pr->model->_globalUtilization = pr->ut;
   assert(!IS_NAN(pr->model->_globalUtilization));
   pr->model->_lock.release();
}

void NetworkModelAnalytical::enable()
{
   m_enabled = true;
}

void NetworkModelAnalytical::disable()
{
   m_enabled = false;
}
<commit_msg>[network/analytical] Eliminate costs for self-sends.<commit_after>#include <math.h>
#include <stdlib.h>

#include "network_model_analytical.h"
#include "network_model_analytical_params.h"
#include "message_types.h"
#include "config.h"
#include "core.h"
#include "performance_model.h"
#include "transport.h"
#include "lock.h"

#define IS_NAN(x) (!((x < 0.0) || (x >= 0.0)))

using namespace std;

NetworkModelAnalytical::NetworkModelAnalytical(Network *net, EStaticNetwork net_type)
      : NetworkModel(net)
      , _bytesSent(0)
      , _cyclesProc(0)
      , _cyclesLatency(0)
      , _cyclesContention(0)
      , _globalUtilization(0)
      , _localUtilizationLastUpdate(0)
      , _localUtilizationFlitsSent(0)
      , m_enabled(true)
{
   getNetwork()->registerCallback(MCP_UTILIZATION_UPDATE_TYPE,
                                  receiveMCPUpdate,
                                  this);

   // Create network parameters
   m_params.Tw2 = 1; // single cycle between nodes in 2d mesh
   m_params.s = 1; // single cycle switching time
   m_params.n = 1; // 2-d mesh network
   m_params.W = 32; // 32-bit wide channels
   m_params.update_interval = 100000;
   m_params.proc_cost = (net_type == STATIC_NETWORK_MEMORY) ? 0 : 100;
}

NetworkModelAnalytical::~NetworkModelAnalytical()
{
   getNetwork()->unregisterCallback(MCP_UTILIZATION_UPDATE_TYPE);
}

void NetworkModelAnalytical::routePacket(const NetPacket &pkt,
      std::vector<Hop> &nextHops)
{
   // basic magic network routing, with two additions
   // (1) compute latency of packet
   // (2) update utilization

   PerformanceModel *perf = getNetwork()->getCore()->getPerformanceModel();

   Hop h;
   h.dest = pkt.receiver;

   UInt64 network_latency = computeLatency(pkt);
   LOG_PRINT ("Network Latency = %llu", network_latency);
   h.time = pkt.time + network_latency;

   nextHops.push_back(h);

   if (m_params.proc_cost > 0)
      perf->queueDynamicInstruction(new DynamicInstruction(m_params.proc_cost));
   _cyclesProc += m_params.proc_cost;

   updateUtilization();

   _bytesSent += pkt.length;
}

UInt64 NetworkModelAnalytical::computeLatency(const NetPacket &packet)
{
   if (!m_enabled)
      return 0;

   // self-sends incur no cost
   if (packet.sender == packet.receiver)
     return 0;

   // We model a unidirectional network with end-around connections
   // using the network model in "Limits on Interconnect Performance"
   // (by Anant). Currently, this ignores communication locality and
   // sets static values for all parameters. We also assume uniform
   // packet distribution, so we do not take the packet destination
   // into account.
   //
   // We combine the contention model (eq. 12) with the model for
   // limited bisection width (sec. 4.2).

   // TODO: Fix (if necessary) distance calculation for uneven
   // topologies, i.e. 8-node 2d mesh or 10-node 3d mesh.

   // TODO: Confirm model for latency computed based on actual number
   // of network hops.

   // Retrieve parameters
   double Tw2 = m_params.Tw2;
   double s = m_params.s;
   int n = m_params.n;
   double W = m_params.W;
   double p = _globalUtilization;
   assert(!IS_NAN(_globalUtilization));

   // This lets us derive the latency, ignoring contention

   int N;                    // number of nodes in the network
   double k;                 // length of mesh in one dimension
   double kd;                // number of hops per dimension
   double time_per_hop;      // time spent in one hop through the network
   double B;                 // number of flits for packet
   double hops_in_network;   // number of nodes visited
   double Tb;                // latency, without contention

   N = Config::getSingleton()->getTotalCores();
   k = pow(N, 1./n);                  // pg 5
   kd = k/2.;                         // pg 5 (note this will be
   // different for different network configurations...say,
   // bidirectional networks)
   time_per_hop = s + pow(k, n/2.-1.);  // pg 6
   B = ceil(packet.length * 8. / W);

   // Compute the number of hops based on src, dest
   // Based on this eqn:
   // node number = x1 + x2 k + x3 k^2 + ... + xn k^(n-1)
   int network_distance = 0;
   int src = packet.sender;
   int dest = packet.receiver;
   int ki = (int)k;
   for (int i = 0; i < n; i++)
   {
      div_t q1, q2;
      q1 = div(src, ki);
      q2 = div(dest, ki);
      // This models a unidirectional network distance
      // Should use abs() for bidirectional.
      if (q1.rem > q2.rem)
         network_distance += ki - (q1.rem - q2.rem);
      else
         network_distance += q2.rem - q1.rem;
      src = q1.quot;
      dest = q2.quot;
   }
   hops_in_network = network_distance + B; // B flits must be sent
   // (with wormhole routing, this adds B hops)

   Tb = Tw2 * time_per_hop * hops_in_network; // pg 5

   // Now to model contention... (sec 3.2)
   double w;                 // delay due to contention

   w  = p * B / (1. - p);
   w *= (kd-1.)/(kd*kd);
   w *= 1.+1./((double)n);

   if (w < 0) w = 0; // correct negative contention values for small
   // networks

   double hops_with_contention;
   double Tc;                // latency, with contention
   hops_with_contention = network_distance * (1. + w) + B;
   Tc = Tw2 * time_per_hop * hops_with_contention;

   // Computation finished...
   _lock.acquire();

   UInt64 Tci = (UInt64)(ceil(Tc));
   _cyclesLatency += Tci;
   _cyclesContention += (UInt64)(Tc - Tb);

   // ** update utilization counter **
   // we must account for the usage throughout the mesh
   // which means that we must include the # of hops
   _localUtilizationFlitsSent += (UInt64)(B * hops_in_network);

   _lock.release();

   return Tci;
}

void NetworkModelAnalytical::outputSummary(ostream &out)
{
   out << "    bytes sent: " << _bytesSent << endl;
   out << "    cycles spent proc: " << _cyclesProc << endl;
   out << "    cycles spent latency: " << _cyclesLatency << endl;
   out << "    cycles spent contention: " << _cyclesContention << endl;
}

struct UtilizationMessage
{
   double ut;
   NetworkModelAnalytical *model;
};

struct UtilizationMCPMessage
{
   int msg_type;
   UtilizationMessage msg;
};

// we send and receive updates asynchronously for performance and
// because the MCP is unable to reply to itself.

void NetworkModelAnalytical::updateUtilization()
{
   // ** send updates

   // don't lock because this is all approximate anyway
   UInt64 core_time = getNetwork()->getCore()->getPerformanceModel()->getCycleCount();
   UInt64 elapsed_time = core_time - _localUtilizationLastUpdate;

   if (elapsed_time < m_params.update_interval)
      return;

   _lock.acquire();

   // FIXME: This assumes one cycle per flit, might not be accurate.
   double local_utilization = ((double)_localUtilizationFlitsSent) / ((double)elapsed_time);

   _localUtilizationLastUpdate = core_time;
   _localUtilizationFlitsSent = 0;

   // build packet
   UtilizationMCPMessage m;
   m.msg_type = MCP_MESSAGE_UTILIZATION_UPDATE;
   m.msg.ut = local_utilization;
   m.msg.model = this;

   NetPacket update;
   update.sender = getNetwork()->getCore()->getId();
   update.receiver = Config::getSingleton()->getMCPCoreNum();
   update.length = sizeof(m);
   update.type = MCP_SYSTEM_TYPE;
   update.data = &m;

   getNetwork()->netSend(update);

   _lock.release();
}

void NetworkModelAnalytical::receiveMCPUpdate(void *obj, NetPacket response)
{
   assert(response.length == sizeof(UtilizationMessage));

   UtilizationMessage *pr = (UtilizationMessage*) response.data;

   pr->model->_lock.acquire();
   pr->model->_globalUtilization = pr->ut;
   assert(!IS_NAN(pr->model->_globalUtilization));
   pr->model->_lock.release();
}

void NetworkModelAnalytical::enable()
{
   m_enabled = true;
}

void NetworkModelAnalytical::disable()
{
   m_enabled = false;
}
<|endoftext|>