<commit_before>#include "General.h"
#include "require.h"
#include "Options.h"
#include "DataSet.h"
#include "RecursiveNN.h"
#include <cstdlib>
#include <cfloat>
#include <ctime>
#include <map>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;

double adjustLearningRate(double curr_error, bool& restore_weights_flag, double& alpha) {
  /*** Vogl adaptive acceleration learning method (additive) ***/
  static double prev_eta = atof((Options::instance()->get_parameter("eta")).c_str());
  static double prev_error = FLT_MAX;

  double alpha_0 = 1e-1;
  double phi = 1.05, beta = .5, epsilon = 1e-2;
  double phi_additive = prev_eta/100;

  double curr_eta;

  if(curr_error < prev_error) {
    curr_eta = phi_additive + prev_eta;
    if(curr_eta > 1)
      curr_eta = 1;
    alpha = alpha_0;
    prev_eta = curr_eta;
    prev_error = curr_error;
  } else if(curr_error < (1 + epsilon) * prev_error) {
    curr_eta = beta * prev_eta;
    alpha = 0;
    prev_eta = curr_eta;
    prev_error = curr_error;
  } else {
    restore_weights_flag = true;
    curr_eta = beta * prev_eta;
    alpha = 0;
  }

  return curr_eta;
}

void computeErrorOnDataset();

void train(const string& netname, DataSet* trainingSet, DataSet* validationSet, ostream& os = cout) {
  // Get important training parameters
  bool onlinelearning = (atoi((Options::instance()->get_parameter("onlinelearning")).c_str()))?true:false;
  bool random_net = (atoi((Options::instance()->get_parameter("random_net")).c_str()))?true:false;

  int epochs = atoi((Options::instance()->get_parameter("epochs")).c_str());
  int savedelta = atoi((Options::instance()->get_parameter("savedelta")).c_str());

  /*
   * read network in if it exists, otherwise make one from scratch
   */
  RecursiveNN<TanH, Sigmoid, MGradientDescent>* rnn;

  if(trainingSet->size()) {
    os << "Creating new network...";
    rnn = new RecursiveNN<TanH, Sigmoid, MGradientDescent>();
    os << " Done." << endl;
  } else {
    os << "Need some data to train network, please specify value for the --training-set argument\n";
    return;
  }

  os << endl << endl;

  bool restore_weights_flag = false;
  double curr_eta = atof((Options::instance()->get_parameter("eta")).c_str());
  double alpha = .9;

  double prev_error = FLT_MAX, min_error = FLT_MAX;
  int min_error_epoch = -1;
  double threshold_error = atof((Options::instance()->get_parameter("threshold_error")).c_str());

  for(int epoch = 1; epoch<=epochs; epoch++) {
    double error_training_set = .0, error_validation_set = .0;

    os << endl << "Epoch " << epoch << '\t';

    for(DataSet::iterator it=trainingSet->begin(); it!=trainingSet->end(); ++it) {
      // (*it)->print(os);
      rnn->propagateStructuredInput(*it);
      rnn->backPropagateError(*it);

      /* stochastic (i.e. online) gradient descent */
      if(onlinelearning) {
      	if(restore_weights_flag)
      	  rnn->restorePrevWeights();

      	rnn->adjustWeights(curr_eta, alpha);
      	//curr_eta = adjustLearningRate(curr_train_error, restore_weights_flag, alpha);
      }
    }

    /* batch weight update */
    if(!onlinelearning) {
      if(restore_weights_flag)
    	rnn->restorePrevWeights();

      rnn->adjustWeights(curr_eta, alpha);
      //curr_eta = adjustLearningRate(curr_train_error, restore_weights_flag, alpha);
    }

    double error;
    double error_training_set = rnn->computeErrorOnDataset(trainingSet);
    os << "E_training = " << error_training_set << '\t';

    if(validationSet) {
      double error_validation_set = rnn->computeErrorOnDataset(validationSet);
      error = error_validation_set;
      os << "E_validation = " << error_validation_set;
    } else
      error = error_training_set;

    os << endl;

    if(min_error > error) {
      min_error = error;
      min_error_epoch = epoch;
      rnn->saveParameters(netname.c_str());
    }

    // stopping criterion based on error threshold
    if(fabs(prev_error - error) < threshold_error) {
      os << endl << << endl << "Network error decay below given threshold. Stopping training..." << endl;
      break;
    }

    prev_error = error;

    // save network every 'savedelta' epochs
    if(!(epoch % savedelta)) {
      ostringstream oss;
      oss << netname << '.' << epoch;
      rnn->saveParameters((oss.str()).c_str());
    }

  }

  os << endl << flush;

  // deallocate Recursive Neural Network instace
  delete rnn; rnn = 0;

}

int main(int argc, char* argv[]) {
  setenv("RNNOPTIONTYPE", "train", 1);

  DataSet *trainingSet = NULL, *testSet = NULL, *validationSet = NULL;
  string netname;

  try {
    Options::instance()->parse_args(argc,argv);

    netname = Options::instance()->get_parameter("netname");
    if(!netname.length()) {
      cerr << "Must specify a network file" << endl << endl;
      throw Options::BadOptionSetting(Options::instance()->usage());
    }

    string training_set_fname = Options::instance()->get_parameter("training_set");

    if(training_set_fname.length()) {
      cout << "Creating training set. " << flush;
      trainingSet = new DataSet(training_set_fname.c_str());
      cout << "Done." << flush << endl;
    } else
      cout << "Training set not specified. Skipping training..." << endl;

    string test_set_fname = Options::instance()->get_parameter("test_set");
    if(test_set_fname.length()) {
      cout << "Creating test set. " << flush;
      testSet = new DataSet(test_set_fname.c_str());
      cout << "Done." << flush << endl;
    } else
      cout << "Test set not specified. Skipping testing..." << endl;

    string validation_set_fname = Options::instance()->get_parameter("validation_set");
    if(validation_set_fname.length()) {
      cout << "Creating validation set. " << flush;
      validationSet = new DataSet(validation_set_fname.c_str());
      cout << "Done." << flush << endl;
    }
  } catch(Options::BadOptionSetting e) {
    cerr << e.what() << endl;
    exit(EXIT_FAILURE);
  }

  /*** Train the network and save results ***/
  if(trainingSet) {
    cout << "Training set has " << (trainingSet->size()) << " instances." << endl;
    if(validationSet) {
      cout << "Training network with validation set." << endl;
      cout << "Validation set has " << validationSet->size() << " instances." << endl;
    }
    else
      cout << "Training without validation set." << endl;

    train(netname, trainingSet, validationSet);
    cout << "RNN model saved to file " << netname << endl;

    /*
     * TODO
     * predict(netname, trainingSet, "training.pred");
     * predict(netname, validationSet, "validation.pred");
     */

    delete trainingSet;
    if(validationSet)
      delete validationSet;

  } else if(validationSet) {
    cerr << "Cannot use validation set without training set. Skipping training..." << endl;
    delete validationSet;
  }

  if(testSet) {
    cout << "Test set has " << testSet->size() << " instances." << endl
	 << "Evaluating test set performance using network defined in file " << netname << endl;

    /*
     * TODO
     * predict(netname, testSet, "test.pred");
     */
    delete testSet;
  }

  return EXIT_SUCCESS;
}
<commit_msg>Always start training with a network with randomised weights. Syntax error.<commit_after>#include "General.h"
#include "require.h"
#include "Options.h"
#include "DataSet.h"
#include "RecursiveNN.h"
#include <cstdlib>
#include <cfloat>
#include <ctime>
#include <map>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;

double adjustLearningRate(double curr_error, bool& restore_weights_flag, double& alpha) {
  /*** Vogl adaptive acceleration learning method (additive) ***/
  static double prev_eta = atof((Options::instance()->get_parameter("eta")).c_str());
  static double prev_error = FLT_MAX;

  double alpha_0 = 1e-1;
  double phi = 1.05, beta = .5, epsilon = 1e-2;
  double phi_additive = prev_eta/100;

  double curr_eta;

  if(curr_error < prev_error) {
    curr_eta = phi_additive + prev_eta;
    if(curr_eta > 1)
      curr_eta = 1;
    alpha = alpha_0;
    prev_eta = curr_eta;
    prev_error = curr_error;
  } else if(curr_error < (1 + epsilon) * prev_error) {
    curr_eta = beta * prev_eta;
    alpha = 0;
    prev_eta = curr_eta;
    prev_error = curr_error;
  } else {
    restore_weights_flag = true;
    curr_eta = beta * prev_eta;
    alpha = 0;
  }

  return curr_eta;
}

void computeErrorOnDataset();

