#ifndef TRAJI_HPP
#define TRAJI_HPP

#include <vector>
#include <utility>
#include <tuple>
#include <boost/geometry.hpp>
#include <Eigen/Core>

/* forward declarations */
namespace traji {

typedef float TFloat;
typedef Eigen::Matrix<TFloat, 2, 1> Vector2;
typedef Eigen::Matrix<TFloat, 3, 1> Vector3;
typedef Eigen::Matrix<TFloat, 2, 2> Matrix2;
typedef Eigen::Matrix<TFloat, 3, 3> Matrix3;
typedef Eigen::Matrix<TFloat, 6, 1> Vector6;
typedef Eigen::Matrix<TFloat, -1, 1> VectorX;
typedef Eigen::Array<TFloat, -1, 1> ArrayX;

#ifndef M_PI
constexpr TFloat pi = 3.14159265358979323846;
constexpr TFloat pi2 = pi/2;
#else
constexpr TFloat pi = M_PI;
constexpr TFloat pi2 = M_PI_2;
#endif

typedef boost::geometry::model::point<TFloat, 2, boost::geometry::cs::cartesian> Point;
typedef boost::geometry::model::linestring<Point> LineString;

class Path;
class Trajectory;
class HeteroSegment;
class HeteroPath;
class QuinticPolyTrajectory;
class CTRATrajectory;

} // namespace traji

/* helper functions for boost.geometry */
namespace boost { namespace geometry { namespace model
{
inline bool operator==(const traji::Point& lhs, const traji::Point& rhs) { return lhs.get<0>() == rhs.get<0>() && lhs.get<1>() == rhs.get<1>(); }
inline bool operator!=(const traji::Point& lhs, const traji::Point& rhs) { return !(lhs == rhs); }
}}} // namespace boost.geometry.model

/* main implementations */
namespace traji
{

enum class SegmentType
{
    Line, // no params
    Arc, // param: x, y of the arc center
    QuadraticBezier, // param: x, y of the control point
    CubicBezier, // param: x1, y1, x2, y2 of the two control points

    // For polynomials, the latent parameter range need to be normalized to [0, 1]
    Polynomial, // params: polynomial coeffs (high to low)
};

// ==================================== Non-parametric paths ====================================

/// Representation of a position in the path (and possibly extended line)
/// When the position is on the path, 0 <= segment < #segments, 0 <= fraction < 1
/// When the position is on the extended last segment, segment = #segments - 1, fraction >= 1
/// When the position is on the extended first segment, segment = 0, fraction < 0
// TODO: implement comparison operators
struct PathPosition
{
    std::size_t component; // index in multi-path collection
    std::size_t segment; // segment index in the line string
    TFloat fraction; // fraction of the point in the segment

    PathPosition(std::size_t component_, std::size_t segment_, TFloat fraction_)
        : component(component_), segment(segment_), fraction(fraction_) {}
    PathPosition(std::size_t segment_, TFloat fraction_)
        : component(0), segment(segment_), fraction(fraction_) {}

    /// Convert the position to the distance to the beginning
    TFloat to_s(const Path &path) const;
    TFloat to_s(const HeteroPath &path) const;

    /// Convert the distance to the beginning to s
    static PathPosition from_s(const Path &path, TFloat s);
    static PathPosition from_s(const HeteroPath &path, TFloat s);
    static std::vector<PathPosition> from_s(const Path &path, const std::vector<TFloat> &s_list);

    /// Convert the position to the distance to the timestamp
    TFloat to_t(const Trajectory &traj) const;
    static PathPosition from_t(const Trajectory &traj, TFloat t);
    static std::vector<PathPosition> from_t(const Trajectory &path, const std::vector<TFloat> &t_list);

    /// Move the position forward along the path. Note that this function is only efficient
    /// when the distance is not too large. Otherwise please use to_s() and from_s()
    PathPosition forward(const Path &path, TFloat s) const;
    PathPosition backward(const Path &path, TFloat s) const;
};

/// (immutable) non-parametric linestring
class Path
{
protected:
    LineString _line; // the geometry of the line string
    std::vector<TFloat> _distance; // the distance of each vertices to the first vertex along the line.
                                   // first value is zero by default, but can be assigned.

    /// Update _distance values
    void update_distance(TFloat s0 = 0);

    /// Calculate feasible smooth radius given the input as max limit
    std::vector<TFloat> calc_feasible_radius(TFloat smooth_radius) const;

private:
    /// respacing with smooth_radius = 0
    Path respacing0(TFloat resolution) const;
    TFloat solve_curvature(size_t segment_idx) const;

public:
    friend class PathPosition;
    friend class QuinticPolyTrajectory;
    friend class CTRATrajectory;
    friend class HeteroPath;

    inline Path() {}
    template<typename Iterator>
    inline Path(Iterator begin, Iterator end, TFloat s0 = 0) : _line(begin, end) { update_distance(s0); }
    inline Path(std::initializer_list<Point> l) : Path(l.begin(), l.end()) {}
    inline Path(const std::vector<Point> &l, TFloat s0 = 0): Path(l.begin(), l.end(), s0) {}
    inline Path(std::vector<Point> &&l, TFloat s0 = 0): Path(l.begin(), l.end(), s0) {}

    /// The size of a path is the number of segments
    inline std::size_t size() const { return _line.empty() ? 0 : _line.size() - 1; }
    inline TFloat length() const { return _distance.back(); }
    inline std::vector<TFloat> segment_lengths() const
    {
        std::vector<TFloat> lengths(size());
        for (int i = 1; i < _line.size(); i++)
            lengths[i-1] = _distance[i] - _distance[i-1];
        return lengths;
    }

    /// Access the underlying boost linestring
    inline LineString& data() { return _line; }
    inline const LineString& data() const { return _line; }

    /// Access vertices of the path
    inline std::vector<Point>& vertices() { return _line; }
    inline const LineString& vertices() const { return _line; }

    /// Get the point indicated by the distance from the beginning
    inline Point point_from(TFloat s) const
    {
        return point_at(PathPosition::from_s(*this, s));
    }
    Point point_at(const PathPosition &pos) const;

    /// Get the tagent at the point indicated by the distance from the beginning
    inline TFloat tangent_from(TFloat s) const
    {
        return tangent_at(PathPosition::from_s(*this, s));
    }
    TFloat tangent_at(const PathPosition &pos) const;

    /// Get the curvature at given position. The curvature is precise on the vertices, and
    /// interpolated on segments. The curvature is positive if the center is to the left
    /// of the path.
    inline TFloat curvature_from(TFloat s) const
    {
        return curvature_at(PathPosition::from_s(*this, s));
    }
    TFloat curvature_at(const PathPosition &pos) const;

    /// Get the value interpolated by the distance from the beginning
    inline TFloat interpolate_from(const std::vector<TFloat> &values, TFloat s) const
    {
        return interpolate_at(values, PathPosition::from_s(*this, s));
    }
    TFloat interpolate_at(const std::vector<TFloat> &values, const PathPosition &pos) const;

    /// Get the signed distance and foot point from a point to the path. The distance is positive
    /// if the point is at left hand side of the direction of path
    /// @return (distance to the path, projection point position)
    std::pair<TFloat, PathPosition> project(const Point &point) const;

    /// Return the path in a form with equally space points (interpolating over s)
    /// The starting and end point of the original line string is guaranteed to be included and not smoothed
    /// @param smooth_radius The distance from original vertex to the new smoothed vertex.
    Path respacing(TFloat resolution, TFloat smooth_radius = 0) const;

    /// Return the path with each segment's length less than the given resolution
    /// This method will retain the original corner points, unlike respacing function
    Path densify(TFloat resolution) const;

    /// Return the path with rounded corners. This method doesn't change the density of
    /// the points on the line segments
    HeteroPath smooth(TFloat smooth_radius, SegmentType segtype = SegmentType::Arc) const;

    /// Return a path represented by a list of distance to start.
    /// The best performance is achieved when s_list is sorted ascendingly.
    Path resample_from(const std::vector<TFloat> &s_list) const;
};

/// non-parametric linestring with time, assuming constant acceleration
/// the values will still be interpolated based on position
class Trajectory : public Path
{
protected:
    std::vector<TFloat> _timestamps; // the timestamp over each point

private:
    Vector2 solve_velocity(size_t segment_idx) const;
    Vector2 solve_acceleration(size_t point_idx) const;

public:
    friend class PathPosition;
    friend class QuinticPolyTrajectory;
    friend class CTRATrajectory;

    inline Trajectory() {}
    inline Trajectory(const Path& path, const std::vector<TFloat> &timestamps) : Path(path), _timestamps(timestamps) {}
    inline Trajectory(Path&& path, std::vector<TFloat> &&timestamps) : Path(path), _timestamps(timestamps) {}
    template<typename Iterator, typename TIterator>
    inline Trajectory(Iterator begin, Iterator end, TIterator t_begin, TIterator t_end, TFloat s0 = 0)
        : Path(begin, end, s0), _timestamps(t_begin, t_end) { }

    const std::vector<TFloat>& timestamps() const { return _timestamps; }

    /// Get the point indicated by the time
    using Path::point_at;
    inline Point point_at(TFloat t) const
    {
        return point_at(PathPosition::from_t(*this, t));
    }
    using Path::tangent_at;
    inline TFloat tangent_at(TFloat t) const
    {
        return tangent_at(PathPosition::from_t(*this, t));
    }
    Vector2 velocity_at(const PathPosition &pos, bool interpolate = false) const;
    inline Vector2 velocity_from(TFloat s, bool interpolate = false) const
    {
        return velocity_at(PathPosition::from_s(*this, s), interpolate);
    }
    inline Vector2 velocity_at(TFloat t, bool interpolate = false) const
    {
        return velocity_at(PathPosition::from_t(*this, t), interpolate);
    }
    Vector2 acceleration_at(const PathPosition &pos, bool interpolate = false) const;
    inline Vector2 acceleration_from(TFloat s, bool interpolate = false) const
    {
        return acceleration_at(PathPosition::from_s(*this, s), interpolate);
    }
    inline Vector2 acceleration_at(TFloat t, bool interpolate = false) const
    {
        return acceleration_at(PathPosition::from_t(*this, t), interpolate);
    }

    /// Return the trajectory represented by points with equal time intervals
    Trajectory reperiodize(TFloat interval) const;

    /// Return a path represented by a list of timestamp.
    /// The best performance is achieved when t_list is sorted ascendingly.
    Trajectory resample_at(const std::vector<TFloat> &t_list) const;
};

// ==================================== Parametric paths ====================================

/// This class represents an optimal trajectory determined by planning horizon T, starting states (s, v, a)
/// and end states at T. It's represented by a quintic polynomial. Optionally the final position on the x
/// direction can by relaxed by specify `relax_sx` on construction, then the optiimal trajectory is a quartic polynomial.
class QuinticPolyTrajectory
{
protected:
    Vector6 _x_coeffs, _y_coeffs; // high-order to low-order
    TFloat _T; // the trajectory starts at t=0 and ends at t=T

public:
    QuinticPolyTrajectory(TFloat T, const Vector6 &x_coeffs, const Vector6 &y_coeffs)
        : _x_coeffs(x_coeffs), _y_coeffs(y_coeffs), _T(T) {}

    /// Solve optimal trajectory based on x and y states (including 1st and 2nd state derivatives)
    QuinticPolyTrajectory(TFloat T,
                          const Vector3 &x0, const Vector3 &xT,
                          const Vector3 &y0, const Vector3 &yT, bool relax_sx);

    inline const Vector6& x_coeffs() const { return _x_coeffs; }
    inline const Vector6& y_coeffs() const { return _y_coeffs; }
    inline TFloat T() const { return _T; }

    Point point_at(TFloat t) const;
    TFloat tangent_at(TFloat t) const;
    Vector2 velocity_at(TFloat t) const;
    Vector2 acceleration_at(TFloat t) const;

