//---------------------------------------------------------------------------//
// Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
// Copyright (c) 2021 Ilias Khairullin <ilias@nil.foundation>
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//---------------------------------------------------------------------------//

#ifndef CRYPTO3_ACCUMULATORS_MAC_HPP
#define CRYPTO3_ACCUMULATORS_MAC_HPP

#include <boost/parameter/value_type.hpp>

#include <boost/accumulators/framework/accumulator_base.hpp>
#include <boost/accumulators/framework/extractor.hpp>
#include <boost/accumulators/framework/depends_on.hpp>
#include <boost/accumulators/framework/parameters/sample.hpp>

#include <nil/crypto3/mac/accumulators/parameters/iterator_last.hpp>

namespace nil {
    namespace crypto3 {
        namespace accumulators {
            namespace impl {
                template<typename ProcessingPolicy>
                struct mac_impl : boost::accumulators::accumulator_base {
                protected:
                    typedef ProcessingPolicy processing_policy;
                    typedef typename processing_policy::mac_type mac_type;
                    typedef typename processing_policy::key_type key_type;
                    typedef typename processing_policy::internal_accumulator_type internal_accumulator_type;

                public:
                    typedef typename processing_policy::result_type result_type;

                    template<typename Args>
                    mac_impl(const Args &args) : key(args[boost::accumulators::sample]) {
                        processing_policy::init_accumulator(key, acc);
                    }

                    template<typename ArgumentPack>
                    inline void operator()(const ArgumentPack &args) {
                        resolve_type(args[boost::accumulators::sample],
                                     args[::nil::crypto3::accumulators::iterator_last | nullptr]);
                    }

                    inline result_type result(boost::accumulators::dont_care) const {
                        return processing_policy::process(key, acc);
                    }

                protected:
                    template<typename InputRange, typename InputIterator>
                    inline void resolve_type(const InputRange &range, InputIterator) {
                        processing_policy::update(key, acc, range);
                    }

                    template<typename InputIterator>
                    inline void resolve_type(InputIterator first, InputIterator second) {
                        processing_policy::update(key, acc, first, second);
                    }

                    key_type key;
                    mutable internal_accumulator_type acc;
                };
            }    // namespace impl

            namespace tag {
                template<typename ProcessingPolicy>
                struct mac : boost::accumulators::depends_on<> {
                    typedef ProcessingPolicy processing_policy;

                    /// INTERNAL ONLY
                    ///

                    typedef boost::mpl::always<accumulators::impl::mac_impl<processing_policy>> impl;
                };
            }    // namespace tag

            namespace extract {
                template<typename ProcessingPolicy, typename AccumulatorSet>
                typename boost::mpl::apply<AccumulatorSet, tag::mac<ProcessingPolicy>>::type::result_type
                    mac(const AccumulatorSet &acc) {
                    return boost::accumulators::extract_result<tag::mac<ProcessingPolicy>>(acc);
                }
            }    // namespace extract
        }        // namespace accumulators
    }            // namespace crypto3
}    // namespace nil

#endif    // CRYPTO3_ACCUMULATORS_MAC_HPP


#include <string>
#include <boost/graph/adjacency_list.hpp>

inline std::vector<std::vector<char const*>> supported_formats() {
    return {{"DOT",     "(.gv, .dot)"},
            {"GraphML", "(.graphml, .xml)"}};
}

struct Feature;

typedef boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::undirectedS,
    Feature>
  HeightMap;

typedef HeightMap::vertex_descriptor Location;

typedef HeightMap::vertices_size_type HeightMapSize;

struct Feature : FeatureBase {
    Location parent;
    std::string id;
};

inline HeightMapSize num_locations(HeightMap const& m) {
    return boost::num_vertices(m);
}

inline boost::iterator_range<boost::graph_traits<HeightMap>::vertex_iterator>
locations(HeightMap const& m) {
    return boost::make_iterator_range(boost::vertices(m));
}

inline boost::iterator_range<boost::graph_traits<HeightMap>::adjacency_iterator>
adjacent_locations(Location l, HeightMap const& m) {
    return boost::make_iterator_range(boost::adjacent_vertices(l, m));
}

inline std::string get_name(Location l, HeightMap const& m) {
    return m[l].id;
}


//#include <ndt_fuser.h>
#include <ndt_fuser/ndt_fuser_hmt.h>
#include <ndt_map/ndt_conversions.h>
#include <ndt_map/NDTMapMsg.h>
#include <ndt_map/ndt_conversions.h>
#include "ndt_fuser/ndt_fuser_ros_wrappers/ros_fuser_init.hpp"

#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>

#include <pcl_conversions/pcl_conversions.h>
#include "pcl/point_cloud.h"
#include "sensor_msgs/PointCloud2.h"
#include "pcl/io/pcd_io.h"
#include <cstdio>
#include <Eigen/Eigen>
#include <fstream>
#include "message_filters/subscriber.h"
#include "tf/message_filter.h"
#include <tf/transform_broadcaster.h>
#include <tf_conversions/tf_eigen.h>

#include <boost/circular_buffer.hpp>
#include <laser_geometry/laser_geometry.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/PoseStamped.h>

#include <visualization_msgs/MarkerArray.h>
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <std_srvs/Empty.h>
#include <cstdio>
#include <Eigen/Geometry>
#include <boost/foreach.hpp>

#include "eigen_conversions/eigen_msg.h"
class view_bag {

protected:
  // Our NodeHandle
  ros::NodeHandle nh_;

  ros::Subscriber *odom_sub_;
  ros::Subscriber *gt_sub;

  ros::Publisher *gt_pub,*odom_pub;
  nav_msgs::Odometry gt_pose_msg,odom_pose_msg;
  std::string odometry_topic="",gt_topic="";
  Eigen::Affine3d Todom,Todom_prev,Todom_init;
  Eigen::Affine3d Tgt,Tgt_prev,Tgt_init;
  bool init_gt_set=false;
  bool first_odom_set=false;
  int t_merge_frames=1;

public:
  // Constructor
  view_bag(ros::NodeHandle param_nh)
  {

    param_nh.param<std::string>("odometry_topic",odometry_topic,"/vmc_navserver/odom");
    ///if we want to compare to a ground truth topic;
    param_nh.param<std::string>("gt_topic",gt_topic,"/vmc_navserver/state");
    param_nh.param<int>("t_merge_frames",t_merge_frames,1);
    odom_sub_=new ros::Subscriber();
    gt_sub=new ros::Subscriber();
    gt_pub=new ros::Publisher();
    odom_pub=new ros::Publisher();
    *odom_sub_ = nh_.subscribe<nav_msgs::Odometry>(odometry_topic,10,&view_bag::odom_callback, this);
    *gt_sub = nh_.subscribe<nav_msgs::Odometry>(gt_topic,10,&view_bag::gt_callback, this);
    *odom_pub=param_nh.advertise<nav_msgs::Odometry>("odom_aligned_with_gt",100);
    *gt_pub=param_nh.advertise<nav_msgs::Odometry>("gt_odom",100);
    gt_pose_msg.header.frame_id="/world";
    odom_pose_msg.header.frame_id="/world";
  }

  // Callback
  void gt_callback(const nav_msgs::Odometry::ConstPtr& msg_in)
  {
    static unsigned int counter=0;
    Eigen::Quaterniond qd;
    Eigen::Affine3d gt_pose;

    qd.x() = msg_in->pose.pose.orientation.x;
    qd.y() = msg_in->pose.pose.orientation.y;
    qd.z() = msg_in->pose.pose.orientation.z;
    qd.w() = msg_in->pose.pose.orientation.w;

    gt_pose = Eigen::Translation3d (msg_in->pose.pose.position.x,
                                    msg_in->pose.pose.position.y,msg_in->pose.pose.position.z) * qd;

    if(!init_gt_set && counter==t_merge_frames) {
      Tgt_init = gt_pose;
      ROS_INFO("Set initial pose from GT track");
      init_gt_set = true;
    }

    gt_pose_msg.header.stamp=msg_in->header.stamp;
    tf::poseEigenToMsg(gt_pose, gt_pose_msg.pose.pose);
    gt_pub->publish(gt_pose_msg);
    counter++;
  }
  void odom_callback(const nav_msgs::Odometry::ConstPtr& msg_in)
  {
    Eigen::Quaterniond qd;

    qd.x() = msg_in->pose.pose.orientation.x;
    qd.y() = msg_in->pose.pose.orientation.y;
    qd.z() = msg_in->pose.pose.orientation.z;
    qd.w() = msg_in->pose.pose.orientation.w;

    Todom = Eigen::Translation3d (msg_in->pose.pose.position.x,
                                  msg_in->pose.pose.position.y,msg_in->pose.pose.position.z) * qd;
    std::cout<<"odom:"<<Todom.translation().transpose()<<std::endl;
    if(!first_odom_set && init_gt_set) {
      Todom_init = Todom;
      ROS_INFO("Set initial odom pose");
      first_odom_set = true;
    }
    if(init_gt_set){
      std::cout<<"Todom_init: "<<Todom_init.translation()<<std::endl;
      std::cout<<"Tgt_init: "<<Tgt_init.translation()<<std::endl;
      Eigen::Affine3d odom_pose_in_gt_frame=Tgt_init*Todom_init.inverse()*Todom;
      tf::poseEigenToMsg(odom_pose_in_gt_frame, odom_pose_msg.pose.pose);
      odom_pose_msg.header.stamp=msg_in->header.stamp;
      odom_pub->publish(odom_pose_msg);
    }
  }

};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "ndt_fuser_node");
  ros::NodeHandle param("~");
  view_bag t(param);
  while(ros::ok()){
    ros::spinOnce();
  }

  return 0;
}


// Copyright 2005 The Trustees of Indiana University.

// Use, modification and distribution is subject to 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)

//  Authors: Douglas Gregor
//           Andrew Lumsdaine
#include "graph_types.hpp"
#include <boost/graph/fruchterman_reingold.hpp>
#include <boost/graph/random_layout.hpp>
#include <boost/graph/python/point2d.hpp>
#include <boost/graph/python/point3d.hpp>
#include <boost/graph/python/iterator.hpp>
#include <boost/random/linear_congruential.hpp>
#include <ctime>
#include <boost/python.hpp>

namespace boost { namespace graph { namespace python {

template<typename F, typename Result = typename F::result_type>
struct python_or_functor
{
  typedef Result result_type;

  explicit python_or_functor(boost::python::object callable, const F& f = F())
    : callable(callable), f(f), registered_apply_force(false) { }

  // For cooling
  result_type operator()()
  {
    using boost::python::object;
    using boost::python::extract;
    if (callable != object()) return extract<result_type>(callable());
    else return f();
  }

