/*-----------------------------------------------------------------------------+
Copyright (c) 2008-2009: Joachim Faulhaber
+------------------------------------------------------------------------------+
   Distributed under the Boost Software License, Version 1.0.
      (See accompanying file LICENCE.txt or copy at
           http://www.boost.org/LICENSE_1_0.txt)
+-----------------------------------------------------------------------------*/
#define BOOST_TEST_MODULE icl::interval unit test
#include <libs/icl/test/disable_test_warnings.hpp>
#include <string>
#include <boost/mpl/list.hpp>
#include "../unit_test_unwarned.hpp"
#include <boost/test/test_case_template.hpp>

// interval instance types
#include "../test_type_lists.hpp"
#include "../test_value_maker.hpp"
#include "../test_interval_laws.hpp"

using namespace std;
using namespace boost;
using namespace unit_test;
using namespace boost::icl;

#include "../test_icl_interval_shared.hpp"
#include "../test_icl_interval.hpp"
#include "../test_icl_dynamic_interval.hpp"
#include "../test_icl_discrete_interval.hpp"
#include "../test_icl_continuous_interval.hpp"
#include "../test_icl_static_interval.hpp"

#include <boost/icl/right_open_interval.hpp>
#include <boost/icl/left_open_interval.hpp>
#include <boost/icl/closed_interval.hpp>
#include <boost/icl/open_interval.hpp>

#include <boost/icl/discrete_interval.hpp>
#include <boost/icl/continuous_interval.hpp>

//- sta.asy.{dis|con} ----------------------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_right_open_interval_ctor_4_ordered_types, T, ordered_types)
{                   interval_ctor_4_ordered_types<right_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_right_open_interval_4_ordered_types, T, discrete_types)
{      singelizable_interval_4_ordered_types<right_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_right_open_interval_4_bicremental_types, T, discrete_types)
{      singelizable_interval_4_bicremental_types<right_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_left_open_interval_ctor_4_ordered_types, T, ordered_types)
{                  interval_ctor_4_ordered_types<left_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_left_open_interval_4_ordered_types_singelizable, T, signed_discrete_types)
{     singelizable_interval_4_ordered_types<left_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_left_open_interval_4_bicremental_types, T, discrete_types)
{     singelizable_interval_4_bicremental_types<left_open_interval<T> >(); }

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

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_distant_intervals_4_discrete_types, T, discrete_types)
{         distant_intervals_4_discrete_types<T, std::less>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(test_itl_distant_intervals_4_numeric_continuous_types, T, numeric_continuous_types)
{         distant_intervals_4_numeric_continuous_types<T, std::less>(); }

//- sta.asy.{dis|con} ----------------------------------------------------------
//- n tests for right_open_inverval --------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_right_open_interval_ctor_4_ordered_types, T, ordered_types)
{                       interval_ctor_4_ordered_types<right_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_right_open_interval_4_ordered_types, T, discrete_types)
{          singelizable_interval_4_ordered_types<right_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_right_open_interval_4_bicremental_types, T, discrete_types)
{         singelizable_interval_4_bicremental_types<right_open_interval<T> >(); }

//- n tests for left_open_inverval ---------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_left_open_interval_ctor_4_ordered_types, T, ordered_types)
{                     interval_ctor_4_ordered_types<left_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_left_open_interval_4_ordered_types_singelizable, T, signed_discrete_types)
{        singelizable_interval_4_ordered_types<left_open_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_left_open_interval_4_bicremental_types, T, discrete_types)
{        singelizable_interval_4_bicremental_types<left_open_interval<T> >(); }

//- dyn.dis --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_discrete_interval_ctor_4_discrete_types_base, T, discrete_types)
{                     interval_ctor_4_ordered_types<discrete_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_discrete_interval_ctor_4_discrete_types_dynamic, T, discrete_types)
{             dynamic_interval_ctor_4_ordered_types<discrete_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_discrete_interval_4_ordered_types, T, discrete_types)
{        singelizable_interval_4_ordered_types<discrete_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_discrete_interval_4_bicremental_types, T, discrete_types)
{        singelizable_interval_4_bicremental_types<discrete_interval<T> >(); }

//- dyn.con --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_continuous_interval_ctor_4_continuous_types_base, T, continuous_types)
{                       interval_ctor_4_ordered_types<continuous_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_continuous_interval_ctor_4_continuous_types_dynamic, T, continuous_types)
{               dynamic_interval_ctor_4_ordered_types<continuous_interval<T> >(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_continuous_interval_4_continuous_types_singelizable, T, continuous_types)
{          singelizable_interval_4_ordered_types<continuous_interval<T> >(); }

//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_distant_intervals_4_discrete_types, T, discrete_types)
{            distant_intervals_4_discrete_types<T, std::less>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_distant_intervals_4_numeric_continuous_types, T, numeric_continuous_types)
{            distant_intervals_4_numeric_continuous_types<T, std::less>(); }

//------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_itl_dynamic_interval_bounds_4_bicremental_types, T, bicremental_types)
{            dynamic_interval_bounds_4_bicremental_types<T>(); }

//==============================================================================
//==============================================================================
BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_equal_4_integral_types, T, integral_types)
{            interval_equal_4_integral_types<T>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_less_4_integral_types, T, integral_types)
{            interval_less_4_integral_types<T>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_touches_4_bicremental_types, T, bicremental_types)
{            interval_touches_4_bicremental_types<T>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_touches_4_integral_types, T, integral_types)
{            interval_touches_4_integral_types<T>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_subtract_4_bicremental_types, T, bicremental_types)
{            interval_subtract_4_bicremental_types<T>(); }

#ifndef BOOST_ICL_USE_STATIC_BOUNDED_INTERVALS

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_ctor_specific)
{            interval_ctor_specific(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_equal_4_bicremental_continuous_types, T, bicremental_continuous_types)
{            interval_equal_4_bicremental_continuous_types<T>(); }

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_infix_intersect_4_bicremental_types, T, bicremental_types)
{            interval_infix_intersect_4_bicremental_types<T>(); }

#else

BOOST_AUTO_TEST_CASE_TEMPLATE
(fastest_icl_interval_infix_intersect_4_bicremental_types, T, discrete_types)
{            interval_infix_intersect_4_bicremental_types<T>(); }

#endif // ndef BOOST_ICL_USE_STATIC_BOUNDED_INTERVALS


/**
BSD 3-Clause License

This file is part of the code accompanying the paper
From Planes to Corners: Multi-Purpose Primitive Detection in Unorganized 3D Point Clouds
by C. Sommer, Y. Sun, L. Guibas, D. Cremers and T. Birdal,
accepted for Publication in IEEE Robotics and Automation Letters (RA-L) 2020.

Copyright (c) 2019, Christiane Sommer.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// includes
#include <iostream>
#include <fstream>
#include "definitions.h"
// libraries
#include <Eigen/Dense>
#include <opencv2/core/core.hpp>
#include <CLI/CLI.hpp>
// classes
#include "Timer.h"
#include "Plane.h"
#include "graph/PlaneGraph.h"
#include "graph/ParallelPlaneGraph.h"
#include "PPF/PairDetector.h"
// function includes
#include "io/load_ply_cloud.h"
#include "visualize/pcshow.h"

/*
 * main
 */
int main(int argc, char** argv) {

    Timer T;

    // parse setttings from command line
    std::string ply_file;
    int min_votes = 5;
    double d_min = .1, d_max = 1.;
    int sampling = 50;

    CLI::App app{"Detect and refine orthogonal plane configurations"};
    app.add_option("--img", ply_file, "ply file path, from data/")->required();
    app.add_option("--min-votes", min_votes, "minimal number of votes to accept configuration");
    app.add_option("--dmin", d_min, "minimal distance between two points");
    app.add_option("--dmax", d_max, "maximal distance between two points");
    app.add_option("--sampling", sampling, "sampling of points");

    try {
        app.parse(argc, argv);
    } catch (const CLI::ParseError& e) {
        return app.exit(e);
    }

    // load data
    std::string filepath = "../data/";
    std::vector<Eigen::Vector3f> points;
    std::vector<Eigen::Vector3f> normals;

    T.tic();
    read_ply_file(filepath+ply_file, points, normals);
    T.toc("read data");
    std::cout << points.size() << " points loaded." << std::endl;
    std::cout << normals.size() << " normals loaded." << std::endl;

    pcshow(points);

    // pairing
    ppf::PairDetector pairDet(d_max, d_min, min_votes);
    PlaneGraph planeMap(pairDet.para_thresh(), pairDet.distance_bin());
    T.tic();
    pairDet.detect_ortho_pairs(points, normals, planeMap);
    T.toc("time pairing PPF ");
    planeMap.print_info();

    std::cout << std::endl << "Thresholds:\tAngle:\t" << pairDet.para_thresh() << "\tDistance:\t" << pairDet.distance_bin() << std::endl << std::endl;

    // clustering & filtering
    T.tic();
    planeMap.cluster_graph_vertices();
    T.toc("clustering planes");
    planeMap.print_info();
    planeMap.print_parameters();
    planeMap.print_edges();

    // find triangles
    std::vector<Graph<Plane>::Triangle> triangles;
    T.tic();
    planeMap.find_triangles(triangles);
    T.toc("Finding triangles");
    planeMap.print_triangles(triangles);

    // reduce graph to ParallelPlaneGraph
    T.tic();
    ParallelPlaneGraph redMap = planeMap.reduce_graph();
    T.toc("graph reduction");
    redMap.print_info();
    redMap.print_edges();
    T.tic();
    redMap.triangle_reduce();
    T.toc("triangle reduction");
    redMap.print_info();
    redMap.print_parameters();
    redMap.print_edges();

    T.tic();
    redMap.filter_outliers(points, normals, pairDet.distance_bin(), .5*sampling);
    T.toc("outlier filtering");
    redMap.print_info();
    redMap.print_parameters();
    redMap.print_edges();

    // CERES problem setup and solving
    double lambda = 0.01 * points.size();
    T.tic();
    redMap.refine_coarse_fine(points, normals, lambda, pairDet.distance_bin(), sampling);
    T.toc("Multi-plane parameter optimization");
    redMap.print_info();
    redMap.print_parameters();
    redMap.print_edges();

    T.tic();
    redMap.filter_outliers(points, normals, pairDet.distance_bin(), .5*sampling);
    T.toc("outlier filtering");
    redMap.print_info();
    redMap.print_parameters();
    redMap.print_edges();

    // From here on visualization / debugging

//    // get points located on planes and not-planes
    PlaneGraph finalMap = PlaneGraph::from_ppg(redMap, 2*pairDet.para_thresh()*pairDet.para_thresh()-1, pairDet.distance_bin()); // double angle
    std::vector<Eigen::Matrix<float, 6, 1>> labeled;
    T.tic();
    finalMap.go_thr_pcl(points, normals, labeled);
    T.toc("labeling planes");

    // visualize
    pcshow(labeled, "Result");

//    std::vector<Vec6> lines;
//    // line extraction and visualization
//    T.tic();
//    lines = finalMap.extract_lines(points, normals);
//    T.toc("get lines");
//    std::cout << lines.size() << " lines found." << std::endl;
//
//    pcshow_lines(points, lines, "Orth Plane Intersections");

}