    // Trajectory rasterize(TFloat resolution) const;
    Trajectory periodize(TFloat interval) const;
};

/// Trajectory of a Constant Turn-Rate and (longitudinal) Acceleration model.
class CTRATrajectory
{
protected:
    Vector6 _init_state; // [x, y, theta, v, a, omega]
    TFloat _T;

public:
    CTRATrajectory(TFloat T, const Vector6 &init_state) : _T(T), _init_state(init_state) {}
    CTRATrajectory(TFloat T, Point p, TFloat theta, TFloat v, TFloat a = 0, TFloat omega = 0)
        : _T(T), _init_state() {
        _init_state << p.get<0>(), p.get<1>(), theta, v, a, omega;
    }

    inline const Vector6& initial_state() const { return _init_state; }
    inline TFloat T() const { return _T; }

    Point point_at(TFloat t) const;
    inline TFloat tangent_at(TFloat t) const
    {
        return /*theta*/ _init_state(2) + /*omega*/ _init_state(5) * t;
    }
    Vector2 velocity_at(TFloat t) const;

    Trajectory periodize(TFloat interval) const;
};
// TODO: spline interpolated paths are also parametric paths

// ==================================== Hybrid paths ====================================

struct HeteroSegment
{
    /// Type of the segment
    SegmentType type;

    /// Params for the segments, see SegmentType for details
    std::vector<TFloat> params;

    TFloat length (const Point &start, const Point &end) const;
    Point point_at (const Point &start, const Point &end, TFloat fraction) const;
    TFloat tangent_at (const Point &start, const Point &end, TFloat fraction) const;
};

class HeteroPath
{
protected:
    std::vector<Point> _points;
    std::vector<HeteroSegment> _segments;
    std::vector<TFloat> _distance; // same as Path::_distance

    /// Update _distance values
    void update_distance(TFloat s0 = 0);

public:
    HeteroPath() {}
    inline HeteroPath(const Path& path) : _points(path._line), _distance(path._distance),
        _segments(path.size(), HeteroSegment { SegmentType::Line, {} }) {}
    inline HeteroPath(Path&& path) : _points(std::move(path._line)), _distance(std::move(path._distance)),
        _segments(path.size(), HeteroSegment { SegmentType::Line, {} }) {}
    inline HeteroPath(const std::vector<Point> &points, const std::vector<HeteroSegment> &segments, TFloat s0 = 0) :
        _points(points), _segments(segments) { update_distance(); }

    friend class PathPosition;
    friend class Path;

    /// Access vertices of the path
    inline std::vector<Point>& vertices() { return _points; }
    inline const std::vector<Point>& vertices() const { return _points; }

    /// number of segments
    inline std::size_t size() const { return _segments.size(); }
    /// total length of the hetero path
    inline TFloat length() const { return _distance.back(); }
    /// size of each segment
    inline std::vector<TFloat> segment_lengths() const
    {
        std::vector<TFloat> lengths(size());
        for (int i = 1; i < _points.size(); i++)
            lengths[i-1] = _distance[i] - _distance[i-1];
        return lengths;
    }

    Point point_from(TFloat s)
    {
        return point_at(PathPosition::from_s(*this, s));
    }
    Point point_at(const PathPosition &pos);
    TFloat tangent_from(TFloat s)
    {
        return tangent_at(PathPosition::from_s(*this, s));
    }
    TFloat tangent_at(const PathPosition &pos);

    /// Convert to Path by only rasterizing curves (excl. line segment)
    /// If resolution <= 0, then the result will be directly generated from vertices
    Path rasterize(TFloat resolution = 0) const;

    /// Return the path with each segment's length less than the given resolution
    HeteroPath densify(TFloat resolution) const;
};

// ==================================== frenet paths ====================================

/// In frenet coordinate, Point::x represents s along the path (forward = positive), Point::y
/// represents l along the normal direction of the path (left = positive)
namespace frenet
{
    Point from_cartesian(const Path &ref, const Point &point);
    Point to_cartesian(const Path &ref, const Point &point);

    // TODO: add conversion for dynamic states from/to frenet
    // REF: https://blog.csdn.net/davidhopper/article/details/79162385#t6

    Path from_cartesian(const Path &ref, const Path &path);
    Path to_cartesian(const Path &ref, const Path &path);

    inline Trajectory from_cartesian(const Path &ref, const Trajectory &traj)
    {
        return Trajectory(from_cartesian(ref, (Path&)traj), traj.timestamps());
    }
    inline Trajectory to_cartesian(const Path &ref, const Trajectory &traj)
    {
        return Trajectory(to_cartesian(ref, (Path&)traj), traj.timestamps());
    }

    // Convert the trajectory to cartesian coordinate and adjust vertices position to
    // accomodate curvature change
    Trajectory to_cartesian_rescale(const Path &ref, const Trajectory &traj);
}

// ==================================== binary functions ====================================

inline TFloat distance(const Point &lhs, const Point &rhs) { return boost::geometry::distance(lhs, rhs); }
inline TFloat distance(const Path &lhs, const Point &rhs) { return std::abs(lhs.project(rhs).first); }
inline PathPosition arg_distance(const Path &lhs, const Point &rhs) { return lhs.project(rhs).second; }

/// Return the closest distance at the same time point between two trajectories
TFloat tdistance(const Trajectory &lhs, const Trajectory &rhs);

std::vector<Point> intersection(const Path &lhs, const Path &rhs);
// TODO: make the intersection result sorted?
std::vector<std::pair<PathPosition, PathPosition>> arg_intersection(const Path &lhs, const Path &rhs);

// ==================================== standard functions ====================================

inline bool operator==(const PathPosition& lhs, const PathPosition& rhs)
{
    return std::tie(lhs.component, lhs.segment, lhs.fraction)
        == std::tie(rhs.component, rhs.segment, rhs.fraction);
}
inline bool operator!=(const PathPosition& lhs, const PathPosition& rhs) { return !(lhs == rhs); }
inline bool operator< (const PathPosition& lhs, const PathPosition& rhs)
{
    return std::tie(lhs.component, lhs.segment, lhs.fraction)
        < std::tie(rhs.component, rhs.segment, rhs.fraction);
}
inline bool operator> (const PathPosition& lhs, const PathPosition& rhs) { return rhs < lhs; }
inline bool operator<=(const PathPosition& lhs, const PathPosition& rhs) { return !(lhs > rhs); }
inline bool operator>=(const PathPosition& lhs, const PathPosition& rhs) { return !(lhs < rhs); }

bool operator==(const Path& lhs, const Path& rhs);
inline bool operator!=(const Path& lhs, const Path& rhs) { return !(lhs == rhs); }

} // namespace traji

namespace std
{

std::string to_string(const traji::Point &value);
std::string to_string(const traji::Path &value);
std::string to_string(const traji::PathPosition &value);
std::string to_string(const traji::Trajectory &value);
std::string to_string(const traji::QuinticPolyTrajectory &value);

}

#endif // TRAJI_HPP


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

#include <cstdio>
#include <cstdint>

#include <vector>

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/index/rtree.hpp>

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;

typedef bg::model::d2::point_xy<double> point_t;
typedef bg::model::box<point_t> box_t;
typedef bg::model::polygon<point_t> polygon_t;
typedef bg::model::multi_polygon<polygon_t> multipolygon_t;
typedef std::pair<box_t, int> value_t;
typedef bgi::rtree<value_t, bgi::linear<8>> rtree_t;

std::vector<rtree_t> trees;

extern "C" int add_tree()
{
    trees.emplace_back();
    return trees.size();
}

extern "C" double query(int index, double xmin, double ymin, double xmax, double ymax)
{
    box_t box = box_t(point_t(xmin, ymin), point_t(xmax, ymax));
    multipolygon_t difference;
    bg::convert(box, difference);
    std::vector<value_t> results;

    trees[index].query(bgi::intersects(box), std::back_inserter(results));

    for (const auto &result : results)
    {
        multipolygon_t new_difference;
        bg::difference(difference, result.first, new_difference);
        difference = new_difference;
    }

    return (bg::area(difference) / bg::area(box));
}

extern "C" void insert(int index, double xmin, double ymin, double xmax, double ymax)
{
    box_t box = box_t(point_t(xmin, ymin), point_t(xmax, ymax));
    trees[index].insert(std::make_pair(box, 33));
}


// Copyright (c) 2015-2020 Daniel Cooke
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

#include "posterior_probability_by_depth.hpp"

#include <boost/variant.hpp>
#include <boost/optional.hpp>

#include "io/variant/vcf_record.hpp"
#include "posterior_probability.hpp"

namespace octopus { namespace csr {

const std::string PosteriorProbabilityByDepth::name_ = "PPD";

PosteriorProbabilityByDepth::PosteriorProbabilityByDepth(bool recalculate) : depth_ {recalculate, true} {}

std::unique_ptr<Measure> PosteriorProbabilityByDepth::do_clone() const
{
    return std::make_unique<PosteriorProbabilityByDepth>(*this);
}

Measure::ValueType PosteriorProbabilityByDepth::get_value_type() const
{
    return double {};
}

Measure::ResultType PosteriorProbabilityByDepth::do_evaluate(const VcfRecord& call, const FacetMap& facets) const
{
    Optional<ValueType> result {};
    const auto posterior_probability = boost::get<Optional<ValueType>>(PosteriorProbability().evaluate(call, facets));
    if (posterior_probability) {
        const auto depth = boost::get<std::size_t>(boost::get<ValueType>(depth_.evaluate(call, facets)));
        if (depth > 0) {
            result = boost::get<double>(*posterior_probability) / depth;
        }
    }
    return result;
}

Measure::ResultCardinality PosteriorProbabilityByDepth::do_cardinality() const noexcept
{
    return depth_.cardinality();
}

const std::string& PosteriorProbabilityByDepth::do_name() const
{
    return name_;
}

std::string PosteriorProbabilityByDepth::do_describe() const
{
    return "PP divided by DP";
}

std::vector<std::string> PosteriorProbabilityByDepth::do_requirements() const
{
    return depth_.requirements();
}

bool PosteriorProbabilityByDepth::is_equal(const Measure& other) const noexcept
{
    return depth_ == static_cast<const PosteriorProbabilityByDepth&>(other).depth_;
}

} // namespace csr
} // namespace octopus


#include "Logit.h"
#include "../Obs.h"
#include "../Scheme.h"
#include "../Parameters.h"
#include "../Variables/Variable.h"
#include "../Measures/Measure.h"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>

DiscreteLogit::DiscreteLogit(const Options& iOptions, const Data& iData) : Discrete(iOptions, iData),
      mUseConst(false) {

   //! Include the constant term in the regression?
   iOptions.getValue("useConst", mUseConst);
   std::vector<std::string> measureTags;

   //! Ensemble measures to use in regression model
   iOptions.getValues("measures", measureTags);
   for(int i = 0; i < measureTags.size(); i++) {
      Measure* measure = Measure::getScheme(measureTags[i], mData);
      mMeasures.push_back(measure);
   }

   mNumCoeff = mUseConst + mMeasures.size();
   if(mNumCoeff == 0) {
      std::stringstream ss;
      ss << "DiscreteLogit: At least one of 'useConst' and 'measures' must selected";
      Global::logger->write(ss.str(), Logger::error);
   }

   if(mEstimator == NULL) {
      std::stringstream ss;
      ss << "DiscreteLogit: No estimator specified. Default to EstimatorMaximumLikelihood.";
      Global::logger->write(ss.str(), Logger::message);
      Options opt("tag=test class=EstimatorMaximumLikelihood");
      mEstimator = EstimatorProbabilistic::getScheme(opt, iData, *this);
   }
   iOptions.check();
}