  // For force pairs
  template<typename Graph, typename ApplyForce>
  void operator()(const Graph& g, ApplyForce apply_force)
  {
    using boost::python::extract;
    using boost::python::object;
    using boost::graph::python::detail::type_already_registered;

    if (callable != object()) {
      if (!registered_apply_force && !type_already_registered<ApplyForce>())
        {
          using boost::python::class_;
          using boost::python::no_init;
          typedef typename graph_traits<Graph>::vertex_descriptor
            vertex_descriptor;

          typedef void (ApplyForce::* apply_force_call_t)(vertex_descriptor,
                                                          vertex_descriptor);

          class_<ApplyForce>("ApplyForce", no_init)
            .def("__call__", (apply_force_call_t)&ApplyForce::operator());

          registered_apply_force = true;
        }

      if (extract<bool>(callable(ref(g), apply_force)))
        f(g, apply_force);
    }
    else f(g, apply_force);
  }

  // For the attractive_force
  template<typename Graph>
  result_type
  operator()(typename graph_traits<Graph>::edge_descriptor e,
             float k, float dist, const Graph& g) const
  {
    using boost::python::object;
    using boost::python::extract;
    if (callable != object())
      return extract<result_type>(callable(e, k, dist, ref(g)));
    else
      return f(e, k, dist, g);
  }

  // For the repulsive_force
  template<typename Graph>
  result_type
  operator()(typename graph_traits<Graph>::vertex_descriptor u,
             typename graph_traits<Graph>::vertex_descriptor v,
             float k, float dist, const Graph& g) const
  {
    using boost::python::object;
    using boost::python::extract;
    if (callable != object())
      return extract<result_type>(callable(u, v, k, dist, ref(g)));
    else return f(u, v, k, dist, g);
  }

private:
  boost::python::object callable;
  F f;
  bool registered_apply_force;
};

template<typename Graph, typename Point>
void
fruchterman_reingold_force_directed_layout
  (Graph& g,
   vector_property_map
     <Point, typename property_map<Graph, vertex_index_t>::const_type>& pos,
   const Point& origin,
   const Point& extent,
   boost::python::object attractive_force,
   boost::python::object repulsive_force,
   boost::python::object force_pairs,
   boost::python::object cooling,
   bool progressive)
{
  using boost::python::object;

  typedef typename property_map<Graph, vertex_index_t>::const_type
    VertexIndexMap;
  typedef vector_property_map<Point, VertexIndexMap> PositionMap;

  // Build the displacement map.
  typedef vector_property_map<Point, VertexIndexMap> DisplacementMap;
  DisplacementMap displacement(num_vertices(g), get(vertex_index, g));

  if (!progressive) {
    minstd_rand gen(std::time(0));
    random_graph_layout(g, pos, origin, extent, gen);
  }

  if (attractive_force != object() || repulsive_force != object()
      || force_pairs != object() || cooling != object()) {
    python_or_functor<square_distance_attractive_force, float>
      fa(attractive_force);
    python_or_functor<square_distance_repulsive_force, float>
      fr(repulsive_force);
    python_or_functor<grid_force_pairs<PositionMap>, void>
      fp(force_pairs, make_grid_force_pairs(origin, extent, pos, g));
    python_or_functor<linear_cooling<float> > local_cool(cooling, 100);

    boost::fruchterman_reingold_force_directed_layout
      (g, pos, origin, extent, fa, fr, fp, local_cool, displacement);

  } else {
    boost::fruchterman_reingold_force_directed_layout
      (g, pos, origin, extent,
       square_distance_attractive_force(),
       square_distance_repulsive_force(),
       make_grid_force_pairs(origin, extent, pos, g),
       linear_cooling<float>(100), displacement);
  }
}

void export_fruchterman_reingold_force_directed_layout()
{
  using boost::python::arg;
  using boost::python::class_;
  using boost::python::def;
  using boost::python::init;
  using boost::python::no_init;
  using boost::python::object;

#define UNDIRECTED_GRAPH(Name,Type)                             \
  def("fruchterman_reingold_force_directed_layout",             \
      &fruchterman_reingold_force_directed_layout<Type, point2d>, \
      (arg("graph"),                                            \
       arg("position"),                                         \
       arg("origin") = point2d(),                               \
       arg("extent") = point2d(500, 500),                       \
       arg("attractive_force") = object(),                      \
       arg("repulsive_force") = object(),                       \
       arg("force_pairs") = object(),                           \
       arg("cooling") = object(),                               \
       arg("progressive") = false));                            \
  def("fruchterman_reingold_force_directed_layout",             \
      &fruchterman_reingold_force_directed_layout<Type, point3d>, \
      (arg("graph"),                                            \
       arg("position"),                                         \
       arg("origin") = point3d(),                               \
       arg("extent") = point3d(500, 500, 500),                  \
       arg("attractive_force") = object(),                      \
       arg("repulsive_force") = object(),                       \
       arg("force_pairs") = object(),                           \
       arg("cooling") = object(),                               \
       arg("progressive") = false));
#include "graphs.hpp"
}

} } } // end namespace boost::graph::python


//
// HOGpp - Fast histogram of oriented gradients computation using integral
// histograms
//
// Copyright 2021 Sergiu Deitsch <sergiu.deitsch@gmail.com>
//
// 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.
//

#define BOOST_TEST_MODULE hogpp

#include <hogpp/integralhogdescriptor.hpp>

#include <boost/mpl/list.hpp>
#include <boost/test/included/unit_test.hpp>

using Scalars = boost::mpl::list<float, double, long double>;

BOOST_AUTO_TEST_CASE_TEMPLATE(empty, Scalar, Scalars)
{
    BOOST_TEST(hogpp::IntegralHOGDescriptor<Scalar>{}.isEmpty());
    BOOST_TEST(hogpp::IntegralHOGDescriptor<Scalar>{}.features().size() == 0);
    BOOST_TEST(
        hogpp::IntegralHOGDescriptor<Scalar>{}.features(cv::Rect{}).size() ==
        0);
    BOOST_TEST(hogpp::IntegralHOGDescriptor<Scalar>{}.histogram().size() == 0);
}

BOOST_AUTO_TEST_CASE_TEMPLATE(void_gradient, Scalar, Scalars)
{
    hogpp::IntegralHOGDescriptor<Scalar, void> d;

    Eigen::Tensor<Scalar, 3> dxs;
    Eigen::Tensor<Scalar, 3> dys;

    d.compute(dxs, dys, nullptr);

    BOOST_TEST(d.isEmpty());
}


/****************************************************************************/
/*                                                                          */
/* Original algorithm: http://ivrg.epfl.ch/research/superpixels             */
/* Original OpenCV implementation: http://github.com/PSMM/SLIC-Superpixels  */
/*                                                                          */
/* Paper: "Optimizing Superpixel Clustering for Real-Time                   */
/*         Egocentric-Vision Applications"                                  */
/*        http://www.isip40.it/resources/papers/2015/SPL_Pietro.pdf         */
/*                                                                          */
/****************************************************************************/

#include "SLIC.h"

/* OpenCV libraries for video and image
   elaborations. */
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv2/imgproc/imgproc.hpp>

/* Chrono library for measuring time
   performances. */
#include <boost/chrono.hpp>

#include <vector>

using namespace std;
using namespace cv;

/* Function performing SLIC algorithm on a video sequence. */
int VideoSLIC(
	VideoCapture&        capturedVideo,
	unsigned             superpixelNumber,
	unsigned             spatialDistanceWeight,
	bool                 connectedFrames,
	SLICElaborationMode  SLICMode,
	unsigned             iterationNumber,
	double               errorThreshold,
	VideoElaborationMode videoMode,
	unsigned             keyFramesRatio,
	double               GaussianStdDev
	);

int main(int argc, char *argv[])
{
	/* Video source location. */
	const string videoLocation = (argc == 2) ? argv[1] : "C:\\Users\\Claudiu\\Desktop\\Video Data Set\\EDSH1.avi";

	/* Output window name. */
	const string windowName = "VideoSLIC";

	/* Declare a container for the video and try to import the video from
	   a specific location. */
	VideoCapture capturedVideo(videoLocation);

	/* Check if the video was correctly imported into the program. */
	if (capturedVideo.isOpened() == false)
	{
		/* Send an error message and then close the program if there was
		   an error with the video capture. */
		cout << "\nSorry, there was an error with video capturing.\n";
		return -1;
	}

	/* SLIC algorithm parameters. */
	unsigned spatialDistanceWeight = 30;
	unsigned superpixelNumber      = 1000;
	/* There's no need to set both iterationNumber and errorThreshold,
	   it's enough to set only one of them and set the other one to zero.
	   Which of the two values will be used for video elaboration depends
	   on the value of the field SLICMode. */
	unsigned iterationNumber       = 10;
	double   errorThreshold        = 0.25;

	/* Compute SLIC algorithm step for later use in generating Gaussian noise. */
	const unsigned videoWidth  = static_cast<unsigned>(capturedVideo.get(CV_CAP_PROP_FRAME_WIDTH));
	const unsigned videoHeight = static_cast<unsigned>(capturedVideo.get(CV_CAP_PROP_FRAME_HEIGHT));
	unsigned       stepSLIC    = static_cast<unsigned>(sqrt((videoHeight * videoWidth) / superpixelNumber) + 0.5);

	/* Parameters used when applying SLIC algorithm to video sequences. */
	/* Decide if frames are to be processed independently or the result
	   obtained after elaborating one frame should be used to initialize
	   the next frame (more details are found in the paper). */
	bool                 connectedFrames = true;
	SLICElaborationMode  SLICMode        = ERROR_THRESHOLD;
	VideoElaborationMode VideoMode       = KEY_FRAMES_NOISE;
	/* Use a key frame every keyFramesRatio frames. */
	unsigned             keyFramesRatio  = 30;
	/* Standard deviation of the Gaussian noise. */
	double               GaussianStdDev  = static_cast<double>(stepSLIC / 5);

	/* Call function to perform SLIC algorithm operations on video. */
	VideoSLIC(
		capturedVideo,
		superpixelNumber,
		spatialDistanceWeight,
		connectedFrames,
		SLICMode,
		iterationNumber,
		errorThreshold,
		VideoMode,
		keyFramesRatio,
		GaussianStdDev);

	return 0;
}

