// GMTL is (C) Copyright 2001-2010 by Allen Bierbaum
// Distributed under the GNU Lesser General Public License 2.1 with an
// addendum covering inlined code. (See accompanying files LICENSE and
// LICENSE.addendum or http://www.gnu.org/copyleft/lesser.txt)

// Includes ====================================================================
#include <boost/python.hpp>
#include <gmtl-Generate.h>

// Using =======================================================================
using namespace boost::python;

// Declarations ================================================================

namespace  {

BOOST_PYTHON_FUNCTION_OVERLOADS(setDirCos_overloads_4_7, gmtl::setDirCos, 4, 7)

}// namespace

// Module ======================================================================
void _Export_gmtl_Generate_h()
{
    def("makeConj", (gmtl::Quat<double> (*)(const gmtl::Quat<double> &))&gmtl::makeConj);
    def("makeConj", (gmtl::Quat<float> (*)(const gmtl::Quat<float> &))&gmtl::makeConj);
    def("makeCross", (gmtl::Vec<int,3> (*)(const gmtl::Vec<int,3> &, const gmtl::Vec<int,3> &))&gmtl::makeCross);
    def("makeCross", (gmtl::Vec<float,3> (*)(const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::makeCross);
    def("makeCross", (gmtl::Vec<double,3> (*)(const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtl::makeCross);
    def("makeInvert", (gmtl::Quat<float> (*)(const gmtl::Quat<float> &))&gmtl::makeInvert);
    def("makeInvert", (gmtl::Quat<double> (*)(const gmtl::Quat<double> &))&gmtl::makeInvert);
    def("makeInvert", (gmtl::Matrix<double,4,4> (*)(const gmtl::Matrix<double,4,4> &))&gmtl::makeInvert);
    def("makeInvert", (gmtl::Matrix<float,3,3> (*)(const gmtl::Matrix<float,3,3> &))&gmtl::makeInvert);
    def("makeInvert", (gmtl::Matrix<float,4,4> (*)(const gmtl::Matrix<float,4,4> &))&gmtl::makeInvert);
    def("makeInvert", (gmtl::Matrix<double,3,3> (*)(const gmtl::Matrix<double,3,3> &))&gmtl::makeInvert);
    def("makeNormal", (gmtl::Quat<float> (*)(const gmtl::Quat<float> &))&gmtl::makeNormal);
    def("makeNormal", (gmtl::Quat<double> (*)(const gmtl::Quat<double> &))&gmtl::makeNormal);
    def("makeNormal", (gmtl::Vec<float,4> (*)(gmtl::Vec<float,4>))&gmtl::makeNormal);
    def("makeNormal", (gmtl::Vec<double,4> (*)(gmtl::Vec<double,4>))&gmtl::makeNormal);
    def("makeNormal", (gmtl::Vec<float,3> (*)(gmtl::Vec<float,3>))&gmtl::makeNormal);
    def("makeNormal", (gmtl::Vec<double,3> (*)(gmtl::Vec<double,3>))&gmtl::makeNormal);
    def("makeNormal", (gmtl::AxisAngle<float> (*)(const gmtl::AxisAngle<float> &))&gmtl::makeNormal);
    def("makeNormal", (gmtl::AxisAngle<double> (*)(const gmtl::AxisAngle<double> &))&gmtl::makeNormal);
    def("makePure", (gmtl::Quat<float> (*)(const gmtl::Vec<float,3> &))&gmtl::makePure);
    def("makePure", (gmtl::Quat<double> (*)(const gmtl::Vec<double,3> &))&gmtl::makePure);
    def("makeTranspose", (gmtl::Matrix<float,3,3> (*)(const gmtl::Matrix<float,3,3> &))&gmtl::makeTranspose);
    def("makeTranspose", (gmtl::Matrix<float,4,4> (*)(const gmtl::Matrix<float,4,4> &))&gmtl::makeTranspose);
    def("makeTranspose", (gmtl::Matrix<double,3,3> (*)(const gmtl::Matrix<double,3,3> &))&gmtl::makeTranspose);
    def("makeTranspose", (gmtl::Matrix<double,4,4> (*)(const gmtl::Matrix<double,4,4> &))&gmtl::makeTranspose);
    def("makeVec", (gmtl::Vec<float,3> (*)(const gmtl::Quat<float> &))&gmtl::makeVec);
    def("makeVec", (gmtl::Vec<double,3> (*)(const gmtl::Quat<double> &))&gmtl::makeVec);
    def("makeXRot", (float (*)(const gmtl::Matrix<float,3,3> &))&gmtl::makeXRot);
    def("makeXRot", (float (*)(const gmtl::Matrix<float,4,4> &))&gmtl::makeXRot);
    def("makeXRot", (double (*)(const gmtl::Matrix<double,3,3> &))&gmtl::makeXRot);
    def("makeXRot", (double (*)(const gmtl::Matrix<double,4,4> &))&gmtl::makeXRot);
    def("makeYRot", (float (*)(const gmtl::Matrix<float,4,4> &))&gmtl::makeYRot);
    def("makeYRot", (double (*)(const gmtl::Matrix<double,3,3> &))&gmtl::makeYRot);
    def("makeYRot", (float (*)(const gmtl::Matrix<float,3,3> &))&gmtl::makeYRot);
    def("makeYRot", (double (*)(const gmtl::Matrix<double,4,4> &))&gmtl::makeYRot);
    def("makeZRot", (float (*)(const gmtl::Matrix<float,3,3> &))&gmtl::makeZRot);
    def("makeZRot", (double (*)(const gmtl::Matrix<double,3,3> &))&gmtl::makeZRot);
    def("makeZRot", (float (*)(const gmtl::Matrix<float,4,4> &))&gmtl::makeZRot);
    def("makeZRot", (double (*)(const gmtl::Matrix<double,4,4> &))&gmtl::makeZRot);
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::Quat<double> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Quat<float> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::AxisAngle<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Quat<float> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::AxisAngle<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::AxisAngle<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::AxisAngle<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const gmtl::Quat<double> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::EulerAngle<float,gmtl::ZXY> & (*)(gmtl::EulerAngle<float,gmtl::ZXY> &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::EulerAngle<float,gmtl::ZXY> & (*)(gmtl::EulerAngle<float,gmtl::ZXY> &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::EulerAngle<float,gmtl::ZYX> & (*)(gmtl::EulerAngle<float,gmtl::ZYX> &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::EulerAngle<float,gmtl::ZYX> & (*)(gmtl::EulerAngle<float,gmtl::ZYX> &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::EulerAngle<float,gmtl::XYZ> & (*)(gmtl::EulerAngle<float,gmtl::XYZ> &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::EulerAngle<float,gmtl::XYZ> & (*)(gmtl::EulerAngle<float,gmtl::XYZ> &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<double> & (*)(gmtl::Quat<double> &, const gmtl::Matrix<double,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::AxisAngle<float> & (*)(gmtl::AxisAngle<float> &, gmtl::Quat<float>))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::AxisAngle<double> & (*)(gmtl::AxisAngle<double> &, gmtl::Quat<double>))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,4,4> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > &, const gmtl::Matrix<float,3,3> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::AxisAngle<float> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Quat<double> & (*)(gmtl::Quat<double> &, const gmtl::AxisAngle<double> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::AxisAngle<double> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::AxisAngle<float> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::EulerAngle<double,gmtl::XYZ> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::EulerAngle<double,gmtl::ZYX> &))&gmtl::set, return_internal_reference< 1 >());
    def("set", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::EulerAngle<double,gmtl::ZXY> &))&gmtl::set, return_internal_reference< 1 >());
    def("setAxes", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtl::setAxes, return_internal_reference< 1 >());
    def("setAxes", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::setAxes, return_internal_reference< 1 >());
    def("setAxes", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtl::setAxes, return_internal_reference< 1 >());
    def("setAxes", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::setAxes, return_internal_reference< 1 >());
#ifndef _MSC_VER
    def("setDirCos", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::setDirCos,
        setDirCos_overloads_4_7()[return_internal_reference<1>()]);
    def("setDirCos", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtl::setDirCos,
        setDirCos_overloads_4_7()[return_internal_reference<1>()]);
    def("setDirCos", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::setDirCos,
        setDirCos_overloads_4_7()[return_internal_reference<1>()]);
    def("setDirCos", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtl::setDirCos,
        setDirCos_overloads_4_7()[return_internal_reference<1>()]);
#endif
    def("setFrustum", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, float, float, float, float, float, float))&gmtl::setFrustum, return_internal_reference< 1 >());
    def("setFrustum", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, double, double, double, double, double, double))&gmtl::setFrustum, return_internal_reference< 1 >());
    def("setPerspective", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, float, float, float, float))&gmtl::setPerspective, return_internal_reference< 1 >());
    def("setPerspective", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, double, double, double, double))&gmtl::setPerspective, return_internal_reference< 1 >());
    def("setPure", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::Vec<float,3> &))&gmtl::setPure, return_internal_reference< 1 >());
    def("setPure", (gmtl::Quat<double> & (*)(gmtl::Quat<double> &, const gmtl::Vec<double,3> &))&gmtl::setPure, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::Quat<float> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::Quat<double> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::XYZ> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<double> & (*)(gmtl::Quat<double> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::Quat<float> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > & (*)(gmtl::Coord<gmtl::Vec<float, 4>,gmtl::EulerAngle<float, gmtl::ZXY> > &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::EulerAngle<float,gmtl::XYZ> & (*)(gmtl::EulerAngle<float,gmtl::XYZ> &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::EulerAngle<float,gmtl::ZXY> & (*)(gmtl::EulerAngle<float,gmtl::ZXY> &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::EulerAngle<float,gmtl::ZYX> & (*)(gmtl::EulerAngle<float,gmtl::ZYX> &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::Matrix<float,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<double> & (*)(gmtl::Quat<double> &, const gmtl::Matrix<double,4,4> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::AxisAngle<float> & (*)(gmtl::AxisAngle<float> &, gmtl::Quat<float>))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::AxisAngle<double> & (*)(gmtl::AxisAngle<double> &, gmtl::Quat<double>))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Quat<float> & (*)(gmtl::Quat<float> &, const gmtl::AxisAngle<float> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::AxisAngle<float> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::AxisAngle<double> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::AxisAngle<float> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::EulerAngle<double,gmtl::XYZ> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::EulerAngle<double,gmtl::ZXY> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::EulerAngle<double,gmtl::ZYX> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > & (*)(gmtl::Coord<gmtl::Vec<float, 3>,gmtl::EulerAngle<float, gmtl::ZYX> > &, const gmtl::Matrix<float,3,3> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Quat<float> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Quat<float> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setRot", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const gmtl::Quat<double> &))&gmtl::setRot, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::Vec<float,2> &))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const double))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const gmtl::Vec<double,2> &))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const float))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::Vec<float,3> &))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const double))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::Vec<double,3> &))&gmtl::setScale, return_internal_reference< 1 >());
    def("setScale", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const float))&gmtl::setScale, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<float,4> & (*)(gmtl::Vec<float,4> &, const gmtl::Matrix<float,4,4> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<float,3> & (*)(gmtl::Vec<float,3> &, const gmtl::Matrix<float,3,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<double,3> & (*)(gmtl::Vec<double,3> &, const gmtl::Matrix<double,4,4> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<float,3> & (*)(gmtl::Vec<float,3> &, const gmtl::Matrix<float,4,4> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<float,4> & (*)(gmtl::Vec<float,4> &, const gmtl::Matrix<float,3,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<float,2> & (*)(gmtl::Vec<float,2> &, const gmtl::Matrix<float,3,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Vec<double,2> & (*)(gmtl::Vec<double,2> &, const gmtl::Matrix<double,3,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::VecBase<float,4> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::VecBase<float,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::VecBase<float,4> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<float,4,4> & (*)(gmtl::Matrix<float,4,4> &, const gmtl::VecBase<float,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<double,4,4> & (*)(gmtl::Matrix<double,4,4> &, const gmtl::VecBase<double,3> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<float,3,3> & (*)(gmtl::Matrix<float,3,3> &, const gmtl::VecBase<float,2> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setTrans", (gmtl::Matrix<double,3,3> & (*)(gmtl::Matrix<double,3,3> &, const gmtl::VecBase<double,2> &))&gmtl::setTrans, return_internal_reference< 1 >());
    def("setRow", (void (*)(gmtl::Vec<float, 3>&, const gmtl::Matrix<float, 3, 3>&, unsigned))&gmtl::setRow);
    def("setRow", (void (*)(gmtl::Vec<double, 3>&, const gmtl::Matrix<double, 3, 3>&, unsigned))&gmtl::setRow);
    def("setRow", (void (*)(gmtl::Vec<float, 4>&, const gmtl::Matrix<float, 4, 4>&, unsigned))&gmtl::setRow);
    def("setRow", (void (*)(gmtl::Vec<double, 4>&, const gmtl::Matrix<double, 4, 4>&, unsigned))&gmtl::setRow);
    def("makeRow", (gmtl::Vec<float, 3> (*)(const gmtl::Matrix<float, 3, 3>&, unsigned))&gmtl::makeRow);
    def("makeRow", (gmtl::Vec<double, 3> (*)(const gmtl::Matrix<double, 3, 3>&, unsigned))&gmtl::makeRow);
    def("makeRow", (gmtl::Vec<float, 4> (*)(const gmtl::Matrix<float, 4, 4>&, unsigned))&gmtl::makeRow);
    def("makeRow", (gmtl::Vec<double, 4> (*)(const gmtl::Matrix<double, 4, 4>&, unsigned))&gmtl::makeRow);
    def("setColumn", (void (*)(gmtl::Vec<float, 3>&, const gmtl::Matrix<float, 3, 3>&, unsigned))&gmtl::setColumn);
    def("setColumn", (void (*)(gmtl::Vec<double, 3>&, const gmtl::Matrix<double, 3, 3>&, unsigned))&gmtl::setColumn);
    def("setColumn", (void (*)(gmtl::Vec<float, 4>&, const gmtl::Matrix<float, 4, 4>&, unsigned))&gmtl::setColumn);
    def("setColumn", (void (*)(gmtl::Vec<double, 4>&, const gmtl::Matrix<double, 4, 4>&, unsigned))&gmtl::setColumn);
    def("makeColumn", (gmtl::Vec<float, 3> (*)(const gmtl::Matrix<float, 3, 3>&, unsigned))&gmtl::makeColumn);
    def("makeColumn", (gmtl::Vec<double, 3> (*)(const gmtl::Matrix<double, 3, 3>&, unsigned))&gmtl::makeColumn);
    def("makeColumn", (gmtl::Vec<float, 4> (*)(const gmtl::Matrix<float, 4, 4>&, unsigned))&gmtl::makeColumn);
    def("makeColumn", (gmtl::Vec<double, 4> (*)(const gmtl::Matrix<double, 4, 4>&, unsigned))&gmtl::makeColumn);
}


//==================================================================================================
/**
  Copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
**/
//==================================================================================================
#ifndef BOOST_SIMD_ARCH_X86_AVX2_SIMD_FUNCTION_LOOKUP_HPP_INCLUDED
#define BOOST_SIMD_ARCH_X86_AVX2_SIMD_FUNCTION_LOOKUP_HPP_INCLUDED

#include <boost/simd/detail/overload.hpp>

namespace boost { namespace simd { namespace ext
{
   namespace bd = boost::dispatch;
   namespace bs = boost::simd;

  BOOST_DISPATCH_OVERLOAD( lookup_
                         , (typename A0, typename A1)
                         , bs::avx2_
                         , bs::pack_<bd::ints32_<A0>, bs::avx_>
                         , bs::pack_<bd::ints32_<A1>, bs::avx_>
                         )
  {
    BOOST_FORCEINLINE A0 operator()(A0 const& a0, A1 const& a1) const BOOST_NOEXCEPT
    {
      return _mm256_permutevar8x32_epi32(a0,a1);
    }
  };
  BOOST_DISPATCH_OVERLOAD( lookup_
                         , (typename A0, typename A1)
                         , bs::avx2_
                         , bs::pack_<bd::single_<A0>, bs::avx_>
                         , bs::pack_<bd::ints32_<A1>, bs::avx_>
                         )
  {
    BOOST_FORCEINLINE A0 operator()(A0 const& a0, A1 const& a1) const BOOST_NOEXCEPT
    {
      return _mm256_permutevar8x32_ps(a0,a1);
    }
  };

} } }

#endif


#pragma once

#include <ros/ros.h>

#include <Eigen/Dense>
#include <queue>
#include <memory>

#include "dynamic_motion_planner/RRT_node.hpp"

namespace hdi_plan {

class Human {
public:
	Human(Eigen::Vector2d start_position, int human_id, double start_time, double planning_horizon_time);
	~Human();

	Eigen::Vector2d predict_path(double node_time);
	bool check_if_node_inside_human(const std::shared_ptr<RRTNode>& node);
	double get_distance(const Eigen::Vector2d& state1, const Eigen::Vector2d& state2);

	int get_human_id() const {
		return this->human_id_;
	};

	void set_human_id(int human_id) {
		this->human_id_ = human_id;
	};

	bool get_if_move() const {
		return this->if_move_;
	}

	void set_if_move(bool if_move) {
		this->if_move_ = if_move;
	};

	bool get_if_add() const {
		return this->if_add_;
	}

	void set_if_add(bool if_add) {
		this->if_add_ = if_add;
	};

	void set_start_position(Eigen::Vector2d start_position) {
		this->start_position_ = start_position;
	};

	void set_second_position(Eigen::Vector2d second_position) {
		this->second_position_ = second_position;
	};

	double get_human_block_distance() {
		return this->human_block_distance_;
	}

	double human_height_{3};
	double human_velocity_{1};

private:
	Eigen::Vector2d start_position_;
	Eigen::Vector2d second_position_;
	bool if_move_{false};
	int human_id_{0};
	double start_time_;
	bool if_add_{false};
	double human_block_distance_{4};
	double planning_horizon_time_{15};
	double quadrotor_radius_{0.5};
};

}


// -*- C++ -*-
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//                                   Jiao Lin
//                      California Institute of Technology
//                         (C) 2005 All Rights Reserved
//
// {LicenseText}
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

#include <boost/python.hpp>
#include "mccomposite/mccomposite.h"

namespace wrap_mccomposite {

  typedef mccomposite::geometry::Vector Vector;
  typedef mccomposite::geometry::RotationMatrix RotationMatrix;

  inline double V3_getitem( const Vector & v3, size_t i)
  {
    return v3[i];
  }

  inline size_t V3_size( const Vector & v3)
  {
    return Vector::size();
  }

  void wrap_basics()
  {
    using namespace boost::python;
    // check if prior registration exists
    if (converter::registry::query(type_id<Vector>())==NULL) {
      // register
      class_<Vector>
	("Vector",
	 init<double, double, double>()
	 )
	.def(init<> () )
	.def("__len__", &V3_size )
	.def("__getitem__", &V3_getitem)
	.def("__iter__", iterator<Vector>() )
	;
    }

    // check if prior registration exists
    if (converter::registry::query(type_id<RotationMatrix>())==NULL) {
      class_<RotationMatrix>
	("RotationMatrix",
	 init<double, double, double, double, double, double, double, double, double>()
	 )
	.def(init<> () )
	;
    }
  } // wrap_basics
}

// version
// $Id$

// End of file


#include <iostream>
#include <string>

using std::string;

#include <boost/log/trivial.hpp>

#include "eigenIncluder.hpp"

#include "streamTrace.hpp"
#include "navigation.hpp"
#include "gTime.hpp"
#include "common.hpp"
#include "enums.h"

/* satellite code to satellite system ----------------------------------------*/
E_Sys code2sys(char code)
{
	if (code=='G'||code==' ') return E_Sys::GPS;
	if (code=='R') return E_Sys::GLO;
	if (code=='E') return E_Sys::GAL; /* extension to sp3-c */
	if (code=='J') return E_Sys::QZS; /* extension to sp3-c */
	if (code=='C') return E_Sys::CMP; /* extension to sp3-c */
	if (code=='L') return E_Sys::LEO; /* extension to sp3-c */
	return E_Sys::NONE;
}

/* read sp3 precise ephemeris file ---------------------------------------------
* read sp3 precise ephemeris/clock files and set them to navigation data
* args   : char   *file       I   sp3-c precise ephemeris file
*                                 (wind-card * is expanded)
*          nav_t  *nav        IO  navigation data
*          int    opt         I   options (1: only observed + 2: only predicted +
*                                 4: not combined)
* notes  : see ref [1]
*          precise ephemeris is appended and combined
*-----------------------------------------------------------------------------*/
void readsp3(
	string&	file,
	nav_t*	nav,
	int		opt)
{
	GTime	time			= {};
	double	bfact[2]		= {};
	char	type=' ';
	char	tsys[4] = "";

	//fprintf(stdout,"\n SP3READ: Expanded  %s to %d files\n",file,n);

	std::ifstream fileStream(file);
	if (!fileStream)
	{
		printf("\nSp3 file open error %s\n", file.c_str());
	}

	//keep track of file number
	static int index = 0;
	index++;

	int hashCount	= 0;
	int cCount		= 0;
	int fCount		= 0;
	int iCount		= 0;
	int plusCount	= 0;
	int pplusCount	= 0;

	string line;
	while (fileStream)
	{
		getline(fileStream, line);

		char* buff = &line[0];

		if (buff[0] == '*')
		{
			//epoch line
			bool error = str2time(buff, 3, 28, time);
			if (error)
			{
				printf("\nInvalid epoch line in sp3 file %s\n", line.c_str());
				return;
			}

			if (!strcmp(tsys, "UTC"))
			{
				time = utc2gpst(time); /* utc->gpst */
			}
			continue;
		}

		if (buff[0] == 'P')
		{
			//position line
			bool pred_p = false;
			bool pred_c = false;

			E_Sys sys = code2sys(buff[1]);
			int prn = (int)str2num(buff, 2, 2);

			if		(sys == +E_Sys::SBS)	prn += 100;
			else if (sys == +E_Sys::QZS)	prn += 192; /* extension to sp3-c */

			SatSys Sat;
			Sat.sys = sys;
			Sat.prn = prn;
			if (!Sat)
				continue;

			Peph peph 	= {};
			peph.time 	= time;
			peph.index	= index;
			peph.Sat	= Sat;
			bool valid	= false;

			if (buff[0] == 'P')
			{
				pred_c = strlen(buff)>=76 && buff[75]=='P';
				pred_p = strlen(buff)>=80 && buff[79]=='P';
			}

			//positions/rates
			for (int j = 0; j < 3; j++)
			{
				/* read option for predicted value */
				if (j < 3 	&& (opt&1)	&&  pred_p)		continue;
				if (j < 3 	&& (opt&2)	&& !pred_p)		continue;

				double val = str2num(buff, 4	+ j * 14,	14);
				double std = str2num(buff,61	+ j * 3,	2);

				if (buff[0]=='P')
				{
					/* position */
					if	( val != 0
						&&fabs(val - 999999.999999) >= 1E-6)
					{
						peph.Pos[j] = val * 1000;
						valid = true;
					}

					double base = bfact[0];
					if	(  base	> 0
						&& std	> 0)
					{
						peph.PosStd[j] = pow(base, std) * 1E-3;
					}
				}
				else if (valid)
				{
// 					/* velocity */
// 					if	( val !=0
// 						&&fabs(val - 999999.999999) >= 1E-6)
// 					{
// 						peph.Vel[j] = val * 0.1;
// 					}
//
// 					double base = bfact[j < 3 ? 0 : 1];
// 					if	(  base	> 0
// 						&& std	> 0)
// 					{
// 						peph.VelStd[j] = pow(base, std) * 1E-7;
// 					}
				}
			}

			//clocks / rates
			for (int j = 3; j < 4; j++)
			{
				/* read option for predicted value */
				if (j == 3	&& (opt&1)	&&  pred_c)		continue;
				if (j == 3	&& (opt&2)	&& !pred_c)		continue;

				double val = str2num(buff, 4	+ j * 14,	14);
				double std = str2num(buff,61	+ j * 3,	3);

				if (buff[0] == 'P')
				{
					/* position */
					if	( val != 0
						&&fabs(val - 999999.999999) >= 1E-6)
					{
						peph.Clk = val * 1E-6;
						valid = 1; /* valid epoch */
					}

					double base = bfact[1];
					if	(  base	> 0
						&& std	> 0)
					{
						peph.ClkStd = pow(base, std) * 1E-12;
					}
				}
				else if (valid)
				{
// 					/* velocity */
// 					if	( val !=0
// 						&&fabs(val - 999999.999999) >= 1E-6)
// 					{
// 						peph.dCk = val * 1E-10;
// 					}
//
// 					double base = bfact[j < 3 ? 0 : 1];
// 					if	(  base	> 0
// 						&& std	> 0)
// 					{
// 						peph.dCkStd = pow(base, std) * 1E-16;
// 					}
				}
			}

			if (valid)
			{
				nav->pephMap[peph.Sat][peph.time] = peph;
			}

			continue;
		}

		if (buff[0] == '#')
		{
			hashCount++;

			if (hashCount == 1)
			{
				//first line is time and type
				type = buff[2];
				int error = str2time(buff, 3, 28, time);
				if (error)
					return;

				continue;
			}
		}

		string twoChars = line.substr(0,2);

// 		if (twoChars == "+ ")
// 		{
//			plusCount++;
// 			//number and list of satellites included in the file - information only, sat ids are included in epoch lines..
// 			if (lineNum == 2)
// 			{
// 				ns = (int)str2num(buff,4,2);
// 			}
// 			for (int j = 0; j < 17 && k < ns; j++)
// 			{
// 				E_Sys sys=code2sys(buff[9+3*j]);
//
// 				int prn = (int)str2num(buff,10+3*j,2);
//
// 				if (k < MAXSAT)
// 					sats[k++] = SatSys(sys, prn);
// 			}
//			continue;
// 		}

// 		if (twoChars == "++")
// 		{
// 			pplusCount++;
// 			continue;
// 		}

		if (twoChars == "%c")
		{
			cCount++;

			if (cCount == 1)
			{
				strncpy(tsys, buff+9,3);
				tsys[3] = '\0';
			}
			continue;
		}

		if (twoChars == "%f")
		{
			fCount++;

			if (fCount == 1)
			{
				bfact[0] = str2num(buff, 3,10);
				bfact[1] = str2num(buff,14,12);
			}
			continue;
		}

		if (line.substr(0,3) == "EOF")
		{
			//all done
			return;
		}
	}
	printf("\nDidnt find eof in sp3 file\n");
}

void orb2sp3(
	nav_t& nav)
{
	for (auto& [Sat,	satOrbit]	: nav.orbpod.satOrbitMap)
	for (auto& [time,	orbitInfo]	: satOrbit.orbitInfoList)
	{
		Peph peph = {};

		peph.index			= 0;
		peph.time			= time;
		peph.Sat			= Sat;

		/* copy itrf coordinates */
		for (int k = 0; k < 3; k++)
		{
			peph.Pos[k] = orbitInfo.xtrf[k];
		}

		nav.pephMap[Sat][time] = peph;
	}
}


#include <chainparams.h>
#include <masternodes/masternodes.h>
#include <validation.h>

#include <test/setup_common.h>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(dip1fork_tests, TestingSetup)

BOOST_AUTO_TEST_CASE(blockreward_dfip1)
{
    const CScript SCRIPT_PUB{CScript(OP_TRUE)};
    const Consensus::Params & consensus = Params().GetConsensus();
    auto height = consensus.AMKHeight;

    CMutableTransaction coinbaseTx{};

    coinbaseTx.vin.resize(1);
    coinbaseTx.vin[0].prevout.SetNull();
    coinbaseTx.vout.resize(1);
    coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB;
    coinbaseTx.vout[0].nValue = GetBlockSubsidy(height, consensus);
    coinbaseTx.vin[0].scriptSig = CScript() << height << OP_0;

    {   // check on pre-AMK height:
        CCustomCSView mnview(*pcustomcsview.get());
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(coinbaseTx), height-1, 0, consensus);
        BOOST_CHECK(res.ok);
    }
    {   // try to generate wrong tokens
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout[0].nTokenId.v = 1;
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-wrong-tokens");
    }
    {   // do not pay foundation reward at all
        CCustomCSView mnview(*pcustomcsview.get());
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(coinbaseTx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-foundation-reward");
    }
    {   // try to pay foundation reward slightly less than expected
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        tx.vout[1].nValue = GetBlockSubsidy(height, consensus) * consensus.foundationShareDFIP1 / COIN -1;
        tx.vout[0].nValue -= tx.vout[1].nValue;

        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-foundation-reward");
    }
    {   // pay proper foundation reward, but not subtract consensus share
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        tx.vout[1].nValue = GetBlockSubsidy(height, consensus) * consensus.foundationShareDFIP1 / COIN;
        tx.vout[0].nValue -= tx.vout[1].nValue;

        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-amount");
    }
    {   // at least, all is ok
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        CAmount const baseSubsidy = GetBlockSubsidy(height, consensus);
        tx.vout[1].nValue = baseSubsidy * consensus.foundationShareDFIP1 / COIN;
        tx.vout[0].nValue -= tx.vout[1].nValue;
        tx.vout[0].nValue -= baseSubsidy * consensus.nonUtxoBlockSubsidies.at(CommunityAccountType::IncentiveFunding) / COIN;
        tx.vout[0].nValue -= baseSubsidy * consensus.nonUtxoBlockSubsidies.at(CommunityAccountType::AnchorReward) / COIN;

        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(res.ok);
    }
}

BOOST_AUTO_TEST_CASE(blockreward_dfip8)
{
    const CScript SCRIPT_PUB{CScript(OP_TRUE)};
    Consensus::Params consensus = Params().GetConsensus();
    consensus.EunosHeight = 10000000;
    auto height = consensus.EunosHeight;
    CAmount blockReward = GetBlockSubsidy(height, consensus);

    CMutableTransaction coinbaseTx{};

    coinbaseTx.vin.resize(1);
    coinbaseTx.vin[0].prevout.SetNull();
    coinbaseTx.vout.resize(1);
    coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB;
    coinbaseTx.vout[0].nValue = GetBlockSubsidy(height, consensus);
    coinbaseTx.vin[0].scriptSig = CScript() << height << OP_0;

    {   // do not pay foundation reward at all
        CCustomCSView mnview(*pcustomcsview.get());
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(coinbaseTx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-foundation-reward");
    }
    {   // try to pay foundation reward slightly less than expected
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[0].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.masternode);
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        tx.vout[1].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.community) - 1;
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-foundation-reward");
    }
    {   // try to pay foundation reward slightly more than expected
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[0].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.masternode);
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        tx.vout[1].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.community) + 1;
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-amount");
    }
    {   // Try and pay staker too much
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[0].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.masternode) + 1;
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        tx.vout[1].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.community);
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(!res.ok && res.dbgMsg == "bad-cb-amount");
    }
    {   // Test everything is okay
        CCustomCSView mnview(*pcustomcsview.get());
        CMutableTransaction tx(coinbaseTx);
        tx.vout.resize(2);
        tx.vout[0].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.masternode);
        tx.vout[1].scriptPubKey = consensus.foundationShareScript;
        tx.vout[1].nValue = CalculateCoinbaseReward(blockReward, consensus.dist.community);
        Res res = ApplyGeneralCoinbaseTx(mnview, CTransaction(tx), height, 0, consensus);
        BOOST_CHECK(res.ok);
    }
}

BOOST_AUTO_TEST_CASE(blockreward_dfip8_reductions)
{
    Consensus::Params consensus = Params().GetConsensus();
    consensus.EunosHeight = 10000000;

    auto GetReductionsHeight = [consensus](const uint32_t reductions)
    {
        return consensus.EunosHeight + (reductions * Params().GetConsensus().emissionReductionPeriod);
    };

    // Test coinbase rewards reduction 0
    {
        auto blockSubsidy = GetBlockSubsidy(GetReductionsHeight(0), consensus);
        BOOST_CHECK_EQUAL(blockSubsidy, 40504000000);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.masternode), 13499983200);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.community), 1988746400);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.anchor), 8100800);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.liquidity), 10308268000);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.swap), 4998193600);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.futures), 4998193600);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.options), 4001795200);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.unallocated), 700719200);
    }

    // Test coinbase rewards reduction 1
    {
        auto blockSubsidy = GetBlockSubsidy(GetReductionsHeight(1), consensus);
        BOOST_CHECK_EQUAL(blockSubsidy, 39832443680);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.masternode), 13276153478);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.community), 1955772984);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.anchor), 7966488);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.liquidity), 10137356916);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.swap), 4915323550);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.futures), 4915323550);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.options), 3935445435);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.unallocated), 689101275);
    }

    // Test coinbase rewards reduction 100
    {
        auto blockSubsidy = GetBlockSubsidy(GetReductionsHeight(100), consensus);
        BOOST_CHECK_EQUAL(blockSubsidy, 7610296073);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.masternode), 2536511681);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.community), 373665537);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.anchor), 1522059);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.liquidity), 1936820350);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.swap), 939110535);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.futures), 939110535);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.options), 751897252);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.unallocated), 131658122);
    }

    // Test coinbase rewards reduction 1000
    {
        auto blockSubsidy = GetBlockSubsidy(GetReductionsHeight(1000), consensus);
        BOOST_CHECK_EQUAL(blockSubsidy, 2250);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.masternode), 749);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.community), 110);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.anchor), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.liquidity), 572);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.swap), 277);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.futures), 277);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.options), 222);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.unallocated), 38);
    }

    // Test coinbase rewards reduction 1251
    {
        auto blockSubsidy = GetBlockSubsidy(GetReductionsHeight(1251), consensus);
        BOOST_CHECK_EQUAL(blockSubsidy, 60);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.masternode), 19);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.community), 2);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.anchor), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.liquidity), 15);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.swap), 7);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.futures), 7);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.options), 5);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.unallocated), 1);
    }

    // Test coinbase rewards reduction 1252
    {
        auto blockSubsidy = GetBlockSubsidy(GetReductionsHeight(1252), consensus);
        BOOST_CHECK_EQUAL(blockSubsidy, 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.masternode), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.community), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.anchor), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.liquidity), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.swap), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.futures), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.options), 0);
        BOOST_CHECK_EQUAL(CalculateCoinbaseReward(blockSubsidy, consensus.dist.unallocated), 0);
    }
}