/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */

/**
 * \file boost/numeric/ublasx/operation/any.hpp
 *
 * \brief The \c any operation.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 * <hr/>
 *
 * Copyright (c) 2010, Marco Guazzone
 *
 * Distributed under the Boost Software License, Version 1.0. (See
 * accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_NUMERIC_UBLASX_OPERATION_ANY_HPP
#define BOOST_NUMERIC_UBLASX_OPERATION_ANY_HPP

#include <boost/numeric/ublas/detail/config.hpp>
#include <boost/numeric/ublas/expression_types.hpp>
//#include <boost/numeric/ublas/operation/begin.hpp>
//#include <boost/numeric/ublas/operation/end.hpp>
#include <boost/numeric/ublasx/operation/num_columns.hpp>
#include <boost/numeric/ublasx/operation/num_rows.hpp>
#include <boost/numeric/ublasx/operation/size.hpp>
//#include <boost/numeric/ublasx/tags.hpp>
#include <boost/numeric/ublas/traits.hpp>
//#include <boost/numeric/ublasx/traits/const_iterator_type.hpp>
#include <functional>

namespace boost { namespace numeric { namespace ublasx {

using namespace ::boost::numeric::ublas;

//@{ Declarations

/**
 * \brief Tell if there is at least one element of the given vector expression
 *  which satisfies the given unary predicate.
 * \tparam VectorExprT The type of the vector expression.
 * \tparam UnaryPredicateT The type of the unary predicate functor.
 * \param ve The vector expression over which check for the predicate.
 * \param p The unary predicate functor: must accept one argument and return
 *  a boolean value.
 * \return \c true if there exists at least one element of the given vector
 *  expression which satisfies the given predicate; \c false otherwise.
 *
 * \author Marco Guazzone, <marco.guazzone@gmail.com>
 */
template <typename VectorExprT, typename UnaryPredicateT>
bool any(vector_expression<VectorExprT> const& ve, UnaryPredicateT p);

/**
 * \brief Tell if the given vector expression contains at least one non-zero
 *  element.
 * \tparam VectorExprT The type of the vector expression.
 * \param ve The vector expression over which check for existence of non-zero
 *  elements.
 * \return \c true if the given vector expression contains at least one non-zero
 *  element; \c false otherwise.
 *
 * \note The test for zero equality is done in the strong sense, that is by not
 *  using any tolerance.
 *  For checking for "weak" zero equality between a given tolerance use the
 *  two-argument version of this function with an appropriate predicate.
 *
 * \author Marco Guazzone, <marco.guazzone@gmail.com>
 */
template <typename VectorExprT>
bool any(vector_expression<VectorExprT> const& ve);

/**
 * \brief Tell if there is at least one element of the given matrix expression
 *  which satisfies the given unary predicate.
 * \tparam MatrixExprT The type of the matrix expression.
 * \tparam UnaryPredicateT The type of the unary predicate functor.
 * \param me The matrix expression over which check for the predicate.
 * \param p The unary predicate functor: must accept one argument and return
 *  a boolean value.
 * \return \c true if there exists at least one element of the given matrix
 *  expression which satisfies the given predicate; \c false otherwise.
 *
 * \author Marco Guazzone, <marco.guazzone@gmail.com>
 */
template <typename MatrixExprT, typename UnaryPredicateT>
bool any(matrix_expression<MatrixExprT> const& me, UnaryPredicateT p);

/**
 * \brief Tell if the given matrix expression contains at least one non-zero
 *  element.
 * \tparam MatrixExprT The type of the matrix expression.
 * \param me The matrix expression over which check for existence of non-zero
 *  elements.
 * \return \c true if the given matrix expression contains at least one non-zero
 *  element; \c false otherwise.
 *
 * \note The test for zero equality is done in the strong sense, that is by not
 *  using any tolerance.
 *  For checking for "weak" zero equality between a given tolerance use the
 *  two-argument version of this function with an appropriate predicate.
 *
 * \author Marco Guazzone, <marco.guazzone@gmail.com>
 */
template <typename MatrixExprT>
bool any(matrix_expression<MatrixExprT> const& me);

//@} Declarations

//@{ Definitions

template <typename VectorExprT, typename UnaryPredicateT>
BOOST_UBLAS_INLINE
bool any(vector_expression<VectorExprT> const& ve, UnaryPredicateT p)
{
    // Implementation Note:
    //  Currently (06-2010) there are only iterators that skip zero-valued
    //  elements.
    //  So the iteration is done through plain indices instead of iterators.

//  typedef typename vector_traits<VectorExprT>::const_iterator iterator_type;
//
//  iterator_type it_end = end(ve);
//  for (iterator_type it = begin(ve); it != it_end; ++it)
//  {
//      if (p(*it))
//      {
//          return true;
//      }
//  }
//

    typedef typename vector_traits<VectorExprT>::size_type size_type;

    size_type n = size(ve);
    for (size_type i = 0; i < n; ++i)
    {
        if (p(ve()(i)))
        {
            return true;
        }
    }

    return false;
}

template <typename VectorExprT>
BOOST_UBLAS_INLINE
bool any(vector_expression<VectorExprT> const& ve)
{
    typedef typename vector_traits<VectorExprT>::value_type value_type;

    return any(ve, ::std::bind2nd(::std::not_equal_to<value_type>(), 0));
}

template <typename MatrixExprT, typename UnaryPredicateT>
BOOST_UBLAS_INLINE
bool any(matrix_expression<MatrixExprT> const& me, UnaryPredicateT p)
{
    // Implementation Note:
    //  Currently (06-2010) there are only iterators that skip zero-valued
    //  elements.
    //  So the iteration is done through plain indices instead of iterators.

//  typedef typename const_iterator_type<MatrixExprT,tag::major>::type maj_iterator_type;
//  typedef typename const_iterator_type<MatrixExprT,tag::minor>::type min_iterator_type;
//
//  maj_iterator_type maj_it_end = end<tag::major>(me);
//  for (maj_iterator_type maj_it = begin<tag::major>(me); maj_it != maj_it_end; ++maj_it)
//  {
//      min_iterator_type min_it_end = end(maj_it);
//      for (min_iterator_type min_it = begin(maj_it); min_it != min_it_end; ++min_it)
//      {
//          if (p(*min_it))
//          {
//              return true;
//          }
//      }
//  }

    typedef typename matrix_traits<MatrixExprT>::size_type size_type;

    size_type nr = num_rows(me);
    size_type nc = num_columns(me);
    for (size_type r = 0; r < nr; ++r)
    {
        for (size_type c = 0; c < nc; ++c)
        {
            if (p(me()(r,c)))
            {
                return true;
            }
        }
    }

    return false;
}

template <typename MatrixExprT>
BOOST_UBLAS_INLINE
bool any(matrix_expression<MatrixExprT> const& me)
{
    typedef typename matrix_traits<MatrixExprT>::value_type value_type;

    return any(me, ::std::bind2nd(::std::not_equal_to<value_type>(), value_type(0)));
}

//@} Definitions

}}} // Namespace boost::numeric::ublasx

#endif // BOOST_NUMERIC_UBLASX_OPERATION_ANY_HPP


//---------------------------------------------------------------------------//
//!
//! \file   tstInverseSquareAngstromUnit.cpp
//! \author Alex Robinson
//! \brief  The inverse square Angstrom unit unit tests
//!
//---------------------------------------------------------------------------//

// Boost Includes
#include <boost/units/quantity.hpp>
#include <boost/units/systems/cgs/area.hpp>
#include <boost/units/systems/si/area.hpp>

// Trilinos Includes
#include <Teuchos_UnitTestHarness.hpp>

// FRENSIE Includes
#include "Utility_InverseSquareAngstromUnit.hpp"
#include "Utility_InverseAngstromUnit.hpp"
#include "Utility_AngstromUnit.hpp"

using namespace Utility::Units;
using boost::units::quantity;
namespace si = boost::units::si;
namespace cgs = boost::units::cgs;

//---------------------------------------------------------------------------//
// Tests
//---------------------------------------------------------------------------//
// Check that the inverse square angstrom unit can be initialized
TEUCHOS_UNIT_TEST( InverseSquareAngstromUnit, initialize )
{
  quantity<InverseSquareAngstrom>
    inverse_sqr_angstrom( 1.0*inverse_square_angstrom );

  TEST_EQUALITY_CONST( inverse_sqr_angstrom.value(), 1.0 );

  inverse_sqr_angstrom = 2.0*inverse_square_angstrom;

  TEST_EQUALITY_CONST( inverse_sqr_angstrom.value(), 2.0 );
}

