#include "SupportsBoundingBox.h"
#include <boost/algorithm/string.hpp>
#include <macgyver/Exception.h>
#include <ogr_geometry.h>

namespace bw = SmartMet::Plugin::WFS;
namespace ba = boost::algorithm;
using SmartMet::Spine::BoundingBox;
using SmartMet::Spine::Value;

const char* bw::SupportsBoundingBox::P_BOUNDING_BOX = "boundingBox";

bw::SupportsBoundingBox::SupportsBoundingBox(StoredQueryConfig::Ptr config,
                                             SmartMet::Spine::CRSRegistry& crs_registry,
                                             bool mandatory)
    : StoredQueryParamRegistry(config),
      SupportsExtraHandlerParams(config, false),
      crs_registry(crs_registry)
{
  try
  {
    register_scalar_param<BoundingBox>(P_BOUNDING_BOX, mandatory);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

bw::SupportsBoundingBox::~SupportsBoundingBox() {}

bool bw::SupportsBoundingBox::get_bounding_box(const RequestParameterMap& param_values,
                                               const std::string& default_crs,
                                               SmartMet::Spine::BoundingBox* bbox) const
{
  try
  {
    assert(bbox != nullptr);

    if (param_values.count(P_BOUNDING_BOX))
    {
      *bbox = param_values.get_single<SmartMet::Spine::BoundingBox>(P_BOUNDING_BOX);

      // Bounding box without crs use always XY notation.
      // Swap the coords to XY order if order is YX.
      if (ba::trim_copy(bbox->crs) == "")
      {
        bbox->crs = default_crs;
      }
// else
//{
//      *bbox = swapXYByBoundingBoxCrs(*bbox);
//}
#if 0
        // CRS with height included are not supported here for bounding box
        // Additionally it is verified that CRS is known
        bool bb_show_height = false;
        crs_registry.get_attribute(bbox->crs, "showHeight", &bb_show_height);
        if (bb_show_height)
          {
            std::ostringstream msg;
            msg << METHOD_NAME << ": CRS " << bbox->crs << " is not supported"
                << " for specifying bounding box";
            Fmi::Exception exception(BCP,msg.str());
            exception.addParameter(WFS_EXCEPTION_CODE,WFS_OPERATION_PROCESSING_FAILED);
            throw exception;
          }
#endif
      return true;
    }
    else
    {
      return false;
    }
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

void bw::SupportsBoundingBox::bbox2polygon(const SmartMet::Spine::BoundingBox& src,
                                           OGRPolygon* polygon,
                                           const int npoints)
{
  try
  {
    assert(polygon != nullptr);

    OGRLinearRing boundary;

    double xStep = (src.xMax - src.xMin) / (npoints - 1);
    double yStep = (src.yMax - src.yMin) / (npoints - 1);

    for (int i = 0; i < npoints; i++)
      boundary.addPoint(src.xMin, src.yMin + i * yStep);
    for (int i = 1; i < npoints; i++)
      boundary.addPoint(src.xMin + i * xStep, src.yMax);
    for (int i = 1; i < npoints; i++)
      boundary.addPoint(src.xMax, src.yMax - i * yStep);
    for (int i = 1; i < npoints; i++)
      boundary.addPoint(src.xMax - i * xStep, src.yMin);

    boundary.closeRings();

    polygon->empty();
    polygon->addRing(&boundary);
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

SmartMet::Spine::BoundingBox bw::SupportsBoundingBox::transform_bounding_box(
    const BoundingBox& src, const std::string& dest_crs, const int npoints) const
{
  try
  {
    auto transformation = crs_registry.create_transformation(src.crs, dest_crs);

    OGRPolygon polygon;
    bbox2polygon(src, &polygon, npoints);

    transformation->transform(polygon);

    OGREnvelope envelope;
    polygon.getEnvelope(&envelope);

    SmartMet::Spine::BoundingBox result;
    result.xMin = envelope.MinX;
    result.yMin = envelope.MinY;
    result.xMax = envelope.MaxX;
    result.yMax = envelope.MaxY;
    result.crs = transformation->get_dest_name();

    return result;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

bool bw::SupportsBoundingBox::isInverseAxisOrderPossible(const std::string& crs) const
{
  try
  {
    int epsg = 0;
    if (crs_registry.get_attribute(crs, "epsg", &epsg))
    {
      OGRSpatialReference sr;
      sr.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      sr.importFromEPSGA(epsg);
      if (sr.EPSGTreatsAsLatLong() or sr.EPSGTreatsAsNorthingEasting())
        return true;
    }
    return false;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

SmartMet::Spine::BoundingBox bw::SupportsBoundingBox::swapXYByBoundingBoxCrs(
    const SmartMet::Spine::BoundingBox& boundingBox) const
{
  try
  {
    SmartMet::Spine::BoundingBox bbox = boundingBox;
    if (isInverseAxisOrderPossible(bbox.crs))
    {
      bbox.xMin = boundingBox.yMin;
      bbox.yMin = boundingBox.xMin;
      bbox.xMax = boundingBox.yMax;
      bbox.yMax = boundingBox.xMax;
    }
    return bbox;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Operation failed!");
  }
}

/**

@page WFS_SQ_PARAM_BBOX Bounding box

@section WFS_SQ_PARAM_BBOX_INTRO Introduction

Deriving stored query handler C++ class from SmartMet::Plugin::WFS::SupportsBoundingBox additionally
to
SmartMet::Plugin::WFS::StoredQueryHandlerBase adds bounding box support to handler. Bounding box
support
is
implemented separately from other @ref WFS_SQ_LOCATION_PARAMS as it may be needed separatelly and
also
@ref WFS_SQ_LOCATION_PARAMS may be needed without bounding box support.

@section WFS_SQ_PARAM_BBOX_PARAM Built-in stored query handler parameters

Adds scalar stored query handler parameter @b boundingBox which has to map to either corresponding
stored query parameter or constant.

Entry name
Type
Data type
Description

  boundingBox
  @ref WFS_CFG_SCALAR_PARAM_TMPL "cfgScalarParameterTemplate"
  BoundingBox
  Specifies bounding box of an area

Bounding box can be specified in one of two possible ways (the second one is for XML requests only):
- string in format MinX,MinY,MaxX,MaxY[,CRS], where
    - MinX and MinY is coordinates of left lower corner of the box
    - MaxX and MaxY is coordiantes of upper right cornet of the box
    - optional value @b CRS specifies the projection name (for example EPSG:3067). The
default
      is empty string. In that case stored query handler is required to interpret it correctly.
- XML type gml:Envelope (when this type provided as xmlType for the actual stored query parameter)

@section WFS_SQ_PARAM_BBOX_EXAMPLES Examples

@verbatim
boundingBox = "19,59,29,72,EPSG::4326";
@endverbatim

Fixed bounding box given in the configuration

@verbatim
boundingBox = "${bbox : 19,59,29,72,EPSG::4326}";
@endverbatim

Maps to stored query parameter @b bbox with the provided default value

@verbatim
boundingBox = ${bbox > defaultBbox}
@endverbatim

Maps to stored query parameter @b bbox. The value of named parameter @b defaultBbox
is used if parameter @b bbox is not provided in the query

*/


#ifndef YASMIC_SIMPLE_ROW_AND_COLUMN_MATRIX_AS_GRAPH_HPP
#define YASMIC_SIMPLE_ROW_AND_COLUMN_MATRIX_AS_GRAPH_HPP

/**
 * @file simple_row_and_column_matrix_as_graph.hpp
 * Implement the types to
 */

/*
 * David Gleich
 * Copyright, Stanford University, 2006-2007
 */

/*
 * 9 July 2007
 * Initial version
 */

#include <yasmic/simple_row_and_column_matrix.hpp>
#include <yasmic/simple_csr_matrix_as_graph.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/integer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/if.hpp>
#include <boost/integer.hpp>
#include <boost/iterator/counting_iterator.hpp>

#define YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS \
    typename Index,typename Value,typename EdgeIndex
#define YASMIC_SIMPLE_RAC_GRAPH_TYPE \
    typename yasmic::simple_row_and_column_matrix<Index,Value,EdgeIndex>

namespace yasmic {
    namespace impl {
        struct simple_rac_graph_traversal :
            public boost::vertex_list_graph_tag,
		    public boost::edge_list_graph_tag,
            public boost::adjacency_graph_tag,
            public boost::bidirectional_graph_tag { };

        template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS>
        class simple_rac_in_edge_iterator;
    } // end namspase yasmic::impl
} // end namespace yasmic

template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS>
class yasmic::impl::simple_rac_in_edge_iterator
    : public boost::iterator_facade<
            typename yasmic::impl::simple_rac_in_edge_iterator<Index,Value,EdgeIndex>,
            yasmic::impl::simple_csr_edge<Index,EdgeIndex>,
            std::random_access_iterator_tag,
            typename yasmic::impl::simple_csr_edge<Index,EdgeIndex>,
            typename boost::int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast>
{
private:
    typedef yasmic::impl::simple_csr_edge<Index,EdgeIndex> edge_descriptor;

public:
    typedef typename boost::int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast
        difference_type;

    // Implicit copy constructor OK
    explicit simple_rac_in_edge_iterator(Index *atj, EdgeIndex *atid)
        : atj(atj), atid(atid)
    {}

    simple_rac_in_edge_iterator() {}

private:
    // iterator_facade requirements
    edge_descriptor dereference() const { return edge_descriptor(*atj,*atid); }

    bool equal(const simple_rac_in_edge_iterator<Index,Value,EdgeIndex>& other) const
    { return atid == other.atid; }

    void increment() { ++atid; ++atj; }
    void decrement() { ++atid; ++atj; }
    void advance(difference_type n) { atid+=n; atj+=n; }

    difference_type distance_to(const simple_rac_in_edge_iterator<Index,Value,EdgeIndex>& other) const
    { return other.atid - atid; }

    Index *atj;
    EdgeIndex *atid;

    friend class boost::iterator_core_access;
};

namespace boost {
    //
    // implement the graph traits
    //
    template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS>
    struct graph_traits<YASMIC_SIMPLE_RAC_GRAPH_TYPE>
        : public graph_traits<yasmic::simple_csr_matrix<Index,Value,EdgeIndex> >
    {
        // modified requirement for Graph
        typedef yasmic::impl::simple_rac_graph_traversal traversal_category;
        // requirements for BidirectionalGraph
        typedef yasmic::impl::simple_rac_in_edge_iterator<Index,Value,EdgeIndex>
            in_edge_iterator;
    };
    //
    // implement the requirements for BidirectionalGraph
    //
    template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS>
    inline typename graph_traits<YASMIC_SIMPLE_RAC_GRAPH_TYPE>::degree_size_type
        in_degree(Index v, const YASMIC_SIMPLE_RAC_GRAPH_TYPE& g) {
            return g.ati[v+1]-g.ati[v];
    }
    template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS>
    inline typename graph_traits<YASMIC_SIMPLE_RAC_GRAPH_TYPE>::degree_size_type
        degree(Index v, const YASMIC_SIMPLE_RAC_GRAPH_TYPE& g) {
            return in_degree(v,g)+out_degree(v,g);
    }
    template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS>
    inline std::pair< typename graph_traits<YASMIC_SIMPLE_RAC_GRAPH_TYPE>::in_edge_iterator,
                      typename graph_traits<YASMIC_SIMPLE_RAC_GRAPH_TYPE>::in_edge_iterator >
        in_edges(Index v, const YASMIC_SIMPLE_RAC_GRAPH_TYPE& g) {
            typedef typename graph_traits<YASMIC_SIMPLE_RAC_GRAPH_TYPE>::in_edge_iterator ei;
            EdgeIndex start = g.ati[v];
            EdgeIndex end = g.ati[v+1];
            return std::make_pair(ei(&g.atj[start],&g.atid[start]),
                                  ei(&g.atj[end],&g.atid[end]));
    }
    //
    // implement the property map, just inherit from csr matrix
    //
    template <YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS, typename Tag>
    struct property_map<YASMIC_SIMPLE_RAC_GRAPH_TYPE, Tag>
        : public property_map< yasmic::simple_csr_matrix<Index,Value,EdgeIndex>, Tag>
    {};

} // end namespace boost

#undef YASMIC_SIMPLE_RAC_GRAPH_TYPE
#undef YASMIC_SIMPLE_RAC_TEMPLATE_PARAMS

#endif // YASMIC_SIMPLE_ROW_AND_COLUMN_MATRIX_AS_GRAPH_HPP


#ifndef CLIPPER_METRICS_HPP
#define CLIPPER_METRICS_HPP

#include <atomic>
#include <vector>
#include <mutex>
#include <shared_mutex>
#include <string>
#include <thread>

#include <boost/property_tree/ptree.hpp>

namespace clipper {

namespace metrics {

using std::vector;

enum class MetricType {
  Counter = 0,
  RatioCounter = 1,
  Meter = 2,
  Histogram = 3
};

class Metric {
 public:
  /**
   * @return The metric's type (Counter, RatioCounter, Meter, etc...)
   */
  virtual MetricType type() const = 0;
  /**
   *
   * @return The name of the metric, generally user-defined
   */
  virtual const std::string name() const = 0;
  /**
   * @return A boost property tree containing relevant metric attributes
   */
  virtual const boost::property_tree::ptree report_tree() = 0;
  /**
   * @return A json-formatted string containing relevant metric attributes
   */
  virtual const std::string report_str() = 0;
  /**
   * Resets all metric attributes to their default values (typically zero)
   */
  virtual void clear() = 0;

};

class Counter : public Metric {
 public:
  /** Creates a Counter with initial count zero */
  explicit Counter(const std::string name);
  explicit Counter(const std::string name, const int initial_count);

  // Disallow copy and move
  Counter(Counter &other) = delete;
  Counter &operator=(Counter &other) = delete;
  Counter(Counter &&other) = delete;
  Counter &operator=(Counter &&other) = delete;

  void increment(const int value);
  void decrement(const int value);
  int value() const;

  // Metric implementation
  MetricType type() const override;
  const std::string name() const override;
  const boost::property_tree::ptree report_tree() override;
  const std::string report_str() override;
  void clear() override;

 private:
  const std::string name_;
  std::atomic_int count_;

};

/**
 * Represents a numerator/denominator ratio, where both
 * numerator and denominator are positive integers.
 */
class RatioCounter : public Metric {
 public:
  /** Creates a RatioCounter with numerator 0 and denominator 0 **/
  explicit RatioCounter(const std::string name);
  explicit RatioCounter(const std::string name, const uint32_t num, const uint32_t denom);

  // Disallow copy and move
  RatioCounter(RatioCounter &other) = delete;
  RatioCounter &operator=(RatioCounter &other) = delete;
  RatioCounter(RatioCounter &&other) = delete;
  RatioCounter &operator=(RatioCounter &&other) = delete;

  void increment(const uint32_t num_incr, const uint32_t denom_incr);
  double get_ratio();

  // Metric implementation
  MetricType type() const override;
  const std::string name() const override;
  const boost::property_tree::ptree report_tree() override;
  const std::string report_str() override;
  void clear() override;

 private:
  const std::string name_;
  std::shared_timed_mutex ratio_lock_;
  std::atomic<uint32_t> numerator_;
  std::atomic<uint32_t> denominator_;

};

class MeterClock {
 public:
  virtual long get_time_micros() const = 0;
};

class RealTimeClock : public MeterClock {
 public:
  long get_time_micros() const override;
};

/**
 * A manually adjustable clock used for testing
 * exponentially weighted moving average (EWMA)
 * functionality
 */
class PresetClock : public MeterClock {
 public:
  long get_time_micros() const override;
  void set_time_micros(const long time_micros);

 private:
  long time_ = 0;
};

/// Represents the different load average options for exponentially
/// weighted moving averages (EWMA) within meters. For a one minute EWMA,
/// we use the OneMinute load average, etc...
enum class LoadAverage {
  OneMinute,
  FiveMinute,
  FifteenMinute
};

/// Represents an exponentially weighted moving average.
/// Multiple EWMAs are included within a single meter
/// corresponding to different load averages.
///
/// The EWMA is updated using "ticks" at a frequency determined
/// by a specified tick interval. For a detailed explanation of the update
/// (tick) procedure and decay mechanisms, see the following:
/// 1. http://www.teamquest.com/pdfs/whitepaper/ldavg1.pdf
/// 2. http://www.teamquest.com/pdfs/whitepaper/ldavg2.pdf
/// 3. http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
class EWMA {
 public:
  EWMA(long tick_interval_seconds, LoadAverage load_average);
  void tick();
  void mark_uncounted(uint32_t num);
  void reset();
  double get_rate_seconds();

 private:
  // The time interval between ticks
  const long tick_interval_seconds_;
  // The exponential decay factor applied to the previous
  // rate at every tick
  double alpha_;
  double rate_ = -1;
  std::shared_timed_mutex rate_lock_;
  // The number of new events to be included
  // in the rate at the next tick
  std::atomic<uint32_t> uncounted_;

};

class Meter : public Metric {
 public:
  explicit Meter(std::string name, std::shared_ptr<MeterClock> clock);

  // Disallow copy and move
  Meter(Meter &other) = delete;
  Meter &operator=(Meter &other) = delete;
  Meter(Meter &&other) = delete;
  Meter &operator=(Meter &&other) = delete;

  void mark(uint32_t num);

  /**
   * @return The rate of this meter, in events-per-microsecond, since
   * the time of initialization
   */
  double get_rate_micros();

  /**
   * @return The rate of this meter, in events-per-second, since the
   * time of initialization
   */
  double get_rate_seconds();

  /**
   * @return The rate of this meter, in events-per-second, for the last minute
   * This rate is calculated using an expontentially weighted moving average
   */
  double get_one_minute_rate_seconds();

  /**
   * @return the rate of this meter, in events-per-second, for the last five minutes
   * This rate is calculated using an expontentially weighted moving average.
   */
  double get_five_minute_rate_seconds();

  /**
   * @return the rate of this meter, in events-per-second, for the last fifteen minutes
   * This rate is calculated using an expontentially weighted moving average.
   */
  double get_fifteen_minute_rate_seconds();

  // Metric implementation
  MetricType type() const override;
  const std::string name() const override;
  const boost::property_tree::ptree report_tree() override;
  const std::string report_str() override;
  void clear() override;

 private:
  const std::string unit_ = "events per second";
  std::string name_;
  std::shared_ptr<MeterClock> clock_;
  std::atomic<uint32_t> count_;
  std::shared_timed_mutex start_time_lock_;
  long start_time_micros_;

  // EWMA
  void tick_if_necessary();
  const long ewma_tick_interval_seconds_ = 5;
  std::atomic_long last_ewma_tick_micros_;
  EWMA m1_rate;
  EWMA m5_rate;
  EWMA m15_rate;

};

class ReservoirSampler {
 public:
  explicit ReservoirSampler(size_t sample_size);

  // Disallow copy and move
  ReservoirSampler(ReservoirSampler &other) = delete;
  ReservoirSampler &operator=(ReservoirSampler &other) = delete;
  ReservoirSampler(ReservoirSampler &&other) = delete;
  ReservoirSampler &operator=(ReservoirSampler &&other) = delete;

  void sample(const int64_t value);
  void clear();
  const std::vector<int64_t> snapshot() const;

 private:
  size_t sample_size_;
  size_t n_ = 0;
  std::vector<int64_t> reservoir_;

};

class HistogramStats {
 public:
  /** Constructs a HistogramStats object with all values zero **/
  explicit HistogramStats() {};
  explicit HistogramStats(size_t data_size,
                          int64_t min,
                          int64_t max,
                          double mean,
                          double std_dev,
                          double p50,
                          double p95,
                          double p99);

  size_t data_size_ = 0;
  int64_t min_ = 0;
  int64_t max_ = 0;
  double mean_ = 0;
  double std_dev_ = 0;
  double p50_ = 0;
  double p95_ = 0;
  double p99_ = 0;
};

class Histogram : public Metric {
 public:
  explicit Histogram(const std::string name, const std::string unit, const size_t sample_size);

  // Disallow copy and move
  Histogram(Histogram &other) = delete;
  Histogram &operator=(Histogram &other) = delete;
  Histogram(Histogram &&other) = delete;
  Histogram &operator=(Histogram &&other) = delete;

  void insert(const int64_t value);
  const HistogramStats compute_stats();
  static double percentile(std::vector<int64_t> snapshot, double rank);

  // Metric implementation
  MetricType type() const override;
  const std::string name() const override;
  const std::string report_str() override;
  const boost::property_tree::ptree report_tree() override;
  void clear() override;

 private:
  std::string name_;
  std::string unit_;
  ReservoirSampler sampler_;
  std::shared_timed_mutex sampler_lock_;

};

/**
 * Obtains a human readable string representation of the provided MetricType
 */
const std::string get_metrics_category_name(MetricType type);

/**
 * Singleton object that manages creation, logging, and persistence
 * of system metrics.
 */
class MetricsRegistry {

 public:
  /**
   * Obtains an instance of the MetricsRegistry singleton
   * that can be used to create new metrics
   */
  static MetricsRegistry &get_metrics();
  /**
   * @return A JSON-formatted string containing structured reports
   * of all metrics in the registry. The schema is as follows:
   * {
   *  "counters" : [{counter_name: counter_report}, {counter_name: counter_report}],
   *  "histograms": [{counter_name: counter_report}, {counter_name: counter_report}],
   *  ...
   * }
   */
  const std::string report_metrics(const bool clear=false);

  /** Creates a Counter with initial value zero */
  std::shared_ptr<Counter> create_counter(const std::string name);
  std::shared_ptr<Counter> create_counter(const std::string name, const int initial_count);
  /** Creates a RatioCounter with initial value zero */
  std::shared_ptr<RatioCounter> create_ratio_counter(const std::string name);
  std::shared_ptr<RatioCounter> create_ratio_counter(const std::string name, const uint32_t num, const uint32_t denom);
  std::shared_ptr<Meter> create_meter(const std::string name);
  std::shared_ptr<Histogram> create_histogram(const std::string name, const std::string unit, const size_t sample_size);

 private:
  MetricsRegistry();
  MetricsRegistry(MetricsRegistry &other) = delete;
  MetricsRegistry &operator=(MetricsRegistry &other) = delete;
  MetricsRegistry(MetricsRegistry &&other) = delete;
  MetricsRegistry &operator=(MetricsRegistry &&other) = delete;

  void manage_metrics();
  std::shared_ptr<vector<std::shared_ptr<Metric>>> metrics_;
  std::shared_ptr<std::mutex> metrics_lock_;

};

} // namespace metrics

} // namespace clipper

#endif //CLIPPER_METRICS_HPP


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

  @copyright 2016 NumScale SAS

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

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

 /*!

    @ingroup group-boolean
    Function object implementing if_allbits_else capabilities

    If @c c is @ref True returns @ref Allbits else returns @c f

    @par Semantic:

    For every parameters @c c of type @c C and @c f of type @c T:

    @code
    T r = if_allbits_else(c, f);
    @endcode

    is similar to:

    @code
    T r = c ? Allbits<T>() : f;
    @endcode

    @par Alias:
    @c if_nan_else,

    @see genmask, Allbits, Nan

  **/
  Value if_allbits_else(Value const& c, Value const& f);

  //@overload
  Value if_allbits_else(LogicalValue const& c, Value const& f);
} }
#endif

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

#endif


#include <boost/test/unit_test.hpp>
#include <shz/math/bbox.hpp>

BOOST_AUTO_TEST_CASE(bboxConstructors)
{
	shz::math::bbox<shz::math::f64> p1;
    shz::math::bbox<shz::math::f32> p2;

    p1[0].data[0] = 0;
    p2[0].x = 0;
    p2[1].x = 0;
}


/*
 * table.cpp
 *
 *  Created on: Jan 12, 2012
 *      Author: eba
 */

#include "mhfpython.h"
#include <boost/python.hpp>
#include <boost/range.hpp>
#include <SplitTable.h>
#include <vector>

using std::vector;
using namespace boost::python;
using namespace boost::python::numeric;

double get_variance(const TableEntry<1>& self) {return self.variance;}
vector<GaussianHypothesis<1> >get_hypotheses(const TableEntry<1>& self) {return self.hypotheses;}

void export_tables()
{
    class_<SplitTable<1> >("SplitTable1",init<const char *>())
    		.def(init<>())
    		.def("getUpperEntry", &SplitTable<1>::getUpperEntry)
    ;
    class_<TableEntry<1> >("TableEntry1",no_init)
    	    .add_property("variance", &get_variance)
    	    .add_property("hypotheses", &get_hypotheses)
    ;
    class_<vector<GaussianHypothesis<1> > >("GHvector")
    		.def("__iter__", iterator<vector<GaussianHypothesis<1> > >())
    		.def("__len__", &vector<GaussianHypothesis<1> >::size)
    ;
    export_hypothesis<1>();
}


// g++ main.cpp -o main -larmadillo -fopenmp -I. -lstdc++fs

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <omp.h>
#include <armadillo>

#include "tools.h"
#include "mesh.h"
#include "direction.h"
#include "euler.h"
#include "gp.h"
#include "reconstruction.h"

#include <thread>

using namespace std;
using namespace arma;

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

    string ec_type = "DECT";
    int n_filtration = 60;
    int n_cone = 4;
    int n_direction_per_cone = 4;
    double cap_radius = 0.80;
    double cutoff = 4.0;
    string y_filename = "label.txt";

    string prot_A = "protA";
    string prot_B = "protB";
    string directory = "output";
    string pdbpath_A = "data/pdb/WT_offset_0/";
    string pdbpath_B = "data/pdb/R164S_offset_0/";
    string pdbfile_recon = pdbpath_A + "WT_frame0.pdb";

    string input;
    cout << "Name for protein A: ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> prot_A;
    }
    cout << "Name for protein B: ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> prot_B;
    }
    cout << "Path to PDB files for protein A: ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> pdbpath_A;
    }
    cout << "Path to PDB files for protein B: ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> pdbpath_B;
    }
    cout << "PDB file for visualization protein A: ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> pdbfile_recon;
    }
    cout << "Directory for output files (default: output): ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> directory;
    }

    string mshpath_A = directory + "msh/" + prot_A + "/";
    string mshpath_B = directory + "msh/" + prot_B + "/";

    string tmp;
    cout << "Type of Euler characteristic measure (DECT/ECT/SECT, default: DECT): ";
    getline(cin,input);
    if ( !input.empty() ) {
        istringstream stream(input);
        stream >> tmp;
    }
    if (tmp.compare("SECT") == 0) { ec_type = "SECT"; }
    else if (tmp.compare("ECT") == 0) { ec_type = "ECT"; }
    else {ec_type = "DECT"; }

    cout << "Radius cutoff for simplicial construction (default: 4.0): ";
    cin >> cutoff;
    cout << "Number of cones: (default: 4)";
    cin >> n_cone;
    cout << "Number of directions per cone (default: 4): ";
    cin >> n_direction_per_cone;
    cout << "Cap radius: ";
    cin >> cap_radius;
    cout << "Number of filtration steps (default: 60): ";
    cin >> n_filtration;

    int number_of_threads = -1;
    cout << "Number of CPU cores used for calculation (default: -1, which automatically detect all cores): ";
    cin >> number_of_threads;
    if (number_of_threads == -1)
        const auto processor_count = thread::hardware_concurrency();    //may return 0 when not able to detect
    omp_set_num_threads(number_of_threads);

    string filesuffix;
    stringstream ss_filesuffix;
    ss_filesuffix << '_' << n_cone << '_' << n_direction_per_cone << '_' << setprecision(4) << cap_radius << '_' << n_filtration;
    ss_filesuffix >> filesuffix;

    pdb_to_mesh(pdbpath_A,pdbpath_B,mshpath_A,mshpath_B,cutoff);
    vector<vector<double> > directions = generate_equidistributed_cones(n_cone,cap_radius,n_direction_per_cone,false);
    cout << directions.size() << " Directions generated\n";

    string ec_filename = directory + "/" + ec_type + filesuffix + ".txt";
    compute_ec_curve_multiple_files(mshpath_A,mshpath_B,directions,n_filtration,ec_type,y_filename,ec_filename);

    dmat X;
    dvec y;

    X.load(directory+"/"+ec_type+filesuffix+".txt",raw_ascii);
    y.load(y_filename,raw_ascii);

    dvec rates;
    rates = find_rate_variables_with_other_sampling_methods(X,y);
    rates.save(directory+"/rates"+filesuffix+".txt",raw_ascii);

    vector<double> vec_rates_vert = reconstruct_multiple_mesh(mshpath_A,rates,directions,n_filtration,n_direction_per_cone);

    dvec rates_vert = conv_to<dvec>::from(vec_rates_vert);
    rates_vert.save(directory+"/rates_vert"+filesuffix+".txt",raw_ascii);
    add_rate_pdb(pdbfile_recon,directory+"/rates_vert"+filesuffix+".pdb",rates_vert);

    return 0;
}


#ifndef MOCHIMOCHI_LOAD_SVMLIGHT_FILE_HPP_
#define MOCHIMOCHI_LOAD_SVMLIGHT_FILE_HPP_

#include <Eigen/Dense>
#include <fstream>
#include <sstream>
#include <map>

namespace utility {
  template<typename T>
  inline std::pair<T, Eigen::VectorXd> read_ones(std::string line, const std::size_t dim) {
    Eigen::VectorXd values = Eigen::VectorXd::Zero(dim);
    std::istringstream parsed_line(line);
    T label;
    parsed_line >> label;

    std::string token;
    while(parsed_line >> token) {
      std::string::size_type pos = token.find(":");
      token.replace(pos, 1, " ");
      std::istringstream iss(token);
      int number;
      double value;
      iss >> number >> value;
      values(number - 1) = value;
    }
    return std::make_pair(label, values);
  }
}

#endif //MOCHIMOCHI_LOAD_SVMLIGHT_FILE_HPP_


#include <boost/geometry/algorithms/perimeter.hpp>


//---------------------------------------------------------------------------//
//!
//! \file   Utility_RotationSphericalCoordinateConversionPolicy.hpp
//! \author Alex Robinson
//! \brief  Rotation spherical coordinate conversion policy declaration
//!
//---------------------------------------------------------------------------//

#ifndef UTILITY_ROTATION_SPHERICAL_COORDINATE_CONVERSION_POLICY_HPP
#define UTILITY_ROTATION_SPHERICAL_COORDINATE_CONVERSION_POLICY_HPP

// Boost Includes
#include <boost/serialization/array_wrapper.hpp>

// FRENSIE Includes
#include "Utility_SphericalSpatialCoordinateConversionPolicy.hpp"
#include "Utility_SphericalDirectionalCoordinateConversionPolicy.hpp"

namespace Utility{

//! The rotation spherical coordinate conversion policy class
class RotationSphericalCoordinateConversionPolicy : public SphericalSpatialCoordinateConversionPolicy,
                                                    public SphericalDirectionalCoordinateConversionPolicy
{

public:

  //! Constructor
  RotationSphericalCoordinateConversionPolicy( const double axis[3] );

  //! Destructor
  ~RotationSphericalCoordinateConversionPolicy()
  { /* ... */ }

  //! Convert the spatial coordinates to cartesian coordinates
  void convertToCartesianSpatialCoordinates(
                                      const double primary_spatial_coord,
                                      const double secondary_spatial_coord,
                                      const double tertiary_spatial_coord,
                                      double& x_spatial_coord,
                                      double& y_spatial_coord,
                                      double& z_spatial_coord ) const override;

  //! Convert the cartesian coordinates to the spatial coordinate system
  void convertFromCartesianSpatialCoordinates(
                               const double x_spatial_coord,
                               const double y_spatial_coord,
                               const double z_spatial_coord,
                               double& primary_spatial_coord,
                               double& secondary_spatial_coord,
                               double& tertiary_spatial_coord ) const override;

  //! Convert the directional coordinates to cartesian coordinates
  void convertToCartesianDirectionalCoordinates(
                                  const double primary_directional_coord,
                                  const double secondary_directional_coord,
                                  const double tertiary_directional_coord,
                                  double& x_directional_coord,
                                  double& y_directional_coord,
                                  double& z_directional_coord ) const override;

  //! Convert the cartesian coordinates to the directional coordinate system
  void convertFromCartesianDirectionalCoordinates(
                           const double x_directional_coord,
                           const double y_directional_coord,
                           const double z_directional_coord,
                           double& primary_directional_coord,
                           double& secondary_directional_coord,
                           double& tertiary_directional_coord ) const override;

  //! Convert the spatial coordinates to cartesian coordinates
  using SphericalSpatialCoordinateConversionPolicy::convertToCartesianSpatialCoordinates;

  //! Convert the cartesian coordinates to the spatial coordinate system
  using SphericalSpatialCoordinateConversionPolicy::convertFromCartesianSpatialCoordinates;

  //! Convert the directional coordinates to cartesian coordinates
  using SphericalDirectionalCoordinateConversionPolicy::convertToCartesianDirectionalCoordinates;

  //! Convert the cartesian coordinates to the directional coordinate system
  using SphericalDirectionalCoordinateConversionPolicy::convertFromCartesianDirectionalCoordinates;

private:

  // The default constructor should not be used - if the z-axis of the local
  // coordinate system w.r.t. the global Cartesian coordinate system aligns
  // with the z-axis of the Cartesian coordinate system use the basic
  // conversion policy
  RotationSphericalCoordinateConversionPolicy()
  { /* ... */ }

  // We have C-arrays as members - hide the copy constructor and assignment
  // operator
  RotationSphericalCoordinateConversionPolicy( const RotationSphericalCoordinateConversionPolicy& that );
  RotationSphericalCoordinateConversionPolicy& operator=( const RotationSphericalCoordinateConversionPolicy& that );

  // Save the policy to an archive
  template<typename Archive>
  void save( Archive& ar, const unsigned version ) const;

  // Load the policy from an archive
  template<typename Archive>
  void load( Archive& ar, const unsigned version );

  BOOST_SERIALIZATION_SPLIT_MEMBER();

  // Declare the boost serialization access object as a friend
  friend class boost::serialization::access;

  // The z-axis (unit vector) of the local Cartesian coordinate system w.r.t.
  // the global Cartesian coordinate system
  double d_axis[3];
};

// Save the policy to an archive
template<typename Archive>
void RotationSphericalCoordinateConversionPolicy::save( Archive& ar, const unsigned version ) const
{
  // Save the base classes
  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( SphericalSpatialCoordinateConversionPolicy );
  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( SphericalDirectionalCoordinateConversionPolicy );

  // Save the local data
  ar & boost::serialization::make_nvp( "d_axis", boost::serialization::make_array( d_axis, 3 ) );
}

// Load the policy from an archive
template<typename Archive>
void RotationSphericalCoordinateConversionPolicy::load( Archive& ar, const unsigned version )
{
  // Load the base classes
  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( SphericalSpatialCoordinateConversionPolicy );
  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( SphericalDirectionalCoordinateConversionPolicy );

  // Load the local data
  ar & boost::serialization::make_nvp( "d_axis", boost::serialization::make_array( d_axis, 3 ) );
}

} // end Utility namespace

BOOST_SERIALIZATION_CLASS_VERSION( RotationSphericalCoordinateConversionPolicy, Utility, 0 );
BOOST_SERIALIZATION_CLASS_EXPORT_STANDARD_KEY( RotationSphericalCoordinateConversionPolicy, Utility );
EXTERN_EXPLICIT_CLASS_SAVE_LOAD_INST( Utility, RotationSphericalCoordinateConversionPolicy );

#endif // end UTILITY_ROTATION_SPHERICAL_COORDINATE_CONVERSION_POLICY_HPP

//---------------------------------------------------------------------------//
// end Utility_RotationSphericalCoordinateConversionPolicy.hpp
//---------------------------------------------------------------------------//


// Copyright (C) 2018 Thejaka Amila Kanewala, Marcin Zalewski, Andrew Lumsdaine.

// Boost Software License - Version 1.0 - August 17th, 2003

// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:

// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.

// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//  Authors: Thejaka Kanewala
//           Andrew Lumsdaine

#ifndef __AGM_PAGE_RANK_HPP__
#define __AGM_PAGE_RANK_HPP__

#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/parallel/thread_support.hpp> // for compare_and_swap
#include <boost/graph/parallel/iteration_macros.hpp>
#include <boost/parallel/append_buffer.hpp>

#include <boost/graph/agm/util/stat.hpp>
#include <boost/graph/agm/model/agm.hpp>
#include <boost/graph/agm/runtime/runtime.hpp>
#include <boost/graph/agm/model/general_orderings.hpp>

namespace boost { namespace graph { namespace agm {

#define DANGLING_VERTEX 0
#define NOT_DANGLING_VERTEX 1

#define ALL_DANGLING_RECV_TRUE 0
#define ALL_DANGLING_RECV_FALSE 1

template<typename Graph,
         typename InDegreeMap>
class pagerank_family {

  typedef typename boost::graph_traits < Graph >::vertex_descriptor Vertex;
  typedef double PageRank;

  // work item set definition
  // Every work item must have the time
  // destination, level
  typedef int DangleVertexType;
  typedef std::tuple<Vertex, PageRank, DangleVertexType> WorkItem;
  typedef typename graph_traits<Graph>::degree_size_type degree_t;

  // the processing function
  template<typename State,
           typename ReceiveEdgeCounterMap,
           typename DanglingRecvIndicatorMap,
           typename agm_instance_params>
  struct pagerank_pf {

  public:
    pagerank_pf(const Graph& _rg,
                InDegreeMap& _indeg,
                State& _st,
                State& _dynamicst,
                State& _staticst,
                ReceiveEdgeCounterMap& _recvecountr,
                DanglingRecvIndicatorMap& _danglind,
                agm_instance_params& _insp,
                agm_work_stats& _sr) : g(_rg),
                                       indegrees(_indeg),
                                       pr_state(_st),
                                       pr_dynamic_state(_dynamicst),
                                       pr_static_state(_staticst),
                                       recv_edge_counter(_recvecountr),
                                       dangling_recv_indicator(_danglind),
                                       params(_insp),
                                       stats(_sr){}

  private:
    const Graph& g;
    InDegreeMap& indegrees;
    State& pr_state;
    State& pr_dynamic_state;
    State& pr_static_state;
    ReceiveEdgeCounterMap& recv_edge_counter;
    DanglingRecvIndicatorMap& dangling_recv_indicator;
    agm_instance_params& params;
    agm_work_stats& stats;

  public:
    template<typename buckets>
    void operator()(const WorkItem& wi,
                    int tid,
		    buckets& outset) {
      Vertex v = std::get<0>(wi);
      double inportion = std::get<1>(wi);
      DangleVertexType isdanglingrecv = std::get<2>(wi);

      // first atomically set the dangling indicator
      // this must be first action since if another thread
      // complete the receive count it may try to send the state as dangling
      if (isdanglingrecv == NOT_DANGLING_VERTEX) {
        // update dangling indicator to say that we have an incoming
        // message from a normal in vertex
        int expected = dangling_recv_indicator[v];
        int oldexpected = ALL_DANGLING_RECV_TRUE;
        int newstate = ALL_DANGLING_RECV_FALSE;

        while(oldexpected == expected) {
          if (__atomic_compare_exchange_n(&dangling_recv_indicator[v],
                                          &expected,
                                          newstate,
                                          true,
                                          __ATOMIC_RELAXED,
                                          __ATOMIC_RELAXED)) {
            assert(newstate == dangling_recv_indicator[v]);
          }
        }

        // increase dynamic (accumulating) page rank value
        // for dynamic portion, we will do the multiplication at the end
        // why this is not compiling in OSX ?
        auto newval = pr_dynamic_state[v]+inportion;
        auto expectedval = pr_dynamic_state[v];

        while(true) {
          expectedval = pr_dynamic_state[v];
          if (__atomic_compare_exchange(&pr_dynamic_state[v],
                                          &expectedval,
                                          &newval,
                                          true,
                                          __ATOMIC_RELAXED,
                                          __ATOMIC_RELAXED)) {
            break;
          }
        }

      } else {
        // rank update is from a dangling vertex,
        // update the static page rank value
        // this may lead to a race condition -- need to think!
        auto newval = pr_static_state[v]+inportion;
        auto expectedval = pr_static_state[v];

        while(true) {
          expectedval = pr_static_state[v];
          if (__atomic_compare_exchange(&pr_static_state[v],
                                        &expectedval,
                                        &newval,
                                        true,
                                        __ATOMIC_RELAXED,
                                        __ATOMIC_RELAXED)) {
            break;
          }
        }

      }

      // atomically increase the number of receives
      uint32_t receives_so_far = recv_edge_counter[v];

      while(true) {
        uint32_t newrecvs = receives_so_far+1;
        if (__atomic_compare_exchange_n(&recv_edge_counter[v],
                                        &receives_so_far,
                                        newrecvs,
                                        true,
                                        __ATOMIC_RELAXED,
                                        __ATOMIC_RELAXED)) {
          assert(newrecvs <= indegrees[v]);

          if (newrecvs == indegrees[v]) {

            // only one thread (the last thread) should enter this region
            // we have completed receives for the current iteration
            auto newrank = params.damping_factor * (pr_static_state[v] + pr_dynamic_state[v]);
            auto oldrank = pr_state[v];
            pr_state[v] = newrank;

            if ((newrank - oldrank) > params.epsillon) {
              // we are not done, we need to update out-edges
              // all the pageranks we receive are from danlging vertices ?
              // If yes, this vertex also, become a dangling vertex, then send
              // update neighbors saying current vertex is in dangling state
              auto portion = newrank / boost::out_degree(v, g);
              BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
                Vertex u = target(e, g);
                if (dangling_recv_indicator[v] == ALL_DANGLING_RECV_TRUE) {
                  // once the vertex goes to the dangling state, it will not receive
                  // any updates, therefore, the page rank value is final
                  WorkItem w(u, portion, DANGLING_VERTEX);
                  outset.push(w, tid);
                } else {
                  // if the vertex is not dangling, keep the static part
                  // reset the dynamic part
                  pr_dynamic_state[v] = 0;
                  // reset for next iteration
                  dangling_recv_indicator[v] = ALL_DANGLING_RECV_TRUE;
                  recv_edge_counter[v] = 0;

                  WorkItem w(u, portion, NOT_DANGLING_VERTEX);
                  outset.push(w, tid);
                }
              }
            }
          }

          break;
        }
      }
    }
  };

  template<typename append_buffer_t>
  struct threaded_initializer {
  private:
    int nthreads;
    Graph& graph;
    InDegreeMap& indegrees;
    double initial_pr;
    append_buffer_t* buffer;

  public:
    threaded_initializer(int _nthreads,
                         Graph& _g,
                         InDegreeMap& _indeg,
                         double _init,
                         append_buffer_t* _buf) : nthreads(_nthreads),
                                                  graph(_g),
                                                  indegrees(_indeg),
                                                  initial_pr(_init),
                                                  buffer(_buf) {}

    void operator()(int tid) {
      BGL_PARFORALL_VERTICES_T(u, graph, Graph, tid, nthreads) {
        double portion = initial_pr / boost::out_degree(u, graph);
        BGL_FORALL_OUTEDGES_T(u, e, graph, Graph) {
          Vertex v = target(e, graph);
          if (indegrees[u] == 0)
            buffer->push_back(WorkItem(v, portion, DANGLING_VERTEX));
          else
            buffer->push_back(WorkItem(v, portion, NOT_DANGLING_VERTEX));
        }
      }
    }
  };

public:
  template<typename PageRankState>
  bool verify(Graph& g, InDegreeMap& indegree, PageRankState& ranks) {
    // TODO
  }

  template<typename RuntimeModelGen,
           typename EAGMConfig,
           typename agm_instance_params>
  time_type execute_eagm(Graph& g,
                         InDegreeMap& indegrees,
                         RuntimeModelGen rtmodelgen,
                         EAGMConfig& config,
                         instance_params& runtime_params,
                         agm_instance_params& agm_params,
                         agm_work_stats& sr,
                         bool _verify=true) {
    info("Creating the state ...");
    // State
    typedef typename boost::property_map<Graph, boost::vertex_index_t>::type VertexIndexMap;
    std::vector<PageRank> pagerankmap(num_vertices(g), 0);
    typedef boost::iterator_property_map<typename std::vector<PageRank>::iterator, VertexIndexMap> PageRankMap;
    PageRankMap pr_state(pagerankmap.begin(), get(boost::vertex_index, g));

    // PR dynamic state
    std::vector<PageRank> pagerankdynamicmap(num_vertices(g), 0);
    PageRankMap pr_dynamic_state(pagerankdynamicmap.begin(), get(boost::vertex_index, g));

    // PR static state
    std::vector<PageRank> pagerankstaticmap(num_vertices(g), 0);
    PageRankMap pr_static_state(pagerankstaticmap.begin(), get(boost::vertex_index, g));

    // To track receive in edges
    std::vector<uint32_t> recvedgecntermap(num_vertices(g), 0);
    typedef boost::iterator_property_map<typename std::vector<uint32_t>::iterator, VertexIndexMap> ReceiveEdgeCounterMap;
    ReceiveEdgeCounterMap recv_edge_counter(recvedgecntermap.begin(), get(boost::vertex_index, g));

    // To check whether all the incoming messages are from a dangling
    // vertices. If so the receiving vertex will go to dangling state from next
    // iteration
    std::vector<int> danglinrecv(num_vertices(g), ALL_DANGLING_RECV_TRUE);
    typedef boost::iterator_property_map<typename std::vector<int>::iterator, VertexIndexMap> DanglingRecvIndicatorMap;
    DanglingRecvIndicatorMap dangling_recv_ind(danglinrecv.begin(), get(boost::vertex_index, g));

    info("Setting the initial work item set ...");
    // Initial work item set
    int nthreads = runtime_params.threads;
    typedef append_buffer<WorkItem, 10u> InitialBuffer;
    InitialBuffer initial;
    threaded_initializer<InitialBuffer> initializer(nthreads,
                                                    g,
                                                    indegrees,
                                                    agm_params.initial_pr,
                                                    &initial);
    boost::scoped_array<boost::thread> threads(new boost::thread[nthreads - 1]);
    for (int i = 0; i < nthreads - 1; ++i) {
      boost::thread thr(boost::ref(initializer), i + 1);
      threads[i].swap(thr);
    }

    initializer(0);

    for (int i = 0; i < (nthreads - 1); ++i)
      threads[i].join();

    info("Setting the processing function ...");
    // Processing funcion
    typedef pagerank_pf<PageRankMap,
                        ReceiveEdgeCounterMap,
                        DanglingRecvIndicatorMap,
                        agm_instance_params> ProcessingFunction;

    ProcessingFunction pf(g,
                          indegrees,
                          pr_state,
                          pr_dynamic_state,
                          pr_static_state,
                          recv_edge_counter,
                          dangling_recv_ind,
                          agm_params,
                          sr);

    // CC algorithm
    typedef eagm<Graph,
                 WorkItem,
                 ProcessingFunction,
                 EAGMConfig,
                 RuntimeModelGen> pr_eagm_t;

    pr_eagm_t pralgo(rtmodelgen,
                     config,
                     pf,
                     initial);

    info("Invoking PageRank algorithm ...");
    time_type elapsed = pralgo(runtime_params);

    if (_verify) {
      verify(g, indegrees, pr_state);
    }

    return elapsed;
  }
};
}}}