BOOST_AUTO_TEST_SUITE_END()


/******************************************************************************
 *   Copyright (C) 2006-2021 by the resistivity.net development team          *
 *   Carsten Rücker carsten@resistivity.net                                   *
 *                                                                            *
 *   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.                                           *
 *                                                                            *
 ******************************************************************************/

#include "bertJacobian.h"

#include <calculateMultiThread.h>
#include <elementmatrix.h>
#include <memwatch.h>
#include <meshentities.h>
#include <shape.h>
#include <stopwatch.h>

#include <shape.h>

namespace GIMLI{

#if USE_BOOST_THREAD
    #include <boost/thread.hpp>
    boost::mutex eraseMutex__;
#else
    #include <thread>
    #include <mutex>
    std::mutex eraseMutex__;
#endif

template < class ValueType > class CreateSensitivityColMT : public GIMLI::BaseCalcMT{
public:
  CreateSensitivityColMT(Matrix < ValueType >          & S,
                         const std::vector < Cell * >  & para,
                         const DataContainerERT        & data,
                         const Matrix < ValueType >    & pots,
                         const std::map< long, uint >  & currPatternIdx,
                         const RVector                 & weights,
                         const RVector                 & k,
                         bool calc1,
                         bool verbose)
    : BaseCalcMT(verbose), S_(&S), para_(&para), //cellMapIndex_ (&cellMapIndex),
        data_(&data), pots_(&pots), currPatternIdx_(&currPatternIdx),
        weights_(&weights), k_(&k), calc1_(calc1){
            nData_ = data.size();
            nElecs_ = data.sensorCount();
    }

    virtual ~CreateSensitivityColMT(){}

    virtual void calc(){

        if (calc1_){
            calc1();
        }else {
            calc2();
        }
    }

    virtual void calc2(){
        ElementMatrix < double > S_i;
        ElementMatrix < double > S1_i;

        Cell * cell = NULL;
        int modelIdx = 0;

        const Vector < ValueType > *va;
        const Vector < ValueType > *vb;
        const Vector < ValueType > *vm;
        const Vector < ValueType > *vn;
        Vector < ValueType > dummy((*pots_)[0].size(), ValueType(0));

        const RVector *da = &(*data_)("a");
        const RVector *db = &(*data_)("b");
        const RVector *dm = &(*data_)("m");
        const RVector *dn = &(*data_)("n");

        for (Index cellID = start_; cellID < end_; cellID ++) {

            cell    = (*para_)[cellID];
            modelIdx = cell->marker();

            if (modelIdx < 0) continue;

            S1_i.ux2uy2uz2(*cell);

            for (Index kIdx = 0; kIdx < weights_->size(); kIdx ++){
                S_i.u2(*cell);
                S_i *= (*k_)[kIdx] * (*k_)[kIdx];
                S_i += S1_i;
                int a = 0, b = 0, m = 0, n = 0;
                for (Index dataIdx = 0; dataIdx < nData_; dataIdx ++ ){

                    a = (int)(*da)[dataIdx];
                    b = (int)(*db)[dataIdx];
                    m = (int)(*dm)[dataIdx];
                    n = (int)(*dn)[dataIdx];

                    if (a > -1) va = &(*pots_)[a + nElecs_ * kIdx]; else va = &dummy;
                    if (b > -1) vb = &(*pots_)[b + nElecs_ * kIdx]; else vb = &dummy;
                    if (m > -1) vm = &(*pots_)[m + nElecs_ * kIdx]; else vm = &dummy;
                    if (n > -1) vn = &(*pots_)[n + nElecs_ * kIdx]; else vn = &dummy;

                    (*S_)[dataIdx][modelIdx] +=
                       S_i.mult((*va), (*vb), (*vm), (*vn)) * (*weights_)[kIdx];
                }
            }
        }
    }

    virtual void calc1(){
        // log(Debug, "Thread #" + str(_threadNumber) + ": on CPU " + str(schedGetCPU()) +
        //            " slice " + str(start_) + ":" + str(end_));
        bool haveCurrentPatterns = false;

        if (currPatternIdx_->size() * weights_->size() == pots_->rows()) {
        //** we have current and measurements pattern instead of pol pol potentials;
            haveCurrentPatterns = true;
        }

        ElementMatrix < double > S_i;
        Cell * cell = NULL;
        int modelIdx = 0;
        // Index si, sj;

        const Vector < ValueType > *va;
        const Vector < ValueType > *vb;
        const Vector < ValueType > *vm;
        const Vector < ValueType > *vn;

        const RVector *da = &(*data_)("a");
        const RVector *db = &(*data_)("b");
        const RVector *dm = &(*data_)("m");
        const RVector *dn = &(*data_)("n");

        Vector < ValueType > dummy((*pots_)[0].size(), ValueType(0));

        for (Index cellID = start_; cellID < end_; cellID ++) {

            cell    = (*para_)[cellID];
            modelIdx = cell->marker();

            if (modelIdx < 0) continue;

            if (verbose_) {
                // 	cout << "\r";
                // 	for (int i = 0; i < tNr; i ++) cout << "\t\t\t";
                // 	cout <<	cellID << "/" << para_->size() - 1;
            }

            S_i.ux2uy2uz2(*cell);
            Index cellNodeCount = cell->nodeCount();

//             ValueType tmpPotA = ValueType(0);
//             ValueType tmpPotM = ValueType(0);
            ValueType sum = ValueType(0);

            int a = 0, b = 0, m = 0, n = 0;

            double weightsFactor = 1.0;
            //** if weights_->size() > 1, assuming 2.5D so we need to double the weights
            //** we integrate from 0 to \infty but need we need from -\infty to \infty
            if (weights_->size() > 1) weightsFactor = 2.0;

            for (Index dataIdx = 0; dataIdx < nData_; dataIdx ++ ){

                if (haveCurrentPatterns){
                    a = currPatternIdx_->find(data_->electrodeToCurrentPattern(a, b))->second;
                    m = currPatternIdx_->find(data_->electrodeToCurrentPattern(m, n))->second;
                    b = -1;
                    n = -1;
                } else {
                    a = (int)(*da)[dataIdx];
                    b = (int)(*db)[dataIdx];
                    m = (int)(*dm)[dataIdx];
                    n = (int)(*dn)[dataIdx];
                }

                for (Index kIdx = 0; kIdx < weights_->size(); kIdx ++){
                    sum = ValueType(0);

                    if (a > -1) va = &(*pots_)[a + nElecs_ * kIdx]; else va = &dummy;
                    if (b > -1) vb = &(*pots_)[b + nElecs_ * kIdx]; else vb = &dummy;
                    if (m > -1) vm = &(*pots_)[m + nElecs_ * kIdx]; else vm = &dummy;
                    if (n > -1) vn = &(*pots_)[n + nElecs_ * kIdx]; else vn = &dummy;

                    (*S_)[dataIdx][modelIdx] += S_i.mult((*va), (*vb), (*vm), (*vn)) * (weightsFactor * (*weights_)[kIdx]);
                    continue;
//                     std::cout << cell->id() << std::endl;
                    for (Index i = 0; i < cellNodeCount; i ++){
//                         si = S_i.idx(i);
//                         std::cout << cell->node(i).id() << std::endl;
                        for (Index j = 0; j < cellNodeCount; j ++){
//                             sj = S_i.idx(j);
                            // very most time criticle section here
//                             tmpPotA  = (*va)[si] - (*vb)[si];
//                             tmpPotM  = (*vm)[sj] - (*vn)[sj];
//
//                             sum += S_i.getVal(i, j) * tmpPotA * tmpPotM;

//                             sum += S_i.getVal(i, j) *
//                                     ((*va)[si] - (*vb)[si]) *
//                                     ((*vm)[sj] - (*vn)[sj]);
                            sum += S_i.getVal(i, j) *
                                    ((*va)[S_i.idx(i)] - (*vb)[S_i.idx(i)]) *
                                    ((*vm)[S_i.idx(j)] - (*vn)[S_i.idx(j)]);

                      /*  std::cout << i<<" "<<j<<" "<< S_i.getVal(i, j)<<" "<< (*va)[S_i.idx(i)]<<" "<<
                        (*vb)[S_i.idx(i)]<<" "<< (*vm)[S_i.idx(j)]<<" "<< (*vn)[S_i.idx(j)] << std::endl;
                      */
                        }
                    }
                    if (isInfNaN(sum)){
                        std::cerr << WHERE_AM_I << std::endl;
                    }
// 	  if ((*cellMapIndex_)[cellID] - 2 < 0 ||
// 	       (*cellMapIndex_)[cellID] - 2 > nModel-1){
// 	    std::cerr << WHERE_AM_I << " index out of bounds: [0 -- " << nModel-1 << "]" << cellMapIndex[cellID] - 2 << std::endl;
// 	  }

//	  (*S_)[dataIdx][(*cellMapIndex_)[cellID] - 2] += sum * (data_->k(dataIdx) * 2.0 * (*weights_)[kIdx]);

                    /*! Dangerous!!! mt writing into matrix*/
	       //(*S_)[dataIdx][(*cellMapIndex_)[cellID]] += sum * (2.0 * (*weights_)[kIdx]);
                    {
//                   #ifdef HAVE_LIBBOOST_THREAD
//                   boost::mutex::scoped_lock lock(eraseMutex__); // slows down alot
//                   #endif

                        (*S_)[dataIdx][modelIdx] += sum * (weightsFactor * (*weights_)[kIdx]);
//                         std::cout << "b: " << dataIdx<<" "<<modelIdx<<" "<<(*S_)[dataIdx][modelIdx]<< " "
//                         << sum * (weightsFactor * (*weights_)[kIdx]) << std::endl;
                    }
//                     exit(1);
                } // for each k
//                      exit(1);
            } // for each data
        } // for each cellID
    }

protected:
    Matrix < ValueType >            * S_;
    const std::vector < Cell * >    * para_;
    const DataContainerERT          * data_;
    const Matrix < ValueType >      * pots_;
    const std::map< long, uint >    * currPatternIdx_;
    const RVector                   * weights_;
    const RVector                   * k_;
    uint                            nData_;
    uint                            nElecs_;
    bool                            calc1_;

};

bool lessCellMarker(const Cell * c1, const Cell * c2) { return c1->marker() < c2->marker(); }

template < class ValueType >
void createSensitivityCol_(Matrix < ValueType > & S,
                          const Mesh & mesh,
                          const DataContainerERT & data,
                          const Matrix < ValueType > & pots,
                          const RVector & weights,
                          const RVector & k,
                          std::vector < std::pair < Index, Index > > & matrixClusterIds,
                          uint nThreads, bool verbose){

MEMINFO

    Index nData  = data.size();
    Index nModel = max(mesh.cellMarkers()) + 1;
    Index maxRows = weights.size() * data.sensorCount();

    if (pots.rows() >= maxRows){
//         if (pots[0].size() < mesh.nodeCount()){
//             std::stringstream str; str << WHERE_AM_I << " potential matrix colsize to small. "
//                                        << pots[0].size()  << "< " << mesh.nodeCount() << std::endl;
//         }
    } else {
        std::stringstream str1; str1 << WHERE_AM_I << " potential matrix rowsize to small."
                                   << pots.rows() << " < " << maxRows << std::endl;
        throwLengthError(str1.str());
    }

    Stopwatch swatch(true);
    std::map< long, uint > currPatternIdx;
    //std::cout << "CreateSensitivityColMT " << nThreads << std::endl;

    std::vector< Cell * > cells(mesh.findCellByMarker(0, -1));
    std::sort(cells.begin(), cells.end(), lessCellMarker);

    double maxMemSize = max(0.0, getEnvironment("SENSMATMAXMEM", 0.0, verbose));
    double maxSizeNeeded = mByte((double)nData * nModel * sizeof(double));

    if (maxMemSize > 0 && verbose){
        std::cout << "Size of S: " << maxSizeNeeded << " MB" << std::endl;
    }

    //** avoid MT problems
    for (std::vector< Cell * >::iterator it = cells.begin();
         it != cells.end(); it ++){
        (*it)->pShape()->invJacobian();
    }

//     ShapeFunctionCache::instance().shapeFunctions(cells[0]->shape());
//     ShapeFunctionCache::instance().deriveShapeFunctions(cells[0]->shape(), 0);
//     ShapeFunctionCache::instance().deriveShapeFunctions(cells[0]->shape(), 1);
//     ShapeFunctionCache::instance().deriveShapeFunctions(cells[0]->shape(), 2);
//     ShapeFunctionCache::instance().shapeFunctions(*cells[0]);
//     ShapeFunctionCache::instance().deriveShapeFunctions(*cells[0], 0);
//     ShapeFunctionCache::instance().deriveShapeFunctions(*cells[0], 1);
//     ShapeFunctionCache::instance().deriveShapeFunctions(*cells[0], 2);
//     //cells[0]->createShapefunctionts();

    if (maxMemSize > 0 && maxMemSize < maxSizeNeeded){

        uint modelCluster = std::floor((double)nModel / (maxSizeNeeded / maxMemSize));

        if (modelCluster < 1) {
            throwError(WHERE_AM_I + " sorry, size of single sensitivity-row exceeds memory limitations.");
        }

        std::cout << "Size of S cluster: " << mByte((double)nData * modelCluster * sizeof(ValueType)) << " MB" << std::endl;
        std::cout << "Using model cluster " << nModel << " x " << modelCluster << std::endl;

        S.resize(nData, modelCluster);

        matrixClusterIds.clear();
        matrixClusterIds.push_back(std::pair < Index, Index >(nData, nModel));

        bool calc1 = getEnvironment("SENSMAT1", false, true);
        for (uint i = 0; i < nModel; i += modelCluster ){
MEMINFO
            Index start = i;
            Index end   = min(start + modelCluster, nModel);
            std::cout << " " << start << " " << end<< std::endl;

            S.resize(nData, end - start);

            std::vector< Cell * > cellsCluster(mesh.findCellByMarker(start, end));
            std::sort(cellsCluster.begin(), cellsCluster.end(), lessCellMarker);

MEMINFO
            // subtract marker start index
            for (std::vector< Cell * >::iterator it = cellsCluster.begin(); it != cellsCluster.end(); it ++){
                (*it)->setMarker((*it)->marker() - start);
            }

            S *= ValueType(0);
MEMINFO

            distributeCalc(CreateSensitivityColMT< ValueType >(S, cellsCluster,
                                                               data, pots,
                                                               currPatternIdx,
                                                               weights, k,
                                                               calc1,
                                                               verbose),
                           cellsCluster.size(), nThreads, verbose);

MEMINFO

            //** fight against the Lorenz butterfly
            //** 1e-8 is to coarse, need adaptive tolerance
            //S.round(1e-8);
MEMINFO

            S.save("sensPart_" + str(start) + "-" + str(end));

            matrixClusterIds.push_back(std::pair < Index, Index >(start, end));

            // add marker start index
            for (std::vector< Cell * >::iterator it = cellsCluster.begin(); it != cellsCluster.end(); it ++){
                (*it)->setMarker((*it)->marker() + start);
            }
MEMINFO
        }

        S.clear();
    } else {

        // __MS(nData << " "<< S.rows() << " "<<  nModel << " "<<  S.cols())
        if (S.rows() != nData || S.cols() != nModel) S.resize(nData, nModel);
        S *= ValueType(0);
MEMINFO

        if (verbose){
            std::cout << "S(" << numberOfCPU() << "/" << nThreads; //**check!!!
            #if USE_BOOST_THREAD
            std::cout << "-boost::mt";
            #else
            std::cout << "-std::mt";
            #endif
            std::cout << "): " << swatch.duration() << ":";
//swatch.stop(verbose);
        }
        bool calc1 = getEnvironment("SENSMAT1", false, true);
        distributeCalc(CreateSensitivityColMT< ValueType >(S, cells, data,
                                                           pots, currPatternIdx,
                                                           weights, k, calc1, verbose),
                        cells.size(), nThreads, verbose);
         if (verbose){
             swatch.stop(verbose);
         }
MEMINFO
        //** fight against the Lorenz butterfly
        //** 1e-8 is to coarse, need adaptive tolerance
        //S.round(1e-8);
    }
}

void createSensitivityCol(RMatrix & S,
                          const Mesh & mesh,
                          const DataContainerERT & data,
                          const RMatrix & pots,
                          const RVector & weights,
                          const RVector & k,
                          std::vector < std::pair < Index, Index > > & matrixClusterIds,
                          uint nThreads, bool verbose){
    createSensitivityCol_(S, mesh, data, pots, weights, k, matrixClusterIds, nThreads, verbose);
}

void createSensitivityCol(CMatrix & S,
                          const Mesh & mesh,
                          const DataContainerERT & data,
                          const CMatrix & pots,
                          const RVector & weights,
                          const RVector & k,
                          std::vector < std::pair < Index, Index > > & matrixClusterIds,
                          uint nThreads, bool verbose){
    createSensitivityCol_(S, mesh, data, pots, weights, k, matrixClusterIds, nThreads, verbose);
}

void sensitivityDCFEMSingle(const std::vector < Cell * > & para, const RVector & p1, const RVector & p2,
		       RVector & sens, bool verbose){
    uint nCells = para.size();
    if (sens.size() != nCells) sens.resize(nCells);

    ElementMatrix < double > S_i;
    double sum = 0.0, a_jk = 0.0, tmppot = 0.0;
    //  cout << nCells << std::endl;

    for (uint i = 0; i < nCells; i ++){
    //cout << "Nr. " << i << std::endl;
        S_i.ux2uy2uz2(*para[i]);

        sum = 0.0;
        for (int j = 0, jmax = para[i]->nodeCount(); j < jmax; j ++){
            for (int k = 0, kmax = para[i]->nodeCount(); k < kmax; k ++){
	       a_jk = S_i.getVal(j, k);
	       tmppot = p1[S_i.idx(j)] * p2[S_i.idx(k)];
	       sum += a_jk * tmppot;
	//	cout << "\tS_mn: " << a_jk << "\tp1*p2: " << tmppot << "\tp*S_mn: " << a_jk * tmppot << "\tsum: " << sum << std::endl;
            }
        }
        sens[i] = sum;
    }
}

RVector prepExportSensitivityData(const Mesh & mesh, const RVector & data, double logdrop){
    Index nModel = unique(sort(mesh.cellMarkers())).size();

    ASSERT_EQUAL(nModel, data.size())

    //data have always the right length since it comes from S directly
    RVector modelSizes(nModel, 0.0);
    for (Index i = 0; i < mesh.cellCount(); i ++ ){
        modelSizes[mesh.cell(i).marker()] += mesh.cell(i).size();
    }

    return logTransDropTol(data/modelSizes, logdrop, true)(mesh.cellMarkers());

    // //RVector tmp(data/mesh.cellSizes());
    // if ((uint)data.size() != (uint)mesh.cellCount()){

    //     throwLengthError(WHERE_AM_I + " Datasize missmatch: " + str(mesh.cellCount())+
    //                         " " + str(data.size()));
    // } else {
    //     //for (uint i = 0; i < tmp.size(); i ++) tmp[i] = tmp[i] / mesh.cell(i).shape().domainSize();
    // }
    // RVector tmp(data/mesh.cellSizes());

    // RVector s(sign(tmp));

    // double tmpMax = max(abs(tmp));
    // tmp /= tmpMax;

    // for (uint i = 0; i < tmp.size(); i ++) {
    //     tmp[i] = std::fabs(tmp[i] / logdrop);
    //     if (tmp[i] < 1.0) tmp[i] = 1.0;
    // }

    // tmp = log10(tmp);
    // tmp /= max(tmp) * s;
    // return tmp;
}

void exportSensitivityVTK(const std::string & fileName,
                          const Mesh & mesh, const RVector & data,
                          double logdrop){
    std::map< std::string, RVector > res;
    res.insert(std::make_pair("Sensitivity" ,
                              prepExportSensitivityData(mesh, data, logdrop)));
    mesh.exportVTK(fileName, res);
}

// void exportSensMatrixDC(const std::string & filename, const Mesh & mesh, const RMatrix & S) {
//     exportSensMatrixDC(filename, mesh, S
// }

void exportSensMatrixDC(const std::string & filename, const Mesh & mesh,
                        const RMatrix & S, const IVector & idx,
                        double logdrop) {
    std::map< std::string, RVector > res;

    for (std::map < std::string, RVector >::const_iterator
            it = mesh.dataMap().begin();
            it != mesh.dataMap().end(); it ++){
        res.insert(std::make_pair(it->first, it->second));
    }

    std::string add;
//     RVector tmp(mesh.cellCount());

    for (size_t i = 0; i < S.rows(); i ++) {
        if (i < 100000) add = "0";
        if (i < 10000) add = "00";
        if (i < 1000) add = "000";
        if (i < 100) add = "0000";
        if (i < 10) add = "00000";

//         for (uint j = 0; j < tmp.size(); j ++) tmp[j] = S[i][mesh.cell(j).marker()];

//#res.insert(std::make_pair("sens-" + add + str(i), log10(RVector(abs(tmp)))));

            res.insert(std::make_pair("sens-" + add + str(i),
                        prepExportSensitivityData(mesh, S[i], logdrop)));

   }
   mesh.exportVTK(filename, res);
}

RVector coverageDC(const RMatrix & sensMatrix) {
    RVector cov;
    if (sensMatrix.rows() > 0) {
        cov.resize(sensMatrix.cols(), 0.0);

        for (size_t i = 0; i < sensMatrix.rows(); i ++) {
            cov += abs(sensMatrix[i]);
        }
    } else {
        std::cout << "Sensmatrix invalid" << std::endl;
    }
    return cov;
}

RVector coverageDCtrans(const MatrixBase & S, const RVector & dd, const RVector & mm) {
    RVector cov;

    if (S.rows() > 0) {
        cov.resize(S.cols(), 0.0);
    } else {
        std::cout << "Sensmatrix invalid" << std::endl;
    }

    if (S.rtti() == GIMLI_MATRIX_RTTI){
        const RMatrix *Sl = dynamic_cast < const RMatrix * >(&S);

        for (size_t i = 0; i < S.rows(); i ++) {
            cov += abs((*Sl)[i] * dd[i]);
        }
    } else if (S.rtti() == GIMLI_SPARSE_MAP_MATRIX_RTTI){

        const RSparseMapMatrix * Sl = dynamic_cast< const RSparseMapMatrix * >(&S);

        for (RSparseMapMatrix::const_iterator it = Sl->begin(); it != Sl->end(); it ++){
            Index row = (*it).first.first;
            Index col = (*it).first.second;
            cov[col] += (*it).second * dd[row];
        }
    } else {
        CERR_TO_IMPL
    }

    return cov / abs(mm);
}

RVector createCoverage(const MatrixBase & S, const Mesh & mesh){
    return createCoverage(S, mesh, RVector(S.rows(), 1.0), RVector(S.cols(), 1.0));
}

RVector createCoverage(const MatrixBase & S, const Mesh & mesh,
                       const RVector & response, const RVector & model){

    RVector covModel(coverageDCtrans(S, 1.0 / response, 1.0 / model));
	RVector covMesh(covModel(mesh.cellMarkers()));
    if (mesh.cellCount() == model.size()) {
        covMesh /= mesh.cellSizes();
    } else {
        RVector modelCellSizes(covMesh.size(), 0.0);
        for (Index i = 0; i < mesh.cellCount(); i ++){
            Cell *c = &mesh.cell(i);
            modelCellSizes[c->marker()] += c->shape().domainSize();
        }
        if (min(modelCellSizes) > TOLERANCE){
            covMesh /= modelCellSizes;
        } else {
            log(Error, "Coverage fails:" + str(mesh.cellCount()) + " " + str(model.size()));
        }
    }

    return covMesh;
}
} // namespace GIMLI