float DiscreteLogit::getPCore(const Ensemble& iEnsemble, const Parameters& iParameters) const {
   std::vector<float> vars;
   getVariables(iEnsemble, vars);

   if(mEstimator) {
      assert(vars.size() == iParameters.size());
   }
   else {
      assert((int) vars.size() + vars.size()*vars.size() == iParameters.size());
   }

   // Add up regression terms
   float logit = 0;
   for(int i = 0; i < mNumCoeff; i++) {
      if(!Global::isValid(iParameters[i]) || !Global::isValid(vars[i])) {
         return Global::MV;
      }
      logit += iParameters[i] * vars[i];
   }

   assert(Global::isValid(logit));
   float P = exp(logit)/(1 + exp(logit));

   assert(P>=0 && P <= 1);
   return P;
}

void DiscreteLogit::getDefaultParametersCore(Parameters& iParameters) const {
   std::vector<float> param(mNumCoeff,0);
   iParameters.setAllParameters(param);
}

void DiscreteLogit::getVariables(const Ensemble& iEnsemble, std::vector<float>& iVariables) const {
   iVariables.clear();
   if(mUseConst) {
      iVariables.push_back(1);
   }
   for(int i = 0; i < mMeasures.size(); i++) {
      // TODO: Parameters
      float measure = mMeasures[i]->measure(iEnsemble);
      iVariables.push_back(measure);
   }
   assert((int) iVariables.size() == mNumCoeff);
}
void DiscreteLogit::getCoefficients(const Parameters& iParameters, Parameters& iCoefficients) const {
   std::vector<float> param;
   param.resize(mNumCoeff);

   assert(iParameters.size() == mNumCoeff + mNumCoeff*mNumCoeff);
   for(int i = 0; i < mNumCoeff; i++) {
      param[i] = iParameters[i];
   }
   iCoefficients.setAllParameters(param);
}
void DiscreteLogit::updateParametersCore(const std::vector<Ensemble>& iEnsemble, const std::vector<Obs>& iObs, Parameters& iParameters) const {
   std::stringstream ss;
   ss << "DiscreteLogit: Does not have its own parameter estimator. Must use external estimator";
   Global::logger->write(ss.str(), Logger::error);
}

float DiscreteLogit::getLambda() const {
   assert(Global::isValid(mEfold));
   return 1 - 1/mEfold;
}

bool DiscreteLogit::getH(const Obs& iObs, const Ensemble& iEnsemble, const Parameters& iParameters, std::vector<float>& iH) const {

   iH.clear();
   iH.resize(mNumCoeff);

   std::vector<float> gradL;
   bool status = getGradL(iObs, iEnsemble, iParameters, gradL);
   if(!status) {
      return false;
   }
   //std::cout << "Grad = " << gradL[0] << std::endl;
   assert((int) gradL.size() == mNumCoeff);

   float L = getLikelihood(iObs.getValue(), iEnsemble, iParameters);
   assert(L > 0);
   if(!Global::isValid(L)) {
      return false;
   }
   for(int i = 0; i < mNumCoeff; i++) {
      float value = gradL[i]/L;
      iH[i] = value;
   }
   return true;
}

bool DiscreteLogit::getGradL(const Obs& iObs, const Ensemble& iEnsemble, const Parameters& iParameters, std::vector<float>& iGradL) const {

   iGradL.clear();
   iGradL.resize(mNumCoeff);

   Parameters coeffs;
   getCoefficients(iParameters, coeffs);

   float dx = 0.001;
   float L0 = getLikelihood(iObs.getValue(), iEnsemble, iParameters);
   if(!Global::isValid(L0))
      return false;
   for(int i = 0; i < mNumCoeff; i++) {
      // Perturb current parameter
      Parameters par = iParameters;
      par[i] += dx;

      // Compute likelihood derivative
      float currL = getLikelihood(iObs.getValue(), iEnsemble, par);
      if(!Global::isValid(currL))
         return false;
      float dL = currL - L0;
      iGradL[i] = dL/dx;
   }
   return true;
}

bool DiscreteLogit::getInverse(boost::numeric::ublas::matrix<float> iMatrix, boost::numeric::ublas::matrix<float>& iInverse) {
   // Taken from https://gist.github.com/2464434
   using namespace boost::numeric::ublas;
   typedef permutation_matrix<std::size_t> pmatrix;
   // create a working copy of the input
   matrix<float> A(iMatrix);
   // create a permutation matrix for the LU-factorization
   pmatrix pm(A.size1());

   // perform LU-factorization
   int res = lu_factorize(A,pm);
   if( res != 0 ) return false;

   // create identity matrix of "inverse"
   iInverse.assign(identity_matrix<float>(A.size1()));

   // backsubstitute to get the inverse
   lu_substitute(A, pm, iInverse);

   return true;
}
int DiscreteLogit::numParametersCore() const {
   return mNumCoeff;
}


#ifndef ASSEMBLY_VALUES_HPP
#define ASSEMBLY_VALUES_HPP

#include <polyfem/Quadrature.hpp>
#include <polyfem/Basis.hpp>

#include <Eigen/Dense>
#include <iostream>

//stores per local bases evaluations
namespace polyfem
{
	class AssemblyValues
	{
	public:
		// Weighted sum to express the current ("virtual") node as a linear-combination
		// of the real (unknown) nodes
		std::vector<Local2Global> global;

		// Evaluation of the basis over the quadrature points of the element
		Eigen::MatrixXd val; // R^m

		// Gradient of the basis over the quadrature points
		Eigen::MatrixXd grad; // R^{m x dim}

		// Gradient of the basis pre-multiplied by the inverse transpose of the
		// Jacobian of the geometric mapping of the element
		Eigen::MatrixXd grad_t_m; // J^{-T}*∇φi per row R^{m x dim}

		void finalize()
		{
			grad_t_m.resize(grad.rows(), grad.cols());
		}
	};
} // namespace polyfem

#endif //ASSEMBLY_VALUES_HPP


#include <mpi.h>
#include <sys/time.h>
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
#include <sstream>
#ifdef NOTR1
	#include <boost/tr1/tuple.hpp>
#else
	#include <tr1/tuple>
#endif
#include "../SpParVec.h"
#include "../SpTuples.h"
#include "../SpDCCols.h"
#include "../SpParMat.h"
#include "../DenseParMat.h"
#include "../FullyDistVec.h"
#include "../SpDefs.h"

using namespace std;

// Simple helper class for declarations: Just the numerical type is templated
// The index type and the sequential matrix type stays the same for the whole code
// In this case, they are "int" and "SpDCCols"
template <class NT>
class PSpMat
{
public:
	typedef SpDCCols < int, NT > DCCols;
	typedef SpParMat < int, NT, DCCols > MPI_DCCols;
};

int main(int argc, char* argv[])
{
	MPI::Init(argc, argv);
	int nprocs = MPI::COMM_WORLD.Get_size();
	int myrank = MPI::COMM_WORLD.Get_rank();

	if(argc < 4)
	{
		if(myrank == 0)
		{
			cout << "Usage: ./ReduceTest <MatrixA> <SumColumns> <SumRows>" << endl;
			cout << "<Matrix>,<SumColumns>,<SumRows> are absolute addresses, and files should be in triples format" << endl;
		}
		MPI::Finalize();
		return -1;
	}
	{
		string Aname(argv[1]);
		string Bname(argv[2]);
		string Cname(argv[3]);

		ifstream inputA(Aname.c_str());
		ifstream inputB(Bname.c_str());
		ifstream inputC(Cname.c_str());

		MPI::COMM_WORLD.Barrier();

		PSpMat<double>::MPI_DCCols A;
		FullyDistVec<int,double> colsums(A.getcommgrid(), 0.0);
		FullyDistVec<int,double> rowsums(A.getcommgrid(), 0.0);

		A.ReadDistribute(inputA, 0);
		colsums.ReadDistribute(inputB, 0);
		rowsums.ReadDistribute(inputC, 0);

		FullyDistVec< int, double > rowsums_control, colsums_control;
		A.Reduce(rowsums_control, Row, std::plus<double>() , 0.0);
		A.Reduce(colsums_control, Column, std::plus<double>() , 0.0);

		if (rowsums_control == rowsums && colsums_control == colsums)
		{
			SpParHelper::Print("Reduction via summation working correctly\n");
		}
		else
		{
			SpParHelper::Print("ERROR in Reduce via summation, go fix it!\n");
		}

		inputA.clear();
		inputA.close();
		inputB.clear();
		inputB.close();
		inputC.clear();
		inputC.close();
	}
	MPI::Finalize();
	return 0;
}


// Copyright 2020 Open Source Robotics Foundation, Inc.
// All rights reserved.
//
// Software License Agreement (BSD License 2.0)
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//  * Neither the name of Open Source Robotics Foundation, Inc. nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

/*
 * Author: Adam Leeper, Stuart Glaser
 */

#ifndef TF2_EIGEN_KDL__TF2_EIGEN_KDL_HPP_
#define TF2_EIGEN_KDL__TF2_EIGEN_KDL_HPP_

#include <Eigen/Core>
#include <Eigen/Geometry>

#include <kdl/frames.hpp>

#include <tf2/impl/convert.h>

#include "tf2_eigen_kdl/visibility_control.h"

