//#pragma once

#include <boost/scoped_ptr.hpp>
#include "ros/ros.h"
#include "std_msgs/Int8.h"
#include "std_msgs/Float64.h"
#include "geometry_msgs/Pose.h"
#include "geometry_msgs/Twist.h"
#include "algoreg/lineFollow.h"
#include "tf/transform_datatypes.h"
#include "nav_msgs/Path.h"
#include <geodesy/utility.h>
//#include <iostream>
//#include <math.h>

enum State{
    manual = 0,
    linefollowing = 1,
    stationKeeping = 2
};

class Regulation
{
public:
    Regulation(){
        // Subscribers
        sub_pose = node.subscribe("pose_est", 1, &Regulation::updatePose, this);
        sub_twist = node.subscribe("twist_est", 1, &Regulation::updateTwist, this);
        sub_line = node.subscribe("line", 1, &Regulation::updateFollowedLine, this);

        sub_state = node.subscribe("cmd_state", 1, &Regulation::updateCmdState, this);
        sub_speed = node.subscribe("cmd_max_speed", 1, &Regulation::updateMaxSpeed, this);

        // Publishers
        cmdVel_pub = node.advertise<geometry_msgs::Twist>("cmd_vel", 1);

        // Internal variables
        cmd_state = manual;
        cmd_max_speed = 1.0; // m/s
        cmd_vel.angular.x = 0;
        cmd_vel.angular.y = 0;
        cmd_vel.angular.z = 0;
        cmd_vel.linear.x = 0;
        cmd_vel.linear.y = 0;
        cmd_vel.linear.z = 0;
        pose.position.z = 0;
        pose.position.x = 0;
        pose.position.y = 0;
        line.poses = {geometry_msgs::PoseStamped(), geometry_msgs::PoseStamped()};
        const tf::Quaternion q = tf::createQuaternionFromYaw(0);
        pose.orientation.z = q.z();
        pose.orientation.w = q.w();
        pose.orientation.x = q.x();
        pose.orientation.y = q.y();

        // Algo
        algoHead.reset(new LineFollow());
    }

    void updatePose(const geometry_msgs::Pose::ConstPtr& msg){
        pose.orientation = msg->orientation;
        pose.position = msg->position;
        ROS_DEBUG("I received an estimated position: ([%f], [%f], [%f])", pose.position.x, pose.position.y, pose.position.z);
    }

    void updateTwist(const geometry_msgs::Twist::ConstPtr& msg){
        twist.angular = msg->angular;
        twist.linear = msg->linear;
    }

    void updateFollowedLine(const nav_msgs::Path::ConstPtr& msg){
        line.poses[0] = msg->poses[0];
        line.poses[1] = msg->poses[1];
    }

    void updateCmdState(const std_msgs::Int8::ConstPtr& msg){
        cmd_state = msg->data;
    }

    void updateMaxSpeed(const std_msgs::Float64::ConstPtr& msg){
        cmd_max_speed = msg->data;
    }

    double computeSpeedFromHeading(double distance, double errorHeading){
        /**
         * Ralentit si on arrive proche de la cible et si le cap par rapport à l'angle voulu est mauvais
         */
        const double d_max = 15; // m
        const double err_angle_max = 1.57; // rad
        errorHeading = fmin(fabs(errorHeading), err_angle_max);
        distance = fmin(distance, d_max);
        return distance/d_max * (err_angle_max - errorHeading) * cmd_max_speed / err_angle_max;
    }

    void computelineFollow(){

        // Gestion des donnees
        const std::vector<double> wp_a = {
                line.poses[0].pose.position.x,
                line.poses[0].pose.position.y
        };
        const std::vector<double> wp_b = {
                line.poses[1].pose.position.x,
                line.poses[1].pose.position.y
        };
        const double headLine = atan2(wp_b[1]-wp_a[1],wp_b[0]-wp_a[0]); // ENU convention, angle from east

        const double head = tf::getYaw(pose.orientation);
        const std::vector<double> state_vec = {
                pose.position.x,
                pose.position.y,
                head
        };

        // Desired heading algo
        const double wantedHead = algoHead->run(wp_a, wp_b, state_vec); // par rapport au repère global

        // Desired speed from heading
        const double wantedSpeed = computeSpeedFromHeading(distance(state_vec[0], state_vec[1], wp_b[0], wp_b[1]), angle_rad(head,- wantedHead));

        // Commande
        cmd_vel.angular.z = angle_rad(wantedHead,- head); // rad
        cmd_vel.linear.x = wantedSpeed; // m/s

        printf("ang aim = [%f]\n",cmd_vel.angular.z);
        printf("lin vel = [%f]\n",cmd_vel.linear.x);
    }

    void stationKeep(){

    }

    void updateCommand(){
        printf(" --== Updating command ==-- \n");

        if(cmd_state==linefollowing){
            computelineFollow();
        } else if(cmd_state==stationKeeping){
            stationKeep();
        }

    }

    void spin(){

        ros::Rate loop(10);
        while (ros::ok()){

            // call all waiting callbacks
            ros::spinOnce();

            if(cmd_state!=manual){

                updateCommand();

                // publish the command
                cmdVel_pub.publish(cmd_vel);
            }

            loop.sleep();

        }
    }

private:
    // Node
    ros::NodeHandle node;

    // Subscriber
    ros::Subscriber sub_pose;
    ros::Subscriber sub_twist;
    ros::Subscriber sub_line;
    ros::Subscriber sub_state;
    ros::Subscriber sub_speed;

    // Publishers
    ros::Publisher cmdVel_pub;

    // Internal variables
    int cmd_state;
    double cmd_max_speed;
    geometry_msgs::Twist twist;
    geometry_msgs::Pose pose;
    geometry_msgs::Twist cmd_vel;
    nav_msgs::Path line;

    // Algo
    std::unique_ptr<Algo> algoHead;
};

int main(int argc, char **argv)
{
    // Node initialization
    std::cout << "Node initialization " << std::endl;
    ros::init(argc, argv, "regulation");

    Regulation regulation;

    regulation.spin();
    return 0;
}


//
// Copyright (c) 2015-2018 CNRS
//

#include "pinocchio/spatial/fwd.hpp"
#include "pinocchio/spatial/se3.hpp"
#include "pinocchio/multibody/visitor.hpp"
#include "pinocchio/multibody/model.hpp"
#include "pinocchio/multibody/data.hpp"
#include "pinocchio/algorithm/crba.hpp"
#include "pinocchio/algorithm/rnea.hpp"
#include "pinocchio/algorithm/cholesky.hpp"
#include "pinocchio/algorithm/jacobian.hpp"
#include "pinocchio/algorithm/center-of-mass.hpp"
#include "pinocchio/algorithm/compute-all-terms.hpp"
#include "pinocchio/algorithm/kinematics.hpp"
#include "pinocchio/algorithm/geometry.hpp"
#include "pinocchio/parsers/urdf.hpp"
#include "pinocchio/parsers/sample-models.hpp"
#include "pinocchio/multibody/geometry.hpp"
#include "pinocchio/utils/timer.hpp"

#include <iostream>
#include <Eigen/StdVector>

EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::VectorXd)

int main()
{
  using namespace Eigen;
  using namespace pinocchio;

  PinocchioTicToc timer(PinocchioTicToc::US);
  #ifdef NDEBUG
  const unsigned int NBT = 1000*100;
  const unsigned int NBD = 1000; // for heavy tests, like computeDistances()
  #else
    const unsigned int NBT = 1;
    const unsigned int NBD = 1;
    std::cout << "(the time score in debug mode is not relevant) " << std::endl;
  #endif

  std::string romeo_filename = PINOCCHIO_SOURCE_DIR"/models/romeo/romeo_description/urdf/romeo.urdf";
  std::vector < std::string > package_dirs;
  std::string romeo_meshDir  = PINOCCHIO_SOURCE_DIR"/models/";
  package_dirs.push_back(romeo_meshDir);

  pinocchio::Model model;
  pinocchio::urdf::buildModel(romeo_filename, pinocchio::JointModelFreeFlyer(),model);
  pinocchio::GeometryModel geom_model; pinocchio::urdf::buildGeom(model, romeo_filename, COLLISION, geom_model, package_dirs);
#ifdef PINOCCHIO_WITH_HPP_FCL
  geom_model.addAllCollisionPairs();
#endif // PINOCCHIO_WITH_HPP_FCL

  Data data(model);
  GeometryData geom_data(geom_model);

  std::vector<VectorXd> qs_romeo     (NBT);
  std::vector<VectorXd> qdots_romeo  (NBT);
  std::vector<VectorXd> qddots_romeo (NBT);
  for(size_t i=0;i<NBT;++i)
  {
    qs_romeo[i]     = Eigen::VectorXd::Random(model.nq);
    qs_romeo[i].segment<4>(3) /= qs_romeo[i].segment<4>(3).norm();
    qdots_romeo[i]  = Eigen::VectorXd::Random(model.nv);
    qddots_romeo[i] = Eigen::VectorXd::Random(model.nv);
  }

  timer.tic();
  SMOOTH(NBT)
  {
    forwardKinematics(model,data,qs_romeo[_smooth]);
  }
  double geom_time = timer.toc(PinocchioTicToc::US)/NBT;

  timer.tic();
  SMOOTH(NBT)
  {
    updateGeometryPlacements(model,data,geom_model,geom_data,qs_romeo[_smooth]);
  }
  double update_col_time = timer.toc(PinocchioTicToc::US)/NBT - geom_time;
  std::cout << "Update Collision Geometry < false > = \t" << update_col_time << " " << PinocchioTicToc::unitName(PinocchioTicToc::US) << std::endl;

#ifdef PINOCCHIO_WITH_HPP_FCL
  timer.tic();
  SMOOTH(NBT)
  {
    updateGeometryPlacements(model,data,geom_model,geom_data,qs_romeo[_smooth]);
    for (std::vector<pinocchio::CollisionPair>::iterator it = geom_model.collisionPairs.begin(); it != geom_model.collisionPairs.end(); ++it)
    {
      computeCollision(geom_model,geom_data,std::size_t(it-geom_model.collisionPairs.begin()));
    }
  }
  double collideTime = timer.toc(PinocchioTicToc::US)/NBT - (update_col_time + geom_time);
  std::cout << "Collision test between two geometry objects (mean time) = \t" << collideTime / double(geom_model.collisionPairs.size())
            << PinocchioTicToc::unitName(PinocchioTicToc::US) << std::endl;

  timer.tic();
  SMOOTH(NBT)
  {
    computeCollisions(geom_model,geom_data, true);
  }
  double is_colliding_time = timer.toc(PinocchioTicToc::US)/NBT - (update_col_time + geom_time);
  std::cout << "Collision Test : robot in collision? = \t" << is_colliding_time
            << PinocchioTicToc::unitName(PinocchioTicToc::US) << std::endl;

  timer.tic();
  SMOOTH(NBD)
  {
    computeDistances(model,data,geom_model,geom_data,qs_romeo[_smooth]);
  }
  double computeDistancesTime = timer.toc(PinocchioTicToc::US)/NBD - (update_col_time + geom_time);
  std::cout << "Compute distance between two geometry objects (mean time) = \t" << computeDistancesTime / double(geom_model.collisionPairs.size())
            << " " << PinocchioTicToc::unitName(PinocchioTicToc::US) << " " << geom_model.collisionPairs.size() << " col pairs" << std::endl;

#endif // PINOCCHIO_WITH_HPP_FCL
  return 0;
}


//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include "RefWorkloadUtils.hpp"
#include "TensorBufferArrayView.hpp"
#include "BaseIterator.hpp"
#include "Decoders.hpp"
#include "Encoders.hpp"