#endif


//transforms_ex.cpp
/*
* the transforms from object to shadow and vice versa
* .implementation.
* (C) 2005 olegabr. All rights reserved.
*/
#include "transforms_ex.h"
#include "object3d.h"
#include "shadow2d.h"
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <list>
#include <cmath>

#include <boost/lambda/lambda.hpp>

#include <iostream>
using std::cout; using std::endl;

shadow2d& create_mask(const shadow2d& sh, shadow2d& mask)
{
	shadow2d::const_iterator s = sh.begin(), send = sh.end();
	shadow2d::iterator m = mask.begin();
	for (; s != send; ++s, ++m)
	{
		size2d_t sz = m->get_size();
		projection2d::const_iterator ps = s->begin(), psend = s->end();
		int i1(0), i2(0), j1(0), j2(0);
		{
			projection1d::const_iterator pps = ps->begin(), ppsend = ps->end();
			for (; pps != ppsend; ++pps)
				if (*pps > 0.) break; else ++i1;
		}

		for (; ps != psend; ++ps)
			if (*(ps->end()-1) > 0.) break; else ++i2;

		for (ps = s->begin(); ps != psend; ++ps, ++j1)
			if (*(ps->begin()) > 0.) break;
		for (; ps != psend; ++ps, ++j1)
			if (*(ps->begin()) == 0.) break;

		{
			ps = psend-1;
			projection1d::const_iterator pps = ps->begin(), ppsend = ps->end();
			for (; pps != ppsend; ++pps, ++j2)
				if (*pps > 0.) break;
			for (; pps != ppsend; ++pps, ++j2)
				if (*pps == 0.) break;
		}

		{
			int offset = 2;
			projection2d::iterator pm = m->begin(), pmend = m->end();
			pixel2d px(0,0); //i,j
			for (; pm != pmend; ++pm, ++px.j)
			{
				projection1d::iterator ppm = pm->begin(), ppmend = pm->end();
				for (px.i = 0; ppm != ppmend; ++ppm, ++px.i)
				{
					if
					(
						(px.i == 0)||
						(px.i == (sz.height - 1))||
						((px.i+px.j) <= i1+offset)||
						((int(sz.height)+px.j-px.i-1) <= i2+offset)||
						((sz.width - 1 + px.i-px.j) <= sz.width - 1 - (j1-offset))||
						((sz.width - 1 + sz.height - 1 - px.i-px.j) <= sz.height - 1 - (j2-offset))
					) *ppm = 0.;
					else *ppm = 1.;
				}
			}
		}
	}

	return mask;
}