namespace tf2
{

/// Converts a KDL rotation into an Eigen quaternion
TF2_EIGEN_KDL_PUBLIC
void quaternionKDLToEigen(const KDL::Rotation & k, Eigen::Quaterniond & e);

/// Converts an Eigen quaternion into a KDL rotation
TF2_EIGEN_KDL_PUBLIC
void quaternionEigenToKDL(const Eigen::Quaterniond & e, KDL::Rotation & k);

/// Converts a KDL frame into an Eigen Affine3d
TF2_EIGEN_KDL_PUBLIC
void transformKDLToEigen(const KDL::Frame & k, Eigen::Affine3d & e);

/// Converts a KDL frame into an Eigen Isometry3d
TF2_EIGEN_KDL_PUBLIC
void transformKDLToEigen(const KDL::Frame & k, Eigen::Isometry3d & e);

/// Converts an Eigen Affine3d into a KDL frame
TF2_EIGEN_KDL_PUBLIC
void transformEigenToKDL(const Eigen::Affine3d & e, KDL::Frame & k);

/// Converts an Eigen Isometry3d into a KDL frame
TF2_EIGEN_KDL_PUBLIC
void transformEigenToKDL(const Eigen::Isometry3d & e, KDL::Frame & k);

/// Converts a KDL twist into an Eigen matrix
TF2_EIGEN_KDL_PUBLIC
void twistKDLToEigen(const KDL::Twist & k, Eigen::Matrix<double, 6, 1> & e);

/// Converts an Eigen matrix into a KDL Twist
TF2_EIGEN_KDL_PUBLIC
void twistEigenToKDL(const Eigen::Matrix<double, 6, 1> & e, KDL::Twist & k);

/// Converts a KDL vector into an Eigen matrix
TF2_EIGEN_KDL_PUBLIC
void vectorKDLToEigen(const KDL::Vector & k, Eigen::Matrix<double, 3, 1> & e);

/// Converts an Eigen matrix into a KDL vector
TF2_EIGEN_KDL_PUBLIC
void vectorEigenToKDL(const Eigen::Matrix<double, 3, 1> & e, KDL::Vector & k);

/// Converts a KDL wrench into an Eigen matrix
TF2_EIGEN_KDL_PUBLIC
void wrenchKDLToEigen(const KDL::Wrench & k, Eigen::Matrix<double, 6, 1> & e);

/// Converts an Eigen matrix into a KDL wrench
TF2_EIGEN_KDL_PUBLIC
void wrenchEigenToKDL(const Eigen::Matrix<double, 6, 1> & e, KDL::Wrench & k);

namespace impl
{

template<>
template<>
inline void Converter<false, false>::convert(const KDL::Rotation & a, Eigen::Quaterniond & b)
{
  quaternionKDLToEigen(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const Eigen::Quaterniond & a, KDL::Rotation & b)
{
  quaternionEigenToKDL(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const KDL::Frame & a, Eigen::Affine3d & b)
{
  transformKDLToEigen(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const KDL::Frame & a, Eigen::Isometry3d & b)
{
  transformKDLToEigen(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const Eigen::Affine3d & a, KDL::Frame & b)
{
  transformEigenToKDL(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const Eigen::Isometry3d & a, KDL::Frame & b)
{
  transformEigenToKDL(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const KDL::Twist & a, Eigen::Matrix<double, 6, 1> & b)
{
  twistKDLToEigen(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const Eigen::Matrix<double, 6, 1> & a, KDL::Twist & b)
{
  twistEigenToKDL(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const KDL::Vector & a, Eigen::Matrix<double, 3, 1> & b)
{
  vectorKDLToEigen(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const Eigen::Matrix<double, 3, 1> & a, KDL::Vector & b)
{
  vectorEigenToKDL(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const KDL::Wrench & a, Eigen::Matrix<double, 6, 1> & b)
{
  wrenchKDLToEigen(a, b);
}

template<>
template<>
inline void Converter<false, false>::convert(const Eigen::Matrix<double, 6, 1> & a, KDL::Wrench & b)
{
  wrenchEigenToKDL(a, b);
}
}  // namespace impl

}  // namespace tf2

#endif  // TF2_EIGEN_KDL__TF2_EIGEN_KDL_HPP_


/*
 *  @file 		ex1.cpp
 *  @details  	This file is the solution to exercise 1.
 *  @author    	Alexander Rettkowski
 *  @date      	22.04.2017
 */

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

#include <iostream>
#include <string>
#include <complex>
#include <fstream>

namespace exercise1
{
	namespace qi = boost::spirit::qi;
	namespace ascii = boost::spirit::ascii;

	/**
		* This struct is used in the boost::qi parser.
	*/
	struct line
	{
		int id;
		int location;
		double value;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	exercise1::line,
	(int, id)
	(int, location)
	(double, value)
)

namespace exercise1
{
	template <typename Iterator>
	struct line_parser : qi::grammar<Iterator, line(), ascii::space_type>
	{
		line_parser() : line_parser::base_type(start)
		{
			using qi::int_;
			using qi::double_;

			start %= int_ >> ';' >> int_ >> ";" >> double_;
		}

		qi::rule<Iterator, line(), ascii::space_type> start;
	};
}

/**
 * The main function that reads in a file and processes it.
 * @param argc Number of command line arguments.
 * @param *argv a pointer to the array of command line arguments.
 */
int main(int argc, char *argv[])
{
	using boost::spirit::ascii::space;
	typedef std::string::const_iterator iterator_type;
	typedef exercise1::line_parser<iterator_type> line_parser;
	line_parser parser;
	std::string currentLine;
	std::ifstream file(argv[1]);
	std::vector<double> values[2];
	double mean[2]{0.0, 0.0};
	long numberOfLines = 0;

	while (getline(file, currentLine))
	{
		numberOfLines++;

		exercise1::line parsedLine;
		std::string::const_iterator currentPosition = currentLine.begin();
		std::string::const_iterator lineEnd = currentLine.end();
		bool parsingSucceeded = phrase_parse(currentPosition, lineEnd, parser, space, parsedLine);

		if (parsingSucceeded && currentPosition == lineEnd)
		{
			if (std::isnan(parsedLine.value) || parsedLine.value <= 0 || parsedLine.location < 1 || parsedLine.location > 2)
				continue;
			values[--parsedLine.location].push_back(parsedLine.value);
		}
	}

	file.close();

	for (int i = 0; i < 2; i++)
	{
		for (double d : values[i])
		{
			mean[i] += std::log2(d);
		}
		mean[i] = std::exp2(mean[i] / values[i].size());
	}

	printf("File: %s with %ld lines\n", argv[1], numberOfLines);
	printf("Valid values Loc1: %ld with GeoMean: %f\n", values[0].size(), mean[0]);
	printf("Valid values Loc2: %ld with GeoMean: %f\n", values[1].size(), mean[1]);
	return 0;
}


// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// 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)
//
// Projection example 2, using factory

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

#include <boost/geometry/extensions/gis/latlong/latlong.hpp>
#include <boost/geometry/extensions/gis/projections/parameters.hpp>
#include <boost/geometry/extensions/gis/projections/factory.hpp>

#include <boost/shared_ptr.hpp>

int main()
{
    using namespace boost::geometry;

    // Initialize projection parameters. For construction using a factory the projection name is required.
    projections::parameters par = projections::init("+proj=robin +ellps=WGS84 +units=m");

    // Construct the specified projection, using specified point types
    // Note that this is the only difference from p01_projection_example. It constructs a projection
    // with virtual methods, which can be used polymorphically. Therefore it is a pointer. For
    // convenience we use a boost shared pointer here.
    typedef model::ll::point<degree> point_ll_deg;
    typedef model::d2::point_xy<double> point_xy;
    projections::factory<point_ll_deg, point_xy> fac;
    boost::shared_ptr<projections::projection<point_ll_deg, point_xy> > prj(fac.create_new(par));

    // Define Amsterdam / Barcelona in decimal degrees / degrees/minutes
    point_ll_deg amsterdam(longitude<>(5.9), latitude<>(52.4));
    point_ll_deg barcelona(
        latitude<>(dms<north>(41, 23)),
        longitude<>(dms<east>(2, 11))
        );

    point_xy pa, pb;

    // Do the forward projection
    if (prj->forward(amsterdam, pa) && prj->forward(barcelona, pb))
    {
        std::cout << "Amsterdam: " << wkt(pa) << std::endl << "Barcelona: " << wkt(pb) << std::endl;

        std::cout << "Distance (unprojected):" << distance(amsterdam, barcelona) / 1000.0 << " km" << std::endl;
        std::cout << "Distance (  projected):" << distance(pa, pb) / 1000.0 << " km" << std::endl;

        // Get the inverse
        point_ll_deg a1;
        if (prj->inverse(pa, a1))
        {
            std::cout << "Amsterdam (original): " << wkt(amsterdam)  << std::endl
                << "Amsterdam (projected, and back):" << wkt(a1) << std::endl;
            std::cout << "Distance a-a': " << distance(amsterdam, a1) << " meter" << std::endl;
        }
    }

    return 0;
}


#include <CGAL/Surface_mesh.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/boost/graph/Graph_with_descriptor_with_graph.h>

#include <boost/graph/graph_concepts.hpp>
#include <CGAL/boost/graph/graph_concepts.h>

typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> SM;
typedef CGAL::Graph_with_descriptor_with_graph<SM> Surface_mesh;
typedef boost::graph_traits< Surface_mesh > Traits;
typedef Traits::edge_descriptor edge_descriptor;
typedef Traits::halfedge_descriptor halfedge_descriptor;
typedef Traits::vertex_descriptor vertex_descriptor;
typedef Traits::face_descriptor face_descriptor;

void concept_check_surface_mesh()
{
  boost::function_requires< boost::GraphConcept<Surface_mesh> >();
  boost::function_requires< boost::VertexListGraphConcept<Surface_mesh> >();
  boost::function_requires< boost::EdgeListGraphConcept<Surface_mesh> >();
  boost::function_requires< boost::IncidenceGraphConcept<Surface_mesh> >();
  boost::function_requires< boost::AdjacencyMatrixConcept<Surface_mesh> >();
  boost::function_requires< boost::BidirectionalGraphConcept<Surface_mesh> >();
  boost::function_requires< CGAL::HalfedgeGraphConcept<Surface_mesh> >();
  boost::function_requires< CGAL::HalfedgeListGraphConcept<Surface_mesh> >();
  boost::function_requires< CGAL::FaceGraphConcept<Surface_mesh> >();
  boost::function_requires< CGAL::FaceListGraphConcept<Surface_mesh> >();
  boost::function_requires< CGAL::MutableHalfedgeGraphConcept<Surface_mesh> >();
  boost::function_requires< CGAL::MutableFaceGraphConcept<Surface_mesh> >();

  boost::function_requires< boost::concepts::ReadablePropertyGraph<
    Surface_mesh, halfedge_descriptor, CGAL::halfedge_index_t> >();
  boost::function_requires< boost::concepts::ReadablePropertyGraph<
    Surface_mesh, edge_descriptor, boost::edge_index_t> >();
  boost::function_requires< boost::concepts::ReadablePropertyGraph<
    Surface_mesh, edge_descriptor, boost::edge_weight_t> >();
  boost::function_requires< boost::concepts::PropertyGraph<
    Surface_mesh, vertex_descriptor, CGAL::vertex_point_t> >();
  boost::function_requires< boost::concepts::ReadablePropertyGraph<
    Surface_mesh, vertex_descriptor, boost::vertex_index_t> >();
  boost::function_requires< boost::concepts::ReadablePropertyGraph<
    Surface_mesh, face_descriptor, CGAL::face_index_t> >();

  // null
  boost::graph_traits<Surface_mesh>::null_vertex();
  boost::graph_traits<Surface_mesh>::null_halfedge();
  boost::graph_traits<Surface_mesh>::null_face();
}

int main()
{
  concept_check_surface_mesh();
  return 0;
}


// Copyright (c) 2015 The Dogecoin Core developers
// Copyright (c) 2021-2022 The CoinGreen Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "arith_uint256.h"
#include "chainparams.h"
#include "coingreen.h"
#include "test/test_bitcoin.h"

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(coingreen_tests, TestingSetup)

BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
    uint32_t nHeight = 1;
    const CChainParams& mainParams = Params(CBaseChainParams::MAIN);
    CAmount subsidy = 0;
    CAmount sum = GENESIS_BLOCK_REWARD * COIN;
    uint256 prevHash = uint256S("0");

    uint32_t nThreshold = (INITIAL_SUPPLY - GENESIS_BLOCK_REWARD - FOUNDER_MINT)/REWARD_PER_BLOCK + 1;

    for (nHeight = 1; nHeight <= nThreshold; nHeight++) {
        subsidy = GetCoinGreenBlockSubsidy(nHeight, mainParams.GetConsensus(nHeight), prevHash);
        sum += subsidy;
        BOOST_CHECK(subsidy == ((nHeight == mainParams.GetConsensus(nHeight).nFounderMintHeight ? FOUNDER_MINT : REWARD_PER_BLOCK) * COIN));
    }
    subsidy = GetCoinGreenBlockSubsidy(nHeight, mainParams.GetConsensus(nHeight), prevHash);
    CAmount expected = (INITIAL_SUPPLY - FOUNDER_MINT - (nThreshold-1)*REWARD_PER_BLOCK - GENESIS_BLOCK_REWARD);
    BOOST_CHECK(subsidy == expected * COIN);
    sum += subsidy;

    subsidy = GetCoinGreenBlockSubsidy(nHeight+1, mainParams.GetConsensus(nHeight), prevHash);
    BOOST_CHECK(subsidy == 0);

    subsidy = GetCoinGreenBlockSubsidy(nHeight+100, mainParams.GetConsensus(nHeight), prevHash);
    BOOST_CHECK(subsidy == 0);

    BOOST_CHECK(sum/COIN == INITIAL_SUPPLY);

}

BOOST_AUTO_TEST_SUITE_END()


/**
 * @file test_potential.cpp
 * @brief This file defines the test cases for the potential calculation.
 *
 * @copyright Copyright (c) 2022
 *
 */

#include <algorithm>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <cstddef>
#include <eigen3/Eigen/Core>
#include <iterator>
#include <memory>
#include <string>
#include <vector>

#include "proseco_planning/agent/cost_model/costModel.h"
#include "proseco_planning/agent/desire.h"
#include "proseco_planning/agent/vehicle.h"
#include "proseco_planning/config/computeOptions.h"
#include "proseco_planning/config/configuration.h"
#include "proseco_planning/config/defaultConfiguration.h"
#include "proseco_planning/config/scenarioOptions.h"

using namespace proseco_planning;

BOOST_AUTO_TEST_SUITE(potential)

BOOST_AUTO_TEST_CASE(laneCenterDeviation) {
  Config::create(config::scenarioSimple, config::optionsSimple);

  int lane{1};

  Vehicle vehicle(config::vehicle);
  vehicle.m_positionX = 0;
  vehicle.m_velocityX = 35.0;
  vehicle.setLane(lane);
  Desire desire = Desire(config::Desire(35.0, 0, lane, 0));

  std::vector<float> v1(50, 1.0);
  Eigen::MatrixXd w1 = config::CostModel::convertVectorToEigenMatrix(v1, 10, 5);
  std::vector<float> v2(5, 1.0);
  Eigen::MatrixXd w2 = config::CostModel::convertVectorToEigenMatrix(v2, 5, 1);
  // Set cost Parameter and generate cost model
  auto configCostModel = config::CostModel("costContinuous", -50, 20, 100, 30, -1, 0, -500, -500,
                                           -500, -10, 0, 1, 1, 1, 1, 1, 1, 1, w1, w2);

  auto costModel = CostModel::createCostModel(configCostModel);

  const unsigned int steps = 11;
  std::vector<float> potentialLaneCenterOffset(steps);
  for (size_t offset = 0; offset < potentialLaneCenterOffset.size(); ++offset) {
    vehicle.m_positionY               = sOpt().road.lane_width * (lane + offset / 10.f);
    potentialLaneCenterOffset[offset] = costModel->updateStatePotential(desire, vehicle);
  }

  std::vector<float> potentialLaneCenterOffsetReverse(potentialLaneCenterOffset.size());
  std::reverse_copy(std::begin(potentialLaneCenterOffset), std::end(potentialLaneCenterOffset),
                    std::begin(potentialLaneCenterOffsetReverse));
  for (size_t i = 0; i < potentialLaneCenterOffset.size(); ++i) {
    BOOST_REQUIRE_SMALL(potentialLaneCenterOffsetReverse[i] - potentialLaneCenterOffset[i],
                        float(0.001));
  }
}

BOOST_AUTO_TEST_SUITE_END()


//
//	HSPVAR core module
//	onion software/onitama 2003/4
//
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#define NOMINMAX
#include <Windows.h>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <memory>
#include "../HSP_Includes/hsp3plugin.h"
#include "../HSP_Includes/hspvar_core.h"
#include "../HSP_Includes/hsp3debug.h"
#include <boost/multiprecision/cpp_int.hpp>
/*------------------------------------------------------------*/
/*
HSPVAR core interface (Boost_Longint)
*/
/*------------------------------------------------------------*/
typedef boost::multiprecision::cpp_int boost_longint;
#define GetPtr(pval) ((boost_longint *)pval)
#define sbAlloc hspmalloc
#define sbFree hspfree

static int mytype;
static boost_longint conv;
static short *aftertype;
static std::string sstr;
static int sint;
static double sdouble;

// Core
static PDAT *HspVarBoost_Longint_GetPtr(PVal *pval)
{
	return (PDAT *)(((boost_longint *)(pval->pt)) + pval->offset);
}

static void *HspVarBoost_Longint_Cnv(const void *buffer, int flag)
{
	//		リクエストされた型 -> 自分の型への変換を行なう
	//		(組み込み型にのみ対応でOK)
	//		(参照元のデータを破壊しないこと)
	//
	switch (flag) {
	case HSPVAR_FLAG_STR:
		conv = boost_longint(std::string((char*)buffer));
		return &conv;
	case HSPVAR_FLAG_INT:
		conv = (boost_longint)(*(int *)buffer);
		return &conv;
	case HSPVAR_FLAG_DOUBLE:
		conv = (boost_longint)(*(double *)buffer);
		break;
	default:
		throw HSPVAR_ERROR_TYPEMISS;
	}
	return (void *)buffer;
}

static void *HspVarBoost_Longint_CnvCustom(const void *buffer, int flag)
{
	//		(カスタムタイプのみ)
	//		自分の型 -> リクエストされた型 への変換を行なう
	//		(組み込み型に対応させる)
	//		(参照元のデータを破壊しないこと)
	//
	boost_longint p;
	p = *(boost_longint *)buffer;
	std::string sdata;
	switch (flag) {
	case HSPVAR_FLAG_STR:
		sstr= p.str();
		return const_cast<char *>(sstr.c_str());
		break;
	case HSPVAR_FLAG_INT:
		sint = static_cast<int>(p);
		return &sint;
		break;
	case HSPVAR_FLAG_DOUBLE:
		sdouble = static_cast<double>(p);
		return &sdouble;
		break;
	default:
		throw HSPVAR_ERROR_TYPEMISS;
	}
	return nullptr;
}

static int GetVarSize(PVal *pval)
{
	//		PVALポインタの変数が必要とするサイズを取得する
	//		(sizeフィールドに設定される)
	//
	int size;
	size = pval->len[1];
	if (pval->len[2]) size *= pval->len[2];
	if (pval->len[3]) size *= pval->len[3];
	if (pval->len[4]) size *= pval->len[4];
	size *= sizeof(boost_longint);
	return size;
}

static void HspVarBoost_Longint_Free(PVal *pval)
{
	//		PVALポインタの変数メモリを解放する
	//
	if (pval->mode == HSPVAR_MODE_MALLOC) { sbFree(pval->pt); }
	pval->pt = NULL;
	pval->mode = HSPVAR_MODE_NONE;
}

static void HspVarBoost_Longint_Alloc(PVal *pval, const PVal *pval2)
{
	//		pval変数が必要とするサイズを確保する。
	//		(pvalがすでに確保されているメモリ解放は呼び出し側が行なう)
	//		(flagの設定は呼び出し側が行なう)
	//		(pval2がNULLの場合は、新規データ)
	//		(pval2が指定されている場合は、pval2の内容を継承して再確保)
	//
	int i, size;
	char *pt;
	boost_longint *fv;
	if (pval->len[1] < 1) pval->len[1] = 1;		// 配列を最低1は確保する
	size = GetVarSize(pval);
	pval->mode = HSPVAR_MODE_MALLOC;
	pt = sbAlloc(size);
	fv = (boost_longint *)pt;
	for (i = 0; i<(int)(size / sizeof(boost_longint)); i++) { fv[i] = 0; }
	if (pval2 != NULL) {
		memcpy(pt, pval->pt, pval->size);
		sbFree(pval->pt);
	}
	pval->pt = pt;
	pval->size = size;
}

/*
static void *HspVarBoost_Longint_ArrayObject( PVal *pval, int *mptype )
{
//		配列要素の指定 (文字列/連想配列用)
//
throw HSPERR_UNSUPPORTED_FUNCTION;
return NULL;
}
*/

// Size
static int HspVarBoost_Longint_GetSize(const PDAT *pval)
{
	return sizeof(boost_longint);
}

// Set
static void HspVarBoost_Longint_Set(PVal *pval, PDAT *pdat, const void *in)
{
	*GetPtr(pdat) = *((boost_longint *)(in));
}

// Add
static void HspVarBoost_Longint_AddI(PDAT *pval, const void *val)
{
	*GetPtr(pval) += *((boost_longint *)(val));
	*aftertype = mytype;
}

// Sub
static void HspVarBoost_Longint_SubI(PDAT *pval, const void *val)
{
	*GetPtr(pval) -= *((boost_longint *)(val));
	*aftertype = mytype;
}

// Mul
static void HspVarBoost_Longint_MulI(PDAT *pval, const void *val)
{
	*GetPtr(pval) *= *((boost_longint *)(val));
	*aftertype = mytype;
}

// Div
static void HspVarBoost_Longint_DivI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) /= p;
	*aftertype = mytype;
}
// Mod
static void HspVarBoost_Longint_ModI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) %= p;
	*aftertype = mytype;
}
// And
static void HspVarBoost_Longint_AndI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) &= p;
	*aftertype = mytype;
}
// Or
static void HspVarBoost_Longint_OrI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) |= p;
	*aftertype = mytype;
}
// Xor
static void HspVarBoost_Longint_XorI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) ^= p;
	*aftertype = mytype;
}
static void HspVarBoost_Longint_RrI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) >>= static_cast<int>(p);
	*aftertype = mytype;
}
// Xor
static void HspVarBoost_Longint_LrI(PDAT *pval, const void *val)
{
	boost_longint p = *((boost_longint *)(val));
	if (p == 0) throw(HSPVAR_ERROR_DIVZERO);
	*GetPtr(pval) <<= static_cast<int>(p);
	*aftertype = mytype;
}
// Eq
static void HspVarBoost_Longint_EqI(PDAT *pval, const void *val)
{
	*((int *)pval) = (*GetPtr(pval) == *((boost_longint *)(val)));
	*aftertype = HSPVAR_FLAG_INT;
}