#include <armnn/Tensor.hpp>

#include <armnnUtils/DataLayoutIndexed.hpp>

#include <boost/numeric/conversion/cast.hpp>

#include <cmath>
#include <limits>

namespace armnn
{

/// Performs multiplication of an integer with a multiplier which is less than one,
/// using quantized integer arithmetic which is consistent with AndroidNN's CPU executor.
struct QuantizedMultiplierSmallerThanOne
{
public:
    /// Constructs a QuantizedMultiplierSmallerThanOne which will multiply by the given multiplier.
    /// This stores the appropriate integer quantities (derived from the given multiplier) for later use.
    /// The implementation of this function is adapted from Android NN's QuantizeMultiplierSmallerThanOne().
    QuantizedMultiplierSmallerThanOne(float multiplier);

    /// The implementation of this function is adapted from Android NN's MultiplyByQuantizedMultiplierSmallerThanOne().
    int32_t operator*(int32_t rhs) const;

private:
    /// The implementation of this function is adapted from gemmlowp's SaturatingRoundingDoublingHighMul().
    static int32_t SaturatingRoundingDoublingHighMul(int32_t a, int32_t b);

    /// The implementation of this function is adapted from gemmlowp's RoundingDivideByPOT().
    static int32_t RoundingDivideByPOT(int32_t x, int exponent);

    int32_t m_Multiplier;
    int32_t m_RightShift;
};

void Convolve(const TensorShape& rInputShape,
              Decoder<float>& rInputDecoder,
              const TensorShape& rOutputShape,
              Encoder<float>& rOutputEncoder,
              const TensorShape& rFilterShape,
              Decoder<float>& rFilterDecoder,
              bool biasEnabled,
              Decoder<float>* pBiasDecoder,
              DataLayout dataLayout,
              unsigned int paddingTop,
              unsigned int paddingLeft,
              unsigned int xStride,
              unsigned int yStride,
              unsigned int xDilation,
              unsigned int yDilation,
              bool depthwise = false);
} //namespace armnn


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

#include "trait_weight.hpp"

#include <boost/random/normal_distribution.hpp>
#include "clotho/random/normal_distribution_parameter.hpp"

namespace clotho {
namespace utility {

template < class URNG, class RealType >
class random_generator< URNG, trait_weight< RealType > > {
public:
    typedef RealType    real_type;
    typedef real_type   result_type;
    typedef random_generator< URNG, trait_weight< real_type > > self_type;

    typedef boost::random::normal_distribution< real_type >     dist_type;
    typedef normal_distribution_parameter< real_type >          norm_param_type;

    class param_type {
    public:
        real_type          _mean, _sigma;

        param_type( real_type m = 0., real_type s = 1. ) :
            _mean(m), _sigma(s) {
        }

        real_type mean()   const {
            return _mean;
        }

        real_type sigma()  const {
            return _sigma;
        }
    };

    random_generator( URNG & rng, boost::property_tree::ptree & config ) :
        m_rng( &rng )
        , m_dist( ) {
        parseConfig( config );
    }

    random_generator( URNG & rng, real_type mean = 0.0, real_type sigma = 1.0 ) :
        m_rng( &rng )
        , m_dist( mean, sigma ) {
    }

    random_generator( const self_type & other ) :
        m_rng( other.m_rng )
        , m_dist( other.m_dist.param() ) {
    }

    result_type operator()() {
        return m_dist(*m_rng);
    }

protected:

    void parseConfig( boost::property_tree::ptree & config ) {
        boost::property_tree::ptree lconfig;
        lconfig = config.get_child( TRAIT_BLOCK_K, lconfig );

        norm_param_type norm_param( lconfig );

        config.put_child( TRAIT_BLOCK_K, lconfig );

        typename dist_type::param_type p( norm_param.m_mean, norm_param.m_sigma );
        m_dist.param( p );
    }

    URNG            * m_rng;
    dist_type       m_dist;
};

}   // namespace utility
}   // namespace clotho

#endif  // TRAIT_WEIGHT_GENERATOR_HPP_


#ifndef DENSE_ARRAY2_HPP_ZJGDW1JR
#define DENSE_ARRAY2_HPP_ZJGDW1JR

#include <math.h>
#include <stdint.h>

#include <vector>

#include <Eigen/Core>
#include <Eigen/Dense>

#include <ros/console.h>

#include <geom_cast/geom_cast.hpp>
#include <pcl_util/point_types.hpp>

#include "scrollgrid/grid_types.hpp"

namespace ca
{

/**
 * A dense 2D array.
 * Maps ij to an CellT.
 * No notion of origin, scrolling etc.
 * The *Grid2 classes handle that.
 *
 */
template<class CellT>
class DenseArray2 {
public:
  typedef CellT CellType;
  typedef CellT * ArrayType;
  typedef CellT * iterator;
  typedef const CellT * const_iterator;

  typedef boost::shared_ptr<DenseArray2> Ptr;
  typedef boost::shared_ptr<const DenseArray2> ConstPtr;

public:
  // TODO perhaps stride/memory layout should
  // be further configurable.
  // TODO maybe *grid3 should just map to ijk and then
  // this class will map to linear memory address.
  // problem: then it needs scrolling info
  // I guess we can separate
  // - world_to_grid (infinite grid)
  // - grid_to_storage (linear mem or hash key)
  // - storage (dense array or sparse table)
  //

  DenseArray2() :
      dimension_(0, 0),
      num_cells_(0),
      strides_(0, 0),
      grid_(NULL),
      begin_(NULL),
      end_(NULL)
  { }

  DenseArray2(const Vec2Ix& dimension) :
      dimension_(dimension),
      num_cells_(dimension.prod()),
      strides_(dimension[1], 1),
      grid_(new CellT[num_cells_]),
      begin_(&grid_[0]),
      end_(&grid_[0]+num_cells_)
  { }

  virtual ~DenseArray2() {
    if (grid_) { delete[] grid_; }
  }

  void reset(const ca::Vec2Ix& dimension) {
    if (grid_) { delete[] grid_; }
    dimension_ = dimension;
    num_cells_ = dimension.prod();
    strides_ = ca::Vec2Ix(dimension[1], 1);
    grid_ = new CellT[num_cells_]();
    begin_ = &grid_[0];
    end_ = &grid_[0]+num_cells_;
  }

public:

  /**
   * NOTE be careful when using these!
   * They do no take into account any sort of wrapping
   * coming from scrollgrid.
   */
  grid_ix_t grid_to_mem(grid_ix_t i, grid_ix_t j) const {
    return this->grid_to_mem(Vec2Ix(i, j));
  }

  grid_ix_t grid_to_mem(const Vec2Ix& grid_ix) const {
    return strides_.dot(grid_ix);
  }

  /**
   * Note: no bound checking.
   */
  CellType& get(grid_ix_t i, grid_ix_t j) {
    grid_ix_t mem_ix = this->grid_to_mem(i, j);
    return grid_[mem_ix];
  }

  const CellType& get(grid_ix_t i, grid_ix_t j) const {
    grid_ix_t mem_ix = this->grid_to_mem(i, j);
    return grid_[mem_ix];
  }

  CellType& get(const Vec2Ix& grid_ix) {
    grid_ix_t mem_ix = this->grid_to_mem(grid_ix);
    return grid_[mem_ix];
  }

  const CellType& get(const Vec2Ix& grid_ix) const {
    grid_ix_t mem_ix = this->grid_to_mem(grid_ix);
    return grid_[mem_ix];
  }

  CellType& get(grid_ix_t mem_ix) {
    return grid_[mem_ix];
  }

  const CellType& get(grid_ix_t mem_ix) const {
    return grid_[mem_ix];
  }

  CellType& operator[](mem_ix_t mem_ix) {
    return grid_[mem_ix];
  }

  const CellType& operator[](mem_ix_t mem_ix) const {
    return grid_[mem_ix];
  }

public:
  // properties
  grid_ix_t dim_i() const { return dimension_[0]; }
  grid_ix_t dim_j() const { return dimension_[1]; }
  Vec2Ix dimension() const { return dimension_; }
  grid_ix_t num_cells() const { return num_cells_; }

private:
  DenseArray2(const DenseArray2& other);
  DenseArray2& operator=(const DenseArray2& other);

private:
  // number of grid cells along each axis
  Vec2Ix dimension_;

  // number of cells
  grid_ix_t num_cells_;

  // grid strides to translate from linear to 3D layout.
  // C-ordering, ie x slowest, z fastest.
  Vec2Ix strides_;

  ArrayType grid_;
  iterator begin_, end_;
};

} /* ca */

#endif /* end of include guard: DENSE_ARRAY2_HPP_ZJGDW1JR */


// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test

// Copyright (c) 2016-2017, Oracle and/or its affiliates.

// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle

// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html

#ifndef BOOST_GEOMETRY_TEST_DISTANCE_GEO_COMMON_HPP
#define BOOST_GEOMETRY_TEST_DISTANCE_GEO_COMMON_HPP

#include <iostream>
#include <string>

#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_same.hpp>

#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>

#include <boost/geometry/io/wkt/write.hpp>
#include <boost/geometry/io/dsv/write.hpp>

#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/distance.hpp>

#include <boost/geometry/strategies/strategies.hpp>

#include <from_wkt.hpp>
#include <string_from_type.hpp>

#include "distance_brute_force.hpp"

namespace bg = ::boost::geometry;

typedef bg::srs::spheroid<double> stype;

// Spherical strategy  for point-point distance

typedef bg::strategy::distance::haversine<double> spherical_pp;

// Geo strategies for point-point distance

typedef bg::strategy::distance::andoyer<stype> andoyer_pp;
typedef bg::strategy::distance::thomas<stype> thomas_pp;
typedef bg::strategy::distance::vincenty<stype> vincenty_pp;

// Spherical strategy  for point-segment distance

typedef bg::strategy::distance::cross_track<> spherical_ps;

// Geo strategies for point-segment distance

typedef bg::strategy::distance::geographic_cross_track<bg::strategy::andoyer, stype, double>
        andoyer_ps;

typedef bg::strategy::distance::geographic_cross_track<bg::strategy::thomas, stype, double>
        thomas_ps;

typedef bg::strategy::distance::geographic_cross_track<bg::strategy::vincenty, stype, double>
        vincenty_ps;

// Spherical strategy  for point-box distance

typedef bg::strategy::distance::cross_track_point_box<> spherical_pb;

// Geo strategies for point-box distance

typedef bg::strategy::distance::geographic_cross_track_point_box
<
    bg::strategy::andoyer,
    stype,
    double
> andoyer_pb;

typedef bg::strategy::distance::geographic_cross_track_point_box
<
    bg::strategy::thomas,
    stype,
    double
> thomas_pb;

typedef bg::strategy::distance::geographic_cross_track_point_box
<
    bg::strategy::vincenty,
    stype,
    double
> vincenty_pb;

// Spherical strategy  for segment-box distance

typedef bg::strategy::distance::spherical_segment_box<> spherical_sb;

// Geo strategies for segment-box distance

typedef bg::strategy::distance::geographic_segment_box<bg::strategy::andoyer, stype, double>
        andoyer_sb;

typedef bg::strategy::distance::geographic_segment_box<bg::strategy::thomas, stype, double>
        thomas_sb;

typedef bg::strategy::distance::geographic_segment_box<bg::strategy::vincenty, stype, double>
        vincenty_sb;

// Strategies for box-box distance

typedef bg::strategy::distance::cross_track_box_box<> spherical_bb;