int VideoSLIC(
	VideoCapture&        capturedVideo,
	unsigned             superpixelNumber,
	unsigned             spatialDistanceWeight,
	bool                 connectedFrames,
	SLICElaborationMode  SLICMode,
	unsigned             iterationNumber,
	double               errorThreshold,
	VideoElaborationMode videoMode,
	unsigned             keyFramesRatio,
	double               GaussianStdDev
	)
{
	/* Get video width and height. */
	const unsigned videoWidth  = static_cast<unsigned>(capturedVideo.get(CV_CAP_PROP_FRAME_WIDTH));
	const unsigned videoHeight = static_cast<unsigned>(capturedVideo.get(CV_CAP_PROP_FRAME_HEIGHT));

	/* Compute the sampling step and round to the nearest integer. */
	unsigned stepSLIC = static_cast<unsigned>(sqrt((videoHeight * videoWidth) / superpixelNumber) + 0.5);

	/* Create an object for SLIC algorithm operations. */
	SLIC* SLICFrame = new SLIC();

	/* A container which will hold a video frame for
	   the time necessary for its elaboration. */
	Mat currentFrame;

	/* Video frames counter. */
	unsigned framesNumber = 0;

	/* Debug data. */
	double totalTime    = 0;
	double totalTime2   = 0;
	double avgTime      = 0;
	double stdDeviation = 0;

	/* Output window name. */
	const string windowName = "VideoSLIC";

	/* Open a new window where to play the video. */
	namedWindow(windowName, CV_WINDOW_AUTOSIZE);

	/* Enter an infinite cycle to elaborate the video until its last frame. */
	while (true)
	{
		/* Measure time before processing a video frame. */
		boost::chrono::high_resolution_clock::time_point startPoint =
			boost::chrono::high_resolution_clock::now();

		/* Take the next frame from the video. */
		capturedVideo >> currentFrame;

		/* If there are no more frames in the video, break the loop because
		   the video has reached its end or there was an error. */
		if (currentFrame.data == NULL)
			break;

		/* Convert the frame from RGB to LAB color space
		   before SLIC elaboration. */
		cvtColor(currentFrame, currentFrame, CV_BGR2Lab);

		/* Perform the SLIC algorithm operations. */
		SLICFrame->createSuperpixels(
			currentFrame, stepSLIC, spatialDistanceWeight, iterationNumber, errorThreshold,
			SLICMode, videoMode, keyFramesRatio, GaussianStdDev, connectedFrames);
		//SLICFrame->enforceConnectivity(currentFrame);
		//SLICFrame->colorSuperpixels(currentFrame);

		/* Convert frame back to RGB. */
		cvtColor(currentFrame, currentFrame, CV_Lab2BGR);

		SLICFrame->drawClusterContours(currentFrame, Vec3b(0, 0, 255)/*, Rect(videoWidth / 2, 0, videoWidth / 2, videoHeight)*/);
		//SLICFrame->drawClusterCentres(currentFrame, Scalar(0, 0, 255));

		/* Measure time after processing a video frame. */
		boost::chrono::high_resolution_clock::time_point endPoint =
			boost::chrono::high_resolution_clock::now();

		/* Get frame processing time in milliseconds. */
		boost::chrono::duration<int, boost::milli> elapsedTime =
			boost::chrono::duration_cast<boost::chrono::milliseconds>(endPoint - startPoint);

		++framesNumber;
		//SLICFrame->drawInformation(currentFrame, framesNumber, elapsedTime.count());

		/* Show frame in the window. */
		imshow(windowName, currentFrame);

		/* Compute some statistics and print them on screen. */
		totalTime  += elapsedTime.count();
		totalTime2 += elapsedTime.count() * elapsedTime.count();
		avgTime     = totalTime / framesNumber;

		stdDeviation = sqrt(framesNumber * totalTime2 - totalTime * totalTime) / framesNumber;

		cout << "Frame: " << framesNumber << "   ex. time now: " << elapsedTime.count() << "   average ex. time: "
			<< avgTime << "   stdDev: " << stdDeviation << endl << endl;

		/* End program on ESC press. */
		if (cvWaitKey(1) == 27)
			break;
	}

	/* Free used memory before closing the program. */
	if (SLICFrame != NULL)
		delete SLICFrame;

	/* Close window after video processing. */
	cv::destroyAllWindows();

	return 0;
}


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

// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.

// This file was modified by Oracle on 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.

// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

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

#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_POINT_HPP

#include <cstddef>

#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>

#include <boost/geometry/views/detail/indexed_point_view.hpp>

#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>

#include <boost/geometry/strategy/envelope.hpp>

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{

template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_point
{
    template <std::size_t Index, typename Point, typename Box>
    static inline void apply(Point const& point, Box& mbr)
    {
        detail::indexed_point_view<Box, Index> box_corner(mbr);
        detail::conversion::point_to_point
            <
                Point,
                detail::indexed_point_view<Box, Index>,
                Dimension,
                DimensionCount
            >::apply(point, box_corner);
    }

    template <typename Point, typename Box>
    static inline void apply(Point const& point, Box& mbr)
    {
        apply<min_corner>(point, mbr);
        apply<max_corner>(point, mbr);
    }
};

}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL

namespace strategy { namespace envelope
{

struct cartesian_point
{
    template <typename Point, typename Box>
    static inline void apply(Point const& point, Box& mbr)
    {
        geometry::detail::envelope::envelope_one_point
            <
                0, dimension<Point>::value
            >::apply(point, mbr);
    }
};

#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

namespace services
{

template <typename CalculationType>
struct default_strategy<point_tag, cartesian_tag, CalculationType>
{
    typedef strategy::envelope::cartesian_point type;
};

}

#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

}} // namespace strategy::envelope

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_POINT_HPP


// Copyright 2018 Hans Dembinski
//
// 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/core/lightweight_test.hpp>
#include <boost/histogram/axis/category.hpp>
#include <boost/histogram/axis/integer.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/mp11.hpp>
#include "utility_axis.hpp"

using namespace boost::histogram::axis;

int main() {
  {
    auto a = integer<>(1, 3);
    BOOST_TEST_EQ(traits::index(a, 1), 0);
    BOOST_TEST_EQ(traits::value(a, 0), 1);
    BOOST_TEST_EQ(traits::width(a, 0), 0);
    BOOST_TEST_EQ(traits::width(a, 0), 0);

    auto b = integer<double>(1, 3);
    BOOST_TEST_EQ(traits::index(b, 1), 0);
    BOOST_TEST_EQ(traits::value(b, 0), 1);
    BOOST_TEST_EQ(traits::width(b, 0), 1);
    auto& b1 = b;
    BOOST_TEST(traits::static_options<decltype(b1)>::test(option::underflow));
    const auto& b2 = b;
    BOOST_TEST(traits::static_options<decltype(b2)>::test(option::underflow));

    auto c = category<std::string>{"red", "blue"};
    BOOST_TEST_EQ(traits::index(c, "blue"), 1);
    BOOST_TEST_EQ(traits::value(c, 0), std::string("red"));
    BOOST_TEST_EQ(traits::width(c, 0), 0);
  }

  {
    using A = integer<>;
    BOOST_TEST_EQ(traits::static_options<A>::test(option::growth), false);
    BOOST_TEST_EQ(traits::static_options<A&>::test(option::growth), false);
    BOOST_TEST_EQ(traits::static_options<const A&>::test(option::growth), false);
    BOOST_TEST_EQ(traits::options(A{}), option::underflow | option::overflow);

    using B = integer<int, null_type, option::growth_t>;
    BOOST_TEST_EQ(traits::static_options<B>::test(option::growth), true);
    BOOST_TEST_EQ(traits::static_options<B&>::test(option::growth), true);
    BOOST_TEST_EQ(traits::static_options<const B&>::test(option::growth), true);
    BOOST_TEST_EQ(traits::options(B{}), option::growth);

    struct growing {
      auto update(double) { return std::make_pair(0, 0); }
    };
    using C = growing;
    BOOST_TEST_EQ(traits::static_options<C>::test(option::growth), true);
    BOOST_TEST_EQ(traits::static_options<C&>::test(option::growth), true);
    BOOST_TEST_EQ(traits::static_options<const C&>::test(option::growth), true);
    BOOST_TEST_EQ(traits::options(C{}), option::growth);

    struct notgrowing {
      auto index(double) { return 0; }
    };
    using D = notgrowing;
    BOOST_TEST_EQ(traits::static_options<D>::test(option::growth), false);
    BOOST_TEST_EQ(traits::static_options<D&>::test(option::growth), false);
    BOOST_TEST_EQ(traits::static_options<const D&>::test(option::growth), false);
    BOOST_TEST_EQ(traits::options(D{}), option::none);
  }

  {
    auto a = integer<int, null_type, option::growth_t>();
    BOOST_TEST_EQ(traits::update(a, 0), (std::pair<index_type, index_type>(0, -1)));
    BOOST_TEST_THROWS(traits::update(a, "foo"), std::invalid_argument);
  }

  return boost::report_errors();
}


// Copyright 2018 The Simons Foundation, Inc. - All Rights Reserved.
//
// 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.

// authors: Hugo Théveniaut and Fabien Alet

#ifndef NETKET_CUSTOMSAMPLERPT_HPP
#define NETKET_CUSTOMSAMPLERPT_HPP

#include <mpi.h>
#include <Eigen/Dense>
#include <iostream>
#include <limits>
#include "Operator/local_operator.hpp"
#include "Utils/parallel_utils.hpp"
#include "Utils/random_utils.hpp"
#include "abstract_sampler.hpp"

namespace netket {

// Metropolis sampling using custom moves provided by user
template <class WfType>
class CustomSamplerPt : public AbstractSampler<WfType> {
  WfType& psi_;
  const AbstractHilbert& hilbert_;
  LocalOperator move_operators_;
  std::vector<double> operatorsweights_;
  // number of visible units
  const int nv_;

  netket::default_random_engine rgen_;

  // states of visible units
  // for each sampled temperature
  std::vector<Eigen::VectorXd> v_;

  Eigen::VectorXd accept_;
  Eigen::VectorXd moves_;

  int mynode_;
  int totalnodes_;

  // Look-up tables
  std::vector<typename WfType::LookupType> lt_;

  std::vector<std::vector<int>> tochange_;
  std::vector<std::vector<double>> newconfs_;
  std::vector<std::complex<double>> mel_;

  int nstates_;
  std::vector<double> localstates_;

  int nrep_;
  std::vector<double> beta_;

 public:
  explicit CustomSamplerPt(
      WfType& psi, const LocalOperator& move_operators,
      std::vector<double> move_weights = std::vector<double>(),
      int nreplicas = 1)
      : psi_(psi),
        hilbert_(psi.GetHilbert()),
        move_operators_(move_operators),
        nv_(hilbert_.Size()),
        nrep_(nreplicas) {
    CustomSampler<WfType>::CheckMoveOperators(move_operators_);

    if (hilbert_.Size() != move_operators.GetHilbert().Size()) {
      throw InvalidInputError(
          "Move operators in CustomSampler act on a different hilbert space "
          "than the Machine");
    }

    if (move_weights.size()) {
      operatorsweights_ = move_weights;

      if (operatorsweights_.size() != move_operators.Size()) {
        throw InvalidInputError(
            "The custom sampler definition is inconsistent (between "
            "MoveWeights and MoveOperators sizes)");
      }

    } else {  // By default the stochastic operators are drawn uniformly
      operatorsweights_.resize(move_operators_.Size(), 1.0);
    }

    Init();
  }

