/* adjacency_matrix_test.cpp source file
 *
 * Copyright Cromwell D. Enage 2004
 *
 * 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)
 */

/*
 * Defines the std::ios class and std::cout, its global output instance.
 */
#include <iostream>

/*
 * Defines the boost::property_map class template and the boost::get and
 * boost::put function templates.
 */
#include <boost/property_map/property_map.hpp>

/*
 * Defines the boost::graph_traits class template.
 */
#include <boost/graph/graph_traits.hpp>

/*
 * Defines the vertex and edge property tags.
 */
#include <boost/graph/properties.hpp>

/*
 * Defines the boost::adjacency_list class template and its associated
 * non-member function templates.
 */
#include <boost/graph/adjacency_list.hpp>

/*
 * Defines the boost::adjacency_matrix class template and its associated
 * non-member function templates.
 */
#include <boost/graph/adjacency_matrix.hpp>

#include <boost/core/lightweight_test.hpp>

#include <vector>
#include <algorithm> // For std::sort
#include <boost/type_traits/is_convertible.hpp>

#include <boost/graph/iteration_macros.hpp>

template < typename Graph1, typename Graph2 > void run_test()
{
    typedef typename boost::property_map< Graph1, boost::vertex_index_t >::type
        IndexMap1;
    typedef typename boost::property_map< Graph2, boost::vertex_index_t >::type
        IndexMap2;

    Graph1 g1(24);
    Graph2 g2(24);

    boost::add_edge(boost::vertex(1, g1), boost::vertex(2, g1), g1);
    boost::add_edge(boost::vertex(1, g2), boost::vertex(2, g2), g2);
    boost::add_edge(boost::vertex(2, g1), boost::vertex(10, g1), g1);
    boost::add_edge(boost::vertex(2, g2), boost::vertex(10, g2), g2);
    boost::add_edge(boost::vertex(2, g1), boost::vertex(5, g1), g1);
    boost::add_edge(boost::vertex(2, g2), boost::vertex(5, g2), g2);
    boost::add_edge(boost::vertex(3, g1), boost::vertex(10, g1), g1);
    boost::add_edge(boost::vertex(3, g2), boost::vertex(10, g2), g2);
    boost::add_edge(boost::vertex(3, g1), boost::vertex(0, g1), g1);
    boost::add_edge(boost::vertex(3, g2), boost::vertex(0, g2), g2);
    boost::add_edge(boost::vertex(4, g1), boost::vertex(5, g1), g1);
    boost::add_edge(boost::vertex(4, g2), boost::vertex(5, g2), g2);
    boost::add_edge(boost::vertex(4, g1), boost::vertex(0, g1), g1);
    boost::add_edge(boost::vertex(4, g2), boost::vertex(0, g2), g2);
    boost::add_edge(boost::vertex(5, g1), boost::vertex(14, g1), g1);
    boost::add_edge(boost::vertex(5, g2), boost::vertex(14, g2), g2);
    boost::add_edge(boost::vertex(6, g1), boost::vertex(3, g1), g1);
    boost::add_edge(boost::vertex(6, g2), boost::vertex(3, g2), g2);
    boost::add_edge(boost::vertex(7, g1), boost::vertex(17, g1), g1);
    boost::add_edge(boost::vertex(7, g2), boost::vertex(17, g2), g2);
    boost::add_edge(boost::vertex(7, g1), boost::vertex(11, g1), g1);
    boost::add_edge(boost::vertex(7, g2), boost::vertex(11, g2), g2);
    boost::add_edge(boost::vertex(8, g1), boost::vertex(17, g1), g1);
    boost::add_edge(boost::vertex(8, g2), boost::vertex(17, g2), g2);
    boost::add_edge(boost::vertex(8, g1), boost::vertex(1, g1), g1);
    boost::add_edge(boost::vertex(8, g2), boost::vertex(1, g2), g2);
    boost::add_edge(boost::vertex(9, g1), boost::vertex(11, g1), g1);
    boost::add_edge(boost::vertex(9, g2), boost::vertex(11, g2), g2);
    boost::add_edge(boost::vertex(9, g1), boost::vertex(1, g1), g1);
    boost::add_edge(boost::vertex(9, g2), boost::vertex(1, g2), g2);
    boost::add_edge(boost::vertex(10, g1), boost::vertex(19, g1), g1);
    boost::add_edge(boost::vertex(10, g2), boost::vertex(19, g2), g2);
    boost::add_edge(boost::vertex(10, g1), boost::vertex(15, g1), g1);
    boost::add_edge(boost::vertex(10, g2), boost::vertex(15, g2), g2);
    boost::add_edge(boost::vertex(10, g1), boost::vertex(8, g1), g1);
    boost::add_edge(boost::vertex(10, g2), boost::vertex(8, g2), g2);
    boost::add_edge(boost::vertex(11, g1), boost::vertex(19, g1), g1);
    boost::add_edge(boost::vertex(11, g2), boost::vertex(19, g2), g2);
    boost::add_edge(boost::vertex(11, g1), boost::vertex(15, g1), g1);
    boost::add_edge(boost::vertex(11, g2), boost::vertex(15, g2), g2);
    boost::add_edge(boost::vertex(11, g1), boost::vertex(4, g1), g1);
    boost::add_edge(boost::vertex(11, g2), boost::vertex(4, g2), g2);
    boost::add_edge(boost::vertex(12, g1), boost::vertex(19, g1), g1);
    boost::add_edge(boost::vertex(12, g2), boost::vertex(19, g2), g2);
    boost::add_edge(boost::vertex(12, g1), boost::vertex(8, g1), g1);
    boost::add_edge(boost::vertex(12, g2), boost::vertex(8, g2), g2);
    boost::add_edge(boost::vertex(12, g1), boost::vertex(4, g1), g1);
    boost::add_edge(boost::vertex(12, g2), boost::vertex(4, g2), g2);
    boost::add_edge(boost::vertex(13, g1), boost::vertex(15, g1), g1);
    boost::add_edge(boost::vertex(13, g2), boost::vertex(15, g2), g2);
    boost::add_edge(boost::vertex(13, g1), boost::vertex(8, g1), g1);
    boost::add_edge(boost::vertex(13, g2), boost::vertex(8, g2), g2);
    boost::add_edge(boost::vertex(13, g1), boost::vertex(4, g1), g1);
    boost::add_edge(boost::vertex(13, g2), boost::vertex(4, g2), g2);
    boost::add_edge(boost::vertex(14, g1), boost::vertex(22, g1), g1);
    boost::add_edge(boost::vertex(14, g2), boost::vertex(22, g2), g2);
    boost::add_edge(boost::vertex(14, g1), boost::vertex(12, g1), g1);
    boost::add_edge(boost::vertex(14, g2), boost::vertex(12, g2), g2);
    boost::add_edge(boost::vertex(15, g1), boost::vertex(22, g1), g1);
    boost::add_edge(boost::vertex(15, g2), boost::vertex(22, g2), g2);
    boost::add_edge(boost::vertex(15, g1), boost::vertex(6, g1), g1);
    boost::add_edge(boost::vertex(15, g2), boost::vertex(6, g2), g2);
    boost::add_edge(boost::vertex(16, g1), boost::vertex(12, g1), g1);
    boost::add_edge(boost::vertex(16, g2), boost::vertex(12, g2), g2);
    boost::add_edge(boost::vertex(16, g1), boost::vertex(6, g1), g1);
    boost::add_edge(boost::vertex(16, g2), boost::vertex(6, g2), g2);
    boost::add_edge(boost::vertex(17, g1), boost::vertex(20, g1), g1);
    boost::add_edge(boost::vertex(17, g2), boost::vertex(20, g2), g2);
    boost::add_edge(boost::vertex(18, g1), boost::vertex(9, g1), g1);
    boost::add_edge(boost::vertex(18, g2), boost::vertex(9, g2), g2);
    boost::add_edge(boost::vertex(19, g1), boost::vertex(23, g1), g1);
    boost::add_edge(boost::vertex(19, g2), boost::vertex(23, g2), g2);
    boost::add_edge(boost::vertex(19, g1), boost::vertex(18, g1), g1);
    boost::add_edge(boost::vertex(19, g2), boost::vertex(18, g2), g2);
    boost::add_edge(boost::vertex(20, g1), boost::vertex(23, g1), g1);
    boost::add_edge(boost::vertex(20, g2), boost::vertex(23, g2), g2);
    boost::add_edge(boost::vertex(20, g1), boost::vertex(13, g1), g1);
    boost::add_edge(boost::vertex(20, g2), boost::vertex(13, g2), g2);
    boost::add_edge(boost::vertex(21, g1), boost::vertex(18, g1), g1);
    boost::add_edge(boost::vertex(21, g2), boost::vertex(18, g2), g2);
    boost::add_edge(boost::vertex(21, g1), boost::vertex(13, g1), g1);
    boost::add_edge(boost::vertex(21, g2), boost::vertex(13, g2), g2);
    boost::add_edge(boost::vertex(22, g1), boost::vertex(21, g1), g1);
    boost::add_edge(boost::vertex(22, g2), boost::vertex(21, g2), g2);
    boost::add_edge(boost::vertex(23, g1), boost::vertex(16, g1), g1);
    boost::add_edge(boost::vertex(23, g2), boost::vertex(16, g2), g2);

    IndexMap1 index_map1 = boost::get(boost::vertex_index_t(), g1);
    IndexMap2 index_map2 = boost::get(boost::vertex_index_t(), g2);
    typename boost::graph_traits< Graph1 >::vertex_iterator vi1, vend1;
    typename boost::graph_traits< Graph2 >::vertex_iterator vi2, vend2;

    typename boost::graph_traits< Graph1 >::adjacency_iterator ai1, aend1;
    typename boost::graph_traits< Graph2 >::adjacency_iterator ai2, aend2;

    for (boost::tie(vi1, vend1) = boost::vertices(g1),
                         boost::tie(vi2, vend2) = boost::vertices(g2);
         vi1 != vend1; ++vi1, ++vi2)
    {
        BOOST_TEST(
            boost::get(index_map1, *vi1) == boost::get(index_map2, *vi2));

        for (boost::tie(ai1, aend1) = boost::adjacent_vertices(*vi1, g1),
                             boost::tie(ai2, aend2)
             = boost::adjacent_vertices(*vi2, g2);
             ai1 != aend1; ++ai1, ++ai2)
        {
            BOOST_TEST(
                boost::get(index_map1, *ai1) == boost::get(index_map2, *ai2));
        }
    }

    typename boost::graph_traits< Graph1 >::out_edge_iterator ei1, eend1;
    typename boost::graph_traits< Graph2 >::out_edge_iterator ei2, eend2;

    for (boost::tie(vi1, vend1) = boost::vertices(g1),
                         boost::tie(vi2, vend2) = boost::vertices(g2);
         vi1 != vend1; ++vi1, ++vi2)
    {
        BOOST_TEST(
            boost::get(index_map1, *vi1) == boost::get(index_map2, *vi2));

        for (boost::tie(ei1, eend1) = boost::out_edges(*vi1, g1),
                             boost::tie(ei2, eend2)
             = boost::out_edges(*vi2, g2);
             ei1 != eend1; ++ei1, ++ei2)
        {
            BOOST_TEST(boost::get(index_map1, boost::target(*ei1, g1))
                == boost::get(index_map2, boost::target(*ei2, g2)));
        }
    }

    typename boost::graph_traits< Graph1 >::in_edge_iterator iei1, ieend1;
    typename boost::graph_traits< Graph2 >::in_edge_iterator iei2, ieend2;

    for (boost::tie(vi1, vend1) = boost::vertices(g1),
                         boost::tie(vi2, vend2) = boost::vertices(g2);
         vi1 != vend1; ++vi1, ++vi2)
    {
        BOOST_TEST(
            boost::get(index_map1, *vi1) == boost::get(index_map2, *vi2));

        for (boost::tie(iei1, ieend1) = boost::in_edges(*vi1, g1),
                              boost::tie(iei2, ieend2)
             = boost::in_edges(*vi2, g2);
             iei1 != ieend1; ++iei1, ++iei2)
        {
            BOOST_TEST(boost::get(index_map1, boost::target(*iei1, g1))
                == boost::get(index_map2, boost::target(*iei2, g2)));
        }
    }

    // Test construction from a range of pairs
    std::vector< std::pair< int, int > > edge_pairs_g1;
    BGL_FORALL_EDGES_T(e, g1, Graph1)
    {
        edge_pairs_g1.push_back(std::make_pair(
            get(index_map1, source(e, g1)), get(index_map1, target(e, g1))));
    }
    Graph2 g3(edge_pairs_g1.begin(), edge_pairs_g1.end(), num_vertices(g1));
    BOOST_TEST(num_vertices(g1) == num_vertices(g3));
    std::vector< std::pair< int, int > > edge_pairs_g3;
    IndexMap2 index_map3 = boost::get(boost::vertex_index_t(), g3);
    BGL_FORALL_EDGES_T(e, g3, Graph2)
    {
        edge_pairs_g3.push_back(std::make_pair(
            get(index_map3, source(e, g3)), get(index_map3, target(e, g3))));
    }
    // Normalize the edge pairs for comparison
    if (boost::is_convertible<
            typename boost::graph_traits< Graph1 >::directed_category*,
            boost::undirected_tag* >::value
        || boost::is_convertible<
            typename boost::graph_traits< Graph2 >::directed_category*,
            boost::undirected_tag* >::value)
    {
        for (size_t i = 0; i < edge_pairs_g1.size(); ++i)
        {
            if (edge_pairs_g1[i].first < edge_pairs_g1[i].second)
            {
                std::swap(edge_pairs_g1[i].first, edge_pairs_g1[i].second);
            }
        }
        for (size_t i = 0; i < edge_pairs_g3.size(); ++i)
        {
            if (edge_pairs_g3[i].first < edge_pairs_g3[i].second)
            {
                std::swap(edge_pairs_g3[i].first, edge_pairs_g3[i].second);
            }
        }
    }
    std::sort(edge_pairs_g1.begin(), edge_pairs_g1.end());
    std::sort(edge_pairs_g3.begin(), edge_pairs_g3.end());
    edge_pairs_g1.erase(std::unique(edge_pairs_g1.begin(), edge_pairs_g1.end()),
        edge_pairs_g1.end());
    edge_pairs_g3.erase(std::unique(edge_pairs_g3.begin(), edge_pairs_g3.end()),
        edge_pairs_g3.end());
    BOOST_TEST(edge_pairs_g1 == edge_pairs_g3);
}