typedef bg::strategy::distance::geographic_cross_track_box_box
        <
            bg::strategy::andoyer,
            stype,
            double
        > andoyer_bb;

typedef bg::strategy::distance::geographic_cross_track_box_box
        <
            bg::strategy::thomas,
            stype,
            double
        > thomas_bb;

typedef bg::strategy::distance::geographic_cross_track_box_box
        <
            bg::strategy::vincenty,
            stype,
            double
        > vincenty_bb;

//===========================================================================

template <typename Point, typename Strategy>
inline typename bg::default_distance_result<Point>::type
pp_distance(std::string const& wkt1,
            std::string const& wkt2,
            Strategy const& strategy)
{
    Point p1, p2;
    bg::read_wkt(wkt1, p1);
    bg::read_wkt(wkt2, p2);
    return bg::distance(p1, p2, strategy);
}

//===========================================================================

template <typename Point, typename Strategy>
inline typename bg::default_distance_result<Point>::type
ps_distance(std::string const& wkt1,
            std::string const& wkt2,
            Strategy const& strategy)
{
    Point p;
    typedef bg::model::segment<Point> segment_type;
    segment_type s;
    bg::read_wkt(wkt1, p);
    bg::read_wkt(wkt2, s);
    return bg::distance(p, s, strategy);
}

//===========================================================================

template <typename Point, typename Strategy>
inline typename bg::default_distance_result<Point>::type
sb_distance(std::string const& wkt1,
            std::string const& wkt2,
            Strategy const& strategy)
{
    typedef bg::model::segment<Point> segment_type;
    typedef bg::model::box<Point> box_type;
    segment_type s;
    box_type b;
    bg::read_wkt(wkt1, s);
    bg::read_wkt(wkt2, b);
    return bg::distance(s, b, strategy);
}

//===================================================================

template <typename Tag> struct dispatch
{
    //tag dispatching for swaping arguments in segments
    template <typename T>
    static inline T swap(T const& t)
    {
        return t;
    }

    // mirror geometry w.r.t. equator
    template <typename T>
    static inline T mirror(T const& t)
    {
        return t;
    }
};

// Specialization for segments
template <> struct dispatch<boost::geometry::segment_tag>
{
    template <typename Segment>
    static inline Segment swap(Segment const& s)
    {
        Segment s_swaped;

        bg::set<0, 0>(s_swaped, bg::get<1, 0>(s));
        bg::set<0, 1>(s_swaped, bg::get<1, 1>(s));
        bg::set<1, 0>(s_swaped, bg::get<0, 0>(s));
        bg::set<1, 1>(s_swaped, bg::get<0, 1>(s));

        return s_swaped;
    }

    template <typename Segment>
    static inline Segment mirror(Segment const& s)
    {
        Segment s_mirror;

        bg::set<0, 0>(s_mirror, bg::get<0, 0>(s));
        bg::set<0, 1>(s_mirror, bg::get<0, 1>(s) * -1);
        bg::set<1, 0>(s_mirror, bg::get<1, 0>(s));
        bg::set<1, 1>(s_mirror, bg::get<1, 1>(s) * -1);

        return s_mirror;
    }
};

// Specialization for boxes
template <> struct dispatch<boost::geometry::box_tag>
{
    template <typename T>
    static inline T swap(T const& t)
    {
        return t;
    }

    template <typename Box>
    static inline Box mirror(Box const& b)
    {
        Box b_mirror;

        bg::set<0, 0>(b_mirror, bg::get<bg::min_corner, 0>(b));
        bg::set<0, 1>(b_mirror, bg::get<bg::max_corner, 1>(b) * -1);
        bg::set<1, 0>(b_mirror, bg::get<bg::max_corner, 0>(b));
        bg::set<1, 1>(b_mirror, bg::get<bg::min_corner, 1>(b) * -1);

        return b_mirror;
    }
};

// Specialization for points
template <> struct dispatch<boost::geometry::point_tag>
{
    template <typename T>
    static inline T swap(T const& t)
    {
        return t;
    }

    template <typename Point>
    static inline Point mirror(Point const& p)
    {
        Point p_mirror;

        bg::set<0>(p_mirror, bg::get<0>(p));
        bg::set<1>(p_mirror, bg::get<1>(p) * -1);

        return p_mirror;
    }
};

//========================================================================

template <typename T>
struct check_equal
{
    template <typename Value, typename = void>
    struct equal_to
    {
        static inline void apply(Value const& x, Value const& y)
        {
            BOOST_CHECK(x == y);
        }
    };

    template <typename Dummy>
    struct equal_to<double, Dummy>
    {
        static inline void apply(double x, double y)
        {
            BOOST_CHECK_CLOSE(x, y, 0.001);
        }
    };

    template <typename Geometry1, typename Geometry2>
    static inline void apply(std::string const& /*case_id*/,
                             std::string const& /*subcase_id*/,
                             Geometry1 const& /*geometry1*/,
                             Geometry2 const& /*geometry2*/,
                             T const& detected,
                             T const& expected)
    {
        equal_to<T>::apply(expected, detected);
    }
};

//========================================================================

template
<
    typename Geometry1, typename Geometry2,
    int id1 = bg::geometry_id<Geometry1>::value,
    int id2 = bg::geometry_id<Geometry2>::value
>
struct test_distance_of_geometries
    : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
{};

template <typename Geometry1, typename Geometry2>
struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
{
    template <typename DistanceType, typename Strategy>
    static inline
    void apply(std::string const& case_id,
               std::string const& wkt1,
               std::string const& wkt2,
               DistanceType const& expected_distance,
               Strategy const& strategy,
               bool test_reversed = true,
               bool swap_geometry_args = false,
               bool mirror_geometry = true)
    {
        Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
        Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);

        apply(case_id, geometry1, geometry2,
              expected_distance,
              strategy, test_reversed, swap_geometry_args,
              mirror_geometry);
    }

    template
    <
        typename DistanceType,
        typename Strategy
    >
    static inline
    void apply(std::string const& case_id,
               Geometry1 const& geometry1,
               Geometry2 const& geometry2,
               DistanceType const& expected_distance,
               Strategy const& strategy,
               bool test_reversed = true,
               bool swap_geometry_args = false,
               bool mirror_geometry = true)
    {
#ifdef BOOST_GEOMETRY_TEST_DEBUG
        std::cout << "case ID: " << case_id << "; "
                  << "G1: " << bg::wkt(geometry1)
                  << " - "
                  << "G2: " << bg::wkt(geometry2)
                  << std::endl;
#endif
        namespace services = bg::strategy::distance::services;

        using bg::unit_test::distance_brute_force;

        typedef typename bg::default_distance_result
            <
                Geometry1, Geometry2
            >::type default_distance_result;

        typedef typename services::return_type
            <
                Strategy, Geometry1, Geometry2
            >::type distance_result_from_strategy;

        static const bool same_regular = boost::is_same
            <
                default_distance_result,
                distance_result_from_strategy
            >::type::value;

        BOOST_CHECK(same_regular);

        // check distance with passed strategy
        distance_result_from_strategy dist =
            bg::distance(geometry1, geometry2, strategy);

        check_equal
            <
                distance_result_from_strategy
            >::apply(case_id, "a", geometry1, geometry2,
                     dist, expected_distance);

        // check against the comparable distance computed in a
        // brute-force manner
        default_distance_result dist_brute_force
            = distance_brute_force(geometry1, geometry2, strategy);

        check_equal
            <
                default_distance_result
            >::apply(case_id, "b", geometry1, geometry2,
                     dist_brute_force, expected_distance);

#ifdef BOOST_GEOMETRY_TEST_DEBUG
        std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name()
                  << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name()
                  << " -> "
                  << string_from_type<default_distance_result>::name()
                  << std::endl;
        std::cout << "expected distance = "
                  << expected_distance << " ; "
                  << std::endl;
        std::cout << "distance = "
                  << dist << " ; "
                  << std::endl;

        if ( !test_reversed )
        {
            std::cout << std::endl;
        }
#endif

        if ( test_reversed )
        {
            // check distance with given strategy
            dist = bg::distance(geometry2, geometry1, strategy);

            check_equal
                <
                    default_distance_result
                >::apply(case_id, "ra", geometry2, geometry1,
                         dist, expected_distance);

#ifdef BOOST_GEOMETRY_TEST_DEBUG
            std::cout << "distance[reversed args] = "
                      << dist
                      << std::endl;
#endif
        }

        if (swap_geometry_args)
        {
            Geometry1 g1 = dispatch
                <
                    typename boost::geometry::tag<Geometry1>::type
                >::swap(geometry1);

            Geometry2 g2 = dispatch
                <
                    typename boost::geometry::tag<Geometry2>::type
                >::swap(geometry2);

            // check distance with given strategy
            dist = bg::distance(g1, g2, strategy);

            check_equal
                <
                    default_distance_result
                >::apply(case_id, "swap", g1, g2,
                         dist, expected_distance);

#ifdef BOOST_GEOMETRY_TEST_DEBUG
            std::cout << "distance[swap geometry args] = "
                      << dist
                      << std::endl;
            std::cout << std::endl;
#endif
        }
        if (mirror_geometry)
        {
            Geometry1 g1 = dispatch
                <
                    typename boost::geometry::tag<Geometry1>::type
                >::mirror(geometry1);

            Geometry2 g2 = dispatch
                <
                    typename boost::geometry::tag<Geometry2>::type
                >::mirror(geometry2);

            // check distance with given strategy
            dist = bg::distance(g1, g2, strategy);

            check_equal
                <
                    default_distance_result
                >::apply(case_id, "mirror", g1, g2,
                         dist, expected_distance);

#ifdef BOOST_GEOMETRY_TEST_DEBUG
            std::cout << "distance[mirror geometries] = "
                      << dist
                      << std::endl;
            std::cout << std::endl;
#endif
        }
#ifdef BOOST_GEOMETRY_TEST_DEBUG
            std::cout << std::endl;
#endif

    }
};

//========================================================================

template <typename Geometry1, typename Geometry2, typename Strategy>
void test_empty_input(Geometry1 const& geometry1,
                      Geometry2 const& geometry2,
                      Strategy const& strategy)
{
    try
    {
        bg::distance(geometry1, geometry2);
    }
    catch(bg::empty_input_exception const& )
    {
        return;
    }
    BOOST_CHECK_MESSAGE(false,
                        "A empty_input_exception should have been thrown");

    try
    {
        bg::distance(geometry2, geometry1);
    }
    catch(bg::empty_input_exception const& )
    {
        return;
    }
    BOOST_CHECK_MESSAGE(false,
                        "A empty_input_exception should have been thrown");

    try
    {
        bg::distance(geometry1, geometry2, strategy);
    }
    catch(bg::empty_input_exception const& )
    {
        return;
    }
    BOOST_CHECK_MESSAGE(false,
                        "A empty_input_exception should have been thrown");

    try
    {
        bg::distance(geometry2, geometry1, strategy);
    }
    catch(bg::empty_input_exception const& )
    {
        return;
    }
    BOOST_CHECK_MESSAGE(false,
                        "A empty_input_exception should have been thrown");
}

#endif // BOOST_GEOMETRY_TEST_DISTANCE_GEO_COMMON_HPP


//==============================================================================
//         Copyright 2003 - 2011   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_EXPONENTIAL_CONSTANTS_MAXLOG_HPP_INCLUDED
#define NT2_EXPONENTIAL_CONSTANTS_MAXLOG_HPP_INCLUDED

#include <nt2/include/functor.hpp>
#include <boost/simd/constant/hierarchy.hpp>
#include <boost/simd/constant/register.hpp>