//---------------------------------------------------------------------------//
// Check that the inv. sqr. angs. unit can be initialized from the inv. angs.
TEUCHOS_UNIT_TEST( InverseSquareAngstromUnit, initialize_from_inv_angstrom )
{
  quantity<InverseSquareAngstrom>
    inverse_sqr_angstrom( 1.0*inverse_angstrom*inverse_angstrom );

  TEST_EQUALITY_CONST( inverse_sqr_angstrom.value(), 1.0 );

  inverse_sqr_angstrom = 2.0*inverse_angstrom*inverse_angstrom;

  TEST_EQUALITY_CONST( inverse_sqr_angstrom.value(), 2.0 );
}

//---------------------------------------------------------------------------//
// Check that the inv. sqr. angs. unit can be initialized from the angs. unit
TEUCHOS_UNIT_TEST( InverseSquareAngstromUnit, initialize_from_angstrom )
{
  quantity<InverseSquareAngstrom>
    inverse_sqr_angstrom( 1.0/(angstrom*angstrom) );

  TEST_EQUALITY_CONST( inverse_sqr_angstrom.value(), 1.0 );

  inverse_sqr_angstrom = 2.0/(angstrom*angstrom);

  TEST_EQUALITY_CONST( inverse_sqr_angstrom.value(), 2.0 );
}

//---------------------------------------------------------------------------//
// Check that the inv. sqr. angs. unit can be initialized from cgs, si units
TEUCHOS_UNIT_TEST( InverseSquareAngstromUnit, initialize_from_cgs_si )
{
  quantity<InverseSquareAngstrom>
    inverse_sqr_angstrom_cgs( 1.0/cgs::square_centimeter );

  quantity<InverseSquareAngstrom>
    inverse_sqr_angstrom_si( 1.0/si::square_meter );

  TEST_EQUALITY_CONST( inverse_sqr_angstrom_cgs.value(), 1e-16 );
  TEST_EQUALITY_CONST( inverse_sqr_angstrom_si.value(), 1e-20 );
}

//---------------------------------------------------------------------------//
// end tstInverseSquareAngstrom.cpp
//---------------------------------------------------------------------------//


// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/local_function

#include <boost/spirit/include/phoenix.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <algorithm>
#include <iostream>

//[add_phoenix
int main(void) {
    using boost::phoenix::let;
    using boost::phoenix::local_names::_f;
    using boost::phoenix::cref;
    using boost::phoenix::ref;
    using boost::phoenix::arg_names::_1;

    int sum = 0, factor = 10;
    int nums[] = {1, 2, 3};

    // Passed to template, `factor` by constant, and defined in expression.
    std::for_each(nums, nums + 3, let(_f = cref(factor))[
        // Unfortunately, body cannot use C++ statement syntax.
        ref(sum) += _f * _1, _1 // Access `sum` by reference.
    ]);

    BOOST_TEST(sum == 60);
    return boost::report_errors();
}
//]


/*
 * test_AD.cpp
 *
 *  Created on: 2019-5-18
 *      Author: fasiondog
 */

#ifdef TEST_ALL_IN_ONE
    #include <boost/test/unit_test.hpp>
#else
    #define BOOST_TEST_MODULE test_hikyuu_indicator_suite
    #include <boost/test/unit_test.hpp>
#endif

#include <fstream>
#include <hikyuu/StockManager.h>
#include <hikyuu/indicator/crt/AD.h>

using namespace hku;

/**
 * @defgroup test_indicator_AD test_indicator_AD
 * @ingroup test_hikyuu_indicator_suite
 * @{
 */

/** @par 检测点 */
BOOST_AUTO_TEST_CASE( test_AD ) {
    StockManager& sm = StockManager::instance();

    Stock stk = getStock("SH600004");
    KQuery query = KQueryByIndex(-10);
    KData k = stk.getKData(query);

    Indicator ad = AD(k);
    BOOST_CHECK(ad.name() == "AD");
    BOOST_CHECK(ad.size() == k.size());
    BOOST_CHECK(ad.discard() == 0);
    BOOST_CHECK(ad[0] == 0);
    BOOST_CHECK_CLOSE(ad[1], 458.65, 0.1);
    BOOST_CHECK_CLOSE(ad[2], 63.99, 0.1);
    BOOST_CHECK_CLOSE(ad[5], 30.77, 0.1);
}

//-----------------------------------------------------------------------------
// test export
//-----------------------------------------------------------------------------
#if HKU_SUPPORT_SERIALIZATION

/** @par 检测点 */
BOOST_AUTO_TEST_CASE( test_AD_export ) {
    StockManager& sm = StockManager::instance();
    string filename(sm.tmpdir());
    filename += "/AD.xml";

    KData k = getStock("SH600000").getKData(KQuery(-10));
    Indicator x1 = AD(k);
    x1.setContext(k);

    {
        std::ofstream ofs(filename);
        boost::archive::xml_oarchive oa(ofs);
        oa << BOOST_SERIALIZATION_NVP(x1);
    }

    Indicator x2;
    {
        std::ifstream ifs(filename);
        boost::archive::xml_iarchive ia(ifs);
        ia >> BOOST_SERIALIZATION_NVP(x2);
    }

    BOOST_CHECK(x2.name() == "AD");
    BOOST_CHECK(x1.size() == x2.size());
    BOOST_CHECK(x1.discard() == x2.discard());
    BOOST_CHECK(x1.getResultNumber() == x2.getResultNumber());
    for (size_t i = 0; i < x1.size(); ++i) {
        BOOST_CHECK_CLOSE(x1[i], x2[i], 0.00001);
    }
}
#endif /* #if HKU_SUPPORT_SERIALIZATION */

/** @} */


/*
 * PolynomialSplineContainer.hpp
 *
 *  Created on: Dec 8, 2014
 *      Author: C. Dario Bellicoso, Peter Fankhauser
 */

#pragma once

// Eigen
#include <Eigen/Core>
#include <Eigen/Dense>
#include "curves/polynomial_splines.hpp"

// std
#include <iostream>
#include <limits>
#include <memory>

// boost
#include <boost/math/special_functions/pow.hpp>

namespace curves {

template <int splineOrder_>
class PolynomialSplineContainer {
 public:
  using SplineType = PolynomialSpline<splineOrder_>;
  using SplineList = std::vector<SplineType>;

  EIGEN_MAKE_ALIGNED_OPERATOR_NEW

  PolynomialSplineContainer();
  virtual ~PolynomialSplineContainer() = default;

  //! Get a pointer to the spline with a given index.
  SplineType* getSpline(int splineIndex);

  //! Get a reference to the spline with a given index.
  const SplineList& getSplines() const;

  //! Update the spline internal time by dt [seconds].
  bool advance(double dt);

  //! Jump to a specific point in time domain.
  void setContainerTime(double t);

  //! Add a spline to the container.
  template <typename SplineType_>
  bool addSpline(SplineType_&& spline) {
    containerDuration_ += spline.getSplineDuration();
    splines_.emplace_back(std::forward<SplineType_>(spline));
    return true;
  }

  //! Reserve memory for the spline container.
  bool reserveSplines(const unsigned int numSplines);

  //! Clear spline container.
  bool reset();

  //! Set container.
  bool resetTime();

  //! Get total trajectory duration.
  double getContainerDuration() const;

  //! Get currently active time point.
  double getContainerTime() const;

  //! True if splines are empty.
  bool isEmpty() const;

  //! Get the position evaluated at the internal time.
  double getPosition() const;

  //! Get the velocity evaluated at the internal time.
  double getVelocity() const;

  //! Get the acceleration evaluated at the internal time.
  double getAcceleration() const;

  /*! Get the index of the spline active at time t [seconds].
   *  Update timeOffset with the duration of the container at the beginning of the active spline.
   */
  int getActiveSplineIndexAtTime(double t, double& timeOffset) const;

  //! Return spline index at current time validity.
  int getActiveSplineIndex() const;

  //! Get position at time t[seconds];
  double getPositionAtTime(double t) const;

  //! Get velocity at time t[seconds];
  double getVelocityAtTime(double t) const;

  //! Get acceleration at time t[seconds];
  double getAccelerationAtTime(double t) const;

  //! Get position at the end of the spline.
  double getEndPosition() const;

  //! Get velocity at the end of the spline.
  double getEndVelocity() const;

  //! Get acceleration at the end of the spline.
  double getEndAcceleration() const;

  /*!
   * Minimize spline coefficients s.t. position, velocity and acceleration constraints are satisfied
   * (i.e., s.t. the spline conjunction is smooth up the second derivative).
   */
  bool setData(const std::vector<double>& knotDurations, const std::vector<double>& knotPositions, double initialVelocity,
               double initialAcceleration, double finalVelocity, double finalAcceleration);

  /*!
   * Minimize spline coefficients s.t. position and velocity constraints are satisfied
   * (i.e., s.t. the spline conjunction is smooth up the first derivative).
   */
  bool setData(const std::vector<double>& knotDurations, const std::vector<double>& knotPositions, double initialVelocity,
               double finalVelocity);

  /*!
   * Find linear part of the spline coefficients (a0, a1) s.t. position constraints are satisfied.
   * If the spline order is larger than 1, the remaining spline coefficients are set to zero.
   */
  virtual bool setData(const std::vector<double>& knotDurations, const std::vector<double>& knotPositions);

  static constexpr double undefinedValue = std::numeric_limits<double>::quiet_NaN();

  bool checkContainer() const;