void train(const string& netname, DataSet* trainingSet, DataSet* validationSet, ostream& os = cout) {
  // Get important training parameters
  bool onlinelearning = (atoi((Options::instance()->get_parameter("onlinelearning")).c_str()))?true:false;
  // bool random_net = (atoi((Options::instance()->get_parameter("random_net")).c_str()))?true:false;

  int epochs = atoi((Options::instance()->get_parameter("epochs")).c_str());
  int savedelta = atoi((Options::instance()->get_parameter("savedelta")).c_str());

  /*
   * read network in if it exists, otherwise make one from scratch
   */
  RecursiveNN<TanH, Sigmoid, MGradientDescent>* rnn;

  if(trainingSet->size()) {
    os << "Creating new network...";
    rnn = new RecursiveNN<TanH, Sigmoid, MGradientDescent>();
    os << " Done." << endl;
  } else {
    os << "Need some data to train network, please specify value for the --training-set argument\n";
    return;
  }

  os << endl << endl;

  bool restore_weights_flag = false;
  double curr_eta = atof((Options::instance()->get_parameter("eta")).c_str());
  double alpha = .9;

  double prev_error = FLT_MAX, min_error = FLT_MAX;
  int min_error_epoch = -1;
  double threshold_error = atof((Options::instance()->get_parameter("threshold_error")).c_str());

  for(int epoch = 1; epoch<=epochs; epoch++) {
    os << "Epoch " << epoch << '\t';

    for(DataSet::iterator it=trainingSet->begin(); it!=trainingSet->end(); ++it) {
      // (*it)->print(os);
      rnn->propagateStructuredInput(*it);
      rnn->backPropagateError(*it);

      /* stochastic (i.e. online) gradient descent */
      if(onlinelearning) {
      	if(restore_weights_flag)
      	  rnn->restorePrevWeights();

      	rnn->adjustWeights(curr_eta, alpha);
      	//curr_eta = adjustLearningRate(curr_train_error, restore_weights_flag, alpha);
      }
    }

    /* batch weight update */
    if(!onlinelearning) {
      if(restore_weights_flag)
    	rnn->restorePrevWeights();

      rnn->adjustWeights(curr_eta, alpha);
      //curr_eta = adjustLearningRate(curr_train_error, restore_weights_flag, alpha);
    }

    double error;
    double error_training_set = rnn->computeErrorOnDataset(trainingSet);
    os << "E_training = " << error_training_set << '\t';

    if(validationSet) {
      double error_validation_set = rnn->computeErrorOnDataset(validationSet);
      error = error_validation_set;
      os << "E_validation = " << error_validation_set;
    } else
      error = error_training_set;

    os << endl;

    if(min_error > error) {
      min_error = error;
      min_error_epoch = epoch;
      rnn->saveParameters(netname.c_str());
    }

    // stopping criterion based on error threshold
    if(fabs(prev_error - error) < threshold_error) {
      os << endl << endl << "Network error decay below given threshold. Stopping training..." << endl;
      break;
    }

    prev_error = error;

    // save network every 'savedelta' epochs
    if(!(epoch % savedelta)) {
      ostringstream oss;
      oss << netname << '.' << epoch;
      rnn->saveParameters((oss.str()).c_str());
    }

  }

  os << endl << flush;

  // deallocate Recursive Neural Network instace
  delete rnn; rnn = 0;

}

int main(int argc, char* argv[]) {
  setenv("RNNOPTIONTYPE", "train", 1);

  DataSet *trainingSet = NULL, *testSet = NULL, *validationSet = NULL;
  string netname;

  try {
    Options::instance()->parse_args(argc,argv);

    netname = Options::instance()->get_parameter("netname");
    if(!netname.length()) {
      cerr << "Must specify a network file" << endl << endl;
      throw Options::BadOptionSetting(Options::instance()->usage());
    }

    string training_set_fname = Options::instance()->get_parameter("training_set");

    if(training_set_fname.length()) {
      cout << "Creating training set. " << flush;
      trainingSet = new DataSet(training_set_fname.c_str());
      cout << "Done." << flush << endl;
    } else
      cout << "Training set not specified. Skipping training..." << endl;

    string test_set_fname = Options::instance()->get_parameter("test_set");
    if(test_set_fname.length()) {
      cout << "Creating test set. " << flush;
      testSet = new DataSet(test_set_fname.c_str());
      cout << "Done." << flush << endl;
    } else
      cout << "Test set not specified. Skipping testing..." << endl;

    string validation_set_fname = Options::instance()->get_parameter("validation_set");
    if(validation_set_fname.length()) {
      cout << "Creating validation set. " << flush;
      validationSet = new DataSet(validation_set_fname.c_str());
      cout << "Done." << flush << endl;
    }
  } catch(Options::BadOptionSetting e) {
    cerr << e.what() << endl;
    exit(EXIT_FAILURE);
  }

  /*** Train the network and save results ***/
  if(trainingSet) {
    cout << "Training set has " << (trainingSet->size()) << " instances." << endl;
    if(validationSet) {
      cout << "Training network with validation set." << endl;
      cout << "Validation set has " << validationSet->size() << " instances." << endl;
    }
    else
      cout << "Training without validation set." << endl;

    train(netname, trainingSet, validationSet);
    cout << "RNN model saved to file " << netname << endl;

    /*
     * TODO
     * predict(netname, trainingSet, "training.pred");
     * predict(netname, validationSet, "validation.pred");
     */

    delete trainingSet;
    if(validationSet)
      delete validationSet;

  } else if(validationSet) {
    cerr << "Cannot use validation set without training set. Skipping training..." << endl;
    delete validationSet;
  }

  if(testSet) {
    cout << "Test set has " << testSet->size() << " instances." << endl
	 << "Evaluating test set performance using network defined in file " << netname << endl;

    /*
     * TODO
     * predict(netname, testSet, "test.pred");
     */
    delete testSet;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>Sat: sync code<commit_after><|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include "SceneGraph.h"
#include "Quaternion.h"
#include "Allocator.h"
#include <string.h>
#include "Hash.h"
#include "StringUtils.h"

namespace crown
{

//-----------------------------------------------------------------------------
SceneGraph::SceneGraph(Allocator& a, uint32_t index)
	: m_allocator(&a)
	, m_index(index)
	, m_num_nodes(0)
	, m_world_poses(NULL)
	, m_local_poses(NULL)
	, m_parents(NULL)
	, m_names(NULL)
{
}

//-----------------------------------------------------------------------------
void SceneGraph::create(uint32_t count, const StringId32* name, const Matrix4x4* local, int32_t* parent)
{
	char* mem = (char*) m_allocator->allocate(count * (sizeof(StringId32) + sizeof(Matrix4x4) + sizeof(Matrix4x4) + sizeof(int32_t)));

	m_num_nodes = count;

	m_world_poses = (Matrix4x4*) mem; mem += sizeof(Matrix4x4) * count;
	m_local_poses = (Matrix4x4*) mem; mem += sizeof(Matrix4x4) * count;
	m_parents = (int32_t*) mem; mem += sizeof(int32_t) * count;
	m_names = (StringId32*) mem; mem += sizeof(StringId32) * count;

	memcpy(m_local_poses, local, count* sizeof(Matrix4x4));
	memcpy(m_parents, parent, count * sizeof(int32_t));
	memcpy(m_names, name, count * sizeof(StringId32));
}

//-----------------------------------------------------------------------------
void SceneGraph::destroy()
{
	// m_world_poses is the start of allocated memory
	m_allocator->deallocate(m_world_poses);
}

//-----------------------------------------------------------------------------
int32_t SceneGraph::node(const char* name) const
{
	StringId32 name_hash = hash::murmur2_32(name, string::strlen(name), 0);

	for (uint32_t i = 0; i < m_num_nodes; i++)
	{
		if (m_names[i] == name_hash)
		{
			return i;
		}
	}

	CE_ASSERT(false, "Node not found: '%s'", name);
}

//-----------------------------------------------------------------------------
bool SceneGraph::has_node(const char* name) const
{
	StringId32 name_hash = hash::murmur2_32(name, string::strlen(name), 0);

	for (uint32_t i = 0; i < m_num_nodes; i++)
	{
		if (m_names[i] == name_hash)
		{
			return true;
		}
	}

	return false;
}

//-----------------------------------------------------------------------------
uint32_t SceneGraph::num_nodes() const
{
	return m_num_nodes;
}

//-----------------------------------------------------------------------------
void SceneGraph::link(int32_t child, int32_t parent)
{
	CE_ASSERT(child < (int32_t) m_num_nodes, "Child node does not exist");
	CE_ASSERT(parent < (int32_t) m_num_nodes, "Parent node does not exist");
	CE_ASSERT(parent < child, "Parent must be < child");

	m_world_poses[child] = Matrix4x4::IDENTITY;
	m_local_poses[child] = Matrix4x4::IDENTITY;
	m_parents[child] = parent;
}

//-----------------------------------------------------------------------------
void SceneGraph::unlink(int32_t child)
{
	CE_ASSERT(child < (int32_t) m_num_nodes, "Child node does not exist");

	if (m_parents[child] != -1)
	{
		// Copy world pose before unlinking from parent
		m_local_poses[child] = m_world_poses[child];
		m_parents[child] = -1;
	}
}

//-----------------------------------------------------------------------------
void SceneGraph::set_local_position(int32_t node, const Vector3& pos)
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	Matrix4x4& local_pose = m_local_poses[node];
	local_pose.set_translation(pos);
}

//-----------------------------------------------------------------------------
void SceneGraph::set_local_rotation(int32_t node, const Quaternion& rot)
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	Matrix4x4& local_pose = m_local_poses[node];

	Vector3 local_translation = local_pose.translation();
	local_pose = rot.to_matrix4x4();
	local_pose.set_translation(local_translation);
}

//-----------------------------------------------------------------------------
void SceneGraph::set_local_pose(int32_t node, const Matrix4x4& pose)
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	m_local_poses[node] = pose;
}

//-----------------------------------------------------------------------------
Vector3 SceneGraph::local_position(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_local_poses[node].translation();
}

//-----------------------------------------------------------------------------
Quaternion SceneGraph::local_rotation(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_local_poses[node].to_quaternion();
}

//-----------------------------------------------------------------------------
Matrix4x4 SceneGraph::local_pose(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_local_poses[node];
}

//-----------------------------------------------------------------------------
Vector3 SceneGraph::world_position(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_world_poses[node].translation();
}

//-----------------------------------------------------------------------------
Quaternion SceneGraph::world_rotation(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_world_poses[node].to_quaternion();
}

//-----------------------------------------------------------------------------
Matrix4x4 SceneGraph::world_pose(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_world_poses[node];
}