shadow2d& apply_mask(const shadow2d& mask, shadow2d& sh)
{
	//shadow2d::iterator s = sh.begin(), send = sh.end();
	//shadow2d::const_iterator m = mask.begin();
	//for (; s != send; ++s, ++m)
	//{
	//	projection2d::iterator ps = s->begin(), psend = s->end();
	//	projection2d::const_iterator pm = m->begin();
	//	for (; ps != psend; ++ps, ++pm)
	//	{
	//		projection1d::iterator pps = ps->begin(), ppsend = ps->end();
	//		projection1d::const_iterator ppm = pm->begin();
	//		for (; pps != ppsend; ++pps, ++ppm)
	//			//if (*ppm < 0.5) *pps = 0.;
	//			*pps *= *ppm;
	//	}
	//}
	return sh;
}

namespace {
	object3d::value_type calc_mean(const object3d& o, const pixel3d& px)
	{
		double k(1.1);
		object3d::value_type value(0);
		for (pixel3d d(-1,-1,-1); d.i <= 1; ++d.i)
			for (d.j = -1; d.j <= 1; ++d.j)
				for (d.k = -1; d.k <= 1; ++d.k)
					value += o(px+d);

		return k*( value )/27.;
	}

	bool is_hole(const object3d& o, const pixel3d& px)
	{
		const object3d::value_type z = 0.001;
		int n(0);
		for (pixel3d d(-1,-1,-1); d.i <= 1; ++d.i)
			for (d.j = -1; d.j <= 1; ++d.j)
				for (d.k = -1; d.k <= 1; ++d.k)
					n += ((o(px+d) > z) ? 1 : 0);
		return
		(
			o(px) < z && /* == 0.*/
			n >= (26 - 23)
		);
	}