#include "LineSymbolizer.h"
#include "ParserUtils.h"
#include "vt/BitmapCanvas.h"

#include <cmath>
#include <algorithm>

#include <boost/algorithm/string.hpp>

namespace carto { namespace mvt {
    LineSymbolizer::FeatureProcessor LineSymbolizer::createFeatureProcessor(const ExpressionContext& exprContext, const SymbolizerContext& symbolizerContext) const {
        vt::FloatFunction strokeWidthFunc = _strokeWidth.getFunction(exprContext);
        vt::FloatFunction strokeOpacityFunc = _strokeOpacity.getFunction(exprContext);
        vt::ColorFunction strokeColorFunc = _stroke.getFunction(exprContext);
        if (strokeWidthFunc == vt::FloatFunction(0) || strokeOpacityFunc == vt::FloatFunction(0) || strokeColorFunc == vt::ColorFunction(vt::Color())) {
            return FeatureProcessor();
        }

        vt::CompOp compOp = _compOp.getValue(exprContext);
        vt::LineJoinMode strokeLinejoin = _strokeLinejoin.getValue(exprContext);
        vt::LineCapMode strokeLinecap = _strokeLinecap.getValue(exprContext);
        vt::ColorFunction strokeFunc = _strokeFuncBuilder.createColorOpacityFunction(strokeColorFunc, strokeOpacityFunc);
        std::optional<vt::Transform> geometryTransform = _geometryTransform.getValue(exprContext);

        std::shared_ptr<const vt::BitmapPattern> strokePattern;
        std::string strokeDashArray = _strokeDashArray.getValue(exprContext);
        if (!strokeDashArray.empty()) {
            int height = 1;
            if (strokeLinecap != vt::LineCapMode::NONE) {
                height = _strokeWidth.getStaticValue(exprContext);
            }
            std::string file = "__line_dasharray_" + std::to_string(height) + "_" + std::to_string(static_cast<int>(strokeLinecap)) + "_" + strokeDashArray;
            strokePattern = symbolizerContext.getBitmapManager()->getBitmapPattern(file);
            if (!strokePattern) {
                std::vector<std::string> dashList;
                boost::split(dashList, strokeDashArray, boost::is_any_of(","));
                std::vector<float> strokeDashArray;
                for (const std::string& dash : dashList) {
                    try {
                        strokeDashArray.push_back(std::stof(boost::trim_copy(dash)));
                    }
                    catch (const boost::bad_lexical_cast& ex) {
                        _logger->write(Logger::Severity::ERROR, "Illegal dash value: " + dash + ", ex: " +  ex.what() );
                    }
                }
                strokePattern = createDashBitmapPattern(strokeDashArray, height, strokeLinecap);
                symbolizerContext.getBitmapManager()->storeBitmapPattern(file, strokePattern);
            }
        }

        vt::LineStyle style(compOp, strokeLinejoin, strokeLinecap, strokeFunc, strokeWidthFunc, strokePattern, geometryTransform);

        std::shared_ptr<vt::StrokeMap> strokeMap = symbolizerContext.getStrokeMap();

        return [style, strokeMap, this](const FeatureCollection& featureCollection, vt::TileLayerBuilder& layerBuilder) {
            bool suppressWarning = false;
            if (auto lineProcessor = layerBuilder.createLineProcessor(style, strokeMap)) {
                for (std::size_t featureIndex = 0; featureIndex < featureCollection.size(); featureIndex++) {
                    if (auto lineGeometry = std::dynamic_pointer_cast<const LineGeometry>(featureCollection.getGeometry(featureIndex))) {
                        for (const auto& vertices : lineGeometry->getVerticesList()) {
                            lineProcessor(featureCollection.getLocalId(featureIndex), vertices);
                        }
                    }
                    else if (auto polygonGeometry = std::dynamic_pointer_cast<const PolygonGeometry>(featureCollection.getGeometry(featureIndex))) {
                        for (const auto& verticesList : polygonGeometry->getPolygonList()) {
                            for (const auto& vertices : verticesList) {
                                lineProcessor(featureCollection.getLocalId(featureIndex), vertices);
                            }
                        }
                    }
                    else if (!suppressWarning) {
                        _logger->write(Logger::Severity::WARNING, "Unsupported geometry for LineSymbolizer");
                        suppressWarning = true;
                    }
                }
            }
        };
    }