template < typename Graph > void test_remove_edges()
{
    using namespace boost;

    // Build a 2-vertex graph
    Graph g(2);
    add_edge(vertex(0, g), vertex(1, g), g);
    BOOST_TEST(num_vertices(g) == 2);
    BOOST_TEST(num_edges(g) == 1);
    remove_edge(vertex(0, g), vertex(1, g), g);
    BOOST_TEST(num_edges(g) == 0);

    // Make sure we don't decrement the edge count if the edge doesn't actually
    // exist.
    remove_edge(vertex(0, g), vertex(1, g), g);
    BOOST_TEST(num_edges(g) == 0);
}

int main(int, char*[])
{
    // Use setS to keep out edges in order, so they match the adjacency_matrix.
    typedef boost::adjacency_list< boost::setS, boost::vecS,
        boost::undirectedS >
        UGraph1;
    typedef boost::adjacency_matrix< boost::undirectedS > UGraph2;
    run_test< UGraph1, UGraph2 >();

    // Use setS to keep out edges in order, so they match the adjacency_matrix.
    typedef boost::adjacency_list< boost::setS, boost::vecS,
        boost::bidirectionalS >
        BGraph1;
    typedef boost::adjacency_matrix< boost::directedS > BGraph2;
    run_test< BGraph1, BGraph2 >();

    test_remove_edges< UGraph2 >();
    test_remove_edges< BGraph2 >();

    return boost::report_errors();
}


//---------------------------------------------------------------------------//
//!
//! \file   Utility_RotationCylindricalSpatialCoordinateConversionPolicy.hpp
//! \author Alex Robinson
//! \brief  Rotation cylindrical spatial coordinate conversion policy decl.
//!
//---------------------------------------------------------------------------//

#ifndef UTILITY_ROTATION_CYLINDRICAL_SPATIAL_COORDINATE_CONVERSION_POLICY_HPP
#define UTILITY_ROTATION_CYLINDRICAL_SPATIAL_COORDINATE_CONVERSION_POLICY_HPP

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

// FRENSIE Includes
#include "Utility_CylindricalSpatialCoordinateConversionPolicy.hpp"

namespace Utility{

//! The rotation cylindrical spatial coordinate conversion policy class
class RotationCylindricalSpatialCoordinateConversionPolicy : public CylindricalSpatialCoordinateConversionPolicy
{

public:

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

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

  //! 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 spatial coordinates to cartesian coordinates
  using CylindricalSpatialCoordinateConversionPolicy::convertToCartesianSpatialCoordinates;

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

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
  RotationCylindricalSpatialCoordinateConversionPolicy()
  { /* ... */ }