 protected:
  /*!
   * aijh:
   *  i --> spline id (1,...,n)
   *  j --> spline coefficient aj (a5,...,a1,a0)
   *  h --> dimX, dimY
   *
   * Coefficient vector is:
   *    q = [a15x a14x ... a10x a15y ... a10y a25x ... a20y ... an5x ... an0y]
   */
  inline int getCoeffIndex(const int splineIdx, const int aIdx) const { return splineIdx * (splineOrder_ + 1) + aIdx; }

  inline int getSplineColumnIndex(const int splineIdx) const { return getCoeffIndex(splineIdx, 0); }

  void addInitialConditions(const Eigen::VectorXd& initialConditions, unsigned int& constraintIdx);

  void addFinalConditions(const Eigen::VectorXd& finalConditions, unsigned int& constraintIdx, const double lastSplineDuration,
                          const unsigned int lastSplineId);

  void addJunctionsConditions(const std::vector<double>& splineDurations, const std::vector<double>& knotPositions,
                              unsigned int& constraintIdx, const unsigned int num_junctions);

  bool extractSplineCoefficients(const Eigen::VectorXd& coeffs, const std::vector<double>& splineDurations, const unsigned int num_splines);

  //! Conjunction of smoothly interconnected splines.
  SplineList splines_;

  //! Helper variable.
  double timeOffset_;

  //! Current time of spline conjunction.
  double containerTime_;

  //! Total duration of spline conjunction.
  double containerDuration_;

  //! Spline index currently active.
  int activeSplineIdx_;

  //! Equality matrix of quadratic program (A in Ax=b).
  Eigen::MatrixXd equalityConstraintJacobian_;

  //! Equality target values of quatratic program (b in Ax=b).
  Eigen::VectorXd equalityConstraintTargetValues_;
};

}  // namespace curves

#include <curves/PolynomialSplineContainer.tpp>


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

#include <boost/hana/ext/boost/mpl/integral_c.hpp>
#include <boost/hana/tuple.hpp>

#include <laws/constant.hpp>

#include <boost/mpl/int.hpp>
#include <boost/mpl/integral_c.hpp>
using namespace boost::hana;
namespace mpl = boost::mpl;

int main() {
    auto constants = make<Tuple>(
        mpl::int_<-10>{}, mpl::int_<-2>{}, mpl::integral_c<int, 0>{},
        mpl::integral_c<int, 1>{}, mpl::integral_c<int, 3>{}
    );

    //////////////////////////////////////////////////////////////////////////
    // Constant
    //////////////////////////////////////////////////////////////////////////
    {
        // value
        static_assert(value(mpl::integral_c<int, 0>{}) == 0, "");
        static_assert(value(mpl::integral_c<int, 1>{}) == 1, "");
        static_assert(value(mpl::integral_c<int, 3>{}) == 3, "");

        // laws
        test::TestConstant<ext::boost::mpl::IntegralC<int>>{constants};
    }
}


/*
 * Copyright 2021 INRIA
 */

#ifndef __eigenpy_decomposition_minres_hpp__
#define __eigenpy_decomposition_minres_hpp__

#include "eigenpy/eigenpy.hpp"

#include <iostream>
#include <Eigen/Core>
#include <unsupported/Eigen/IterativeSolvers>

#include "eigenpy/utils/scalar-name.hpp"

namespace eigenpy
{
  template<typename _Solver>
  struct IterativeSolverBaseVisitor
  : public boost::python::def_visitor< IterativeSolverBaseVisitor<_Solver> >
  {
    typedef _Solver Solver;
    typedef typename Solver::MatrixType MatrixType;
    typedef typename Solver::Preconditioner Preconditioner;
    typedef typename Solver::Scalar Scalar;
    typedef typename Solver::RealScalar RealScalar;

    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic,MatrixType::Options> MatrixXs;

    template<class PyClass>
    void visit(PyClass& cl) const
    {
      namespace bp = boost::python;
      cl
      .def("analyzePattern",
           (Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::analyzePattern,
           bp::args("self","A"),
           "Initializes the iterative solver for the sparsity pattern of the matrix A for further solving Ax=b problems.",
           bp::return_self<>())
      .def("factorize",
           (Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::factorize,
           bp::args("self","A"),
           "Initializes the iterative solver with the numerical values of the matrix A for further solving Ax=b problems.",
           bp::return_self<>())
      .def("compute",
           (Solver & (Solver::*)(const Eigen::EigenBase<MatrixType> & matrix))&Solver::compute,
           bp::args("self","A"),
           "Initializes the iterative solver with the matrix A for further solving Ax=b problems.",
           bp::return_self<>())

      .def("rows",&Solver::rows,bp::arg("self"),"Returns the number of rows.")
      .def("cols",&Solver::cols,bp::arg("self"),"Returns the number of columns.")
      .def("tolerance",&Solver::tolerance,bp::arg("self"),
           "Returns the tolerance threshold used by the stopping criteria.")
      .def("setTolerance",&Solver::setTolerance,bp::args("self","tolerance"),
           "Sets the tolerance threshold used by the stopping criteria.\n"
           "This value is used as an upper bound to the relative residual error: |Ax-b|/|b|.\n"
           "The default value is the machine precision given by NumTraits<Scalar>::epsilon().",
           bp::return_self<>())
      .def("preconditioner",(Preconditioner & (Solver::*)())&Solver::preconditioner,bp::arg("self"),
           "Returns a read-write reference to the preconditioner for custom configuration.",
           bp::return_internal_reference<>())

      .def("maxIterations",&Solver::maxIterations,bp::arg("self"),
           "Returns the max number of iterations.\n"
           "It is either the value setted by setMaxIterations or, by default, twice the number of columns of the matrix.")
      .def("setMaxIterations",&Solver::setMaxIterations,bp::args("self","max_iterations"),
           "Sets the max number of iterations.\n"
           "Default is twice the number of columns of the matrix.",
           bp::return_self<>())

      .def("iterations",&Solver::iterations,bp::arg("self"),
           "Returns the number of iterations performed during the last solve.")
      .def("error",&Solver::error,bp::arg("self"),
           "Returns the tolerance error reached during the last solve.\n"
           "It is a close approximation of the true relative residual error |Ax-b|/|b|.")
      .def("info",&Solver::error,bp::arg("info"),
           "Returns Success if the iterations converged, and NoConvergence otherwise.")

      .def("solveWithGuess",&solveWithGuess<MatrixXs,MatrixXs>,bp::args("self","b","x0"),
           "Returns the solution x of A x = b using the current decomposition of A and x0 as an initial solution.")

      .def("solve",&solve<MatrixXs>,bp::args("self","b"),
           "Returns the solution x of A x = b using the current decomposition of A where b is a right hand side matrix or vector.")
      ;
    }

  private:

    template<typename MatrixOrVector1, typename MatrixOrVector2>
    static MatrixOrVector1 solveWithGuess(const Solver & self, const MatrixOrVector1 & b, const MatrixOrVector2 & guess)
    {
      return self.solveWithGuess(b,guess);
    }

    template<typename MatrixOrVector>
    static MatrixOrVector solve(const Solver & self, const MatrixOrVector & mat_or_vec)
    {
      MatrixOrVector res = self.solve(mat_or_vec);
      return res;
    }
  };

  template<typename _MatrixType>
  struct MINRESSolverVisitor
  : public boost::python::def_visitor< MINRESSolverVisitor<_MatrixType> >
  {

    typedef _MatrixType MatrixType;
    typedef typename MatrixType::Scalar Scalar;
    typedef typename MatrixType::RealScalar RealScalar;
    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1,MatrixType::Options> VectorXs;
    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic,MatrixType::Options> MatrixXs;
    typedef Eigen::MINRES<MatrixType> Solver;

    template<class PyClass>
    void visit(PyClass& cl) const
    {
      namespace bp = boost::python;
      cl
      .def(bp::init<>("Default constructor"))
      .def(bp::init<MatrixType>(bp::arg("matrix"),
                                "Initialize the solver with matrix A for further Ax=b solving.\n"
                                "This constructor is a shortcut for the default constructor followed by a call to compute()."))

      .def(IterativeSolverBaseVisitor<Solver>())
      ;
    }

    static void expose()
    {
      static const std::string classname = "MINRES" + scalar_name<Scalar>::shortname();
      expose(classname);
    }

    static void expose(const std::string & name)
    {
      namespace bp = boost::python;
      bp::class_<Solver, boost::noncopyable>(name.c_str(),
                         "A minimal residual solver for sparse symmetric problems.\n"
                         "This class allows to solve for A.x = b sparse linear problems using the MINRES algorithm of Paige and Saunders (1975). The sparse matrix A must be symmetric (possibly indefinite). The vectors x and b can be either dense or sparse.\n"
                         "The maximal number of iterations and tolerance value can be controlled via the setMaxIterations() and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations and NumTraits<Scalar>::epsilon() for the tolerance.\n",
                         bp::no_init)
      .def(MINRESSolverVisitor());
    }

  private:

    template<typename MatrixOrVector>
    static MatrixOrVector solve(const Solver & self, const MatrixOrVector & vec)
    {
      return self.solve(vec);
    }
  };

} // namespace eigenpy

#endif // ifndef __eigenpy_decomposition_minres_hpp__


#include "headers/Heapsort.hpp"
#include "headers/Object.hpp"
#include <armadillo>
#include <vector>

using namespace arma;
using namespace std;

Heapsort::Heapsort() {
}

vector<Object*> Heapsort::heapsort(vector <Object *> &objetos, int n, int eixo){

    int i = (n/2)+1, pai, filho;
    Object * t;

    for (;;){

        if (i > 0){
            i--;
            t = objetos[i];
        }

        else{
            n--;

            if (n == 0)  {
                return objetos;
            }

            t = objetos[n];
            objetos[n] = objetos[0];
        }

        pai = i;
        filho = i*2;

        while (filho < n){

            if ((filho + 1 < n)  &&  (objetos[filho + 1]->getCentro()(eixo) > objetos[filho]->getCentro()(eixo))) {
                filho++;
            }

            if (objetos[filho]->getCentro()(eixo) > t->getCentro()(eixo)){

                objetos[pai] = objetos[filho];
                pai = filho;
                filho = pai*2 + 1;
            }

            else {
                break;
            }
        }

        objetos[pai] = t;
    }

}


//#include <boost/config.hpp>
#include <iostream>
#include <fstream>
#include <string>

#include <boost/graph/graphviz.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/adjacency_list.hpp>

using boost::GraphvizDigraph;

template <typename Vertex_Descriptor, typename Vertex_Name_Map>
::std::string const & vertex_label(Vertex_Descriptor v, Vertex_Name_Map & name_map)
{
  return (*(name_map[v].find("label"))).second;
}

// Accepting state?
template <typename Vertex_Descriptor, typename Vertex_Name_Map>
bool accepting(Vertex_Descriptor v, Vertex_Name_Map & name_map)
{
  return (*(name_map[v].find("peripheries"))).second == "2" ? true : false;
}

template <typename Edge_Descriptor, typename Edge_Name_Map>
::std::string const & edge_label(Edge_Descriptor e, Edge_Name_Map & name_map)
{
  return(*(name_map[e].find("label"))).second;
}

void print_all_vertices(GraphvizDigraph const & g)
{
  char c;
  ::std::cout << "VERTICES:\n";

  typedef boost::graph_traits<GraphvizDigraph>::vertex_iterator Vertex_Iter_t;

  boost::property_map<GraphvizDigraph, boost::vertex_attribute_t>::const_type
    name_map = boost::get(boost::vertex_attribute, g);

  for(::std::pair<Vertex_Iter_t, Vertex_Iter_t> p = boost::vertices(g); p.first != p.second; ++p.first){

    if(accepting(*p.first, name_map))
      c = 'a';
    else
      c = '-';

    ::std::cout << vertex_label(*p.first, name_map)
                << "[" << c << "]" << ::std::endl;

  }
}

void print_all_edges(GraphvizDigraph const & g)
{
  ::std::cout << "EDGES:\n";

  typedef boost::graph_traits<GraphvizDigraph>::edge_iterator Edge_Iter_t;

  boost::property_map<GraphvizDigraph, boost::edge_attribute_t>::const_type
    name_map;
  name_map = boost::get(boost::edge_attribute, g);

  for(::std::pair<Edge_Iter_t, Edge_Iter_t> p = boost::edges(g); p.first != p.second; ++p.first){
    ::std::cout << edge_label(*p.first, name_map) << ::std::endl;
  }
}

void scc(GraphvizDigraph const & g)
{
  ::std::cout <<"SCC\n";
  typedef ::boost::graph_traits<GraphvizDigraph>::vertex_descriptor vertex_t;
  ::std::map<vertex_t, int> component;

  int num = strong_components(g, ::boost::make_assoc_property_map(component));

  ::boost::graph_traits<GraphvizDigraph>::vertex_iterator vi, vi_end;
  for(::boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi){
    ::std::cout << component[*vi] << ::std::endl;
  }

//   std::vector<int> c(num_vertices(g));
//   int num = strong_components
//     (g, ::boost::make_iterator_property_map(c.begin(), get(::boost::vertex_index, g)));

//   ::std::cout << "Total comps " << num << ::std::endl;
//   ::std::vector<int>::iterator i;
//   for(i = c.begin(); i != c.end(); ++i)
//     ::std::cout << "Vertex " << i - c.begin() << " is in comp " << *i
//		<< ::std::endl;
}

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

  std::string filename = "graphviz_test.dot";

  if ( argc > 1 )
    filename = argv[1];
  else{
    std::cout << "Usage: " << argv[0] << "  <input>.dot  <output>.dot " << std::endl;
    return 0;
  }

  ::boost::GraphvizDigraph g;

  boost::read_graphviz(filename, g);

  print_all_vertices(g);
  print_all_edges(g);
  scc(g);

  const char* dot = "graphviz_test_new.dot";
  if ( argc > 2 )
    dot = argv[2];

  boost::write_graphviz(dot, g);

  return 0;
}


/**
 * Copyright (c) 2015 Carnegie Mellon University, Daniel Maturana <dimatura@cmu.edu>
 *
 * For License information please see the LICENSE file in the root directory.
 *
 */

#ifndef DENSE_ARRAY3_HPP_JEO7CAXQ
#define DENSE_ARRAY3_HPP_JEO7CAXQ

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

#include <vector>

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

#include <ros/console.h>

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

#include "scrollgrid/grid_types.hpp"

namespace ca
{

/**
 * A dense 3D array.
 * Maps ijk to an CellT.
 * No notion of origin, scrolling etc.
 * The *Grid3 classes handle that.
 * TODO maybe use boost::shared_array,
 * or std::shared_array if we move to C++11
 *
 */
template<class CellT>
class DenseArray3 {
public:
  typedef CellT CellType;
  typedef CellT * ArrayType;
  typedef CellT * iterator;
  typedef const CellT * const_iterator;

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

public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW;

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