//-----------------------------------------------------------------------------
void SceneGraph::update()
{
	for (uint32_t i = 0; i < m_num_nodes; i++)
	{
		if (m_parents[i] == -1)
		{
			m_world_poses[i] = m_local_poses[i];
		}
		else
		{
			m_world_poses[i] = m_local_poses[m_parents[i]] * m_local_poses[i];
		}
	}
}

} // namespace crown
<commit_msg>Fix SceneGraph wrong matrix selection<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include "SceneGraph.h"
#include "Quaternion.h"
#include "Allocator.h"
#include <string.h>
#include "Hash.h"
#include "StringUtils.h"

namespace crown
{

//-----------------------------------------------------------------------------
SceneGraph::SceneGraph(Allocator& a, uint32_t index)
	: m_allocator(&a)
	, m_index(index)
	, m_num_nodes(0)
	, m_world_poses(NULL)
	, m_local_poses(NULL)
	, m_parents(NULL)
	, m_names(NULL)
{
}

//-----------------------------------------------------------------------------
void SceneGraph::create(uint32_t count, const StringId32* name, const Matrix4x4* local, int32_t* parent)
{
	char* mem = (char*) m_allocator->allocate(count * (sizeof(StringId32) + sizeof(Matrix4x4) + sizeof(Matrix4x4) + sizeof(int32_t)));

	m_num_nodes = count;

	m_world_poses = (Matrix4x4*) mem; mem += sizeof(Matrix4x4) * count;
	m_local_poses = (Matrix4x4*) mem; mem += sizeof(Matrix4x4) * count;
	m_parents = (int32_t*) mem; mem += sizeof(int32_t) * count;
	m_names = (StringId32*) mem; mem += sizeof(StringId32) * count;

	memcpy(m_local_poses, local, count* sizeof(Matrix4x4));
	memcpy(m_parents, parent, count * sizeof(int32_t));
	memcpy(m_names, name, count * sizeof(StringId32));
}

//-----------------------------------------------------------------------------
void SceneGraph::destroy()
{
	// m_world_poses is the start of allocated memory
	m_allocator->deallocate(m_world_poses);
}

//-----------------------------------------------------------------------------
int32_t SceneGraph::node(const char* name) const
{
	StringId32 name_hash = hash::murmur2_32(name, string::strlen(name), 0);

	for (uint32_t i = 0; i < m_num_nodes; i++)
	{
		if (m_names[i] == name_hash)
		{
			return i;
		}
	}

	CE_ASSERT(false, "Node not found: '%s'", name);
}

//-----------------------------------------------------------------------------
bool SceneGraph::has_node(const char* name) const
{
	StringId32 name_hash = hash::murmur2_32(name, string::strlen(name), 0);

	for (uint32_t i = 0; i < m_num_nodes; i++)
	{
		if (m_names[i] == name_hash)
		{
			return true;
		}
	}

	return false;
}

//-----------------------------------------------------------------------------
uint32_t SceneGraph::num_nodes() const
{
	return m_num_nodes;
}

//-----------------------------------------------------------------------------
void SceneGraph::link(int32_t child, int32_t parent)
{
	CE_ASSERT(child < (int32_t) m_num_nodes, "Child node does not exist");
	CE_ASSERT(parent < (int32_t) m_num_nodes, "Parent node does not exist");
	CE_ASSERT(parent < child, "Parent must be < child");

	m_world_poses[child] = Matrix4x4::IDENTITY;
	m_local_poses[child] = Matrix4x4::IDENTITY;
	m_parents[child] = parent;
}

//-----------------------------------------------------------------------------
void SceneGraph::unlink(int32_t child)
{
	CE_ASSERT(child < (int32_t) m_num_nodes, "Child node does not exist");

	if (m_parents[child] != -1)
	{
		// Copy world pose before unlinking from parent
		m_local_poses[child] = m_world_poses[child];
		m_parents[child] = -1;
	}
}

//-----------------------------------------------------------------------------
void SceneGraph::set_local_position(int32_t node, const Vector3& pos)
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	Matrix4x4& local_pose = m_local_poses[node];
	local_pose.set_translation(pos);
}

//-----------------------------------------------------------------------------
void SceneGraph::set_local_rotation(int32_t node, const Quaternion& rot)
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	Matrix4x4& local_pose = m_local_poses[node];

	Vector3 local_translation = local_pose.translation();
	local_pose = rot.to_matrix4x4();
	local_pose.set_translation(local_translation);
}

//-----------------------------------------------------------------------------
void SceneGraph::set_local_pose(int32_t node, const Matrix4x4& pose)
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	m_local_poses[node] = pose;
}

//-----------------------------------------------------------------------------
Vector3 SceneGraph::local_position(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_local_poses[node].translation();
}

//-----------------------------------------------------------------------------
Quaternion SceneGraph::local_rotation(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_local_poses[node].to_quaternion();
}

//-----------------------------------------------------------------------------
Matrix4x4 SceneGraph::local_pose(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_local_poses[node];
}

//-----------------------------------------------------------------------------
Vector3 SceneGraph::world_position(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_world_poses[node].translation();
}

//-----------------------------------------------------------------------------
Quaternion SceneGraph::world_rotation(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_world_poses[node].to_quaternion();
}

//-----------------------------------------------------------------------------
Matrix4x4 SceneGraph::world_pose(int32_t node) const
{
	CE_ASSERT(node < (int32_t) m_num_nodes, "Node does not exist");

	return m_world_poses[node];
}

//-----------------------------------------------------------------------------
void SceneGraph::update()
{
	for (uint32_t i = 0; i < m_num_nodes; i++)
	{
		if (m_parents[i] == -1)
		{
			m_world_poses[i] = m_local_poses[i];
		}
		else
		{
			m_world_poses[i] = m_world_poses[m_parents[i]] * m_local_poses[i];
		}
	}
}

} // namespace crown
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>

#include "vtrc-transformer-iface.h"
#include "vtrc-random-device.h"
#include "vtrc-hash-iface.h"
#include "vtrc-memory.h"

#include "crypt/chacha/ecrypt-sync.h"

namespace vtrc { namespace common {

    namespace {

        struct transformer_chacha: public transformer_iface {

            ECRYPT_ctx ctx_;

            //// need poly!!!
            transformer_chacha( const char *transform_key, size_t t_length )
            {
                std::string key;
                key.reserve( 32 );
                size_t max = 32;

                static const size_t input_len = sizeof(ctx_.input) /
                                                sizeof(ctx_.input[0]);

                for( size_t i=0; i<input_len; ++i ) {
                    ctx_.input[i] = 0;
                }

                if( t_length < 32 ) {
                    while( max < 32 ) {
                        size_t next_len = std::min( 32 - max, t_length );
                        key.append( transform_key + max, next_len );
                        max += next_len;
                    }
                } else {
                    key.assign( transform_key, transform_key + 32 );
                }

//                std::cout << "Key is! "
//                          << transform_key << ":" << t_length
//                          << "\n";

                ECRYPT_keysetup( &ctx_,
                              reinterpret_cast<const uint8_t *>(key.c_str( )),
                              key.size( ) * 8, 0);
            }

            void transform( std::string &data )
            {
                char s;
                char *ptr = data.empty( ) ? &s : &data[0];
                ECRYPT_encrypt_bytes( &ctx_,
                                      reinterpret_cast<const uint8_t *>( ptr ),
                                      reinterpret_cast<      uint8_t *>( ptr ),
                                      data.size( ) );
            }

        };

    }

    namespace transformers { namespace chacha {
        transformer_iface *create( const char *transform_key, size_t length )
        {
            return new transformer_chacha( transform_key, length );
        }
    }}
}}

<commit_msg>defaults<commit_after>#include <iostream>
#include <algorithm>

#include "vtrc-transformer-iface.h"
#include "vtrc-random-device.h"
#include "vtrc-hash-iface.h"
#include "vtrc-memory.h"

#include "crypt/chacha/ecrypt-sync.h"

namespace vtrc { namespace common {

    namespace {

        struct transformer_chacha: public transformer_iface {

            ECRYPT_ctx ctx_;

            //// need poly!!!
            transformer_chacha( const char *transform_key, size_t t_length )
            {
                std::string key;
                key.reserve( 32 );
                size_t max = 32;

                static const size_t input_len = sizeof(ctx_.input) /
                                                sizeof(ctx_.input[0]);

                for( size_t i=0; i<input_len; ++i ) {
                    ctx_.input[i] = 0;
                }

                if( t_length < 32 ) {
                    while( max < 32 ) {
                        size_t next_len = std::min( 32 - max, t_length );
                        key.append( transform_key + max, next_len );
                        max += next_len;
                    }
                } else {
                    key.assign( transform_key, transform_key + 32 );
                }

                ECRYPT_keysetup( &ctx_,
                              reinterpret_cast<const uint8_t *>(key.c_str( )),
                              key.size( ) * 8, 0);
            }

            void transform( std::string &data )
            {
                char s;
                char *ptr = data.empty( ) ? &s : &data[0];
                ECRYPT_encrypt_bytes( &ctx_,
                                      reinterpret_cast<const uint8_t *>( ptr ),
                                      reinterpret_cast<      uint8_t *>( ptr ),
                                      data.size( ) );
            }

        };

    }

    namespace transformers { namespace chacha {
        transformer_iface *create( const char *transform_key, size_t length )
        {
            return new transformer_chacha( transform_key, length );
        }
    }}
}}

<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(1)