namespace nt2
{
  namespace tag
  {
    /*!
      @brief Maxlog generic tag

      Represents the Maxlog constant in generic contexts.

      @par Models:
      Hierarchy
    **/
    BOOST_SIMD_CONSTANT_REGISTER( Maxlog, double
                                , 0, 0x42b0c0a5UL
                                , 0x40862e42fefa39efULL
                                )
  }
  namespace ext
  {
    template<class Site, class... Ts>
    BOOST_FORCEINLINE generic_dispatcher<tag::Maxlog, Site> dispatching_Maxlog(adl_helper, boost::dispatch::meta::unknown_<Site>, boost::dispatch::meta::unknown_<Ts>...)
    {
      return generic_dispatcher<tag::Maxlog, Site>();
    }
    template<class... Args>
    struct impl_Maxlog;
  }
  /*!
    Generates constant MaxLog used in logarithm/exponential computations
    nt2::log(x) return inf if x is greater than Maxlog (overflow)

    @par Semantic:

    @code
    T r = Maxlog<T>();
    @endcode

    is similar to:

    @code
    if T is double
      r = 709.78271289338400;
    else if T is float
      r =  88.3762626647949
    @endcode

    @see @{Minlog}

  **/
  BOOST_SIMD_CONSTANT_IMPLEMENTATION(tag::Maxlog, Maxlog);
}

#endif


//==================================================================================================
/*!
  @file

  @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_COMMON_SCALAR_FUNCTION_REMCEIL_HPP_INCLUDED
#define BOOST_SIMD_ARCH_COMMON_SCALAR_FUNCTION_REMCEIL_HPP_INCLUDED

#include <boost/simd/function/div.hpp>
#include <boost/simd/function/ceil.hpp>
#include <boost/simd/function/is_nez.hpp>
#include <boost/simd/function/fnms.hpp>
#include <boost/simd/function/minus.hpp>
#include <boost/simd/function/multiplies.hpp>
#include <boost/simd/detail/dispatch/function/overload.hpp>
#include <boost/config.hpp>
/////////////////////////////////////////////////////////////////////////////
// The remceil() function computes the remceil of dividing x by y.  The
// return value is x-n*y, where n is the value x / y, rounded toward +infinity
/////////////////////////////////////////////////////////////////////////////
namespace boost { namespace simd { namespace ext
{
  namespace bd = boost::dispatch;
  BOOST_DISPATCH_OVERLOAD ( rem_
                          , (typename A0)
                          , bd::cpu_
                          , bs::tag::ceil_
                          , bd::scalar_< bd::int_<A0> >
                          , bd::scalar_< bd::int_<A0> >
                          )
  {
    BOOST_FORCEINLINE A0 operator() (bd::functor<bs::tag::ceil_> const&
                                    , A0 a0, A0 a1) const BOOST_NOEXCEPT
    {
      if (is_nez(a1))
        return fnms(div(ceil, a0, a1), a1, a0);
      else
        return a0;
    }
  };

  BOOST_DISPATCH_OVERLOAD ( rem_
                          , (typename A0)
                          , bd::cpu_
                          , bs::fast_tag
                          , bs::tag::ceil_
                          , bd::scalar_< bd::int_<A0> >
                          , bd::scalar_< bd::int_<A0> >
                          )
  {
    BOOST_FORCEINLINE A0 operator() (const fast_tag &
                                    , bd::functor<bs::tag::ceil_> const&
                                    , A0 a0, A0 a1) const BOOST_NOEXCEPT
    {
      return fnms(div(ceil, a0, a1), a1, a0);
    }
  };

  BOOST_DISPATCH_OVERLOAD ( rem_
                          , (typename A0)
                          , bd::cpu_
                          , bs::fast_tag
                          , bs::tag::ceil_
                          , bd::scalar_< bd::floating_<A0> >
                          , bd::scalar_< bd::floating_<A0> >
                          )
  {
    BOOST_FORCEINLINE A0 operator() (const fast_tag &
                                    , bd::functor<bs::tag::ceil_> const&
                                    , A0 a0, A0 a1) const BOOST_NOEXCEPT
    {
      return  fnms(div(ceil, a0,a1), a1, a0);
    }
  };

  BOOST_DISPATCH_OVERLOAD ( rem_
                          , (typename A0)
                          , bd::cpu_
                          , bs::tag::ceil_
                          , bd::scalar_< bd::floating_<A0> >
                          , bd::scalar_< bd::floating_<A0> >
                          )
  {
    BOOST_FORCEINLINE A0 operator() ( bd::functor<bs::tag::ceil_> const&
                                    , A0 a0, A0 a1) const BOOST_NOEXCEPT
    {
      if (is_nez(a1)&&is_eqz(a0)) return a0;
      return fnms(div(ceil, a0, a1), a1, a0);
    }
  };

} } }

#endif


//          Copyright Erle Carrara 2017.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <pybind11/pybind11.h>

using namespace boost::accumulators;
namespace py = pybind11;

using accumulator_set_type = accumulator_set<double, stats<tag::mean>>;

PYBIND11_PLUGIN(accumulators) {
    py::module m("accumulators");

    py::class_<accumulator_set_type>(m, "Accumulator")
        .def(py::init())
        .def("__call__", [](accumulator_set_type &acc, double v) {
            return acc(v);
        }, py::is_operator())
        .def("mean", [](const accumulator_set_type &acc) {
        return mean(acc);
    });

    return m.ptr();
}


/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

/*! \file test/equitycrossassetmodel.hpp
    \brief cross asset model - equity components test
*/

#ifndef quantext_test_equitycrossassetmodel_hpp
#define quantext_test_equitycrossassetmodel_hpp

#include <boost/test/unit_test.hpp>

namespace testsuite {

//! EquityCrossAssetModel tests
class EquityCrossAssetModelTest {
public:
    /*! In a EUR-USD CrossAssetModel with two equities, test a Monte Carlo pricing of an equiy forward under the base
     *  currency numeraire against the analytical expectation. Perform similar checks for an equity option. */
    static void testEqLgm5fPayouts();

    /*! Test the calibration of all components of a full CrossAssetModel (3 IR LGM models and 2 FX Black Scholes
     * models and 2 equities) by comparing the model prices and market prices of the calibration instruments. */
    static void testLgm5fEqCalibration();

    /*! Compare the analytical (unconditional) expectation and covariance matrix of the 7 dimensional stochastic process
     * of a CrossAssetModel at t=10 against Monte Carlo estimates using both an exact and an Euler
     * discretisation. Special attention paid to the equity components of the process. */
    static void testLgm5fMoments();

    static boost::unit_test_framework::test_suite* suite();
};
}

#endif


/*******************************************************************************
 *         Copyright 2003-2012 LASMEA UMR 6602 CNRS/U.B.P
 *         Copyright 2009-2012 LRI    UMR 8623 CNRS/Univ Paris Sud XI
 *
 *          Distributed under the Boost Software License, Version 1.0.
 *                 See accompanying file LICENSE.txt or copy at
 *                     http://www.boost.org/LICENSE_1_0.txt
 ******************************************************************************/
#ifndef NT2_TOOLBOX_LINALG_FUNCTIONS_MPOWER_HPP_INCLUDED
#define NT2_TOOLBOX_LINALG_FUNCTIONS_MPOWER_HPP_INCLUDED

#include <nt2/include/functor.hpp>
#include <nt2/core/container/dsl/size.hpp>
#include <nt2/core/container/dsl/value_type.hpp>
#include <nt2/sdk/meta/value_as.hpp>
#include <nt2/core/utility/max_extent.hpp>
#include <nt2/sdk/meta/tieable_hierarchy.hpp>
#include <nt2/sdk/complex/meta/is_complex.hpp>
#include <nt2/include/functions/isscalar.hpp>
#include <nt2/include/functions/issquare.hpp>
#include <nt2/include/functions/extent.hpp>
#include <boost/mpl/if.hpp>
#include <boost/assert.hpp>

namespace nt2
{
  namespace tag
  {
    /*!
     * \brief Define the tag mpower_ of functor mpower
     *        in namespace nt2::tag for toolbox algebra
     **/
    struct mpower_ :  ext::tieable_<mpower_>
    {
      typedef ext::tieable_<mpower_>  parent;
    };
  }
  /**
   * @brief compute matricial power a0^a1
   *
   * a0 or a1 can be a square matricial expression,  but one of the two must be scalar
   *
   * @param  a0  Matrix expression or scalar
   * @param  a1  Scalar or matrix expression
   *
   * @return a matrix containing a0^a1
   **/

  BOOST_DISPATCH_FUNCTION_IMPLEMENTATION(tag::mpower_, mpower, 2)

}

namespace nt2 { namespace ext
{
  template<class Domain, int N, class Expr>
  struct  size_of<tag::mpower_,Domain,N,Expr>
  {
    typedef typename boost::proto::result_of::child_c<Expr&,0>::value_type  c0_t;
    typedef typename boost::proto::result_of::child_c<Expr&,1>::value_type  c1_t;
    typedef typename c0_t::extent_type                                     ex0_t;
    typedef typename c1_t::extent_type                                     ex1_t;
    typedef typename utility::result_of::max_extent<ex0_t, ex1_t>::type         result_type;
    BOOST_FORCEINLINE result_type operator()(Expr& e) const
    {
      BOOST_ASSERT_MSG((isscalar( boost::proto::child_c<0>(e))&&issquare(boost::proto::child_c<1>(e)))||
                       (isscalar( boost::proto::child_c<1>(e))&&issquare(boost::proto::child_c<0>(e))),
                       "mpower needs a square matrix expression and a scalar or a scalar and a square matrix expression");

      return nt2::utility::max_extent(nt2::extent(boost::proto::child_c<0>(e)),  nt2::extent(boost::proto::child_c<1>(e)));
    }
  };

  template<class Domain, int N, class Expr>
  struct  value_type<tag::mpower_,Domain,N,Expr>
        : meta::value_as<Expr,0>
  {
    typedef typename  boost::proto::result_of::child_c<Expr&,0>::value_type::value_type v0_t;
    typedef typename  boost::proto::result_of::child_c<Expr&,1>::value_type::value_type v1_t;
    typedef typename  meta::is_complex<v0_t>::type                                  iscplx_0;
    typedef typename  meta::is_complex<v1_t>::type                                  iscplx_1;
    typedef typename  boost::mpl::if_<iscplx_0, v0_t, v1_t>::type                       t0_t;
    typedef typename  boost::mpl::if_<iscplx_1, v1_t, t0_t>::type                       type;
  };
} }

#endif


//
//  Copyright (c) 2000-2002
//  Joerg Walter, Mathias Koch
//
//  Permission to use, copy, modify, distribute and sell this software
//  and its documentation for any purpose is hereby granted without fee,
//  provided that the above copyright notice appear in all copies and
//  that both that copyright notice and this permission notice appear
//  in supporting documentation.  The authors make no representations
//  about the suitability of this software for any purpose.
//  It is provided "as is" without express or implied warranty.
//
//  The authors gratefully acknowledge the support of
//  GeNeSys mbH & Co. KG in producing this work.
//

#ifdef BOOST_MSVC

#pragma warning (disable: 4355)
#pragma warning (disable: 4503)
#pragma warning (disable: 4786)

#endif

#include <iostream>

#include <boost/numeric/ublas/config.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/io.hpp>

#include <boost/numeric/ublas/blas.hpp>

#include "test2.hpp"