// Ne
static void HspVarBoost_Longint_NeI(PDAT *pval, const void *val)
{
	*((int *)pval) = (*GetPtr(pval) != *((boost_longint *)(val)));
	*aftertype = HSPVAR_FLAG_INT;
}

// Gt
static void HspVarBoost_Longint_GtI(PDAT *pval, const void *val)
{
	*((int *)pval) = (*GetPtr(pval) > *((boost_longint *)(val)));
	*aftertype = HSPVAR_FLAG_INT;
}

// Lt
static void HspVarBoost_Longint_LtI(PDAT *pval, const void *val)
{
	*((int *)pval) = (*GetPtr(pval) < *((boost_longint *)(val)));
	*aftertype = HSPVAR_FLAG_INT;
}

// GtEq
static void HspVarBoost_Longint_GtEqI(PDAT *pval, const void *val)
{
	*((int *)pval) = (*GetPtr(pval) >= *((boost_longint *)(val)));
	*aftertype = HSPVAR_FLAG_INT;
}

// LtEq
static void HspVarBoost_Longint_LtEqI(PDAT *pval, const void *val)
{
	*((int *)pval) = (*GetPtr(pval) <= *((boost_longint *)(val)));
	*aftertype = HSPVAR_FLAG_INT;
}

/*
// INVALID
static void HspVarBoost_Longint_Invalid( PDAT *pval, const void *val )
{
throw( HSPVAR_ERROR_INVALID );
}
*/

static void *GetBlockSize(PVal *pval, PDAT *pdat, int *size)
{
	*size = pval->size - (((char *)pdat) - pval->pt);
	return (pdat);
}

static void AllocBlock(PVal *pval, PDAT *pdat, int size)
{
}

/*------------------------------------------------------------*/

EXPORT int HspVarBoost_Longint_typeid(void)
{
	return mytype;
}

EXPORT void HspVarBoost_Longint_Init(HspVarProc *p)
{
	aftertype = &p->aftertype;

	p->Set = HspVarBoost_Longint_Set;
	p->Cnv = HspVarBoost_Longint_Cnv;
	p->GetPtr = HspVarBoost_Longint_GetPtr;
	p->CnvCustom = HspVarBoost_Longint_CnvCustom;
	p->GetSize = HspVarBoost_Longint_GetSize;
	p->GetBlockSize = GetBlockSize;
	p->AllocBlock = AllocBlock;

	//	p->ArrayObject = HspVarBoost_Longint_ArrayObject;
	p->Alloc = HspVarBoost_Longint_Alloc;
	p->Free = HspVarBoost_Longint_Free;

	p->AddI = HspVarBoost_Longint_AddI;
	p->SubI = HspVarBoost_Longint_SubI;
	p->MulI = HspVarBoost_Longint_MulI;
	p->DivI = HspVarBoost_Longint_DivI;
	p->ModI = HspVarBoost_Longint_ModI;

	p->AndI = HspVarBoost_Longint_AndI;
	p->OrI  = HspVarBoost_Longint_OrI;
	p->XorI = HspVarBoost_Longint_XorI;

	p->EqI = HspVarBoost_Longint_EqI;
	p->NeI = HspVarBoost_Longint_NeI;
	p->GtI = HspVarBoost_Longint_GtI;
	p->LtI = HspVarBoost_Longint_LtI;
	p->GtEqI = HspVarBoost_Longint_GtEqI;
	p->LtEqI = HspVarBoost_Longint_LtEqI;

	p->RrI = HspVarBoost_Longint_RrI;
	p->LrI = HspVarBoost_Longint_LrI;

	p->vartype_name = "boost_longint";				// タイプ名
	p->version = 0x001;					// 型タイプランタイムバージョン(0x100 = 1.0)
	p->support = HSPVAR_SUPPORT_STORAGE | HSPVAR_SUPPORT_FLEXARRAY;
	// サポート状況フラグ(HSPVAR_SUPPORT_*)
	p->basesize = sizeof(boost_longint);		// １つのデータが使用するサイズ(byte) / 可変長の時は-1
	mytype = p->flag;
}