  // We have C-arrays as members - hide the copy constructor and assignment
  // operator
  RotationCylindricalSpatialCoordinateConversionPolicy( const RotationCylindricalSpatialCoordinateConversionPolicy& that );
  RotationCylindricalSpatialCoordinateConversionPolicy& operator=( const RotationCylindricalSpatialCoordinateConversionPolicy& 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 cylindrical coordinate system w.r.t.
  // the global Cartesian coordinate system
  double d_axis[3];
};

// Save the policy to an archive
template<typename Archive>
void RotationCylindricalSpatialCoordinateConversionPolicy::save( Archive& ar, const unsigned version ) const
{
  // Save the base class
  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( CylindricalSpatialCoordinateConversionPolicy );

  // 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 RotationCylindricalSpatialCoordinateConversionPolicy::load( Archive& ar, const unsigned version )
{
  // Load the base class
  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( CylindricalSpatialCoordinateConversionPolicy );

  // 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( RotationCylindricalSpatialCoordinateConversionPolicy, Utility, 0 );
BOOST_SERIALIZATION_CLASS_EXPORT_STANDARD_KEY( RotationCylindricalSpatialCoordinateConversionPolicy, Utility );
EXTERN_EXPLICIT_CLASS_SAVE_LOAD_INST( Utility, RotationCylindricalSpatialCoordinateConversionPolicy );

#endif // end UTILITY_ROTATION_CYLINDRICAL_SPATIAL_COORDINATE_CONVERSION_POLICY_HPP

//---------------------------------------------------------------------------//
// end Utility_RotationCylindricalSpatialCoordinateConversionPolicy.hpp
//---------------------------------------------------------------------------//


// For base noise type
#include "Ornstein.h"

// Used to tokenize the parameters
#include <boost/tokenizer.hpp>

using namespace gazebo;

// Configure using the given SDF
Ornstein::Ornstein(double beta, double sigma) : Noise(), _beta(beta), _sigma(sigma)
{
	Reset();
}

// Destructor
Ornstein::~Ornstein()
{
	// Do nothing
}

void Ornstein::Reset()
{
	// Rest time
	tim = 0;

	// Initialise parameters
	for (int i = 0; i < MAX_VARS; i++)
		vars[i] = math::Rand::GetDblNormal(0,_sigma);
}

void Ornstein::Sample(double t)
{
	// Discrete time
	double dt = t - tim;

	// Get parameter k, acknowledging that values outside (0,1] may cause issues
	// with exp(.) precision. So, set to 0 to avoid NaNs and Infs in state.
	double k  = (dt <= 0.0 || dt > 1.0  ? 0 : exp(-_beta*dt));

    // Sample!
    for (int i = 0; i < MAX_VARS; i++)
    	vars[i] = vars[i] * k + math::Rand::GetDblNormal(0,_sigma);

    // Time lag
    tim = t;
}


#include <boost/graph/graph_concepts.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp>
//#include <boost/graph/astar_search.hpp>

#include "boost/tuple/tuple.hpp"
#include <boost/bind.hpp>
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <list>

static const size_t BOARD_SIZE = 8;
static const size_t NUM_KNIGHT_MOVES = 8;

typedef std::pair < int, int > Position;
Position knight_jumps[NUM_KNIGHT_MOVES] = {
  Position(2, -1),
  Position(1, -2),
  Position(-1, -2),
  Position(-2, -1),
  Position(-2, 1),
  Position(-1, 2),
  Position(1, 2),
  Position(2, 1)
};

bool position_valid(Position p) {
  return p.first >= 0 && p.first < BOARD_SIZE && p.second >= 0 && p.second < BOARD_SIZE;
}

Position vertex_to_position(size_t v) {
  return std::make_pair(v / BOARD_SIZE, v % BOARD_SIZE);
}

size_t position_to_vertex(Position p) {
  return BOARD_SIZE * p.first + p.second;
}

std::string chess_notation(Position p) {
  char rank_file[] = {'a' + p.first, '1' + p.second, 0};
  return std::string(rank_file);
}

std::ostream& operator<<(std::ostream& os, Position rhs) {
  //os << rhs.first << " " << rhs.second;
  //  os << 'a' + rhs.first << '1' + rhs.second);
  os << chess_notation(rhs);
  return os;
}

Position operator+(const Position & p1, const Position & p2) {
  return Position(p1.first + p2.first, p1.second + p2.second);
}

typedef std::pair<int, int> Edge;

std::vector<Edge> make_vertex_edges(int n) {
  std::vector<Edge> ret;
  ret.reserve(BOARD_SIZE);
  Position vertex_pos = vertex_to_position(n);

  for (int i = 0; i < BOARD_SIZE; ++i) {
    Position jump_position = vertex_pos + knight_jumps[i];
    if (position_valid(jump_position)) {
      ret.push_back(std::make_pair(n, position_to_vertex(jump_position)));
    }
  }
  return ret;
}

void concat_edges(std::vector<Edge>& result, std::vector<Edge>& src) {
  result.insert(result.end(), src.begin(), src.end());
}

int main(int argc, char **argv)
{
  using namespace boost;
  std::cout << "Running knight-graph" << std::endl;

  typedef adjacency_list < vecS, vecS, directedS,
    no_property, property < edge_weight_t, int > > graph_t;
  typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
  typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;

  const int num_nodes = BOARD_SIZE * BOARD_SIZE;

  std::vector<Position> vertex_positions;
  vertex_positions.reserve(BOARD_SIZE * BOARD_SIZE);
  std::transform(boost::counting_iterator<int>(0),
                  boost::counting_iterator<int>(num_nodes),
                  std::back_inserter(vertex_positions),
                  vertex_to_position);

  std::vector<Edge> edges;
  std::list<std::vector<Edge> > vertex_edges;
  std::transform(boost::counting_iterator<int>(0),
                  boost::counting_iterator<int>(num_nodes),
                  std::back_inserter(vertex_edges),
                  make_vertex_edges);

  std::for_each(vertex_edges.begin(), vertex_edges.end(),
      boost::bind(concat_edges, boost::ref(edges), _1));

  std::vector<int> weights(edges.size(), 1);
  graph_t g(edges.begin(), edges.end(), weights.begin(), num_nodes);

  int v = 50;
  std::cout << "out_degree(v, g) " << out_degree(v, g) << "\n";
  std::cout << vertex_to_position(v) <<  " adjacents\n";
  graph_traits<graph_t>::out_edge_iterator ei, ei_end;
  for (boost::tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
//    std::cout << "e " << vertex_to_position(e->first) << "\n";
    edge_descriptor e = *ei;
    std::cout << "e " << vertex_to_position(source(e, g)) <<
      " -> " << vertex_to_position(target(e, g)) << std::endl;
  }

  for (int x = 0; x < 1; ++x) {
    for (int src_index = 0; src_index < BOARD_SIZE*BOARD_SIZE; ++src_index) {
      std::vector<vertex_descriptor> pred(num_vertices(g));
      std::vector<int> d(num_vertices(g));
      vertex_descriptor src = vertex(src_index, g);
      dijkstra_shortest_paths(g, src, predecessor_map(&pred[0]).distance_map(&d[0]));

         std::cout << "distances and parents:" << std::endl;
         graph_traits < graph_t >::vertex_iterator vi, vend;
         for (boost::tie(vi, vend) = vertices(g); vi != vend; ++vi) {
         std::cout << "distance(" << vertex_positions[*vi] << ") = "
         << d[*vi] << ", ";
         std::cout << "parent(" << vertex_positions[*vi] << ") = "
         << vertex_positions[pred[*vi]] << std:: endl;
         }
    }
  }

  std::cout << std::endl;
  return 0;
}


//==============================================================================
//         Copyright 2003 - 2013   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2013   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
//==============================================================================
#include <boost/simd/ieee/include/functions/ilogb.hpp>
#include <boost/simd/sdk/simd/logical.hpp>

#include <boost/dispatch/functor/meta/call.hpp>
#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/tests/type_expr.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <boost/simd/sdk/config.hpp>

#include <boost/simd/include/constants/mone.hpp>
#include <boost/simd/include/constants/one.hpp>
#include <boost/simd/include/constants/two.hpp>
#include <boost/simd/include/constants/four.hpp>
#include <boost/simd/include/constants/zero.hpp>
#include <boost/simd/include/constants/minf.hpp>
#include <boost/simd/include/constants/nan.hpp>

NT2_TEST_CASE_TPL ( ilogb_real,  BOOST_SIMD_REAL_TYPES)
{
  using boost::simd::ilogb;
  using boost::simd::tag::ilogb_;
  typedef typename boost::dispatch::meta::call<ilogb_(T)>::type r_t;
  typedef typename boost::dispatch::meta::as_integer<T,signed>::type iT;
  typedef iT wished_r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS(r_t, wished_r_t);

  // specific values tests
#ifndef BOOST_SIMD_NO_INVALIDS
  NT2_TEST_EQUAL(ilogb(boost::simd::Minf<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Nan<T>()), boost::simd::Zero<r_t>());
#endif
  NT2_TEST_EQUAL(ilogb(boost::simd::Mone<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::One<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Two<T>()), boost::simd::One<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Four<T>()), boost::simd::Two<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Zero<T>()), boost::simd::Zero<r_t>());
}

NT2_TEST_CASE_TPL ( ilogb_unsigned_int,  BOOST_SIMD_UNSIGNED_TYPES)
{
  using boost::simd::ilogb;
  using boost::simd::tag::ilogb_;
  typedef typename boost::dispatch::meta::call<ilogb_(T)>::type r_t;
  typedef typename boost::dispatch::meta::as_integer<T>::type iT;
  typedef iT wished_r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS(r_t, wished_r_t);

  // specific values tests
  NT2_TEST_EQUAL(ilogb(boost::simd::One<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Two<T>()), boost::simd::One<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Zero<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Four<T>()), boost::simd::Two<r_t>());
}

NT2_TEST_CASE_TPL ( ilogb_signed_int,  BOOST_SIMD_INTEGRAL_SIGNED_TYPES)
{
  using boost::simd::ilogb;
  using boost::simd::tag::ilogb_;
  typedef typename boost::dispatch::meta::call<ilogb_(T)>::type r_t;
  typedef typename boost::dispatch::meta::as_integer<T,signed>::type iT;
  typedef iT wished_r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS(r_t, wished_r_t);

  // specific values tests
  NT2_TEST_EQUAL(ilogb(boost::simd::Mone<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::One<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Two<T>()), boost::simd::One<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Zero<T>()), boost::simd::Zero<r_t>());
  NT2_TEST_EQUAL(ilogb(boost::simd::Four<T>()), boost::simd::Two<r_t>());
}


/* =========================================================================
   Copyright (c) 2010-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.
   Portions of this software are copyright by UChicago Argonne, LLC.

                            -----------------
                  ViennaCL - The Vienna Computing Library
                            -----------------

   Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at

   (A list of authors and contributors can be found in the PDF manual)

   License:         MIT (X11), see file LICENSE in the base directory
============================================================================= */

//#define NDEBUG
//#define VIENNACL_DEBUG_BUILD

//
// *** System
//
#include <iostream>

//
// *** Boost
//
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>

//
// *** ViennaCL
//
//#define VIENNACL_DEBUG_ALL
//#define VIENNACL_DEBUG_BUILD
#define VIENNACL_HAVE_UBLAS 1
#include "viennacl/scalar.hpp"
#include "viennacl/matrix.hpp"
#include "viennacl/matrix_proxy.hpp"
#include "viennacl/vector.hpp"
#include "viennacl/linalg/prod.hpp"
#include "viennacl/linalg/norm_2.hpp"
#include "viennacl/linalg/direct_solve.hpp"
#include "examples/tutorial/Random.hpp"
//
// -------------------------------------------------------------
//
using namespace boost::numeric;
//
// -------------------------------------------------------------
//
template <typename ScalarType>
ScalarType diff(ScalarType & s1, viennacl::scalar<ScalarType> & s2)
{
   viennacl::backend::finish();
   if (s1 != s2)
      return (s1 - s2) / std::max(fabs(s1), fabs(s2));
   return 0;
}

template <typename ScalarType>
ScalarType diff(ublas::vector<ScalarType> & v1, viennacl::vector<ScalarType> & v2)
{
   ublas::vector<ScalarType> v2_cpu(v2.size());
   viennacl::backend::finish();  //workaround for a bug in APP SDK 2.7 on Trinity APUs (with Catalyst 12.8)
   viennacl::copy(v2.begin(), v2.end(), v2_cpu.begin());

   for (std::size_t i=0;i<v1.size(); ++i)
   {
      if ( std::max( fabs(v2_cpu[i]), fabs(v1[i]) ) > 0 )
         v2_cpu[i] = fabs(v2_cpu[i] - v1[i]) / std::max( fabs(v2_cpu[i]), fabs(v1[i]) );
      else
         v2_cpu[i] = 0.0;
   }

   return norm_inf(v2_cpu);
}

template <typename ScalarType, typename VCLMatrixType>
ScalarType diff(ublas::matrix<ScalarType> & mat1, VCLMatrixType & mat2)
{
   ublas::matrix<ScalarType> mat2_cpu(mat2.size1(), mat2.size2());
   viennacl::backend::finish();  //workaround for a bug in APP SDK 2.7 on Trinity APUs (with Catalyst 12.8)
   viennacl::copy(mat2, mat2_cpu);
   double ret = 0;
   double act = 0;

    for (unsigned int i = 0; i < mat2_cpu.size1(); ++i)
    {
      for (unsigned int j = 0; j < mat2_cpu.size2(); ++j)
      {
         act = fabs(mat2_cpu(i,j) - mat1(i,j)) / std::max( fabs(mat2_cpu(i, j)), fabs(mat1(i,j)) );
         if (act > ret)
           ret = act;
      }
    }
   //std::cout << ret << std::endl;
   return ret;
}

//
// Part 1: Matrix-matrix multiplications
//

template< typename NumericT, typename Epsilon,
          typename ReferenceMatrixTypeA, typename ReferenceMatrixTypeB, typename ReferenceMatrixTypeC,
          typename MatrixTypeA, typename MatrixTypeB, typename MatrixTypeC>