template<class V, int N>
void test_blas_1<V, N>::operator () () {
    try {
        value_type t;
        real_type n;
        V v1 (N), v2 (N);

        // _asum
        initialize_vector (v1);
        n = ublas::blas_1::asum (v1);
        std::cout << "asum (v1) = " << n << std::endl;

        // _amax
        initialize_vector (v1);
        n = ublas::blas_1::amax (v1);
        std::cout << "amax (v1) = " << n << std::endl;

        // _nrm2
        initialize_vector (v1);
        n = ublas::blas_1::nrm2 (v1);
        std::cout << "nrm2 (v1) = " << n << std::endl;

        // _dot
        // _dotu
        // _dotc
        initialize_vector (v1);
        initialize_vector (v2);
        t = ublas::blas_1::dot (v1, v2);
        std::cout << "dot (v1, v2) = " << t << std::endl;
        t = ublas::blas_1::dot (ublas::conj (v1), v2);
        std::cout << "dot (conj (v1), v2) = " << t << std::endl;

        // _copy
        initialize_vector (v2);
        ublas::blas_1::copy (v1, v2);
        std::cout << "copy (v1, v2) = " << v1 << std::endl;

        // _swap
        initialize_vector (v1);
        initialize_vector (v2);
        ublas::blas_1::swap (v1, v2);
        std::cout << "swap (v1, v2) = " << v1 << " " << v2 << std::endl;

        // _scal
        // csscal
        // zdscal
        initialize_vector (v1);
        ublas::blas_1::scal (v1, value_type (1));
        std::cout << "scal (v1, 1) = " << v1 << std::endl;

        // _axpy
        initialize_vector (v1);
        initialize_vector (v2);
        ublas::blas_1::axpy (v1, value_type (1), v2);
        std::cout << "axpy (v1, 1, v2) = " << v1 << std::endl;

        // _rot
        initialize_vector (v1);
        initialize_vector (v2);
        ublas::blas_1::rot (value_type (1), v1, value_type (1), v2);
        std::cout << "rot (1, v1, 1, v2) = " << v1 << " " << v2 << std::endl;
    }
    catch (std::exception &e) {
        std::cout << e.what () << std::endl;
    }
    catch (...) {
        std::cout << "unknown exception" << std::endl;
    }
}

#ifdef USE_FLOAT
template struct test_blas_1<ublas::vector<float>, 3>;
#endif

#ifdef USE_DOUBLE
template struct test_blas_1<ublas::vector<double>, 3>;
#endif

#ifdef USE_STD_COMPLEX
#ifdef USE_FLOAT
template struct test_blas_1<ublas::vector<std::complex<float> >, 3>;
#endif

#ifdef USE_DOUBLE
template struct test_blas_1<ublas::vector<std::complex<double> >, 3>;
#endif
#endif


#include <iostream>
//#include <boost/numeric/ublas/vector.hpp>
using namespace std;

//typedef boost::numeric::ublas::vector<float> vector3;

class vector3
{
	union
	{
		boost::numeric::ublas::vector<float> val;

		struct
		{
			float x, y, z;
		};
	};

	vector3()    : val(3)
	{
	}

	~vector3()
	{
	}
};

int main()
{
	//vector3 vec;

	return 0;
}


#define BZ_NEW_EXPRESSION_TEMPLATES

#include <blitz/array.h>

BZ_USING_NAMESPACE(blitz)

double myFunction(double x)
{ return 1.0 / (1 + x); }

double foobar(double x, double y)
{
    return x*y;
}

BZ_DECLARE_FUNCTION(myFunction)
BZ_DECLARE_FUNCTION2(foobar)

int main()
{
    Array<double,2> A(4,4), B(4,4), C(4,4);

    A = 0,  1,  2,  3,
        4,  5,  6,  7,
        8,  9, 10, 11,
       12, 13, 14, 15;
    C = 3;

    cout << "A = " << A << endl
         << "C = " << C << endl;

    B = myFunction(A);

    cout << "B = myFunction(A) = " << B << endl;

    B = foobar(A,C);
    cout << "B = foobar(A,C) = " << B << endl;

    B = foobar(tensor::i, tensor::j);
    cout << "B = foobar(tensor::i, tensor::j) = " << B << endl;
}


#include <iostream>
#include <iomanip>
#include <vector>
#include <thread>

#include <boost/iostreams/device/mapped_file.hpp>

#include "skt.hpp"

int main(int  argc, char const *const  argv[]) {

	// Evaluate Parameters
	if(argc != 3) {
		std::cerr << argv[0] << " <file> <threads>" << std::endl;
		return -1;
	}

	boost::iostreams::mapped_file  ibuf(argv[1], std::ios_base::in);
	uint32_t const *const  idata    = (uint32_t const*)ibuf.const_data();
	size_t const           isize    = ibuf.size()/sizeof(uint32_t);
	unsigned const         nthreads = atoi(argv[2]);

	std::cout << "Processing " << isize << " items by " << nthreads << " threads." << std::endl;
	if(nthreads < 1)  return  0;

	std::vector<SktCollector> collectors;
	collectors.reserve(nthreads);
	hash_e const  hash = value_of<hash_e>("MURMUR3_128");

	// Distribute data to partial sketches
	std::thread  workers[nthreads];
	for(unsigned  i = 0; i < nthreads; i++) {
		collectors.emplace_back(13, 5, 13, 5, 13, hash);
		SktCollector &collector = collectors.back();
		workers[i] = std::thread([&collector, data = &idata[i*isize/nthreads], size = (i+1)*isize/nthreads - i*isize/nthreads](){
			collector.collect(data, size);
		});
	}

	// Compact into first Table
	workers[0].join();
	SktCollector &master_collector = collectors.front();
	for(unsigned  i = 1; i < nthreads; i++) {
		workers[i].join();
		master_collector.merge(collectors[i]);
	}

	double const  cardest = collectors[0].estimate_cardinality();
	std::cout  << "Estimated cardinality: " << cardest << std::endl;

	return 0;
}


#include <sparse.h>
#include <sparse_fill.h>
#include <cstdlib>

#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/test_tools.hpp>

BOOST_AUTO_TEST_SUITE(SPARSE);

BOOST_AUTO_TEST_CASE(sparse_conjugate_gradient_test)
{
  typedef sparse::Block<3,3,float>                    block3x3_type;
  typedef sparse::Block<3,1,float>                    block3x1_type;
  typedef sparse::Vector<block3x1_type>               block3Vector_type;
  typedef sparse::CompressedRowMatrix<block3x3_type>  compressed3x3_type;

  compressed3x3_type A;
  block3Vector_type x;
  block3Vector_type b;
  block3Vector_type expected_x;

  //set up variables
  A.resize(4,4,4);
  x.resize(4);
  b.resize(4);
  expected_x.resize(4);

  for(int i = 0; i < 4; ++i)
  {
    A(i,i) = block3x3_type::identity();
    b(i)= 1;
    expected_x(i)= 1;
  }
  //run conjugate gradient
  conjugate_gradient(A,x,b);
  //test values
  for(size_t i = 0; i < A.size(); ++i)
  {
    BOOST_CHECK(x(i) == expected_x(i));
  }
  //reset the values for use
  A.clear();
  b.clear_data();
  x.clear_data();
  expected_x.clear_data();

  //set up variables
  A.resize(4,4,4,false);
  x.resize(4);
  b.resize(4);
  expected_x.resize(4);

  for(int i = 0; i < 4; ++i)
  {
    A(i,i) = block3x3_type::identity();
    sparse::mul(2.0f,A(i,i));
    b(i)= 1;
    expected_x(i)= 0.5;
  }
  //run conjugate gradient
  conjugate_gradient(A,x,b);
  //test values
  for(size_t i = 0; i < A.size(); ++i)
  {
    BOOST_CHECK(x(i) == expected_x(i));
  }

  //reset the values for use
  A.clear();
  b.clear_data();
  x.clear_data();
  expected_x.clear_data();

  //set up variables
  A.resize(4,4,4,false);
  x.resize(4);
  b.resize(4);
  expected_x.resize(4);

  for(int i = 0; i < 4; ++i)
  {
    A(i,i) = block3x3_type::identity();
    sparse::mul(i+2.0f,A(i,i));
    expected_x(i)= i*2 % 3;
  }
  prod(A,expected_x, b);
  //run conjugate gradient
  conjugate_gradient(A,x,b);
  //test values
  for(size_t i = 0; i < A.size(); ++i)
  {
    BOOST_CHECK(x(i) == expected_x(i));
  }

  //reset the values for use
  A.clear();
  b.clear_data();
  x.clear_data();
  expected_x.clear_data();

  //set up variables
  A.resize(4,4,10);
  x.resize(4);
  b.resize(4);
  expected_x.resize(4);
  //create an upper triangle matrix (with no zeros in diagonal) as it
  //is ensured to have full rank
  for(size_t i = 0; i < 4; ++i)
  {
    for(size_t j = 0; j < 4; ++j)
    {
      sparse::mul(1.0f,block3x3_type::identity(),A(i,j));
    }
    expected_x(i)= 2;
  }
  //calculate b
  sparse::prod(A,expected_x,b);

  //run conjugate gradient
  conjugate_gradient(A,x,b);
  //test values
  for(size_t i = 0; i < A.nrows(); ++i)
  {
    BOOST_CHECK(x(i) == expected_x(i));
  }
  //reset the values for use
  A.clear();
  b.clear_data();
  x.clear_data();
  expected_x.clear_data();

  //set up variables
  A.resize(4,4,10);
  x.resize(4);
  b.resize(4);
  expected_x.resize(4);

  for(size_t i = 0; i < 4; ++i)
  {
    for(size_t j = 0; j < 4; ++j)
    {
      sparse::mul(1.0f,block3x3_type::identity(),A(i,j));
    }
    expected_x(i)= 2;
  }
  //calculate b
  sparse::prod(A,expected_x,b);

  //run conjugate gradient
  conjugate_gradient(A,x,b);
  //test values

  for(size_t i = 0; i < A.nrows(); ++i)
  {
    BOOST_CHECK(x(i) == expected_x(i));
  }

  //reset the values for use
  A.clear();
  b.clear_data();
  x.clear_data();
  expected_x.clear_data();

  A.resize(4,4,16);
  compressed3x3_type P;
  for(size_t i = 0; i < 4; ++i)
  {
    for(size_t j = 0; j < 4; ++j)
    {
      sparse::mul(2.0f,block3x3_type::identity(),A(i,j));
    }
    expected_x(i)= 2;
  }
  sparse::make_jacobi_preconditioner(A,P);
  compressed3x3_type::iterator PIter = P.begin();
  compressed3x3_type::iterator PEnd = P.end();
  for(; PIter < PEnd; ++PIter)
  {
    BOOST_CHECK(*PIter == block3x3_type::make_diag(1.0f/2.0f));
    BOOST_CHECK(row(PIter) == col(PIter));
  }
}

BOOST_AUTO_TEST_SUITE_END();


#include <igl/matlab/MexStream.h>
#include <igl/embree/ambient_occlusion.h>
#include <igl/per_vertex_normals.h>
#include <Eigen/Core>
#include <mex.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