    std::shared_ptr<vt::BitmapPattern> LineSymbolizer::createDashBitmapPattern(const std::vector<float>& strokeDashArray, int height, vt::LineCapMode lineCap) {
        float size = std::accumulate(strokeDashArray.begin(), strokeDashArray.end(), 0.0f);
        if (size <= 0 || height <= 0) {
            return std::shared_ptr<vt::BitmapPattern>();
        }
        float superSamplingFactor = DASH_SUPERSAMPLING_FACTOR / std::accumulate(strokeDashArray.begin(), strokeDashArray.end(), 1.0f, [](float a, float b) { return b > 0 ? std::min(a, b) : a; });

        int pow2Size = 1;
        while (pow2Size < size * superSamplingFactor && pow2Size < 2048) {
            pow2Size *= 2;
        }
        float sizeScale = pow2Size / size;

        int pow2Height = 1;
        while (pow2Height < height * superSamplingFactor && pow2Height < 2048) {
            pow2Height *= 2;
        }
        float heightScale = pow2Height / height;

        vt::BitmapCanvas canvas(pow2Size, pow2Height, false);
        float radius = pow2Height * 0.5f * sizeScale / heightScale;
        float x0 = strokeDashArray.back() * 0.5f * sizeScale;
        float x1 = x0;
        float y0 = 0;
        float y1 = pow2Height;
        for (std::size_t n = 0; n < strokeDashArray.size(); n++) {
            x1 += strokeDashArray[n] * sizeScale;
            if (n % 2 == 0) {
                switch (lineCap) {
                case vt::LineCapMode::ROUND:
                    canvas.drawEllipse(cglib::vec2<float>(x0, (y0 + y1) * 0.5f), radius, pow2Height * 0.5f);
                    canvas.drawEllipse(cglib::vec2<float>(x1, (y0 + y1) * 0.5f), radius, pow2Height * 0.5f);
                    canvas.drawRectangle(cglib::vec2<float>(x0, y0), cglib::vec2<float>(x1, y1));
                    break;
                case vt::LineCapMode::SQUARE:
                    canvas.drawRectangle(cglib::vec2<float>(x0 - radius, y0), cglib::vec2<float>(x1 + radius, y1));
                    break;
                default:
                    canvas.drawRectangle(cglib::vec2<float>(x0, y0), cglib::vec2<float>(x1, y1));
                    break;
                }
            }
            x0 = x1;
        }

        return std::make_shared<vt::BitmapPattern>(DASH_PATTERN_SCALE / sizeScale, 1.0f / heightScale, canvas.buildBitmapImage()->bitmap);
    }
} }