	struct filled_area
	{
		typedef std::size_t hash_t;
		typedef std::set<hash_t> data_type;

		filled_area(const size3d_t& sz) : size_(sz)
		{
			//use size_.depth to store the multiplication for optimization purpose
			size_.depth = size_.width*size_.height;
		}
		filled_area& add_pixel(const pixel3d& px)
		{
			data_.insert(pixel2hash_(px));
			return *this;
		}
		filled_area& add_area(filled_area& ar)
		{
			assert(ar.size_ == size_);
			data_.insert(ar.data_.begin(), ar.data_.end());
			ar.data_.clear();
			return *this;
		}
		bool is_adjacent(const pixel3d& px)
		{
			for (pixel3d d(-1,-1,-1); d.i <= 1; ++d.i)
				for (d.j = -1; d.j <= 1; ++d.j)
					for (d.k = -1; d.k <= 1; ++d.k)
					{
						if (d == pixel3d()) continue;
						if ( find_pixel_(px+d) ) return true;
					}
			return false;
		}
		std::size_t size() const { return data_.size(); }
		void clear(object3d& o, object3d::value_type replace_val)
		{
			for (data_type::iterator i(data_.begin()); i != data_.end(); ++i)
				o(hash2pixel_(*i)) = replace_val;
			//data_.clear();
		}
	private :
		hash_t pixel2hash_(const pixel3d& px)
		{
			return (px.k*size_.height + px.i)*size_.width + px.j;//ind;
		}
		pixel3d hash2pixel_(hash_t ind)
		{
			pixel3d px;
			px.k = ind/size_.depth;
			px.i = (ind - px.k*size_.depth)/size_.width;
			px.j = ind - px.k*size_.depth - px.i*size_.width;
			return px;
		}
		bool find_pixel_(const pixel3d& px)
		{
			return data_.find(pixel2hash_(px)) != data_.end();
		}
		data_type data_;
		size3d_t size_;
	};