// Parse right hand side arguments for a matlab mex function.
//
// Inputs:
//   nrhs  number of right hand side arguments
//   prhs  pointer to right hand side arguments
// Outputs:
//   V  n by dim list of mesh vertex positions
//   F  m by dim list of mesh face indices
//   P  #P by 3 list of origin points
//   N  #P by 3 list of origin normals
//   num_samples  number of samples
// Throws matlab errors if dimensions are not sane.
void parse_rhs(
  const int nrhs,
  const mxArray *prhs[],
  Eigen::MatrixXd & V,
  Eigen::MatrixXi & F,
  Eigen::MatrixXd & P,
  Eigen::MatrixXd & N,
  int & num_samples)
{
  using namespace std;
  if(nrhs < 5)
  {
    mexErrMsgTxt("nrhs < 5");
  }

  const int dim = mxGetN(prhs[0]);
  if(dim != 3)
  {
    mexErrMsgTxt("Mesh vertex list must be #V by 3 list of vertex positions");
  }
  if(dim != (int)mxGetN(prhs[1]))
  {
   mexErrMsgTxt("Mesh facet size must be 3");
  }
  if(mxGetN(prhs[2]) != dim)
  {
    mexErrMsgTxt("Point list must be #P by 3 list of origin locations");
  }
  if(mxGetN(prhs[3]) != dim)
  {
    mexErrMsgTxt("Normal list must be #P by 3 list of origin normals");
  }
  if(mxGetN(prhs[4]) != 1 || mxGetM(prhs[4]) != 1)
  {
    mexErrMsgTxt("Number of samples must be scalar.");
  }

  V.resize(mxGetM(prhs[0]),mxGetN(prhs[0]));
  copy(mxGetPr(prhs[0]),mxGetPr(prhs[0])+V.size(),V.data());
  F.resize(mxGetM(prhs[1]),mxGetN(prhs[1]));
  copy(mxGetPr(prhs[1]),mxGetPr(prhs[1])+F.size(),F.data());
  F.array() -= 1;
  P.resize(mxGetM(prhs[2]),mxGetN(prhs[2]));
  copy(mxGetPr(prhs[2]),mxGetPr(prhs[2])+P.size(),P.data());
  N.resize(mxGetM(prhs[3]),mxGetN(prhs[3]));
  copy(mxGetPr(prhs[3]),mxGetPr(prhs[3])+N.size(),N.data());
  if(*mxGetPr(prhs[4]) != (int)*mxGetPr(prhs[4]))
  {
    mexErrMsgTxt("Number of samples should be non negative integer.");
  }
  num_samples = (int) *mxGetPr(prhs[4]);
}

void mexFunction(int nlhs, mxArray *plhs[],
    int nrhs, const mxArray *prhs[])
{
  // This is useful for debugging whether Matlab is caching the mex binary
  //mexPrintf("%s %s\n",__TIME__,__DATE__);
  igl::matlab::MexStream mout;
  std::streambuf *outbuf = std::cout.rdbuf(&mout);
  using namespace std;
  using namespace Eigen;
  using namespace igl;
  MatrixXd V,P,N;
  VectorXd S;
  MatrixXi F;
  int num_samples;
  parse_rhs(nrhs,prhs,V,F,P,N,num_samples);
  // Prepare left-hand side
  nlhs = 1;
  igl::embree::ambient_occlusion(V,F,P,N,num_samples,S);
  plhs[0] = mxCreateDoubleMatrix(S.rows(),S.cols(), mxREAL);
  copy(S.data(),S.data()+S.size(),mxGetPr(plhs[0]));
  // Restore the std stream buffer Important!
  std::cout.rdbuf(outbuf);
}


/* Boost.MultiIndex example of use of rearrange facilities.
 *
 * Copyright 2003-2008 Joaquin M Lopez Munoz.
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * See http://www.boost.org/libs/multi_index for library home page.
 */

#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif

#include <boost/config.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/random/binomial_distribution.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

using boost::multi_index_container;
using namespace boost::multi_index;

/* We model a card deck with a random access array containing
 * card numbers (from 0 to 51), supplemented with an additional
 * index which retains the start ordering.
 */

class deck
{
  BOOST_STATIC_CONSTANT(std::size_t,num_cards=52);

  typedef multi_index_container<
    int,
    indexed_by<
      random_access<>, /* base index    */
      random_access<>  /* "start" index */
    >
  >                              container_type;
  container_type cont;

public:
  deck()
  {
    cont.reserve(num_cards);
    get<1>(cont).reserve(num_cards);
    for(std::size_t i=0;i<num_cards;++i)cont.push_back(i);
  }

  typedef container_type::iterator  iterator;
  typedef container_type::size_type size_type;

  iterator  begin()const{return cont.begin();}
  iterator  end()const{return cont.end();}
  size_type size()const{return cont.size();}

  template<typename InputIterator>
  void rearrange(InputIterator it)
  {
    cont.rearrange(it);
  }

  void reset()
  {
    /* simply rearrange the base index like the start index */

    cont.rearrange(get<1>(cont).begin());
  }

  std::size_t position(int i)const
  {
    /* The position of a card in the deck is calculated by locating
     * the card through the start index (which is ordered), projecting
     * to the base index and diffing with the begin position.
     * Resulting complexity: constant.
     */

    return project<0>(cont,get<1>(cont).begin()+i)-cont.begin();
  }

  std::size_t rising_sequences()const
  {
    /* Iterate through all cards and increment the sequence count
     * when the current position is left to the previous.
     * Resulting complexity: O(n), n=num_cards.
     */

    std::size_t s=1;
    std::size_t last_pos=0;

    for(std::size_t i=0;i<num_cards;++i){
      std::size_t pos=position(i);
      if(pos<last_pos)++s;
      last_pos=pos;
    }

    return s;
  }
};

/* A vector of reference_wrappers to deck elements can be used
 * as a view to the deck container.
 * We use a special implicit_reference_wrapper having implicit
 * ctor from its base type, as this simplifies the use of generic
 * techniques on the resulting data structures.
 */

template<typename T>
class implicit_reference_wrapper:public boost::reference_wrapper<T>
{
private:
  typedef boost::reference_wrapper<T> super;
public:
  implicit_reference_wrapper(T& t):super(t){}
};

typedef std::vector<implicit_reference_wrapper<const int> > deck_view;

/* Riffle shuffle is modeled like this: A cut is selected in the deck
 * following a binomial distribution. Then, cards are randomly selected
 * from one packet or the other with probability proportional to
 * packet size.
 */

template<typename RandomAccessIterator,typename OutputIterator>
void riffle_shuffle(
  RandomAccessIterator first,RandomAccessIterator last,
  OutputIterator out)
{
  static boost::mt19937 rnd_gen;

  typedef typename boost::detail::iterator_traits<
    RandomAccessIterator>::difference_type         difference_type;
  typedef boost::binomial_distribution<
    difference_type>                               rnd_cut_select_type;
  typedef boost::uniform_real<>                    rnd_deck_select_type;

  rnd_cut_select_type  cut_select(last-first);
  RandomAccessIterator middle=first+cut_select(rnd_gen);
  difference_type      s0=middle-first;
  difference_type      s1=last-middle;
  rnd_deck_select_type deck_select;

  while(s0!=0&&s1!=0){
    if(deck_select(rnd_gen)<(double)s0/(s0+s1)){
      *out++=*first++;
      --s0;
    }
    else{
      *out++=*middle++;
      --s1;
    }
  }
  std::copy(first,first+s0,out);
  std::copy(middle,middle+s1,out);
}

struct riffle_shuffler
{
  void operator()(deck& d)const
  {
    dv.clear();
    dv.reserve(d.size());
    riffle_shuffle(
      d.begin(),d.end(),std::back_inserter(dv)); /* do the shuffling  */
    d.rearrange(dv.begin());                     /* apply to the deck */
  }

private:
  mutable deck_view dv;
};

/* A truly random shuffle (up to stdlib implementation quality) using
 * std::random_shuffle.
 */

struct random_shuffler
{
  void operator()(deck& d)const
  {
    dv.clear();
    dv.reserve(d.size());
    std::copy(d.begin(),d.end(),std::back_inserter(dv));
    std::random_shuffle(dv.begin(),dv.end()); /* do the shuffling  */
    d.rearrange(dv.begin());                  /* apply to the deck */
  }

private:
  mutable deck_view dv;
};

/* Repeat a given shuffling algorithm repeats_num times
 * and obtain the resulting rising sequences number. Average
 * for tests_num trials.
 */

template<typename Shuffler>
double shuffle_test(
 unsigned int repeats_num,unsigned int tests_num
 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Shuffler))
{
  deck          d;
  Shuffler      sh;
  unsigned long total=0;

  for(unsigned int n=0;n<tests_num;++n){
    for(unsigned m=0;m<repeats_num;++m)sh(d);
    total+=d.rising_sequences();
    d.reset();
  }

  return (double)total/tests_num;
}

int main()
{
  unsigned rifs_num=0;
  unsigned tests_num=0;

  std::cout<<"number of riffle shuffles (vg 5):";
  std::cin>>rifs_num;
  std::cout<<"number of tests (vg 1000):";
  std::cin>>tests_num;

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

  std::cout<<"riffle shuffling\n"
             "  avg number of rising sequences: "
           <<shuffle_test<riffle_shuffler>(rifs_num,tests_num)
           <<std::endl;

  std::cout<<"random shuffling\n"
             "  avg number of rising sequences: "
           <<shuffle_test<random_shuffler>(1,tests_num)
           <<std::endl;

  return 0;
}


#include <benchmark/benchmark.h>

#include <mitrax/operator.hpp>

#include <random>
#include <string>

#include "../../../include/get_binaryop.hpp"

using namespace mitrax;
using namespace mitrax::literals;

template < typename T, typename Op, typename D1, typename D2 >
[[gnu::noinline]]
void bm(benchmark::State& state, Op op, D1 d1, D2 d2){
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_int_distribution< T > dis(
		std::numeric_limits< T >::min(),
		std::numeric_limits< T >::max()
	);

	auto m1 = make_matrix_fn(d1,
		[&dis, &gen](auto, auto){
			return dis(gen);
		});

	auto m2 = make_matrix_fn(d2,
		[&dis, &gen](auto, auto){
			return dis(gen);
		});

	while(state.KeepRunning()){
		auto res = op(m1, m2);
		benchmark::DoNotOptimize(res);
	}
}

#include <boost/hana/tuple.hpp>
#include <boost/hana/for_each.hpp>

namespace init{

	constexpr auto dimensions = boost::hana::make_tuple(
			dim_pair(2_CS, 2_RS),
			dim_pair(4_CS, 2_RS),
			dim_pair(8_CS, 2_RS),
			dim_pair(8_CS, 4_RS),
			dim_pair(8_CS, 8_RS),
			dim_pair(8_CS, 16_RS),
			dim_pair(8_CS, 32_RS),
			dim_pair(8_CS, 64_RS),
			dim_pair(16_CS, 64_RS),
			dim_pair(32_CS, 64_RS),
			dim_pair(64_CS, 64_RS)/*,
			dim_pair(128_CS, 64_RS),
			dim_pair(256_CS, 64_RS),
			dim_pair(256_CS, 128_RS),
			dim_pair(256_CS, 256_RS)*/
		);

	using plus = std::plus<>;
	using multiplies = std::multiplies<>;

}

#include "main.hpp"


/*
 * Copyright (c) 2013-2015 Masahide Kashiwagi (kashi@waseda.jp)
 */

#ifndef ODE_NV_HPP
#define ODE_NV_HPP

// ODE (not verified)

#include <iostream>
#include <cmath>
#include <algorithm>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <kv/psa.hpp>
#include <kv/ode-param.hpp>

#ifndef ODE_FAST
#define ODE_FAST 1
#endif