  void Init() {
    MPI_Comm_size(MPI_COMM_WORLD, &totalnodes_);
    MPI_Comm_rank(MPI_COMM_WORLD, &mynode_);

    if (!hilbert_.IsDiscrete()) {
      throw InvalidInputError(
          "Custom Metropolis sampler works only for discrete Hilbert spaces");
    }

    nstates_ = hilbert_.LocalSize();
    localstates_ = hilbert_.LocalStates();

    v_.resize(nrep_);
    for (int i = 0; i < nrep_; i++) {
      v_[i].resize(nv_);
    }

    for (int i = 0; i < nrep_; i++) {
      beta_.push_back(1. - double(i) / double(nrep_));
    }

    lt_.resize(nrep_);

    accept_.resize(2 * nrep_);
    moves_.resize(2 * nrep_);

    Seed();

    Reset(true);

    InfoMessage() << "Custom Metropolis sampler with parallel tempering "
                     "is ready "
                  << std::endl;
    InfoMessage() << nrep_ << " replicas are being used" << std::endl;
  }

  void Seed(int baseseed = 0) {
    std::random_device rd;
    std::vector<int> seeds(totalnodes_);

    if (mynode_ == 0) {
      for (int i = 0; i < totalnodes_; i++) {
        seeds[i] = rd() + baseseed;
      }
    }

    SendToAll(seeds);

    rgen_.seed(seeds[mynode_]);
  }

  void Reset(bool initrandom = false) override {
    if (initrandom) {
      for (int i = 0; i < nrep_; i++) {
        hilbert_.RandomVals(v_[i], rgen_);
      }
    }

    for (int i = 0; i < nrep_; i++) {
      psi_.InitLookup(v_[i], lt_[i]);
    }

    accept_ = Eigen::VectorXd::Zero(2 * nrep_);
    moves_ = Eigen::VectorXd::Zero(2 * nrep_);
  }

  void LocalSweep(int rep) {
    std::discrete_distribution<int> disc_dist(operatorsweights_.begin(),
                                              operatorsweights_.end());
    std::uniform_real_distribution<double> distu;
    for (int i = 0; i < nv_; i++) {
      // pick a random operator in possible ones according to the provided
      // weights
      int op = disc_dist(rgen_);
      move_operators_.FindConn(op, v_[rep], mel_, tochange_, newconfs_);

      double p = distu(rgen_);
      std::size_t exit_state = 0;
      double cumulative_prob = std::real(mel_[0]);
      while (p > cumulative_prob) {
        exit_state++;
        cumulative_prob += std::real(mel_[exit_state]);
      }

      double ratio = std::norm(std::exp(
          beta_[rep] * psi_.LogValDiff(v_[rep], tochange_[exit_state],
                                       newconfs_[exit_state], lt_[rep])));

      // Metropolis acceptance test
      if (ratio > distu(rgen_)) {
        accept_(rep) += 1;
        psi_.UpdateLookup(v_[rep], tochange_[exit_state], newconfs_[exit_state],
                          lt_[rep]);
        hilbert_.UpdateConf(v_[rep], tochange_[exit_state],
                            newconfs_[exit_state]);
      }
      moves_(rep) += 1;
    }
  }

  void Sweep() override {
    // First we do local sweeps
    for (int i = 0; i < nrep_; i++) {
      LocalSweep(i);
    }

    // Temperature exchanges
    std::uniform_real_distribution<double> distribution(0, 1);

    for (int r = 1; r < nrep_; r += 2) {
      if (ExchangeProb(r, r - 1) > distribution(rgen_)) {
        Exchange(r, r - 1);
        accept_(nrep_ + r) += 1.;
        accept_(nrep_ + r - 1) += 1;
      }
      moves_(nrep_ + r) += 1.;
      moves_(nrep_ + r - 1) += 1;
    }

    for (int r = 2; r < nrep_; r += 2) {
      if (ExchangeProb(r, r - 1) > distribution(rgen_)) {
        Exchange(r, r - 1);
        accept_(nrep_ + r) += 1.;
        accept_(nrep_ + r - 1) += 1;
      }
      moves_(nrep_ + r) += 1.;
      moves_(nrep_ + r - 1) += 1;
    }
  }

  // computes the probability to exchange two replicas
  double ExchangeProb(int r1, int r2) {
    const double lf1 = 2 * std::real(psi_.LogVal(v_[r1], lt_[r1]));
    const double lf2 = 2 * std::real(psi_.LogVal(v_[r2], lt_[r2]));

    return std::exp((beta_[r1] - beta_[r2]) * (lf2 - lf1));
  }

  void Exchange(int r1, int r2) {
    std::swap(v_[r1], v_[r2]);
    std::swap(lt_[r1], lt_[r2]);
  }

  Eigen::VectorXd Visible() override { return v_[0]; }

  void SetVisible(const Eigen::VectorXd& v) override { v_[0] = v; }

  WfType& GetMachine() noexcept override { return psi_; }

  const AbstractHilbert& GetHilbert() const noexcept override {
    return hilbert_;
  }

  Eigen::VectorXd Acceptance() const override {
    Eigen::VectorXd acc = accept_;
    for (int i = 0; i < acc.size(); i++) {
      acc(i) /= moves_(i);
    }
    return acc;
  }
};
}  // namespace netket

#endif


//  Copyright Neil Groves 2009. Use, modification and
//  distribution is subject to 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)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED
#define BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED

#include <boost/concept_check.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/detail/range_return.hpp>
#include <boost/range/value_type.hpp>
#include <iterator>
#include <algorithm>

namespace boost
{
    namespace range
    {

namespace range_detail
{
    // Rationale: search_n is implemented rather than delegate to
    // the standard library implementation because some standard
    // library implementations are broken eg. MSVC.

    // search_n forward iterator version
    template<typename ForwardIterator, typename Integer, typename Value>
    inline ForwardIterator
    search_n_impl(ForwardIterator first, ForwardIterator last, Integer count,
                  const Value& value, std::forward_iterator_tag)
    {
        first = std::find(first, last, value);
        while (first != last)
        {
            typename std::iterator_traits<ForwardIterator>::difference_type n = count;
            ForwardIterator i = first;
            ++i;
            while (i != last && n != 1 && *i==value)
            {
                ++i;
                --n;
            }
            if (n == 1)
                return first;
            if (i == last)
                return last;
            first = std::find(++i, last, value);
        }
        return last;
    }

    // search_n random-access iterator version
    template<typename RandomAccessIterator, typename Integer, typename Value>
    inline RandomAccessIterator
    search_n_impl(RandomAccessIterator first, RandomAccessIterator last,
                  Integer count, const Value& value,
                  std::random_access_iterator_tag)
    {
        typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;

        difference_t tail_size = last - first;
        const difference_t pattern_size = count;

        if (tail_size < pattern_size)
            return last;

        const difference_t skip_offset = pattern_size - 1;
        RandomAccessIterator look_ahead = first + skip_offset;
        tail_size -= pattern_size;

        while (1)
        {
            // look_ahead here is pointing to the last element of the
            // next possible match
            while (!(*look_ahead == value)) // skip loop...
            {
                if (tail_size < pattern_size)
                    return last; // no match
                look_ahead += pattern_size;
                tail_size -= pattern_size;
            }
            difference_t remainder = skip_offset;
            for (RandomAccessIterator back_track = look_ahead - 1;
                    *back_track == value; --back_track)
            {
                if (--remainder == 0)
                {
                    return look_ahead - skip_offset; // matched
                }
            }
            if (remainder > tail_size)
                return last; // no match
            look_ahead += remainder;
            tail_size -= remainder;
        }

        return last;
    }

    // search_n for forward iterators using a binary predicate
    // to determine a match
    template<typename ForwardIterator, typename Integer, typename Value,
             typename BinaryPredicate>
    inline ForwardIterator
    search_n_pred_impl(ForwardIterator first, ForwardIterator last,
                       Integer count, const Value& value,
                       BinaryPredicate pred, std::forward_iterator_tag)
    {
        typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_t;

        while (first != last && !static_cast<bool>(pred(*first, value)))
            ++first;

        while (first != last)
        {
            difference_t n = count;
            ForwardIterator i = first;
            ++i;
            while (i != last && n != 1 && static_cast<bool>(pred(*i, value)))
            {
                ++i;
                --n;
            }
            if (n == 1)
                return first;
            if (i == last)
                return last;
            first = ++i;
            while (first != last && !static_cast<bool>(pred(*first, value)))
                ++first;
        }
        return last;
    }

    // search_n for random-access iterators using a binary predicate
    // to determine a match
    template<typename RandomAccessIterator, typename Integer,
             typename Value, typename BinaryPredicate>
    inline RandomAccessIterator
    search_n_pred_impl(RandomAccessIterator first, RandomAccessIterator last,
                       Integer count, const Value& value,
                       BinaryPredicate pred, std::random_access_iterator_tag)
    {
        typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_t;

        difference_t tail_size = last - first;
        const difference_t pattern_size = count;

        if (tail_size < pattern_size)
            return last;

        const difference_t skip_offset = pattern_size - 1;
        RandomAccessIterator look_ahead = first + skip_offset;
        tail_size -= pattern_size;

        while (1)
        {
            // look_ahead points to the last element of the next
            // possible match
            while (!static_cast<bool>(pred(*look_ahead, value))) // skip loop
            {
                if (tail_size < pattern_size)
                    return last; // no match
                look_ahead += pattern_size;
                tail_size -= pattern_size;
            }
            difference_t remainder = skip_offset;
            for (RandomAccessIterator back_track = look_ahead - 1;
                    pred(*back_track, value); --back_track)
            {
                if (--remainder == 0)
                    return look_ahead -= skip_offset; // success
            }
            if (remainder > tail_size)
            {
                return last; // no match
            }
            look_ahead += remainder;
            tail_size -= remainder;
        }
    }

    template<typename ForwardIterator, typename Integer, typename Value>
    inline ForwardIterator
    search_n_impl(ForwardIterator first, ForwardIterator last,
                  Integer count, const Value& value)
    {
        BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
        BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<Value>));
        BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept<typename std::iterator_traits<ForwardIterator>::value_type>));
        //BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2<typename std::iterator_traits<ForwardIterator>::value_type, Value>));

        typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;

        if (count <= 0)
            return first;
        if (count == 1)
            return std::find(first, last, value);
        return range_detail::search_n_impl(first, last, count, value, cat_t());
    }

    template<typename ForwardIterator, typename Integer, typename Value,
             typename BinaryPredicate>
    inline ForwardIterator
    search_n_pred_impl(ForwardIterator first, ForwardIterator last,
                       Integer count, const Value& value,
                       BinaryPredicate pred)
    {
        BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept<ForwardIterator>));
        BOOST_RANGE_CONCEPT_ASSERT((
            BinaryPredicateConcept<
                BinaryPredicate,
                typename std::iterator_traits<ForwardIterator>::value_type,
                Value>
            ));

        typedef typename std::iterator_traits<ForwardIterator>::iterator_category cat_t;

        if (count <= 0)
            return first;
        if (count == 1)
        {
            while (first != last && !static_cast<bool>(pred(*first, value)))
                ++first;
            return first;
        }
        return range_detail::search_n_pred_impl(first, last, count,
                                                value, pred, cat_t());
    }
} // namespace range_detail