#include <boost/sml.hpp>
#include <cassert>

namespace sml = boost::sml;

namespace {
// events
struct release {};
struct ack {};
struct fin {};
struct timeout {};

// guards
const auto is_ack_valid = [](const ack&) { return true; };
const auto is_fin_valid = [](const fin&) { return true; };

// actions
const auto send_fin = [] {};
const auto send_ack = [] {};

#if !defined(_MSC_VER)
struct hello_world {
  auto operator()() const {
    using namespace sml;
    // clang-format off
    return make_transition_table(
      *"established"_s + event<release> / send_fin = "fin wait 1"_s,
       "fin wait 1"_s + event<ack> [ is_ack_valid ] = "fin wait 2"_s,
       "fin wait 2"_s + event<fin> [ is_fin_valid ] / send_ack = "timed wait"_s,
       "timed wait"_s + event<timeout> / send_ack = X
    );
    // clang-format on
  }
};
}

int main() {
  using namespace sml;

  sm<hello_world> sm;
  // static_assert(1 == sizeof(sm), "sizeof(sm) != 1b");
  assert(sm.is("established"_s));

  sm.process_event(release{});
  assert(sm.is("fin wait 1"_s));

  sm.process_event(ack{});
  assert(sm.is("fin wait 2"_s));

  sm.process_event(fin{});
  assert(sm.is("timed wait"_s));

  sm.process_event(timeout{});
  assert(sm.is(X));  // released
}
#else
class established;
class fin_wait_1;
class fin_wait_2;
class timed_wait;