namespace kv{

namespace ub = boost::numeric::ublas;

template <class T, class F>
void
ode_nv(F f, ub::vector<T>& init, const T& start, T& end, ode_param<T> p = ode_param<T>()) {
	int n = init.size();
	int i, j;

	ub::vector< psa<T> > x, y;
	psa<T> torg;
	psa<T> t;

	T deltat;
	ub::vector<T> result;

	T m;

	T radius, radius_tmp;
	T tolerance;
	int n_rad;

	bool save_mode, save_uh, save_rh;

	m = 1.;
	for (i=0; i<n; i++) {
		using std::abs;
		m = std::max(m, abs(init(i)));
	}
	tolerance = m * p.epsilon;

	x = init;
	torg.v.resize(2);
	torg.v(0) = start; torg.v(1) = 1.;

	save_mode = psa<T>::mode();
	save_uh = psa<T>::use_history();
	save_rh = psa<T>::record_history();
	psa<T>::mode() = 1;
	psa<T>::use_history() = false;
	psa<T>::record_history() = false;
	#if ODE_FAST == 1
	psa<T>::record_history() = true;
	psa<T>::history().clear();
	#endif
	for (j=0; j<p.order; j++) {
		#if ODE_FAST == 1
		if (j == 1) psa<T>::use_history() = true;
		if (j == p.order - 1) psa<T>::record_history() = false;
		#endif
		t = setorder(torg, j);
		y = f(x, t);
		for (i=0; i<n; i++) {
			y(i) = integrate(y(i));
			y(i) = setorder(y(i), j+1);
		}
		x = init + y;
	}

	if (p.autostep) {
		radius = 0.;
		n_rad = 0;
		for (j = p.order; j>=1; j--) {
			m = 0.;
			for (i=0; i<n; i++) {
				using std::abs;
				m = std::max(m, abs(x(i).v(j)));
			}
			if (m == 0.) continue;
			radius_tmp = std::pow((double)m, 1./j);
			if (radius_tmp > radius) radius = radius_tmp;
			n_rad++;
			if (n_rad == 2) break;
		}
		radius = std::pow((double)tolerance, 1./p.order) / radius;
	}

	deltat = end - start;

	if (p.autostep && radius < deltat) {
		end = start + radius;
		deltat = end - start;
	}

	result.resize(n);
	for (i=0; i<n; i++) {
		result(i) = eval(x(i), deltat);
	}

	init = result;

	psa<T>::mode() = save_mode;
	psa<T>::use_history() = save_uh;
	psa<T>::record_history() = save_rh;
}

template <class T, class F>
void
odelong_nv(F f, ub::vector<T>& init, const T& start, const T& end, ode_param<T> p = ode_param<T>()) {

	ub::vector<T> x;
	T t, t1;

	x = init;
	t = start;
	p.set_autostep(true);
	while (1) {
		t1 = end;
		if (t == t1) break;

		ode_nv(f, x, t, t1, p);
		if (p.verbose == 1) {
			std::cout << "t: " << t1 << "\n";
			std::cout << x << "\n";
		}
		t = t1;
	}

	init = x;
}

} // namespace kv

#endif // ODE_NV_HPP


// 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)

// This file was originally part of PyJuggler.

// PyJuggler is (C) Copyright 2002, 2003 by Patrick Hartling
// Distributed under the GNU Lesser General Public License 2.1.  (See
// accompanying file COPYING.txt or http://www.gnu.org/copyleft/lesser.txt)

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

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

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

namespace  {

BOOST_PYTHON_FUNCTION_OVERLOADS(makeDirCosMatrix33_overloads_3_6, gmtlWrappers::makeDirCosMatrix33, 3, 6)
BOOST_PYTHON_FUNCTION_OVERLOADS(makeDirCosMatrix44_overloads_3_6, gmtlWrappers::makeDirCosMatrix44, 3, 6)

}// namespace