int test_prod(Epsilon const& epsilon,

              ReferenceMatrixTypeA const & A, ReferenceMatrixTypeA const & A_trans,
              ReferenceMatrixTypeB const & B, ReferenceMatrixTypeB const & B_trans,
              ReferenceMatrixTypeC & C,

              MatrixTypeA const & vcl_A, MatrixTypeA const & vcl_A_trans,
              MatrixTypeB const & vcl_B, MatrixTypeB const & vcl_B_trans,
              MatrixTypeC & vcl_C
             )
{
   int retval = EXIT_SUCCESS;
   NumericT act_diff = 0;

   // Test: C +-= A * B --------------------------------------------------------------------------
   C     = viennacl::linalg::prod(A, B);
   vcl_C = viennacl::linalg::prod(vcl_A, vcl_B);
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C = A * B passed!" << std::endl;

   C     += viennacl::linalg::prod(A, B);
   vcl_C += viennacl::linalg::prod(vcl_A, vcl_B);
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C += A * B passed!" << std::endl;

   C     -= viennacl::linalg::prod(A, B);
   vcl_C -= viennacl::linalg::prod(vcl_A, vcl_B);
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C -= A * B passed!" << std::endl;

   // Test: C +-= A * trans(B) --------------------------------------------------------------------------
   C     = boost::numeric::ublas::prod(A, trans(B_trans));
   vcl_C = viennacl::linalg::prod(vcl_A, trans(vcl_B_trans));
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C = A * trans(B) passed!" << std::endl;

   C     += boost::numeric::ublas::prod(A, trans(B_trans));
   vcl_C += viennacl::linalg::prod(vcl_A, trans(vcl_B_trans));
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C += A * trans(B) passed!" << std::endl;

   C     -= boost::numeric::ublas::prod(A, trans(B_trans));
   vcl_C -= viennacl::linalg::prod(vcl_A, trans(vcl_B_trans));
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C -= A * trans(B) passed!" << std::endl;

   // Test: C +-= trans(A) * B --------------------------------------------------------------------------
   C     = boost::numeric::ublas::prod(trans(A_trans), B);
   vcl_C = viennacl::linalg::prod(trans(vcl_A_trans), vcl_B);
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C = trans(A) * B passed!" << std::endl;

   C     += boost::numeric::ublas::prod(trans(A_trans), B);
   vcl_C += viennacl::linalg::prod(trans(vcl_A_trans), vcl_B);
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C += trans(A) * B passed!" << std::endl;

   C     -= boost::numeric::ublas::prod(trans(A_trans), B);
   vcl_C -= viennacl::linalg::prod(trans(vcl_A_trans), vcl_B);
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C -= trans(A) * B passed!" << std::endl;

   // Test: C +-= trans(A) * trans(B) --------------------------------------------------------------------------
   C     = boost::numeric::ublas::prod(trans(A_trans), trans(B_trans));
   vcl_C = viennacl::linalg::prod(trans(vcl_A_trans), trans(vcl_B_trans));
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C = trans(A) * trans(B) passed!" << std::endl;

   C     += boost::numeric::ublas::prod(trans(A_trans), trans(B_trans));
   vcl_C += viennacl::linalg::prod(trans(vcl_A_trans), trans(vcl_B_trans));
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C += trans(A) * trans(B) passed!" << std::endl;

   C     -= boost::numeric::ublas::prod(trans(A_trans), trans(B_trans));
   vcl_C -= viennacl::linalg::prod(trans(vcl_A_trans), trans(vcl_B_trans));
   act_diff = fabs(diff(C, vcl_C));

   if( act_diff > epsilon )
   {
     std::cout << "# Error at operation: matrix-matrix product" << std::endl;
     std::cout << "  diff: " << act_diff << std::endl;
     retval = EXIT_FAILURE;
   }
   else
     std::cout << "Test C -= trans(A) * trans(B) passed!" << std::endl;

   return retval;
}

template< typename NumericT, typename F_A, typename F_B, typename F_C, typename Epsilon >
int test_prod(Epsilon const& epsilon)
{
  int ret;

  long matrix_size1 = 131;  //some odd number, not too large
  long matrix_size2 = 67;  //some odd number, not too large
  long matrix_size3 = 73;  //some odd number, not too large
  //long matrix_size1 = 128;  //some odd number, not too large
  //long matrix_size2 = 64;  //some odd number, not too large
  //long matrix_size3 = 128;  //some odd number, not too large

  // --------------------------------------------------------------------------

  // ublas reference:
  ublas::matrix<NumericT> A(matrix_size1, matrix_size2);
  ublas::matrix<NumericT> big_A = ublas::scalar_matrix<NumericT>(4*matrix_size1, 4*matrix_size2, 3.1415);

  ublas::matrix<NumericT> B(matrix_size2, matrix_size3);
  ublas::matrix<NumericT> big_B = ublas::scalar_matrix<NumericT>(4*matrix_size2, 4*matrix_size3, 42.0);

  ublas::matrix<NumericT> C(matrix_size1, matrix_size3);

  //fill A and B:
  for (unsigned int i = 0; i < A.size1(); ++i)
    for (unsigned int j = 0; j < A.size2(); ++j)
        A(i,j) = static_cast<NumericT>(0.1) * random<NumericT>();
  for (unsigned int i = 0; i < B.size1(); ++i)
    for (unsigned int j = 0; j < B.size2(); ++j)
        B(i,j) = static_cast<NumericT>(0.1) * random<NumericT>();

  ublas::matrix<NumericT>     A_trans = trans(A);
  ublas::matrix<NumericT> big_A_trans = trans(big_A);

  ublas::matrix<NumericT>     B_trans = trans(B);
  ublas::matrix<NumericT> big_B_trans = trans(big_B);

  //
  // ViennaCL objects
  //

  // A
  viennacl::range range1_A(matrix_size1, 2*matrix_size1);
  viennacl::range range2_A(matrix_size2, 2*matrix_size2);
  viennacl::slice slice1_A(matrix_size1, 2, matrix_size1);
  viennacl::slice slice2_A(matrix_size2, 3, matrix_size2);

  viennacl::matrix<NumericT, F_A>    vcl_A(matrix_size1, matrix_size2);
  viennacl::copy(A, vcl_A);

  viennacl::matrix<NumericT, F_A>    vcl_big_range_A(4*matrix_size1, 4*matrix_size2);
  viennacl::matrix_range<viennacl::matrix<NumericT, F_A> > vcl_range_A(vcl_big_range_A, range1_A, range2_A);
  viennacl::copy(A, vcl_range_A);

  viennacl::matrix<NumericT, F_A>    vcl_big_slice_A(4*matrix_size1, 4*matrix_size2);
  viennacl::matrix_slice<viennacl::matrix<NumericT, F_A> > vcl_slice_A(vcl_big_slice_A, slice1_A, slice2_A);
  viennacl::copy(A, vcl_slice_A);

  // A^T
  viennacl::matrix<NumericT, F_A>    vcl_A_trans(matrix_size2, matrix_size1);
  viennacl::copy(A_trans, vcl_A_trans);

  viennacl::matrix<NumericT, F_A>    vcl_big_range_A_trans(4*matrix_size2, 4*matrix_size1);
  viennacl::matrix_range<viennacl::matrix<NumericT, F_A> > vcl_range_A_trans(vcl_big_range_A_trans, range2_A, range1_A);
  viennacl::copy(A_trans, vcl_range_A_trans);

  viennacl::matrix<NumericT, F_A>    vcl_big_slice_A_trans(4*matrix_size2, 4*matrix_size1);
  viennacl::matrix_slice<viennacl::matrix<NumericT, F_A> > vcl_slice_A_trans(vcl_big_slice_A_trans, slice2_A, slice1_A);
  viennacl::copy(A_trans, vcl_slice_A_trans);

  // B
  viennacl::range range1_B(2*matrix_size2, 3*matrix_size2);
  viennacl::range range2_B(2*matrix_size3, 3*matrix_size3);
  viennacl::slice slice1_B(matrix_size2, 3, matrix_size2);
  viennacl::slice slice2_B(matrix_size3, 2, matrix_size3);

  viennacl::matrix<NumericT, F_B>    vcl_B(matrix_size2, matrix_size3);
  viennacl::copy(B, vcl_B);

  viennacl::matrix<NumericT, F_B>    vcl_big_range_B(4*matrix_size2, 4*matrix_size3);
  viennacl::matrix_range<viennacl::matrix<NumericT, F_B> > vcl_range_B(vcl_big_range_B, range1_B, range2_B);
  viennacl::copy(B, vcl_range_B);

  viennacl::matrix<NumericT, F_B>    vcl_big_slice_B(4*matrix_size2, 4*matrix_size3);
  viennacl::matrix_slice<viennacl::matrix<NumericT, F_B> > vcl_slice_B(vcl_big_slice_B, slice1_B, slice2_B);
  viennacl::copy(B, vcl_slice_B);

  // B^T

  viennacl::matrix<NumericT, F_B>    vcl_B_trans(matrix_size3, matrix_size2);
  viennacl::copy(B_trans, vcl_B_trans);

  viennacl::matrix<NumericT, F_B>    vcl_big_range_B_trans(4*matrix_size3, 4*matrix_size2);
  viennacl::matrix_range<viennacl::matrix<NumericT, F_B> > vcl_range_B_trans(vcl_big_range_B_trans, range2_B, range1_B);
  viennacl::copy(B_trans, vcl_range_B_trans);

  viennacl::matrix<NumericT, F_B>    vcl_big_slice_B_trans(4*matrix_size3, 4*matrix_size2);
  viennacl::matrix_slice<viennacl::matrix<NumericT, F_B> > vcl_slice_B_trans(vcl_big_slice_B_trans, slice2_B, slice1_B);
  viennacl::copy(B_trans, vcl_slice_B_trans);

  // C

  viennacl::range range1_C(matrix_size1-1, 2*matrix_size1-1);
  viennacl::range range2_C(matrix_size3-1, 2*matrix_size3-1);
  viennacl::slice slice1_C(matrix_size1-1, 3, matrix_size1);
  viennacl::slice slice2_C(matrix_size3-1, 3, matrix_size3);

  viennacl::matrix<NumericT, F_C>    vcl_C(matrix_size1, matrix_size3);

  viennacl::matrix<NumericT, F_C>    vcl_big_range_C(4*matrix_size1, 4*matrix_size3);
  viennacl::matrix_range<viennacl::matrix<NumericT, F_C> > vcl_range_C(vcl_big_range_C, range1_C, range2_C);

  viennacl::matrix<NumericT, F_C>    vcl_big_slice_C(4*matrix_size1, 4*matrix_size3);
  viennacl::matrix_slice<viennacl::matrix<NumericT, F_C> > vcl_slice_C(vcl_big_slice_C, slice1_C, slice2_C);

  std::cout << "--- Part 1: Testing matrix-matrix products ---" << std::endl;

  //////
  //////  A: matrix
  //////

  //
  //
  std::cout << "Now using A=matrix, B=matrix, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=matrix, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=matrix, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=range, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=range, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=range, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=slice, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=slice, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=matrix, B=slice, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_A, vcl_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //////
  //////  A: range
  //////

  //
  //
  std::cout << "Now using A=range, B=matrix, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=matrix, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=matrix, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=range, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=range, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=range, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=slice, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=slice, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=range, B=slice, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_range_A, vcl_range_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //////
  //////  A: slice
  //////

  //
  //
  std::cout << "Now using A=slice, B=matrix, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=matrix, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=matrix, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_B, vcl_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=range, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=range, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=range, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_range_B, vcl_range_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=slice, C=matrix" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=slice, C=range" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_range_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  //
  //
  std::cout << "Now using A=slice, B=slice, C=slice" << std::endl;
  ret = test_prod<NumericT>(epsilon,
                            A, A_trans, B, B_trans, C,
                            vcl_slice_A, vcl_slice_A_trans,
                            vcl_slice_B, vcl_slice_B_trans,
                            vcl_slice_C);
  if (ret != EXIT_SUCCESS)
    return ret;

  return ret;

}