/// \brief template function search
///
/// range-based version of the search std algorithm
///
/// \pre ForwardRange is a model of the ForwardRangeConcept
/// \pre Integer is an integral type
/// \pre Value is a model of the EqualityComparableConcept
/// \pre ForwardRange's value type is a model of the EqualityComparableConcept
/// \pre Object's of ForwardRange's value type can be compared for equality with Objects of type Value
template< class ForwardRange, class Integer, class Value >
inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
search_n(ForwardRange& rng, Integer count, const Value& value)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
    return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value);
}

/// \overload
template< class ForwardRange, class Integer, class Value >
inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
search_n(const ForwardRange& rng, Integer count, const Value& value)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
    return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value);
}

/// \overload
template< class ForwardRange, class Integer, class Value,
          class BinaryPredicate >
inline BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
search_n(ForwardRange& rng, Integer count, const Value& value,
         BinaryPredicate binary_pred)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
    BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
        BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type, const Value&>));
    return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng),
        count, value, binary_pred);
}

/// \overload
template< class ForwardRange, class Integer, class Value,
          class BinaryPredicate >
inline BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type
search_n(const ForwardRange& rng, Integer count, const Value& value,
         BinaryPredicate binary_pred)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
    BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
        BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type, const Value&>));
    return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng),
        count, value, binary_pred);
}

// range_return overloads

/// \overload
template< range_return_value re, class ForwardRange, class Integer,
          class Value >
inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
search_n(ForwardRange& rng, Integer count, const Value& value)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
    return range_return<ForwardRange,re>::
        pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng),
                           count, value),
             rng);
}

/// \overload
template< range_return_value re, class ForwardRange, class Integer,
          class Value >
inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
search_n(const ForwardRange& rng, Integer count, const Value& value)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
    return range_return<const ForwardRange,re>::
        pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng),
                           count, value),
             rng);
}

/// \overload
template< range_return_value re, class ForwardRange, class Integer,
          class Value, class BinaryPredicate >
inline BOOST_DEDUCED_TYPENAME range_return<ForwardRange,re>::type
search_n(ForwardRange& rng, Integer count, const Value& value,
         BinaryPredicate pred)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRange>));
    BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
        BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type,
        const Value&>));
    return range_return<ForwardRange,re>::
        pack(range_detail::search_n_pred_impl(boost::begin(rng),
                                              boost::end(rng),
                           count, value, pred),
             rng);
}

/// \overload
template< range_return_value re, class ForwardRange, class Integer,
          class Value, class BinaryPredicate >
inline BOOST_DEDUCED_TYPENAME range_return<const ForwardRange,re>::type
search_n(const ForwardRange& rng, Integer count, const Value& value,
         BinaryPredicate pred)
{
    BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRange>));
    BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept<BinaryPredicate,
        BOOST_DEDUCED_TYPENAME range_value<const ForwardRange>::type,
        const Value&>));
    return range_return<const ForwardRange,re>::
        pack(range_detail::search_n_pred_impl(boost::begin(rng),
                                              boost::end(rng),
                           count, value, pred),
             rng);
}

    } // namespace range
    using range::search_n;
} // namespace boost

#endif // include guard


//==================================================================================================
/*!
  @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_FUNCTION_IS_LESS_EQUAL_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_IS_LESS_EQUAL_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

  /*!
    @ingroup group-predicates

    This function object returns @ref True  or @ref False depending on whether x is
    less than or equal to y or not.

    Infix notation can be used with operator '<='.

    @par Header <boost/simd/function/is_less_equal.hpp>

    @par Note

     Using `is_less_equal(x,y)` is equivalent to `x <= y`

    @par Example:

      @snippet is_less_equal.cpp is_less_equal

    @par Possible output:

      @snippet is_less_equal.txt is_less_equal

  **/
  as_logical_t<Value> is_less_equal(Value const& x, Value const& y);
} }
#endif

#include <boost/simd/function/scalar/is_less_equal.hpp>
#include <boost/simd/function/simd/is_less_equal.hpp>

#endif


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

#include <boost/test/unit_test.hpp>

#include <variadic/size.hpp>

#include <type_traits>
#include <tuple>

#include <variadic/collection.hpp>

BOOST_AUTO_TEST_CASE( variadic_size )
{
    {
        static_assert(variadic::size<>::value == 0, "Invalid size deduction for variadic::size");
        static_assert(variadic::size<char, int, int>::value == 3, "Invalid size deduction for variadic::size");
    }

    {
        static_assert(variadic::pack_size<>::value == 0, "Invalid size deduction for variadic::pack_size");

        static_assert(variadic::pack_size<variadic::collection<>>::value == 0, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<>>::value == 0, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<char, int, int>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<char, int, int>>::value == 3, "Invalid size deduction for variadic::pack_size");

        static_assert(variadic::pack_size<variadic::collection<>, variadic::collection<>>::value == 0, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<>, std::tuple<>>::value == 0, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<>, variadic::collection<char, int, int>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<>, std::tuple<char, int, int>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<char, int, int>, variadic::collection<>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<char, int, int>, std::tuple<>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<char, int, int>, variadic::collection<char, int, int>>::value == 6, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<variadic::collection<char, int, int>, std::tuple<char, int, int>>::value == 6, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<>, variadic::collection<>>::value == 0, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<>, std::tuple<>>::value == 0, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<>, variadic::collection<char, int, int>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<>, std::tuple<char, int, int>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<char, int, int>, variadic::collection<>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<char, int, int>, std::tuple<>>::value == 3, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<char, int, int>, variadic::collection<char, int, int>>::value == 6, "Invalid size deduction for variadic::pack_size");
        static_assert(variadic::pack_size<std::tuple<char, int, int>, std::tuple<char, int, int>>::value == 6, "Invalid size deduction for variadic::pack_size");
    }
}


/*
    Copyright 2013 Adobe
    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 <adobe/implementation/expression_filter.hpp>

#include <cctype>
#include <iterator>
#include <vector>

#include <boost/bind.hpp>

#include <adobe/algorithm/copy.hpp>
#include <adobe/algorithm/find.hpp>
#include <adobe/algorithm/lower_bound.hpp>
#include <adobe/functional.hpp>
#include <adobe/table_index.hpp>
#include <adobe/unicode.hpp>

/**************************************************************************************************/

using namespace std;

/**************************************************************************************************/