/**
 * class Compare {
 *     public:
 *     static int cmp(int a, int b);
 * };
 * You can use Compare::cmp(a, b) to compare nuts "a" and bolts "b",
 * if "a" is bigger than "b", it will return 1, else if they are equal,
 * it will return 0, else if "a" is smaller than "b", it will return -1.
 * When "a" is not a nut or "b" is not a bolt, it will return 2, which is not valid.
*/
class Solution {
public:
    typedef enum { SMALLER = -1, EQUAL = 0, BIGGER = 1, REVERSE = 2 } CompareResult;
    /**
     * @param nuts: a vector of integers
     * @param bolts: a vector of integers
     * @return: nothing
     */
    void sortNutsAndBolts(vector<int> &nuts, vector<int> &bolts) {
        quickSort(nuts, bolts, 0, nuts.size() - 1);
    }

private:
    // Method which works just like quick sort
    void quickSort(vector<int>& nuts, vector<int>& bolts, int left, int right) {
        if (left < right) {
            // Randomly choose a bolt as a pivot for nuts partition.
            default_random_engine gen((random_device())());
            uniform_int_distribution<int> dis(left, right);
            int pivot = dis(gen);

            // Use the pivot bolt to make a partition of nuts.
            // The we could know the index where the pivot (bolt, nut) pair should be in sorted order.
            pivot = partition(nuts, left, right, bolts[pivot]);

            // Using the nut in the pivot bolt to make a partition of bolts.
            partition(bolts, left, right, nuts[pivot]);

            // Now, both nuts and bolts are partitioned by the pivot nut-bolt pair.
            // The pivot nut-bolt pair is also in the correct index of the sorted order.
            // Recursively do the same thing in the left and right side of the pivot.
            quickSort(nuts, bolts, left, pivot - 1);
            quickSort(nuts, bolts, pivot + 1, right);
        }
    }

    // All the smaller elements should be in the left side of the pivot,
    // and all the bigger elements should in the right side of the pivot.
    int partition(vector<int>& arr, int left, int right, int pivot) {
        for (int i = left; i < right; ) {
            if (Compare::cmp(arr[i], pivot) == SMALLER ||  // Smaller.
                (Compare::cmp(arr[i], pivot) == REVERSE &&
                 Compare::cmp(pivot, arr[i]) == BIGGER)) {
                swap(arr[left++], arr[i++]);
            } else if (Compare::cmp(arr[i], pivot) == BIGGER ||  // Bigger.
                      (Compare::cmp(arr[i], pivot) == REVERSE &&
                       Compare::cmp(pivot, arr[i]) == SMALLER)) {
                ++i;
            } else {  // Equal.
                swap(arr[i], arr[right]);
            }
        }
        // Put the pivot to the partition index.
        swap(arr[left], arr[right]);

        // Return the partition index of an array.
        return left;
    }
};
<commit_msg>Update nuts-bolts-problem.cpp<commit_after>// Time:  O(nlogn)
// Space: O(1)

/**
 * class Comparator {
 *     public:
 *      int cmp(string a, string b);
 * };
 * You can use compare.cmp(a, b) to compare nuts "a" and bolts "b",
 * if "a" is bigger than "b", it will return 1, else if they are equal,
 * it will return 0, else if "a" is smaller than "b", it will return -1.
 * When "a" is not a nut or "b" is not a bolt, it will return 2, which is not valid.
*/

class Solution {
public:
    typedef enum { SMALLER = -1, EQUAL = 0,
                   BIGGER = 1, REVERSE = 2 } CompareResult;
    /**
     * @param nuts: a vector of integers
     * @param bolts: a vector of integers
     * @param compare: a instance of Comparator
     * @return: nothing
     */
    void sortNutsAndBolts(vector<string> &nuts, vector<string> &bolts,
                          Comparator compare) {
        quickSort(nuts, bolts, 0, nuts.size() - 1, compare);
    }

    // Method which works just like quick sort
    void quickSort(vector<string>& nuts, vector<string>& bolts,
                   int left, int right,
                   Comparator& compare) {
        if (left < right) {
            // Randomly choose a bolt as a pivot for nuts partition.
            default_random_engine gen((random_device())());
            uniform_int_distribution<int> dis(left, right);
            int pivot = dis(gen);

            // Use the pivot bolt to make a partition of nuts.
            // The we could know the index where the pivot (bolt, nut)
            // pair should be in sorted order.
            pivot = partition(nuts, left, right, bolts[pivot], compare);

            // Using the nut in the pivot bolt to make a partition of bolts.
            partition(bolts, left, right, nuts[pivot], compare);

            // Now, both nuts and bolts are partitioned by the pivot nut-bolt pair.
            // The pivot nut-bolt pair is also in the correct index of the sorted order.
            // Recursively do the same thing in the left and right side of the pivot.
            quickSort(nuts, bolts, left, pivot - 1, compare);
            quickSort(nuts, bolts, pivot + 1, right, compare);
        }
    }

    // All the smaller elements should be in the left side of the pivot,
    // and all the bigger elements should in the right side of the pivot.
    int partition(vector<string>& arr,
                  int left, int right, const string& pivot,
                  Comparator& compare) {
        for (int i = left; i < right; ) {
            if (compare.cmp(arr[i], pivot) == SMALLER ||  // Smaller.
                (compare.cmp(arr[i], pivot) == REVERSE &&
                 compare.cmp(pivot, arr[i]) == BIGGER)) {
                swap(arr[left++], arr[i++]);
            } else if (compare.cmp(arr[i], pivot) == BIGGER ||  // Bigger.
                      (compare.cmp(arr[i], pivot) == REVERSE &&
                       compare.cmp(pivot, arr[i]) == SMALLER)) {
                ++i;
            } else {  // Equal.
                swap(arr[i], arr[right]);
            }
        }
        // Put the pivot to the partition index.
        swap(arr[left], arr[right]);

        // Return the partition index of an array.
        return left;
    }
};
<|endoftext|>


<commit_before>#include <stan/math/error_handling/matrix/check_ordered.hpp>
#include <gtest/gtest.h>

using stan::math::check_ordered;

TEST(MathErrorHandlingMatrix, checkOrdered) {
  double result;
  Eigen::Matrix<double, Eigen::Dynamic, 1> y;
  y.resize(3);

  y << 0, 1, 2;
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << 0, 10, std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << -10, 10, std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << -std::numeric_limits<double>::infinity(), 10, std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << 0, 0, 0;
  EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
               std::domain_error);

  y << 0, std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
               std::domain_error);

  y << -1, 3, 2;
  EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
               std::domain_error);
}

TEST(MathErrorHandlingMatrix, checkOrdered_one_indexed_message) {
  std::string message;
  double result;
  Eigen::Matrix<double, Eigen::Dynamic, 1> y;
  y.resize(3);

  y << 0, 5, 1;
  try {
    check_ordered("check_ordered(%1%)", y, "y", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_NE(std::string::npos, message.find("element at 3"))
    << message;
}
<commit_msg>added NaN test for check_ordered<commit_after>#include <stan/math/error_handling/matrix/check_ordered.hpp>
#include <gtest/gtest.h>

using stan::math::check_ordered;

TEST(MathErrorHandlingMatrix, checkOrdered) {
  double result;
  Eigen::Matrix<double, Eigen::Dynamic, 1> y;
  y.resize(3);

  y << 0, 1, 2;
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << 0, 10, std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << -10, 10, std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << -std::numeric_limits<double>::infinity(), 10, std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_ordered("check_ordered(%1%)", y, "y", &result));

  y << 0, 0, 0;
  EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
               std::domain_error);

  y << 0, std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
               std::domain_error);

  y << -1, 3, 2;
  EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
               std::domain_error);
}