/*------------------------------------------------------------*/


/*
   Copyright (C) 2013 the QuantumDove authors

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

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

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

#include <qdove/models/poisson.h>

#include <deal.II/dofs/dof_tools.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/fe/fe_values.h>

namespace qdove
{

  namespace Poisson
  {

    template <int dim>
    Problem<dim>::Problem ()
      :
      init (false)
    {}

    template <int dim>
    Problem<dim>::Problem (qdove::TrialSpace<dim> &trial,
			   qdove::TestSpace<dim>  &test)
      :
      trial_space (&trial),
      test_space (&test),
      init (false)
    {}

    template <int dim>
    Problem<dim>::~Problem ()
    {}

    // Setup the matrices and vectors
    template <int dim>
    void
      Problem<dim>::reinit ()
    {
      // distribute degrees of freedom on the finite element space
      test_space->dofs ().distribute_dofs (test_space->fe ());

      // Initialise system matrices and vectors.
      system_matrix.reinit (test_space->n_dofs (),
			    test_space->n_dofs (),
			    test_space->max_couplings_between_dofs ());

      system_vector.reinit (test_space->n_dofs ());

      solution_vector.reinit (test_space->n_dofs ());

      // Initialise boundary constraints
      constraints.clear ();
      dealii::DoFTools::make_zero_boundary_constraints (test_space->dofs (), constraints);
      constraints.close ();

      init = true;
    }

    // Simple CG solver
    template <int dim>
    void
      Problem<dim>::assemble (const dealii::PETScWrappers::Vector &rhs_function)
    {
      // assert (false && "Pure virtual function called...   :-|");
      assert (init==true && "Problem has not been initialised");
      assert ((rhs_function.size ()==test_space->n_dofs ()) && "Incompatible vector sizes.");

      dealii::QGauss<dim> quadrature_formula (2);
      dealii::FEValues<dim> fe_values (test_space->fe (), quadrature_formula,
				       dealii::update_values            |
				       dealii::update_gradients         |
				       dealii::update_quadrature_points |
				       dealii::update_JxW_values);

      const unsigned int dofs_per_cell = test_space->n_dofs_per_cell ();
      const unsigned int n_q_points    = quadrature_formula.size ();

      std::vector<unsigned int> local_dof_indices (dofs_per_cell);

      // cell-wise representation of a system of equations
      dealii::FullMatrix<double> cell_system (dofs_per_cell, dofs_per_cell);
      dealii::Vector<double>     cell_rhs (dofs_per_cell);

      // cell-wise representation of the function
      std::vector<double> cell_rhs_function (n_q_points);

      typename dealii::DoFHandler<dim>::active_cell_iterator
       	cell = test_space->dofs ().begin_active (),
       	endc = test_space->dofs ().end();

      // assemble matrices cell-wise
      for (; cell!=endc; ++cell)
	{
	  cell_system = 0;
	  cell_rhs    = 0;
	  fe_values.reinit (cell);

	  // get the representation of the function on this cell
	  fe_values.get_function_values (rhs_function, cell_rhs_function);

	  for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	    for (unsigned int j=0; j<dofs_per_cell; ++j)
	      {
		for (unsigned int i=0; i<dofs_per_cell; ++i)
		  {

		    cell_system(i,j)
		      +=
		      fe_values.shape_grad (i,q_point) *
		      fe_values.shape_grad (j,q_point) *
		      fe_values.JxW(q_point);
		  } // i

		cell_rhs(j)
		  +=
		  cell_rhs_function[q_point]        *
		  fe_values.shape_value (j,q_point) *
		  fe_values.JxW (q_point);

	      } // j

	  // Apply constraints and distribute local objects to global
	  // objects.
	  cell->get_dof_indices (local_dof_indices);

	  constraints.
	    distribute_local_to_global (cell_system,
					local_dof_indices,
					system_matrix);

	  constraints.
	    distribute_local_to_global (cell_rhs,
					local_dof_indices,
					system_vector);
	} // cell

      system_matrix.compress (dealii::VectorOperation::add);
      system_vector.compress (dealii::VectorOperation::add);
    }

    // Simple CG solver
    template <int dim>
    unsigned int
      Problem<dim>::solve ()
    {
      dealii::SolverControl solver_control (solution_vector.size (),
					    1e-8*system_vector.l2_norm ());

      dealii::PETScWrappers::SolverCG cg (solver_control);
      dealii::PETScWrappers::PreconditionBlockJacobi preconditioner(system_matrix);
      cg.solve (system_matrix, solution_vector, system_vector, preconditioner);

      return solver_control.last_step();
    }

    // Return the eigenpairs
    template <int dim>
    void
    Problem<dim>::get_solution_vector (dealii::PETScWrappers::Vector &vector)
    {
       vector.reinit (test_space->n_dofs ());
       vector = solution_vector;
    }

  } // namespace Poisson

} // namespace qdove

#include "poisson.inst"


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

#include <nt2/reduction/functions/minimum.hpp>
#include <nt2/include/functions/posmin.hpp>
#include <nt2/include/functions/real.hpp>
#include <nt2/include/functions/imag.hpp>
#include <boost/dispatch/meta/scalar_of.hpp>

namespace nt2 { namespace ext
{
  NT2_FUNCTOR_IMPLEMENTATION( nt2::tag::minimum_, tag::cpu_, (A0)
                            , (generic_< complex_< arithmetic_<A0> > >)
                            )
  {
    typedef typename boost::dispatch::meta::scalar_of<A0>::type result_type;

    BOOST_FORCEINLINE result_type operator()(A0 const& a0) const
    {
      return a0[posmin(a0)];
    }
  };

  NT2_FUNCTOR_IMPLEMENTATION( nt2::tag::minimum_, tag::cpu_, (A0)
                            , (generic_< imaginary_< arithmetic_<A0> > >)
                            )
  {
    typedef typename boost::dispatch::meta::scalar_of<A0>::type result_type;

    BOOST_FORCEINLINE result_type operator()(A0 const& a0) const
    {
      return result_type(nt2::minimum(nt2::imag(a0)));
    }
  };

  NT2_FUNCTOR_IMPLEMENTATION( nt2::tag::minimum_, tag::cpu_, (A0)
                            , (generic_< dry_< arithmetic_<A0> > >)
                            )
  {
    typedef typename boost::dispatch::meta::scalar_of<A0>::type result_type;

    BOOST_FORCEINLINE result_type operator()(A0 const& a0) const
    {
      return result_type(nt2::minimum(nt2::real(a0)));
    }
  };
} }

#endif


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

////////////////////////////////////////////////////////////////////////////////
// Meta-function that creates a standard real type from a size in bytes.
// As all make_xxx, also provides an optional lambda to apply to the result.
// See: http://nt2.metascale.org/sdk/meta/traits/make_real.html
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/apply.hpp>
#include <nt2/sdk/meta/na.hpp>

namespace nt2 { namespace meta
{
  template<std::size_t Size, class Transform = na_>
  struct  make_real;

  template<> struct  make_real<sizeof(double) , na_ > { typedef double  type; };
  template<> struct  make_real<sizeof(float)  , na_ > { typedef float   type; };

  template<class Transform>
  struct  make_real<sizeof(double),Transform>
        : boost::mpl::apply<Transform,double> {};

  template<class Transform>
  struct  make_real<sizeof(float),Transform>
        : boost::mpl::apply<Transform,float> {};
} }

#endif


#include "party.hh"

#include <boost/format.hpp>

#include <iostream>

const int PARTY_LENGTH = 20;

Party::Party(std::string party) : _party{std::move(party)} {
	if (_party.length() == PARTY_LENGTH) {
		_three_front = _party[0] == '3';
		_has_gp = _party[1] == 'G';
		_on_world_map = _party[2] == '+';

		_level = std::stoi(_party.substr(18, 2)); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)

		for (std::size_t i = 3; i < 18; i += 3) { // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
			auto character{static_cast<int>(_party[i])};

			if (character == '-') {
				character = 0;
			} else if (character >= 'A' && character <= 'Z') {
				character = character - 'A' + 1;
			} else if (character >= 'a' && character <= 'z') {
				character = character - 'a' + ('Z' - 'A' + 1) + 1;
			} else {
				std::cerr << "WARNING: Invalid character '" << _party[i] << "' in party '" << _party << "'\n";
			}

			int agility{0};

			try {
				agility = std::stoi(_party.substr(i + 1, 2));
			} catch (...) {}

			_characters.emplace_back(character, agility);
		}
	}

	_key1 += _three_front ? 1ULL << 15U : 0; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
	_key1 += _has_gp ? 1ULL << 14U : 0; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
	_key1 += _on_world_map ? 1ULL << 13U : 0; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)

	_key1 += static_cast<uint16_t>(_level);

	uint64_t characters{0};
	uint64_t agilities{0};

	for (const auto & [character, agility] : _characters) {
		characters = (characters << 6U) + static_cast<uint64_t>(character); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
		agilities = agilities * 100 + static_cast<uint64_t>(agility); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
	}

	_key2 = (characters << 34U) + agilities;// NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
}

auto Party::get_keys() const -> std::pair<uint16_t, uint64_t> {
	return std::make_pair(_key1, _key2);
}

auto operator<<(std::ostream & os, const Party & party) -> std::ostream & {
	os << party._party;
	return os;
}


/*=============================================================================
    Copyright (c) 2001-2011 Joel de Guzman

    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)
=============================================================================*/
#if !defined(PAWN_AST_HPP)
#define PAWN_AST_HPP

#include <boost/config/warning_disable.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/optional.hpp>
#include <boost/variant/recursive_variant.hpp>

#include <list>
#include <map>

#include <aast.hpp>
#include <helper.hpp>
#include <last.hpp>
#include <lcast.hpp>
#include <mast.hpp>

namespace client {
namespace pawn {
namespace ast {
using ColIndices = client::helper::ColIndices;
using uint_ = unsigned int;
using mathExpr = client::math::ast::expr;
using logicalExpr = client::logical::ast::expr;
using logicalCmd = client::logicalc::ast::expr;
using reduceExpr = client::reduce::ast::expr;

struct src {
  std::string fname;
  ColIndices colIndices;
  int index;
};

using quoted_stringT = std::string;

using identifierT = std::string;
using strOperand = boost::variant<identifierT, unsigned int>;

struct map {
  identifierT identifier;
  mathExpr operation;
};

using filter = boost::variant<logicalExpr, logicalCmd>;

struct reduce {
  std::vector<strOperand> cols;
  reduceExpr operation;
  ColIndices colIndices;
};

struct zipExpr;

using unit =
    boost::variant<map, filter, reduce, boost::recursive_wrapper<zipExpr>>;

struct zipExpr {
  std::vector<strOperand> cols;
  src first;
  std::list<unit> units;
  ColIndices colIndices;
  int zipCount;
};

using numSrc = boost::variant<identifierT, uint_>;

struct saveNum {
  numSrc src;
  identifierT dest;
};

struct saveStr {
  strOperand src;
  identifierT dest;
};

struct fileName {
  std::string name;
};

struct queryName {
  std::string name;
};

using saveVal = std::vector<boost::variant<saveNum, saveStr>>;

using terminal = boost::variant<queryName, saveVal, fileName>;

struct expr {
  src first;
  std::list<unit> units;
  terminal last;
  ColIndices colIndices;
  int zipCount{0};
};

struct printer {
  typedef void result_type;