namespace {

/**************************************************************************************************/
/*!
    hexadecimal atoi

    Iterator-based atoi, but for hexadecimal number strings.

    REVISIT (fbrereto) : Copied from xml_parser to eliminate a dependency. The
                         xml parser relies on copy_on_write which relies on
                         atomic_t which is not implemented for ARM under TBB, so
                         does not compile for Apple's iPod/iPhone/iPad.
*/
template <typename Result, typename InputIterator>
InputIterator xatoi(InputIterator first, InputIterator last, Result& result) {
    result = 0;

    while (first != last && std::isxdigit(*first)) {
        typename std::iterator_traits<InputIterator>::value_type c(*first);

        result <<= 4;

        if (std::isdigit(c)) {
            result += c - '0';
        } else {
            c = std::use_facet<std::ctype<char>>(std::locale()).tolower(c);

            result += c - 'a' + 10;
        }

        ++first;
    }

    return first;
}

/**************************************************************************************************/
/*!
    decimal atoi

    Iterator-based atoi

    REVISIT (fbrereto) : Copied from xml_parser to eliminate a dependency. The
                         xml parser relies on copy_on_write which relies on
                         atomic_t which is not implemented for ARM under TBB, so
                         does not compile for Apple's iPod/iPhone/iPad.
*/
template <typename Result, typename InputIterator>
InputIterator datoi(InputIterator first, InputIterator last, Result& result) {
    result = 0;

    while (first != last && std::isdigit(*first)) {
        result *= 10;

        result += *first - '0';

        ++first;
    }

    return first;
}

/**************************************************************************************************/

template <typename I, typename O, typename P>
std::pair<I, O> copy_until(I first, I last, O output,
                           P pred =
                               adobe::always_true<typename std::iterator_traits<I>::value_type>()) {
    for (; first != last && pred(*first); ++first)
        *output++ = *first;

    return std::make_pair(first, output);
}

/**************************************************************************************************/

#define ADOBE_CODE_POINT(x) boost::uint32_t(x##UL)

/**************************************************************************************************/

typedef pair<string, boost::uint32_t> code_point_set_value_type;
typedef vector<code_point_set_value_type> code_point_set_t;

/**************************************************************************************************/

const code_point_set_t& code_point_set() {
    typedef code_point_set_value_type value_type;

    static code_point_set_t code_point_set_s;
    static bool inited(false);

    if (!inited) {
        inited = true;

        value_type default_entry_set[] = {
            value_type("Aacute", ADOBE_CODE_POINT(0x00C1)),
            value_type("aacute", ADOBE_CODE_POINT(0x00E1)),
            value_type("Acirc", ADOBE_CODE_POINT(0x00C2)),
            value_type("acirc", ADOBE_CODE_POINT(0x00E2)),
            value_type("acute", ADOBE_CODE_POINT(0x00B4)),
            value_type("AElig", ADOBE_CODE_POINT(0x00C6)),
            value_type("aelig", ADOBE_CODE_POINT(0x00E6)),
            value_type("Agrave", ADOBE_CODE_POINT(0x00C0)),
            value_type("agrave", ADOBE_CODE_POINT(0x00E0)),
            value_type("alefsym", ADOBE_CODE_POINT(0x2135)),
            value_type("Alpha", ADOBE_CODE_POINT(0x0391)),
            value_type("alpha", ADOBE_CODE_POINT(0x03B1)),
            value_type("amp", ADOBE_CODE_POINT(0x0026)),
            value_type("and", ADOBE_CODE_POINT(0x2227)),
            value_type("ang", ADOBE_CODE_POINT(0x2220)),
            value_type("Aring", ADOBE_CODE_POINT(0x00C5)),
            value_type("aring", ADOBE_CODE_POINT(0x00E5)),
            value_type("asymp", ADOBE_CODE_POINT(0x2248)),
            value_type("Atilde", ADOBE_CODE_POINT(0x00C3)),
            value_type("atilde", ADOBE_CODE_POINT(0x00E3)),
            value_type("Auml", ADOBE_CODE_POINT(0x00C4)),
            value_type("auml", ADOBE_CODE_POINT(0x00E4)),
            value_type("bdquo", ADOBE_CODE_POINT(0x201E)),
            value_type("Beta", ADOBE_CODE_POINT(0x0392)),
            value_type("beta", ADOBE_CODE_POINT(0x03B2)),
            value_type("brvbar", ADOBE_CODE_POINT(0x00A6)),
            value_type("bull", ADOBE_CODE_POINT(0x2022)),
            value_type("cap", ADOBE_CODE_POINT(0x2229)),
            value_type("Ccedil", ADOBE_CODE_POINT(0x00C7)),
            value_type("ccedil", ADOBE_CODE_POINT(0x00E7)),
            value_type("cedil", ADOBE_CODE_POINT(0x00B8)),
            value_type("cent", ADOBE_CODE_POINT(0x00A2)),
            value_type("Chi", ADOBE_CODE_POINT(0x03A7)),
            value_type("chi", ADOBE_CODE_POINT(0x03C7)),
            value_type("circ", ADOBE_CODE_POINT(0x02C6)),
            value_type("clubs", ADOBE_CODE_POINT(0x2663)),
            value_type("cong", ADOBE_CODE_POINT(0x2245)),
            value_type("copy", ADOBE_CODE_POINT(0x00A9)),
            value_type("cr", ADOBE_CODE_POINT(0x000D)),
            value_type("crarr", ADOBE_CODE_POINT(0x21B5)),
            value_type("cup", ADOBE_CODE_POINT(0x222A)),
            value_type("curren", ADOBE_CODE_POINT(0x00A4)),
            value_type("dagger", ADOBE_CODE_POINT(0x2020)),
            value_type("Dagger", ADOBE_CODE_POINT(0x2021)),
            value_type("darr", ADOBE_CODE_POINT(0x2193)),
            value_type("dArr", ADOBE_CODE_POINT(0x21D3)),
            value_type("deg", ADOBE_CODE_POINT(0x00B0)),
            value_type("Delta", ADOBE_CODE_POINT(0x0394)),
            value_type("delta", ADOBE_CODE_POINT(0x03B4)),
            value_type("diams", ADOBE_CODE_POINT(0x2666)),
            value_type("divide", ADOBE_CODE_POINT(0x00F7)),
            value_type("Eacute", ADOBE_CODE_POINT(0x00C9)),
            value_type("eacute", ADOBE_CODE_POINT(0x00E9)),
            value_type("Ecirc", ADOBE_CODE_POINT(0x00CA)),
            value_type("ecirc", ADOBE_CODE_POINT(0x00EA)),
            value_type("Egrave", ADOBE_CODE_POINT(0x00C8)),
            value_type("egrave", ADOBE_CODE_POINT(0x00E8)),
            value_type("empty", ADOBE_CODE_POINT(0x2205)),
            value_type("emsp", ADOBE_CODE_POINT(0x2003)),
            value_type("ensp", ADOBE_CODE_POINT(0x2002)),
            value_type("Epsilon", ADOBE_CODE_POINT(0x0395)),
            value_type("epsilon", ADOBE_CODE_POINT(0x03B5)),
            value_type("equiv", ADOBE_CODE_POINT(0x2261)),
            value_type("Eta", ADOBE_CODE_POINT(0x0397)),
            value_type("eta", ADOBE_CODE_POINT(0x03B7)),
            value_type("ETH", ADOBE_CODE_POINT(0x00D0)),
            value_type("eth", ADOBE_CODE_POINT(0x00F0)),
            value_type("Euml", ADOBE_CODE_POINT(0x00CB)),
            value_type("euml", ADOBE_CODE_POINT(0x00EB)),
            value_type("euro", ADOBE_CODE_POINT(0x20AC)),
            value_type("exist", ADOBE_CODE_POINT(0x2203)),
            value_type("fnof", ADOBE_CODE_POINT(0x0192)),
            value_type("forall", ADOBE_CODE_POINT(0x2200)),
            value_type("frac12", ADOBE_CODE_POINT(0x00BD)),
            value_type("frac14", ADOBE_CODE_POINT(0x00BC)),
            value_type("frac34", ADOBE_CODE_POINT(0x00BE)),
            value_type("frasl", ADOBE_CODE_POINT(0x2044)),
            value_type("Gamma", ADOBE_CODE_POINT(0x0393)),
            value_type("gamma", ADOBE_CODE_POINT(0x03B3)),
            value_type("ge", ADOBE_CODE_POINT(0x2265)),
            value_type("gt", ADOBE_CODE_POINT(0x003E)),
            value_type("harr", ADOBE_CODE_POINT(0x2194)),
            value_type("hArr", ADOBE_CODE_POINT(0x21D4)),
            value_type("hearts", ADOBE_CODE_POINT(0x2665)),
            value_type("hellip", ADOBE_CODE_POINT(0x2026)),
            value_type("Iacute", ADOBE_CODE_POINT(0x00CD)),
            value_type("iacute", ADOBE_CODE_POINT(0x00ED)),
            value_type("Icirc", ADOBE_CODE_POINT(0x00CE)),
            value_type("icirc", ADOBE_CODE_POINT(0x00EE)),
            value_type("iexcl", ADOBE_CODE_POINT(0x00A1)),
            value_type("Igrave", ADOBE_CODE_POINT(0x00CC)),
            value_type("igrave", ADOBE_CODE_POINT(0x00EC)),
            value_type("image", ADOBE_CODE_POINT(0x2111)),
            value_type("infin", ADOBE_CODE_POINT(0x221E)),
            value_type("int", ADOBE_CODE_POINT(0x222B)),
            value_type("Iota", ADOBE_CODE_POINT(0x0399)),
            value_type("iota", ADOBE_CODE_POINT(0x03B9)),
            value_type("iquest", ADOBE_CODE_POINT(0x00BF)),
            value_type("isin", ADOBE_CODE_POINT(0x2208)),
            value_type("Iuml", ADOBE_CODE_POINT(0x00CF)),
            value_type("iuml", ADOBE_CODE_POINT(0x00EF)),
            value_type("Kappa", ADOBE_CODE_POINT(0x039A)),
            value_type("kappa", ADOBE_CODE_POINT(0x03BA)),
            value_type("Lambda", ADOBE_CODE_POINT(0x039B)),
            value_type("lambda", ADOBE_CODE_POINT(0x03BB)),
            value_type("lang", ADOBE_CODE_POINT(0x2329)),
            value_type("laquo", ADOBE_CODE_POINT(0x00AB)),
            value_type("larr", ADOBE_CODE_POINT(0x2190)),
            value_type("lArr", ADOBE_CODE_POINT(0x21D0)),
            value_type("lceil", ADOBE_CODE_POINT(0x2308)),
            value_type("ldquo", ADOBE_CODE_POINT(0x201C)),
            value_type("le", ADOBE_CODE_POINT(0x2264)),
            value_type("lf", ADOBE_CODE_POINT(0x000A)),
            value_type("lfloor", ADOBE_CODE_POINT(0x230A)),
            value_type("lowast", ADOBE_CODE_POINT(0x2217)),
            value_type("loz", ADOBE_CODE_POINT(0x25CA)),
            value_type("lrm", ADOBE_CODE_POINT(0x200E)),
            value_type("lsaquo", ADOBE_CODE_POINT(0x2039)),
            value_type("lsquo", ADOBE_CODE_POINT(0x2018)),
            value_type("lt", ADOBE_CODE_POINT(0x003C)),
            value_type("macr", ADOBE_CODE_POINT(0x00AF)),
            value_type("mdash", ADOBE_CODE_POINT(0x2014)),
            value_type("micro", ADOBE_CODE_POINT(0x00B5)),
            value_type("middot", ADOBE_CODE_POINT(0x00B7)),
            value_type("minus", ADOBE_CODE_POINT(0x2212)),
            value_type("Mu", ADOBE_CODE_POINT(0x039C)),
            value_type("mu", ADOBE_CODE_POINT(0x03BC)),
            value_type("nabla", ADOBE_CODE_POINT(0x2207)),
            value_type("nbsp", ADOBE_CODE_POINT(0x00A0)),
            value_type("ndash", ADOBE_CODE_POINT(0x2013)),
            value_type("ne", ADOBE_CODE_POINT(0x2260)),
            value_type("ni", ADOBE_CODE_POINT(0x220B)),
            value_type("not", ADOBE_CODE_POINT(0x00AC)),
            value_type("notin", ADOBE_CODE_POINT(0x2209)),
            value_type("nsub", ADOBE_CODE_POINT(0x2284)),
            value_type("Ntilde", ADOBE_CODE_POINT(0x00D1)),
            value_type("ntilde", ADOBE_CODE_POINT(0x00F1)),
            value_type("Nu", ADOBE_CODE_POINT(0x039D)),
            value_type("nu", ADOBE_CODE_POINT(0x03BD)),
            value_type("Oacute", ADOBE_CODE_POINT(0x00D3)),
            value_type("oacute", ADOBE_CODE_POINT(0x00F3)),
            value_type("Ocirc", ADOBE_CODE_POINT(0x00D4)),
            value_type("ocirc", ADOBE_CODE_POINT(0x00F4)),
            value_type("OElig", ADOBE_CODE_POINT(0x0152)),
            value_type("oelig", ADOBE_CODE_POINT(0x0153)),
            value_type("Ograve", ADOBE_CODE_POINT(0x00D2)),
            value_type("ograve", ADOBE_CODE_POINT(0x00F2)),
            value_type("oline", ADOBE_CODE_POINT(0x203E)),
            value_type("Omega", ADOBE_CODE_POINT(0x03A9)),
            value_type("omega", ADOBE_CODE_POINT(0x03C9)),
            value_type("Omicron", ADOBE_CODE_POINT(0x039F)),
            value_type("omicron", ADOBE_CODE_POINT(0x03BF)),
            value_type("oplus", ADOBE_CODE_POINT(0x2295)),
            value_type("or", ADOBE_CODE_POINT(0x2228)),
            value_type("ordf", ADOBE_CODE_POINT(0x00AA)),
            value_type("ordm", ADOBE_CODE_POINT(0x00BA)),
            value_type("Oslash", ADOBE_CODE_POINT(0x00D8)),
            value_type("oslash", ADOBE_CODE_POINT(0x00F8)),
            value_type("Otilde", ADOBE_CODE_POINT(0x00D5)),
            value_type("otilde", ADOBE_CODE_POINT(0x00F5)),
            value_type("otimes", ADOBE_CODE_POINT(0x2297)),
            value_type("Ouml", ADOBE_CODE_POINT(0x00D6)),
            value_type("ouml", ADOBE_CODE_POINT(0x00F6)),
            value_type("para", ADOBE_CODE_POINT(0x00B6)),
            value_type("part", ADOBE_CODE_POINT(0x2202)),
            value_type("permil", ADOBE_CODE_POINT(0x2030)),
            value_type("perp", ADOBE_CODE_POINT(0x22A5)),
            value_type("Phi", ADOBE_CODE_POINT(0x03A6)),
            value_type("phi", ADOBE_CODE_POINT(0x03C6)),
            value_type("Pi", ADOBE_CODE_POINT(0x03A0)),
            value_type("pi", ADOBE_CODE_POINT(0x03C0)),
            value_type("piv", ADOBE_CODE_POINT(0x03D6)),
            value_type("plusmn", ADOBE_CODE_POINT(0x00B1)),
            value_type("pound", ADOBE_CODE_POINT(0x00A3)),
            value_type("prime", ADOBE_CODE_POINT(0x2032)),
            value_type("Prime", ADOBE_CODE_POINT(0x2033)),
            value_type("prod", ADOBE_CODE_POINT(0x220F)),
            value_type("prop", ADOBE_CODE_POINT(0x221D)),
            value_type("Psi", ADOBE_CODE_POINT(0x03A8)),
            value_type("psi", ADOBE_CODE_POINT(0x03C8)),
            value_type("quot", ADOBE_CODE_POINT(0x0022)),
            value_type("radic", ADOBE_CODE_POINT(0x221A)),
            value_type("rang", ADOBE_CODE_POINT(0x232A)),
            value_type("raquo", ADOBE_CODE_POINT(0x00BB)),
            value_type("rarr", ADOBE_CODE_POINT(0x2192)),
            value_type("rArr", ADOBE_CODE_POINT(0x21D2)),
            value_type("rceil", ADOBE_CODE_POINT(0x2309)),
            value_type("rdquo", ADOBE_CODE_POINT(0x201D)),
            value_type("real", ADOBE_CODE_POINT(0x211C)),
            value_type("reg", ADOBE_CODE_POINT(0x00AE)),
            value_type("rfloor", ADOBE_CODE_POINT(0x230B)),
            value_type("Rho", ADOBE_CODE_POINT(0x03A1)),
            value_type("rho", ADOBE_CODE_POINT(0x03C1)),
            value_type("rlm", ADOBE_CODE_POINT(0x200F)),
            value_type("rsaquo", ADOBE_CODE_POINT(0x203A)),
            value_type("rsquo", ADOBE_CODE_POINT(0x2019)),
            value_type("sbquo", ADOBE_CODE_POINT(0x201A)),
            value_type("Scaron", ADOBE_CODE_POINT(0x0160)),
            value_type("scaron", ADOBE_CODE_POINT(0x0161)),
            value_type("sdot", ADOBE_CODE_POINT(0x22C5)),
            value_type("sect", ADOBE_CODE_POINT(0x00A7)),
            value_type("shy", ADOBE_CODE_POINT(0x00AD)),
            value_type("Sigma", ADOBE_CODE_POINT(0x03A3)),
            value_type("sigma", ADOBE_CODE_POINT(0x03C3)),
            value_type("sigmaf", ADOBE_CODE_POINT(0x03C2)),
            value_type("sim", ADOBE_CODE_POINT(0x223C)),
            value_type("spades", ADOBE_CODE_POINT(0x2660)),
            value_type("sub", ADOBE_CODE_POINT(0x2282)),
            value_type("sube", ADOBE_CODE_POINT(0x2286)),
            value_type("sum", ADOBE_CODE_POINT(0x2211)),
            value_type("sup", ADOBE_CODE_POINT(0x2283)),
            value_type("sup1", ADOBE_CODE_POINT(0x00B9)),
            value_type("sup2", ADOBE_CODE_POINT(0x00B2)),
            value_type("sup3", ADOBE_CODE_POINT(0x00B3)),
            value_type("supe", ADOBE_CODE_POINT(0x2287)),
            value_type("szlig", ADOBE_CODE_POINT(0x00DF)),
            value_type("tab", ADOBE_CODE_POINT(0x0009)),
            value_type("Tau", ADOBE_CODE_POINT(0x03A4)),
            value_type("tau", ADOBE_CODE_POINT(0x03C4)),
            value_type("there4", ADOBE_CODE_POINT(0x2234)),
            value_type("Theta", ADOBE_CODE_POINT(0x0398)),
            value_type("theta", ADOBE_CODE_POINT(0x03B8)),
            value_type("thetasym", ADOBE_CODE_POINT(0x03D1)),
            value_type("thinsp", ADOBE_CODE_POINT(0x2009)),
            value_type("THORN", ADOBE_CODE_POINT(0x00DE)),
            value_type("thorn", ADOBE_CODE_POINT(0x00FE)),
            value_type("tilde", ADOBE_CODE_POINT(0x02DC)),
            value_type("times", ADOBE_CODE_POINT(0x00D7)),
            value_type("trade", ADOBE_CODE_POINT(0x2122)),
            value_type("Uacute", ADOBE_CODE_POINT(0x00DA)),
            value_type("uacute", ADOBE_CODE_POINT(0x00FA)),
            value_type("uarr", ADOBE_CODE_POINT(0x2191)),
            value_type("uArr", ADOBE_CODE_POINT(0x21D1)),
            value_type("Ucirc", ADOBE_CODE_POINT(0x00DB)),
            value_type("ucirc", ADOBE_CODE_POINT(0x00FB)),
            value_type("Ugrave", ADOBE_CODE_POINT(0x00D9)),
            value_type("ugrave", ADOBE_CODE_POINT(0x00F9)),
            value_type("uml", ADOBE_CODE_POINT(0x00A8)),
            value_type("upsih", ADOBE_CODE_POINT(0x03D2)),
            value_type("Upsilon", ADOBE_CODE_POINT(0x03A5)),
            value_type("upsilon", ADOBE_CODE_POINT(0x03C5)),
            value_type("Uuml", ADOBE_CODE_POINT(0x00DC)),
            value_type("uuml", ADOBE_CODE_POINT(0x00FC)),
            value_type("weierp", ADOBE_CODE_POINT(0x2118)),
            value_type("Xi", ADOBE_CODE_POINT(0x039E)),
            value_type("xi", ADOBE_CODE_POINT(0x03BE)),
            value_type("Yacute", ADOBE_CODE_POINT(0x00DD)),
            value_type("yacute", ADOBE_CODE_POINT(0x00FD)),
            value_type("yen", ADOBE_CODE_POINT(0x00A5)),
            value_type("yuml", ADOBE_CODE_POINT(0x00FF)),
            value_type("Yuml", ADOBE_CODE_POINT(0x0178)),
            value_type("Zeta", ADOBE_CODE_POINT(0x0396)),
            value_type("zeta", ADOBE_CODE_POINT(0x03B6)),
            value_type("zwj", ADOBE_CODE_POINT(0x200D)),
            value_type("zwnj", ADOBE_CODE_POINT(0x200C))
#if 1
            // NOTE (fbrereto) : These are not a part of the HTML default entity list, but are still
            // useful
            ,
            value_type("apos", ADOBE_CODE_POINT(0x0027))
#endif
        };

        std::size_t entry_set_size(sizeof(default_entry_set) / sizeof(default_entry_set[0]));

        code_point_set_s.reserve(entry_set_size);

        adobe::copy(default_entry_set, std::back_inserter(code_point_set_s));

        assert(code_point_set_s.size() == entry_set_size);
    }

    return code_point_set_s;
}

/**************************************************************************************************/

#undef ADOBE_CODE_POINT

/**************************************************************************************************/

typedef adobe::table_index<const boost::uint32_t, const code_point_set_t::value_type>
code_point_index_type;

/**************************************************************************************************/

const code_point_index_type& code_point_index() {
    static const code_point_index_type index(code_point_set().begin(), code_point_set().end(),
                                             &code_point_set_t::value_type::second);
    static bool inited(false);

    if (!inited) {
        inited = true;

        const_cast<code_point_index_type&>(index).sort();
        // const_cast<code_point_index_type&>(index).unique();

        assert(index.size() == code_point_set().size());
    }

    return index;
}

/**************************************************************************************************/

code_point_index_type::const_iterator code_point_index_find(boost::uint32_t code_point) {
    const code_point_index_type& index(code_point_index());
    code_point_index_type::const_iterator found(adobe::lower_bound(
        index, code_point, adobe::compare_members(&code_point_set_t::value_type::second)));

    return found == index.end() || found->second != code_point ? index.end() : found;
}

/**************************************************************************************************/

typedef adobe::table_index<const string, const code_point_set_t::value_type> entity_name_index_type;

/**************************************************************************************************/

const entity_name_index_type& entity_name_index() {
    static const entity_name_index_type index(code_point_set().begin(), code_point_set().end(),
                                              &code_point_set_t::value_type::first);
    static bool inited(false);

    if (!inited) {
        inited = true;

        const_cast<entity_name_index_type&>(index).sort();
        // const_cast<entity_name_index_type&>(index).unique();

        assert(index.size() == code_point_set().size());
    }

    return index;
}

/**************************************************************************************************/

entity_name_index_type::const_iterator entity_name_index_find(const string& entity_name) {
    const entity_name_index_type& index(entity_name_index());
    entity_name_index_type::const_iterator found(adobe::lower_bound(
        index, entity_name, adobe::compare_members(&code_point_set_t::value_type::first)));

    return found == index.end() || found->first != entity_name ? index.end() : found;
}

/**************************************************************************************************/

inline bool needs_escape(unsigned char c) {
    return !std::isprint(c) || (c & 0x80);
}

/**************************************************************************************************/

} // namespace