// Module ======================================================================
void _Export_gmtl_wrappers_h()
{
    def("makeAxesMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtlWrappers::makeAxesMatrix33);
    def("makeAxesMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtlWrappers::makeAxesMatrix33);
    def("makeAxesMatrix44", (gmtl::Matrix<double,4,4> (*)(const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtlWrappers::makeAxesMatrix44);
    def("makeAxesMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtlWrappers::makeAxesMatrix44);
    def("makeDirCosMatrix33", (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> &))&gmtlWrappers::makeDirCosMatrix33, makeDirCosMatrix33_overloads_3_6());
    def("makeDirCosMatrix33", (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> &))&gmtlWrappers::makeDirCosMatrix33, makeDirCosMatrix33_overloads_3_6());
    def("makeDirCosMatrix44", (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> &))&gmtlWrappers::makeDirCosMatrix44, makeDirCosMatrix44_overloads_3_6());
    def("makeDirCosMatrix44", (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> &))&gmtlWrappers::makeDirCosMatrix44, makeDirCosMatrix44_overloads_3_6());
    def("makeRotEulerAngleXYZ", (gmtl::EulerAngle<float,gmtl::XYZ> (*)(const gmtl::Matrix<float,4,4> &))&gmtlWrappers::makeRotEulerAngleXYZ);
    def("makeRotEulerAngleXYZ", (gmtl::EulerAngle<double,gmtl::XYZ> (*)(const gmtl::Matrix<double,4,4> &))&gmtlWrappers::makeRotEulerAngleXYZ);
    def("makeRotEulerAngleZXY", (gmtl::EulerAngle<float,gmtl::ZXY> (*)(const gmtl::Matrix<float,4,4> &))&gmtlWrappers::makeRotEulerAngleZXY);
    def("makeRotEulerAngleZXY", (gmtl::EulerAngle<double,gmtl::ZXY> (*)(const gmtl::Matrix<double,4,4> &))&gmtlWrappers::makeRotEulerAngleZXY);
    def("makeRotEulerAngleZYX", (gmtl::EulerAngle<float,gmtl::ZYX> (*)(const gmtl::Matrix<float,4,4> &))&gmtlWrappers::makeRotEulerAngleZYX);
    def("makeRotEulerAngleZYX", (gmtl::EulerAngle<double,gmtl::ZYX> (*)(const gmtl::Matrix<double,4,4> &))&gmtlWrappers::makeRotEulerAngleZYX);
    def("makeRotMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::Quat<double> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::Quat<float> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::AxisAngle<float> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::AxisAngle<double> &))&gmtlWrappers::makeRotMatrix33);
    def("makeRotMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::Quat<float> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::EulerAngle<float,gmtl::XYZ> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::EulerAngle<float,gmtl::ZXY> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<double,4,4> (*)(const gmtl::Quat<double> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::EulerAngle<float,gmtl::ZYX> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::AxisAngle<float> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<double,4,4> (*)(const gmtl::AxisAngle<double> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtlWrappers::makeRotMatrix44);
    def("makeRotQuat", (gmtl::Quat<float> (*)(const gmtl::Matrix<float,4,4> &))&gmtlWrappers::makeRotQuat);
    def("makeRotQuat", (gmtl::Quat<double> (*)(const gmtl::Matrix<double,4,4> &))&gmtlWrappers::makeRotQuat);
    def("makeRotQuat", (gmtl::Quat<float> (*)(const gmtl::AxisAngle<float> &))&gmtlWrappers::makeRotQuat);
    def("makeRotQuat", (gmtl::Quat<double> (*)(const gmtl::AxisAngle<double> &))&gmtlWrappers::makeRotQuat);
    def("makeRotQuat", (gmtl::Quat<float> (*)(const gmtl::Vec<float,3> &, const gmtl::Vec<float,3> &))&gmtlWrappers::makeRotQuat);
    def("makeRotQuat", (gmtl::Quat<double> (*)(const gmtl::Vec<double,3> &, const gmtl::Vec<double,3> &))&gmtlWrappers::makeRotQuat);
    def("makeScaleMatrix33", (gmtl::Matrix<double,3,3> (*)(const double&))&gmtlWrappers::makeScaleMatrix33);
    def("makeScaleMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::Vec<double,2> &))&gmtlWrappers::makeScaleMatrix33);
    def("makeScaleMatrix33", (gmtl::Matrix<float,3,3> (*)(const float&))&gmtlWrappers::makeScaleMatrix33);
    def("makeScaleMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::Vec<double,3> &))&gmtlWrappers::makeScaleMatrix33);
    def("makeScaleMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::Vec<float,2> &))&gmtlWrappers::makeScaleMatrix33);
    def("makeScaleMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::Vec<float,3> &))&gmtlWrappers::makeScaleMatrix33);
    def("makeScaleMatrix44", (gmtl::Matrix<double,4,4> (*)(const double&))&gmtlWrappers::makeScaleMatrix44);
    def("makeScaleMatrix44", (gmtl::Matrix<double,4,4> (*)(const gmtl::Vec<double,4> &))&gmtlWrappers::makeScaleMatrix44);
    def("makeScaleMatrix44", (gmtl::Matrix<float,4,4> (*)(const float&))&gmtlWrappers::makeScaleMatrix44);
    def("makeScaleMatrix44", (gmtl::Matrix<double,4,4> (*)(const gmtl::Vec<double,3> &))&gmtlWrappers::makeScaleMatrix44);
    def("makeScaleMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::Vec<float,4> &))&gmtlWrappers::makeScaleMatrix44);
    def("makeScaleMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::Vec<float,3> &))&gmtlWrappers::makeScaleMatrix44);
    def("makeTransMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::Vec<double,2> &))&gmtlWrappers::makeTransMatrix33);
    def("makeTransMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::Vec<float,2> &))&gmtlWrappers::makeTransMatrix33);
    def("makeTransMatrix33", (gmtl::Matrix<double,3,3> (*)(const gmtl::Vec<double,3> &))&gmtlWrappers::makeTransMatrix33);
    def("makeTransMatrix33", (gmtl::Matrix<float,3,3> (*)(const gmtl::Vec<float,3> &))&gmtlWrappers::makeTransMatrix33);
    def("makeTransMatrix44", (gmtl::Matrix<double,4,4> (*)(const gmtl::Vec<double,3> &))&gmtlWrappers::makeTransMatrix44);
    def("makeTransMatrix44", (gmtl::Matrix<float,4,4> (*)(const gmtl::Vec<float,3> &))&gmtlWrappers::makeTransMatrix44);
    def("makeTransVec3", (gmtl::Vec<double,3> (*)(const gmtl::Matrix<double,4,4> &))&gmtlWrappers::makeTransVec3);
    def("makeTransVec3", (gmtl::Vec<float,3> (*)(const gmtl::Matrix<float,4,4> &))&gmtlWrappers::makeTransVec3);
    def("makeTransVec3", (gmtl::Vec<double,3> (*)(const gmtl::Matrix<double,3,3> &))&gmtlWrappers::makeTransVec3);
    def("makeTransVec3", (gmtl::Vec<float,3> (*)(const gmtl::Matrix<float,3,3> &))&gmtlWrappers::makeTransVec3);
    def("makeTransVec2", (gmtl::Vec<double,2> (*)(const gmtl::Matrix<double,3,3> &))&gmtlWrappers::makeTransVec2);
    def("makeTransVec2", (gmtl::Vec<float,2> (*)(const gmtl::Matrix<float,3,3> &))&gmtlWrappers::makeTransVec2);
    def("makeTransPoint3", (gmtl::Point<double,3> (*)(const gmtl::Matrix<double,4,4> &))&gmtlWrappers::makeTransPoint3);
    def("makeTransPoint3", (gmtl::Point<float,3> (*)(const gmtl::Matrix<float,4,4> &))&gmtlWrappers::makeTransPoint3);
}


#define PCL_NO_PRECOMPILE
#include <vector>
#include <iostream>
#include <Eigen/Core>
#include <pcl/io/pcd_io.h>
#include <pcl/common/transforms.h>
#include <pcl/registration/transforms.h>
#include <pcl/pcl_macros.h>
#include <pcl/console/parse.h>

int angle_ (30);
float division_ (6.0f);
float size_ (1.0f);
int name_number_ (0);

std::string model_filename_;

void
showHelp (char *filename)
{
  std::cout << std::endl;
  std::cout << "***************************************************************************" << std::endl;
  std::cout << "*                                                                         *" << std::endl;
  std::cout << "*             Dataset creation - Usage Guide              *" << std::endl;
  std::cout << "*                                                                         *" << std::endl;
  std::cout << "***************************************************************************" << std::endl << std::endl;
  std::cout << "Usage: " << filename << " model_filename.pcd [Options]" << std::endl << std::endl;
  std::cout << "Options:" << std::endl;
  std::cout << "     --angle val:          rotation angle (degree) (default :"<< angle_ << ")"  << std::endl;
  std::cout << "       every 15 from -90 to 90, for example: -90, -75, -60, -45, etc."  << std::endl;
  std::cout << "     --size val:               size (default :" << size_ << ")" << std::endl;
  std::cout << "       it's better from 0.5 to -2.0 "  << std::endl;
  std::cout << "     --name_number val:        name_number (default :" << name_number_ << ")" << std::endl;
  std::cout << "       The name is : training_model_[name_number].pcd"  << std::endl;
}

void transform_dataset (pcl::PointCloud<pcl::PointXYZ>::Ptr &points1,
                        pcl::PointCloud<pcl::PointXYZ>::Ptr &points1_trans,
                        float & division_,
                        float & size_,
                        int & name_number_)
{
  // to rotate the model grounded //
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud_ (new pcl::PointCloud<pcl::PointXYZ> ());
  Eigen::Affine3f transform_1 = Eigen::Affine3f::Identity();

  Eigen::Matrix3f angle;
  angle = Eigen::AngleAxisf(M_PI/2, Eigen::Vector3f::UnitX())
          * Eigen::AngleAxisf(M_PI,  Eigen::Vector3f::UnitY())
          * Eigen::AngleAxisf(M_PI/2, Eigen::Vector3f::UnitZ());

  transform_1.translation() << 108, 234, 2105;
  transform_1.rotate (angle);
  transform_1.scale (150.0);
  pcl::transformPointCloud (*points1, *transformed_cloud_, transform_1);

  ////// do not modify above //////

  Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();

  Eigen::Matrix3f angle_set;
  angle_set = Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX())
              * Eigen::AngleAxisf(M_PI/division_,  Eigen::Vector3f::UnitY())
              * Eigen::AngleAxisf(0, Eigen::Vector3f::UnitZ());

  transform_2.rotate (angle_set);
  transform_2.scale (size_);
  pcl::transformPointCloud (*transformed_cloud_, *points1_trans, transform_2);

  std::stringstream ss1;
  ss1 << "training_model_"<<name_number_<<".pcd";

  pcl::io::savePCDFileASCII(ss1.str (), *points1_trans);
  std::cout << "save No."<<name_number_<< " to the PCD."<< std::endl;
}

void
parseCommandLine (int argc, char *argv[])
{
  //Show help
  if (pcl::console::find_switch (argc, argv, "-h"))
  {
    showHelp (argv[0]);
    exit (0);
  }

  //Model & scene filenames
  std::vector<int> filenames;
  filenames = pcl::console::parse_file_extension_argument (argc, argv, ".pcd");
  if (filenames.size () != 1)
  {
    std::cout << "Filenames missing.\n";
    showHelp (argv[0]);
    exit (-1);
  }

  model_filename_ = argv[filenames[0]];

  //General parameters
  pcl::console::parse_argument (argc, argv, "--angle", angle_);
  pcl::console::parse_argument (argc, argv, "--size", size_);
  pcl::console::parse_argument (argc, argv, "--name_number", name_number_);

  if (angle_ == -90 )  division_ = 2;
  else if (angle_ == -75 )  division_ = 2.4;
  else if (angle_ == -60 )  division_ = 3;
  else if (angle_ == -45 )  division_ = 4;
  else if (angle_ == -30 )  division_ = 6;
  else if (angle_ == -15 )  division_ = 12;
  else if (angle_ == 0 )  division_ = 10000;
  else if (angle_ == 15 )  division_ = -12;
  else if (angle_ == 30 )  division_ = -6;
  else if (angle_ == 45 )  division_ = -4;
  else if (angle_ == 60 )  division_ = -3;
  else if (angle_ == 75 )  division_ = -2.4;
  else if (angle_ == 90 )  division_ = -2;
  else division_ = 10000;
}

int main (int argc, char *argv[])
{

  parseCommandLine (argc, argv);
  // Create some new point clouds to hold our data
  pcl::PointCloud<pcl::PointXYZ>::Ptr points1 (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr points1_move (new pcl::PointCloud<pcl::PointXYZ>);

  //  Load clouds
  if (pcl::io::loadPCDFile (model_filename_, *points1) < 0)
  {
    std::cout << "Error loading model cloud." << std::endl;
    showHelp (argv[0]);
    return (-1);
  }

  std::cout << "load " << model_filename_ << " successfully" << std::endl;
  transform_dataset(points1, points1_move, division_, size_, name_number_);

  return (0);
}


#include<iostream>
#include <Eigen/Eigenvalues>
#include"numerics.hpp"
#include"reddm.hpp"
#include"tpoperators.hpp"
#include "files.hpp"
#include"FTLanczos.hpp"
#include<omp.h>
#include <boost/program_options.hpp>
using namespace Many_Body;
using Mat= Operators::Mat;

using namespace boost::program_options;
int main(int argc, char *argv[])
{

  int M{};
  int L{};
  double t0{};
  double omega{};
  double gamma{};
  bool PB{0};
   int runs={};
   int Ldim={};
    double T{};
    double err{};
  std::string sLdim={};
  std::string sruns={};
std::string sT{};
std::string sM{};
std::string sL{};
std::string st0{};
std::string somega{};
std::string sgamma{};
std::string sPB{};
 std::string serr{};
 std::string filename="ompFTLM";

  try
  {
    options_description desc{"Options"};
    desc.add_options()
      ("help,h", "Help screen")
      ("L", value(&L)->default_value(4), "L")
      ("M", value(&M)->default_value(2), "M")
      ("r", value(&runs)->default_value(20), "r")
      ("Ld", value(&Ldim)->default_value(20), "Ld")
      ("t0", value(&t0)->default_value(1.), "t0")
      ("gam", value(&gamma)->default_value(1.), "gamma")
      ("omg", value(&omega)->default_value(1.), "omega")
      ("T", value(&T)->default_value(1.), "T")
      ("pb", value(&PB)->default_value(false), "PB")
      ("err", boost::program_options::value(&err)->default_value(1E-9), "err");
    boost::program_options::variables_map vm;
    boost::program_options::store(parse_command_line(argc, argv, desc), vm);
    boost::program_options::notify(vm);
 if (vm.count("help"))
      {std::cout << desc << '\n'; return 0;}
    else{
      if (vm.count("L"))
      {
  	std::cout << "L: " << vm["L"].as<int>() << '\n';
	sL="L"+std::to_string(vm["L"].as<int>());
	filename+=sL;

      }
     if (vm.count("M"))
      {
  	std::cout << "M: " << vm["M"].as<int>() << '\n';
	sM="M"+std::to_string(vm["M"].as<int>());
	filename+=sM;

      }
     if (vm.count("r"))
      {
  	std::cout << "runs: " << vm["r"].as<int>() << '\n';
	sruns="r"+std::to_string(vm["r"].as<int>());
	filename+=sruns;

      }
if (vm.count("Ld"))
      {
  	std::cout << "lanczos dim: " << vm["Ld"].as<int>() << '\n';

      }
      if (vm.count("t"))
      {
      	std::cout << "t0: " << vm["t"].as<double>() << '\n';
      	      	st0="t0"+std::to_string(vm["t0"].as<double>()).substr(0, 3);
      	filename+=st0;
      }
       if (vm.count("omg"))
      {
      	std::cout << "omega: " << vm["omg"].as<double>() << '\n';
      	      	somega="omg"+std::to_string(vm["omg"].as<double>()).substr(0, 3);
      	filename+=somega;
      }
       if (vm.count("gam"))
      {
      	std::cout << "gamma: " << vm["gam"].as<double>() << '\n';
      	sgamma="gam"+std::to_string(vm["gam"].as<double>()).substr(0, 3);
      	filename+=sgamma;
      }
       if (vm.count("T"))
      {
      	std::cout << "T: " << vm["T"].as<double>() << '\n';
      }if (vm.count("pb"))
      {
      	std::cout << "PB: " << vm["pb"].as<bool>() << '\n';
      	sPB="PB"+std::to_string(vm["pb"].as<bool>());
      	filename+=sPB;
      }
      		     if (vm.count("err"))
      {      std::cout << "error: " << vm["err"].as<double>() << '\n';
      	 std::stringstream ss;
      	 ss<<vm["err"].as<double>();
      	 serr="err"+ss.str();
      	filename+=serr;
      }
    }
  }
  catch (const error &ex)
  {
    std::cerr << ex.what() << '\n';
    return 0;
  }

     using HolsteinBasis= TensorProduct<ElectronBasis, PhononBasis>;

  filename+=".bin";
     std::vector<double> Tem;
     std::vector<double> beta;
     for(int i=1; i<11; i++)
       {
	 	  Tem.push_back((0.1*i));
	  beta.push_back(1./(0.1*i));
       }

    Mat H;
    Mat N;
    Mat EK;
    Mat X;
  std::vector<Mat> obs;
  {

    ElectronBasis e( L, 1);
  PhononBasis ph(L, M);
  HolsteinBasis TP(e, ph);
  std::cout<< TP.dim<<std::endl;
        Mat E1=Operators::EKinOperatorL(TP, e, t0,PB);
       Mat Ebdag=Operators::NBosonCOperator(TP, ph, gamma, PB);
       Mat Eb=Operators::NBosonDOperator(TP, ph, gamma, PB);
      Mat Eph=Operators::NumberOperator(TP, ph, omega,  PB);

      Eigen::VectorXd eigenVals(TP.dim);
       H=E1+Eb+Eph+Ebdag;
        N=Eph/omega;
	EK=E1;
	X=(Ebdag+Eb)/gamma;
       obs.push_back(H);
       obs.push_back(N);
       obs.push_back(E1);
       obs.push_back(X);
  }

     Eigen::MatrixXd Astot=Eigen::MatrixXd::Zero(beta.size(), obs.size());
Eigen::VectorXd Zstot=Eigen::VectorXd::Zero(beta.size());
#pragma omp parallel
  {

#pragma omp for
 for(int i=0; i<runs; i++)
   {
     //     std::cout<< " om num thread " <<omp_get_thread_num()<<std::endl;
     auto [Observables, SUMs]=calculate_lanczFT(obs[0], obs, beta, Ldim, err);

	#pragma omp critical
	{
	  Astot+=Observables;
	  Zstot+=SUMs;
	}
	//	std::cout << " got meanZ "<< SUMs.mean() << std::endl;

   }
  }

  std::cout<< "Astot  "<<std::endl<< Astot<< std::endl;
  for(int i=0; i<beta.size(); i++)
    {
      Astot.row(i)/=Zstot(i);
  	   std::cout<<" T "<< 1./beta[i] << "  "<<Astot(i, 0)<<" SUM "<< Astot(i, 1)+Astot(i, 2)+Astot(i, 3)*gamma<<std::endl;
    }
  bin_write("E"+filename, Eigen::VectorXd(Astot.col(0)));
  bin_write("Nph"+filename,  Eigen::VectorXd(Astot.col(1)));
  bin_write("EK"+filename, Eigen::VectorXd(Astot.col(2)));
  bin_write("nX"+filename, Eigen::VectorXd(Astot.col(3)));
  bin_write("temp"+filename, Tem);

  return 0;
}