//
// Control functions
//

template< typename NumericT, typename Epsilon >
int test(Epsilon const& epsilon)
{
  int ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=row, B=row, C=row ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::row_major, viennacl::row_major, viennacl::row_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=row, B=row, C=col ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::row_major, viennacl::row_major, viennacl::column_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=row, B=col, C=row ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::row_major, viennacl::column_major, viennacl::row_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=row, B=col, C=col ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::row_major, viennacl::column_major, viennacl::column_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=col, B=row, C=row ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::column_major, viennacl::row_major, viennacl::row_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=col, B=row, C=col ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::column_major, viennacl::row_major, viennacl::column_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=col, B=col, C=row ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::column_major, viennacl::column_major, viennacl::row_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  std::cout << "///////////////////////////////////////" << std::endl;
  std::cout << "/// Now testing A=col, B=col, C=col ///" << std::endl;
  std::cout << "///////////////////////////////////////" << std::endl;
  ret = test_prod<NumericT, viennacl::column_major, viennacl::column_major, viennacl::column_major>(epsilon);
  if (ret != EXIT_SUCCESS)
    return ret;

  return ret;
}

//
// -------------------------------------------------------------
//
int main()
{
   std::cout << std::endl;
   std::cout << "----------------------------------------------" << std::endl;
   std::cout << "----------------------------------------------" << std::endl;
   std::cout << "## Test :: BLAS 3 routines" << std::endl;
   std::cout << "----------------------------------------------" << std::endl;
   std::cout << "----------------------------------------------" << std::endl;
   std::cout << std::endl;

   int retval = EXIT_SUCCESS;

   std::cout << std::endl;
   std::cout << "----------------------------------------------" << std::endl;
   std::cout << std::endl;
   {
      typedef float NumericT;
      NumericT epsilon = NumericT(1.0E-3);
      std::cout << "# Testing setup:" << std::endl;
      std::cout << "  eps:     " << epsilon << std::endl;
      std::cout << "  numeric: float" << std::endl;
      retval = test<NumericT>(epsilon);
      if( retval == EXIT_SUCCESS )
        std::cout << "# Test passed" << std::endl;
      else
        return retval;
   }
   std::cout << std::endl;
   std::cout << "----------------------------------------------" << std::endl;
   std::cout << std::endl;
#ifdef VIENNACL_HAVE_OPENCL
   if( viennacl::ocl::current_device().double_support() )
#endif
   {
      {
        typedef double NumericT;
        NumericT epsilon = 1.0E-11;
        std::cout << "# Testing setup:" << std::endl;
        std::cout << "  eps:     " << epsilon << std::endl;
        std::cout << "  numeric: double" << std::endl;
        retval = test<NumericT>(epsilon);
        if( retval == EXIT_SUCCESS )
          std::cout << "# Test passed" << std::endl;
        else
          return retval;
      }
      std::cout << std::endl;
      std::cout << "----------------------------------------------" << std::endl;
      std::cout << std::endl;
   }

   std::cout << std::endl;
   std::cout << "------- Test completed --------" << std::endl;
   std::cout << std::endl;

   return retval;
}


//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

// clang-format off

#include "PyImathConfigInternal.h"

#include "PyImathBox.h"
#include "PyImathVec.h"
#include "PyImathMathExc.h"
#include "PyImathDecorators.h"
#include "PyImathExport.h"
#include <boost/python/make_constructor.hpp>
#include <ImathBoxAlgo.h>
#include "PyImathTask.h"
#include <vector>
#include "PyImathBoxArrayImpl.h"