  DenseArray3() :
      dimension_(0, 0, 0),
      num_cells_(0),
      strides_(0, 0, 0),
      grid_(NULL),
      begin_(NULL),
      end_(NULL),
      owns_memory_(false)
  { }

  DenseArray3(const Vec3Ix& dimension) :
      dimension_(dimension),
      num_cells_(dimension.prod()),
      strides_(dimension.tail<2>().prod(), dimension[2], 1),
      grid_(new CellT[num_cells_]()),
      begin_(&grid_[0]),
      end_(&grid_[0]+num_cells_),
      owns_memory_(true)
  { }

  /**
   * Used when wrapping an external chunk of data.
   */
  DenseArray3(const Vec3Ix& dimension, ArrayType grid_data) :
      dimension_(dimension),
      num_cells_(dimension.prod()),
      strides_(dimension.tail<2>().prod(), dimension[2], 1),
      grid_(grid_data),
      begin_(&grid_[0]),
      end_(&grid_[0]+num_cells_),
      owns_memory_(false)
  { }

  void CopyFrom(const DenseArray3& other) {
    this->reset(other.dimension());
    std::copy(other.begin(), other.end(), this->begin());
  }

  virtual ~DenseArray3() {
    if (owns_memory_ && grid_) { delete[] grid_; grid_ = NULL; }
  }

  void reset(const Vec3Ix& dimension) {
    dimension_ = dimension;
    num_cells_ = dimension.prod();
    // TODO configurable
    strides_ = Vec3Ix(dimension.tail<2>().prod(), dimension[2], 1);
    if (owns_memory_ && grid_) { delete[] grid_; }
    // note new T[n]() != new T[n];
    // the former initializes to zero
    grid_ = new CellT[num_cells_]();
    begin_ = &(grid_[0]);
    end_ = &(grid_[0])+num_cells_;
  }

  void reset(const Vec3Ix& dimension, ArrayType grid_data) {
    if (owns_memory_ && grid_) { delete[] grid_; }
    dimension_ = dimension;
    num_cells_ = dimension.prod();
    // TODO configurable
    strides_ = Vec3Ix(dimension.tail<2>().prod(), dimension[2], 1);
    owns_memory_ = false;
    grid_ = grid_data;
    begin_ = &(grid_[0]);
    end_ = &(grid_[0])+num_cells_;
  }

  size_t allocated_bytes() {
    return sizeof(CellT)*num_cells_;
  }

public:

  void fill(const CellT& val) {
    std::fill(this->begin(), this->end(), val);
  }

public:
  iterator begin() const { return begin_; }
  iterator end() const { return end_; }

public:

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

  grid_ix_t local_grid_to_mem(const Vec3Ix& grid_ix) const {
    return strides_.dot(grid_ix);
  }

  Vec3Ix local_mem_to_grid(grid_ix_t mem_ix) const {
    grid_ix_t i = mem_ix/strides_[0];
    mem_ix -= i*strides_[0];
    grid_ix_t j = mem_ix/strides_[1];
    mem_ix -= j*strides_[1];
    grid_ix_t k = mem_ix;
    return Vec3Ix(i, j, k);
  }

public:

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

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

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

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

public:

  /**
   * Bound check with ROS_ASSERT
   * Not 'really' safe
   */
  CellType& get_safe(grid_ix_t mem_ix) {
    ROS_ASSERT(mem_ix >= 0 && mem_ix < num_cells_);
    return grid_[mem_ix];
  }

  /**
   * Bound check with ROS_ASSERT
   * Not 'really' safe
   */
  const CellType& get_safe(grid_ix_t mem_ix) const {
    ROS_ASSERT(mem_ix >= 0 && mem_ix < num_cells_);
    return grid_[mem_ix];
  }

public:

  /**
   * No bound check
   */
  CellType& operator[](grid_ix_t mem_ix) {
    return grid_[mem_ix];
  }

  /**
   * No bound check
   */
  const CellType& operator[](grid_ix_t mem_ix) const {
    return grid_[mem_ix];
  }

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

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

  // number of cells
  grid_ix_t num_cells_;

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

  ArrayType grid_;
  iterator begin_, end_;

  // does this object own the grid_ mem
  bool owns_memory_;

//private:
 // DenseArray3(const DenseArray3& other);
 // DenseArray3& operator=(const DenseArray3& other);
};

} /* ca */

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


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

// authors: Hugo Théveniaut and Fabien Alet

#ifndef NETKET_CUSTOMSAMPLER_HPP
#define NETKET_CUSTOMSAMPLER_HPP

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

namespace netket {

// Metropolis sampling using custom moves provided by user
template <class WfType>
class CustomSampler : public AbstractSampler<WfType> {
  WfType &psi_;
  const Hilbert &hilbert_;
  std::vector<LocalOperator> move_operators_;
  std::vector<double> operatorsweights_;