  void operator()(map const &m) const {
    client::math::ast::printer mathPrint;
    std::cout << "map " << m.identifier << " to ";
    mathPrint(m.operation);
    std::cout << " | ";
  }

  void operator()(logicalExpr const &f) const {
    client::logical::ast::printer logicalPrint;
    std::cout << "filter with expr ";
    logicalPrint(f);
    std::cout << " | ";
  }

  void operator()(logicalCmd const &f) const {
    client::logicalc::ast::printer logicalPrint;
    std::cout << "filter with cmd ";
    logicalPrint(f);
    std::cout << " | ";
  }

  void operator()(filter const &f) const {
    boost::apply_visitor(*this, f);
  }

  struct printStrOperand {
    using result_type = void;
    result_type operator()(const std::string &x) const {
      std::cout << x;
    }
    result_type operator()(const unsigned int &x) const {
      std::cout << x;
    }
  };

  void operator()(zipExpr const &z) const {
    std::cout << "zip ";
    if (!z.cols.empty()) {
      std::cout << "group by ";
      for (auto& it : z.cols) {
        boost::apply_visitor(printStrOperand{}, it);
      }
    }
    std::cout << "(";
    std::cout << z.first.index << ": file " << z.first.fname << " | ";
    client::helper::print(z.first.colIndices);
    for (const auto &it : z.units) {
      boost::apply_visitor(*this, it);
    }
    std::cout << ")";
    client::helper::print(z.colIndices);
    std::cout << " | ";
  }

  void operator()(reduce const &r) const {
    client::reduce::ast::printer reducePrint;
    std::cout << "reduce to ";
    reducePrint(r.operation);
    if (!r.cols.empty()) {
      std::cout << " group by ";
      for (auto& it : r.cols) {
        boost::apply_visitor(printStrOperand{}, it);
        std::cout << ", ";
      }
    }
    client::helper::print(r.colIndices);
    std::cout << " | ";
  }

  void operator()(const saveNum &s) const {
    std::cout << " saveNum from ";
    boost::apply_visitor(printStrOperand{}, s.src);
    std::cout << " to " << s.dest;
  }

  void operator()(const saveStr &s) const {
    std::cout << " saveStr from ";
    boost::apply_visitor(printStrOperand{}, s.src);
    std::cout << " to " << s.dest;
  }

  void operator()(saveVal const &s) const {
    std::cout << "saveVal ";
    for (const auto &it : s) {
      boost::apply_visitor(*this, it);
    }
  }

  void operator()(queryName const &q) const {
    std::cout << " saveQuery as " << q.name;
  }

  void operator()(fileName const &f) const {
    std::cout << " saveFile as " << f.name;

  }

  void operator()(expr const &x) const {
    std::cout << x.first.index << ": file " << x.first.fname << " | ";
    client::helper::print(x.first.colIndices);
    for (const auto &it : x.units) {
      boost::apply_visitor(*this, it);
    }
    boost::apply_visitor(*this, x.last);
    std::cout << "zipC: " << x.zipCount;
  }
};

///////////////////////////////////////////////////////////////////////////
//  The cols evaluator
///////////////////////////////////////////////////////////////////////////
struct colsEval {
private:
  using ColIndices = client::helper::ColIndices;
  using Global = client::helper::Global;

  const Global &_global;
  ColIndices _cur;
  ColIndices *_pre {nullptr};
  client::math::ast::colsEval _meval;
  client::logical::ast::colsEval _leval;
  client::reduce::ast::colsEval _aeval;
  client::logicalc::ast::colsEval _lcmd;
  enum class state : int { none, first, many };
  state _st{state::none};
  int _zipCount = 0;
  std::vector<std::string> _headers;

  struct colsOperand {
    using result_type = std::pair<unsigned int, std::string>;
    const std::vector<std::string>& _headers;
    const std::vector<std::string>& _vars;
    colsOperand(const std::vector<std::string>& headers, const std::vector<std::string>& vars) : _headers{headers}, _vars{vars} {}
    result_type operator()(const std::string &var) const {
      auto jt = std::find(begin(_headers), end(_headers), var);
      if (jt != std::end(_headers)) return (*this)((unsigned int)(jt - std::begin(_headers)) + 1);
      auto it = std::find(begin(_vars), end(_vars), var);
      if (it == std::end(_vars)) return std::make_pair(0, "Error: " + var + " used before declaration.");
      return std::make_pair(0, "");
    }
    result_type operator()(unsigned int col) const { return std::make_pair(col, ""); }
  };

  struct chekStrOperand {
    using result_type = std::pair<unsigned int, std::string>;
    const ColIndices& _pre;
    const std::vector<std::string>& _headers;
    chekStrOperand(const ColIndices& pre, const std::vector<std::string>& headers) : _pre{pre}, _headers{headers} {}
    result_type operator()(const std::string &var) const {
      auto jt = std::find(begin(_headers), end(_headers), var);
      if (jt != std::end(_headers)) return (*this)((unsigned int)(jt - std::begin(_headers)) + 1);
      auto it = std::find(begin(_pre.varStr), end(_pre.varStr), var);
      if (it == std::end(_pre.varStr)) return std::make_pair(0, "Error: %" + var + " used before declaration.");
      return std::make_pair(0, "");
    }
    result_type operator()(unsigned int col) const {
      auto it = std::find(begin(_pre.str), end(_pre.str), col);
      if (it == std::end(_pre.str)) return std::make_pair(0, "Error: %" + std::to_string(col) + " used before declaration.");
      return std::make_pair(col, "");
    }
  };

  struct chekNumOperand {
    using result_type = std::pair<unsigned int, std::string>;
    const ColIndices& _pre;
    const std::vector<std::string>& _headers;
    chekNumOperand(const ColIndices& pre, const std::vector<std::string>& headers) : _pre{pre}, _headers{headers} {}
    result_type operator()(const std::string &var) const {
      auto jt = std::find(begin(_headers), end(_headers), var);
      if (jt != std::end(_headers)) return (*this)((unsigned int)(jt - std::begin(_headers)) + 1);
      auto it = std::find(begin(_pre.var), end(_pre.var), var);
      if (it == std::end(_pre.var)) return std::make_pair(0, "Error: %" + var + " used before declaration.");
      return std::make_pair(0, "");
    }
    result_type operator()(unsigned int col) const {
      auto it = std::find(begin(_pre.num), end(_pre.num), col);
      if (it == std::end(_pre.num)) return std::make_pair(0, "Error: %" + std::to_string(col) + " used before declaration.");
      return std::make_pair(col, "");
    }
  };

  struct terminalCheck {
  private:
    ColIndices &_pre;
    const std::vector<std::string>& _headers;
    bool _isInitial;
  public:
    using result_type = std::pair<ColIndices, std::string>;
    terminalCheck(ColIndices &cols, const std::vector<std::string>& headers, bool isInitial)
        : _pre{cols}, _headers{headers}, _isInitial{isInitial} {}
    result_type operator()(const queryName &) const { return result_type{}; }
    result_type operator()(const fileName &) const { return result_type{}; }
    result_type operator()(const saveVal &s) const {
      ColIndices res;
      for (auto &it : s) {
        auto x = boost::apply_visitor(*this, it);
        if (x.second.size() > 0) return x;
        res.add(x.first);
      }
      return std::make_pair(res, "");
    }
    result_type operator()(const saveNum &s) const {
      ColIndices res;
      if (_isInitial) {
        auto x = boost::apply_visitor(colsOperand{_headers, _pre.var}, s.src);
        if (x.second.size() > 0) return std::make_pair(res, x.second);
        if (x.first) res.num.push_back(x.first);
        return std::make_pair(res, "");
      }
      auto x = boost::apply_visitor(chekNumOperand{_pre, _headers}, s.src);
      return std::make_pair(res, x.second);
    }
    result_type operator()(const saveStr &s) const {
      ColIndices res;
      if (_isInitial) {
        auto x = boost::apply_visitor(colsOperand{_headers, _pre.varStr}, s.src);
        if (x.second.size() > 0) return std::make_pair(res, x.second);
        if (x.first) res.str.push_back(x.first);
        return std::make_pair(res, "");
      }
      auto x = boost::apply_visitor(chekStrOperand{_pre, _headers}, s.src);
      return std::make_pair(res, x.second);
    }
  };

public:
  typedef std::string result_type;
  colsEval(const Global &global)
      : _global{global}, _cur{}, _meval{_cur, _global},
        _leval{_cur, _global}, _aeval{_cur}, _lcmd{} {}

  result_type operator()(map const &m) {
    auto i = std::find(std::begin(_cur.var), std::end(_cur.var), m.identifier);
    if (i != std::end(_cur.var)) return "Err: " + m.identifier + " redeclared.";
    auto j = _global.gVarsN.find(m.identifier);
    if (j != std::end(_global.gVarsN)) return "Err: " + m.identifier + " is already used in global vars.";
    auto k = std::find(std::begin(_headers), std::end(_headers), m.identifier);
    if (k != std::end(_headers)) return "Err: " + m.identifier + " is also present in input column headers.";
    auto x = _meval(m.operation);
    _cur.add(x.first);
    _cur.var.push_back(m.identifier);
    return x.second;
  }

  result_type operator()(logicalExpr const &f) {
    auto x =  _leval(f);
    _cur.add(x.first);
    return x.second;
  }

  result_type operator()(logicalCmd const &f) {
    auto x =  _lcmd(f);
    return x.second;
  }

  result_type operator()(filter const &f) {
    return boost::apply_visitor(*this, f);
  }

  std::string hitReduce(ColIndices &cl) {
    if (_st == state::none) {
      _st = state::first;
      notInitial();
      return "";
    } else if (_st == state::first) {
      _st = state::many;
    }
    if (!std::includes(begin(_cur.str), end(_cur.str), begin(cl.str),
                       end(cl.str))) {
      return "The later reduce can only have same or more keys.";
    }
    return "";
  }

  bool _isInitial{true};
  void notInitial() {
    _isInitial = false;
    _meval.notInitial();
    _leval.notInitial();
    _aeval.notInitial();
    //_lcmd.notInitial();
  }

  result_type operator()(reduce &r) {
    std::string err;
    *_pre = _cur; // value of what pre was pointing to is changed
    std::tie(_cur, err) = _aeval(r.operation);
    if (err.size() > 0) return err;
    for (auto& it : r.cols) {
      auto colNumErr = boost::apply_visitor(colsOperand{_headers, _pre->varStr}, it);
      if (colNumErr.second.size() > 0) return colNumErr.second;
      _cur.str.push_back(colNumErr.first);
    }
    err = hitReduce(_cur);
    if (err.size() > 0) return err;
    if (_st == state::first) {
      std::copy(begin(_cur.str), end(_cur.str), back_inserter(_pre->str));
      std::copy(begin(_cur.num), end(_cur.num), back_inserter(_pre->num));
    }
    _cur.num.clear();
    _pre->uniq();
    _pre->sort();
    helper::processHeader(*_pre, _headers);
    _pre = &(r.colIndices);
    return err;
  }