namespace PyImath {
using namespace boost::python;
using namespace IMATH_NAMESPACE;
using namespace PyImath;

template <class T> struct BoxName { static const char *value; };
template <> const char *BoxName<IMATH_NAMESPACE::V2s>::value = "Box2s";
template <> const char *BoxName<IMATH_NAMESPACE::V2i>::value = "Box2i";
template <> const char *BoxName<IMATH_NAMESPACE::V2f>::value = "Box2f";
template <> const char *BoxName<IMATH_NAMESPACE::V2d>::value = "Box2d";
template <> const char *BoxName<IMATH_NAMESPACE::V3s>::value = "Box3s";
template <> const char *BoxName<IMATH_NAMESPACE::V3i>::value = "Box3i";
template <> const char *BoxName<IMATH_NAMESPACE::V3f>::value = "Box3f";
template <> const char *BoxName<IMATH_NAMESPACE::V3d>::value = "Box3d";

template <> PYIMATH_EXPORT const char *PyImath::Box2sArray::name() { return "Box2sArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box2iArray::name() { return "Box2iArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box2fArray::name() { return "Box2fArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box2dArray::name() { return "Box2dArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box3sArray::name() { return "Box3sArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box3iArray::name() { return "Box3iArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box3fArray::name() { return "Box3fArray"; }
template <> PYIMATH_EXPORT const char *PyImath::Box3dArray::name() { return "Box3dArray"; }

template <class T>
static Box<T> * box2TupleConstructor1(const tuple &t)
{
    if(t.attr("__len__")() == 2)
    {
        // The constructor was called like this:
        // Box2f ((V2f(1,2), V2f(3,4))) or
        // Box2f (((1,2), (3,4)))

        PyObject *t0Obj = extract <object> (t[0])().ptr();
        PyObject *t1Obj = extract <object> (t[1])().ptr();
        T t0, t1;
        if (V2<typename T::BaseType>::convert (t0Obj, &t0) &&
            V2<typename T::BaseType>::convert (t1Obj, &t1))
        {
            return new Box<T> (t0, t1);
        }

        // The constructor was called like this:
        // Box2f ((1,2))

        else
        {
            T point;
            point.x = extract<double>(t[0]);
            point.y = extract<double>(t[1]);
            return new Box<T>(point);
        }
    }
    else
      throw std::invalid_argument ( "Invalid input to Box tuple constructor");
}

template <class T>
static Box<T> * box2TupleConstructor2(const tuple &t0, const tuple &t1)
{
    if(t0.attr("__len__")() == 2 && t1.attr("__len__")() == 2)
    {
        T point0, point1;
        point0.x = extract<double>(t0[0]); point0.y = extract<double>(t0[1]);
        point1.x = extract<double>(t1[0]); point1.y = extract<double>(t1[1]);

        return new Box<T>(point0, point1);
    }
    else
      throw std::invalid_argument ("Invalid input to Box tuple constructor");
}

template <class T, class S>
static Box<T> *boxConstructor(const Box<S> &box)
{
    Box<T> *newBox = new Box<T>;
    newBox->min = box.min;
    newBox->max = box.max;

    return newBox;
}

template <class T>
static Box<T> * box3TupleConstructor1(const tuple &t)
{
    if(t.attr("__len__")() == 3)
    {
        // The constructor was called like this:
        // Box3f ((1,2,3))

        T point;
        point.x = extract<double>(t[0]);
        point.y = extract<double>(t[1]);
        point.z = extract<double>(t[2]);
        return new Box<T>(point);
    }

    else if (t.attr("__len__")() == 2)
    {
        // The constructor was called like this:
        // Box3f ((V3f(1,2,3), V3f(4,5,6))) or
        // Box3f (((1,2,3), (4,5,6)))

        PyObject *t0Obj = extract <object> (t[0])().ptr();
        PyObject *t1Obj = extract <object> (t[1])().ptr();
        T t0, t1;
        if (V3<typename T::BaseType>::convert (t0Obj, &t0) &&
            V3<typename T::BaseType>::convert (t1Obj, &t1))
        {
            return new Box<T> (t0, t1);
        }
        else
          throw std::invalid_argument ("Invalid input to Box tuple constructor");
    }

    else
      throw std::invalid_argument ("Invalid input to Box tuple constructor");
}

template <class T>
static Box<T> * box3TupleConstructor2(const tuple &t0, const tuple &t1)
{
    if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3)
    {
        T point0, point1;
        point0.x = extract<double>(t0[0]);
        point0.y = extract<double>(t0[1]);
        point0.z = extract<double>(t0[2]);

        point1.x = extract<double>(t1[0]);
        point1.y = extract<double>(t1[1]);
        point1.z = extract<double>(t1[2]);

        return new Box<T>(point0, point1);
    }
    else
      throw std::invalid_argument ("Invalid input to Box tuple constructor");
}

template <class T>
static std::string Box2_repr(const Box<T> &box)
{
    std::stringstream stream;
    typename boost::python::return_by_value::apply <T>::type converter;

    PyObject *minObj = converter (box.min);
    PyObject *minReprObj = PyObject_Repr (minObj);
#if PY_MAJOR_VERSION > 2
    std::string minReprStr = PyUnicode_AsUTF8 (minReprObj);
#else
    std::string minReprStr = PyString_AsString (minReprObj);
#endif
    Py_DECREF (minReprObj);
    Py_DECREF (minObj);

    PyObject *maxObj = converter (box.max);
    PyObject *maxReprObj = PyObject_Repr (maxObj);
#if PY_MAJOR_VERSION > 2
    std::string maxReprStr = PyUnicode_AsUTF8 (maxReprObj);
#else
    std::string maxReprStr = PyString_AsString (maxReprObj);
#endif
    Py_DECREF (maxReprObj);
    Py_DECREF (maxObj);

    stream << BoxName<T>::value << "(" << minReprStr << ", " << maxReprStr << ")";

    return stream.str();
}

template <class T>
static std::string Box3_repr(const Box<T> &box)
{
    std::stringstream stream;
    typename boost::python::return_by_value::apply <T>::type converter;

    PyObject *minObj = converter (box.min);
    PyObject *minReprObj = PyObject_Repr (minObj);
#if PY_MAJOR_VERSION > 2
    std::string minReprStr = PyUnicode_AsUTF8 (minReprObj);
#else
    std::string minReprStr = PyString_AsString (minReprObj);
#endif
    Py_DECREF (minReprObj);
    Py_DECREF (minObj);

    PyObject *maxObj = converter (box.max);
    PyObject *maxReprObj = PyObject_Repr (maxObj);
#if PY_MAJOR_VERSION > 2
    std::string maxReprStr = PyUnicode_AsUTF8 (maxReprObj);
#else
    std::string maxReprStr = PyString_AsString (maxReprObj);
#endif
    Py_DECREF (maxReprObj);
    Py_DECREF (maxObj);

    stream << BoxName<T>::value << "(" << minReprStr << ", " << maxReprStr << ")";

    return stream.str();
}

template <class T>
static void boxSetMin(IMATH_NAMESPACE::Box<T> &box, const T &m)
{
    box.min = m;
}

template <class T>
static void boxSetMax(IMATH_NAMESPACE::Box<T> &box, const T &m)
{
    box.max = m;
}

template <class T>
static T
boxMin(IMATH_NAMESPACE::Box<T> &box)
{
    return box.min;
}

template <class T>
static T
boxMax(IMATH_NAMESPACE::Box<T> &box)
{
    return box.max;
}

template <class T>
struct IntersectsTask : public Task
{
    const IMATH_NAMESPACE::Box<T>& box;
    const PyImath::FixedArray<T>& points;
    PyImath::FixedArray<int>& results;

    IntersectsTask(IMATH_NAMESPACE::Box<T>& b, const PyImath::FixedArray<T> &p, PyImath::FixedArray<int> &r)
        : box(b), points(p), results(r) {}

    void execute(size_t start, size_t end)
    {
        for(size_t p = start; p < end; ++p)
            results[p] = box.intersects(points[p]);
    }
};

template <class T>
struct ExtendByTask : public Task
{
    std::vector<IMATH_NAMESPACE::Box<T> >& boxes;
    const PyImath::FixedArray<T>& points;

    ExtendByTask(std::vector<IMATH_NAMESPACE::Box<T> >& b, const PyImath::FixedArray<T> &p)
        : boxes(b), points(p) {}

    void execute(size_t start, size_t end, int tid)
    {
        for(size_t p = start; p < end; ++p)
            boxes[tid].extendBy(points[p]);
    }
    void execute(size_t start, size_t end)
    {
        throw std::invalid_argument ("Box::ExtendBy execute requires a thread id");
    }
};

template <class T>
static void
box_extendBy(IMATH_NAMESPACE::Box<T> &box, const PyImath::FixedArray<T> &points)
{
    size_t numBoxes = workers();
    std::vector<IMATH_NAMESPACE::Box<T> > boxes(numBoxes);
    ExtendByTask<T> task(boxes,points);
    dispatchTask(task,points.len());
    for (size_t i=0; i<numBoxes; ++i) {
        box.extendBy(boxes[i]);
    }
}

template <class T>
PyImath::FixedArray<int>
box_intersects(IMATH_NAMESPACE::Box<T>& box, const PyImath::FixedArray<T>& points)
{
    size_t numPoints = points.len();
    PyImath::FixedArray<int> mask(numPoints);

    IntersectsTask<T> task(box,points,mask);
    dispatchTask(task,numPoints);
    return mask;
}

template <class T>
class_<IMATH_NAMESPACE::Box<T> >
register_Box2()
{
    void (IMATH_NAMESPACE::Box<T>::*extendBy1)(const T&)              = &IMATH_NAMESPACE::Box<T>::extendBy;
    void (IMATH_NAMESPACE::Box<T>::*extendBy2)(const IMATH_NAMESPACE::Box<T>&)  = &IMATH_NAMESPACE::Box<T>::extendBy;
    bool (IMATH_NAMESPACE::Box<T>::*intersects1)(const T&) const              = &IMATH_NAMESPACE::Box<T>::intersects;
    bool (IMATH_NAMESPACE::Box<T>::*intersects2)(const IMATH_NAMESPACE::Box<T>&) const  = &IMATH_NAMESPACE::Box<T>::intersects;
    const char *name = BoxName<T>::value;
    class_<Box<T> > box_class(name);
    box_class
        .def(init<>("Box() create empty box") )
        .def(init<T>("Box(point)create box containing the given point") )
        .def(init<T,T>("Box(point,point) create box continaing min and max") )
        .def("__init__", make_constructor(box2TupleConstructor1<T>), "Box(point) where point is a python tuple")
        .def("__init__", make_constructor(box2TupleConstructor2<T>), "Box(point,point) where point is a python tuple")
        .def("__init__", make_constructor(boxConstructor<T, IMATH_NAMESPACE::V2f>))
        .def("__init__", make_constructor(boxConstructor<T, IMATH_NAMESPACE::V2d>))
        .def("__init__", make_constructor(boxConstructor<T, IMATH_NAMESPACE::V2i>))
        .def_readwrite("min",&Box<T>::min)
        .def_readwrite("max",&Box<T>::max)
        .def("min", &boxMin<T>)
        .def("max", &boxMax<T>)
        .def(self == self) // NOSONAR - suppress SonarCloud bug report.
        .def(self != self) // NOSONAR - suppress SonarCloud bug report.
        .def("__repr__", &Box2_repr<T>)
        .def("makeEmpty",&Box<T>::makeEmpty,"makeEmpty() make the box empty")
        .def("makeInfinite",&Box<T>::makeInfinite,"makeInfinite() make the box cover all space")
        .def("extendBy",extendBy1,"extendBy(point) extend the box by a point")
        .def("extendBy",box_extendBy<T>,"extendBy(array) extend the box the values in the array")
        .def("extendBy",extendBy2,"extendBy(box) extend the box by a box")
        .def("size",&Box<T>::size,"size() size of the box")
        .def("center",&Box<T>::center,"center() center of the box")
        .def("intersects",intersects1,"intersects(point) returns true if the box intersects the given point")
        .def("intersects",intersects2,"intersects(box) returns true if the box intersects the given box")
        .def("majorAxis",&Box<T>::majorAxis,"majorAxis() major axis of the box")
        .def("isEmpty",&Box<T>::isEmpty,"isEmpty() returns true if the box is empty")
        .def("isInfinite",&Box<T>::isInfinite,"isInfinite() returns true if the box covers all space")
        .def("hasVolume",&Box<T>::hasVolume,"hasVolume() returns true if the box has volume")
        .def("setMin",&boxSetMin<T>,"setMin() sets the min value of the box")
        .def("setMax",&boxSetMax<T>,"setMax() sets the max value of the box")
        ;
    return box_class;
}

template <class T, class U>
static IMATH_NAMESPACE::Box<T>
mulM44 (const IMATH_NAMESPACE::Box<T> &b, const Matrix44<U> &m)
{
    MATH_EXC_ON;
    return IMATH_NAMESPACE::transform (b, m);
}

template <class T, class U>
static const IMATH_NAMESPACE::Box<T> &
imulM44 (IMATH_NAMESPACE::Box<T> &b, const Matrix44<U> &m)
{
    MATH_EXC_ON;
    b = IMATH_NAMESPACE::transform (b, m);
    return b;
}

template <class T>
class_<IMATH_NAMESPACE::Box<T> >
register_Box3()
{
    void (IMATH_NAMESPACE::Box<T>::*extendBy1)(const T&)              = &IMATH_NAMESPACE::Box<T>::extendBy;
    void (IMATH_NAMESPACE::Box<T>::*extendBy2)(const IMATH_NAMESPACE::Box<T>&)  = &IMATH_NAMESPACE::Box<T>::extendBy;
    bool (IMATH_NAMESPACE::Box<T>::*intersects1)(const T&) const              = &IMATH_NAMESPACE::Box<T>::intersects;
    bool (IMATH_NAMESPACE::Box<T>::*intersects2)(const IMATH_NAMESPACE::Box<T>&) const  = &IMATH_NAMESPACE::Box<T>::intersects;
    const char *name = BoxName<T>::value;
    class_<Box<T> > box_class(name);
    box_class
        .def(init<>("Box() create empty box") )
        .def(init<T>("Box(point)create box containing the given point") )
        .def(init<T,T>("Box(point,point) create box continaing min and max") )
        .def("__init__", make_constructor(box3TupleConstructor1<T>), "Box(point) where point is a python tuple")
        .def("__init__", make_constructor(box3TupleConstructor2<T>), "Box(point,point) where point is a python tuple")
        .def("__init__", make_constructor(boxConstructor<T, IMATH_NAMESPACE::V3f>))
        .def("__init__", make_constructor(boxConstructor<T, IMATH_NAMESPACE::V3d>))
        .def("__init__", make_constructor(boxConstructor<T, IMATH_NAMESPACE::V3i>))
        .def_readwrite("min",&Box<T>::min)
        .def_readwrite("max",&Box<T>::max)
        .def(self == self) // NOSONAR - suppress SonarCloud bug report.
        .def(self != self) // NOSONAR - suppress SonarCloud bug report.
        .def("__mul__", &mulM44<T, float>)
        .def("__mul__", &mulM44<T, double>)
        .def("__imul__", &imulM44<T, float>,return_internal_reference<>())
        .def("__imul__", &imulM44<T, double>,return_internal_reference<>())
        .def("min", &boxMin<T>)
        .def("max", &boxMax<T>)
        .def("__repr__", &Box3_repr<T>)
        .def("makeEmpty",&Box<T>::makeEmpty,"makeEmpty() make the box empty")
        .def("makeInfinite",&Box<T>::makeInfinite,"makeInfinite() make the box cover all space")
        .def("extendBy",extendBy1,"extendBy(point) extend the box by a point")
        .def("extendBy",box_extendBy<T>,"extendBy(array) extend the box the values in the array")
        .def("extendBy",extendBy2,"extendBy(box) extend the box by a box")
        .def("size",&Box<T>::size,"size() size of the box")
        .def("center",&Box<T>::center,"center() center of the box")
        .def("intersects",intersects1,"intersects(point) returns true if the box intersects the given point")
        .def("intersects",intersects2,"intersects(box) returns true if the box intersects the given box")
        .def("intersects",box_intersects<T>, "intersects(array) returns an int array where 0 indicates the point is not in the box and 1 indicates that it is")
        .def("majorAxis",&Box<T>::majorAxis,"majorAxis() major axis of the box")
        .def("isEmpty",&Box<T>::isEmpty,"isEmpty() returns true if the box is empty")
        .def("isInfinite",&Box<T>::isInfinite,"isInfinite() returns true if the box covers all space")
        .def("hasVolume",&Box<T>::hasVolume,"hasVolume() returns true if the box has volume")
        .def("setMin",&boxSetMin<T>,"setMin() sets the min value of the box")
        .def("setMax",&boxSetMax<T>,"setMax() sets the max value of the box")
        ;

    decoratecopy(box_class);

    return box_class;
}

template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2s> > register_Box2<IMATH_NAMESPACE::V2s>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2i> > register_Box2<IMATH_NAMESPACE::V2i>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2f> > register_Box2<IMATH_NAMESPACE::V2f>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2d> > register_Box2<IMATH_NAMESPACE::V2d>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3s> > register_Box3<IMATH_NAMESPACE::V3s>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3i> > register_Box3<IMATH_NAMESPACE::V3i>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3f> > register_Box3<IMATH_NAMESPACE::V3f>();
template PYIMATH_EXPORT class_<IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3d> > register_Box3<IMATH_NAMESPACE::V3d>();

}


#include <iostream>
#include <map>
#include <cstring>
#include <fstream>
#include <queue>
#include <boost/algorithm/string.hpp>
#include <list>
#include <algorithm>

using namespace std;

std::map<std::string, int> Tokenize()
		{
	string filename;
	cout << "What file do you want to use for input? ";
	getline(cin, filename);

	std::map<string,int> mymap;

	ifstream fin;
	fin.open(filename.c_str());
	char * token;

	string str;

	while (fin >> str)
	{
		char *fileName = (char*)str.c_str();
		token = strtok (fileName," ,.-!;:");
		while (token != NULL)
		{
			boost::algorithm::to_lower(token);
			mymap[token]++;
			token = strtok (NULL, " ,.-!;:");
		}
	}
	fin.close();
	return mymap;
		}

void print (std::list<string> myMap)
{
	for (std::list<string>::iterator it=myMap.begin(); it!=myMap.end(); ++it)
	{
		std::cout << *it<< endl;
	}
}

std::list<string>Tokenize_list()
		{
	std::list<string> mylist;
	std::map<std::string, int> myMap =Tokenize();

	for (std::map<string,int>::iterator it=myMap.begin(); it!=myMap.end(); ++it)
	{
		mylist.push_back(it->first);
	}

	return mylist;
		}
int print_freq(std::map<std::string, int> myMap)
{
	int total=0;

	std::priority_queue<std::pair<int, std::string> > pq;
	for (std::map<string,int>::iterator it=myMap.begin(); it!=myMap.end(); ++it)
	{
		pq.push(std::make_pair(it->second, it->first)); ///push into heap
		total=total+it->second;
	}
	int size=myMap.size();
	for(int i=1; i<=size;i++)
	{
		std::cout << pq.top().first << ", " << pq.top().second << std::endl;
		pq.pop();
	}

	/*
	for (std::map<string,int>::iterator it=myMap.begin(); it!=myMap.end(); ++it)
	{
		std::cout <<it->first<<"=>"<< it->second<< endl;
		total=total+it->second;
	}
	 */
	cout<<"Total Number of words"<<":"<<total<<endl;
	return total;
}

int main()
{
	//int total;
	std::list<string> mylist= Tokenize_list();
	print(mylist);

	//std::list<string> mylist;
	std::map<std::string, int> myMap =Tokenize(); // Calculate Frequencies
	int total=print_freq(myMap);

	return 0;
}


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

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.

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

#ifndef BOOST_GEOMETRY_EXTENSIONS_ALGORITHMS_CONNECT_HPP
#define BOOST_GEOMETRY_EXTENSIONS_ALGORITHMS_CONNECT_HPP

#include <map>

#include <boost/range.hpp>

#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/policies/compare.hpp>

#include <boost/geometry/geometries/concepts/check.hpp>

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

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace connect
{

template <typename Point>
struct node
{
    int index;
    bool is_from;
    Point point;

    node(int i, bool f, Point const& p)
        : index(i)
        , is_from(f)
        , point(p)
    {}

    node()
        : index(-1)
        , is_from(false)
    {}
};

template <typename Point>
struct map_policy
{
    typedef typename strategy::distance::services::default_strategy
        <
            point_tag, point_tag, Point
        >::type strategy_type;

    // Have a map<point, <index,start/end> > such that we can find
    // the corresponding point on each end. Note that it uses the
    // default "equals" for the point-type
    typedef std::map
        <
            Point,
            std::vector<node<Point> >,
            geometry::less<Point>
        > map_type;

    typedef typename map_type::const_iterator map_iterator_type;
    typedef typename std::vector<node<Point> >::const_iterator vector_iterator_type;

    typedef Point point_type;
    typedef typename default_distance_result<Point>::type distance_result_type;

    map_type map;

    inline bool find_start(node<Point>& object,
            std::map<int, bool>& included,
            int expected_count = 1)
    {
        for (map_iterator_type it = map.begin();
            it != map.end();
            ++it)
        {
            if ((expected_count == 1 && boost::size(it->second) == 1)
                || (expected_count > 1 && boost::size(it->second) > 1))
            {
                for (vector_iterator_type vit = it->second.begin();
                    vit != it->second.end();
                    ++vit)
                {
                    if (! included[vit->index])
                    {
                        included[vit->index] = true;
                        object = *vit;
                        return true;
                    }
                }
            }
        }

        // Not found with one point, try one with two points
        // to find rings
        if (expected_count == 1)
        {
            return find_start(object, included, 2);
        }

        return false;
    }

    inline void add(int index, Point const& p, bool is_from)
    {
        map[p].push_back(node<Point>(index, is_from, p));
    }

    template <typename LineString>
    inline void add(int index, LineString const& ls)
    {
        if (boost::size(ls) > 0)
        {
            add(index, *boost::begin(ls), true);
            add(index, *(boost::end(ls) - 1), false);
        }
    }

    inline node<Point> find_closest(Point const& p1, std::map<int, bool>& included)
    {
        std::vector<node<Point> > const& range = map[p1];

        node<Point> closest;

        // Alternatively, we might look for the closest points
        if (boost::size(range) == 0)
        {
            std::cout << "nothing found" << std::endl;
            return closest;
        }

        // 2c: for all candidates get closest one
        strategy_type strategy;

        distance_result_type min_dist = strategy::distance::services
            ::result_from_distance<strategy_type, Point, Point>::apply(strategy, 100);

        for (vector_iterator_type it = boost::begin(range);
            it != boost::end(range);
            ++it)
        {
            if (! included[it->index])
            {
                distance_result_type d = geometry::comparable_distance(p1, it->point);
                if (d < min_dist)
                {
                    closest = *it;
                    min_dist = d;

                    //std::cout << "TO " << geometry::wkt(p2) << std::endl;
                }
            }
        }
        return closest;
    }

};

template <typename Point>
struct fuzzy_policy
{
    typedef typename strategy::distance::services::default_strategy
        <
            point_tag, point_tag, Point
        >::type strategy_type;

    // Have a map<point, <index,start/end> > such that we can find
    // the corresponding point on each end. Note that it uses the
    // default "equals" for the point-type
    typedef std::vector
        <
            std::pair
                <
                    Point,
                    std::vector<node<Point> >
                >
        > map_type;

    typedef typename map_type::const_iterator map_iterator_type;
    typedef typename std::vector<node<Point> >::const_iterator vector_iterator_type;

    typedef Point point_type;
    typedef typename default_distance_result<Point>::type distance_result_type;

    map_type map;
    typename coordinate_type<Point>::type m_limit;

    fuzzy_policy(typename coordinate_type<Point>::type limit)
        : m_limit(limit)
    {}

    inline bool find_start(node<Point>& object,
            std::map<int, bool>& included,
            int expected_count = 1)
    {
        for (map_iterator_type it = map.begin();
            it != map.end();
            ++it)
        {
            if ((expected_count == 1 && boost::size(it->second) == 1)
                || (expected_count > 1 && boost::size(it->second) > 1))
            {
                for (vector_iterator_type vit = it->second.begin();
                    vit != it->second.end();
                    ++vit)
                {
                    if (! included[vit->index])
                    {
                        included[vit->index] = true;
                        object = *vit;
                        return true;
                    }
                }
            }
        }

        // Not found with one point, try one with two points
        // to find rings
        if (expected_count == 1)
        {
            return find_start(object, included, 2);
        }

        return false;
    }

    inline typename boost::range_iterator<map_type>::type fuzzy_closest(Point const& p)
    {
        typename boost::range_iterator<map_type>::type closest = boost::end(map);

        for (typename boost::range_iterator<map_type>::type it = boost::begin(map);
            it != boost::end(map);
            ++it)
        {
            distance_result_type d = geometry::distance(p, it->first);
            if (d < m_limit)
            {
                if (closest == boost::end(map))
                {
                    closest = it;
                }
                else
                {
                    distance_result_type dc = geometry::distance(p, closest->first);
                    if (d < dc)
                    {
                        closest = it;
                    }
                }
            }
        }
        return closest;
    }

    inline void add(int index, Point const& p, bool is_from)
    {
        // Iterate through all points and get the closest one.
        typename boost::range_iterator<map_type>::type it = fuzzy_closest(p);
        if (it == map.end())
        {
            map.resize(map.size() + 1);
            map.back().first = p;
            it = map.end() - 1;
        }
        it->second.push_back(node<Point>(index, is_from, p));
    }

    template <typename LineString>
    inline void add(int index, LineString const& ls)
    {
        if (boost::size(ls) > 0)
        {
            add(index, *boost::begin(ls), true);
            add(index, *(boost::end(ls) - 1), false);
        }
    }

    inline node<Point> find_closest(Point const& p1, std::map<int, bool>& included)
    {
        namespace services = strategy::distance::services;

        node<Point> closest;

        typename boost::range_iterator<map_type>::type it = fuzzy_closest(p1);
        if (it == map.end())
        {
            return closest;
        }

        std::vector<node<Point> > const& range = it->second;

        // Alternatively, we might look for the closest points
        if (boost::size(range) == 0)
        {
            std::cout << "nothing found" << std::endl;
            return closest;
        }

        // 2c: for all candidates get closest one
        strategy_type strategy;
        distance_result_type min_dist = strategy::distance::services
            ::result_from_distance<strategy_type, Point, Point>::apply(strategy, 100);

        for (vector_iterator_type it = boost::begin(range);
            it != boost::end(range);
            ++it)
        {
            if (! included[it->index])
            {
                distance_result_type d = geometry::comparable_distance(p1, it->point);
                if (d < min_dist)
                {
                    closest = *it;
                    min_dist = d;

                    //std::cout << "TO " << geometry::wkt(p2) << std::endl;
                }
            }
        }
        return closest;
    }
};

template <typename Policy>
inline void debug(Policy const& policy)
{
    std::cout << "MAP" << std::endl;
    typedef typename Policy::map_type::const_iterator iterator;
    typedef typename Policy::point_type point_type;

    for (iterator it=policy.map.begin(); it != policy.map.end(); ++it)
    {
        std::cout << geometry::dsv(it->first) << " => " ;
        std::vector<node<point_type> > const& range =it->second;
        for (typename std::vector<node<point_type> >::const_iterator
            vit = boost::begin(range); vit != boost::end(range); ++vit)
        {
            std::cout
                << " (" << vit->index
                << ", " << (vit->is_from ? "F" : "T")
                << ")"
                ;
        }
        std::cout << std::endl;
    }
}

// Dissolve on multi_linestring tries to create larger linestrings from input,
// or closed rings.

template <typename Multi, typename GeometryOut, typename Policy>
struct connect_multi_linestring
{
    typedef typename point_type<Multi>::type point_type;
    typedef typename boost::range_iterator<Multi const>::type iterator_type;
    typedef typename boost::range_value<Multi>::type linestring_type;

    static inline void copy(linestring_type const& ls,
            GeometryOut& target,
            bool copy_forward)
    {
        if (copy_forward)
        {
            std::copy(boost::begin(ls), boost::end(ls),
                std::back_inserter(target));
        }
        else
        {
            std::reverse_copy(boost::begin(ls), boost::end(ls),
                std::back_inserter(target));
        }
    }

    template <typename OutputIterator>
    static inline OutputIterator apply(Multi const& multi, Policy& policy, OutputIterator out)
    {
        if (boost::size(multi) <= 0)
        {
            return out;
        }

        // 1: fill the map.
        int index = 0;
        for (iterator_type it = boost::begin(multi);
            it != boost::end(multi);
            ++it, ++index)
        {
            policy.add(index, *it);
        }

        debug(policy);

        std::map<int, bool> included;

        // 2: connect the lines

        // 2a: start with one having a unique starting point
        node<point_type> starting_point;
        if (! policy.find_start(starting_point, included))
        {
            return out;
        }

        GeometryOut current;
        copy(multi[starting_point.index], current, starting_point.is_from);

        bool found = true;
        while(found)
        {
            // 2b: get all candidates, by asking multi-map for range
            point_type const& p1 = *(boost::end(current) - 1);

            node<point_type> closest = policy.find_closest(p1, included);

            found = false;

            // 2d: if there is a closest one add it
            if (closest.index >= 0)
            {
                found = true;
                included[closest.index] = true;
                copy(multi[closest.index], current, closest.is_from);
            }
            else if ((included.size() != std::size_t(boost::size(multi))))
            {
                // Get one which is NOT found and go again
                node<point_type> next;
                if (policy.find_start(next, included))
                {
                    found = true;

                    *out++ = current;
                    geometry::clear(current);

                    copy(multi[next.index], current, next.is_from);
                }
            }
        }
        if (boost::size(current) > 0)
        {
            *out++ = current;
        }

        return out;
    }
};

}} // namespace detail::connect
#endif

#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{

template
<
    typename GeometryTag,
    typename GeometryOutTag,
    typename Geometry,
    typename GeometryOut,
    typename Policy
>
struct connect
{};

template<typename Multi, typename GeometryOut, typename Policy>
struct connect<multi_linestring_tag, linestring_tag, Multi, GeometryOut, Policy>
    : detail::connect::connect_multi_linestring
        <
            Multi,
            GeometryOut,
            Policy
        >
{};

} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