  // number of visible units
  const int nv_;

  netket::default_random_engine rgen_;

  // states of visible units
  Eigen::VectorXd v_;

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

  int mynode_;
  int totalnodes_;

  // Look-up tables
  typename WfType::LookupType lt_;

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

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

 public:
  using MatType = std::vector<std::vector<std::complex<double>>>;

  explicit CustomSampler(WfType &psi, const json &pars)
      : psi_(psi), hilbert_(psi.GetHilbert()), nv_(hilbert_.Size()) {
    CheckFieldExists(pars["Sampler"], "MoveOperators");

    if (!pars["Sampler"]["MoveOperators"].is_array()) {
      throw InvalidInputError("MoveOperators is not an array");
    }
    CheckFieldExists(pars["Sampler"], "ActingOn");

    if (!pars["Sampler"]["ActingOn"].is_array()) {
      throw InvalidInputError("ActingOn is not an array");
    }

    auto jop = pars["Sampler"]["MoveOperators"].get<std::vector<MatType>>();
    auto sites =
        pars["Sampler"]["ActingOn"].get<std::vector<std::vector<int>>>();

    if (sites.size() != jop.size()) {
      throw InvalidInputError(
          "The custom sampler definition is inconsistent (between "
          "MoveOperators and ActingOn sizes); Check that ActingOn is defined");
    }

    std::set<int> touched_sites;
    for (std::size_t c = 0; c < jop.size(); c++) {
      // check if matrix of this operator is stochastic
      bool is_stochastic = true;
      bool is_complex = false;
      bool is_definite_positive = true;
      bool is_symmetric = true;
      const double epsilon = 1.0e-6;
      for (std::size_t i = 0; i < jop[c].size(); i++) {
        double sum_column = 0.;
        for (std::size_t j = 0; j < jop[c].size(); j++) {
          if (std::abs(jop[c][i][j].imag()) > epsilon) {
            is_complex = true;
            is_stochastic = false;
            break;
          }
          if (jop[c][i][j].real() < 0) {
            is_definite_positive = false;
            is_stochastic = false;
            break;
          }
          if (std::abs(jop[c][i][j].real() - jop[c][j][i].real()) > epsilon) {
            is_symmetric = false;
            is_stochastic = false;
            break;
          }
          sum_column += jop[c][i][j].real();
        }
        if (std::abs(sum_column - 1.) > epsilon) {
          is_stochastic = false;
        }
      }
      if (is_complex == true) {
        InfoMessage() << "Warning: MoveOperators " << c
                      << " has complex matrix elements" << std::endl;
      }
      if (is_definite_positive == false) {
        InfoMessage() << "Warning: MoveOperators " << c
                      << " has negative matrix elements" << std::endl;
      }
      if (is_symmetric == false) {
        InfoMessage() << "Warning: MoveOperators " << c << " is not symmetric"
                      << std::endl;
      }
      if (is_stochastic == false) {
        InfoMessage() << "Warning: MoveOperators " << c << " is not stochastic"
                      << std::endl;
        InfoMessage() << "MoveOperators " << c << " is discarded" << std::endl;
      }

      else {
        move_operators_.push_back(LocalOperator(hilbert_, jop[c], sites[c]));
        for (std::size_t i = 0; i < sites[c].size(); i++) {
          touched_sites.insert(sites[c][i]);
        }
      }
    }

    if (move_operators_.size() == 0) {
      throw InvalidInputError("No valid MoveOperators provided");
    }

    if (static_cast<int>(touched_sites.size()) != hilbert_.Size()) {
      InfoMessage() << "Warning: MoveOperators appear not to act on "
                       "all sites of the sample:"
                    << std::endl;
      InfoMessage() << "Check ergodicity" << std::endl;
    }

    if (FieldExists(pars["Sampler"], "MoveWeights")) {
      if (!pars["Sampler"]["MoveWeights"].is_array()) {
        throw InvalidInputError("MoveWeights is not an array");
      }
      operatorsweights_ =
          pars["Sampler"]["MoveWeights"].get<std::vector<double>>();

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

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

    Init();
  }

  void Init() {
    v_.resize(nv_);

    MPI_Comm_size(MPI_COMM_WORLD, &totalnodes_);
    MPI_Comm_rank(MPI_COMM_WORLD, &mynode_);

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

    accept_.resize(1);
    moves_.resize(1);

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

    Seed();

    Reset(true);

    InfoMessage() << "Custom Metropolis sampler is ready " << std::endl;
  }

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

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

    SendToAll(seeds);

    rgen_.seed(seeds[mynode_]);
  }

  void Reset(bool initrandom = false) override {
    if (initrandom) {
      hilbert_.RandomVals(v_, rgen_);
    }

    psi_.InitLookup(v_, lt_);

    accept_ = Eigen::VectorXd::Zero(1);
    moves_ = Eigen::VectorXd::Zero(1);
  }