/**************************************************************************************************/

namespace adobe {

/**************************************************************************************************/

const string& entity_map_find(boost::uint32_t code_point) {
    code_point_index_type::const_iterator found(code_point_index_find(code_point));

    if (found == code_point_index().end())
        throw std::range_error("code point not found");

    return found->first;
}

/**************************************************************************************************/

boost::uint32_t entity_map_find(const string& entity) {
    string::const_iterator first(entity.begin());

    if (entity.size() > 1 && *first == '#') {
        string::const_iterator last(entity.end());
        boost::uint32_t result;

        ++first;

        if (*first == 'x')
            xatoi(++first, last, result);
        else
            datoi(first, last, result);

        return result;
    }

    entity_name_index_type::const_iterator found(entity_name_index_find(entity));

    if (found == entity_name_index().end())
        throw std::range_error("entity name not found");

    return found->second;
}

/**************************************************************************************************/

bool needs_entity_escape(const string& value) {
    for (string::const_iterator iter(value.begin()); iter != value.end(); ++iter) {
        unsigned char c(*iter);

        if (needs_escape(c))
            return true;

        code_point_index_type::const_iterator found(
            code_point_index_find(static_cast<boost::uint32_t>(c)));

        if (found != code_point_index().end())
            return true;
    }

    return false;
}

/**************************************************************************************************/

string entity_escape(const string& value) {
    string result;

    result.reserve(value.size());

    for (string::const_iterator iter(value.begin()); iter != value.end(); ++iter) {
        unsigned char c(*iter);

        code_point_index_type::const_iterator found(
            code_point_index_find(static_cast<boost::uint32_t>(c)));

        if (found != code_point_index().end()) {
            result.push_back('&');
            result.append(found->first);
            result.push_back(';');
        } else if (needs_escape(c)) {
            char nybble1((c >> 4) & 0x0f);
            char nybble2(c & 0x0f);

            result.append(string("&#x"));

            result.push_back(nybble1 >= 0x0a ? 'A' + (nybble1 - 0x0a) : '0' + nybble1);

            result.push_back(nybble2 >= 0x0a ? 'A' + (nybble2 - 0x0a) : '0' + nybble2);

            result.push_back(';');
        } else
            result.push_back(c);
    }

    return result;
}

/**************************************************************************************************/

bool needs_entity_unescape(const string& value) {
    /*
        This isn't ideal; it's possible for any string to have an ampersand
        followed by a semicolon, which will return true in this case but the
        string does not need unescaping.
    */
    string::const_iterator first(find(value, '&'));
    string::const_iterator next(std::find(first, value.end(), ';'));

    return next != value.end();
}

/**************************************************************************************************/

string entity_unescape(const string& value) {
    string result;
    string::const_iterator iter(value.begin());

    result.reserve(value.size());

    while (iter != value.end()) {
        string::const_iterator next(
            copy_until(iter, value.end(), std::back_inserter(result),
                       boost::bind(std::not_equal_to<char>(), _1, '&')).first);

        if (next == value.end())
            return result;

        ++next;

        string::const_iterator next_end(std::find(next, value.end(), ';'));

        if (next_end == value.end())
            return result;

        // snip out the entity and look it up in the map

        boost::uint32_t code_point(entity_map_find(string(next, next_end)));

        if (code_point != 0)
            adobe::copy_utf<char>(&code_point, &code_point + 1, std::back_inserter(result));

        iter = ++next_end;
    }

    return result;
}

/**************************************************************************************************/

} // namespace adobe