template
<
    typename Geometry,
    typename Collection
>
inline void connect(Geometry const& geometry, Collection& output_collection)
{
    typedef typename boost::range_value<Collection>::type geometry_out;

    concepts::check<Geometry const>();
    concepts::check<geometry_out>();

    typedef detail::connect::map_policy
        <
            typename point_type<Geometry>::type
        > policy_type;

    policy_type policy;

    dispatch::connect
    <
        typename tag<Geometry>::type,
        typename tag<geometry_out>::type,
        Geometry,
        geometry_out,
        policy_type
    >::apply(geometry, policy, std::back_inserter(output_collection));
}

template
<
    typename Geometry,
    typename Collection
>
inline void connect(Geometry const& geometry, Collection& output_collection,
            typename coordinate_type<Geometry>::type const& limit)
{
    typedef typename boost::range_value<Collection>::type geometry_out;

    concepts::check<Geometry const>();
    concepts::check<geometry_out>();

    typedef detail::connect::fuzzy_policy
        <
            typename point_type<Geometry>::type
        > policy_type;

    policy_type policy(limit);

    dispatch::connect
    <
        typename tag<Geometry>::type,
        typename tag<geometry_out>::type,
        Geometry,
        geometry_out,
        policy_type
    >::apply(geometry, policy, std::back_inserter(output_collection));
}

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_EXTENSIONS_ALGORITHMS_CONNECT_HPP