  void Sweep() override {
    std::discrete_distribution<int> disc_dist(operatorsweights_.begin(),
                                              operatorsweights_.end());
    std::uniform_real_distribution<double> distu;

    for (int i = 0; i < nv_; i++) {
      // pick a random operator in possible ones according to the provided
      // weights
      int op = disc_dist(rgen_);
      move_operators_[op].FindConn(v_, mel_, tochange_, newconfs_);

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

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

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

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

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

  WfType &Psi() override { return psi_; }

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

#endif


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

// Standard includes
#include <fstream>
#include <string>

// Third party includes
#include <boost/format.hpp>

// VOTCA includes
#include <votca/tools/constants.h>

// Local VOTCA includes
#include "votca/xtp/polarsite.h"

using namespace std;

namespace votca {
namespace xtp {

PolarSite::PolarSite(Index id, std::string element, Eigen::Vector3d pos)
    : StaticSite(id, element, pos) {
  tools::Elements e;
  double default_pol = std::pow(tools::conv::ang2bohr, 3);
  try {
    default_pol =
        e.getPolarizability(element) * std::pow(tools::conv::nm2bohr, 3);
  } catch (const std::runtime_error&) {
    ;
  }
  setpolarization(default_pol * Eigen::Matrix3d::Identity());
}

PolarSite::PolarSite(const data& d) { ReadData(d); }

Eigen::Vector3d PolarSite::getDipole() const {
  Eigen::Vector3d dipole = _Q.segment<3>(1);
  dipole += Induced_Dipole();
  return dipole;
}

void PolarSite::setpolarization(const Eigen::Matrix3d& pol) {
  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es;
  es.computeDirect(pol);
  _pinv = es.eigenvectors() * es.eigenvalues().cwiseInverse().asDiagonal() *
          es.eigenvectors().transpose();
  _eigendamp_invsqrt = 1.0 / std::sqrt(es.eigenvalues().maxCoeff());
}

std::string PolarSite::writepolarization() const {
  double conv_pol = std::pow(tools::conv::bohr2ang, 3);
  Eigen::MatrixX3d pol = _pinv.inverse() * conv_pol;
  return (boost::format("     P %1$+1.7f %2$+1.7f %3$+1.7f %4$+1.7f %5$+1.7f "
                        "%6$+1.7f\n") %
          pol(0, 0) % pol(1, 0) % pol(2, 0) % pol(1, 1) % pol(1, 2) % pol(2, 2))
      .str();
}

void PolarSite::SetupCptTable(CptTable& table) const {
  table.addCol(_id, "index", HOFFSET(data, id));
  table.addCol(_element, "type", HOFFSET(data, element));

  table.addCol(_pos[0], "posX", HOFFSET(data, posX));
  table.addCol(_pos[1], "posY", HOFFSET(data, posY));
  table.addCol(_pos[2], "posZ", HOFFSET(data, posZ));
  // same type as rank
  table.addCol(_rank, "rank", HOFFSET(data, rank));

  table.addCol(_Q[0], "Q00", HOFFSET(data, Q00));
  table.addCol(_Q[1], "Q11c", HOFFSET(data, Q11c));
  table.addCol(_Q[2], "Q11s", HOFFSET(data, Q11s));
  table.addCol(_Q[3], "Q10", HOFFSET(data, Q10));
  table.addCol(_Q[4], "Q20", HOFFSET(data, Q20));
  table.addCol(_Q[5], "Q21c", HOFFSET(data, Q21c));
  table.addCol(_Q[6], "Q21s", HOFFSET(data, Q21s));
  table.addCol(_Q[7], "Q22c", HOFFSET(data, Q22c));
  table.addCol(_Q[8], "Q22s", HOFFSET(data, Q22s));

  table.addCol(_V[0], "Vx", HOFFSET(data, Vx));
  table.addCol(_V[1], "Vy", HOFFSET(data, Vy));
  table.addCol(_V[2], "Vz", HOFFSET(data, Vz));

  table.addCol(_V_noE[0], "Vx_noE", HOFFSET(data, Vx_noE));
  table.addCol(_V_noE[1], "Vy_NoE", HOFFSET(data, Vy_noE));
  table.addCol(_V_noE[2], "Vz_noE", HOFFSET(data, Vz_noE));
  // P_inv and P have same polarization so no problem, as only data type counts
  table.addCol(_pinv(0, 0), "pxx", HOFFSET(data, pxx));
  table.addCol(_pinv(0, 1), "pxy", HOFFSET(data, pxy));
  table.addCol(_pinv(0, 2), "pxz", HOFFSET(data, pxz));
  table.addCol(_pinv(1, 1), "pyy", HOFFSET(data, pyy));
  table.addCol(_pinv(1, 2), "pyz", HOFFSET(data, pyz));
  table.addCol(_pinv(2, 2), "pzz", HOFFSET(data, pzz));

  table.addCol(_induced_dipole.x(), "d_ind_x", HOFFSET(data, d_x_ind));
  table.addCol(_induced_dipole.y(), "d_ind_y", HOFFSET(data, d_y_ind));
  table.addCol(_induced_dipole.z(), "d_ind_z", HOFFSET(data, d_z_ind));
}

void PolarSite::WriteData(data& d) const {
  d.id = _id;
  d.element = const_cast<char*>(_element.c_str());
  d.posX = _pos[0];
  d.posY = _pos[1];
  d.posZ = _pos[2];

  d.rank = _rank;

  d.Q00 = _Q[0];
  d.Q11c = _Q[1];
  d.Q11s = _Q[2];
  d.Q10 = _Q[3];
  d.Q20 = _Q[4];
  d.Q21c = _Q[5];
  d.Q21s = _Q[6];
  d.Q22c = _Q[7];
  d.Q22s = _Q[8];

  d.Vx = _V[0];
  d.Vy = _V[1];
  d.Vz = _V[2];

  d.Vx_noE = _V_noE[0];
  d.Vy_noE = _V_noE[1];
  d.Vz_noE = _V_noE[2];

  Eigen::Matrix3d P = _pinv.inverse();
  d.pxx = P(0, 0);
  d.pxy = P(0, 1);
  d.pxz = P(0, 2);
  d.pyy = P(1, 1);
  d.pyz = P(1, 2);
  d.pzz = P(2, 2);

  d.d_x_ind = _induced_dipole.x();
  d.d_y_ind = _induced_dipole.y();
  d.d_z_ind = _induced_dipole.z();
}

void PolarSite::ReadData(const data& d) {
  _id = d.id;
  _element = std::string(d.element);
  free(d.element);
  _pos[0] = d.posX;
  _pos[1] = d.posY;
  _pos[2] = d.posZ;

  _rank = d.rank;

  _Q[0] = d.Q00;
  _Q[1] = d.Q11c;
  _Q[2] = d.Q11s;
  _Q[3] = d.Q10;
  _Q[4] = d.Q20;
  _Q[5] = d.Q21c;
  _Q[6] = d.Q21s;
  _Q[7] = d.Q22c;
  _Q[8] = d.Q22s;

  _V[0] = d.Vx;
  _V[1] = d.Vy;
  _V[2] = d.Vz;

  _V_noE[0] = d.Vx_noE;
  _V_noE[1] = d.Vy_noE;
  _V_noE[2] = d.Vz_noE;

  Eigen::Matrix3d Ps;
  Ps(0, 0) = d.pxx;
  Ps(0, 1) = d.pxy;
  Ps(1, 0) = d.pxy;
  Ps(0, 2) = d.pxz;
  Ps(2, 0) = d.pxz;
  Ps(1, 1) = d.pyy;
  Ps(1, 2) = d.pyz;
  Ps(2, 1) = d.pyz;
  Ps(2, 2) = d.pzz;

  this->setpolarization(Ps);

  _induced_dipole.x() = d.d_x_ind;
  _induced_dipole.y() = d.d_y_ind;
  _induced_dipole.z() = d.d_z_ind;
}

}  // namespace xtp
}  // namespace votca


// -----------------------------------------------------------------------------
// Fern © Geoneric
//
// This file is part of Geoneric Fern which is available under the terms of
// the GNU General Public License (GPL), version 2. If you do not want to
// be bound by the terms of the GPL, you may purchase a proprietary license
// from Geoneric (http://www.geoneric.eu/contact).
// -----------------------------------------------------------------------------
#define BOOST_TEST_MODULE fern algorithm algebra unary_local_operation
#include <boost/test/unit_test.hpp>
#include "fern/core/data_customization_point/scalar.h"
#include "fern/core/data_customization_point/vector.h"
#include "fern/feature/core/data_customization_point/array.h"
#include "fern/feature/core/data_customization_point/masked_array.h"
#include "fern/feature/core/data_customization_point/masked_scalar.h"
#include "fern/algorithm/algebra/elementary/absolute.h"

namespace fa = fern::algorithm;

using ArgumentValue = int32_t;
using ResultValue = int32_t;

template<
    class ArgumentValue
>
using Algorithm = fa::absolute::detail::Algorithm<ArgumentValue>;

template<
    class Value,
    class Result
>
using OutOfRangePolicy = fa::absolute::OutOfRangePolicy<Value, Result>;

BOOST_AUTO_TEST_CASE(array_0d)
{
    using InputNoDataPolicy = fa::InputNoDataPolicies<fa::SkipNoData>;
    using OutputNoDataPolicy = fa::DontMarkNoData;
    using Argument = ArgumentValue;
    using Result = ResultValue;

    fa::ParallelExecutionPolicy parallel;
    fa::SequentialExecutionPolicy sequential;

    OutputNoDataPolicy output_no_data_policy;
    Argument argument{-5};
    Result result{3};

    fa::unary_local_operation<
        Algorithm,
        fa::unary::DiscardDomainErrors,
        fa::unary::DiscardRangeErrors>(
            InputNoDataPolicy{{}},
            output_no_data_policy,
            sequential, argument, result);

    BOOST_REQUIRE_EQUAL(result, 5);

    result = 3;

    fa::unary_local_operation<
        Algorithm,
        fa::unary::DiscardDomainErrors,
        fa::unary::DiscardRangeErrors>(
            InputNoDataPolicy{{}},
            output_no_data_policy,
            parallel, argument, result);

    BOOST_REQUIRE_EQUAL(result, 5);
}

BOOST_AUTO_TEST_CASE(array_0d_masked)
{
    using InputNoDataPolicy = fa::InputNoDataPolicies<
        fa::DetectNoDataByValue<bool>>;
    using OutputNoDataPolicy = fa::MarkNoDataByValue<bool>;
    using Argument = fern::MaskedScalar<ArgumentValue>;
    using Result = fern::MaskedScalar<ResultValue>;

    fa::SequentialExecutionPolicy sequential;

    Argument argument;
    Result result;

    // Input is not masked.
    {
        argument.value() = -5;
        argument.mask() = false;
        result.value() = 3;

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask(), false);
        BOOST_REQUIRE_EQUAL(result.value(), 5);
    }

    // Input is masked.
    {
        argument.value() = -5;
        argument.mask() = true;
        result.value() = 3;

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);
        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask(), true);
        BOOST_REQUIRE_EQUAL(result.value(), 3);
    }

    // Input is out of domain.
    {
        // TODO  Use sqrt, for example.
    }

    // Result goes out of range.
    {
        argument.value() = fern::min<ArgumentValue>();
        argument.mask() = false;
        result.value() = 3;

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);
        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            OutOfRangePolicy>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask(), true);

        // Result value is max<ArgumentValue> + 1, which equals
        // min<ArgumentValue>.
        BOOST_REQUIRE_EQUAL(result.value(), fern::min<ArgumentValue>());
    }
}

BOOST_AUTO_TEST_CASE(array_1d_sequential)
{
    using InputNoDataPolicy = fa::InputNoDataPolicies<fa::SkipNoData>;
    using OutputNoDataPolicy = fa::DontMarkNoData;

    fa::SequentialExecutionPolicy sequential;

    OutputNoDataPolicy output_no_data_policy;

    // vector
    {
        using Argument = std::vector<ArgumentValue>;
        using Result = std::vector<ResultValue>;

        Argument argument{-5, 0, 5};
        Result result{3, 3, 3};

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                InputNoDataPolicy{{}},
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result[0], 5);
        BOOST_REQUIRE_EQUAL(result[1], 0);
        BOOST_REQUIRE_EQUAL(result[2], 5);
    }

    // 1d array
    {
        using Argument = fern::Array<ArgumentValue, 1>;
        using Result = fern::Array<ResultValue, 1>;

        Argument argument{-5, 0, 5};
        Result result{3, 3, 3};

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                InputNoDataPolicy{{}},
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result[0], 5);
        BOOST_REQUIRE_EQUAL(result[1], 0);
        BOOST_REQUIRE_EQUAL(result[2], 5);
    }

    // empty
    {
        using Argument = std::vector<ArgumentValue>;
        using Result = std::vector<ResultValue>;

        Argument argument;
        Result result;

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                InputNoDataPolicy{{}},
                output_no_data_policy,
                sequential, argument, result);

        BOOST_CHECK(result.empty());
    }
}

BOOST_AUTO_TEST_CASE(array_1d_parallel)
{
    using InputNoDataPolicy = fa::InputNoDataPolicies<fa::SkipNoData>;
    using OutputNoDataPolicy = fa::DontMarkNoData;

    fa::ParallelExecutionPolicy parallel;

    OutputNoDataPolicy output_no_data_policy;

    // vector
    {
        using Argument = std::vector<ArgumentValue>;
        using Result = std::vector<ResultValue>;

        Argument argument{-5, 0, 5};
        Result result{3, 3, 3};

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                InputNoDataPolicy{{}},
                output_no_data_policy,
                parallel, argument, result);

        BOOST_REQUIRE_EQUAL(result[0], 5);
        BOOST_REQUIRE_EQUAL(result[1], 0);
        BOOST_REQUIRE_EQUAL(result[2], 5);
    }

    // 1d array
    {
        using Argument = fern::Array<ArgumentValue, 1>;
        using Result = fern::Array<ResultValue, 1>;

        Argument argument{-5, 0, 5};
        Result result{3, 3, 3};

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                InputNoDataPolicy{{}},
                output_no_data_policy,
                parallel, argument, result);

        BOOST_REQUIRE_EQUAL(result[0], 5);
        BOOST_REQUIRE_EQUAL(result[1], 0);
        BOOST_REQUIRE_EQUAL(result[2], 5);
    }

    // empty
    {
        using Argument = std::vector<ArgumentValue>;
        using Result = std::vector<ResultValue>;

        Argument argument;
        Result result;

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                InputNoDataPolicy{{}},
                output_no_data_policy,
                parallel, argument, result);

        BOOST_CHECK(result.empty());
    }
}