	bool operator < (const filled_area& lh, const filled_area& rh)
	{
		return lh.size() < rh.size();
	}

	void remove_small_areas(object3d& o, object3d::value_type search_val, object3d::value_type replace_val)
	{
		typedef std::list<filled_area> areas_type;
		typedef std::vector<areas_type::iterator> areas_ptrs_type;
		areas_type areas;
		size3d_t sz(o.get_size());
		long count(0), COUNT(norm(sz));
		for (pixel3d p(0, 0, 0); p.i < sz.height; ++p.i)
		{
			for (p.j = 0; p.j < sz.width; ++p.j)
			{
				for (p.k = 0; p.k < sz.depth; ++p.k)
				{ ++count;
					object3d::value_type v(o(p) - search_val);
					object3d::value_type absv(v>0 ? v : -v);
					if (absv < 0.0001)
					{
						areas_ptrs_type arp;
						for (areas_type::iterator a(areas.begin()); a != areas.end(); ++a)
							if ( a->is_adjacent(p) ) arp.push_back(a);

						if (arp.size() > 1)
						{
							//cout << "arp.size = " << arp.size() << "\n";
							//cout << count << '/' << COUNT << "\tareas.size = " << areas.size() << '\n';
							std::sort(arp.begin(), arp.end(), *boost::lambda::_1 < *boost::lambda::_2);
							areas_ptrs_type::iterator a(arp.begin()), big(arp.end()-1), aend(arp.end()-1);
							for (; a != aend; ++a)
							{
								(*big)->add_area(**a);
								areas.erase(*a);
							}

							(*big)->add_pixel(p);
						}
						else if (arp.empty())
						{
							//cout << "arp.empty" << "\n\n";
							filled_area a(sz);
							a.add_pixel(p);
							areas.push_back(a);
							cout << count << '/' << COUNT << "\tareas.size = " << areas.size() << '\n';
						}
						else /*arp.size() == 1*/
						{
							//cout << "add_pixel" << "\n\n";
							arp.front()->add_pixel(p);
						}
					}
				}
			}
		}
		cout << "areas.size() = " << areas.size() << endl;
		areas.sort();
		areas.reverse();
		areas.erase(areas.begin());
		for (areas_type::iterator a(areas.begin()); a != areas.end(); ++a)
			a->clear(o, replace_val);

	}
	void add_mass(object3d& o, object3d::value_type search_val, long V)
	{
		//filled_area area;
		//size3d_t sz(o.get_size());
		//long rV(0);
		//for (pixel3d p(0, 0, 0); p.i < sz.height; ++p.i)
		//	for (p.j = 0; p.j < sz.width; ++p.j)
		//		for (p.k = 0; p.k < sz.depth; ++p.k)
		//		{
		//			++rV;
		//			object3d::value_type v(o(p) - search_val);
		//			object3d::value_type absv(v>0 ? v : -v);
		//			if (absv < 0.0001) area.add_pixel(p);
		//		}
		//for(; rV < V; ++rV)
		//{
		//	area.add_pixel_to_border();
		//}
	}
} //unnamed namespace