/**************************************************************************************************/


// (C) Copyright Andrew Sutton 2009
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

#include <iostream>

#include <boost/assert.hpp>
#include <boost/graph/adjacency_list.hpp>

using namespace boost;

// TODO: Integrate this into a larger adj_list test suite.

template <typename Graph>
void test_graph_nonloop()
{
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;

    // Build a graph with 1 edge and turn it into a loop.
    Graph g(5);
    Vertex u = *vertices(g).first;
    Vertex v = *next(vertices(g).first, 2);
    add_edge(u, v, g);
    BOOST_ASSERT(num_vertices(g) == 5);
    BOOST_ASSERT(num_edges(g) == 1);
    remove_edge(u, v, g);
    BOOST_ASSERT(num_edges(g) == 0);

}

template <typename Graph>
void test_multigraph_nonloop()
{
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;

    // Build a graph with 1 edge and turn it into a loop.
    Graph g(5);
    Vertex u = *vertices(g).first;
    Vertex v = *next(vertices(g).first, 2);
    add_edge(u, v, g);
    add_edge(u, v, g);
    BOOST_ASSERT(num_vertices(g) == 5);
    BOOST_ASSERT(num_edges(g) == 2);
    remove_edge(u, v, g);
    BOOST_ASSERT(num_edges(g) == 0);

}

template <typename Graph>
void test_graph_loop()
{
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;

    Graph g(5);
    Vertex v = *next(vertices(g).first, 2);
    add_edge(v, v, g);
    BOOST_ASSERT(num_vertices(g) == 5);
    BOOST_ASSERT(num_edges(g) == 1);
    remove_edge(v, v, g);
    BOOST_ASSERT(num_edges(g) == 0);
}

template <typename Graph>
void test_multigraph_loop()
{
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;

    Graph g(5);
    Vertex v = *next(vertices(g).first, 2);
    add_edge(v, v, g);
    add_edge(v, v, g);
    BOOST_ASSERT(num_vertices(g) == 5);
    BOOST_ASSERT(num_edges(g) == 2);
    remove_edge(v, v, g);
    BOOST_ASSERT(num_edges(g) == 0);
}

template <typename Kind>
void test()
{
    typedef no_property na;
    typedef adjacency_list<vecS, vecS, Kind, na, na, na, listS> VVL;
    typedef adjacency_list<listS, vecS, Kind, na, na, na, listS> LVL;
    typedef adjacency_list<setS, vecS, Kind, na, na, na, listS> SVL;
    typedef adjacency_list<multisetS, vecS, Kind, na, na, na, listS> MVL;

    test_graph_nonloop<VVL>();
    test_graph_nonloop<LVL>();
    test_graph_nonloop<SVL>();
    test_graph_nonloop<MVL>();
    test_multigraph_nonloop<VVL>();
    test_multigraph_nonloop<LVL>();
    test_multigraph_nonloop<MVL>();
    test_graph_loop<VVL>();
    test_graph_loop<LVL>();
    test_graph_loop<SVL>();
    test_graph_loop<MVL>();
    test_multigraph_loop<VVL>();
    test_multigraph_loop<LVL>();
    test_multigraph_loop<MVL>();
}

int main()
{
    test<undirectedS>();
    test<directedS>();
    test<bidirectionalS>();

    return 0;
}


// External libraries
#include <iostream>
#include <stdio.h>
#include <boost/property_tree/ptree.hpp>

// Local libraries
#include <inout/ioutil.h>
#include <fparameters/parameters.h>
#include <fparameters/SpaceIterator.h>

// Local headers
#include "read.h"
#include "messages.h"
#include "modelParameters.h"
#include "State.h"
#include "write.h"
#include "comptonScattMatrix.h"
#include "thermalProcesses.h"
#include "adafFunctions.h"
#include "globalVariables.h"
#include "flareProcesses.h"
#include "redshiftFunction.h"
#include "thermalDistribution.h"
#include "NTtimescales.h"
#include "NTinjection.h"
#include "injectionNeutrons.h"
#include "distributionNeutrons.h"
#include "NTdistribution.h"
#include "NTradiation.h"
#include "absorption.h"
#include "secondariesProcesses.h"
#include "jetEmission.h"

using namespace std;

int main()
{
	string folder{ prepareOutputfolder() };
	try {
		GlobalConfig = readConfig();
		prepareGlobalCfg();

		State model(GlobalConfig.get_child("model"));
		redshiftFactor(model);
		createH5file("h5prueba.h5", model);
	}
	catch (std::runtime_error& e)
	{
		std::cout << "ERROR: " << e.what() << std::endl;
	}
	return 0;
}

/*	string folder{ prepareOutputfolder() };
	try {
		GlobalConfig = readConfig();
		prepareGlobalCfg();

		State model(GlobalConfig.get_child("model"));
		writeFields(model);
		redshiftFactor(model);

		if (calculateThermal) {
			if (calculateComptonScatt)
				comptonScattMatrix(model);
			else
				comptonScattMatrixRead(model);
			thermalRadiation(model, "lumThermal.dat");
		}
		else
			readEandRParamSpace("photonDensity", model.photon.distribution, 0, 0);

		//writeEandRParamSpace("photonDensity_z",model.photon.injection,0,0);

		if (calculateJetEmission)
			jetProcesses(model,"lumJet.txt");

		if (calculateFlare)
			flareProcesses(model);

//***********nonthermal particles**************
		if (calculateNonThermal) {

			if (calculateLosses) {
				if (calculateNTelectrons)
					nonThermalTimescales(model.ntElectron, model, "electronCoolingTimes.dat");
				if (calculateNTprotons)
					nonThermalTimescales(model.ntProton, model, "protonCoolingTimes.dat");
			}

			if (calculateNTdistributions) {

				if (calculateNTelectrons) {
					injection(model.ntElectron, model);
					if (accMethod == 0)
						//distributionSpatialDiffusion(model.ntElectron, model);
						distributionMultiZone(model.ntElectron, model);
						//distributionSpatialDiffusionSteady(model.ntElectron, model);
					else
						distributionSpatialDiffusion(model.ntElectron, model);
				}
				else {
					readEandRParamSpace("electronInjection_vol", model.ntElectron.injection, 0, 1);
					readEandRParamSpace("electronDistribution_vol", model.ntElectron.distribution, 0, 1);
				}

				if (calculateNTprotons) {
					if (accMethod == 0)
						injection(model.ntProton,model);
					else
						injection(model.ntProton,model);
						//injectionFokkerPlanckOneZone(model.ntProton,model);
					if (accMethod == 0)
						distributionSpatialDiffusionSteady(model.ntProton, model);
						//distributionMultiZoneRadial(model.ntProton, model);
					else
						distributionSpatialDiffusionSteady(model.ntProton, model);
						//distributionFokkerPlanckCompleteSteadyState(model.ntProton, model);
						//distributionFokkerPlanckSpatialDiffusionTimeDependent(model.ntProton, model);
						//distributionFokkerPlanckRadial(model.ntProton,model);
				}
				else {
					readEandRParamSpace("protonInjection_vol", model.ntProton.injection,0,1);
					readEandRParamSpace("protonDistribution_vol", model.ntProton.distribution,0,1);
				}
			}
			else {
				if (calculateNTelectrons) {
					readEandRParamSpace("electronInjection_vol",model.ntElectron.injection,0,1);
					readEandRParamSpace("electronDistribution_vol",model.ntElectron.distribution,0,1);
				}
				if (calculateNTprotons) {
					readEandRParamSpace("protonInjection_vol",model.ntProton.injection,0,1);
					readEandRParamSpace("protonDistribution_vol",model.ntProton.distribution,0,1);
				}
			}

			if (calculateNonThermalLum)
				nonThermalRadiation(model, "lumNonThermal.dat");
			else {
				readEandRParamSpace("photonDensity", model.photon.distribution, 0, 0);
				readEandRParamSpace("NTphotonDensity", model.ntPhoton.distribution, 0, 0);
				readEandRParamSpace("NTphotonDensity", model.ntPhoton.injection, 0, 0);
				readEandRParamSpace("opticalDepth_gg", model.tau_gg, 0, 0);
			}

			if (calculateSecondaries)
				secondariesProcesses(model);
			else {
				readEandRParamSpace("muonDistribution", model.ntMuon.distribution, 0, 0);
				readEandRParamSpace("pionDistribution", model.ntChargedPion.distribution, 0, 0);
			}

			// NEUTRINO TRANSPORT
			if (calculateNeutrinos)
				injectionNeutrino(model.neutrino, model);

			// NEUTRON TRANPOSRT
			if (calculateNeutronInj) {
				injectionNeutrons(model);
				radiativeLossesNeutron(model.ntNeutron,model,"neutronTimescales.dat");
				if (calculateNeutronDis)
					distributionNeutronsAGN(model);
				if (calculateJetDecay)
					jetNeutronDecay(model);
			}
		}
	}
	catch (std::runtime_error& e)
	{
		std::cout << "ERROR: " << e.what() << std::endl;
	}
	return 0;
}*/