BOOST_AUTO_TEST_CASE(array_1d_masked)
{
    using Argument = fern::MaskedArray<ArgumentValue, 1>;
    using Result = fern::MaskedArray<ResultValue, 1>;
    using InputNoDataPolicy = fa::InputNoDataPolicies<
        fa::DetectNoDataByValue<fern::Mask<1>>>;
    using OutputNoDataPolicy = fa::MarkNoDataByValue<fern::Mask<1>>;

    fa::SequentialExecutionPolicy sequential;

    {
        Argument argument{-5, 0, 5};
        Result result(3);

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);

        result.fill(3);

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask()[0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[1], false);
        BOOST_REQUIRE_EQUAL(result.mask()[2], false);
        BOOST_REQUIRE_EQUAL(result[0], 5);
        BOOST_REQUIRE_EQUAL(result[1], 0);
        BOOST_REQUIRE_EQUAL(result[2], 5);

        result.fill(3);
        argument.mask()[1] = true;

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask()[0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[1], true);
        BOOST_REQUIRE_EQUAL(result.mask()[2], false);
        BOOST_REQUIRE_EQUAL(result[0], 5);
        BOOST_REQUIRE_EQUAL(result[1], 3);
        BOOST_REQUIRE_EQUAL(result[2], 5);
    }

    // empty
    {
        Argument argument;
        Result result;

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_CHECK_EQUAL(result.size(), 0u);
    }
}

BOOST_AUTO_TEST_CASE(array_2d_sequential)
{
    using InputNoDataPolicy = fa::InputNoDataPolicies<fa::SkipNoData>;
    using OutputNoDataPolicy = fa::DontMarkNoData;
    using Argument = fern::Array<ArgumentValue, 2>;
    using Result = fern::Array<ResultValue, 2>;

    fa::SequentialExecutionPolicy sequential;

    OutputNoDataPolicy output_no_data_policy;

    Argument argument{
        { -2, -1 },
        {  0,  9 },
        {  1,  2 }
    };
    Result result{
        { 3, 3 },
        { 3, 3 },
        { 3, 3 }
    };

    fa::unary_local_operation<
        Algorithm,
        fa::unary::DiscardDomainErrors,
        fa::unary::DiscardRangeErrors>(
            InputNoDataPolicy{{}},
            output_no_data_policy,
            sequential, argument, result);

    BOOST_CHECK_EQUAL(result[0][0], 2);
    BOOST_CHECK_EQUAL(result[0][1], 1);
    BOOST_CHECK_EQUAL(result[1][0], 0);
    BOOST_CHECK_EQUAL(result[1][1], 9);
    BOOST_CHECK_EQUAL(result[2][0], 1);
    BOOST_CHECK_EQUAL(result[2][1], 2);
}

BOOST_AUTO_TEST_CASE(array_2d_parallel)
{
    using InputNoDataPolicy = fa::InputNoDataPolicies<fa::SkipNoData>;
    using OutputNoDataPolicy = fa::DontMarkNoData;
    using Argument = fern::Array<ArgumentValue, 2>;
    using Result = fern::Array<ResultValue, 2>;

    fa::ParallelExecutionPolicy parallel;

    OutputNoDataPolicy output_no_data_policy;

    Argument argument{
        { -2, -1 },
        {  0,  9 },
        {  1,  2 }
    };
    Result result{
        { 3, 3 },
        { 3, 3 },
        { 3, 3 }
    };

    fa::unary_local_operation<
        Algorithm,
        fa::unary::DiscardDomainErrors,
        fa::unary::DiscardRangeErrors>(
            InputNoDataPolicy{{}},
            output_no_data_policy,
            parallel, argument, result);

    BOOST_CHECK_EQUAL(result[0][0], 2);
    BOOST_CHECK_EQUAL(result[0][1], 1);
    BOOST_CHECK_EQUAL(result[1][0], 0);
    BOOST_CHECK_EQUAL(result[1][1], 9);
    BOOST_CHECK_EQUAL(result[2][0], 1);
    BOOST_CHECK_EQUAL(result[2][1], 2);
}

BOOST_AUTO_TEST_CASE(array_2d_masked)
{
    using Argument = fern::MaskedArray<ArgumentValue, 2>;
    using Result = fern::MaskedArray<ResultValue, 2>;
    using InputNoDataPolicy = fa::InputNoDataPolicies<
        fa::DetectNoDataByValue<fern::Mask<2>>>;
    using OutputNoDataPolicy = fa::MarkNoDataByValue<fern::Mask<2>>;

    fa::SequentialExecutionPolicy sequential;

    {
        Argument argument{
            { -2, -1 },
            {  0,  9 },
            {  1,  2 }
        };
        Result result{
            { 3, 3 },
            { 3, 3 },
            { 3, 3 }
        };

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);

        result.fill(3);

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask()[0][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[0][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[1][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[1][1], false);
        BOOST_REQUIRE_EQUAL(result.mask()[2][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[2][1], false);
        BOOST_CHECK_EQUAL(result[0][0], 2);
        BOOST_CHECK_EQUAL(result[0][1], 1);
        BOOST_CHECK_EQUAL(result[1][0], 0);
        BOOST_CHECK_EQUAL(result[1][1], 9);
        BOOST_CHECK_EQUAL(result[2][0], 1);
        BOOST_CHECK_EQUAL(result[2][1], 2);

        result.fill(3);
        argument.mask()[1][1] = true;

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_REQUIRE_EQUAL(result.mask()[0][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[0][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[1][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[1][1], true);
        BOOST_REQUIRE_EQUAL(result.mask()[2][0], false);
        BOOST_REQUIRE_EQUAL(result.mask()[2][1], false);
        BOOST_CHECK_EQUAL(result[0][0], 2);
        BOOST_CHECK_EQUAL(result[0][1], 1);
        BOOST_CHECK_EQUAL(result[1][0], 0);
        BOOST_CHECK_EQUAL(result[1][1], 3);
        BOOST_CHECK_EQUAL(result[2][0], 1);
        BOOST_CHECK_EQUAL(result[2][1], 2);
    }

    // empty
    {
        Argument argument;
        Result result;

        InputNoDataPolicy input_no_data_policy{{argument.mask(), true}};
        OutputNoDataPolicy output_no_data_policy(result.mask(), true);

        fa::unary_local_operation<
            Algorithm,
            fa::unary::DiscardDomainErrors,
            fa::unary::DiscardRangeErrors>(
                input_no_data_policy,
                output_no_data_policy,
                sequential, argument, result);

        BOOST_CHECK_EQUAL(result.size(), 0u);
    }
}


#define BOOST_TEST_MODULE BackwardFlipperTest

#include "BackwardFlipper.hpp"
#include <vector>
#include <cstddef>

#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>

BOOST_AUTO_TEST_SUITE(BackwardFlipperSuite)

using namespace com::github::nimelo;
using namespace std;

BOOST_AUTO_TEST_CASE(TestScenario_1)
{
    // Arrange
    size_t n = 6, p = 2;
    size_t expected_distance = 2;

    BackwardFlipper flipper;

    // Act
    auto actual_distance = flipper.distance(n, p);

    // Assert
    BOOST_CHECK_EQUAL(expected_distance, actual_distance);
}

BOOST_AUTO_TEST_CASE(TestScenario_2)
{
    // Arrange
    size_t n = 5, p = 4;
    size_t expected_distance = 0;

    BackwardFlipper flipper;

    // Act
    auto actual_distance = flipper.distance(n, p);

    // Assert
    BOOST_CHECK_EQUAL(expected_distance, actual_distance);
}

BOOST_AUTO_TEST_SUITE_END()


#ifndef NETWORKS_HPP
#define NETWORKS_HPP

// For External Library
#include <torch/torch.h>
#include <boost/program_options.hpp>

// Define Namespace
namespace nn = torch::nn;
namespace po = boost::program_options;

// Function Prototype
void weights_init(nn::Module &m);
void DownSampling(nn::Sequential &sq, const size_t in_nc, const size_t out_nc, const bool BN, const bool ReLU, const bool bias=false);
void UpSampling(nn::Sequential &sq, const size_t in_nc, const size_t out_nc, const bool BN, const bool ReLU, const bool bias=false);

// -------------------------------------------------
// struct{ConvolutionalAutoEncoderImpl}(nn::Module)
// -------------------------------------------------
struct ConvolutionalAutoEncoderImpl : nn::Module{
private:
    nn::Sequential encoder, decoder;
public:
    ConvolutionalAutoEncoderImpl(){}
    ConvolutionalAutoEncoderImpl(po::variables_map &vm);
    torch::Tensor forward(torch::Tensor x);
};

TORCH_MODULE(ConvolutionalAutoEncoder);

#endif


//  Copyright John Maddock 2008.
//  Use, modification and distribution are 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)
//
#  include <pch.hpp>
#ifndef BOOST_MATH_TR1_SOURCE
#  define BOOST_MATH_TR1_SOURCE
#endif
#include <boost/math/tr1.hpp>
#include <boost/math/special_functions/bessel.hpp>
#include "c_policy.hpp"

extern "C" float BOOST_MATH_TR1_DECL cyl_bessel_if BOOST_PREVENT_MACRO_SUBSTITUTION(float nu, float x) BOOST_MATH_C99_THROW_SPEC
{
   return c_policies::cyl_bessel_i BOOST_PREVENT_MACRO_SUBSTITUTION(nu, x);
}