TEST(MathErrorHandlingMatrix, checkOrdered_one_indexed_message) {
  std::string message;
  double result;
  Eigen::Matrix<double, Eigen::Dynamic, 1> y;
  y.resize(3);

  y << 0, 5, 1;
  try {
    check_ordered("check_ordered(%1%)", y, "y", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_NE(std::string::npos, message.find("element at 3"))
    << message;
}

TEST(MathErrorHandlingMatrix, checkOrdered_nan) {
  double result;
  Eigen::Matrix<double, Eigen::Dynamic, 1> y;
  double nan = std::numeric_limits<double>::quiet_NaN();
  y.resize(3);

  y << 0, 1, 2;
  for (int i = 0; i < y.size(); i++) {
    y[i] = nan;
    EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
                 std::domain_error);
    y[i] = i;
  }
  for (int i = 0; i < y.size(); i++) {
    y << 0, 10, std::numeric_limits<double>::infinity();
    y[i] = nan;
    EXPECT_THROW(check_ordered("check_ordered(%1%)", y, "y", &result),
                 std::domain_error);
    y[i] = i;
  }
}
<|endoftext|>


<commit_before>//===-- Passes.cpp - Target independent code generation passes ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces to access the target independent code
// generation passes provided by the LLVM backend.
//
//===---------------------------------------------------------------------===//

#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/Passes.h"

using namespace llvm;

//===---------------------------------------------------------------------===//
///
/// RegisterRegAlloc class - Track the registration of register allocators.
///
//===---------------------------------------------------------------------===//
MachinePassRegistry RegisterRegAlloc::Registry;

static FunctionPass *createDefaultRegisterAllocator() { return 0; }
static RegisterRegAlloc
defaultRegAlloc("default",
                "pick register allocator based on -O option",
                createDefaultRegisterAllocator);

//===---------------------------------------------------------------------===//
///
/// RegAlloc command line options.
///
//===---------------------------------------------------------------------===//
static cl::opt<RegisterRegAlloc::FunctionPassCtor, false,
               RegisterPassParser<RegisterRegAlloc> >
RegAlloc("regalloc",
         cl::init(&createDefaultRegisterAllocator),
         cl::desc("Register allocator to use"));

//===---------------------------------------------------------------------===//
///
/// createRegisterAllocator - choose the appropriate register allocator.
///
//===---------------------------------------------------------------------===//
FunctionPass *llvm::createRegisterAllocator(CodeGenOpt::Level OptLevel) {
  RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault();

  if (!Ctor) {
    Ctor = RegAlloc;
    RegisterRegAlloc::setDefault(RegAlloc);
  }

  if (Ctor != createDefaultRegisterAllocator)
    return Ctor();

  // When the 'default' allocator is requested, pick one based on OptLevel.
  switch (OptLevel) {
  case CodeGenOpt::None:
    return createLocalRegisterAllocator();
  default:
    return createLinearScanRegisterAllocator();
  }
}
<commit_msg>Use the fast register allocator by default for -O0 builds.<commit_after>//===-- Passes.cpp - Target independent code generation passes ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces to access the target independent code
// generation passes provided by the LLVM backend.
//
//===---------------------------------------------------------------------===//

#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/Passes.h"

using namespace llvm;

//===---------------------------------------------------------------------===//
///
/// RegisterRegAlloc class - Track the registration of register allocators.
///
//===---------------------------------------------------------------------===//
MachinePassRegistry RegisterRegAlloc::Registry;

static FunctionPass *createDefaultRegisterAllocator() { return 0; }
static RegisterRegAlloc
defaultRegAlloc("default",
                "pick register allocator based on -O option",
                createDefaultRegisterAllocator);

//===---------------------------------------------------------------------===//
///
/// RegAlloc command line options.
///
//===---------------------------------------------------------------------===//
static cl::opt<RegisterRegAlloc::FunctionPassCtor, false,
               RegisterPassParser<RegisterRegAlloc> >
RegAlloc("regalloc",
         cl::init(&createDefaultRegisterAllocator),
         cl::desc("Register allocator to use"));

//===---------------------------------------------------------------------===//
///
/// createRegisterAllocator - choose the appropriate register allocator.
///
//===---------------------------------------------------------------------===//
FunctionPass *llvm::createRegisterAllocator(CodeGenOpt::Level OptLevel) {
  RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault();

  if (!Ctor) {
    Ctor = RegAlloc;
    RegisterRegAlloc::setDefault(RegAlloc);
  }

  if (Ctor != createDefaultRegisterAllocator)
    return Ctor();

  // When the 'default' allocator is requested, pick one based on OptLevel.
  switch (OptLevel) {
  case CodeGenOpt::None:
    return createFastRegisterAllocator();
  default:
    return createLinearScanRegisterAllocator();
  }
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 The Regents of the University of California (Regents).
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include "theia/sfm/estimators/estimate_uncalibrated_relative_pose.h"

#include <Eigen/Core>
#include <Eigen/Geometry>
#include <limits>
#include <memory>
#include <vector>

#include "theia/matching/feature_correspondence.h"
#include "theia/sfm/create_and_initialize_ransac_variant.h"
#include "theia/sfm/pose/eight_point_fundamental_matrix.h"
#include "theia/sfm/pose/essential_matrix_utils.h"
#include "theia/sfm/pose/fundamental_matrix_util.h"
#include "theia/sfm/pose/util.h"
#include "theia/sfm/triangulation/triangulation.h"
#include "theia/solvers/estimator.h"
#include "theia/solvers/sample_consensus_estimator.h"
#include "theia/util/util.h"

namespace theia {

using Eigen::Matrix3d;
using Eigen::Vector3d;

namespace {

// An estimator for computing the relative pose from 8 feature correspondences
// (via decomposition of the fundamental matrix).
//
// NOTE: Feature correspondences must be in pixel coordinates with the principal
// point removed i.e. principal point at (0, 0). This also assumes negligible
// skew (which is reasonable for most cameras).
class UncalibratedRelativePoseEstimator
    : public Estimator<FeatureCorrespondence, UncalibratedRelativePose> {
 public:
  UncalibratedRelativePoseEstimator() {}

  // 8 correspondences are needed to determine a fundamental matrix and thus a
  // relative pose.
  double SampleSize() const { return 8; }

  // Estimates candidate relative poses from correspondences.
  bool EstimateModel(
      const std::vector<FeatureCorrespondence>& centered_correspondences,
      std::vector<UncalibratedRelativePose>* relative_poses) const {
    std::vector<Eigen::Vector2d> image1_points, image2_points;
    for (int i = 0; i < 8; i++) {
      image1_points.emplace_back(centered_correspondences[i].feature1);
      image2_points.emplace_back(centered_correspondences[i].feature2);
    }

    UncalibratedRelativePose relative_pose;
    if (!NormalizedEightPointFundamentalMatrix(
            image1_points, image2_points, &relative_pose.fundamental_matrix)) {
      return false;
    }

    // Only consider fundamental matrices that we can decompose focal lengths
    // from.
    if (!FocalLengthsFromFundamentalMatrix(
            relative_pose.fundamental_matrix.data(),
            &relative_pose.focal_length1,
            &relative_pose.focal_length2)) {
      return false;
    }

    // TODO(cmsweeney): Should we check if the focal lengths are reasonable?

    // Compose the essential matrix from the fundamental matrix and focal
    // lengths.
    const Matrix3d essential_matrix =
        Eigen::DiagonalMatrix<double, 3>(relative_pose.focal_length2,
                                         relative_pose.focal_length2,
                                         1.0) *
        relative_pose.fundamental_matrix *
        Eigen::DiagonalMatrix<double, 3>(relative_pose.focal_length1,
                                         relative_pose.focal_length1,
                                         1.0);

    // Normalize the centered_correspondences.
    std::vector<FeatureCorrespondence> normalized_correspondences(
        centered_correspondences.size());
    for (int i = 0; i < centered_correspondences.size(); i++) {
      normalized_correspondences[i].feature1 =
          centered_correspondences[i].feature1 / relative_pose.focal_length1;
      normalized_correspondences[i].feature2 =
          centered_correspondences[i].feature2 / relative_pose.focal_length2;
    }

    GetBestPoseFromEssentialMatrix(essential_matrix,
                                   normalized_correspondences,
                                   &relative_pose.rotation,
                                   &relative_pose.position);
    relative_poses->emplace_back(relative_pose);
    return true;
  }

  // The error for a correspondences given a model. This is the squared sampson
  // error.
  double Error(const FeatureCorrespondence& centered_correspondence,
               const UncalibratedRelativePose& relative_pose) const {
    return SquaredSampsonDistance(relative_pose.fundamental_matrix,
                                  centered_correspondence.feature1,
                                  centered_correspondence.feature2);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(UncalibratedRelativePoseEstimator);
};

}  // namespace

bool EstimateUncalibratedRelativePose(
    const RansacParameters& ransac_params,
    const RansacType& ransac_type,
    const std::vector<FeatureCorrespondence>& centered_correspondences,
    UncalibratedRelativePose* relative_pose,
    RansacSummary* ransac_summary) {
  UncalibratedRelativePoseEstimator relative_pose_estimator;
  std::unique_ptr<SampleConsensusEstimator<UncalibratedRelativePoseEstimator> >
      ransac = CreateAndInitializeRansacVariant(ransac_type,
                                                ransac_params,
                                                relative_pose_estimator);

  // Estimate essential matrix.
  return ransac->Estimate(centered_correspondences,
                          relative_pose,
                          ransac_summary);
}

}  // namespace theia
<commit_msg>Add cheirality check for fundamental matrix estimation<commit_after>// Copyright (C) 2014 The Regents of the University of California (Regents).
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include "theia/sfm/estimators/estimate_uncalibrated_relative_pose.h"

#include <Eigen/Core>
#include <Eigen/Geometry>
#include <limits>
#include <memory>
#include <vector>

#include "theia/matching/feature_correspondence.h"
#include "theia/sfm/create_and_initialize_ransac_variant.h"
#include "theia/sfm/pose/eight_point_fundamental_matrix.h"
#include "theia/sfm/pose/essential_matrix_utils.h"
#include "theia/sfm/pose/fundamental_matrix_util.h"
#include "theia/sfm/pose/util.h"
#include "theia/sfm/triangulation/triangulation.h"
#include "theia/solvers/estimator.h"
#include "theia/solvers/sample_consensus_estimator.h"
#include "theia/util/util.h"

namespace theia {

using Eigen::Matrix3d;
using Eigen::Vector3d;

namespace {

// An estimator for computing the relative pose from 8 feature correspondences
// (via decomposition of the fundamental matrix).
//
// NOTE: Feature correspondences must be in pixel coordinates with the principal
// point removed i.e. principal point at (0, 0). This also assumes negligible
// skew (which is reasonable for most cameras).
class UncalibratedRelativePoseEstimator
    : public Estimator<FeatureCorrespondence, UncalibratedRelativePose> {
 public:
  UncalibratedRelativePoseEstimator() {}

  // 8 correspondences are needed to determine a fundamental matrix and thus a
  // relative pose.
  double SampleSize() const { return 8; }

  // Estimates candidate relative poses from correspondences.
  bool EstimateModel(
      const std::vector<FeatureCorrespondence>& centered_correspondences,
      std::vector<UncalibratedRelativePose>* relative_poses) const {
    std::vector<Eigen::Vector2d> image1_points, image2_points;
    for (int i = 0; i < 8; i++) {
      image1_points.emplace_back(centered_correspondences[i].feature1);
      image2_points.emplace_back(centered_correspondences[i].feature2);
    }

    UncalibratedRelativePose relative_pose;
    if (!NormalizedEightPointFundamentalMatrix(
            image1_points, image2_points, &relative_pose.fundamental_matrix)) {
      return false;
    }

    // Only consider fundamental matrices that we can decompose focal lengths
    // from.
    if (!FocalLengthsFromFundamentalMatrix(
            relative_pose.fundamental_matrix.data(),
            &relative_pose.focal_length1,
            &relative_pose.focal_length2)) {
      return false;
    }

    // TODO(cmsweeney): Should we check if the focal lengths are reasonable?

    // Compose the essential matrix from the fundamental matrix and focal
    // lengths.
    const Matrix3d essential_matrix =
        Eigen::DiagonalMatrix<double, 3>(relative_pose.focal_length2,
                                         relative_pose.focal_length2,
                                         1.0) *
        relative_pose.fundamental_matrix *
        Eigen::DiagonalMatrix<double, 3>(relative_pose.focal_length1,
                                         relative_pose.focal_length1,
                                         1.0);

    // Normalize the centered_correspondences.
    std::vector<FeatureCorrespondence> normalized_correspondences(
        centered_correspondences.size());
    for (int i = 0; i < centered_correspondences.size(); i++) {
      normalized_correspondences[i].feature1 =
          centered_correspondences[i].feature1 / relative_pose.focal_length1;
      normalized_correspondences[i].feature2 =
          centered_correspondences[i].feature2 / relative_pose.focal_length2;
    }

    GetBestPoseFromEssentialMatrix(essential_matrix,
                                   normalized_correspondences,
                                   &relative_pose.rotation,
                                   &relative_pose.position);
    relative_poses->emplace_back(relative_pose);
    return true;
  }

  // The error for a correspondences given a model. This is the squared sampson
  // error.
  double Error(const FeatureCorrespondence& centered_correspondence,
               const UncalibratedRelativePose& relative_pose) const {
    FeatureCorrespondence normalized_correspondence;
    normalized_correspondence.feature1 =
        centered_correspondence.feature1 / relative_pose.focal_length1;
    normalized_correspondence.feature2 =
        centered_correspondence.feature2 / relative_pose.focal_length2;
    if (!IsTriangulatedPointInFrontOfCameras(normalized_correspondence,
                                             relative_pose.rotation,
                                             relative_pose.position)) {
      return std::numeric_limits<double>::max();
    }

    return SquaredSampsonDistance(relative_pose.fundamental_matrix,
                                  centered_correspondence.feature1,
                                  centered_correspondence.feature2);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(UncalibratedRelativePoseEstimator);
};

}  // namespace

bool EstimateUncalibratedRelativePose(
    const RansacParameters& ransac_params,
    const RansacType& ransac_type,
    const std::vector<FeatureCorrespondence>& centered_correspondences,
    UncalibratedRelativePose* relative_pose,
    RansacSummary* ransac_summary) {
  UncalibratedRelativePoseEstimator relative_pose_estimator;
  std::unique_ptr<SampleConsensusEstimator<UncalibratedRelativePoseEstimator> >
      ransac = CreateAndInitializeRansacVariant(ransac_type,
                                                ransac_params,
                                                relative_pose_estimator);

  // Estimate essential matrix.
  return ransac->Estimate(centered_correspondences,
                          relative_pose,
                          ransac_summary);
}

}  // namespace theia
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 Intel Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "core/page/PerformanceUserTiming.h"

#include "bindings/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/page/Performance.h"
#include "core/page/PerformanceMark.h"
#include "core/page/PerformanceMeasure.h"
#include "wtf/text/WTFString.h"

namespace WebCore {

namespace {

typedef HashMap<String, NavigationTimingFunction> RestrictedKeyMap;
static RestrictedKeyMap restrictedKeyMap()
{
    DEFINE_STATIC_LOCAL(RestrictedKeyMap, map, ());
    if (map.isEmpty()) {
        map.add("navigationStart", &PerformanceTiming::navigationStart);
        map.add("unloadEventStart", &PerformanceTiming::unloadEventStart);
        map.add("unloadEventEnd", &PerformanceTiming::unloadEventEnd);
        map.add("redirectStart", &PerformanceTiming::redirectStart);
        map.add("redirectEnd", &PerformanceTiming::redirectEnd);
        map.add("fetchStart", &PerformanceTiming::fetchStart);
        map.add("domainLookupStart", &PerformanceTiming::domainLookupStart);
        map.add("domainLookupEnd", &PerformanceTiming::domainLookupEnd);
        map.add("connectStart", &PerformanceTiming::connectStart);
        map.add("connectEnd", &PerformanceTiming::connectEnd);
        map.add("secureConnectionStart", &PerformanceTiming::secureConnectionStart);
        map.add("requestStart", &PerformanceTiming::requestStart);
        map.add("responseStart", &PerformanceTiming::responseStart);
        map.add("responseEnd", &PerformanceTiming::responseEnd);
        map.add("domLoading", &PerformanceTiming::domLoading);
        map.add("domInteractive", &PerformanceTiming::domInteractive);
        map.add("domContentLoadedEventStart", &PerformanceTiming::domContentLoadedEventStart);
        map.add("domContentLoadedEventEnd", &PerformanceTiming::domContentLoadedEventEnd);
        map.add("domComplete", &PerformanceTiming::domComplete);
        map.add("loadEventStart", &PerformanceTiming::loadEventStart);
        map.add("loadEventEnd", &PerformanceTiming::loadEventEnd);
    }
    return map;
}

} // namespace anonymous

UserTiming::UserTiming(Performance* performance)
    : m_performance(performance)
{
}

static void insertPerformanceEntry(PerformanceEntryMap& performanceEntryMap, PassRefPtr<PerformanceEntry> performanceEntry)
{
    RefPtr<PerformanceEntry> entry = performanceEntry;
    PerformanceEntryMap::iterator it = performanceEntryMap.find(entry->name());
    if (it != performanceEntryMap.end())
        it->value.append(entry);
    else {
        Vector<RefPtr<PerformanceEntry> > v(1);
        v[0] = entry;
        performanceEntryMap.set(entry->name(), v);
    }
}

static void clearPeformanceEntries(PerformanceEntryMap& performanceEntryMap, const String& name)
{
    if (name.isNull()) {
        performanceEntryMap.clear();
        return;
    }

    if (performanceEntryMap.contains(name))
        performanceEntryMap.remove(name);
}

void UserTiming::mark(const String& markName, ExceptionState& es)
{
    if (restrictedKeyMap().contains(markName)) {
        es.throwDOMException(SyntaxError, "'" + markName + "' is part of the PerformanceTiming interface, and cannot be used as a mark name.");
        return;
    }

    double startTime = m_performance->now();
    insertPerformanceEntry(m_marksMap, PerformanceMark::create(markName, startTime));
}

void UserTiming::clearMarks(const String& markName)
{
    clearPeformanceEntries(m_marksMap, markName);
}

double UserTiming::findExistingMarkStartTime(const String& markName, ExceptionState& es)
{
    if (m_marksMap.contains(markName))
        return m_marksMap.get(markName).last()->startTime();

    if (restrictedKeyMap().contains(markName)) {
        double value = static_cast<double>((m_performance->timing()->*(restrictedKeyMap().get(markName)))());
        if (!value) {
            es.throwDOMException(InvalidAccessError, "'" + markName + "' is empty: either the event hasn't happened yet, or it would provide cross-origin timing information.");
            return 0.0;
        }
        return value - m_performance->timing()->navigationStart();
    }

    es.throwDOMException(SyntaxError, "The mark '" + markName + "' does not exist.");
    return 0.0;
}

void UserTiming::measure(const String& measureName, const String& startMark, const String& endMark, ExceptionState& es)
{
    double startTime = 0.0;
    double endTime = 0.0;

    if (startMark.isNull())
        endTime = m_performance->now();
    else if (endMark.isNull()) {
        endTime = m_performance->now();
        startTime = findExistingMarkStartTime(startMark, es);
        if (es.hadException())
            return;
    } else {
        endTime = findExistingMarkStartTime(endMark, es);
        if (es.hadException())
            return;
        startTime = findExistingMarkStartTime(startMark, es);
        if (es.hadException())
            return;
    }

    insertPerformanceEntry(m_measuresMap, PerformanceMeasure::create(measureName, startTime, endTime));
}

void UserTiming::clearMeasures(const String& measureName)
{
    clearPeformanceEntries(m_measuresMap, measureName);
}

static Vector<RefPtr<PerformanceEntry> > convertToEntrySequence(const PerformanceEntryMap& performanceEntryMap)
{
    Vector<RefPtr<PerformanceEntry> > entries;

    for (PerformanceEntryMap::const_iterator it = performanceEntryMap.begin(); it != performanceEntryMap.end(); ++it)
        entries.append(it->value);

    return entries;
}

static Vector<RefPtr<PerformanceEntry> > getEntrySequenceByName(const PerformanceEntryMap& performanceEntryMap, const String& name)
{
    Vector<RefPtr<PerformanceEntry> > entries;

    PerformanceEntryMap::const_iterator it = performanceEntryMap.find(name);
    if (it != performanceEntryMap.end())
        entries.append(it->value);

    return entries;
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMarks() const
{
    return convertToEntrySequence(m_marksMap);
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMarks(const String& name) const
{
    return getEntrySequenceByName(m_marksMap, name);
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMeasures() const
{
    return convertToEntrySequence(m_measuresMap);
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMeasures(const String& name) const
{
    return getEntrySequenceByName(m_measuresMap, name);
}

} // namespace WebCore
<commit_msg>Added UMA instrumentation for site-instrumented user timing marks and measures<commit_after>/*
 * Copyright (C) 2012 Intel Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "core/page/PerformanceUserTiming.h"

#include "bindings/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/page/Performance.h"
#include "core/page/PerformanceMark.h"
#include "core/page/PerformanceMeasure.h"
#include "core/platform/HistogramSupport.h"
#include "wtf/text/WTFString.h"

namespace WebCore {

namespace {

typedef HashMap<String, NavigationTimingFunction> RestrictedKeyMap;
static RestrictedKeyMap restrictedKeyMap()
{
    DEFINE_STATIC_LOCAL(RestrictedKeyMap, map, ());
    if (map.isEmpty()) {
        map.add("navigationStart", &PerformanceTiming::navigationStart);
        map.add("unloadEventStart", &PerformanceTiming::unloadEventStart);
        map.add("unloadEventEnd", &PerformanceTiming::unloadEventEnd);
        map.add("redirectStart", &PerformanceTiming::redirectStart);
        map.add("redirectEnd", &PerformanceTiming::redirectEnd);
        map.add("fetchStart", &PerformanceTiming::fetchStart);
        map.add("domainLookupStart", &PerformanceTiming::domainLookupStart);
        map.add("domainLookupEnd", &PerformanceTiming::domainLookupEnd);
        map.add("connectStart", &PerformanceTiming::connectStart);
        map.add("connectEnd", &PerformanceTiming::connectEnd);
        map.add("secureConnectionStart", &PerformanceTiming::secureConnectionStart);
        map.add("requestStart", &PerformanceTiming::requestStart);
        map.add("responseStart", &PerformanceTiming::responseStart);
        map.add("responseEnd", &PerformanceTiming::responseEnd);
        map.add("domLoading", &PerformanceTiming::domLoading);
        map.add("domInteractive", &PerformanceTiming::domInteractive);
        map.add("domContentLoadedEventStart", &PerformanceTiming::domContentLoadedEventStart);
        map.add("domContentLoadedEventEnd", &PerformanceTiming::domContentLoadedEventEnd);
        map.add("domComplete", &PerformanceTiming::domComplete);
        map.add("loadEventStart", &PerformanceTiming::loadEventStart);
        map.add("loadEventEnd", &PerformanceTiming::loadEventEnd);
    }
    return map;
}

} // namespace anonymous

UserTiming::UserTiming(Performance* performance)
    : m_performance(performance)
{
}

static void insertPerformanceEntry(PerformanceEntryMap& performanceEntryMap, PassRefPtr<PerformanceEntry> performanceEntry)
{
    RefPtr<PerformanceEntry> entry = performanceEntry;
    PerformanceEntryMap::iterator it = performanceEntryMap.find(entry->name());
    if (it != performanceEntryMap.end())
        it->value.append(entry);
    else {
        Vector<RefPtr<PerformanceEntry> > v(1);
        v[0] = entry;
        performanceEntryMap.set(entry->name(), v);
    }
}

static void clearPeformanceEntries(PerformanceEntryMap& performanceEntryMap, const String& name)
{
    if (name.isNull()) {
        performanceEntryMap.clear();
        return;
    }

    if (performanceEntryMap.contains(name))
        performanceEntryMap.remove(name);
}

void UserTiming::mark(const String& markName, ExceptionState& es)
{
    if (restrictedKeyMap().contains(markName)) {
        es.throwDOMException(SyntaxError, "'" + markName + "' is part of the PerformanceTiming interface, and cannot be used as a mark name.");
        return;
    }

    double startTime = m_performance->now();
    insertPerformanceEntry(m_marksMap, PerformanceMark::create(markName, startTime));
    HistogramSupport::histogramCustomCounts("PLT.UserTiming_Mark", static_cast<int>(startTime), 0, 600000, 100);
}

void UserTiming::clearMarks(const String& markName)
{
    clearPeformanceEntries(m_marksMap, markName);
}

double UserTiming::findExistingMarkStartTime(const String& markName, ExceptionState& es)
{
    if (m_marksMap.contains(markName))
        return m_marksMap.get(markName).last()->startTime();

    if (restrictedKeyMap().contains(markName)) {
        double value = static_cast<double>((m_performance->timing()->*(restrictedKeyMap().get(markName)))());
        if (!value) {
            es.throwDOMException(InvalidAccessError, "'" + markName + "' is empty: either the event hasn't happened yet, or it would provide cross-origin timing information.");
            return 0.0;
        }
        return value - m_performance->timing()->navigationStart();
    }

    es.throwDOMException(SyntaxError, "The mark '" + markName + "' does not exist.");
    return 0.0;
}

void UserTiming::measure(const String& measureName, const String& startMark, const String& endMark, ExceptionState& es)
{
    double startTime = 0.0;
    double endTime = 0.0;

    if (startMark.isNull())
        endTime = m_performance->now();
    else if (endMark.isNull()) {
        endTime = m_performance->now();
        startTime = findExistingMarkStartTime(startMark, es);
        if (es.hadException())
            return;
    } else {
        endTime = findExistingMarkStartTime(endMark, es);
        if (es.hadException())
            return;
        startTime = findExistingMarkStartTime(startMark, es);
        if (es.hadException())
            return;
    }

    insertPerformanceEntry(m_measuresMap, PerformanceMeasure::create(measureName, startTime, endTime));
    if (endTime >= startTime)
        HistogramSupport::histogramCustomCounts("PLT.UserTiming_MeasureDuration", static_cast<int>(endTime - startTime), 0, 600000, 100);
}

void UserTiming::clearMeasures(const String& measureName)
{
    clearPeformanceEntries(m_measuresMap, measureName);
}

static Vector<RefPtr<PerformanceEntry> > convertToEntrySequence(const PerformanceEntryMap& performanceEntryMap)
{
    Vector<RefPtr<PerformanceEntry> > entries;

    for (PerformanceEntryMap::const_iterator it = performanceEntryMap.begin(); it != performanceEntryMap.end(); ++it)
        entries.append(it->value);

    return entries;
}

static Vector<RefPtr<PerformanceEntry> > getEntrySequenceByName(const PerformanceEntryMap& performanceEntryMap, const String& name)
{
    Vector<RefPtr<PerformanceEntry> > entries;

    PerformanceEntryMap::const_iterator it = performanceEntryMap.find(name);
    if (it != performanceEntryMap.end())
        entries.append(it->value);

    return entries;
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMarks() const
{
    return convertToEntrySequence(m_marksMap);
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMarks(const String& name) const
{
    return getEntrySequenceByName(m_marksMap, name);
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMeasures() const
{
    return convertToEntrySequence(m_measuresMap);
}

Vector<RefPtr<PerformanceEntry> > UserTiming::getMeasures(const String& name) const
{
    return getEntrySequenceByName(m_measuresMap, name);
}

} // namespace WebCore
<|endoftext|>


<commit_before>// Copyright 2015-2018 Elviss Strazdins. All rights reserved.

#include "StaticMeshRenderer.hpp"
#include "core/Engine.hpp"
#include "utils/Utils.hpp"

namespace ouzel
{
    namespace scene
    {
        StaticMeshData::StaticMeshData(Box3<float> initBoundingBox,
                                       const std::vector<uint32_t> indices,
                                       const std::vector<graphics::Vertex>& vertices,
                                       const std::shared_ptr<graphics::Material>& initMaterial):
            boundingBox(initBoundingBox),
            material(initMaterial)
        {
            indexCount = static_cast<uint32_t>(indices.size());
            indexSize = sizeof(uint32_t);

            indexBuffer = std::make_shared<graphics::Buffer>(*engine->getRenderer(),
                                                             graphics::Buffer::Usage::INDEX, 0,
                                                             indices.data(),
                                                             static_cast<uint32_t>(getVectorSize(indices)));

            vertexBuffer = std::make_shared<graphics::Buffer>(*engine->getRenderer(),
                                                              graphics::Buffer::Usage::VERTEX, 0,
                                                              vertices.data(),
                                                              static_cast<uint32_t>(getVectorSize(vertices)));
        }

        StaticMeshRenderer::StaticMeshRenderer():
            Component(CLASS)
        {
        }

        StaticMeshRenderer::StaticMeshRenderer(const StaticMeshData& meshData):
            Component(CLASS)
        {
            init(meshData);
        }

        StaticMeshRenderer::StaticMeshRenderer(const std::string& filename):
            Component(CLASS)
        {
            init(filename);
        }

        void StaticMeshRenderer::init(const StaticMeshData& meshData)
        {
            boundingBox = meshData.boundingBox;
            material = meshData.material;
            indexCount = meshData.indexCount;
            indexSize = meshData.indexSize;
            indexBuffer = meshData.indexBuffer;
            vertexBuffer = meshData.vertexBuffer;
        }

        void StaticMeshRenderer::init(const std::string& filename)
        {
            init(*engine->getCache().getStaticMeshData(filename));
        }

        void StaticMeshRenderer::draw(const Matrix4<float>& transformMatrix,
                                      float opacity,
                                      const Matrix4<float>& renderViewProjection,
                                      bool wireframe)
        {
            Component::draw(transformMatrix,
                            opacity,
                            renderViewProjection,
                            wireframe);

            Matrix4<float> modelViewProj = renderViewProjection * transformMatrix;
            float colorVector[] = {material->diffuseColor.normR(), material->diffuseColor.normG(), material->diffuseColor.normB(), material->diffuseColor.normA() * opacity * material->opacity};

            std::vector<std::vector<float>> fragmentShaderConstants(1);
            fragmentShaderConstants[0] = {std::begin(colorVector), std::end(colorVector)};

            std::vector<std::vector<float>> vertexShaderConstants(1);
            vertexShaderConstants[0] = {std::begin(modelViewProj.m), std::end(modelViewProj.m)};

            std::vector<uintptr_t> textures;
            for (const std::shared_ptr<graphics::Texture>& texture : material->textures)
                textures.push_back(texture ? texture->getResource() : 0);

            engine->getRenderer()->setCullMode(material->cullMode);
            engine->getRenderer()->setPipelineState(material->blendState->getResource(),
                                                    material->shader->getResource());
            engine->getRenderer()->setShaderConstants(fragmentShaderConstants,
                                                      vertexShaderConstants);
            engine->getRenderer()->setTextures(textures);
            engine->getRenderer()->draw(indexBuffer->getResource(),
                                        indexCount,
                                        indexSize,
                                        vertexBuffer->getResource(),
                                        graphics::DrawMode::TRIANGLE_LIST,
                                        0);
        }
    } // namespace scene
} // namespace ouzel
<commit_msg>Use 16-bit index buffer for static meshes if 32-bits are not needed<commit_after>// Copyright 2015-2018 Elviss Strazdins. All rights reserved.

#include <limits>
#include "StaticMeshRenderer.hpp"
#include "core/Engine.hpp"
#include "utils/Utils.hpp"

namespace ouzel
{
    namespace scene
    {
        StaticMeshData::StaticMeshData(Box3<float> initBoundingBox,
                                       const std::vector<uint32_t> indices,
                                       const std::vector<graphics::Vertex>& vertices,
                                       const std::shared_ptr<graphics::Material>& initMaterial):
            boundingBox(initBoundingBox),
            material(initMaterial)
        {
            indexCount = static_cast<uint32_t>(indices.size());

            indexSize = sizeof(uint16_t);

            for (uint32_t index : indices)
                if (index > std::numeric_limits<uint16_t>::max())
                {
                    indexSize = sizeof(uint32_t);
                    break;
                }

            if (indexSize == sizeof(uint16_t))
            {
                std::vector<uint16_t> convertedIndices;
                convertedIndices.reserve(indices.size());

                for (uint32_t index : indices)
                    convertedIndices.push_back(static_cast<uint16_t>(index));

                indexBuffer = std::make_shared<graphics::Buffer>(*engine->getRenderer(),
                                                                 graphics::Buffer::Usage::INDEX, 0,
                                                                 convertedIndices.data(),
                                                                 static_cast<uint32_t>(getVectorSize(convertedIndices)));
            }
            else if (indexSize == sizeof(uint32_t))
                indexBuffer = std::make_shared<graphics::Buffer>(*engine->getRenderer(),
                                                                 graphics::Buffer::Usage::INDEX, 0,
                                                                 indices.data(),
                                                                 static_cast<uint32_t>(getVectorSize(indices)));

            vertexBuffer = std::make_shared<graphics::Buffer>(*engine->getRenderer(),
                                                              graphics::Buffer::Usage::VERTEX, 0,
                                                              vertices.data(),
                                                              static_cast<uint32_t>(getVectorSize(vertices)));
        }

        StaticMeshRenderer::StaticMeshRenderer():
            Component(CLASS)
        {
        }

        StaticMeshRenderer::StaticMeshRenderer(const StaticMeshData& meshData):
            Component(CLASS)
        {
            init(meshData);
        }

        StaticMeshRenderer::StaticMeshRenderer(const std::string& filename):
            Component(CLASS)
        {
            init(filename);
        }

        void StaticMeshRenderer::init(const StaticMeshData& meshData)
        {
            boundingBox = meshData.boundingBox;
            material = meshData.material;
            indexCount = meshData.indexCount;
            indexSize = meshData.indexSize;
            indexBuffer = meshData.indexBuffer;
            vertexBuffer = meshData.vertexBuffer;
        }

        void StaticMeshRenderer::init(const std::string& filename)
        {
            init(*engine->getCache().getStaticMeshData(filename));
        }

        void StaticMeshRenderer::draw(const Matrix4<float>& transformMatrix,
                                      float opacity,
                                      const Matrix4<float>& renderViewProjection,
                                      bool wireframe)
        {
            Component::draw(transformMatrix,
                            opacity,
                            renderViewProjection,
                            wireframe);

            Matrix4<float> modelViewProj = renderViewProjection * transformMatrix;
            float colorVector[] = {material->diffuseColor.normR(), material->diffuseColor.normG(), material->diffuseColor.normB(), material->diffuseColor.normA() * opacity * material->opacity};

            std::vector<std::vector<float>> fragmentShaderConstants(1);
            fragmentShaderConstants[0] = {std::begin(colorVector), std::end(colorVector)};

            std::vector<std::vector<float>> vertexShaderConstants(1);
            vertexShaderConstants[0] = {std::begin(modelViewProj.m), std::end(modelViewProj.m)};

            std::vector<uintptr_t> textures;
            for (const std::shared_ptr<graphics::Texture>& texture : material->textures)
                textures.push_back(texture ? texture->getResource() : 0);

            engine->getRenderer()->setCullMode(material->cullMode);
            engine->getRenderer()->setPipelineState(material->blendState->getResource(),
                                                    material->shader->getResource());
            engine->getRenderer()->setShaderConstants(fragmentShaderConstants,
                                                      vertexShaderConstants);
            engine->getRenderer()->setTextures(textures);
            engine->getRenderer()->draw(indexBuffer->getResource(),
                                        indexCount,
                                        indexSize,
                                        vertexBuffer->getResource(),
                                        graphics::DrawMode::TRIANGLE_LIST,
                                        0);
        }
    } // namespace scene
} // namespace ouzel
<|endoftext|>


<commit_before>#include <tests/Base.hh>

#include <cmath>

#include <aleph/geometry/CoverTree.hh>

using namespace aleph::geometry;

template <class T> struct SimpleMetric
{
  T operator()( T a, T b )
  {
    return std::abs( a - b );
  }
};

template <class T> void testSimple()
{
  ALEPH_TEST_BEGIN( "Simple" );

  CoverTree<T,
            SimpleMetric<T> > ct;

  ct.insert( 7 );
  ct.insert( 13 );
  ct.insert( 10 );
  ct.insert( 8 );
  ct.insert( 9 );
  ct.insert( 11 );
  ct.insert( 12 );

  ct.print( std::cerr );

  ALEPH_ASSERT_THROW( ct.checkLevelInvariant() );
  ALEPH_ASSERT_THROW( ct.checkCoveringInvariant() );
  ALEPH_ASSERT_THROW( ct.checkSeparatingInvariant() );

  ALEPH_TEST_END();
}

template <class T> void testSimplePermutations()
{
  ALEPH_TEST_BEGIN( "Simple (using permutations)" );

  std::vector<T> data = {7,8,9,10,11,12,13};

  do
  {
    CoverTree<T,
              SimpleMetric<T> > ct;

    // Debug output ----------------------------------------------------

    std::cerr << "Permutation: ";

    for( auto&& x : data )
      std::cerr << x << " ";

    std::cerr << "\n";

    // Check validity of tree ------------------------------------------

    for( auto&& x : data )
      ct.insert( x );

    ALEPH_ASSERT_THROW( ct.checkLevelInvariant() );
    ALEPH_ASSERT_THROW( ct.checkCoveringInvariant() );
    ALEPH_ASSERT_THROW( ct.checkSeparatingInvariant() );
  }
  while( std::next_permutation( data.begin(), data.end() ) );

  ALEPH_TEST_END();
}

int main( int, char** )
{
  testSimple<double>();
  testSimple<float> ();

  testSimplePermutations<double>();
  testSimplePermutations<float> ();
}
<commit_msg>Added 2D test case for cover tree<commit_after>#include <tests/Base.hh>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <cmath>

#include <aleph/geometry/CoverTree.hh>

using namespace aleph::geometry;

template <class T> struct SimpleMetric
{
  T operator()( T a, T b )
  {
    return std::abs( a - b );
  }
};

template <class T> void testSimple()
{
  ALEPH_TEST_BEGIN( "Simple" );

  CoverTree<T,
            SimpleMetric<T> > ct;

  ct.insert( 7 );
  ct.insert( 13 );
  ct.insert( 10 );
  ct.insert( 8 );
  ct.insert( 9 );
  ct.insert( 11 );
  ct.insert( 12 );

  ct.print( std::cerr );

  ALEPH_ASSERT_THROW( ct.checkLevelInvariant() );
  ALEPH_ASSERT_THROW( ct.checkCoveringInvariant() );
  ALEPH_ASSERT_THROW( ct.checkSeparatingInvariant() );

  ALEPH_TEST_END();
}

template <class T> void testSimplePermutations()
{
  ALEPH_TEST_BEGIN( "Simple (using permutations)" );

  std::vector<T> data = {7,8,9,10,11,12,13};

  do
  {
    CoverTree<T,
              SimpleMetric<T> > ct;

    // Debug output ----------------------------------------------------

    std::cerr << "Permutation: ";

    for( auto&& x : data )
      std::cerr << x << " ";

    std::cerr << "\n";

    // Check validity of tree ------------------------------------------

    for( auto&& x : data )
      ct.insert( x );

    ALEPH_ASSERT_THROW( ct.checkLevelInvariant() );
    ALEPH_ASSERT_THROW( ct.checkCoveringInvariant() );
    ALEPH_ASSERT_THROW( ct.checkSeparatingInvariant() );
  }
  while( std::next_permutation( data.begin(), data.end() ) );

  ALEPH_TEST_END();
}

template <class T> struct Point
{
  T x;
  T y;
};

template <class T> std::ostream& operator<<( std::ostream& o, const Point<T>& p )
{
  o << p.x << "," << p.y << "\n";
  return o;
}

template <class T> struct EuclideanMetric
{
  T operator()( Point<T> a, Point<T> b )
  {
    return std::sqrt( std::pow( a.x - b.x, T(2) ) + std::pow( a.y - b.y, T(2) ) );
  }
};

template <class T> void test2D()
{
  ALEPH_TEST_BEGIN( "2D" );

  using Point     = Point<T>;
  using Metric    = EuclideanMetric<T>;
  using CoverTree = CoverTree<Point, Metric>;

  CoverTree ct;

  std::ifstream in( CMAKE_SOURCE_DIR + std::string( "/tests/input/Cover_tree_simple.txt" ) );
  ALEPH_ASSERT_THROW( in );

  std::vector<Point> points;

  std::string line;
  while( std::getline( in, line ) )
  {
    std::stringstream converter( line );

    T x = T();
    T y = T();

    converter >> x
              >> y;

    ALEPH_ASSERT_THROW( not converter.fail() );

    points.push_back( {x,y} );
  }

  ALEPH_ASSERT_EQUAL( points.size(), 15 );

  for( auto&& p : points )
    ct.insert( p );

  ct.print( std::cerr );

  ALEPH_ASSERT_THROW( ct.isValid() );
  ALEPH_TEST_END();
}

int main( int, char** )
{
  testSimple<double>();
  testSimple<float> ();

  testSimplePermutations<double>();
  testSimplePermutations<float> ();

  test2D<double>();
  test2D<float> ();
}
<|endoftext|>