// Boost.Range library
//
//  Copyright Neil Groves 2010. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/irange.hpp>
#include <boost/range/algorithm_ext.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <vector>

namespace boost
{
    // Test an integer range with a step size of 1.
    template<typename Integer>
    void test_irange_impl(Integer first, Integer last)
    {
        std::vector<Integer> reference;
        for (Integer i = first; i < last; ++i)
        {
            reference.push_back(i);
        }

        std::vector<Integer> test;
        boost::push_back(test, boost::irange(first, last));

        BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
                                       reference.begin(), reference.end() );
    }

    // Test an integer range with a runtime specified step size.
    template<typename Integer>
    void test_irange_impl(Integer first, Integer last, int step)
    {
        BOOST_ASSERT( step != 0 );
        std::vector<Integer> reference;
        if (step > 0)
        {
            for (Integer i = first; i < last; i += step)
                reference.push_back(i);
        }
        else
        {
            for (Integer i = first; i > last; i += step)
                reference.push_back(i);
        }

        std::vector<Integer> test;
        boost::push_back(test, boost::irange(first, last, step));

        BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
                                       reference.begin(), reference.end() );
    }

    // Test driver function that for an integer range [first, last)
    // drives the test implementation through various integer
    // types.
    void test_irange(int first, int last)
    {
        test_irange_impl<signed char>(first,last);
        test_irange_impl<unsigned char>(first, last);
        test_irange_impl<signed short>(first, last);
        test_irange_impl<unsigned short>(first, last);
        test_irange_impl<signed int>(first, last);
        test_irange_impl<unsigned int>(first, last);
        test_irange_impl<signed long>(first, last);
        test_irange_impl<unsigned long>(first, last);
    }

    // Test driver function that for an integer range [first, last)
    // drives the test implementation through various integer
    // types step_size items at a time.
    void test_irange(int first, int last, int step_size)
    {
        BOOST_ASSERT( step_size != 0 );
        BOOST_ASSERT( (last - first) % step_size == 0 );
        test_irange_impl<signed char>(first, last, step_size);
        test_irange_impl<unsigned char>(first, last, step_size);
        test_irange_impl<signed short>(first, last, step_size);
        test_irange_impl<unsigned short>(first, last, step_size);
        test_irange_impl<signed int>(first, last, step_size);
        test_irange_impl<unsigned int>(first, last, step_size);
        test_irange_impl<signed long>(first, last, step_size);
        test_irange_impl<unsigned long>(first, last, step_size);
    }

    // Implementation of the unit test for the integer range
    // function.
    // This starts the test drivers to drive a set of integer types
    // for a combination of range values chosen to exercise a large
    // number of implementation branches.
    void irange_unit_test()
    {
        // Test the single-step version of irange(first, last)
        test_irange(0, 0);
        test_irange(0, 1);
        test_irange(0, 10);
        test_irange(1, 1);
        test_irange(1, 2);
        test_irange(1, 11);

        // Test the n-step version of irange(first, last, step-size)
        test_irange(0, 0, 1);
        test_irange(0, 0, -1);
        test_irange(0, 10, 1);
        test_irange(10, 0, -1);
        test_irange(0, 2, 2);
        test_irange(2, 0, -2);
        test_irange(10, 20, 5);
        test_irange(20, 10, -5);
    }
} // namespace boost

boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
    boost::unit_test::test_suite* test
        = BOOST_TEST_SUITE( "RangeTestSuite.irange" );

    test->add(BOOST_TEST_CASE( &boost::irange_unit_test ));

    return test;
}


/*
 * Main.cpp
 *
 *  Created on: Jun 12, 2013
 *      Author: remocean
 */

#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/filesystem.hpp>

#include "IDLNamespace.h"

using namespace std;
namespace fs = boost::filesystem;
using namespace boost::numeric::ublas;

int main() {
	cout << "START" << endl;

	try {
		 idl::Arr<idl::FLOAT> a(4);
		 a(0) = 10;
		 a(1) = 5;
		 a(2) = -3;
		 a(3) = -8;
		 cout << "a:" << a << endl;
		 a.setToZero();
		 cout << "a.clear:" << a << endl;

		 idl::Arr<idl::FLOAT> a2D(3,2);
		 //riga 0
		 a2D(0,0) = 0;
		 a2D(0,1) = 1;
		 //riga 1
		 a2D(1,0) = 2;
		 a2D(1,1) = 3;
		 //riga 2
		 a2D(2,0) = 4;
		 a2D(2,1) = 5;
		 cout << "a2D:" << a2D << endl;
		 idl::Arr<idl::FLOAT> b2D = idl::rebin(a2D, 6, 4);

		 idl::Arr<idl::FLOAT> z = idl::brange(a2D, 0, 2, 1, 2);
		 cout << "z:" << z << endl;

	} catch (int exp) {
		std::cerr << "IDL Exception : " << ExceptionMsg(exp) << std::endl;
	}

	cout << endl << "END" << endl;

	return 0;
}


// Copyright Aleksey Gurtovoy 2004
// Copyright Eric Friedman 2003
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/mpl for documentation.

// $Id$
// $Date$
// $Revision$

#include <boost/mpl/stable_partition.hpp>

#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/comparison.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/aux_/test.hpp>

typedef vector_c<int,3,4,0,-5,8,-1,7>::type numbers;
typedef vector_c<int,0,-5,-1>::type manual_first;
typedef vector_c<int,3,4,8,7>::type manual_second;

MPL_TEST_CASE()
{
    typedef stable_partition<
          numbers
        , less< _, int_<3> >
        >::type result;

    MPL_ASSERT(( equal< result::first,manual_first > ));
    MPL_ASSERT(( equal< result::second,manual_second > ));
}

MPL_TEST_CASE()
{
    typedef stable_partition<
          numbers
        , greater_equal< _, int_<3> >
        >::type result;

    MPL_ASSERT(( equal< result::first,manual_second > ));
    MPL_ASSERT(( equal< result::second,manual_first > ));
}