/*
 * V = 427437 pixels
 * density = 1.85
 */
object3d& apply_filter(const object3d& obj, const point3d& center, object3d& result)
{
	assert(obj.get_size() == result.get_size());
	const pixel3d pc = obj.point2pixel(center);
	const long V = 216600;
	const double d = 1.85;
	double rd(d); // real density
	long rN(1); // number of pixels in count
	result(pc) = d;
	long rV(1); // number of pixels in new object
	const int rmax(38);
	for (int r(1); r <= rmax; ++r)
	{
		/*
		 * calc main volume
		 */
		{pixel3d dp(-r, -r, -r);
			for (; dp.j <= r; ++dp.j)
			{
				for (dp.k = -r; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					rd += obj(px);
					++rN;
					if (calc_mean(obj, px) >= (rd/rN))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(r, -r, -r);
			for (; dp.j <= r; ++dp.j)
			{
				for (dp.k = -r; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					rd += obj(px);
					++rN;
					if (calc_mean(obj, px) >= (rd/rN))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, -r, -r);
			for (; dp.i < r; ++dp.i)
			{
				for (dp.k = -r; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					rd += obj(px);
					++rN;
					if (calc_mean(obj, px) >= (rd/rN))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, r, -r);
			for (; dp.i < r; ++dp.i)
			{
				for (dp.k = -r; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					rd += obj(px);
					++rN;
					if (calc_mean(obj, px) >= (rd/rN))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, 1-r, -r);
			for (; dp.j < r; ++dp.j)
			{
				for (dp.i = 1-r; dp.i < r; ++dp.i)
				{
					pixel3d px(pc);
					px += dp;
					rd += obj(px);
					++rN;
					if (calc_mean(obj, px) >= (rd/rN))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, 1-r, r);
			for (; dp.j < r; ++dp.j)
			{
				for (dp.i = 1-r; dp.i < r; ++dp.i)
				{
					pixel3d px(pc);
					px += dp;
					rd += obj(px);
					++rN;
					if (calc_mean(obj, px) >= (rd/rN))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}

		/*
		 * fill holes
		 */
		--r;
		{pixel3d dp(-r, -r, -r);
			for (; dp.j <= r; ++dp.j)
			{
				for (dp.k = 0; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					if (is_hole(obj, px))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(r, -r, -r);
			for (; dp.j <= r; ++dp.j)
			{
				for (dp.k = 0; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					if (is_hole(obj, px))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, -r, -r);
			for (; dp.i < r; ++dp.i)
			{
				for (dp.k = 0; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					if (is_hole(obj, px))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, r, -r);
			for (; dp.i < r; ++dp.i)
			{
				for (dp.k = 0; dp.k <= r; ++dp.k)
				{
					pixel3d px(pc);
					px += dp;
					if (is_hole(obj, px))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, 1-r, -r);
			for (; dp.j < r; ++dp.j)
			{
				for (dp.i = 0; dp.i < r; ++dp.i)
				{
					pixel3d px(pc);
					px += dp;
					if (is_hole(obj, px))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		{pixel3d dp(1-r, 1-r, r);
			for (; dp.j < r; ++dp.j)
			{
				for (dp.i = 0; dp.i < r; ++dp.i)
				{
					pixel3d px(pc);
					px += dp;
					if (is_hole(obj, px))
					{
						++rV;
						result(px) = d;
					}
				}
			}
		}
		++r;
		/*
		 * end of fill holes
		 */
		if (rV >= V) break;
	}

	remove_small_areas(result, d, 0.);
	remove_small_areas(result, 0., d);
	//add_mass(result, d, V);
	//cout << "new Volume = " << rV << endl;

	return result;
}

point3d calc_center(const shadow2d& sh)
{
	point3d p;
	shadow2d::const_iterator pr = sh.begin(), epr = sh.end();
	for (; pr != epr; ++pr)
		if (abs(pr->get_angle()) <= angle_t(43)) break;
	point2d p1 = pr->get_mass_center();
	angle_t a1 = pr->get_angle();
	for (; pr != epr; ++pr)
		if (pr->get_angle() == angle_t(0)) break;
	point2d p2 = pr->get_mass_center();
	angle_t a2 = pr->get_angle();

	p.z = .5*(p1.x + p2.x);
	p.y = (p1.y*cos(a2) - p2.y*cos(a1))/(sin(a1)*cos(a2) - sin(a2)*cos(a1));
	p.x = (p1.y - p.y*sin(a1))/cos(a1);

	return p;
}

object3d& filter_object(object3d& object)
{
	const int mean = 167;
	object3d::iterator o2d(object.begin()), end1(object.end());
	for (; o2d != end1; ++o2d)
	{
		object2d::iterator o(o2d->begin()), end2(o2d->end());
		for (; o != end2; ++o)
		{
			double d(*o-mean);
			*o = std::pow((d>0?d:0.), 10.);
		}
	}
	return object;
}

void black_threshold(shadow2d& sh, double threshold)
{
	shadow2d::iterator s = sh.begin(), send = sh.end();
	for (; s != send; ++s)
	{
		projection2d::iterator ps = s->begin(), psend = s->end();
		for (; ps != psend; ++ps)
		{
			projection1d::iterator pps = ps->begin(), ppsend = ps->end();
			for (; pps != ppsend; ++pps)
			{
				projection1d::value_type val = *pps;
				*pps = (val >= threshold) ? val : 0.;
			}
		}
	}
}


// Boost.Function library

// Copyright (C) 2002-2003 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.

// For more information, see http://www.boost.org

#include <iostream>
#include <cstdlib>

#include <boost/test/test_tools.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/function.hpp>

using namespace std;
using namespace boost;
using namespace boost::lambda;

static unsigned
func_impl(int arg1, bool arg2, double arg3)
{
  return abs (static_cast<int>((arg2 ? arg1 : 2 * arg1) * arg3));
}

int test_main(int, char*[])
{
  function <unsigned(bool, double)> f1 = bind(func_impl, 15, _1, _2);
  function <unsigned(double)>       f2 = bind(f1, false, _1);
  function <unsigned()>             f3 = bind(f2, 4.0);

  f3();

  return 0;
}


/*
@copyright Louis Dionne 2014
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#include <boost/hana/functor/adjust_mcd.hpp>
#include <boost/hana/functor/fmap_mcd.hpp>

#include <boost/hana/detail/assert.hpp>
#include <boost/hana/detail/minimal/functor.hpp>
using namespace boost::hana;

template <typename mcd>
void test() {
    constexpr auto functor = detail::minimal::functor<mcd>;
    constexpr auto x = 1;
    constexpr auto y = 2.2;
    BOOST_HANA_CONSTEXPR_ASSERT(fill(y, functor(x)) == functor(y));
}

int main() {
    test<Functor::fmap_mcd>();
    test<Functor::adjust_mcd>();
}