struct hello_world {
  auto operator()() const {
    using namespace sml;
    // clang-format off
    return make_transition_table(
      *state<established> + event<release> / send_fin = state<fin_wait_1>,
       state<fin_wait_1> + event<ack> [ is_ack_valid ] = state<fin_wait_2>,
       state<fin_wait_2> + event<fin> [ is_fin_valid ] / send_ack = state<timed_wait>,
       state<timed_wait> + event<timeout> / send_ack = X
    );
    // clang-format on
  }
};
}

int main() {
  using namespace sml;

  sm<hello_world> sm;
  assert(sm.is(state<established>));

  sm.process_event(release{});
  assert(sm.is(state<fin_wait_1>));

  sm.process_event(ack{});
  assert(sm.is(state<fin_wait_2>));

  sm.process_event(fin{});
  assert(sm.is(state<timed_wait>));

  sm.process_event(timeout{});
  assert(sm.is(X));  // released
}
#endif


//==================================================================================================
/*!

  Copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#include <boost/simd/constant/eight.hpp>
#include <boost/simd/as.hpp>
#include <scalar_test.hpp>

STF_CASE_TPL( "Check eight behavior for integral types"
            , (std::uint8_t)(std::uint16_t)(std::uint32_t)(std::uint64_t)
              (std::int8_t)(std::int16_t)(std::int32_t)(std::int64_t)
            )
{
  using boost::simd::as;
  using boost::simd::detail::eight;
  using boost::simd::Eight;

  STF_TYPE_IS(decltype(Eight<T>()), T);
  STF_EQUAL(Eight<T>(), T(8));
  STF_EQUAL(eight( as(T{}) ),T(8));
}

STF_CASE_TPL( "Check eight behavior for floating types"
            , (double)(float)
            )
{
  using boost::simd::as;
  using boost::simd::detail::eight;
  using boost::simd::Eight;

  STF_TYPE_IS(decltype(Eight<T>()), T);
  STF_IEEE_EQUAL(Eight<T>(), T(8));
  STF_IEEE_EQUAL(eight( as(T{}) ), T(8));
}


//   Copyright 2019 <Huawei Technologies Co., Ltd>
//
//   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.

#include <boost/format.hpp>
#include <boost/mpi.hpp>
#include <boost/program_options.hpp>
#include <chrono>
#include <complex>
#include <cstdint>
#include <iostream>

#include "simulator-mpi/SimulatorMPI.hpp"
#include "simulator-mpi/SwapperMT.hpp"
#include "simulator-mpi/funcs.hpp"
//#include <omp.h>

#include <glog/logging.h>

#include "simulator-mpi/swapping.hpp"

namespace po = boost::program_options;

template <class T>
std::vector<T> allocateData(int rank, uint64_t M)
{
     std::vector<T> res(1ul << M);
     for (size_t i = 0; i < res.size(); ++i)
          res[i] = std::complex<double>(rank, i);

     return res;
}

SimulatorMPI::StateVector allocateData1(int rank, uint64_t M)
{
     SimulatorMPI::StateVector res(1ul << M);
     for (size_t i = 0; i < res.size(); ++i)
          res[i] = rank * (1ul << M) + i;

     return res;
}

typedef typename SwapperMT::value_type value_type;

int main(int argc, const char** argv)
{
     google::InitGoogleLogging("qswap_mpi");

     uint64_t L = 0;
     uint64_t M = 0;
     uint64_t nthreads = 1;
     uint64_t rank = 0;
     std::vector<uint64_t> swap_pairs;
     std::vector<uint64_t> perm_pairs;

     po::options_description desc("Options");
     desc.add_options()("help", "produce help message")(
         "L", po::value<uint64_t>(&L), "total number of qubits")(
         "M", po::value<uint64_t>(&M), "number of local qubits")(
         "nthreads", po::value<uint64_t>(&nthreads), "number of OMP threads")(
         "rank", po::value<uint64_t>(&rank), "rank")(
         "swap", po::value<std::vector<uint64_t>>(&swap_pairs)->multitoken(),
         "pair to swap")(
         "perm", po::value<std::vector<uint64_t>>(&perm_pairs)->multitoken(),
         "initial permutation by pairs");

     po::variables_map vm;
     po::store(po::parse_command_line(argc, argv, desc), vm);
     po::notify(vm);

     if (vm.count("help")) {
          std::cout << desc << "\n";
          return 0;
     }

     //	omp_set_num_threads(nthreads);

     mpi::environment env;
     mpi::communicator world;

     rank = world.rank();

     LOG(INFO) << "I am process " << rank << " of " << world.size() << "."
               << std::endl;

     LOG(INFO) << boost::format("L: %d, M: %d") % L % M << std::endl;

     LOG(INFO) << boost::format("Current permutation: %s")
                      % printPairs(perm_pairs);
     LOG(INFO) << boost::format("Do swaps: %s") % printPairs(swap_pairs);

     LOG(INFO) << boost::format("R: %d, Allocating %d local qubits...") % rank
                      % M
               << std::endl;
     auto t0 = std::chrono::high_resolution_clock::now();
     auto state_vector = allocateData1(rank, M);  // SimulatorMPI::StateVector
     // 	auto state_vector = allocateData<uint64_t>(rank, M);
     auto t1 = std::chrono::high_resolution_clock::now();
     std::chrono::duration<double, std::milli> dt = t1 - t0;
     LOG(INFO) << boost::format("R: %d,  ...done, %.3f ms") % rank % dt.count()
               << std::endl;

     value_type res = 0;

     //     auto perm = permuteQubits(naturalOrdering(L), perm_pairs);
     // 	std::vector<uint64_t> swapBits = q2bits<uint64_t>(M, swap_pairs,
     // inversePermutation(perm));
     //     LOG(INFO) << boost::format("Swap bits: %s") % printPairs(swapBits);
     //
     //     uint64_t color = getColor<uint64_t>(rank, swapBits);
     //     auto comm = world.split(color);
     //     LOG(INFO) << boost::format("R: %d, color: %d, comm size: %d") % rank
     //     % color % comm.size()  << std::endl;
     //
     // //     auto s = Swapper<value_type>(state_vector, comm, rank, color, L,
     // M, swapBits);
     // //     res = s.doSwap();

     //     SwapperMT s(world, state_vector, rank, M, comm.size());
     //     s.doSwap(world.rank(), comm, color, swapBits);
     //     LOG(INFO) << "local satte vector: " << std::endl <<
     //     print(state_vector);

     // 	auto t2 = std::chrono::high_resolution_clock::now();
     // 	std::chrono::duration<double, std::milli> dt2 = t2-t1;
     //     LOG(INFO) << boost::format("swap time: %.3f ms") % dt2.count();
     //     printStateVector(std::cerr, "Local state vector:", L, state_vector);

     //     size_t free_idx_start = 0;
     //     size_t maxSend = 3;
     //     size_t n = maxSend + swapBits.size()/2; // n must be <
     //     state_vector.size() SwapArrays<uint64_t> arrs( (1ul << n) );
     //     free_idx_start =
     //     swapping::Swapping<5>::calcSwap(state_vector.begin(),
     //     free_idx_start, arrs, swapBits);

     //     printStateVector(std::cerr, "svalues: ", L, arrs.svalues);

     world.barrier();

     //     std::cout << "State vector:" << std::endl;
     //     printStateVector(state_vector);

     LOG(INFO) << boost::format("R: %d, res: %d, finish!") % rank % res
               << std::endl;
     LOG(INFO) << std::endl
               << "================================" << std::endl
               << std::endl;

     return 0;
}