<commit_before>#include "external/petscvector/common/femhat.h"

namespace pascinference {
namespace common {

template<>
FemHat<PetscVector>::FemHat(Decomposition<PetscVector> *decomposition1, Decomposition<PetscVector> *decomposition2, double fem_reduce) : Fem<PetscVector>(decomposition1, decomposition2, fem_reduce){
	LOG_FUNC_BEGIN

	#ifdef USE_CUDA
		/* compute optimal kernel calls */
		externalcontent->cuda_occupancy();
		gridSize_reduce = (decomposition2->get_Tlocal() + blockSize_reduce - 1)/ blockSize_reduce;
		gridSize_prolongate = (decomposition1->get_Tlocal() + blockSize_prolongate - 1)/ blockSize_prolongate;
	#endif

	this->diff = (decomposition1->get_T() - 1)/(double)(decomposition2->get_T() - 1);

	compute_overlaps();

	LOG_FUNC_END
}

template<>
void FemHat<PetscVector>::reduce_gamma(GeneralVector<PetscVector> *gamma1, GeneralVector<PetscVector> *gamma2) const {
	LOG_FUNC_BEGIN

	double *gammak1_arr;
	double *gammak2_arr;

	Vec gamma1_Vec = gamma1->get_vector();
	Vec gamma2_Vec = gamma2->get_vector();

	#ifdef USE_CUDA
		TRYCXX( VecCUDACopyToGPU(gamma1_Vec) );
		TRYCXX( VecCUDACopyToGPU(gamma2_Vec) );
	#endif

	Vec gammak1_Vec;
	Vec gammak2_Vec;

	IS gammak1_is;
	IS gammak2_is;

	/* stuff for getting subvector for local computation */
	IS gammak1_sublocal_is;
	Vec gammak1_sublocal_Vec;

	for(int k=0;k<this->decomposition2->get_K();k++){

		/* get gammak */
		this->decomposition1->createIS_gammaK(&gammak1_is, k);
		this->decomposition2->createIS_gammaK(&gammak2_is, k);

		TRYCXX( VecGetSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecGetSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		/* get local necessary part for local computation */
		TRYCXX( ISCreateStride(PETSC_COMM_WORLD, right_t1_idx - left_t1_idx, left_t1_idx, 1, &gammak1_sublocal_is) );
		TRYCXX( VecGetSubVector(gammak1_Vec, gammak1_sublocal_is, &gammak1_sublocal_Vec) );

		#ifndef USE_CUDA
			/* sequential version */
			TRYCXX( VecGetArray(gammak1_sublocal_Vec,&gammak1_arr) );
			TRYCXX( VecGetArray(gammak2_Vec,&gammak2_arr) );

			int Tbegin2 = this->decomposition2->get_Tbegin();

			//TODO: OpenMP?
			for(int t2=0; t2 < this->decomposition2->get_Tlocal(); t2++){
				double center_t1 = (Tbegin2+t2)*diff;
				double left_t1 = (Tbegin2+t2-1)*diff;
				double right_t1 = (Tbegin2+t2+1)*diff;

				int id_counter = floor(left_t1) - left_t1_idx; /* first index in provided local t1 array */

				double phi_value; /* value of basis function */

				/* left part of hat function */
				double mysum = 0.0;
				int t1 = floor(left_t1);

				/* compute linear combination with coefficients given by basis functions */
				while(t1 <= center_t1){
					phi_value = (t1 - left_t1)/(center_t1 - left_t1);
					if(id_counter >= 0){
						mysum += phi_value*gammak1_arr[id_counter];
					}
					t1 += 1;
					id_counter += 1;
				}

				/* right part of hat function */
				while(t1 < right_t1){
					phi_value = (t1 - right_t1)/(center_t1 - right_t1);
					if(id_counter < right_t1_idx - left_t1_idx){
						mysum += phi_value*gammak1_arr[id_counter];
					}
					t1 += 1;
					id_counter += 1;
				}

				gammak2_arr[t2] = mysum;
			}

			TRYCXX( VecRestoreArray(gammak1_sublocal_Vec,&gammak1_arr) );
			TRYCXX( VecRestoreArray(gammak2_Vec,&gammak2_arr) );

		#else
			/* cuda version */
			TRYCXX( VecCUDAGetArrayReadWrite(gammak1_sublocal_Vec,&gammak1_arr) );
			TRYCXX( VecCUDAGetArrayReadWrite(gammak2_Vec,&gammak2_arr) );

			externalcontent->cuda_reduce_data(gammak1_arr, gammak2_arr, this->decomposition1->get_T(), this->decomposition2->get_T(), this->decomposition1->get_Tbegin(), this->decomposition2->get_Tbegin(), this->decomposition1->get_Tlocal(), this->decomposition2->get_Tlocal(), left_t1_idx, right_t1_idx, left_t2_idx, right_t2_idx, diff);

			TRYCXX( VecCUDARestoreArrayReadWrite(gammak1_sublocal_Vec,&gammak1_arr) );
			TRYCXX( VecCUDARestoreArrayReadWrite(gammak2_Vec,&gammak2_arr) );
		#endif

		/* restore local necessary part for local computation */
		TRYCXX( VecRestoreSubVector(gammak1_Vec, gammak1_sublocal_is, &gammak1_sublocal_Vec) );
		TRYCXX( ISDestroy(&gammak1_sublocal_is) );

		TRYCXX( VecRestoreSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecRestoreSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		TRYCXX( ISDestroy(&gammak1_is) );
		TRYCXX( ISDestroy(&gammak2_is) );

	}

	LOG_FUNC_END
}

template<>
void FemHat<PetscVector>::prolongate_gamma(GeneralVector<PetscVector> *gamma2, GeneralVector<PetscVector> *gamma1) const {
	LOG_FUNC_BEGIN

	double *gammak1_arr;
	double *gammak2_arr;

	Vec gamma1_Vec = gamma1->get_vector();
	Vec gamma2_Vec = gamma2->get_vector();

	#ifdef USE_CUDA
		TRYCXX( VecCUDACopyToGPU(gamma1_Vec) );
		TRYCXX( VecCUDACopyToGPU(gamma2_Vec) );
	#endif

	Vec gammak1_Vec;
	Vec gammak2_Vec;

	IS gammak1_is;
	IS gammak2_is;

	/* stuff for getting subvector for local computation */
	IS gammak2_sublocal_is;
	Vec gammak2_sublocal_Vec;

	for(int k=0;k<this->decomposition2->get_K();k++){

		/* get gammak */
		this->decomposition1->createIS_gammaK(&gammak1_is, k);
		this->decomposition2->createIS_gammaK(&gammak2_is, k);

		TRYCXX( VecGetSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecGetSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		TRYCXX( ISCreateStride(PETSC_COMM_WORLD, right_t2_idx - left_t2_idx + 1, left_t2_idx, 1, &gammak2_sublocal_is) );
		TRYCXX( VecGetSubVector(gammak2_Vec, gammak2_sublocal_is, &gammak2_sublocal_Vec) );

		#ifndef USE_CUDA
			TRYCXX( VecGetArray(gammak1_Vec,&gammak1_arr) );
			TRYCXX( VecGetArray(gammak2_sublocal_Vec,&gammak2_arr) );

			int Tbegin1 = this->decomposition1->get_Tbegin();

			//TODO: OpenMP?
			for(int t1=0; t1 < this->decomposition1->get_Tlocal(); t1++){
				int t2_left_id_orig = floor((t1 + Tbegin1)/diff);
				int t2_right_id_orig = floor((t1 + Tbegin1)/diff) + 1;

				double t1_left = t2_left_id_orig*diff;
				double t1_right = t2_right_id_orig*diff;

				int t2_left_id = t2_left_id_orig - left_t2_idx;
				int t2_right_id = t2_right_id_orig - left_t2_idx;

				/* value of basis functions */
				double t1_value = 0.0;
				double phi_value_left = (t1 + Tbegin1 - t1_left)/(t1_right - t1_left);
				t1_value += phi_value_left*gammak2_arr[t2_right_id];

				double phi_value_right = (t1 + Tbegin1 - t1_right)/(t1_left - t1_right);
				t1_value += phi_value_right*gammak2_arr[t2_left_id];

				gammak1_arr[t1] = t1_value;
			}

			TRYCXX( VecRestoreArray(gammak1_Vec,&gammak1_arr) );
			TRYCXX( VecRestoreArray(gammak2_sublocal_Vec,&gammak2_arr) );
		#else
			/* cuda version */
			TRYCXX( VecCUDAGetArrayReadWrite(gammak1_Vec,&gammak1_arr) );
			TRYCXX( VecCUDAGetArrayReadWrite(gammak2_sublocal_Vec,&gammak2_arr) );

			externalcontent->cuda_prolongate_data(gammak1_arr, gammak2_arr, this->decomposition1->get_T(), this->decomposition2->get_T(), this->decomposition1->get_Tbegin(), this->decomposition2->get_Tbegin(), this->decomposition1->get_Tlocal(), this->decomposition2->get_Tlocal(), left_t1_idx, right_t1_idx, left_t2_idx, right_t2_idx, diff);

			TRYCXX( VecCUDARestoreArrayReadWrite(gammak1_Vec,&gammak1_arr) );
			TRYCXX( VecCUDARestoreArrayReadWrite(gammak2_sublocal_Vec,&gammak2_arr) );

		#endif

		/* restore local necessary part for local computation */
		TRYCXX( VecRestoreSubVector(gammak2_Vec, gammak2_sublocal_is, &gammak2_sublocal_Vec) );
		TRYCXX( ISDestroy(&gammak2_sublocal_is) );

		TRYCXX( VecRestoreSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecRestoreSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		TRYCXX( ISDestroy(&gammak1_is) );
		TRYCXX( ISDestroy(&gammak2_is) );
	}

	LOG_FUNC_END
}

}
} /* end of namespace */

<commit_msg>working on gpu<commit_after>#include "external/petscvector/common/femhat.h"

namespace pascinference {
namespace common {

template<>
FemHat<PetscVector>::FemHat(Decomposition<PetscVector> *decomposition1, Decomposition<PetscVector> *decomposition2, double fem_reduce) : Fem<PetscVector>(decomposition1, decomposition2, fem_reduce){
	LOG_FUNC_BEGIN

	#ifdef USE_CUDA
		/* compute optimal kernel calls */
		externalcontent->cuda_occupancy();
		gridSize_reduce = (decomposition2->get_Tlocal() + blockSize_reduce - 1)/ blockSize_reduce;
		gridSize_prolongate = (decomposition1->get_Tlocal() + blockSize_prolongate - 1)/ blockSize_prolongate;
	#endif

	this->diff = (decomposition1->get_T() - 1)/(double)(decomposition2->get_T() - 1);

	compute_overlaps();

	LOG_FUNC_END
}

template<>
void FemHat<PetscVector>::reduce_gamma(GeneralVector<PetscVector> *gamma1, GeneralVector<PetscVector> *gamma2) const {
	LOG_FUNC_BEGIN

	double *gammak1_arr;
	double *gammak2_arr;

	Vec gamma1_Vec = gamma1->get_vector();
	Vec gamma2_Vec = gamma2->get_vector();

	#ifdef USE_CUDA
		TRYCXX( VecCUDACopyToGPU(gamma1_Vec) );
		TRYCXX( VecCUDACopyToGPU(gamma2_Vec) );
	#endif

	Vec gammak1_Vec;
	Vec gammak2_Vec;

	IS gammak1_is;
	IS gammak2_is;

	/* stuff for getting subvector for local computation */
	IS gammak1_sublocal_is;
	Vec gammak1_sublocal_Vec;

	for(int k=0;k<this->decomposition2->get_K();k++){

		/* get gammak */
		this->decomposition1->createIS_gammaK(&gammak1_is, k);
		this->decomposition2->createIS_gammaK(&gammak2_is, k);

		TRYCXX( VecGetSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecGetSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		/* get local necessary part for local computation */
		TRYCXX( ISCreateStride(PETSC_COMM_WORLD, right_t1_idx - left_t1_idx, left_t1_idx, 1, &gammak1_sublocal_is) );
		TRYCXX( VecGetSubVector(gammak1_Vec, gammak1_sublocal_is, &gammak1_sublocal_Vec) );

		#ifndef USE_CUDA
			/* sequential version */
			TRYCXX( VecGetArray(gammak1_sublocal_Vec,&gammak1_arr) );
			TRYCXX( VecGetArray(gammak2_Vec,&gammak2_arr) );

			int Tbegin2 = this->decomposition2->get_Tbegin();

			//TODO: OpenMP?
			for(int t2=0; t2 < this->decomposition2->get_Tlocal(); t2++){
				double center_t1 = (Tbegin2+t2)*diff;
				double left_t1 = (Tbegin2+t2-1)*diff;
				double right_t1 = (Tbegin2+t2+1)*diff;

				int id_counter = floor(left_t1) - left_t1_idx; /* first index in provided local t1 array */

				double phi_value; /* value of basis function */

				/* left part of hat function */
				double mysum = 0.0;
				int t1 = floor(left_t1);

				/* compute linear combination with coefficients given by basis functions */
				while(t1 <= center_t1){
					phi_value = (t1 - left_t1)/(center_t1 - left_t1);
					if(id_counter >= 0){
						mysum += phi_value*gammak1_arr[id_counter];
					}
					t1 += 1;
					id_counter += 1;
				}

				/* right part of hat function */
				while(t1 < right_t1){
					phi_value = (t1 - right_t1)/(center_t1 - right_t1);
					if(id_counter < right_t1_idx - left_t1_idx){
						mysum += phi_value*gammak1_arr[id_counter];
					}
					t1 += 1;
					id_counter += 1;
				}

				gammak2_arr[t2] = mysum;
			}

			TRYCXX( VecRestoreArray(gammak1_sublocal_Vec,&gammak1_arr) );
			TRYCXX( VecRestoreArray(gammak2_Vec,&gammak2_arr) );

		#else
			/* cuda version */
			externalcontent->cuda_reduce_data(gammak1_sublocal_Vec, gammak2_Vec, this->decomposition1->get_T(), this->decomposition2->get_T(), this->decomposition1->get_Tbegin(), this->decomposition2->get_Tbegin(), this->decomposition1->get_Tlocal(), this->decomposition2->get_Tlocal(), left_t1_idx, right_t1_idx, left_t2_idx, right_t2_idx, diff);
		#endif

		/* restore local necessary part for local computation */
		TRYCXX( VecRestoreSubVector(gammak1_Vec, gammak1_sublocal_is, &gammak1_sublocal_Vec) );
		TRYCXX( ISDestroy(&gammak1_sublocal_is) );

		TRYCXX( VecRestoreSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecRestoreSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		TRYCXX( ISDestroy(&gammak1_is) );
		TRYCXX( ISDestroy(&gammak2_is) );

	}

	LOG_FUNC_END
}

template<>
void FemHat<PetscVector>::prolongate_gamma(GeneralVector<PetscVector> *gamma2, GeneralVector<PetscVector> *gamma1) const {
	LOG_FUNC_BEGIN

	double *gammak1_arr;
	double *gammak2_arr;

	Vec gamma1_Vec = gamma1->get_vector();
	Vec gamma2_Vec = gamma2->get_vector();

	#ifdef USE_CUDA
		TRYCXX( VecCUDACopyToGPU(gamma1_Vec) );
		TRYCXX( VecCUDACopyToGPU(gamma2_Vec) );
	#endif

	Vec gammak1_Vec;
	Vec gammak2_Vec;

	IS gammak1_is;
	IS gammak2_is;

	/* stuff for getting subvector for local computation */
	IS gammak2_sublocal_is;
	Vec gammak2_sublocal_Vec;

	for(int k=0;k<this->decomposition2->get_K();k++){

		/* get gammak */
		this->decomposition1->createIS_gammaK(&gammak1_is, k);
		this->decomposition2->createIS_gammaK(&gammak2_is, k);

		TRYCXX( VecGetSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecGetSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		TRYCXX( ISCreateStride(PETSC_COMM_WORLD, right_t2_idx - left_t2_idx + 1, left_t2_idx, 1, &gammak2_sublocal_is) );
		TRYCXX( VecGetSubVector(gammak2_Vec, gammak2_sublocal_is, &gammak2_sublocal_Vec) );

		#ifndef USE_CUDA
			TRYCXX( VecGetArray(gammak1_Vec,&gammak1_arr) );
			TRYCXX( VecGetArray(gammak2_sublocal_Vec,&gammak2_arr) );

			int Tbegin1 = this->decomposition1->get_Tbegin();

			//TODO: OpenMP?
			for(int t1=0; t1 < this->decomposition1->get_Tlocal(); t1++){
				int t2_left_id_orig = floor((t1 + Tbegin1)/diff);
				int t2_right_id_orig = floor((t1 + Tbegin1)/diff) + 1;

				double t1_left = t2_left_id_orig*diff;
				double t1_right = t2_right_id_orig*diff;

				int t2_left_id = t2_left_id_orig - left_t2_idx;
				int t2_right_id = t2_right_id_orig - left_t2_idx;

				/* value of basis functions */
				double t1_value = 0.0;
				double phi_value_left = (t1 + Tbegin1 - t1_left)/(t1_right - t1_left);
				t1_value += phi_value_left*gammak2_arr[t2_right_id];

				double phi_value_right = (t1 + Tbegin1 - t1_right)/(t1_left - t1_right);
				t1_value += phi_value_right*gammak2_arr[t2_left_id];

				gammak1_arr[t1] = t1_value;
			}

			TRYCXX( VecRestoreArray(gammak1_Vec,&gammak1_arr) );
			TRYCXX( VecRestoreArray(gammak2_sublocal_Vec,&gammak2_arr) );
		#else
			/* cuda version */
			externalcontent->cuda_prolongate_data(gammak1_Vec, gammak2_sublocal_Vec, this->decomposition1->get_T(), this->decomposition2->get_T(), this->decomposition1->get_Tbegin(), this->decomposition2->get_Tbegin(), this->decomposition1->get_Tlocal(), this->decomposition2->get_Tlocal(), left_t1_idx, right_t1_idx, left_t2_idx, right_t2_idx, diff);
		#endif

		/* restore local necessary part for local computation */
		TRYCXX( VecRestoreSubVector(gammak2_Vec, gammak2_sublocal_is, &gammak2_sublocal_Vec) );
		TRYCXX( ISDestroy(&gammak2_sublocal_is) );

		TRYCXX( VecRestoreSubVector(gamma1_Vec, gammak1_is, &gammak1_Vec) );
		TRYCXX( VecRestoreSubVector(gamma2_Vec, gammak2_is, &gammak2_Vec) );

		TRYCXX( ISDestroy(&gammak1_is) );
		TRYCXX( ISDestroy(&gammak2_is) );
	}

	LOG_FUNC_END
}

}
} /* end of namespace */

<|endoftext|>


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

#ifndef BASE_PUBLISHER_HPP
#define BASE_PUBLISHER_HPP

#include <algorithm>
#include <iostream>
#include <string>

#include <alvalue/alvalue.h>
#include <qi/session.hpp>

#include <alrosbridge/tools.hpp>

namespace alros
{
namespace publisher
{

// CRTP
template<class T>
class BasePublisher
{

public:
  BasePublisher( const std::string& name, const std::string& topic, float frequency, qi::SessionPtr session ):
    name_( name ),
    topic_( topic ),
    frequency_( frequency ),
    is_initialized_( false ),
    robot_( UNIDENTIFIED ),
    session_(session)
  {}

  virtual ~BasePublisher() {};

  inline std::string name() const
  {
    return name_;
  }

  inline std::string topic() const
  {
    return topic_;
  }

  inline float frequency() const
  {
    return frequency_;
  }

  inline bool isInitialized() const
  {
    return is_initialized_;
  }

  /** Function that returns the type of a robot
   */
  inline Robot robot() const
  {
    if (robot_ != UNIDENTIFIED)
      return robot_;

    qi::AnyObject p_memory = session_->service("ALMemory");
    std::string robot = p_memory.call<AL::ALValue>("getData", "RobotConfig/Body/Type" );
    std::transform(robot.begin(), robot.end(), robot.begin(), ::tolower);

    if (std::string(robot) == "nao")
      robot_ = NAO;
      return robot_;
    if (std::string(robot) == "pepper")
      robot_ = PEPPER;
      return robot_;
    else
      return UNIDENTIFIED;
  }

  virtual bool isSubscribed() const = 0;

protected:
  std::string name_, topic_;

  bool is_initialized_;

  /** Frequency at which the publisher should publish. This is informative */
  float frequency_;
  /** The type of the robot */
  mutable Robot robot_;

  /** Pointer to a session from which we can create proxies */
  qi::SessionPtr session_;
}; // class

} //publisher
} // alros

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

#ifndef BASE_PUBLISHER_HPP
#define BASE_PUBLISHER_HPP

#include <algorithm>
#include <iostream>
#include <string>

#include <alvalue/alvalue.h>
#include <qi/session.hpp>

#include <alrosbridge/tools.hpp>

namespace alros
{
namespace publisher
{

// CRTP
template<class T>
class BasePublisher
{

public:
  BasePublisher( const std::string& name, const std::string& topic, float frequency, qi::SessionPtr session ):
    name_( name ),
    topic_( topic ),
    frequency_( frequency ),
    is_initialized_( false ),
    robot_( UNIDENTIFIED ),
    session_(session)
  {}

  virtual ~BasePublisher() {};

  inline std::string name() const
  {
    return name_;
  }

  inline std::string topic() const
  {
    return topic_;
  }

  inline float frequency() const
  {
    return frequency_;
  }

  inline bool isInitialized() const
  {
    return is_initialized_;
  }

  /** Function that returns the type of a robot
   */
  inline Robot robot() const
  {
    if (robot_ != UNIDENTIFIED)
      return robot_;

    qi::AnyObject p_memory = session_->service("ALMemory");
    std::string robot = p_memory.call<AL::ALValue>("getData", "RobotConfig/Body/Type" );
    std::transform(robot.begin(), robot.end(), robot.begin(), ::tolower);

    if (std::string(robot) == "nao")
      robot_ = NAO;
    else if (std::string(robot) == "pepper")
      robot_ = PEPPER;
    else
      robot_ = UNIDENTIFIED;
    return robot_;
  }

  virtual bool isSubscribed() const = 0;

protected:
  std::string name_, topic_;

  bool is_initialized_;

  /** Frequency at which the publisher should publish. This is informative */
  float frequency_;
  /** The type of the robot */
  mutable Robot robot_;

  /** Pointer to a session from which we can create proxies */
  qi::SessionPtr session_;
}; // class

} //publisher
} // alros

#endif
<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  pipeline_fixed/window_control.cpp                                               */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "window_control.hpp"

// includes, system

#include <hugh/render/software/buffer/color.hpp>
#include <hugh/render/software/buffer/depth.hpp>
#include <hugh/render/software/pipelines.hpp>
#include <hugh/render/software/primitives.hpp>
#include <hugh/render/software/rasterizer/simple.hpp>

// includes, project

#include <gtkmm_wrap/check_button_input.hpp>
#include <gtkmm_wrap/radio_button_input.hpp>
#include <gtkmm_wrap/utilities.hpp>

#define HUGH_USE_TRACE
//#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  enum pipeline_enum { direct3d, opengl, };

  // variables, internal

  // functions, internal

} // namespace {

// variables, exported

// functions, exported

/* explicit */
window_control::window_control()
  : hugh::gtkmm::window(),
    viewport_          (0, 0, 320, 240, 0, 1),
    pipeline_          (nullptr),
    win_color_         (nullptr),
    win_depth_         (nullptr)
{
  TRACE("window_control::window_control");

  {
    set_title             ("pipeline::fixed");
    set_default_size      (250, 600);
    set_border_width      (2);
    set_resizable         (true);
    set_reallocate_redraws(true);
  }

  using namespace hugh::render::software;

  {
    pipeline_.reset(new hugh::render::software::pipeline::fixed::direct3d);

    pipeline_->rasterizer  = new rasterizer::simple(viewport_);
    pipeline_->colorbuffer = new buffer::color     (viewport_);
    pipeline_->depthbuffer = new buffer::depth     (viewport_);

    // (*pipeline_->colorbuffer)->clear_value = glm::vec4(.1, .1, .1, .0);

    win_color_.reset(new window_buffer(get_title(), (*pipeline_->colorbuffer).get()));
    win_depth_.reset(new window_buffer(get_title(), (*pipeline_->depthbuffer).get()));

    win_depth_->set_visible(false);
  }

  {
    using namespace hugh::gtkmm;

    std::array<std::string, 2> const pipeline_enum_list = {
      { "Direct3D", "OpenGL", }
    };

    std::array<Gtk::Widget*, 1> const control_pipeline_item_list = {
      {
        Gtk::manage(new vradio_button_input<pipeline_enum>
                    ("",
                     [&](/*            */){
                      using namespace hugh::render::software::pipeline;

                      return ((dynamic_cast<fixed::opengl*>(pipeline_.get()))
                              ? pipeline_enum::opengl
                              : pipeline_enum::direct3d);
                     },
                     [&](pipeline_enum a) {
                       using namespace hugh::render::software::pipeline;

                       pipeline_enum const result((dynamic_cast<fixed::opengl*>(pipeline_.get()))
                                                  ? pipeline_enum::opengl
                                                  : pipeline_enum::direct3d);

                       fixed::base* ppl(nullptr);

                       switch (a) {
                       case pipeline_enum::opengl:   ppl = new fixed::opengl;   break;
                       case pipeline_enum::direct3d: ppl = new fixed::direct3d; break;
                       }

                       ppl->rasterizer .set(pipeline_->rasterizer .get());
                       ppl->colorbuffer.set(pipeline_->colorbuffer.get());
                       ppl->depthbuffer.set(pipeline_->depthbuffer.get());

                       pipeline_.reset(ppl);
                       render();

                       return result;
                     },
                     "Pipeline type.",
                     std::vector<std::string>(pipeline_enum_list.begin(),
                                              pipeline_enum_list.end()),
                     true, true)),
      }
    };

    std::array<Gtk::Widget*, 2> const control_item_list = {
      {
        empty_label_in_framed_vbox("Viewport", "[x y w h dn df]"),
        pack_items_in_framed_vbox<1>("Pipeline", control_pipeline_item_list),
      }
    };

    std::array<Gtk::Widget*, 2> const stats_ppl_item_list = {
      {
        empty_label_in_framed_vbox("Vertices", ""),
        empty_label_in_framed_vbox("Fragments", ""),
      }
    };

    std::array<Gtk::Widget*, 1> const stats_item_list = {
      {
        pack_items_in_framed_hbox<2>("Pipeline", stats_ppl_item_list),
      }
    };

    std::array<Gtk::Widget*, 3> const output_buffer_item_list = {
      {
        Gtk::manage(new check_button_input<bool>
                    ("  Color",
                     [&]()       { return win_color_->get_visible(); },
                     [&](bool a) { bool r(win_color_->get_visible());
                                   win_color_->set_visible(a);
                                   return r; },
                     "Toggle color-buffer display.", true, true)),
        Gtk::manage(new check_button_input<bool>
                    ("  Depth",
                     [&]()       { return win_depth_->get_visible(); },
                     [&](bool a) { bool r(win_depth_->get_visible());
                                   win_depth_->set_visible(a);
                                   return r; },
                     "Toggle depth-buffer display.", true, true)),
        Gtk::manage(new check_button_input<bool>
                    ("Stencil",
                     [&]()       { return false; },
                     [&](bool)   { return false; },
                     "Toggle stencil-buffer display.", false, true)),
      }
    };

    std::array<Gtk::Widget*, 1> const output_item_list = {
      {
        pack_items_in_framed_vbox<3>("Buffer", output_buffer_item_list),
      }
    };

    std::array<Gtk::Widget*, 3> const top_level = {
      {
        pack_items_in_framed_vbox<2>("Control", control_item_list),
        pack_items_in_framed_vbox<1>("Stats",   stats_item_list),
        pack_items_in_framed_vbox<1>("Output",  output_item_list),
      }
    };

    add     (*pack_items_in_vbox<3>(top_level));
    show_all();
  }

  render();
}

/* virtual */
window_control::~window_control()
{
  TRACE("window_control::~window_control");
}

void
window_control::render()
{
  TRACE("window_control::render");

  using namespace hugh::render::software;

  const_cast<pipeline::base::statistics&>(*pipeline_->stats).reset();

  (*pipeline_->colorbuffer)->clear();
  (*pipeline_->depthbuffer)->clear();

  attribute::list const attr0({ { attribute::type::color, glm::vec4(1,1,1,1) } });
  attribute::list const attr1({ { attribute::type::color, glm::vec4(1,0,0,1) } });
  attribute::list const attr2({ { attribute::type::color, glm::vec4(0,1,0,1) } });
  attribute::list const attr3({ { attribute::type::color, glm::vec4(0,0,1,1) } });

  {
    auto const&     vp    (*(*pipeline_->rasterizer)->viewport);
    glm::vec2 const offset(.75, .75); //(vp.width-vp.x) / 100.0f, (vp.height-vp.y) / 100.0f);
    std::array<vertex const, 4> const vertices = {
      {
        vertex(glm::vec3(              0,               0, 0.25), attr0),
        vertex(glm::vec3(vp.x + offset.x, vp.y + offset.y, 0.35), attr1),
        vertex(glm::vec3(vp.x - offset.x, vp.y + offset.y, 0.45), attr2),
        vertex(glm::vec3(vp.x + offset.x, vp.y - offset.y, 0.55), attr3),
      }
    };

    using point_list  = primitive::point_list;
    using vertex_list = point_list::vertex_list_type;

    pipeline_->process(point_list(vertex_list(vertices.begin(), vertices.end())));
  }

  {
    auto const&     vp    (*(*pipeline_->rasterizer)->viewport);
    glm::vec2 const offset(.5, .5); //(vp.width-vp.x) / 100.0f, (vp.height-vp.y) / 100.0f);
    std::array<vertex const, 4> const vertices = {
      {
        vertex(glm::vec3(vp.x - offset.x, vp.y - offset.y, 0.35), attr1),
        vertex(glm::vec3(vp.x + offset.x, vp.y + offset.y, 0.45), attr3),
        vertex(glm::vec3(vp.x - offset.x, vp.y + offset.y, 0.45), attr3),
        vertex(glm::vec3(vp.x + offset.x, vp.y - offset.y, 0.35), attr1),
      }
    };

    using line_list  = primitive::line_list;
    using vertex_list = line_list::vertex_list_type;

    pipeline_->process(line_list(vertex_list(vertices.begin(), vertices.end())));
  }

  {
    auto const&     vp    (*(*pipeline_->rasterizer)->viewport);
    glm::vec2 const offset(.25, .25); //(vp.width-vp.x) / 100.0f, (vp.height-vp.y) / 100.0f);

    std::array<vertex const, 6> const vertices = {
      {
        // ccw
        vertex(glm::vec3(vp.x - offset.x, vp.y - offset.y, 0.45), attr1),
        vertex(glm::vec3(vp.x + offset.x, vp.y - offset.y, 0.55), attr2),
        vertex(glm::vec3(vp.x - offset.x, vp.y + offset.y, 0.65), attr3),
        // cw
        vertex(glm::vec3(vp.x - offset.x, vp.y - offset.y, 0.45), attr1),
        vertex(glm::vec3(vp.x - offset.x, vp.y + offset.y, 0.55), attr2),
        vertex(glm::vec3(vp.x + offset.x, vp.y - offset.y, 0.65), attr3),
      }
    };

    using triangle_list = primitive::triangle_list;
    using vertex_list   = triangle_list::vertex_list_type;

    pipeline_->process(triangle_list(vertex_list(vertices.begin(), vertices.end())));
  }

  win_color_->queue_draw();
  win_depth_->queue_draw();
  /*       */ queue_draw();
}
<commit_msg>added: visual test case(s)<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2016 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  pipeline_fixed/window_control.cpp                                               */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// include i/f header

#include "window_control.hpp"

// includes, system

#include <hugh/render/software/buffer/color.hpp>
#include <hugh/render/software/buffer/depth.hpp>
#include <hugh/render/software/pipelines.hpp>
#include <hugh/render/software/primitives.hpp>
#include <hugh/render/software/rasterizer/simple.hpp>

// includes, project

#include <gtkmm_wrap/check_button_input.hpp>
#include <gtkmm_wrap/radio_button_input.hpp>
#include <gtkmm_wrap/utilities.hpp>

#define HUGH_USE_TRACE
//#undef HUGH_USE_TRACE
#include <hugh/support/trace.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  enum pipeline_enum { direct3d, opengl, };

  // variables, internal

  // functions, internal

} // namespace {

// variables, exported

// functions, exported

/* explicit */
window_control::window_control()
  : hugh::gtkmm::window(),
    // viewport_          (0, 0, 80, 60, 0, 1),
    viewport_          (0, 0, 320, 240, 0, 1),
    // viewport_          (0, 0, 640, 480, 0, 1),
    // viewport_          (0, 0, 1200, 900, 0, 1),
    pipeline_          (nullptr),
    win_color_         (nullptr),
    win_depth_         (nullptr)
{
  TRACE("window_control::window_control");

  {
    set_title             ("pipeline::fixed");
    set_default_size      (250, 600);
    set_border_width      (2);
    set_resizable         (true);
    set_reallocate_redraws(true);
  }

  using namespace hugh::render::software;

  {
    pipeline_.reset(new hugh::render::software::pipeline::fixed::opengl);

    pipeline_->rasterizer  = new rasterizer::simple(viewport_);
    pipeline_->colorbuffer = new buffer::color     (viewport_);
    pipeline_->depthbuffer = new buffer::depth     (viewport_);

    // (*pipeline_->colorbuffer)->clear_value = glm::vec4(.1, .1, .1, .0);

    win_color_.reset(new window_buffer(get_title(), (*pipeline_->colorbuffer).get()));
    win_depth_.reset(new window_buffer(get_title(), (*pipeline_->depthbuffer).get()));

    win_depth_->set_visible(false);
  }

  {
    using namespace hugh::gtkmm;

    std::array<std::string, 2> const pipeline_enum_list = {
      { "Direct3D", "OpenGL", }
    };

    std::array<Gtk::Widget*, 1> const control_pipeline_item_list = {
      {
        Gtk::manage(new vradio_button_input<pipeline_enum>
                    ("",
                     [&](/*            */){
                      using namespace hugh::render::software::pipeline;

                      return ((dynamic_cast<fixed::opengl*>(pipeline_.get()))
                              ? pipeline_enum::opengl
                              : pipeline_enum::direct3d);
                     },
                     [&](pipeline_enum a) {
                       using namespace hugh::render::software::pipeline;

                       pipeline_enum const result((dynamic_cast<fixed::opengl*>(pipeline_.get()))
                                                  ? pipeline_enum::opengl
                                                  : pipeline_enum::direct3d);

                       fixed::base* ppl(nullptr);

                       switch (a) {
                       case pipeline_enum::opengl:   ppl = new fixed::opengl;   break;
                       case pipeline_enum::direct3d: ppl = new fixed::direct3d; break;
                       }

                       ppl->rasterizer .set(pipeline_->rasterizer .get());
                       ppl->colorbuffer.set(pipeline_->colorbuffer.get());
                       ppl->depthbuffer.set(pipeline_->depthbuffer.get());

                       pipeline_.reset(ppl);
                       render();

                       return result;
                     },
                     "Pipeline type.",
                     std::vector<std::string>(pipeline_enum_list.begin(),
                                              pipeline_enum_list.end()),
                     true, true)),
      }
    };

    std::array<Gtk::Widget*, 2> const control_item_list = {
      {
        empty_label_in_framed_vbox("Viewport", "[x y w h dn df]"),
        pack_items_in_framed_vbox<1>("Pipeline", control_pipeline_item_list),
      }
    };

    std::array<Gtk::Widget*, 2> const stats_ppl_item_list = {
      {
        empty_label_in_framed_vbox("Vertices", ""),
        empty_label_in_framed_vbox("Fragments", ""),
      }
    };

    std::array<Gtk::Widget*, 1> const stats_item_list = {
      {
        pack_items_in_framed_hbox<2>("Pipeline", stats_ppl_item_list),
      }
    };

    std::array<Gtk::Widget*, 3> const output_buffer_item_list = {
      {
        Gtk::manage(new check_button_input<bool>
                    ("  Color",
                     [&]()       { return win_color_->get_visible(); },
                     [&](bool a) { bool r(win_color_->get_visible());
                                   win_color_->set_visible(a);
                                   return r; },
                     "Toggle color-buffer display.", true, true)),
        Gtk::manage(new check_button_input<bool>
                    ("  Depth",
                     [&]()       { return win_depth_->get_visible(); },
                     [&](bool a) { bool r(win_depth_->get_visible());
                                   win_depth_->set_visible(a);
                                   return r; },
                     "Toggle depth-buffer display.", true, true)),
        Gtk::manage(new check_button_input<bool>
                    ("Stencil",
                     [&]()       { return false; },
                     [&](bool)   { return false; },
                     "Toggle stencil-buffer display.", false, true)),
      }
    };

    std::array<Gtk::Widget*, 1> const output_item_list = {
      {
        pack_items_in_framed_vbox<3>("Buffer", output_buffer_item_list),
      }
    };

    std::array<Gtk::Widget*, 3> const top_level = {
      {
        pack_items_in_framed_vbox<2>("Control", control_item_list),
        pack_items_in_framed_vbox<1>("Stats",   stats_item_list),
        pack_items_in_framed_vbox<1>("Output",  output_item_list),
      }
    };

    add     (*pack_items_in_vbox<3>(top_level));
    show_all();
  }

  render();
}

/* virtual */
window_control::~window_control()
{
  TRACE("window_control::~window_control");
}

void
window_control::render()
{
  TRACE("window_control::render");

  using namespace hugh::render::software;

  const_cast<pipeline::base::statistics&>(*pipeline_->stats).reset();

  (*pipeline_->colorbuffer)->clear();
  (*pipeline_->depthbuffer)->clear();

  static attribute::list const attr0({ { attribute::type::color, glm::vec4(1,1,1,0) } });
  static attribute::list const attr1({ { attribute::type::color, glm::vec4(1,0,0,0) } });
  static attribute::list const attr2({ { attribute::type::color, glm::vec4(0,1,0,0) } });
  static attribute::list const attr3({ { attribute::type::color, glm::vec4(0,0,1,0) } });
  static attribute::list const attr4({ { attribute::type::color, glm::vec4(1,1,0,0) } });
  static attribute::list const attr5({ { attribute::type::color, glm::vec4(1,0,1,0) } });
  static attribute::list const attr6({ { attribute::type::color, glm::vec4(0,1,1,0) } });

#if 1
  {
    static std::array<glm::vec3 const, 9> const p = {
      {
        {  .0,  .0, .0078 }, // 0:  0  0
        {  .9,  .0, .0078 }, // 1: +x  0
        {  .9,  .9, .0078 }, // 2: +x +y
        {  .0,  .9, .0078 }, // 3:  0 +y
        { -.9,  .9, .0078 }, // 4: -x +y
        { -.9,  .0, .0078 }, // 5: -x  0
        { -.9, -.9, .0078 }, // 6: -x -y
        {  .0, -.9, .0078 }, // 7:  0 -y
        {  .9, -.9, .0078 }, // 8: +x -y
      }
    };

    static std::array<vertex const, 9> const vertices = {
      {
        vertex(p[0], attr0),
        vertex(p[1], attr1),
        vertex(p[2], attr1),
        vertex(p[3], attr2),
        vertex(p[4], attr2),
        vertex(p[5], attr3),
        vertex(p[6], attr3),
        vertex(p[7], attr4),
        vertex(p[8], attr4),
      }
    };

    using point_list  = primitive::point_list;
    using vertex_list = point_list::vertex_list_type;

    pipeline_->process(point_list(vertex_list(vertices.begin(), vertices.end())));
  }
#endif

#if 1
  {
    static std::array<glm::vec3 const, 9> const p = {
      {
        {  .0,  .0, .5 }, // 0:  0  0
        {  .5,  .0, .5 }, // 1: +x  0
        {  .5,  .5, .5 }, // 2: +x +y
        {  .0,  .5, .5 }, // 3:  0 +y
        { -.5,  .5, .5 }, // 4: -x +y
        { -.5,  .0, .5 }, // 5: -x  0
        { -.5, -.5, .5 }, // 6: -x -y
        {  .0, -.5, .5 }, // 7:  0 -y
        {  .5, -.5, .5 }, // 8: +x -y
      }
    };

    static std::array<glm::vec3 const, 3> const o = {
      {
        { .05, .00, .00 },
        { .00, .05, .00 },
        { .00, .00, .05 },
      }
    };

    static std::array<vertex const, 40> const vertices = {
      {
        vertex(p[0], attr0), vertex(p[1], attr2),
        vertex(p[0], attr0), vertex(p[2], attr3),
        vertex(p[0], attr0), vertex(p[3], attr2),
        vertex(p[0], attr0), vertex(p[4], attr3),
        vertex(p[0], attr0), vertex(p[5], attr2),
        vertex(p[0], attr0), vertex(p[6], attr3),
        vertex(p[0], attr0), vertex(p[7], attr2),
        vertex(p[0], attr0), vertex(p[8], attr3),

        vertex(p[2]+o[0], attr0), vertex(p[6]+o[0], attr1),
        vertex(p[6]-o[0], attr0), vertex(p[2]-o[0], attr1),
        vertex(p[4]+o[0], attr0), vertex(p[8]+o[0], attr1),
        vertex(p[8]-o[0], attr0), vertex(p[4]-o[0], attr1),

        vertex(p[6]+o[0], attr0), vertex(p[4]+o[0], attr1),
        vertex(p[4]-o[0], attr0), vertex(p[6]-o[0], attr1),
        vertex(p[8]+o[0], attr0), vertex(p[2]+o[0], attr1),
        vertex(p[2]-o[0], attr0), vertex(p[8]-o[0], attr1),

        vertex(p[4]+o[1], attr0), vertex(p[2]+o[1], attr1),
        vertex(p[2]-o[1], attr0), vertex(p[4]-o[1], attr1),
        vertex(p[6]+o[1], attr0), vertex(p[8]+o[1], attr1),
        vertex(p[8]-o[1], attr0), vertex(p[6]-o[1], attr1),
      }
    };

    using line_list  = primitive::line_list;
    using vertex_list = line_list::vertex_list_type;

    pipeline_->process(line_list(vertex_list(vertices.begin(), vertices.end())));
  }
#endif

#if 1
  {
    static std::array<glm::vec3 const, 9> const p = {
      {
        {  .0,  .0, .0625 }, // 0:  0  0
        {  .5,  .0, .25 },   // 1: +x  0
        {  .5,  .5, .95 },   // 2: +x +y
        {  .0,  .5, .25 },   // 3:  0 +y
        { -.5,  .5, .95 },   // 4: -x +y
        { -.5,  .0, .25 },   // 5: -x  0
        { -.5, -.5, .95 },   // 6: -x -y
        {  .0, -.5, .25 },   // 7:  0 -y
        {  .5, -.5, .95 },   // 8: +x -y
      }
    };

    static std::array<vertex const, 24> const vertices = {
      {
        // ccw
        vertex(p[0], attr0), vertex(p[1], attr2), vertex(p[3], attr3),
        vertex(p[0], attr0), vertex(p[3], attr3), vertex(p[5], attr2),
        vertex(p[0], attr0), vertex(p[5], attr2), vertex(p[7], attr3),
        vertex(p[0], attr0), vertex(p[7], attr3), vertex(p[1], attr2),
        // cw
        vertex(p[0], attr0), vertex(p[3], attr3), vertex(p[1], attr2),
        vertex(p[0], attr0), vertex(p[5], attr2), vertex(p[3], attr3),
        vertex(p[0], attr0), vertex(p[7], attr3), vertex(p[5], attr2),
        vertex(p[0], attr0), vertex(p[1], attr2), vertex(p[7], attr3),
      }
    };

    using triangle_list = primitive::triangle_list;
    using vertex_list   = triangle_list::vertex_list_type;

    pipeline_->process(triangle_list(vertex_list(vertices.begin(), vertices.end())));
  }
#endif

  win_color_->queue_draw();
  win_depth_->queue_draw();
  /*       */ queue_draw();
}
<|endoftext|>


<commit_before>/*
	Copyright (C) 2016 by Claude SIMON (http://zeusw.org/epeios/contact.html).

	This file is part of 'NJSq'.

    'NJSq' is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

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

    You should have received a copy of the GNU Affero General Public License
    along with 'NJSq'.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "wrapper.h"

#include "n4allw.h"
#include "n4njs.h"
#include "nodeq.h"
#include "sclerror.h"
#include "v8q.h"

using namespace wrapper;

typedef n4all::cCaller cCaller_;

namespace {
	inline void GetString_(
		int Index,
		const v8::FunctionCallbackInfo<v8::Value> &Info,
		str::dString &Value )
	{
		qRH
			v8q::sString String;
		qRB
			String.Init( Info[Index] );

			String.Get( Value );
		qRR
		qRT
		qRE
	}

	namespace {
		class rRStream
		: public n4njs::cURStream
		{
		private:
			nodeq::sRStream Core_;
		protected:
			virtual bso::sBool NANJSRead( str::dString &Chunk ) override
			{
				return Core_.Read( Chunk );
			}
		public:
			void reset( bso::sBool P = true )
			{
				tol::reset( P, Core_ );
			}
			qCVDTOR( rRStream );
			void Init( v8::Local<v8::Value> Value )
			{
				Core_.Init( Value );
			}
		};
	}

	inline void GetStream_(
		int Index,
		const v8::FunctionCallbackInfo<v8::Value> &Info,
		n4njs::cURStream *&Stream )
	{
	qRH
	qRB
		Stream = new rRStream;

		if ( Stream == NULL )
			qRAlc();

		Stream->Init( Info[Index] );
	qRR
	qRT
	qRE
	}
}

void SetReturnValue_(
	const v8::FunctionCallbackInfo<v8::Value> &Info,
	const str::dString &Value )
{
	Info.GetReturnValue().Set( v8q::sString( Value ).Core() );
}

namespace {
	class sCaller_
	: public cCaller_ {
	private:
		qRMV( const v8::FunctionCallbackInfo<v8::Value>, I_, Info_ );
	protected:
		virtual void N4ALLGetArgument(
			bso::sU8 Index,
			n4all::sEnum Type,
			void *Value ) override
		{
			Index++;	// The first one was the function id.

			if ( Index >= I_().Length() )
				qRGnr();

			switch ( Type ) {
			case n4all::tString:
				GetString_( Index, I_(), *( str::dString * )Value );
				break;
			case n4njs::tStream:
				GetStream_( Index, I_(), ( n4njs::cURStream **)Value );
				break;
			case n4njs::tBuffer:
				GetBuffer_( Index, I_(), ( n4njs::cUBuffer **)Value );
				break;
			case n4njs::tCallback:
				GetCallback_( Index, I_(), ( n4njs::cUCallback **)Value );
				break;
			default:
				qRGnr();
				break;
			}
		}
		virtual void N4ALLSetReturnValue(
			n4all::sEnum Type,
			const void *Value ) override
		{
			switch ( Type ) {
			case n4all::tString:
				SetReturnValue_( I_(), *( const str::dString * )Value );
				break;
			default:
				qRGnr();
				break;
			}
		}
	public:
		void reset( bso::sBool = true )
		{
			Info_ = NULL;
		}
		qCDTOR( sCaller_ );
		void Init( const v8::FunctionCallbackInfo<v8::Value> &Info )
		{
			Info_ = &Info;
		}
	};
}

void wrapper::Launch( const v8::FunctionCallbackInfo<v8::Value>& Info )
{
qRH
	sCaller_ Caller;
qRB
	if ( Info.Length() < 1 )
		qRGnr();

	if ( !Info[0]->IsUint32() )
		qRGnr();

	v8::Local<v8::Uint32> Index = v8::Local<v8::Uint32>::Cast(Info[0] );

	Caller.Init( Info );

	n4allw::GetLauncher().Launch( n4allw::GetFunction( Index->Uint32Value()), Caller );

	if ( sclerror::IsErrorPending() )
		qRAbort();	// To force the handling of a pending error.
qRR
qRT
qRE
}

<commit_msg>19/08/2017 17:22:10<commit_after>/*
	Copyright (C) 2016 by Claude SIMON (http://zeusw.org/epeios/contact.html).

	This file is part of 'NJSq'.

    'NJSq' is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

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

    You should have received a copy of the GNU Affero General Public License
    along with 'NJSq'.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "wrapper.h"

#include "n4allw.h"
#include "n4njs.h"
#include "nodeq.h"
#include "sclerror.h"
#include "v8q.h"

using namespace wrapper;

typedef n4all::cCaller cCaller_;

namespace {
	inline void GetString_(
		int Index,
		const v8::FunctionCallbackInfo<v8::Value> &Info,
		str::dString &Value )
	{
		qRH
			v8q::sString String;
		qRB
			String.Init( Info[Index] );

			String.Get( Value );
		qRR
		qRT
		qRE
	}

	namespace {
		template <typename callback, typename host> class rCore_
		: public callback
		{
		protected:
			host Core_;
		protected:
			virtual void N4NJSSet(
				const char *Key,
				void *Value ) override
			{
				v8::Isolate *Isolate = v8q::GetIsolate();

				if ( !v8q::Expose( Core_.Core()->Set( v8q::GetContext(), v8q::ToString( Key, Isolate ), *( v8::Local<v8::Value> * )Value ) ) )
					qRFwk();
			}
			virtual void *N4NJSGet( const char *Key ) override
			{
				v8::Isolate *Isolate = v8q::GetIsolate();

				return &v8q::ToLocal( Core_.Core()->Get( v8q::GetContext( Isolate ), v8q::ToString( Key, Isolate ) ), Isolate );
			}
		public:
			void reset( bso::sBool P = true )
			{
				tol::reset( P, Core_ );
			}
			qCVDTOR( rCore_ );
			void Init( v8::Local<v8::Value> Value )
			{
				Core_.Init( Value );
			}
		};

		template <typename host> inline host *Get_(
			int Index,
			const v8::FunctionCallbackInfo<v8::Value> &Info )
		{
			host *Stream = NULL;
		qRH
		qRB
			Stream = new host;

			if ( Stream == NULL )
				qRAlc();

			Stream->Init( Info[Index] );
		qRR
			if ( Stream != NULL )
				delete Stream;
		qRT
		qRE
			return Stream;
		}

		class rRStream_
		: public rCore_<n4njs::cURStream, nodeq::sRStream>
		{
		protected:
			virtual bso::sBool NANJSRead( str::dString &Chunk ) override
			{
				return Core_.Read( Chunk );
			}
		};

		class rBuffer_
		: public rCore_<n4njs::cUBuffer, nodeq::sBuffer> {
		protected:
			virtual void N4NJSToString( str::dString &String ) override;
			virtual bso::sBool N4NJSIsNull( void ) override;
		};

		class rCallback_
		: public n4njs::cUCallback
		{
		private:
			nodeq::sFunction Core_;
		protected:
			virtual void N4NJSAdd(
				n4njs::eCallbackType_ Type,
				void *Value ) override;
			virtual void *N4NJSLaunch( n4njs::eCallbackType_ Type ) override;	// Type is the expected type of the returned value.
		public:
			void reset( bso::sBool P = true )
			{
				tol::reset( P, Core_ );
			}
			qCVDTOR( rCallback_ );
			void Init( v8::Local<v8::Value> Value )
			{
				Core_.Init( Value );
			}
		};

	}

	inline n4njs::cURStream *GetStream_(
		int Index,
		const v8::FunctionCallbackInfo<v8::Value> &Info )
	{
		return Get_<rRStream_>( Index, Info );
	}

	inline n4njs::cUBuffer *GetBuffer_(
		int Index,
		const v8::FunctionCallbackInfo<v8::Value> &Info )
	{
		return Get_<rBuffer_>( Index, Info );
	}

	inline n4njs::cUCallback *GetCallback_(
		int Index,
		const v8::FunctionCallbackInfo<v8::Value> &Info )
	{
		return Get_<rCallback_>( Index, Info );
	}
}

void SetReturnValue_(
	const v8::FunctionCallbackInfo<v8::Value> &Info,
	const str::dString &Value )
{
	Info.GetReturnValue().Set( v8q::sString( Value ).Core() );
}

namespace {
	class sCaller_
	: public cCaller_ {
	private:
		qRMV( const v8::FunctionCallbackInfo<v8::Value>, I_, Info_ );
	protected:
		virtual void N4ALLGetArgument(
			bso::sU8 Index,
			n4all::sEnum Type,
			void *Value ) override
		{
			Index++;	// The first one was the function id.

			if ( Index >= I_().Length() )
				qRGnr();

			switch ( Type ) {
			case n4all::tString:
				GetString_( Index, I_(), *( str::dString * )Value );
				break;
			case n4njs::tStream:
				(*(n4njs::cURStream **)Value) = GetStream_( Index, I_() );
				break;
			case n4njs::tBuffer:
				(*( n4njs::cUBuffer ** )Value) = GetBuffer_( Index, I_() );
				break;
			case n4njs::tCallback:
				( *( n4njs::cUCallback ** )Value ) = GetCallback_( Index, I_() );
				break;
			default:
				qRGnr();
				break;
			}
		}
		virtual void N4ALLSetReturnValue(
			n4all::sEnum Type,
			const void *Value ) override
		{
			switch ( Type ) {
			case n4all::tString:
				SetReturnValue_( I_(), *( const str::dString * )Value );
				break;
			default:
				qRGnr();
				break;
			}
		}
	public:
		void reset( bso::sBool = true )
		{
			Info_ = NULL;
		}
		qCDTOR( sCaller_ );
		void Init( const v8::FunctionCallbackInfo<v8::Value> &Info )
		{
			Info_ = &Info;
		}
	};
}

void wrapper::Launch( const v8::FunctionCallbackInfo<v8::Value>& Info )
{
qRH
	sCaller_ Caller;
qRB
	if ( Info.Length() < 1 )
		qRGnr();

	if ( !Info[0]->IsUint32() )
		qRGnr();

	v8::Local<v8::Uint32> Index = v8::Local<v8::Uint32>::Cast(Info[0] );

	Caller.Init( Info );

	n4allw::GetLauncher().Launch( n4allw::GetFunction( Index->Uint32Value()), Caller );

	if ( sclerror::IsErrorPending() )
		qRAbort();	// To force the handling of a pending error.
qRR
qRT
qRE
}

<|endoftext|>


<commit_before>/*
  DueTimer.cpp - Implementation of Timers defined on DueTimer.h
  For instructions, go to https://github.com/ivanseidel/DueTimer

  Created by Ivan Seidel Gomes, March, 2013.
  Modified by Philipp Klaus, June 2013.
  Thanks to stimmer (from Arduino forum), for coding the "timer soul" (Register stuff)
  Released into the public domain.
*/

#if defined(_SAM3XA_)
#include "DueTimer.h"

const DueTimer::Timer DueTimer::Timers[NUM_TIMERS] = {
	{TC0,0,TC0_IRQn},
	{TC0,1,TC1_IRQn},
	{TC0,2,TC2_IRQn},
	{TC1,0,TC3_IRQn},
	{TC1,1,TC4_IRQn},
	{TC1,2,TC5_IRQn},
	{TC2,0,TC6_IRQn},
	{TC2,1,TC7_IRQn},
	{TC2,2,TC8_IRQn},
};

// Fix for compatibility with Servo library
#ifdef USING_SERVO_LIB
	// Set callbacks as used, allowing DueTimer::getAvailable() to work
	void (*DueTimer::callbacks[NUM_TIMERS])() = {
		(void (*)()) 1, // Timer 0 - Occupied
		(void (*)()) 0, // Timer 1
		(void (*)()) 1, // Timer 2 - Occupied
		(void (*)()) 1, // Timer 3 - Occupied
		(void (*)()) 1, // Timer 4 - Occupied
		(void (*)()) 1, // Timer 5 - Occupied
		(void (*)()) 0, // Timer 6
		(void (*)()) 0, // Timer 7
		(void (*)()) 0  // Timer 8
	};
#else
	void (*DueTimer::callbacks[NUM_TIMERS])() = {};
#endif
double DueTimer::_frequency[NUM_TIMERS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};

/*
	Initializing all timers, so you can use them like this: Timer0.start();
*/
DueTimer Timer(0);

DueTimer Timer1(1);
// Fix for compatibility with Servo library
#ifndef USING_SERVO_LIB
	DueTimer Timer0(0);
	DueTimer Timer2(2);
	DueTimer Timer3(3);
	DueTimer Timer4(4);
	DueTimer Timer5(5);
#endif
DueTimer Timer6(6);
DueTimer Timer7(7);
DueTimer Timer8(8);

DueTimer::DueTimer(unsigned short _timer) : timer(_timer){
	/*
		The constructor of the class DueTimer
	*/
}

DueTimer DueTimer::getAvailable(void){
	/*
		Return the first timer with no callback set
	*/

	for(int i = 0; i < NUM_TIMERS; i++){
		if(!callbacks[i])
			return DueTimer(i);
	}
	// Default, return Timer0;
	return DueTimer(0);
}

DueTimer& DueTimer::attachInterrupt(void (*isr)()){
	/*
		Links the function passed as argument to the timer of the object
	*/

	callbacks[timer] = isr;

	return *this;
}

DueTimer& DueTimer::detachInterrupt(void){
	/*
		Links the function passed as argument to the timer of the object
	*/

	stop(); // Stop the currently running timer

	callbacks[timer] = NULL;

	return *this;
}

DueTimer& DueTimer::start(long microseconds){
	/*
		Start the timer
		If a period is set, then sets the period and start the timer
	*/

	if(microseconds > 0)
		setPeriod(microseconds);

	if(_frequency[timer] <= 0)
		setFrequency(1);

	NVIC_ClearPendingIRQ(Timers[timer].irq);
	NVIC_EnableIRQ(Timers[timer].irq);

	TC_Start(Timers[timer].tc, Timers[timer].channel);

	return *this;
}

DueTimer& DueTimer::stop(void){
	/*
		Stop the timer
	*/

	NVIC_DisableIRQ(Timers[timer].irq);

	TC_Stop(Timers[timer].tc, Timers[timer].channel);

	return *this;
}

uint8_t DueTimer::bestClock(double frequency, uint32_t& retRC){
	/*
		Pick the best Clock, thanks to Ogle Basil Hall!

		Timer		Definition
		TIMER_CLOCK1	MCK /  2
		TIMER_CLOCK2	MCK /  8
		TIMER_CLOCK3	MCK / 32
		TIMER_CLOCK4	MCK /128
	*/
	const struct {
		uint8_t flag;
		uint8_t divisor;
	} clockConfig[] = {
		{ TC_CMR_TCCLKS_TIMER_CLOCK1,   2 },
		{ TC_CMR_TCCLKS_TIMER_CLOCK2,   8 },
		{ TC_CMR_TCCLKS_TIMER_CLOCK3,  32 },
		{ TC_CMR_TCCLKS_TIMER_CLOCK4, 128 }
	};
	float ticks;
	float error;
	int clkId = 3;
	int bestClock = 3;
	float bestError = 9.999e99;
	do
	{
		ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[clkId].divisor;
		// error = abs(ticks - round(ticks));
		error = clockConfig[clkId].divisor * abs(ticks - round(ticks));	// Error comparison needs scaling
		if (error < bestError)
		{
			bestClock = clkId;
			bestError = error;
		}
	} while (clkId-- > 0);
	ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[bestClock].divisor;
	retRC = (uint32_t) round(ticks);
	return clockConfig[bestClock].flag;
}

DueTimer& DueTimer::setFrequency(double frequency){
	/*
		Set the timer frequency (in Hz)
	*/

	// Prevent negative frequencies
	if(frequency <= 0) { frequency = 1; }

	// Remember the frequency — see below how the exact frequency is reported instead
	//_frequency[timer] = frequency;

	// Get current timer configuration
	Timer t = Timers[timer];

	uint32_t rc = 0;
	uint8_t clock;

	// Tell the Power Management Controller to disable
	// the write protection of the (Timer/Counter) registers:
	pmc_set_writeprotect(false);

	// Enable clock for the timer
	pmc_enable_periph_clk((uint32_t)t.irq);

	// Find the best clock for the wanted frequency
	clock = bestClock(frequency, rc);

	switch (clock) {
	  case TC_CMR_TCCLKS_TIMER_CLOCK1:
	    _frequency[timer] = (double)VARIANT_MCK / 2.0 / (double)rc;
	    break;
	  case TC_CMR_TCCLKS_TIMER_CLOCK2:
	    _frequency[timer] = (double)VARIANT_MCK / 8.0 / (double)rc;
	    break;
	  case TC_CMR_TCCLKS_TIMER_CLOCK3:
	    _frequency[timer] = (double)VARIANT_MCK / 32.0 / (double)rc;
	    break;
	  default: // TC_CMR_TCCLKS_TIMER_CLOCK4
	    _frequency[timer] = (double)VARIANT_MCK / 128.0 / (double)rc;
	    break;
	}

	// Set up the Timer in waveform mode which creates a PWM
	// in UP mode with automatic trigger on RC Compare
	// and sets it up with the determined internal clock as clock input.
	TC_Configure(t.tc, t.channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | clock);
	// Reset counter and fire interrupt when RC value is matched:
	TC_SetRC(t.tc, t.channel, rc);
	// Enable the RC Compare Interrupt...
	t.tc->TC_CHANNEL[t.channel].TC_IER=TC_IER_CPCS;
	// ... and disable all others.
	t.tc->TC_CHANNEL[t.channel].TC_IDR=~TC_IER_CPCS;

	return *this;
}

DueTimer& DueTimer::setPeriod(unsigned long microseconds){
	/*
		Set the period of the timer (in microseconds)
	*/

	// Convert period in microseconds to frequency in Hz
	double frequency = 1000000.0 / microseconds;
	setFrequency(frequency);
	return *this;
}

double DueTimer::getFrequency(void) const {
	/*
		Get current time frequency
	*/

	return _frequency[timer];
}

long DueTimer::getPeriod(void) const {
	/*
		Get current time period
	*/

	return 1.0/getFrequency()*1000000;
}

/*
	Implementation of the timer callbacks defined in
	arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h
*/
// Fix for compatibility with Servo library
#ifndef USING_SERVO_LIB
void TC0_Handler(void){
	TC_GetStatus(TC0, 0);
	DueTimer::callbacks[0]();
}
#endif
void TC1_Handler(void){
	TC_GetStatus(TC0, 1);
	DueTimer::callbacks[1]();
}
// Fix for compatibility with Servo library
#ifndef USING_SERVO_LIB
void TC2_Handler(void){
	TC_GetStatus(TC0, 2);
	DueTimer::callbacks[2]();
}
void TC3_Handler(void){
	TC_GetStatus(TC1, 0);
	DueTimer::callbacks[3]();
}
void TC4_Handler(void){
	TC_GetStatus(TC1, 1);
	DueTimer::callbacks[4]();
}
void TC5_Handler(void){
	TC_GetStatus(TC1, 2);
	DueTimer::callbacks[5]();
}
#endif
void TC6_Handler(void){
	TC_GetStatus(TC2, 0);
	DueTimer::callbacks[6]();
}
void TC7_Handler(void){
	TC_GetStatus(TC2, 1);
	DueTimer::callbacks[7]();
}
void TC8_Handler(void){
	TC_GetStatus(TC2, 2);
	DueTimer::callbacks[8]();
}
#endif
<commit_msg>Update DueTimer.cpp<commit_after>/*
  DueTimer.cpp - Implementation of Timers defined on DueTimer.h
  For instructions, go to https://github.com/ivanseidel/DueTimer

  Created by Ivan Seidel Gomes, March, 2013.
  Modified by Philipp Klaus, June 2013.
  Thanks to stimmer (from Arduino forum), for coding the "timer soul" (Register stuff)
  Released into the public domain.
*/

#if defined(_SAM3XA_)
#include <Arduino.h>
#include "DueTimer.h"

const DueTimer::Timer DueTimer::Timers[NUM_TIMERS] = {
	{TC0,0,TC0_IRQn},
	{TC0,1,TC1_IRQn},
	{TC0,2,TC2_IRQn},
	{TC1,0,TC3_IRQn},
	{TC1,1,TC4_IRQn},
	{TC1,2,TC5_IRQn},
	{TC2,0,TC6_IRQn},
	{TC2,1,TC7_IRQn},
	{TC2,2,TC8_IRQn},
};

// Fix for compatibility with Servo library
#ifdef USING_SERVO_LIB
	// Set callbacks as used, allowing DueTimer::getAvailable() to work
	void (*DueTimer::callbacks[NUM_TIMERS])() = {
		(void (*)()) 1, // Timer 0 - Occupied
		(void (*)()) 0, // Timer 1
		(void (*)()) 1, // Timer 2 - Occupied
		(void (*)()) 1, // Timer 3 - Occupied
		(void (*)()) 1, // Timer 4 - Occupied
		(void (*)()) 1, // Timer 5 - Occupied
		(void (*)()) 0, // Timer 6
		(void (*)()) 0, // Timer 7
		(void (*)()) 0  // Timer 8
	};
#else
	void (*DueTimer::callbacks[NUM_TIMERS])() = {};
#endif
double DueTimer::_frequency[NUM_TIMERS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};

/*
	Initializing all timers, so you can use them like this: Timer0.start();
*/
DueTimer Timer(0);

DueTimer Timer1(1);
// Fix for compatibility with Servo library
#ifndef USING_SERVO_LIB
	DueTimer Timer0(0);
	DueTimer Timer2(2);
	DueTimer Timer3(3);
	DueTimer Timer4(4);
	DueTimer Timer5(5);
#endif
DueTimer Timer6(6);
DueTimer Timer7(7);
DueTimer Timer8(8);

DueTimer::DueTimer(unsigned short _timer) : timer(_timer){
	/*
		The constructor of the class DueTimer
	*/
}

DueTimer DueTimer::getAvailable(void){
	/*
		Return the first timer with no callback set
	*/

	for(int i = 0; i < NUM_TIMERS; i++){
		if(!callbacks[i])
			return DueTimer(i);
	}
	// Default, return Timer0;
	return DueTimer(0);
}

DueTimer& DueTimer::attachInterrupt(void (*isr)()){
	/*
		Links the function passed as argument to the timer of the object
	*/

	callbacks[timer] = isr;

	return *this;
}

DueTimer& DueTimer::detachInterrupt(void){
	/*
		Links the function passed as argument to the timer of the object
	*/

	stop(); // Stop the currently running timer

	callbacks[timer] = NULL;

	return *this;
}

DueTimer& DueTimer::start(long microseconds){
	/*
		Start the timer
		If a period is set, then sets the period and start the timer
	*/

	if(microseconds > 0)
		setPeriod(microseconds);

	if(_frequency[timer] <= 0)
		setFrequency(1);

	NVIC_ClearPendingIRQ(Timers[timer].irq);
	NVIC_EnableIRQ(Timers[timer].irq);

	TC_Start(Timers[timer].tc, Timers[timer].channel);

	return *this;
}

DueTimer& DueTimer::stop(void){
	/*
		Stop the timer
	*/

	NVIC_DisableIRQ(Timers[timer].irq);

	TC_Stop(Timers[timer].tc, Timers[timer].channel);

	return *this;
}

uint8_t DueTimer::bestClock(double frequency, uint32_t& retRC){
	/*
		Pick the best Clock, thanks to Ogle Basil Hall!

		Timer		Definition
		TIMER_CLOCK1	MCK /  2
		TIMER_CLOCK2	MCK /  8
		TIMER_CLOCK3	MCK / 32
		TIMER_CLOCK4	MCK /128
	*/
	const struct {
		uint8_t flag;
		uint8_t divisor;
	} clockConfig[] = {
		{ TC_CMR_TCCLKS_TIMER_CLOCK1,   2 },
		{ TC_CMR_TCCLKS_TIMER_CLOCK2,   8 },
		{ TC_CMR_TCCLKS_TIMER_CLOCK3,  32 },
		{ TC_CMR_TCCLKS_TIMER_CLOCK4, 128 }
	};
	float ticks;
	float error;
	int clkId = 3;
	int bestClock = 3;
	float bestError = 9.999e99;
	do
	{
		ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[clkId].divisor;
		// error = abs(ticks - round(ticks));
		error = clockConfig[clkId].divisor * abs(ticks - round(ticks));	// Error comparison needs scaling
		if (error < bestError)
		{
			bestClock = clkId;
			bestError = error;
		}
	} while (clkId-- > 0);
	ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[bestClock].divisor;
	retRC = (uint32_t) round(ticks);
	return clockConfig[bestClock].flag;
}

DueTimer& DueTimer::setFrequency(double frequency){
	/*
		Set the timer frequency (in Hz)
	*/

	// Prevent negative frequencies
	if(frequency <= 0) { frequency = 1; }

	// Remember the frequency — see below how the exact frequency is reported instead
	//_frequency[timer] = frequency;

	// Get current timer configuration
	Timer t = Timers[timer];

	uint32_t rc = 0;
	uint8_t clock;

	// Tell the Power Management Controller to disable
	// the write protection of the (Timer/Counter) registers:
	pmc_set_writeprotect(false);

	// Enable clock for the timer
	pmc_enable_periph_clk((uint32_t)t.irq);

	// Find the best clock for the wanted frequency
	clock = bestClock(frequency, rc);

	switch (clock) {
	  case TC_CMR_TCCLKS_TIMER_CLOCK1:
	    _frequency[timer] = (double)VARIANT_MCK / 2.0 / (double)rc;
	    break;
	  case TC_CMR_TCCLKS_TIMER_CLOCK2:
	    _frequency[timer] = (double)VARIANT_MCK / 8.0 / (double)rc;
	    break;
	  case TC_CMR_TCCLKS_TIMER_CLOCK3:
	    _frequency[timer] = (double)VARIANT_MCK / 32.0 / (double)rc;
	    break;
	  default: // TC_CMR_TCCLKS_TIMER_CLOCK4
	    _frequency[timer] = (double)VARIANT_MCK / 128.0 / (double)rc;
	    break;
	}

	// Set up the Timer in waveform mode which creates a PWM
	// in UP mode with automatic trigger on RC Compare
	// and sets it up with the determined internal clock as clock input.
	TC_Configure(t.tc, t.channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | clock);
	// Reset counter and fire interrupt when RC value is matched:
	TC_SetRC(t.tc, t.channel, rc);
	// Enable the RC Compare Interrupt...
	t.tc->TC_CHANNEL[t.channel].TC_IER=TC_IER_CPCS;
	// ... and disable all others.
	t.tc->TC_CHANNEL[t.channel].TC_IDR=~TC_IER_CPCS;

	return *this;
}

DueTimer& DueTimer::setPeriod(unsigned long microseconds){
	/*
		Set the period of the timer (in microseconds)
	*/

	// Convert period in microseconds to frequency in Hz
	double frequency = 1000000.0 / microseconds;
	setFrequency(frequency);
	return *this;
}

double DueTimer::getFrequency(void) const {
	/*
		Get current time frequency
	*/

	return _frequency[timer];
}

long DueTimer::getPeriod(void) const {
	/*
		Get current time period
	*/

	return 1.0/getFrequency()*1000000;
}

/*
	Implementation of the timer callbacks defined in
	arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h
*/
// Fix for compatibility with Servo library
#ifndef USING_SERVO_LIB
void TC0_Handler(void){
	TC_GetStatus(TC0, 0);
	DueTimer::callbacks[0]();
}
#endif
void TC1_Handler(void){
	TC_GetStatus(TC0, 1);
	DueTimer::callbacks[1]();
}
// Fix for compatibility with Servo library
#ifndef USING_SERVO_LIB
void TC2_Handler(void){
	TC_GetStatus(TC0, 2);
	DueTimer::callbacks[2]();
}
void TC3_Handler(void){
	TC_GetStatus(TC1, 0);
	DueTimer::callbacks[3]();
}
void TC4_Handler(void){
	TC_GetStatus(TC1, 1);
	DueTimer::callbacks[4]();
}
void TC5_Handler(void){
	TC_GetStatus(TC1, 2);
	DueTimer::callbacks[5]();
}
#endif
void TC6_Handler(void){
	TC_GetStatus(TC2, 0);
	DueTimer::callbacks[6]();
}
void TC7_Handler(void){
	TC_GetStatus(TC2, 1);
	DueTimer::callbacks[7]();
}
void TC8_Handler(void){
	TC_GetStatus(TC2, 2);
	DueTimer::callbacks[8]();
}
#endif
<|endoftext|>


<commit_before>#include <vector>
#include <string>

#include <fstream>

#include "boost/program_options.hpp"
#include "boost/algorithm/string.hpp"
#include "boost/lexical_cast.hpp"

#include "vtrc-client-base/vtrc-client.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-exception.h"

#include "remote-fs-iface.h"

#include "vtrc-condition-variable.h"
#include "vtrc-mutex.h"
#include "vtrc-bind.h"
#include "vtrc-ref.h"

namespace po = boost::program_options;
using namespace vtrc;

void get_options( po::options_description& desc )
{
    desc.add_options( )
        ("help,?",   "help message")
        ("server,s", po::value<std::string>( ),
                     "server name; <tcp address>:<port> or <pipe/file name>")
        ("path,p", po::value<std::string>( ), "Init remote path for client")
        ("pwd,w", "Show current remote path")
        ("info,i", po::value<std::string>( ), "Show info about remote path")
        ("list,l", "list remote directory")
        ("tree,t", "show remote directory as tree")

        ("pull,g", po::value<std::string>( ), "Download remote file")
        ("push,u", po::value<std::string>( ), "Upload local file")

        ("block-size,b", po::value<unsigned>( ), "Block size for pull and push"
                                                 "; 1-44000")

        ;
}

void connect_to( client::vtrc_client_sptr client, std::string const &name )
{
    std::vector<std::string> params;

    std::string::const_reverse_iterator b(name.rbegin( ));
    std::string::const_reverse_iterator e(name.rend( ));
    for( ; b!=e ;++b ) {
        if( *b == ':' ) {
            std::string::const_reverse_iterator bb(b);
            ++bb;
            params.push_back( std::string( name.begin( ), bb.base( )) );
            params.push_back( std::string( b.base( ), name.end( )));

            break;
        }
    }

    if( params.empty( ) ) {
        params.push_back( name );
    }

    if( params.size( ) == 1 ) {        /// local name
        client->connect( params[0] );
    } else if( params.size( ) == 2 ) { /// tcp
        client->connect( params[0], params[1]);
    }

}

void on_client_ready( vtrc::condition_variable &cond )
{
    std::cout << "Connection is ready...\n";
    cond.notify_all( );
}

std::string leaf_of( const std::string &path )
{
    std::string::const_reverse_iterator b(path.rbegin( ));
    std::string::const_reverse_iterator e(path.rend( ));
    for( ; b!=e ;++b ) {
        if( *b == '/' || *b == '\\' ) {
            return std::string( b.base( ), path.end( ) );
        }
    }
    return path;
}

void list_dir( vtrc::shared_ptr<interfaces::remote_fs> &impl )
{
    vtrc::shared_ptr<interfaces::remote_fs_iterator> i(impl->begin_iterator( ));
    std::string lstring( 2, ' ' );
    for( ; !i->end( ); i->next( )) {
        bool is_dir( i->info( ).is_directory_ );
        std::cout << lstring
                  << ( i->info( ).is_empty_ ? " " : "+" );
        std::cout << ( is_dir ? "[" : " " )
                  << leaf_of(i->info( ).path_)
                  << ( is_dir ? "]" : " " )
                  << "\n";
    }
}

void push_file( client::vtrc_client_sptr client,
                const std::string &local_path, size_t block_size )
{
    std::string name = leaf_of( local_path );
    vtrc::shared_ptr<interfaces::remote_file> rem_f
            ( interfaces::create_remote_file( client, name, "wb" ) );

    std::cout << "Open remote file success.\n"
              << "Starting...\n"
              << "Block size = " << block_size
              << std::endl;

    std::ifstream f;
    f.open(local_path.c_str( ), std::ofstream::in );

    std::string block(block_size, 0);
    size_t total = 0;

    size_t r = f.readsome( &block[0], block_size );
    while( r ) {
        size_t shift = 0;
        while ( r ) {
            size_t w = rem_f->write( block.c_str( ) + shift, r );
            total += w;
            shift += w;
            r -= w;
            std::cout << "Post " << total << " bytes\r";
        }
        r = f.readsome( &block[0], block_size );
    }

    std::cout << "\nUpload complete\n";

}

void pull_file( client::vtrc_client_sptr client,
                vtrc::shared_ptr<interfaces::remote_fs> &impl,
                const std::string &remote_path, size_t block_size )
{
    size_t remote_size = -1;
    try {
        remote_size = impl->file_size( remote_path );
        std::cout << "Remote file size is: " << remote_size << "\n";
    } catch( const vtrc::common::exception &ex ) {
        std::cout << "Remote file size is unknown: "
                  << remote_path
                  << " '" << ex.what( ) << "; " << ex.additional( ) << "'"
                  << "\n";
    }

    std::string name = leaf_of( remote_path );
    vtrc::shared_ptr<interfaces::remote_file> rem_f
            ( interfaces::create_remote_file( client, remote_path, "rb" ) );

    std::cout << "Open remote file success.\n"
              << "Starting...\n"
              << "Block size = " << block_size
              << std::endl;

    std::ofstream f;
    f.open(name.c_str( ), std::ofstream::out );

    std::string block;
    size_t total = 0;

    while( rem_f->read( block, block_size ) ) {
        total += block.size( );
        std::cout << "Got " << total << " bytes\r";
        f.write( block.c_str( ), block.size( ) );
    }
    std::cout << "\nDownload complete\n";
}

void tree_dir( vtrc::shared_ptr<interfaces::remote_fs> &impl,
               const std::string &path,
               int level = 0 )
{
    vtrc::shared_ptr<interfaces::remote_fs_iterator> i
                                                (impl->begin_iterator( path ));
    std::string lstring( level * 2, ' ' );
    for( ; !i->end( ); i->next( )) {
        bool is_dir( i->info( ).is_directory_ );
        std::cout << lstring
                  << ( i->info( ).is_empty_ ? " " : "+" );
        if( is_dir ) {
            std::cout << "[" << leaf_of(i->info( ).path_) << "]\n";
            try {
                tree_dir( impl, i->info( ).path_, level + 1 );
            } catch( ... ) {
                std::cout << lstring << "  <iteration failed>\n";
            }
        } else if( i->info( ).is_symlink_ ) {
            std::cout << "<!" << leaf_of(i->info( ).path_) << ">\n";
        } else {
            std::cout << " " << leaf_of(i->info( ).path_) << "\n";
        }

    }
}

void tree_dir( vtrc::shared_ptr<interfaces::remote_fs> &impl )
{
    tree_dir( impl, "", 0 );
}

int start( const po::variables_map &params )
{

    if( params.count( "server" ) == 0 ) {
        throw std::runtime_error("Server is not defined;\n"
                                 "Use --help for details");
    }

    common::pool_pair pp(1, 1);
    client::vtrc_client_sptr client = client::vtrc_client::create( pp );

    /// connect slot to 'on_ready'
    std::cout << "Creating client ... " ;
    vtrc::condition_variable ready_cond;
    client->get_on_ready( ).connect( vtrc::bind( on_client_ready,
                            vtrc::ref( ready_cond ) ) );

    std::cout << "success\n";

    std::string path;

    connect_to( client, params["server"].as<std::string>( ) );

    std::cout << "Connected to "
              << params["server"].as<std::string>( ) << "\n";

    vtrc::mutex                    ready_mutex;
    vtrc::unique_lock<vtrc::mutex> ready_lock(ready_mutex);
    ready_cond.wait( ready_lock, vtrc::bind( &client::vtrc_client::ready,
                                              client ) );

    if( params.count( "path" ) ) {
        path = params["path"].as<std::string>( );
    }

    std::cout << "Path is: '" << path << "'\nCreating interface...";

    vtrc::shared_ptr<interfaces::remote_fs> impl
            (interfaces::create_remote_fs(client, path));

    std::cout << "Success; id is '" << impl->get_handle( ) << "'\n";

    std::cout << "Path " << ( impl->exists(  ) ? "exists" : "not exists" )
              << "\n";

    if( params.count( "pwd" ) ) {
        std::cout << "PWD: " << impl->pwd( ) << "\n";
    }

    if( params.count( "info" ) ) {
        std::string pi(params["info"].as<std::string>( ));
        std::cout << "Trying get info about '" << pi << "'...";
        interfaces::fs_info inf = impl->info( pi );
        std::cout << "success.\nInfo:\n";
        std::cout << "\texists:\t\t"
                  << (inf.is_exist_ ? "true" : "false") << "\n";
        std::cout << "\tdirectory:\t"
                  << (inf.is_directory_ ? "true" : "false") << "\n";
        std::cout << "\tempty:\t\t"
                  << (inf.is_empty_ ? "true" : "false") << "\n";
        std::cout << "\tregular:\t"
                  << (inf.is_regular_ ? "true" : "false") << "\n";
    }

    if( params.count( "list" ) ) {
        std::cout << "List dir:\n";
        list_dir( impl );
    }

    if( params.count( "tree" ) ) {
        std::cout << "Tree dir:\n";
        tree_dir( impl );
    }

    size_t bs = params.count( "block-size" )
            ? params["block-size"].as<unsigned>( )
            : 4096;

    if( params.count( "pull" ) ) {
        std::string path = params["pull"].as<std::string>( );
        std::cout << "pull file '" << path << "'\n";
        pull_file( client, impl, path, bs );
    }

    if( params.count( "push" ) ) {
        std::string path = params["push"].as<std::string>( );
        std::cout << "push file '" << path << "'\n";
        push_file( client, path, bs );
    }

    impl.reset( ); // close fs instance
    pp.stop_all( );
    pp.join_all( );

    return 0;
}
<commit_msg>examples; fix for tcpv6 address<commit_after>#include <vector>
#include <string>

#include <fstream>

#include "boost/program_options.hpp"
#include "boost/algorithm/string.hpp"
#include "boost/lexical_cast.hpp"

#include "vtrc-client-base/vtrc-client.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-exception.h"

#include "remote-fs-iface.h"

#include "vtrc-condition-variable.h"
#include "vtrc-mutex.h"
#include "vtrc-bind.h"
#include "vtrc-ref.h"

namespace po = boost::program_options;
using namespace vtrc;

void get_options( po::options_description& desc )
{
    desc.add_options( )
        ("help,?",   "help message")
        ("server,s", po::value<std::string>( ),
                     "server name; <tcp address>:<port> or <pipe/file name>")
        ("path,p", po::value<std::string>( ), "Init remote path for client")
        ("pwd,w", "Show current remote path")
        ("info,i", po::value<std::string>( ), "Show info about remote path")
        ("list,l", "list remote directory")
        ("tree,t", "show remote directory as tree")

        ("pull,g", po::value<std::string>( ), "Download remote file")
        ("push,u", po::value<std::string>( ), "Upload local file")

        ("block-size,b", po::value<unsigned>( ), "Block size for pull and push"
                                                 "; 1-44000")

        ;
}

void connect_to( client::vtrc_client_sptr client, std::string const &name )
{
    std::vector<std::string> params;

    std::string::const_reverse_iterator b(name.rbegin( ));
    std::string::const_reverse_iterator e(name.rend( ));
    for( ; b!=e ;++b ) {
        if( *b == ':' ) {
            std::string::const_reverse_iterator bb(b);
            ++bb;
            params.push_back( std::string( name.begin( ), bb.base( )) );
            params.push_back( std::string( b.base( ), name.end( )));

            break;
        }
    }

    if( params.empty( ) ) {
        params.push_back( name );
    }

    if( params.size( ) == 1 ) {        /// local name
        client->connect( params[0] );
    } else if( params.size( ) == 2 ) { /// tcp
        client->connect( params[0], params[1]);
    }

}

void on_client_ready( vtrc::condition_variable &cond )
{
    std::cout << "Connection is ready...\n";
    cond.notify_all( );
}

std::string leaf_of( const std::string &path )
{
    std::string::const_reverse_iterator b(path.rbegin( ));
    std::string::const_reverse_iterator e(path.rend( ));
    for( ; b!=e ;++b ) {
        if( *b == '/' || *b == '\\' ) {
            return std::string( b.base( ), path.end( ) );
        }
    }
    return path;
}

void list_dir( vtrc::shared_ptr<interfaces::remote_fs> &impl )
{
    vtrc::shared_ptr<interfaces::remote_fs_iterator> i(impl->begin_iterator( ));
    std::string lstring( 2, ' ' );
    for( ; !i->end( ); i->next( )) {
        bool is_dir( i->info( ).is_directory_ );
        std::cout << lstring
                  << ( i->info( ).is_empty_ ? " " : "+" );
        std::cout << ( is_dir ? "[" : " " )
                  << leaf_of(i->info( ).path_)
                  << ( is_dir ? "]" : " " )
                  << "\n";
    }
}

void push_file( client::vtrc_client_sptr client,
                const std::string &local_path, size_t block_size )
{
    std::string name = leaf_of( local_path );
    vtrc::shared_ptr<interfaces::remote_file> rem_f
            ( interfaces::create_remote_file( client, name, "wb" ) );

    std::cout << "Open remote file success.\n"
              << "Starting...\n"
              << "Block size = " << block_size
              << std::endl;

    std::ifstream f;
    f.open(local_path.c_str( ), std::ofstream::in );

    std::string block(block_size, 0);
    size_t total = 0;

    size_t r = f.readsome( &block[0], block_size );
    while( r ) {
        size_t shift = 0;
        while ( r ) {
            size_t w = rem_f->write( block.c_str( ) + shift, r );
            total += w;
            shift += w;
            r -= w;
            std::cout << "Post " << total << " bytes\r";
        }
        r = f.readsome( &block[0], block_size );
    }

    std::cout << "\nUpload complete\n";

}

void pull_file( client::vtrc_client_sptr client,
                vtrc::shared_ptr<interfaces::remote_fs> &impl,
                const std::string &remote_path, size_t block_size )
{
    size_t remote_size = -1;
    try {
        remote_size = impl->file_size( remote_path );
        std::cout << "Remote file size is: " << remote_size << "\n";
    } catch( const vtrc::common::exception &ex ) {
        std::cout << "Remote file size is unknown: "
                  << remote_path
                  << " '" << ex.what( ) << "; " << ex.additional( ) << "'"
                  << "\n";
    }

    std::string name = leaf_of( remote_path );
    vtrc::shared_ptr<interfaces::remote_file> rem_f
            ( interfaces::create_remote_file( client, remote_path, "rb" ) );

    std::cout << "Open remote file success.\n"
              << "Starting...\n"
              << "Block size = " << block_size
              << std::endl;

    std::ofstream f;
    f.open(name.c_str( ), std::ofstream::out );

    std::string block;
    size_t total = 0;

    while( rem_f->read( block, block_size ) ) {
        total += block.size( );
        std::cout << "Got " << total << " bytes\r";
        f.write( block.c_str( ), block.size( ) );
    }
    std::cout << "\nDownload complete\n";
}

void tree_dir( vtrc::shared_ptr<interfaces::remote_fs> &impl,
               const std::string &path,
               int level = 0 )
{
    vtrc::shared_ptr<interfaces::remote_fs_iterator> i
                                                (impl->begin_iterator( path ));
    std::string lstring( level * 2, ' ' );
    for( ; !i->end( ); i->next( )) {
        bool is_dir( i->info( ).is_directory_ );
        std::cout << lstring
                  << ( i->info( ).is_empty_ ? " " : "+" );
        if( is_dir ) {
            std::cout << "[" << leaf_of(i->info( ).path_) << "]\n";
            try {
                tree_dir( impl, i->info( ).path_, level + 1 );
            } catch( ... ) {
                std::cout << lstring << "  <iteration failed>\n";
            }
        } else if( i->info( ).is_symlink_ ) {
            std::cout << "<!" << leaf_of(i->info( ).path_) << ">\n";
        } else {
            std::cout << " " << leaf_of(i->info( ).path_) << "\n";
        }

    }
}

void tree_dir( vtrc::shared_ptr<interfaces::remote_fs> &impl )
{
    tree_dir( impl, "", 0 );
}

int start( const po::variables_map &params )
{

    if( params.count( "server" ) == 0 ) {
        throw std::runtime_error("Server is not defined;\n"
                                 "Use --help for details");
    }

    /// will use onle one thread for io.
    /// because we don't have callbacks or events from server-side
    common::pool_pair pp( 1 );

    client::vtrc_client_sptr client = client::vtrc_client::create( pp );

    /// connect slot to 'on_ready'
    std::cout << "Creating client ... " ;
    vtrc::condition_variable ready_cond;
    client->get_on_ready( ).connect( vtrc::bind( on_client_ready,
                            vtrc::ref( ready_cond ) ) );

    std::cout << "success\n";

    std::string path;

    connect_to( client, params["server"].as<std::string>( ) );

    std::cout << "Connected to "
              << params["server"].as<std::string>( ) << "\n";

    vtrc::mutex                    ready_mutex;
    vtrc::unique_lock<vtrc::mutex> ready_lock(ready_mutex);
    ready_cond.wait( ready_lock, vtrc::bind( &client::vtrc_client::ready,
                                              client ) );

    if( params.count( "path" ) ) {
        path = params["path"].as<std::string>( );
    }

    std::cout << "Path is: '" << path << "'\nCreating interface...";

    vtrc::shared_ptr<interfaces::remote_fs> impl
            (interfaces::create_remote_fs(client, path));

    std::cout << "Success; id is '" << impl->get_handle( ) << "'\n";

    std::cout << "Path " << ( impl->exists(  ) ? "exists" : "not exists" )
              << "\n";

    if( params.count( "pwd" ) ) {
        std::cout << "PWD: " << impl->pwd( ) << "\n";
    }

    if( params.count( "info" ) ) {
        std::string pi(params["info"].as<std::string>( ));
        std::cout << "Trying get info about '" << pi << "'...";
        interfaces::fs_info inf = impl->info( pi );
        std::cout << "success.\nInfo:\n";
        std::cout << "\texists:\t\t"
                  << (inf.is_exist_ ? "true" : "false") << "\n";
        std::cout << "\tdirectory:\t"
                  << (inf.is_directory_ ? "true" : "false") << "\n";
        std::cout << "\tempty:\t\t"
                  << (inf.is_empty_ ? "true" : "false") << "\n";
        std::cout << "\tregular:\t"
                  << (inf.is_regular_ ? "true" : "false") << "\n";
    }

    if( params.count( "list" ) ) {
        std::cout << "List dir:\n";
        list_dir( impl );
    }

    if( params.count( "tree" ) ) {
        std::cout << "Tree dir:\n";
        tree_dir( impl );
    }

    size_t bs = params.count( "block-size" )
            ? params["block-size"].as<unsigned>( )
            : 4096;

    if( params.count( "pull" ) ) {
        std::string path = params["pull"].as<std::string>( );
        std::cout << "pull file '" << path << "'\n";
        pull_file( client, impl, path, bs );
    }

    if( params.count( "push" ) ) {
        std::string path = params["push"].as<std::string>( );
        std::cout << "push file '" << path << "'\n";
        push_file( client, path, bs );
    }

    impl.reset( ); // close fs instance
    pp.stop_all( );
    pp.join_all( );

    return 0;
}
<|endoftext|>


<commit_before>// FieldMap
// Author: Matthew Raso-Barnett  13/12/2010
#include <list>
#include <cmath>
#include <iostream>

#include "FieldMap.h"
#include "FileParser.h"
#include "VertexStack.h"
#include "Particle.h"
#include "Run.h"

//#define VERBOSE

using namespace std;

//______________________________________________________________________________
// FieldMap -
//
//______________________________________________________________________________

ClassImp(FieldMap)

//_____________________________________________________________________________
FieldMap::FieldMap()
{
// Default constructor.
   Info("FieldMap", "Default Constructor");
}

//_____________________________________________________________________________
FieldMap::FieldMap(const FieldMap& /*other*/)
{
// Copy constructor.
}

//______________________________________________________________________________
FieldMap::~FieldMap()
{
// Destructor.
   Info("FieldMap", "Destructor");
}

//______________________________________________________________________________
// MagFieldMap -
//
//______________________________________________________________________________

ClassImp(MagFieldMap)

//_____________________________________________________________________________
MagFieldMap::MagFieldMap()
            :FieldMap(),
             fTree(NULL)
{
// Default constructor.
   Info("MagFieldMap", "Default Constructor");
}

//_____________________________________________________________________________
MagFieldMap::MagFieldMap(const string& name, const TGeoShape* shape, const TGeoMatrix* matrix)
            :FieldMap(),
             MagField(name, shape, matrix),
             fTree(NULL)
{
// Default constructor.
   Info("MagFieldMap", "Constructor");
}

//_____________________________________________________________________________
MagFieldMap::MagFieldMap(const MagFieldMap& other)
            :FieldMap(other),
             MagField(other),
             fTree(NULL)
{
// Copy constructor.
   Info("MagFieldMap", "Copy Constructor");
}

//______________________________________________________________________________
MagFieldMap::~MagFieldMap()
{
// Destructor.
   Info("MagFieldMap", "Destructor");
   if (fTree) delete fTree;
}

//______________________________________________________________________________
const TVector3 MagFieldMap::GetField(const Point& point) const
{
   // -- Perform interpolation to get current field
   // If point requested was recently measured, return its value. Saves recomputing the value
   static FieldVertex cachedReading(0.,0.,0.,0.,0.,0.,0.);
   if (cachedReading.GetPoint() == point) {
      cout << "Using Cache! Point: " << point.X() << "\t" << point.Y() << "\t" << point.Z() << endl;
      return cachedReading.GetField();
   }
   // Number of interpolation points is currently an arbitrary number. Need to define this
   // at runtime perhaps through another config variable.
   Int_t numInterpolatePoints = 6;
   const TVector3 field = this->Interpolate(point.GetPosition(), numInterpolatePoints);
   // Update cached reading before return vale
   cachedReading.SetField(field);
   return field;
}

//______________________________________________________________________________
Bool_t MagFieldMap::BuildMap(const std::string& filename)
{
   // -- Take input file and initialise a KDTree object data structure to hold the field points.
   cout << "Building MagFieldMap from file: " << filename << endl;
   FileParser parser;
   // Get flat list of Field vertices from provided file using the parser
   vector<FieldVertex*> vertices;
   if (parser.ExtractFieldVertices(filename, vertices) == false) {
      Error("BuildMap","Failed to extract field vertices from: %s", filename.c_str());
      return false;
   }
   // For each vertex, convert coordinates to the global coordinate system
   vector<const FieldVertex*> global_vertices;
   vector<FieldVertex*>::const_iterator iter;
   for (iter = vertices.begin(); iter != vertices.end(); iter++) {
      FieldVertex global = this->ConvertToGlobalFrame((**iter));
      global_vertices.push_back(new FieldVertex(global));
   }
   // Build Tree structure of FieldVertices
   fTree = new KDTree(global_vertices);
   // Delete original local points
   for (iter = vertices.begin(); iter != vertices.end(); iter++) {if (*iter) delete *iter;}
   cout << "Successfully created MagFieldMap from " << global_vertices.size() << " points." << endl;
   return true;
}

//______________________________________________________________________________
TVector3 MagFieldMap::Interpolate(const TVector3& position, const Int_t numInterpolatePoints) const
{
   // -- For given position, find the n-nearest-neighbouring vertices (n being numInterpolatePoints)
   // -- and perform IDW interpolation using Modified Shepard's Method,
   // -- http://en.wikipedia.org/wiki/Inverse_distance_weighting
   FieldVertex vertex(position.X(), position.Y(), position.Z(), 0.,0.,0.,0.);
   const VertexStack* neighbours = fTree->NearestNeighbours(vertex, numInterpolatePoints);
   list<StackElement>::const_iterator stackIter;
   double radius = (neighbours->back()).second;
   double sumWeights = 0.;
   TVector3 avgField;
   for (stackIter = neighbours->begin(); stackIter != neighbours->end(); stackIter++) {
      double distance = stackIter->second;
      const FieldVertex* vertex = stackIter->first;
      double weight = pow((radius - distance)/(radius*distance),2.0);
      #ifdef VERBOSE
         cout << "Vertex: " << vertex->ToString() << "\t";
         cout << "Distance: " << distance << "\t";
         cout << "Weight: " << weight << endl;
      #endif
      sumWeights += weight;
      avgField += weight*(vertex->GetField());
   }
   avgField = avgField*(1.0/sumWeights);
   // Delete nearest neighbours now that we are finished with it
   delete neighbours;
   return avgField;
}

<commit_msg>Remove comments from MagFieldMap::GetField <commit_after>// FieldMap
// Author: Matthew Raso-Barnett  13/12/2010
#include <list>
#include <cmath>
#include <iostream>

#include "FieldMap.h"
#include "FileParser.h"
#include "VertexStack.h"
#include "Particle.h"
#include "Run.h"

//#define VERBOSE

using namespace std;

//______________________________________________________________________________
// FieldMap -
//
//______________________________________________________________________________

ClassImp(FieldMap)

//_____________________________________________________________________________
FieldMap::FieldMap()
{
// Default constructor.
   Info("FieldMap", "Default Constructor");
}

//_____________________________________________________________________________
FieldMap::FieldMap(const FieldMap& /*other*/)
{
// Copy constructor.
}

//______________________________________________________________________________
FieldMap::~FieldMap()
{
// Destructor.
   Info("FieldMap", "Destructor");
}

//______________________________________________________________________________
// MagFieldMap -
//
//______________________________________________________________________________

ClassImp(MagFieldMap)

//_____________________________________________________________________________
MagFieldMap::MagFieldMap()
            :FieldMap(),
             fTree(NULL)
{
// Default constructor.
   Info("MagFieldMap", "Default Constructor");
}

//_____________________________________________________________________________
MagFieldMap::MagFieldMap(const string& name, const TGeoShape* shape, const TGeoMatrix* matrix)
            :FieldMap(),
             MagField(name, shape, matrix),
             fTree(NULL)
{
// Default constructor.
   Info("MagFieldMap", "Constructor");
}

//_____________________________________________________________________________
MagFieldMap::MagFieldMap(const MagFieldMap& other)
            :FieldMap(other),
             MagField(other),
             fTree(NULL)
{
// Copy constructor.
   Info("MagFieldMap", "Copy Constructor");
}

//______________________________________________________________________________
MagFieldMap::~MagFieldMap()
{
// Destructor.
   Info("MagFieldMap", "Destructor");
   if (fTree) delete fTree;
}

//______________________________________________________________________________
const TVector3 MagFieldMap::GetField(const Point& point) const
{
   // -- Perform interpolation to get current field
   // If point requested was recently measured, return its value. Saves recomputing the value
   static FieldVertex cachedReading(0.,0.,0.,0.,0.,0.,0.);
   static FieldVertex cachedReading;
   if (cachedReading.GetPoint() == point) {return cachedReading.GetField();}
   // Number of interpolation points is currently an arbitrary number. Need to define this
   // at runtime perhaps through another config variable.
   Int_t numInterpolatePoints = 6;
   const TVector3 field = this->Interpolate(point.GetPosition(), numInterpolatePoints);
   // Update cached reading before return vale
   cachedReading.SetField(field);
   return field;
}

//______________________________________________________________________________
Bool_t MagFieldMap::BuildMap(const std::string& filename)
{
   // -- Take input file and initialise a KDTree object data structure to hold the field points.
   cout << "Building MagFieldMap from file: " << filename << endl;
   FileParser parser;
   // Get flat list of Field vertices from provided file using the parser
   vector<FieldVertex*> vertices;
   if (parser.ExtractFieldVertices(filename, vertices) == false) {
      Error("BuildMap","Failed to extract field vertices from: %s", filename.c_str());
      return false;
   }
   // For each vertex, convert coordinates to the global coordinate system
   vector<const FieldVertex*> global_vertices;
   vector<FieldVertex*>::const_iterator iter;
   for (iter = vertices.begin(); iter != vertices.end(); iter++) {
      FieldVertex global = this->ConvertToGlobalFrame((**iter));
      global_vertices.push_back(new FieldVertex(global));
   }
   // Build Tree structure of FieldVertices
   fTree = new KDTree(global_vertices);
   // Delete original local points
   for (iter = vertices.begin(); iter != vertices.end(); iter++) {if (*iter) delete *iter;}
   cout << "Successfully created MagFieldMap from " << global_vertices.size() << " points." << endl;
   return true;
}

//______________________________________________________________________________
TVector3 MagFieldMap::Interpolate(const TVector3& position, const Int_t numInterpolatePoints) const
{
   // -- For given position, find the n-nearest-neighbouring vertices (n being numInterpolatePoints)
   // -- and perform IDW interpolation using Modified Shepard's Method,
   // -- http://en.wikipedia.org/wiki/Inverse_distance_weighting
   FieldVertex vertex(position.X(), position.Y(), position.Z(), 0.,0.,0.,0.);
   const VertexStack* neighbours = fTree->NearestNeighbours(vertex, numInterpolatePoints);
   list<StackElement>::const_iterator stackIter;
   double radius = (neighbours->back()).second;
   double sumWeights = 0.;
   TVector3 avgField;
   for (stackIter = neighbours->begin(); stackIter != neighbours->end(); stackIter++) {
      double distance = stackIter->second;
      const FieldVertex* vertex = stackIter->first;
      double weight = pow((radius - distance)/(radius*distance),2.0);
      #ifdef VERBOSE
         cout << "Vertex: " << vertex->ToString() << "\t";
         cout << "Distance: " << distance << "\t";
         cout << "Weight: " << weight << endl;
      #endif
      sumWeights += weight;
      avgField += weight*(vertex->GetField());
   }
   avgField = avgField*(1.0/sumWeights);
   // Delete nearest neighbours now that we are finished with it
   delete neighbours;
   return avgField;
}

<|endoftext|>