  result_type operator()(zipExpr &r) {
    *_pre = _cur;
    _zipCount += 1;
    std::string err = colsEval{_global}.zipInternal(r, _zipCount);
    _zipCount = r.zipCount;
    if (err.size() > 0) return err;
    for (auto& it : r.cols) {
      auto colNumErr = boost::apply_visitor(colsOperand{_headers, _pre->varStr}, it);
      if (colNumErr.second.size() > 0) return colNumErr.second;
      _cur.str.push_back(colNumErr.first);
    }
    // std::copy(begin(r.cols), end(r.cols), std::back_inserter(_cur.str));
    // check if x.cols exist in _pre if _pre is first
    err = hitReduce(_cur);
    if (err.size() > 0) return err;
    if (_st == state::first) {
      std::copy(begin(_cur.str), end(_cur.str), back_inserter(_pre->str));
    }
    _pre->uniq();
    _pre->sort();
    helper::processHeader(*_pre, _headers);
    _pre = &(r.colIndices);
    char ch1 = (int)'a' + 2*(_zipCount - 1);
    char ch2 = ch1 + 1;
    auto nm1 = std::string{ch1};
    auto nm2 = std::string{ch2};
    std::vector<std::string> temp;
    for (auto it : _cur.num) {
      temp.push_back(std::to_string(it) + nm1);
    }
    std::move(begin(_cur.var), end(_cur.var), back_inserter(temp));
    for (auto it : r.colIndices.num) {
      temp.push_back(std::to_string(it) + nm2);
    }
    _cur.num.clear();
    _cur.var = std::move(temp);
    std::copy(begin(r.colIndices.var), end(r.colIndices.var), back_inserter(_cur.var));
    return result_type{};
  }

  result_type zipInternal(zipExpr &x, int zCount) {
    _pre = &x.first.colIndices;
    std::string inFile{x.first.fname.begin() + 1, x.first.fname.end() - 1};
    _headers = helper::headerCols(inFile);
    _meval.setHeaders(_headers);
    _leval.setHeaders(_headers);
    _aeval.setHeaders(_headers);
    _zipCount = zCount;
    x.first.index = zCount;
    for (auto& it : x.cols) {
      auto colNumErr = boost::apply_visitor(colsOperand{_headers, _pre->varStr}, it);
      if (colNumErr.second.size() > 0) return colNumErr.second;
      _cur.str.push_back(colNumErr.first);
    }
    for (auto &it : x.units) {
      auto x = boost::apply_visitor(*this, it);
      if (x.size() > 0) return x;
    }
    _cur.uniq();
    _cur.sort();
    helper::processHeader(_cur, _headers);
    *_pre = _cur;
    x.colIndices = _cur;
    x.zipCount = _zipCount;
    return "";
  }

  auto operator()(expr &x) {
    _pre = &x.first.colIndices;
    std::string inFile{x.first.fname.begin() + 1, x.first.fname.end() - 1};
    _headers = helper::headerCols(inFile);
    _meval.setHeaders(_headers);
    _leval.setHeaders(_headers);
    _aeval.setHeaders(_headers);
    x.first.index = 0;
    for (auto &it : x.units) {
      auto x = boost::apply_visitor(*this, it);
      if (x.size() > 0) return x;
    }
    _cur.uniq();
    _cur.sort();
    helper::processHeader(_cur, _headers);
    *_pre = _cur;
    x.colIndices = _cur;
    x.zipCount = _zipCount;
    auto lastCols = boost::apply_visitor(terminalCheck{_cur, _headers, _isInitial}, x.last);
    if (lastCols.second.size() > 0) return lastCols.second;
    x.colIndices.add(lastCols.first);
    return std::string{};
  }
};
/*
    ///////////////////////////////////////////////////////////////////////////
    //  The keys (string) cols evaluator
    ///////////////////////////////////////////////////////////////////////////
    struct keysEval {
    private:
      enum class state : int {
        none,
        first,
        many
      };
      state _st;
    public:
      using vectorCol = std::vector<size_t>;
      typedef vectorCol result_type;

      result_type operator()(map const &m) {
        return result_type{};
      }

      result_type operator()(filter const &f) {
        return result_type{};
      }

      result_type operator()(reduce const &r) {
        _st = (_st == state::none) ? state::first : state::many;
        return r.cols;
      }

      auto operator()(expr const& x) {
        std::pair<result_type, std::string> res{};
        _st = state::none;
        for (const auto &it : x.units) {
          auto x = boost::apply_visitor(*this, it);
          if (_st == state::first) {
            res.first = x;
          } else if (_st == state::many && !std::includes(
                begin(res.first), end(res.first), begin(x), end(x))) {
            return std::make_pair(result_type{}, std::string{"The later reduce
   can only group by subset of prior ones."});
          }
        }
        return res;
      }
    };
*/
} // namespace ast
} // namespace pawn
} // namespace client

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::fileName, (std::string, name))

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::src,
                          (std::string, fname)
                          /*(client::helper::ColIndices, colIndices)*/)

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::map,
                          (std::string, identifier)
                          (client::math::ast::expr, operation))

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::reduce,
                          (std::vector<client::pawn::ast::strOperand>, cols)
                          (client::reduce::ast::expr, operation)
                          /*(client::helper::ColIndices, colIndices)*/)

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::zipExpr,
                          (std::vector<client::pawn::ast::strOperand>, cols)
                          (client::pawn::ast::src, first)
                          (std::list<client::pawn::ast::unit>, units)
                          /*(client::helper::ColIndices, colIndices)*/)

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::expr,
                          (client::pawn::ast::src, first)
                          (std::list<client::pawn::ast::unit>, units)
                          (client::pawn::ast::terminal, last))

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::saveStr,
                          (client::pawn::ast::strOperand, src)
                          (std::string, dest))

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::saveNum,
                          (client::pawn::ast::numSrc, src)(std::string, dest))

BOOST_FUSION_ADAPT_STRUCT(client::pawn::ast::queryName, (std::string, name))

#endif


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

  @copyright 2016 NumScale SAS
  @copyright 2016 J.T. Lapreste

  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_ORD_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_IS_ORD_HPP_INCLUDED

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

 /*!

    @ingroup group-predicates
    Function object implementing is_ord capabilities

    Returns @ref True if neither x nor y is @ref Nan.

    @par Semantic:

    @code
    as_logical_t<T> r = is_ord(x,y);
    @endcode

    is similar to:

    @code
    as_logical_t<T> r = (x == x) && (y == y);
    @endcode

  **/
  const boost::dispatch::functor<tag::is_ord_> is_ord = {};
} }
#endif

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

#endif


#include "algorithm.hpp"
#include "logger.hpp"
#include <string.h>
#include <boost/thread/mutex.hpp>
#include <limits.h>
#include <boost/random.hpp>
#include <boost/generator_iterator.hpp>
#include "cb_public_functions.hpp"
#include "cb_protocol_public.hpp"

std::string generate_message_id()
{
	unsigned int n = generate_sn();
	char hex[16] = {0};
	sprintf(hex, "%x", n);
	std::string s = hex;
	boost::to_upper(s);
	return s;
}
void generate_message_id_tester()
{
	std::list<std::string> l;
	for(int i = 0; i < 1000000; i++)
	{
		l.push_back(generate_message_id());
	}
	size_t before = l.size(), after;
	l.sort();
	l.unique();
	after = l.size();
	l.clear();
	std::cout<<"befor: "<<before<<", after: "<<after<<std::endl;
}
boost::mutex generate_sn_mutex_;
static unsigned int sn_magic_number = 0;
static unsigned int get_sn_magic_number()
{
	if(sn_magic_number == 0)
	{
		typedef boost::mt19937 RNGType;
		srand((unsigned int)time(NULL));
		RNGType rng(rand() % 777);
		boost::uniform_int<> one_to_max_int( 1, INT_MAX>>3);
		boost::variate_generator< RNGType, boost::uniform_int<> >
		dice(rng, one_to_max_int);
		sn_magic_number = dice();
	}
	return sn_magic_number;
}
unsigned int generate_sn()
{
	boost::mutex::scoped_lock lock(generate_sn_mutex_);
	static int i = 111;
	unsigned int n = get_sn_magic_number() + i++;
	if(i > 999999999)
	{
		i = 111;
	}
	return n;
}


//  Copyright (C) Toon Knapen 2003
//
//  Permission to copy, use, modify, sell and
//  distribute this software is granted provided this copyright notice appears
//  in all copies. This software is provided "as is" without express or implied
//  warranty, and with no claim as to its suitability for any purpose.

#ifndef BOOST_NUMERIC_BINDINGS_BLAS_BLAS2_OVERLOADS_HPP
#define BOOST_NUMERIC_BINDINGS_BLAS_BLAS2_OVERLOADS_HPP

#include <boost/numeric/bindings/blas/blas.h>
#include <boost/numeric/bindings/traits/type_traits.hpp>

namespace boost { namespace numeric { namespace bindings { namespace blas { namespace detail {

  using namespace boost::numeric::bindings::traits ;

  inline
  void gemv( char TRANS, const int& m, const int& n, const float    & alpha, const float    * a_ptr, const int& lda, const float    * x_ptr, const int& incx, const float    & beta, float    * y_ptr, const int& incy ) { BLAS_SGEMV( &TRANS, &m, &n,          ( &alpha ),          ( a_ptr ), &lda,          ( x_ptr ), &incx,          ( &beta ),          ( y_ptr ), &incy ) ; }
  inline
  void gemv( char TRANS, const int& m, const int& n, const double   & alpha, const double   * a_ptr, const int& lda, const double   * x_ptr, const int& incx, const double   & beta, double   * y_ptr, const int& incy ) { BLAS_DGEMV( &TRANS, &m, &n,          ( &alpha ),          ( a_ptr ), &lda,          ( x_ptr ), &incx,          ( &beta ),          ( y_ptr ), &incy ) ; }
  inline
  void gemv( char TRANS, const int& m, const int& n, const complex_f& alpha, const complex_f* a_ptr, const int& lda, const complex_f* x_ptr, const int& incx, const complex_f& beta, complex_f* y_ptr, const int& incy ) { BLAS_CGEMV( &TRANS, &m, &n, complex_ptr( &alpha ), complex_ptr( a_ptr ), &lda, complex_ptr( x_ptr ), &incx, complex_ptr( &beta ), complex_ptr( y_ptr ), &incy ) ; }
  inline
  void gemv( char TRANS, const int& m, const int& n, const complex_d& alpha, const complex_d* a_ptr, const int& lda, const complex_d* x_ptr, const int& incx, const complex_d& beta, complex_d* y_ptr, const int& incy ) { BLAS_ZGEMV( &TRANS, &m, &n, complex_ptr( &alpha ), complex_ptr( a_ptr ), &lda, complex_ptr( x_ptr ), &incx, complex_ptr( &beta ), complex_ptr( y_ptr ), &incy ) ; }

  inline
  void ger( const int& m, const int& n, const float  & alpha, const float  * x_ptr, const int& incx, const float  * y_ptr, const int& incy, float  * a_ptr, const int& lda ) { BLAS_SGER( &m, &n, &alpha, x_ptr, &incx, y_ptr, &incy, a_ptr, &lda ) ; }
  inline
  void ger( const int& m, const int& n, const double & alpha, const double * x_ptr, const int& incx, const double * y_ptr, const int& incy, double * a_ptr, const int& lda ) { BLAS_DGER( &m, &n, &alpha, x_ptr, &incx, y_ptr, &incy, a_ptr, &lda ) ; }
/*
  inline
  void geru( const int& m, const int& n, const complex_f & alpha, const complex_f * x_ptr, const int& incx, complex_f * y_ptr, const int& incy, complex_f * a_ptr, const int& lda ) { BLAS_CGERU( &m, &n, complex_ptr( &alpha ), complex_ptr( x_ptr ), &incx, complex_ptr( y_ptr ), &incy, complex_ptr( a_ptr ), &lda ) ; }
  inline
  void geru( const int& m, const int& n, const complex_d & alpha, const complex_d * x_ptr, const int& incx, complex_d * y_ptr, const int& incy, complex_d * a_ptr, const int& lda ) { BLAS_ZGERU( &m, &n, complex_ptr( &alpha ), complex_ptr( x_ptr ), &incx, complex_ptr( y_ptr ), &incy, complex_ptr( a_ptr ), &lda ) ; }
*/
}}}}}

#endif // BOOST_NUMERIC_BINDINGS_BLAS_BLAS2_OVERLOADS_HPP