/*    Copyright (c) 2010-2016, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 */

#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>

#include <Tudat/Astrodynamics/Aerodynamics/UnitTests/testApolloCapsuleCoefficients.h>
#include <Tudat/Astrodynamics/BasicAstrodynamics/accelerationModel.h>
#include <Tudat/Basics/testMacros.h>
#include <Tudat/Astrodynamics/Propagators/dynamicsSimulator.h>
#include <Tudat/Astrodynamics/BasicAstrodynamics/unitConversions.h>
#include <Tudat/External/SpiceInterface/spiceInterface.h>
#include <Tudat/SimulationSetup/body.h>
#include <Tudat/SimulationSetup/createAccelerationModels.h>
#include <Tudat/SimulationSetup/defaultBodies.h>
#include <Tudat/InputOutput/basicInputOutput.h>

#include <iostream>
#include <limits>
#include <string>

#include <Eigen/Core>

namespace tudat
{

namespace unit_tests
{

BOOST_AUTO_TEST_SUITE( test_dependent_variable_output )

//! Propagate entry of Apollo capsule, and save a list of dependent variables during entry. The saved dependent variables
//! are compred against theoretical/manual values in this test.
BOOST_AUTO_TEST_CASE( testDependentVariableOutput )
{
    using namespace ephemerides;
    using namespace interpolators;
    using namespace numerical_integrators;
    using namespace spice_interface;
    using namespace simulation_setup;
    using namespace basic_astrodynamics;
    using namespace orbital_element_conversions;
    using namespace propagators;
    using namespace aerodynamics;
    using namespace basic_mathematics;
    using namespace input_output;

    // Load Spice kernels.
    spice_interface::loadSpiceKernelInTudat( input_output::getSpiceKernelPath( ) + "pck00009.tpc" );
    spice_interface::loadSpiceKernelInTudat( input_output::getSpiceKernelPath( ) + "de-403-masses.tpc" );
    spice_interface::loadSpiceKernelInTudat( input_output::getSpiceKernelPath( ) + "de421.bsp" );

    // Set simulation start epoch.
    const double simulationStartEpoch = 0.0;

    // Set simulation end epoch.
    const double simulationEndEpoch = 3300.0;

    // Set numerical integration fixed step size.
    const double fixedStepSize = 1.0;

    // Set Keplerian elements for Capsule.
    Vector6d apolloInitialStateInKeplerianElements;
    apolloInitialStateInKeplerianElements( semiMajorAxisIndex ) = spice_interface::getAverageRadius( "Earth" ) + 120.0E3;
    apolloInitialStateInKeplerianElements( eccentricityIndex ) = 0.005;
    apolloInitialStateInKeplerianElements( inclinationIndex ) = unit_conversions::convertDegreesToRadians( 85.3 );
    apolloInitialStateInKeplerianElements( argumentOfPeriapsisIndex )
            = unit_conversions::convertDegreesToRadians( 235.7 );
    apolloInitialStateInKeplerianElements( longitudeOfAscendingNodeIndex )
            = unit_conversions::convertDegreesToRadians( 23.4 );
    apolloInitialStateInKeplerianElements( trueAnomalyIndex ) = unit_conversions::convertDegreesToRadians( 139.87 );

    // Convert apollo state from Keplerian elements to Cartesian elements.
    const Vector6d apolloInitialState = convertKeplerianToCartesianElements(
                apolloInitialStateInKeplerianElements,
                getBodyGravitationalParameter( "Earth" ) );

    // Define simulation body settings.
    std::map< std::string, boost::shared_ptr< BodySettings > > bodySettings =
            getDefaultBodySettings( { "Earth", "Moon" }, simulationStartEpoch - 10.0 * fixedStepSize,
                                    simulationEndEpoch + 10.0 * fixedStepSize );
    bodySettings[ "Earth" ]->gravityFieldSettings =
            boost::make_shared< simulation_setup::GravityFieldSettings >( central_spice );

    // Create Earth object
    simulation_setup::NamedBodyMap bodyMap = simulation_setup::createBodies( bodySettings );

    // Create vehicle objects.
    bodyMap[ "Apollo" ] = boost::make_shared< simulation_setup::Body >( );

    // Create vehicle aerodynamic coefficients
    bodyMap[ "Apollo" ]->setAerodynamicCoefficientInterface(
                unit_tests::getApolloCoefficientInterface( ) );
    bodyMap[ "Apollo" ]->setConstantBodyMass( 5.0E3 );
    bodyMap[ "Apollo" ]->setEphemeris(
                boost::make_shared< ephemerides::TabulatedCartesianEphemeris< > >(
                    boost::shared_ptr< interpolators::OneDimensionalInterpolator< double, basic_mathematics::Vector6d  > >( ),
                    "Earth" ) );

    // Finalize body creation.
    setGlobalFrameBodyEphemerides( bodyMap, "SSB", "ECLIPJ2000" );

    // Define propagator settings variables.
    SelectedAccelerationMap accelerationMap;
    std::vector< std::string > bodiesToPropagate;
    std::vector< std::string > centralBodies;

    // Define acceleration model settings.
    std::map< std::string, std::vector< boost::shared_ptr< AccelerationSettings > > > accelerationsOfApollo;
    accelerationsOfApollo[ "Earth" ].push_back( boost::make_shared< AccelerationSettings >( central_gravity ) );
    accelerationsOfApollo[ "Earth" ].push_back( boost::make_shared< AccelerationSettings >( aerodynamic ) );
    accelerationsOfApollo[ "Moon" ].push_back( boost::make_shared< AccelerationSettings >( central_gravity ) );
    accelerationMap[  "Apollo" ] = accelerationsOfApollo;

    bodiesToPropagate.push_back( "Apollo" );
    centralBodies.push_back( "Earth" );

    // Set initial state
    basic_mathematics::Vector6d systemInitialState = apolloInitialState;

    // Define list of dependent variables to save.
    std::vector< boost::shared_ptr< SingleDependentVariableSaveSettings > > dependentVariables;
    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >( mach_number_dependent_variable, "Apollo" ) );
    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >( altitude_dependent_variable,
                                                                           "Apollo", "Earth" ) );
    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >( relative_distance_dependent_variable,
                                                                           "Apollo", "Earth" ) );
    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >( relative_speed_dependent_variable,
                                                                           "Apollo", "Earth" ) );
    dependentVariables.push_back(
                boost::make_shared< SingleAccelerationDependentVariableSaveSettings >(
                    central_gravity, "Apollo", "Earth", 1 ) );

    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >( relative_position_dependent_variable,
                                                                           "Apollo", "Earth" ) );
    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >( relative_velocity_dependent_variable,
                                                                           "Apollo", "Earth" ) );
    dependentVariables.push_back(
                boost::make_shared< SingleAccelerationDependentVariableSaveSettings >(
                    central_gravity, "Apollo", "Earth", 0 ) );
    dependentVariables.push_back(
                boost::make_shared< SingleDependentVariableSaveSettings >(
                    total_acceleration_dependent_variable, "Apollo" ) );

    // Create acceleration models and propagation settings.
    basic_astrodynamics::AccelerationMap accelerationModelMap = createAccelerationModelsMap(
                bodyMap, accelerationMap, bodiesToPropagate, centralBodies );
    boost::shared_ptr< TranslationalStatePropagatorSettings< double > > propagatorSettings =
            boost::make_shared< TranslationalStatePropagatorSettings< double > >
            ( centralBodies, accelerationModelMap, bodiesToPropagate, systemInitialState,
              boost::make_shared< propagators::PropagationTimeTerminationSettings >( 3200.0 ), cowell,
              boost::make_shared< DependentVariableSaveSettings >( dependentVariables ) );
    boost::shared_ptr< IntegratorSettings< > > integratorSettings =
            boost::make_shared< IntegratorSettings< > >
            ( rungeKutta4, simulationStartEpoch, fixedStepSize );

    // Create simulation object and propagate dynamics.
    SingleArcDynamicsSimulator< > dynamicsSimulator(
                bodyMap, integratorSettings, propagatorSettings, true, false, false );

    // Retrieve numerical solutions for state and dependent variables
    std::map< double, Eigen::Matrix< double, Eigen::Dynamic, 1 > > numericalSolution =
            dynamicsSimulator.getEquationsOfMotionNumericalSolution( );
    std::map< double, Eigen::VectorXd > dependentVariableSoution =
            dynamicsSimulator.getDependentVariableHistory( );

    // Iterate over results for dependent variables, and check against manually retrieved values.
    basic_mathematics::Vector6d currentStateDerivative;
    Eigen::Vector3d manualCentralGravity;
    for( std::map< double, Eigen::VectorXd >::iterator variableIterator = dependentVariableSoution.begin( );
         variableIterator != dependentVariableSoution.end( ); variableIterator++ )
    {
        currentStateDerivative = dynamicsSimulator.getDynamicsStateDerivative( )->computeStateDerivative(
                    variableIterator->first, numericalSolution.at( variableIterator->first ) );

        // Manually compute central gravity.
        manualCentralGravity =
                -bodyMap.at( "Earth" )->getGravityFieldModel( )->getGravitationalParameter( ) *
                variableIterator->second.segment( 5, 3 ) /
                std::pow( variableIterator->second.segment( 5, 3 ).norm( ), 3 );

        // Check output time consistency
        BOOST_CHECK_EQUAL( numericalSolution.count( variableIterator->first ), 1 );

        // Check relative position and velocity against state
        for( unsigned int i = 0; i < 3; i++ )
        {
            BOOST_CHECK_SMALL(
                        std::fabs( numericalSolution.at( variableIterator->first )( i ) -
                                   variableIterator->second( 5 + i ) ), 2.0E-5 );
            BOOST_CHECK_SMALL(
                        std::fabs( numericalSolution.at( variableIterator->first )( 3 + i ) -
                                   variableIterator->second( 8 + i ) ), 5.0E-11 );
        }

        // Check central gravity acceleration
        TUDAT_CHECK_MATRIX_CLOSE_FRACTION(
                    manualCentralGravity.segment( 0, 3 ),
                    variableIterator->second.segment( 11, 3 ), ( 5.0 * std::numeric_limits< double >::epsilon( ) ) );

        // Check total acceleration
        TUDAT_CHECK_MATRIX_CLOSE_FRACTION(
                    ( currentStateDerivative.segment( 3, 3 ) ),
                    (  variableIterator->second.segment( 14, 3 ) ), std::numeric_limits< double >::epsilon( ) );

        // Check relative position and velocity norm.
        BOOST_CHECK_SMALL(
                    std::fabs( ( numericalSolution.at( variableIterator->first ).segment( 0, 3 ) ).norm( ) -
                               variableIterator->second( 2 ) ), 2.0E-5 );
        BOOST_CHECK_SMALL(
                    std::fabs( ( numericalSolution.at( variableIterator->first ).segment( 3, 3 ) ).norm( ) -
                               variableIterator->second( 3 ) ), 2.0E-11 );

        // Check central gravity acceleration norm
        BOOST_CHECK_CLOSE_FRACTION(
                    manualCentralGravity.norm( ),
                    variableIterator->second( 4 ), 5.0 * std::numeric_limits< double >::epsilon( ) );

        // Check Mach number
        BOOST_CHECK_CLOSE_FRACTION(
                    bodyMap.at( "Apollo" )->getFlightConditions( )->getCurrentAirspeed( ) /
                    bodyMap.at( "Apollo" )->getFlightConditions( )->getCurrentSpeedOfSound( ),
                    variableIterator->second( 0 ), std::numeric_limits< double >::epsilon( ) );

        // Check altitude.
        BOOST_CHECK_CLOSE_FRACTION(
                    bodyMap.at( "Apollo" )->getFlightConditions( )->getCurrentAltitude( ),
                    variableIterator->second( 1 ), std::numeric_limits< double >::epsilon( ) );

    }

}

BOOST_AUTO_TEST_SUITE_END( )

}

}


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

#include "../include/string.hpp"

#include <boost/mpl/char.hpp>
#include <boost/mpl/int.hpp>

BOOST_AUTO_TEST_CASE(from_cstr)
{
    constexpr auto s0 = make_string("hello");
    BOOST_CHECK_EQUAL(s0.c_str(), "hello");

    using c = boost::mpl::char_<s0.c_str()[2]>;
    using s = boost::mpl::int_<s0.size()>;

    BOOST_CHECK_EQUAL(c::value, 'l');
    BOOST_CHECK_EQUAL(s::value, 5);
}

BOOST_AUTO_TEST_CASE(pushes)
{
    constexpr auto s0 = make_string("ell");
    constexpr auto s1 = s0.push_back('o');

    BOOST_CHECK_EQUAL(s1.c_str(), "ello");

    constexpr auto s2 = s1.push_front('h');

    BOOST_CHECK_EQUAL(s2.c_str(), "hello");

    using c = boost::mpl::char_<s2.c_str()[1]>;
    using s = boost::mpl::int_<s2.size()>;
}

BOOST_AUTO_TEST_CASE(appending)
{
    constexpr auto s0 = make_string("hello ");
    constexpr auto s1 = s0.append("world");
    constexpr auto s2 = make_string("hello world");
    constexpr auto s3 = s0.append(make_string("world"));

    BOOST_CHECK_EQUAL(s1.size(), s2.size());
    BOOST_CHECK_EQUAL(s1.c_str(), s2.c_str());

    using c = boost::mpl::char_<s1.c_str()[6]>;
    using s = boost::mpl::int_<s1.size()>;

    BOOST_CHECK_EQUAL(c::value, 'w');
    BOOST_CHECK_EQUAL(s::value, s1.size());

    BOOST_CHECK_EQUAL(s1.c_str(), s3.c_str());
}

BOOST_AUTO_TEST_CASE(operators)
{
    constexpr auto s0 = '[' + make_string("hello") + ' ' + make_string("world") + ']';

    BOOST_CHECK_EQUAL(s0.c_str(), "[hello world]");
}


#ifndef MANIFOLDS_FUNCTIONS_FULL_DEFS_HH
#define MANIFOLDS_FUNCTIONS_FULL_DEFS_HH

#include "function.hh"
#include "composition.hh"
#include "is_function.hh"
#include <utility>
#include <type_traits>
#include <boost/preprocessor/cat.hpp>
#include "group.hh"

namespace manifolds {

template <class FunctionImpl> struct FunctionCommon {
  template <class InnerFunc>
  using prepare = typename std::remove_reference<typename std::remove_cv<
      typename std::remove_reference<InnerFunc>::type>::type>::type;

  template <class InnerFunc>
  auto eval_dispatch(std::true_type, InnerFunc f) const {
    return Composition<FunctionImpl, InnerFunc>{
      *static_cast<const FunctionImpl *>(this), f
    };
  }
  template <class Var> auto eval_dispatch(std::false_type, Var x) const {
    return static_cast<const FunctionImpl *>(this)->eval(x);
  }
  template <class T> auto operator()(T t) const {
    return eval_dispatch(is_function<T>(), t);
  }
  template <class... InnerFuncs,
            class = typename std::enable_if<(sizeof...(InnerFuncs) > 1)>::type>
  auto eval_dispatch(std::true_type, InnerFuncs... fs) const {
    auto g = GetGroup(fs...);
    return Composition<FunctionImpl, decltype(g)>(
        *static_cast<const FunctionImpl *>(this), g);
  }
  template <class... Vars,
            class = typename std::enable_if<(sizeof...(Vars) > 1)>::type>
  auto eval_dispatch(std::false_type, Vars... xs) const {
    return static_cast<const FunctionImpl *>(this)->eval(xs...);
  }
  template <class... InnerFunc,
            class = typename std::enable_if<(sizeof...(InnerFunc) > 1)>::type>
  auto operator()(InnerFunc... f) const {
    return eval_dispatch(and_<is_function<InnerFunc>...>(), f...);
  }

  template <class T, std::size_t... Indices>
  auto helper(const T &t,
              std::integer_sequence<std::size_t, Indices...>) const {
    return (*static_cast<const FunctionImpl *>(this))(std::get<Indices>(t)...);
  }
  template <class... Args> auto operator()(tuple<Args...> t) const {
    return helper(t, std::index_sequence_for<Args...>());
  }
};
}

#endif


/*******************************************************************************
 * reservoir/reservoir.hpp
 *
 * Distributed Reservoir Sampling
 *
 * Copyright (C) 2019 Lorenz Hübschle-Schneider <lorenz@4z2.de>
 *
 * All rights reserved. Published under the GNU General Public License 3
 ******************************************************************************/

#pragma once

#ifndef RESERVOIR_RESERVOIR_HEADER
#define RESERVOIR_RESERVOIR_HEADER

#include <reservoir/aggregate.hpp>
#include <reservoir/btree_multimap.hpp>
#include <reservoir/logger.hpp>
#include <reservoir/select_helpers.hpp>
#include <reservoir/stats.hpp>
#include <reservoir/timer.hpp>
#include <reservoir/util.hpp>

#include <tlx/define.hpp>
#include <tlx/die/core.hpp>

#include <boost/mpi.hpp>

#include <algorithm>
#include <utility>

namespace mpi = boost::mpi;

namespace reservoir {

template <typename Key, template <typename> typename select_t, typename RNG>
class reservoir {
public:
    static constexpr const char *short_name = "[res]";

    using key_type = Key;
    using reservoir_type = btree_multimap<double, key_type>;
    using select_type = select_t<reservoir_type>;

    static constexpr bool check = false;
    static constexpr bool debug = false;
    static constexpr bool time = true;

    reservoir(mpi::communicator &comm, size_t size, size_t seed)
        : select_(comm, seed + static_cast<size_t>(comm.size() + comm.rank())),
          rng_(seed + static_cast<size_t>(comm.rank())), comm_(comm),
          size_(size), threshold_(0.0), batch_id_(0) {
        LOGRC(check) << "Checking is active, things might be slow!";
    }

    // Iterator should dereference to (weight, id) pairs
    template <typename Iterator>
    void insert(Iterator begin, Iterator end) {
        timer t, t_total;

        pLOG << "batch " << batch_id_ << " beginning";

        // Step 1: process new items locally
        Iterator it = begin;
        size_t count = 0;
        if (threshold_ == 0.0) {
            size_t size_thresh = std::max(3 * size_ / 2, size_ + 500);
            while (it != end && reservoir_.size() < size_thresh) {
                // generate exponentially distributed variables
                double key = rng_.next_exponential(it->first);
                spLOG0 << "item" << *it << "key" << key;
                reservoir_.insert2(key, it->second);
                ++count;
                // catch a compiler bug in the subtree size compilation
                tlx_die_verbose_unless(reservoir_.size() == count,
                                       "WAAAH tree barfed for key "
                                           << key << "size=" << reservoir_.size()
                                           << "count=" << count);
                ++it;
            }
            spLOG0 << "first batch took" << t.get() << "ms";

            // Once we've processed the initial 1.5*size_ elements locally, do
            // some local thresholding whenever the size exceeds 1.1*size_
            size_thresh = std::max(11 * size_ / 10, size_ + 250);
            double local_threshold = 0;

            while (it != end) {
                // Every time the size increases by an integer multiple,
                // determine a new local threshold
                if (reservoir_.size() >= size_thresh) {
                    auto thresh_it = reservoir_.find_rank(size_);
                    local_threshold = thresh_it->first;
                    spLOG0 << "local threshold" << local_threshold
                          << "for reservoir size" << reservoir_.size()
                          << "splitter" << *thresh_it << "after seeing"
                          << it - begin << "elements";

                    // splitting is fast
                    reservoir_type keep, discard;
                    reservoir_.splitAt(keep, size_, thresh_it, discard);
                    reservoir_ = std::move(keep);
                }
                tlx_die_unless(local_threshold > 0);

                it = insert_skip<false>(it, end, local_threshold);
            }
            spLOG0 << "first round of insertions took" << t.get() << "ms";
        } else {
            while (it != end) {
                it = insert_skip<true>(it, end, threshold_);
            }
        }
        pLOG0 << "done processing items";
        if constexpr (time) {
            stats_.record("size", reservoir_.size());
            double t_insert = t.get();
            stats_.record("insert", t_insert);
            LOG0 << "RESULT op=insert pe=" << comm_.rank()
                 << " np=" << comm_.size() << " batchsize=" << end - begin
                 << " batch=" << batch_id_ << " samplesize=" << size_
                 << " time=" << t_insert;
            t.reset();
        }

        pLOG << "batch " << batch_id_ << " finding splitter...";

        // Step 2: find splitter
        auto [split_it, num_keep] = select_(reservoir_, size_);
        if constexpr (time) {
            double t_select = t.get();
            stats_.record("select", t_select);
            LOG0 << "RESULT op=select pe=" << comm_.rank()
                 << " np=" << comm_.size() << " batchsize=" << end - begin
                 << " batch=" << batch_id_ << " samplesize=" << size_
                 << " time=" << t_select;
            t.reset();
        }

        pLOG << "batch " << batch_id_ << " splitting...";

        // Step 3: split
        reservoir_type keep, discard;
        reservoir_.splitAt(keep, static_cast<size_t>(num_keep), split_it, discard);
        reservoir_ = std::move(keep);
        if constexpr (time) {
            double t_split = t.get();
            stats_.record("split", t_split);
            LOG0 << "RESULT op=split pe=" << comm_.rank()
                 << " np=" << comm_.size() << " batchsize=" << end - begin
                 << " batch=" << batch_id_ << " samplesize=" << size_
                 << " time=" << t_split;
            t.reset();
        }

        pLOG << "batch " << batch_id_ << " finding new threshold";

        // Step 4: determine value of new threshold
        double max_local =
            reservoir_.empty() ? 0.0 : std::prev(reservoir_.end())->first;
        threshold_ = mpi::all_reduce(comm_, max_local, mpi::maximum<double>());
        LOGR << "new threshold is " << threshold_;

        if constexpr (check) {
            reservoir_.verify();
            discard.verify();
            tlx_die_unless(static_cast<ssize_t>(reservoir_.size()) == num_keep);
        }

        if constexpr (time) {
            double t_threshold = t.get();
            stats_.record("threshold", t_threshold);
            LOG0 << "RESULT op=threshold pe=" << comm_.rank()
                 << " np=" << comm_.size() << " batchsize=" << end - begin
                 << " batch=" << batch_id_ << " samplesize=" << size_
                 << " time=" << t_threshold;
            t.reset();

            stats_.record("total", t_total.get());
        }

        pLOG << "batch " << batch_id_ << " done";

        ++batch_id_;
    }

    template <typename Callback>
    void sample(Callback &&callback) const {
        for (auto it = reservoir_.begin(); it != reservoir_.end(); ++it) {
            callback(*it);
        }
    }

    _detail::res_stats<time> &get_stats() {
        return stats_;
    }

    auto get_mss_stats() {
        return select_.get_stats();
    }

protected:
    template <size_t w, typename Iterator>
    constexpr double vec_sum(Iterator it) {
        if constexpr (w == 1) {
            return it->first;
        } else if constexpr (w == 3) {
            return it->first + (it + 1)->first + (it + 2)->first;
        } else {
            return vec_sum<w / 2>(it) + vec_sum<w / 2>(it + w / 2);
        }
    }

    template <bool far, typename Iterator>
    TLX_ATTRIBUTE_ALWAYS_INLINE Iterator insert_skip(Iterator it, Iterator end,
                                                     double threshold) {
        double skip = rng_.next_exponential(threshold);
        pLOG0 << "skip = " << skip;

        if constexpr (far) {
            // number of elements to skip at a time
            constexpr size_t w = 32;

            double sum = 0.0;
            // Check that the next w items (including this) appear before `end`
            Iterator curr_last = it + (w - 1);
            Iterator prev;
            while (curr_last < end && skip >= 0) {
                sum = vec_sum<w>(it);

                if constexpr (check) {
                    double s2 = 0.0;
                    for (size_t i = 0; i < w; i++) {
                        s2 += (it + i)->first;
                    }
                    tlx_die_unless(std::abs(s2 - sum) < 1e-10);
                }

                skip -= sum;
                prev = it;
                // Avoid advancing iterator twice, it might not be a random
                // access iterator
                it = curr_last + 1;
                curr_last += w;
            }
            if (skip < 0) {
                // undo jump
                it = prev;
                skip += sum;
            } else if (it >= end) {
                return end;
            }
        }

        while (++it != end && skip >= 0) {
            skip -= it->first;
        }
        if (it == end)
            return it;

        double minv = std::exp(-threshold * it->first);
        double r = rng_.next(minv, 1.0);
        double key = -std::log(r) / it->first;
        my_assert(key > 0);
        spLOG0 << "item" << *it << "minv" << minv << "r" << r << "key" << key;
        reservoir_.insert2(key, it->second);
        return it;
    }

    reservoir_type reservoir_;
    select_type select_;
    RNG rng_;
    mpi::communicator &comm_;
    size_t size_;
    double threshold_;

    size_t batch_id_;
    mutable _detail::res_stats<time> stats_;
};

} // namespace reservoir

#endif // RESERVOIR_RESERVOIR_HEADER


#include "../swarm.hpp"
#include <Eigen/Core>
#include <pybind11/eigen.h>
#include <pybind11/functional.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace Optima {
namespace Python {

namespace py = pybind11;

void init_swarm(py::module &m) {

  auto constructor = py::init<const ParameterSpace &, const Parameters &,
                              size_t>();
  py::class_<Swarm>(m, "Swarm")
      .def(constructor, py::arg("parameter_space"), py::arg("hyper_params"),
           py::arg("num_particles") = 10)
      .def("optimize", &Swarm::optimize)
      .def("getBestSolution", &Swarm::getBestSolution)
      .def("getBestParameters", &Swarm::getBestParameters)
      .def("getCosts", &Swarm::getCosts);
}
}
}


/* Copyright Institute of Sound and Vibration Research - All rights reserved */

#ifndef VISR_RBBL_BIQUAD_COEFFICIENT_HPP_INCLUDED
#define VISR_RBBL_BIQUAD_COEFFICIENT_HPP_INCLUDED

#include <boost/property_tree/ptree_fwd.hpp>

#include "export_symbols.hpp"

#include <algorithm>
#include <array>
#include <initializer_list>
#include <iosfwd>
#include <stdexcept>
#include <vector>

namespace visr
{
namespace rbbl
{

/**
 * A FIFO-type message queue template class for storing and passing message data.
 * @tparam CoeffType Type of the contained elements.
 * @note This class does provide the same level of thread safety as, e.g., the STL.
 * I.e., calling code from different thread must ensure that concurrent accesses
 * to the same instances are appropriately secured against race conditions.
 */
template< typename CoeffType >
class VISR_RBBL_LIBRARY_SYMBOL BiquadCoefficient
{
public:
  /**
   * The number of coefficients to describe one biquad section.
   */
  static const std::size_t cNumberOfCoeffs = 5;

  /**
   * Create an default object corresponding to a flat EQ.
   */
  BiquadCoefficient()
  {
    mCoeffs.fill( static_cast<CoeffType>(0.0) );
    mCoeffs[0] = static_cast<CoeffType>(1.0);
  }

  BiquadCoefficient( BiquadCoefficient<CoeffType> const & rhs ) = default;

  /**
   * Create a BiquadCoefficient objects from JSON and XML representations.
   */
  //@{
  static BiquadCoefficient fromJson( boost::property_tree::ptree const & tree );

  static BiquadCoefficient fromJson( std::basic_istream<char> & stream );

  static BiquadCoefficient fromXml( boost::property_tree::ptree const & tree );

  static BiquadCoefficient fromXml( std::basic_istream<char> & stream );
  //@}

  BiquadCoefficient( CoeffType b0, CoeffType b1, CoeffType b2,
                   CoeffType a1, CoeffType a2 )
  {
    mCoeffs[0] = b0;
    mCoeffs[1] = b1;
    mCoeffs[2] = b2;
    mCoeffs[3] = a1;
    mCoeffs[4] = a2;
  }

  BiquadCoefficient( std::initializer_list< CoeffType > const & coeffs )
  {
    if( coeffs.size() != mCoeffs.size() )
    {
      throw std::invalid_argument( "BiquadCoefficient: Initialisation vector has wrong number of elements." );
    }
    std::copy( coeffs.begin(), coeffs.end(), mCoeffs.begin() );
  }

  // BiquadCoefficient( const BiquadCoefficient & rhs ) = default;

  BiquadCoefficient & operator=( BiquadCoefficient const & rhs )
  {
    mCoeffs = rhs.mCoeffs;
    return *this;
  }

  CoeffType const * data() const { return &mCoeffs[0]; }

  CoeffType * data() { return &mCoeffs[0]; }

  CoeffType const & operator[]( std::size_t idx ) const
  {
    return mCoeffs[ idx ];
  }

  CoeffType & operator[]( std::size_t idx )
  {
    return mCoeffs[ idx ];
  }

  CoeffType const & at( std::size_t idx ) const
  {
    return mCoeffs.at( idx );
  }

  CoeffType & at( std::size_t idx )
  {
    return mCoeffs.at( idx );
  }

  CoeffType const & b0() const { return mCoeffs[0]; }

  CoeffType const & b1() const { return mCoeffs[1]; }

  CoeffType const & b2() const { return mCoeffs[2]; }

  CoeffType const & a1() const { return mCoeffs[3]; }

  CoeffType const & a2() const { return mCoeffs[4]; }

  CoeffType& b0() { return mCoeffs[0]; }

  CoeffType& b1() { return mCoeffs[1]; }

  CoeffType& b2() { return mCoeffs[2]; }

  CoeffType& a1() { return mCoeffs[3]; }

  CoeffType& a2() { return mCoeffs[4]; }

  void loadJson( boost::property_tree::ptree const & tree );

  void loadJson( std::basic_istream<char> & );

  void loadXml( boost::property_tree::ptree const & tree );

  void loadXml( std::basic_istream<char> & );

  /**
   *
   */
  //@{
  void writeJson( boost::property_tree::ptree & tree ) const;

  void writeJson( std::basic_ostream<char> & stream ) const;

  void writeJson( std::string & str ) const;

  void writeXml( boost::property_tree::ptree & tree ) const;

  void writeXml ( std::basic_ostream<char> & stream ) const;

  void writeXml ( std::string & str ) const;

  //@}
private:
  /**
   * The internal data representation.
   */
  std::array<CoeffType,5> mCoeffs;
};

template< class CoeffType >
class VISR_RBBL_LIBRARY_SYMBOL BiquadCoefficientList
{
public:
  using Container = typename std::vector< BiquadCoefficient< CoeffType > >;
  using iterator = typename Container::iterator;
  using const_iterator = typename Container::const_iterator;

  /**
   * Default constructor, creates an empty list of biquad parameters.
   */
  BiquadCoefficientList() = default;

  explicit BiquadCoefficientList( const std::size_t initialSize )
    : mBiquads( initialSize )
  {
  }

  /**
   * Default copy constructor (required for use within aSTL data structure as, for instance, in BiquadCoefficientList.
   */
  BiquadCoefficientList( BiquadCoefficientList const & rhs ) = default;

  BiquadCoefficientList( std::initializer_list<BiquadCoefficient<CoeffType> > const & initList )
    : mBiquads( initList )
  {
  }

  static BiquadCoefficientList fromJson( boost::property_tree::ptree const & tree );

  static BiquadCoefficientList fromJson( std::basic_istream<char> & stream );

  static BiquadCoefficientList fromJson( std::string const & str );

  static BiquadCoefficientList fromXml( boost::property_tree::ptree const & tree );

  static BiquadCoefficientList fromXml( std::basic_istream<char> & stream );

  static BiquadCoefficientList fromXml( std::string const & str );

  /**
   * Assign the content from another BiquadCoefficientList with consistent size.
   * @throw std::invalid_argument If \p rhs has a different size.
   */
  BiquadCoefficientList & operator=(BiquadCoefficientList const & rhs)
  {
    if( rhs.size() != size() )
    {
      std::invalid_argument( "BiquadCoefficientList: Size of argument to be assigned does not match." );
    }
    mBiquads = rhs.mBiquads;
    return *this;
  }

  std::size_t size() const { return mBiquads.size(); }

  void resize( std::size_t newSize )
  {
    mBiquads.resize( newSize, BiquadCoefficient<CoeffType>() );
  }

  BiquadCoefficient<CoeffType> const & operator[]( std::size_t idx ) const { return mBiquads[idx]; }
  BiquadCoefficient<CoeffType> & operator[]( std::size_t idx ) { return mBiquads[idx]; }

  BiquadCoefficient<CoeffType> const & at( std::size_t idx ) const { return mBiquads.at( idx ); }
  BiquadCoefficient<CoeffType> & at( std::size_t idx ) { return mBiquads.at( idx ); }

  iterator begin() { return mBiquads.begin(); }
  iterator end() { return mBiquads.end(); }

  const_iterator begin() const { return mBiquads.begin(); }
  const_iterator end() const { return mBiquads.end(); }

  /**
   * DE-serialization from text formats.
   */
  //@{
  /**
   * Initialise from a JSON representation, provided as a Boost property tree ptree object.
   */
  void loadJson( boost::property_tree::ptree const & tree );

  /**
  * Initialise from a JSON representation, provided as an input stream containing JSON text data.
  */
  void loadJson( std::basic_istream<char> & stream );

  /**
  * Initialise from a JSON representation, provided as a string containing JSON text data.
  */
  void loadJson( std::string const & str );

  /**
   * Initialise from an XML representation, provided as a Boost property tree ptree object.
   */
  void loadXml( boost::property_tree::ptree const & tree );

  /**
   * Initialise from an XML representation, provided as an input stream containing JSON text data.
   */
  void loadXml( std::basic_istream<char> & stream );

  /**
   * Initialise from an XML representation, provided as a string containing JSON text data.
   */
  void loadXml( std::string const & str );
  //@}

  /**
   * Serialisation into textual formats.
   */
  //@{
  /**
   * Write to a boost property tree object (ptree) that can be serialised to an XML document (or part thereof)
   * @note the ptree representations for XML and JSON differ slightly, so different implementations are needed.
   */
  void writeJson( boost::property_tree::ptree & tree ) const;

  /**
   * Write an XML representation to an output stream.
   */
  void writeJson( std::basic_ostream<char> & stream ) const;

  /**
   * Write an XML representation into a string.
   */
  void writeJson( std::string & str ) const;

  /**
  * Write to a boost property tree object (ptree) that can be serialised to an XML document (or part thereof)
  * @note the ptree representations for XML and JSON differ slightly, so different implementations are needed.
  */
  void writeXml( boost::property_tree::ptree & tree ) const;

  /**
  * Write an XML representation to an output stream.
  */
  void writeXml( std::basic_ostream<char> & stream ) const;

  /**
  * Write an XML representation into a string.
  */
  void writeXml( std::string & str ) const;
  //@}

private:
  Container mBiquads;
};

template<typename CoeffType >
class VISR_RBBL_LIBRARY_SYMBOL BiquadCoefficientMatrix
{
public:
  explicit BiquadCoefficientMatrix( std::size_t numberOfFilters, std::size_t numberOfBiquads );

  ~BiquadCoefficientMatrix();

  static BiquadCoefficientMatrix fromJson( boost::property_tree::ptree const & tree );

  static BiquadCoefficientMatrix fromJson( std::basic_istream<char> & stream );

  static BiquadCoefficientMatrix fromJson( std::string const & str );

  static BiquadCoefficientMatrix fromXml( boost::property_tree::ptree const & tree );

  static BiquadCoefficientMatrix fromXml( std::basic_istream<char> & stream );

  static BiquadCoefficientMatrix fromXml( std::string const & str );

  std::size_t numberOfFilters() const { return mRows.size(); }
  std::size_t numberOfSections() const { return mRows.empty() ? 0 : mRows[0].size(); }

  void resize( std::size_t numberOfFilters, std::size_t numberOfBiquads );
  BiquadCoefficientList<CoeffType> const & operator[]( std::size_t rowIdx ) const { return mRows[rowIdx]; }
  BiquadCoefficientList<CoeffType> & operator[]( std::size_t rowIdx ) { return mRows[rowIdx]; }

  BiquadCoefficient<CoeffType> const & operator()( std::size_t rowIdx, std::size_t colIdx ) const { return mRows[rowIdx][colIdx]; }
  BiquadCoefficient<CoeffType> & operator()( std::size_t rowIdx, std::size_t colIdx ) { return mRows[rowIdx][colIdx]; }

  /**
   * Set the biquad sections for a complete filter specification (a row in the matrix)
   * If \p newFilter has fewer sections than the matrix, the rest is filled with default values.
   * @throw std::out_of_range If \p filterIdx exceeds the number of biquad sections.
   * @throw std::invalid_argument If \p nnewFilters has more elements than the column number of the matrix.
   */
  void setFilter( std::size_t filterIdx, BiquadCoefficientList<CoeffType> const & newFilter );

  /**
  * Deserialisation from text formats.
  */
  //@{
  /**
  * Initialise from a JSON representation, provided as a Boost property tree ptree object.
  */
  void loadJson( boost::property_tree::ptree const & tree );

  /**
  * Initialise from a JSON representation, provided as an input stream containing JSON text data.
  */
  void loadJson( std::basic_istream<char> & stream );

  /**
  * Initialise from a JSON representation, provided as a string containing JSON text data.
  */
  void loadJson( std::string const & str );

  /**
  * Initialise from an XML representation, provided as a Boost property tree ptree object.
  */
  void loadXml( boost::property_tree::ptree const & tree );

  /**
  * Initialise from an XML representation, provided as an input stream containing JSON text data.
  */
  void loadXml( std::basic_istream<char> & stream );

  /**
  * Initialise from an XML representation, provided as a string containing JSON text data.
  */
  void loadXml( std::string const & str );
  //@}

  /**
  * Serialisation into textual formats.
  */
  //@{
  /**
  * Write to a boost property tree object (ptree) that can be serialised to an XML document (or part thereof)
  * @note the ptree representations for XML and JSON differ slightly, so different implementations are needed.
  */
  void writeJson( boost::property_tree::ptree & tree ) const;

  /**
  * Write an XML representation to an output stream.
  */
  void writeJson( std::basic_ostream<char> & stream ) const;

  /**
  * Write an XML representation into a string.
  */
  void writeJson( std::string & str ) const;

  /**
  * Write to a boost property tree object (ptree) that can be serialised to an XML document (or part thereof)
  * @note the ptree representations for XML and JSON differ slightly, so different implementations are needed.
  */
  void writeXml( boost::property_tree::ptree & tree ) const;

  /**
  * Write an XML representation to an output stream.
  */
  void writeXml( std::basic_ostream<char> & stream ) const;

  /**
  * Write an XML representation into a string.
  */
  void writeXml( std::string & str ) const;
  //@}

private:
  using ContainerType = std::vector< BiquadCoefficientList<CoeffType> >;

  ContainerType mRows;
};

} // namespace rbbl
} // namespace visr

#endif // VISR_RBBL_BIQUAD_COEFFICIENT_HPP_INCLUDED


// Boost.Geometry

// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// 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_SRS_PROJECTIONS_DPAR_HPP
#define BOOST_GEOMETRY_SRS_PROJECTIONS_DPAR_HPP

#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>

#include <boost/geometry/srs/projections/exception.hpp>
#include <boost/geometry/srs/projections/par_data.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/srs/spheroid.hpp>

#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/variant/variant.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_void.hpp>

#include <string>
#include <vector>

namespace boost { namespace geometry { namespace srs
{

namespace detail
{

template
<
    typename Types,
    typename T,
    typename Iter = typename boost::mpl::begin<Types>::type,
    typename End = typename boost::mpl::end<Types>::type,
    int I = 0
>
struct find_type_index
{
    typedef typename boost::mpl::deref<Iter>::type type;
    static const int value = boost::is_same<type, T>::value
                           ? I
                           : find_type_index
                                <
                                    Types,
                                    T,
                                    typename boost::mpl::next<Iter>::type,
                                    End,
                                    I + 1
                                >::value;

};

template
<
    typename Types,
    typename T,
    typename End,
    int I
>
struct find_type_index<Types, T, End, End, I>
{
    static const int value = I;
};

template
<
    typename Range,
    typename ToValue,
    bool IsRange = boost::has_range_iterator<Range>::value
>
struct is_convertible_range
    : boost::is_convertible
        <
            typename boost::range_value<Range>::type,
            ToValue
        >
{};

template
<
    typename Range,
    typename ToValue
>
struct is_convertible_range<Range, ToValue, false>
    : boost::false_type
{};

} // namespace detail

namespace dpar
{

enum value_datum
{
    datum_wgs84 = 0,
    datum_ggrs87,
    datum_nad83,
    datum_nad27,
    datum_potsdam,
    datum_carthage,
    datum_hermannskogel,
    datum_ire65,
    datum_nzgd49,
    datum_osgb36,
};

enum value_ellps
{
    ellps_merit = 0,
    ellps_sgs85,
    ellps_grs80,
    ellps_iau76,
    ellps_airy,
    ellps_apl4_9,
    ellps_nwl9d,
    ellps_mod_airy,
    ellps_andrae,
    ellps_aust_sa,
    ellps_grs67,
    ellps_bessel,
    ellps_bess_nam,
    ellps_clrk66,
    ellps_clrk80,
    ellps_clrk80ign,
    ellps_cpm,
    ellps_delmbr,
    ellps_engelis,
    ellps_evrst30,
    ellps_evrst48,
    ellps_evrst56,
    ellps_evrst69,
    ellps_evrstss,
    ellps_fschr60,
    ellps_fschr60m,
    ellps_fschr68,
    ellps_helmert,
    ellps_hough,
    ellps_intl,
    ellps_krass,
    ellps_kaula,
    ellps_lerch,
    ellps_mprts,
    ellps_new_intl,
    ellps_plessis,
    ellps_seasia,
    ellps_walbeck,
    ellps_wgs60,
    ellps_wgs66,
    ellps_wgs72,
    ellps_wgs84,
    ellps_sphere
};

enum value_mode
{
    mode_plane = 0,
    mode_di,
    mode_dd,
    mode_hex
};

enum value_orient
{
    orient_isea = 0,
    orient_pole,
};

enum value_pm
{
    pm_greenwich = 0,
    pm_lisbon,
    pm_paris,
    pm_bogota,
    pm_madrid,
    pm_rome,
    pm_bern,
    pm_jakarta,
    pm_ferro,
    pm_brussels,
    pm_stockholm,
    pm_athens,
    pm_oslo
};

enum value_proj
{
    proj_unknown = 0,
    proj_aea, proj_leac,
    proj_aeqd,
    proj_airy,
    proj_aitoff, proj_wintri,
    proj_august,
    proj_apian, proj_ortel, proj_bacon,
    proj_bipc,
    proj_boggs,
    proj_bonne,
    proj_cass,
    proj_cc,
    proj_cea,
    proj_chamb,
    proj_collg,
    proj_crast,
    proj_denoy,
    proj_eck1,
    proj_eck2,
    proj_eck3, proj_putp1, proj_wag6, proj_kav7,
    proj_eck4,
    proj_eck5,
    proj_eqc,
    proj_eqdc,
    proj_etmerc, proj_utm,
    proj_fahey,
    proj_fouc_s,
    proj_gall,
    proj_geocent,
    proj_geos,
    proj_gins8,
    proj_gn_sinu, proj_sinu, proj_eck6, proj_mbtfps,
    proj_gnom,
    proj_goode,
    proj_gstmerc,
    proj_hammer,
    proj_hatano,
    proj_healpix,
    proj_rhealpix,
    proj_igh,
    proj_imw_p,
    proj_isea,
    proj_krovak,
    proj_labrd,
    proj_laea,
    proj_lagrng,
    proj_larr,
    proj_lask,
    proj_lonlat, proj_latlon, proj_latlong, proj_longlat,
    proj_lcc,
    proj_lcca,
    proj_loxim,
    proj_lsat,
    proj_mbt_fps,
    proj_mbtfpp,
    proj_mbtfpq,
    proj_merc,
    proj_mill,
    proj_mil_os, proj_lee_os, proj_gs48, proj_alsk, proj_gs50,
    proj_moll, proj_wag4, proj_wag5,
    proj_natearth,
    proj_nell,
    proj_nell_h,
    proj_nicol,
    proj_nsper, proj_tpers,
    proj_nzmg,
    proj_ob_tran,
    proj_ocea,
    proj_oea,
    proj_omerc,
    proj_ortho,
    proj_poly,
    proj_putp2,
    proj_putp3, proj_putp3p,
    proj_putp4p, proj_weren,
    proj_putp5, proj_putp5p,
    proj_putp6, proj_putp6p,
    proj_qsc,
    proj_robin,
    proj_rouss,
    proj_rpoly,
    proj_euler, proj_murd1, proj_murd2, proj_murd3, proj_pconic, proj_tissot, proj_vitk1,
    proj_somerc,
    proj_stere, proj_ups,
    proj_sterea,
    proj_kav5, proj_qua_aut, proj_fouc, proj_mbt_s,
    proj_tcc,
    proj_tcea,
    proj_tmerc,
    proj_tpeqd,
    proj_urm5,
    proj_urmfps, proj_wag1,
    proj_vandg,
    proj_vandg2, proj_vandg3,
    proj_vandg4,
    proj_wag2,
    proj_wag3,
    proj_wag7,
    proj_wink1,
    proj_wink2
};

enum value_sweep
{
    sweep_x = 0, sweep_y
};

enum value_units
{
    units_km = 0,
    units_m,
    units_dm,
    units_cm,
    units_mm,
    units_kmi,
    units_in,
    units_ft,
    units_yd,
    units_mi,
    units_fath,
    units_ch,
    units_link,
    units_us_in,
    units_us_ft,
    units_us_yd,
    units_us_ch,
    units_us_mi,
    units_ind_yd,
    units_ind_ft,
    units_ind_ch
};

enum name_f
{
    a = 0,
    b,
    e,
    es,
    f,
    h,
    //h_0, // currently not used
    k = 7,
    k_0,
    m, // also used for M
    n,
    //phdg_0, // currently not used
    //plat_0, // currently not used
    //plon_0, // currently not used
    q = 14,
    r, // originally R
    rf,
    to_meter,
    vto_meter,
    w, // originally W
    x_0,
    y_0
};

enum name_r
{
    alpha = 22,
    azi,
    gamma,
    lat_0,
    lat_1,
    lat_2,
    lat_3,
    lat_b,
    lat_ts, // 30
    lon_0,
    lon_1,
    lon_2,
    lon_3,
    lon_wrap,
    lonc,
    o_alpha,
    o_lat_1,
    o_lat_2,
    o_lat_c, // 40
    o_lat_p,
    o_lon_1,
    o_lon_2,
    o_lon_c,
    o_lon_p,
    r_lat_a, // originally R_lat_a
    r_lat_g, // originally R_lat_g
    theta,
    tilt
};

enum name_i
{
    aperture = 50,
    lsat,
    north_square,
    path,
    resolution,
    south_square,
    zone
};

enum name_be
{
    czech = 57,
    geoc,
    guam,
    no_cut, // 60
    no_defs,
    no_rot,
    ns,
    over,
    r_au, // originally R_A
    r_a, // originally R_a
    r_g, // originally R_g
    r_h, // originally R_h
    r_v, // originally R_V
    rescale, // 70
    south
};

/*enum name_catalog
{
    catalog = 72 // currently not used
};

enum name_date
{
    date = 73 // currently not used
};*/

enum name_datum
{
    datum = 74
};

enum name_ellps
{
    ellps = 75 // id, sphere or spheroid
};

/*enum name_geoidgrids
{
    geoidgrids = 76 // currently not used
};*/

enum name_mode
{
    mode = 77
};

enum name_nadgrids
{
    nadgrids = 78 // arbitrary-length list of strings
};

enum name_orient
{
    orient = 79
};

enum name_pm
{
    pm = 80 // id or angle
};

enum name_proj
{
    o_proj = 81,
    proj
};

enum name_sweep
{
    sweep = 83
};

enum name_towgs84
{
    towgs84 = 84 // 3 or 7 element list of numbers
};

enum name_units
{
    units = 85,
    vunits
};

template <typename T>
struct parameter
{
    parameter()
        : m_id(-1), m_value(false)
    {}

    parameter(name_f id, T const& v)
        : m_id(id), m_value(v)
    {}

    // TODO various angle units
    parameter(name_r id, T const& v)
        : m_id(id), m_value(v)
    {}

    parameter(name_i id, int v)
        : m_id(id), m_value(v)
    {}

    parameter(name_be id)
        : m_id(id), m_value(true)
    {}

    parameter(name_be id, bool v)
        : m_id(id), m_value(v)
    {}

    parameter(name_datum id, value_datum v)
        : m_id(id), m_value(int(v))
    {}

    parameter(value_datum v)
        : m_id(datum), m_value(int(v))
    {}

    // TODO: store model at this point?
    parameter(name_ellps id, value_ellps v)
        : m_id(id), m_value(int(v))
    {}
    // TODO: store model at this point?
    parameter(value_ellps v)
        : m_id(ellps), m_value(int(v))
    {}

    template <typename Sphere>
    parameter(name_ellps id, Sphere const& v,
              typename boost::enable_if_c
                <
                    boost::is_same<typename geometry::tag<Sphere>::type, srs_sphere_tag>::value
                >::type * = 0)
        : m_id(id)
        , m_value(T(get_radius<0>(v)))
    {}

    template <typename Spheroid>
    parameter(name_ellps id, Spheroid const& v,
              typename boost::enable_if_c
                <
                    boost::is_same<typename geometry::tag<Spheroid>::type, srs_spheroid_tag>::value
                >::type * = 0)
        : m_id(id)
        , m_value(srs::spheroid<T>(get_radius<0>(v), get_radius<2>(v)))
    {}

    parameter(name_mode id, value_mode v)
        : m_id(id), m_value(int(v))
    {}

    parameter(value_mode v)
        : m_id(mode), m_value(int(v))
    {}

    template <typename Range>
    parameter(name_nadgrids id, Range const& v,
              typename boost::enable_if_c
                <
                    detail::is_convertible_range<Range const, std::string>::value
                >::type * = 0)
        : m_id(id)
        , m_value(srs::detail::nadgrids(boost::begin(v), boost::end(v)))
    {}

#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
    parameter(name_nadgrids id, std::initializer_list<std::string> v)
        : m_id(id)
        , m_value(srs::detail::nadgrids(v))
    {}
#endif

    parameter(name_orient id, value_orient v)
        : m_id(id), m_value(int(v))
    {}

    parameter(value_orient v)
        : m_id(orient), m_value(int(v))
    {}

    // TODO: store to_meters at this point?
    parameter(name_pm id, value_pm v)
        : m_id(id), m_value(int(v))
    {}
    // TODO: store to_meters at this point?
    parameter(value_pm v)
        : m_id(pm), m_value(int(v))
    {}

    // TODO angle units
    parameter(name_pm id, T const& v)
        : m_id(id), m_value(v)
    {}

    parameter(name_proj id, value_proj v)
        : m_id(id), m_value(int(v))
    {}

    parameter(value_proj v)
        : m_id(proj), m_value(int(v))
    {}

    parameter(name_sweep id, value_sweep v)
        : m_id(id), m_value(int(v))
    {}

    parameter(value_sweep v)
        : m_id(sweep), m_value(int(v))
    {}

    template <typename Range>
    parameter(name_towgs84 id, Range const& v,
              typename boost::enable_if_c
                <
                    detail::is_convertible_range<Range const, T>::value
                >::type * = 0)
        : m_id(id)
        , m_value(srs::detail::towgs84<T>(boost::begin(v), boost::end(v)))
    {
        std::size_t n = boost::size(v);
        if (n != 3 && n != 7)
        {
            BOOST_THROW_EXCEPTION( projection_exception("Invalid number of towgs84 elements. Should be 3 or 7.") );
        }
    }

#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
    parameter(name_towgs84 id, std::initializer_list<T> v)
        : m_id(id)
        , m_value(srs::detail::towgs84<T>(v))
    {
        std::size_t n = v.size();
        if (n != 3 && n != 7)
        {
            BOOST_THROW_EXCEPTION( projection_exception("Invalid number of towgs84 elements. Should be 3 or 7.") );
        }
    }
#endif

    parameter(name_units id, value_units v)
        : m_id(id), m_value(int(v))
    {}

    parameter(value_units v)
        : m_id(units), m_value(int(v))
    {}

private:
    typedef boost::variant
        <
            bool,
            int,
            T,
            srs::spheroid<T>,
            srs::detail::nadgrids,
            srs::detail::towgs84<T>
        > variant_type;

public:
    bool is_id_equal(name_f const& id) const { return m_id == int(id); }
    bool is_id_equal(name_r const& id) const { return m_id == int(id); }
    bool is_id_equal(name_i const& id) const { return m_id == int(id); }
    bool is_id_equal(name_be const& id) const { return m_id == int(id); }
    bool is_id_equal(name_datum const& id) const { return m_id == int(id); }
    bool is_id_equal(name_ellps const& id) const { return m_id == int(id); }
    bool is_id_equal(name_mode const& id) const { return m_id == int(id); }
    bool is_id_equal(name_nadgrids const& id) const { return m_id == int(id); }
    bool is_id_equal(name_orient const& id) const { return m_id == int(id); }
    bool is_id_equal(name_pm const& id) const { return m_id == int(id); }
    bool is_id_equal(name_proj const& id) const { return m_id == int(id); }
    bool is_id_equal(name_sweep const& id) const { return m_id == int(id); }
    bool is_id_equal(name_towgs84 const& id) const { return m_id == int(id); }
    bool is_id_equal(name_units const& id) const { return m_id == int(id); }

    template <typename V>
    V const& get_value() const
    {
        return boost::get<V>(m_value);
    }

    template <typename V>
    bool is_value_set() const
    {
        return m_value.which() == srs::detail::find_type_index
            <
                typename variant_type::types,
                V
            >::value;
    }

private:
    int m_id;
    variant_type m_value;
};

template <typename T = double>
class parameters
{
    typedef std::vector<parameter<T> > container_type;

public:
    typedef typename container_type::value_type value_type;
    typedef typename container_type::const_iterator const_iterator;
    typedef typename container_type::const_reference const_reference;
    typedef typename container_type::size_type size_type;

    BOOST_DEFAULTED_FUNCTION(parameters(), {})

#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    template <typename Id>
    explicit parameters(Id id)
    {
        add(id);
    }

    template <typename Id>
    parameters & add(Id id)
    {
        m_params.push_back(parameter<T>(id));
        return *this;
    }

    template <typename Id>
    parameters & operator()(Id id)
    {
        return add(id);
    }

    template <typename Id, typename V>
    parameters(Id id, V const& value)
    {
        add(id, value);
    }

    template <typename Id, typename V>
    parameters & add(Id id, V const& value)
    {
        m_params.push_back(parameter<T>(id, value));
        return *this;
    }

    template <typename Id, typename V>
    parameters & operator()(Id id, V const& value)
    {
        return add(id, value);
    }

#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
    template <typename Id, typename V>
    parameters(Id id, std::initializer_list<V> value)
    {
        add(id, value);
    }

    template <typename Id, typename V>
    parameters & add(Id id, std::initializer_list<V> value)
    {
        m_params.push_back(parameter<T>(id, value));
        return *this;
    }

    template <typename Id, typename V>
    parameters & operator()(Id id, std::initializer_list<V> value)
    {
        return add(id, value);
    }
#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#else // BOOST_NO_CXX11_RVALUE_REFERENCES || BOOST_NO_CXX11_RVALUE_REFERENCES
    template <typename Id>
    explicit parameters(Id id)
    {
        add(id);
    }

    template <typename Id>
    parameters & add(Id id)
    {
        m_params.emplace_back(id);
        return *this;
    }

    template <typename Id>
    parameters & operator()(Id id)
    {
        return add(id);
    }

    template <typename Id, typename V>
    parameters(Id id, V && value)
    {
        add(id, std::forward<V>(value));
    }

    template <typename Id, typename V>
    parameters & add(Id id, V && value)
    {
        m_params.emplace_back(id, std::forward<V>(value));
        return *this;
    }

    template <typename Id, typename V>
    parameters & operator()(Id id, V && value)
    {
        return add(id, std::forward<V>(value));
    }

#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
    template <typename Id, typename V>
    parameters(Id id, std::initializer_list<V> value)
    {
        add(id, value);
    }

    template <typename Id, typename V>
    parameters & add(Id id, std::initializer_list<V> value)
    {
        m_params.emplace_back(id, value);
        return *this;
    }

    template <typename Id, typename V>
    parameters & operator()(Id id, std::initializer_list<V> value)
    {
        return add(id, value);
    }
#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#endif // BOOST_NO_CXX11_RVALUE_REFERENCES || BOOST_NO_CXX11_RVALUE_REFERENCES

    const_iterator begin() const { return m_params.begin(); }
    const_iterator end() const { return m_params.end(); }
    const_reference operator[](size_type i) const { return m_params[i]; }
    size_type size() { return m_params.size(); }
    bool empty() { return m_params.empty(); }

private:
    container_type m_params;
};

} // namespace dpar

}}} // namespace boost::geometry::srs

#endif // BOOST_GEOMETRY_SRS_PROJECTIONS_DPAR_HPP


/**
 * $Id$
 *
 * Copyright (C)
 * 2015
 *     Martin Wolf <boostnumpy@martin-wolf.org>
 *
 * @file boost/numpy/utilities.cpp
 * @version $Revision$
 * @date $Date$
 * @author Martin Wolf <boostnumpy@martin-wolf.org>
 * @brief This file contains the implementation of the BoostNumpy utility
 *        functions.
 *
 *        This file is 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).
 */
#define BOOST_NUMPY_INTERNAL_IMPL
#include <boost/numpy/internal_impl.hpp>

#include <boost/python.hpp>
#include <boost/python/import.hpp>

#include <boost/numpy/utilities.hpp>

namespace bp = boost::python;

namespace boost {
namespace numpy {

bp::object
all(ndarray const & a, int axis)
{
    bp::object out(bp::detail::new_reference(PyArray_All((PyArrayObject*)a.ptr(), axis, NULL)));
    return out;
}

void
all(ndarray const & a, int axis, ndarray & out)
{
    // The PyArray_All function returns a new reference on the None object, so
    // we need to create a bp::object to decrement the refcount of None after
    // returning from this all function.
    bp::object ret(bp::detail::new_reference(PyArray_All((PyArrayObject*)a.ptr(), axis, (PyArrayObject*)out.ptr())));
}

bp::object
any(ndarray const & a, int axis)
{
    bp::object out(bp::detail::new_reference(PyArray_Any((PyArrayObject*)a.ptr(), axis, NULL)));
    return out;
}

void
any(ndarray const & a, int axis, ndarray & out)
{
    // The PyArray_Any function returns a new reference on the None object, so
    // we need to create a bp::object to decrement the refcount of None after
    // returning from this all function.
    bp::object ret(bp::detail::new_reference(PyArray_Any((PyArrayObject*)a.ptr(), axis, (PyArrayObject*)out.ptr())));
}

ndarray
equal(ndarray const & x1, ndarray const & x2)
{
    bp::object np = bp::import("numpy");
    bp::object out_obj = np.attr("equal")(x1, x2);
    ndarray out(python::detail::borrowed_reference(out_obj.ptr()));
    return out;
}

void
equal(ndarray const & x1, ndarray const & x2, ndarray & out)
{
    bp::object np = bp::import("numpy");
    np.attr("equal")(x1, x2, out);
}

ndarray
empty_like(ndarray const & a)
{
    return empty(a.get_nd(), a.get_shape(), a.get_dtype());
}

ndarray
empty_like(ndarray const & a, dtype const & dt)
{
    return empty(a.get_nd(), a.get_shape(), dt);
}

}// namespace numpy
}// namespace boost


#ifndef SOURCE_HH
#define SOURCE_HH

#include <Eigen/Dense>

#include <vector>

namespace lwt {
  using Eigen::VectorXd;
  using Eigen::MatrixXd;

  // this is called by input nodes to get the inputs
  class ISource
  {
  public:
    virtual VectorXd at(size_t index) const = 0;
    virtual MatrixXd matrix_at(size_t index) const = 0;
  };

  class VectorSource: public ISource
  {
  public:
    VectorSource(std::vector<VectorXd>&&, std::vector<MatrixXd>&& = {});
    virtual VectorXd at(size_t index) const;
    virtual MatrixXd matrix_at(size_t index) const;
  private:
    std::vector<VectorXd> m_inputs;
    std::vector<MatrixXd> m_matrix_inputs;
  };

  class DummySource: public ISource
  {
  public:
    DummySource(const std::vector<size_t>& input_sizes,
                const std::vector<std::pair<size_t, size_t> >& = {});
    virtual VectorXd at(size_t index) const;
    virtual MatrixXd matrix_at(size_t index) const;
  private:
    std::vector<size_t> m_sizes;
    std::vector<std::pair<size_t, size_t> > m_matrix_sizes;
  };
}

#endif //SOURCE_HH


// Distributed under the MIT License.
// See LICENSE.txt for details.

/// \file
/// Defines class AdamsBashforthN

#pragma once

#include <algorithm>
#include <boost/iterator/transform_iterator.hpp>
#include <cstddef>
#include <iosfwd>
#include <iterator>
#include <limits>
#include <map>
#include <pup.h>
#include <tuple>
#include <type_traits>
#include <vector>

#include "NumericalAlgorithms/Interpolation/LagrangePolynomial.hpp"
#include "Options/Options.hpp"
#include "Parallel/CharmPupable.hpp"
#include "Time/EvolutionOrdering.hpp"
#include "Time/Time.hpp"
#include "Time/TimeStepId.hpp"
#include "Time/TimeSteppers/TimeStepper.hpp"  // IWYU pragma: keep
#include "Utilities/CachedFunction.hpp"
#include "Utilities/ErrorHandling/Assert.hpp"
#include "Utilities/ErrorHandling/Error.hpp"
#include "Utilities/Gsl.hpp"
#include "Utilities/MakeWithValue.hpp"
#include "Utilities/Overloader.hpp"
#include "Utilities/TMPL.hpp"

/// \cond
namespace TimeSteppers {
template <typename LocalVars, typename RemoteVars, typename CouplingResult>
class BoundaryHistory;  // IWYU pragma: keep
template <typename Vars, typename DerivVars>
class History;
}  // namespace TimeSteppers
/// \endcond

namespace TimeSteppers {

/*!
 * \ingroup TimeSteppersGroup
 *
 * An Nth order Adams-Bashforth time stepper.
 *
 * The stable step size factors for different orders are given by:
 *
 *

 *

 *     %Order
 *     CFL Factor
 *

 *

 *     1
 *     1
 *

 *

 *     2
 *     1 / 2
 *

 *

 *     3
 *     3 / 11
 *

 *

 *     4
 *     3 / 20
 *

 *

 *     5
 *     45 / 551
 *

 *

 *     6
 *     5 / 114
 *

 *

 *     7
 *     945 / 40663
 *

 *

 *     8
 *     945 / 77432
 *

 *

 */
class AdamsBashforthN : public LtsTimeStepper::Inherit {
 public:
  static constexpr const size_t maximum_order = 8;

  struct Order {
    using type = size_t;
    static constexpr Options::String help = {"Convergence order"};
    static type lower_bound() noexcept { return 1; }
    static type upper_bound() noexcept { return maximum_order; }
  };
  using options = tmpl::list<Order>;
  static constexpr Options::String help = {
      "An Adams-Bashforth Nth order time-stepper."};

  AdamsBashforthN() = default;
  explicit AdamsBashforthN(size_t order) noexcept;
  AdamsBashforthN(const AdamsBashforthN&) noexcept = default;
  AdamsBashforthN& operator=(const AdamsBashforthN&) noexcept = default;
  AdamsBashforthN(AdamsBashforthN&&) noexcept = default;
  AdamsBashforthN& operator=(AdamsBashforthN&&) noexcept = default;
  ~AdamsBashforthN() noexcept override = default;

  template <typename Vars, typename DerivVars>
  void update_u(gsl::not_null<Vars*> u,
                gsl::not_null<History<Vars, DerivVars>*> history,
                const TimeDelta& time_step) const noexcept;

  template <typename Vars, typename ErrVars, typename DerivVars>
  bool update_u(gsl::not_null<Vars*> u, gsl::not_null<ErrVars*> u_error,
                gsl::not_null<History<Vars, DerivVars>*> history,
                const TimeDelta& time_step) const noexcept;

  template <typename Vars, typename DerivVars>
  bool dense_update_u(gsl::not_null<Vars*> u,
                      const History<Vars, DerivVars>& history,
                      double time) const noexcept;

  // This is defined as a separate type alias to keep the doxygen page
  // width somewhat under control.
  template <typename LocalVars, typename RemoteVars, typename Coupling>
  using BoundaryHistoryType =
      BoundaryHistory<LocalVars, RemoteVars,
                      std::result_of_t<const Coupling&(LocalVars, RemoteVars)>>;

  /*!
   * An explanation of the computation being performed by this
   * function:
   * \f$\newcommand\tL{t^L}\newcommand\tR{t^R}\newcommand\tU{\tilde{t}\!}
   * \newcommand\mat{\mathbf}\f$
   *
   * Suppose the local and remote sides of the interface are evaluated
   * at times \f$\ldots, \tL_{-1}, \tL_0, \tL_1, \ldots\f$ and
   * \f$\ldots, \tR_{-1}, \tR_0, \tR_1, \ldots\f$, respectively, with
   * the starting location of the numbering arbitrary in each case.
   * Let the step we wish to calculate the effect of be the step from
   * \f$\tL_{m_S}\f$ to \f$\tL_{m_S+1}\f$.  We call the sequence
   * produced from the union of the local and remote time sequences
   * \f$\ldots, \tU_{-1}, \tU_0, \tU_1, \ldots\f$.  For example, one
   * possible sequence of times is:
   * \f{equation}
   *   \begin{aligned}
   *     \text{Local side:} \\ \text{Union times:} \\ \text{Remote side:}
   *   \end{aligned}
   *   \cdots
   *   \begin{gathered}
   *     \, \\ \tU_1 \\ \tR_5
   *   \end{gathered}
   *   \leftarrow \Delta \tU_1 \rightarrow
   *   \begin{gathered}
   *     \tL_4 \\ \tU_2 \\ \,
   *   \end{gathered}
   *   \leftarrow \Delta \tU_2 \rightarrow
   *   \begin{gathered}
   *     \, \\ \tU_3 \\ \tR_6
   *   \end{gathered}
   *   \leftarrow \Delta \tU_3 \rightarrow
   *   \begin{gathered}
   *    \, \\ \tU_4 \\ \tR_7
   *   \end{gathered}
   *   \leftarrow \Delta \tU_4 \rightarrow
   *   \begin{gathered}
   *     \tL_5 \\ \tU_5 \\ \,
   *   \end{gathered}
   *   \cdots
   * \f}
   * We call the indices of the step's start and end times in the
   * union time sequence \f$n_S\f$ and \f$n_E\f$, respectively.  We
   * define \f$n^L_m\f$ to be the union-time index corresponding to
   * \f$\tL_m\f$ and \f$m^L_n\f$ to be the index of the last local
   * time not later than \f$\tU_n\f$ and similarly for the remote
   * side.  So for the above example, \f$n^L_4 = 2\f$ and \f$m^R_2 =
   * 5\f$, and if we wish to compute the step from \f$\tL_4\f$ to
   * \f$\tL_5\f$ we would have \f$m_S = 4\f$, \f$n_S = 2\f$, and
   * \f$n_E = 5\f$.
   *
   * If we wish to evaluate the change over this step to \f$k\f$th
   * order, we can write the change in the value as a linear
   * combination of the values of the coupling between the elements at
   * unequal times:
   * \f{equation}
   *   \mat{F}_{m_S} =
   *   \mspace{-10mu}
   *   \sum_{q^L = m_S-(k-1)}^{m_S}
   *   \,
   *   \sum_{q^R = m^R_{n_S}-(k-1)}^{m^R_{n_E-1}}
   *   \mspace{-10mu}
   *   \mat{D}_{q^Lq^R}
   *   I_{q^Lq^R},
   * \f}
   * where \f$\mat{D}_{q^Lq^R}\f$ is the coupling function evaluated
   * between data from \f$\tL_{q^L}\f$ and \f$\tR_{q^R}\f$.  The
   * coefficients can be written as the sum of three terms,
   * \f{equation}
   *   I_{q^Lq^R} = I^E_{q^Lq^R} + I^R_{q^Lq^R} + I^L_{q^Lq^R},
   * \f}
   * which can be interpreted as a contribution from equal-time
   * evaluations and contributions related to the remote and local
   * evaluation times.  These are given by
   * \f{align}
   *   I^E_{q^Lq^R} &=
   *   \mspace{-10mu}
   *   \sum_{n=n_S}^{\min\left\{n_E, n^L+k\right\}-1}
   *   \mspace{-10mu}
   *   \tilde{\alpha}_{n,n-n^L} \Delta \tU_n
   *   &&\text{if $\tL_{q^L} = \tR_{q^R}$, otherwise 0}
   *   \\
   *   I^R_{q^Lq^R} &=
   *   \ell_{q^L - m_S + k}\!\left(
   *     \tU_{n^R}; \tL_{m_S - (k-1)}, \ldots, \tL_{m_S}\right)
   *   \mspace{-10mu}
   *   \sum_{n=\max\left\{n_S, n^R\right\}}
   *       ^{\min\left\{n_E, n^R+k\right\}-1}
   *   \mspace{-10mu}
   *   \tilde{\alpha}_{n,n-n^R} \Delta \tU_n
   *   &&\text{if $\tR_{q^R}$ is not in $\{\tL_{\vphantom{|}\cdots}\}$,
   *     otherwise 0}
   *   \\
   *   I^L_{q^Lq^R} &=
   *   \mspace{-10mu}
   *   \sum_{n=\max\left\{n_S, n^R\right\}}
   *       ^{\min\left\{n_E, n^L+k, n^R_{q^R+k}\right\}-1}
   *   \mspace{-10mu}
   *   \ell_{q^R - m^R_n + k}\!\left(\tU_{n^L};
   *     \tR_{m^R_n - (k-1)}, \ldots, \tR_{m^R_n}\right)
   *   \tilde{\alpha}_{n,n-n^L} \Delta \tU_n
   *   &&\text{if $\tL_{q^L}$ is not in $\{\tR_{\vphantom{|}\cdots}\}$,
   *     otherwise 0,}
   * \f}
   * where for brevity we write \f$n^L = n^L_{q^L}\f$ and \f$n^R =
   * n^R_{q^R}\f$, and where \f$\ell_a(t; x_1, \ldots, x_k)\f$ a
   * Lagrange interpolating polynomial and \f$\tilde{\alpha}_{nj}\f$
   * is the \f$j\f$th coefficient for an Adams-Bashforth step over the
   * union times from step \f$n\f$ to step \f$n+1\f$.
   */
  template <typename LocalVars, typename RemoteVars, typename Coupling>
  std::result_of_t<const Coupling&(LocalVars, RemoteVars)>
  compute_boundary_delta(
      const Coupling& coupling,
      gsl::not_null<BoundaryHistoryType<LocalVars, RemoteVars, Coupling>*>
          history,
      const TimeDelta& time_step) const noexcept;

  template <typename LocalVars, typename RemoteVars, typename Coupling>
  std::result_of_t<const Coupling&(LocalVars, RemoteVars)>
  boundary_dense_output(
      const Coupling& coupling,
      const BoundaryHistoryType<LocalVars, RemoteVars, Coupling>& history,
      double time) const noexcept;

  size_t order() const noexcept override;

  size_t error_estimate_order() const noexcept override;

  size_t number_of_past_steps() const noexcept override;

  double stable_step() const noexcept override;

  TimeStepId next_time_id(const TimeStepId& current_id,
                          const TimeDelta& time_step) const noexcept override;

  template <typename Vars, typename DerivVars>
  bool can_change_step_size(
      const TimeStepId& time_id,
      const TimeSteppers::History<Vars, DerivVars>& history) const noexcept;

  WRAPPED_PUPable_decl_template(AdamsBashforthN);  // NOLINT

  explicit AdamsBashforthN(CkMigrateMessage* /*unused*/) noexcept {}

  // clang-tidy: do not pass by non-const reference
  void pup(PUP::er& p) noexcept override;  // NOLINT

 private:
  friend bool operator==(const AdamsBashforthN& lhs,
                         const AdamsBashforthN& rhs) noexcept;

  // Some of the private methods take a parameter of type "Delta" or
  // "TimeType".  Delta is expected to be a TimeDelta or an
  // ApproximateTimeDelta, and TimeType is expected to be a Time or an
  // ApproximateTime.  The former cases will detect and optimize the
  // constant-time-step case, while the latter are necessary for dense
  // output.

  template <typename UpdateVars, typename Vars, typename DerivVars,
            typename Delta>
  void update_u_impl(gsl::not_null<UpdateVars*> u,
                     const History<Vars, DerivVars>& history,
                     const Delta& time_step, size_t order) const noexcept;

  template <typename LocalVars, typename RemoteVars, typename Coupling,
            typename TimeType>
  std::result_of_t<const Coupling&(LocalVars, RemoteVars)> boundary_impl(
      const Coupling& coupling,
      const BoundaryHistoryType<LocalVars, RemoteVars, Coupling>& history,
      const TimeType& end_time) const noexcept;

  /// Get coefficients for a time step.  Arguments are an iterator
  /// pair to past times, oldest to newest, and the time step to take.
  template <typename Iterator, typename Delta>
  static std::vector<double> get_coefficients(const Iterator& times_begin,
                                              const Iterator& times_end,
                                              const Delta& step) noexcept;

  static std::vector<double> get_coefficients_impl(
      const std::vector<double>& steps) noexcept;

  static std::vector<double> variable_coefficients(
      const std::vector<double>& steps) noexcept;

  static std::vector<double> constant_coefficients(size_t order) noexcept;

  struct ApproximateTimeDelta;

  // Time-like interface to a double used for dense output
  struct ApproximateTime {
    double time = std::numeric_limits<double>::signaling_NaN();
    double value() const noexcept { return time; }

    // Only the operators that are actually used are defined.
    friend ApproximateTimeDelta operator-(const ApproximateTime& a,
                                          const Time& b) noexcept {
      return {a.value() - b.value()};
    }

    friend bool operator<(const Time& a, const ApproximateTime& b) noexcept {
      return a.value() < b.value();
    }

    friend bool operator<(const ApproximateTime& a, const Time& b) noexcept {
      return a.value() < b.value();
    }

    friend std::ostream& operator<<(std::ostream& s,
                                    const ApproximateTime& t) noexcept {
      return s << t.value();
    }
  };

  // TimeDelta-like interface to a double used for dense output
  struct ApproximateTimeDelta {
    double delta = std::numeric_limits<double>::signaling_NaN();
    double value() const noexcept { return delta; }
    bool is_positive() const noexcept { return delta > 0.; }

    // Only the operators that are actually used are defined.
    friend bool operator<(const ApproximateTimeDelta& a,
                          const ApproximateTimeDelta& b) noexcept {
      return a.value() < b.value();
    }
  };

  size_t order_ = 3;
};

bool operator!=(const AdamsBashforthN& lhs,
                const AdamsBashforthN& rhs) noexcept;

template <typename Vars, typename DerivVars>
void AdamsBashforthN::update_u(
    const gsl::not_null<Vars*> u,
    const gsl::not_null<History<Vars, DerivVars>*> history,
    const TimeDelta& time_step) const noexcept {
  ASSERT(history->size() >= history->integration_order(),
         "Insufficient data to take an order-" << history->integration_order()
         << " step.  Have " << history->size() << " times, need "
         << history->integration_order());
  history->mark_unneeded(
      history->end() -
      static_cast<typename decltype(history->end())::difference_type>(
          history->integration_order()));
  update_u_impl(u, *history, time_step, history->integration_order());
}

template <typename Vars, typename ErrVars, typename DerivVars>
bool AdamsBashforthN::update_u(
    const gsl::not_null<Vars*> u, const gsl::not_null<ErrVars*> u_error,
    const gsl::not_null<History<Vars, DerivVars>*> history,
    const TimeDelta& time_step) const noexcept {
  ASSERT(history->size() >= history->integration_order(),
         "Insufficient data to take an order-" << history->integration_order()
         << " step.  Have " << history->size() << " times, need "
         << history->integration_order());
  history->mark_unneeded(
      history->end() -
      static_cast<typename decltype(history->end())::difference_type>(
          history->integration_order()));
  update_u_impl(u, *history, time_step, history->integration_order());
  // the error estimate is only useful once the history has enough elements to
  // do more than one order of step
  update_u_impl(u_error, *history, time_step, history->integration_order() - 1);
  *u_error = *u - *u_error;
  return true;
}

template <typename Vars, typename DerivVars>
bool AdamsBashforthN::dense_update_u(const gsl::not_null<Vars*> u,
                                     const History<Vars, DerivVars>& history,
                                     const double time) const noexcept {
  ASSERT(history.integration_order() == order_,
         "Dense output is only supported at full order");
  const ApproximateTimeDelta time_step{time - history.back().value()};
  update_u_impl(u, history, time_step, order_);
  return true;
}

template <typename UpdateVars, typename Vars, typename DerivVars,
          typename Delta>
void AdamsBashforthN::update_u_impl(const gsl::not_null<UpdateVars*> u,
                                    const History<Vars, DerivVars>& history,
                                    const Delta& time_step,
                                    const size_t order) const noexcept {
  ASSERT(
      history.size() > 0,
      "Cannot meaningfully update the evolved variables with an empty history");
  ASSERT(order <= order_,
         "Requested integration order higher than integrator order");

  const auto history_start =
      history.end() -
      static_cast<typename History<Vars, DerivVars>::difference_type>(order);
  const auto coefficients =
      get_coefficients(history_start, history.end(), time_step);

  *u = (history.end() - 1).value();
  auto coefficient = coefficients.rbegin();
  for (auto history_entry = history_start;
       history_entry != history.end();
       ++history_entry, ++coefficient) {
    *u += time_step.value() * *coefficient * history_entry.derivative();
  }
}

template <typename LocalVars, typename RemoteVars, typename Coupling>
std::result_of_t<const Coupling&(LocalVars, RemoteVars)>
AdamsBashforthN::compute_boundary_delta(
    const Coupling& coupling,
    const gsl::not_null<BoundaryHistoryType<LocalVars, RemoteVars, Coupling>*>
        history,
    const TimeDelta& time_step) const noexcept {
  const auto signed_order =
      static_cast<typename decltype(history->local_end())::difference_type>(
          history->integration_order());

  ASSERT(history->local_size() >= history->integration_order(),
         "Insufficient data to take an order-" << history->integration_order()
         << " step.  Have " << history->local_size() << " times, need "
         << history->integration_order());
  history->local_mark_unneeded(history->local_end() - signed_order);

  if (std::equal(history->local_begin(), history->local_end(),
                 history->remote_end() - signed_order)) {
    // GTS
    ASSERT(history->remote_size() >= history->integration_order(),
           "Insufficient data to take an order-" << history->integration_order()
           << " step.  Have " << history->remote_size() << " times, need "
           << history->integration_order());
    history->remote_mark_unneeded(history->remote_end() - signed_order);
  } else {
    const auto remote_step_for_step_start =
        std::upper_bound(history->remote_begin(), history->remote_end(),
                         *(history->local_end() - 1),
                         evolution_less<Time>{time_step.is_positive()});
    ASSERT(remote_step_for_step_start - history->remote_begin() >= signed_order,
           "Insufficient data to take an order-" << history->integration_order()
           << " step.  Have "
           << remote_step_for_step_start - history->remote_begin()
           << " times before the step, need " << history->integration_order());
    history->remote_mark_unneeded(remote_step_for_step_start - signed_order);
  }

  return boundary_impl(coupling, *history,
                       *(history->local_end() - 1) + time_step);
}

template <typename LocalVars, typename RemoteVars, typename Coupling>
std::result_of_t<const Coupling&(LocalVars, RemoteVars)>
AdamsBashforthN::boundary_dense_output(
    const Coupling& coupling,
    const BoundaryHistoryType<LocalVars, RemoteVars, Coupling>& history,
    const double time) const noexcept {
  return boundary_impl(coupling, history, ApproximateTime{time});
}

template <typename LocalVars, typename RemoteVars, typename Coupling,
          typename TimeType>
std::result_of_t<const Coupling&(LocalVars, RemoteVars)>
AdamsBashforthN::boundary_impl(
    const Coupling& coupling,
    const BoundaryHistoryType<LocalVars, RemoteVars, Coupling>& history,
    const TimeType& end_time) const noexcept {
  // Might be different from order_ during self-start.
  const auto current_order = history.integration_order();

  ASSERT(current_order <= order_,
         "Local history is too long for target order (" << current_order
         << " should not exceed " << order_ << ")");
  ASSERT(history.remote_size() >= current_order,
         "Remote history is too short (" << history.remote_size()
         << " should be at least " << current_order << ")");

  // Avoid billions of casts
  const auto order_s = static_cast<typename BoundaryHistoryType<
      LocalVars, RemoteVars, Coupling>::remote_iterator::difference_type>(
      current_order);

  // Start and end of the step we are trying to take
  const Time start_time = *(history.local_end() - 1);
  const auto time_step = end_time - start_time;

  // Result variable.  We evaluate the coupling only for the
  // structure.  This evaluation may be expensive, but by choosing the
  // most recent times on both sides we should guarantee that it is a
  // result we need later, so this will serve to get it into the
  // coupling cache so we don't have to compute it when we actually use it.
  auto accumulated_change =
      make_with_value<std::result_of_t<const Coupling&(LocalVars, RemoteVars)>>(
          history.coupling(coupling, history.local_end() - 1,
                           history.remote_end() - 1),
          0.);

  // We define the local_begin and remote_begin variables as the start
  // of the part of the history relevant to this calculation.
  // Boundary history cleanup happens immediately before the step, but
  // boundary dense output happens before that, so there may be data
  // left over that was needed for the previous step and has not been
  // cleaned out yet.
  const auto local_begin = history.local_end() - order_s;

  if (std::equal(local_begin, history.local_end(),
                 history.remote_end() - order_s)) {
    // No local time-stepping going on.
    const auto coefficients =
        get_coefficients(local_begin, history.local_end(), time_step);

    auto local_it = local_begin;
    auto remote_it = history.remote_end() - order_s;
    for (auto coefficients_it = coefficients.rbegin();
         coefficients_it != coefficients.rend();
         ++coefficients_it, ++local_it, ++remote_it) {
      accumulated_change +=
          *coefficients_it * history.coupling(coupling, local_it, remote_it);
    }
    accumulated_change *= time_step.value();

    return accumulated_change;
  }

  ASSERT(current_order == order_,
         "Cannot perform local time-stepping while self-starting.");

  const evolution_less<> less{time_step.is_positive()};
  const auto remote_begin =
      std::upper_bound(history.remote_begin(), history.remote_end(),
                       start_time, less) -
      order_s;

  ASSERT(std::is_sorted(local_begin, history.local_end(), less),
         "Local history not in order");
  ASSERT(std::is_sorted(remote_begin, history.remote_end(), less),
         "Remote history not in order");
  ASSERT(not less(start_time, *(remote_begin + (order_s - 1))),
         "Remote history does not extend far enough back");
  ASSERT(less(*(history.remote_end() - 1), end_time),
         "Please supply only older data: " << *(history.remote_end() - 1)
         << " is not before " << end_time);

  // Union of times of all step boundaries on any side.
  const auto union_times = [&history, &local_begin, &remote_begin,
                            &less]() noexcept {
    std::vector<Time> ret;
    ret.reserve(history.local_size() + history.remote_size());
    std::set_union(local_begin, history.local_end(), remote_begin,
                   history.remote_end(), std::back_inserter(ret), less);
    return ret;
  }();

  using UnionIter = typename decltype(union_times)::const_iterator;

  // Find the union times iterator for a given time.
  const auto union_step = [&union_times, &less](const Time& t) noexcept {
    return std::lower_bound(union_times.cbegin(), union_times.cend(), t, less);
  };

  // The union time index for the step start.
  const auto union_step_start = union_step(start_time);

  // min(union_times.end(), it + order_s) except being careful not
  // to create out-of-range iterators.
  const auto advance_within_step =
      [order_s, &union_times](const UnionIter& it) noexcept {
    return union_times.end() - it >
                   static_cast<typename decltype(union_times)::difference_type>(
                       order_s)
               ? it + static_cast<typename decltype(
                          union_times)::difference_type>(order_s)
               : union_times.end();
  };

  // Calculating the Adams-Bashforth coefficients is somewhat
  // expensive, so we cache them.  ab_coefs(it, step) returns the
  // coefficients used to step from *it to *it + step.
  auto ab_coefs = make_overloader(
      make_cached_function<std::tuple<UnionIter, TimeDelta>,
                           std::map>([order_s](
          const std::tuple<UnionIter, TimeDelta>& args) noexcept {
        return get_coefficients(
            std::get<0>(args) -
                static_cast<typename UnionIter::difference_type>(order_s - 1),
            std::get<0>(args) + 1, std::get<1>(args));
      }),
      make_cached_function<std::tuple<UnionIter, ApproximateTimeDelta>,
                           std::map>([order_s](
          const std::tuple<UnionIter, ApproximateTimeDelta>& args) noexcept {
        return get_coefficients(
            std::get<0>(args) -
                static_cast<typename UnionIter::difference_type>(order_s - 1),
            std::get<0>(args) + 1, std::get<1>(args));
      }));

  // The value of the coefficient of `evaluation_step` when doing
  // a standard Adams-Bashforth integration over the union times
  // from `step` to `step + 1`.
  const auto base_summand = [&ab_coefs, &end_time, &union_times](
      const UnionIter& step, const UnionIter& evaluation_step) noexcept {
    if (step + 1 != union_times.end()) {
      const TimeDelta step_size = *(step + 1) - *step;
      return step_size.value() *
             ab_coefs(std::make_tuple(
                 step, step_size))[static_cast<size_t>(step - evaluation_step)];
    } else {
      const auto step_size = end_time - *step;
      return step_size.value() *
             ab_coefs(std::make_tuple(
                 step, step_size))[static_cast<size_t>(step - evaluation_step)];
    }
  };

  for (auto local_evaluation_step = local_begin;
       local_evaluation_step != history.local_end();
       ++local_evaluation_step) {
    const auto union_local_evaluation_step = union_step(*local_evaluation_step);
    for (auto remote_evaluation_step = remote_begin;
         remote_evaluation_step != history.remote_end();
         ++remote_evaluation_step) {
      double deriv_coef = 0.;

      if (*local_evaluation_step == *remote_evaluation_step) {
        // The two elements stepped at the same time.  This gives a
        // standard Adams-Bashforth contribution to each segment
        // making up the current step.
        const auto union_step_upper_bound =
            advance_within_step(union_local_evaluation_step);
        for (auto step = union_step_start;
             step < union_step_upper_bound;
             ++step) {
          deriv_coef += base_summand(step, union_local_evaluation_step);
        }
      } else {
        // In this block we consider a coupling evaluation that is not
        // performed at equal times on the two sides of the mortar.

        // Makes an iterator with a map to give time as a double.
        const auto make_lagrange_iterator = [](const auto& it) noexcept {
          return boost::make_transform_iterator(
              it, [](const Time& t) noexcept { return t.value(); });
        };

        const auto union_remote_evaluation_step =
            union_step(*remote_evaluation_step);
        const auto union_step_lower_bound =
            std::max(union_step_start, union_remote_evaluation_step);

        // Compute the contribution to an interpolation over the local
        // times to `remote_evaluation_step->value()`, which we will
        // use as the coupling value for that time.  If there is an
        // actual evaluation at that time then skip this because the
        // Lagrange polynomial will be zero.
        if (not std::binary_search(local_begin, history.local_end(),
                                   *remote_evaluation_step, less)) {
          const auto union_step_upper_bound =
              advance_within_step(union_remote_evaluation_step);
          for (auto step = union_step_lower_bound;
               step < union_step_upper_bound;
               ++step) {
            deriv_coef += base_summand(step, union_remote_evaluation_step);
          }
          deriv_coef *=
              lagrange_polynomial(make_lagrange_iterator(local_evaluation_step),
                                  remote_evaluation_step->value(),
                                  make_lagrange_iterator(local_begin),
                                  make_lagrange_iterator(history.local_end()));
        }

        // Same qualitative calculation as the previous block, but
        // interpolating over the remote times.  This case is somewhat
        // more complicated because the latest remote time that can be
        // used varies for the different segments making up the step.
        if (not std::binary_search(remote_begin, history.remote_end(),
                                   *local_evaluation_step, less)) {
          auto union_step_upper_bound =
              advance_within_step(union_local_evaluation_step);
          if (history.remote_end() - remote_evaluation_step > order_s) {
            union_step_upper_bound = std::min(
                union_step_upper_bound,
                union_step(*(remote_evaluation_step + order_s)));
          }

          auto control_points = make_lagrange_iterator(
              remote_evaluation_step - remote_begin >= order_s
                  ? remote_evaluation_step - (order_s - 1)
                  : remote_begin);
          for (auto step = union_step_lower_bound;
               step < union_step_upper_bound;
               ++step, ++control_points) {
            deriv_coef +=
                base_summand(step, union_local_evaluation_step) *
                lagrange_polynomial(
                    make_lagrange_iterator(remote_evaluation_step),
                    local_evaluation_step->value(), control_points,
                    control_points +
                        static_cast<typename decltype(
                            control_points)::difference_type>(order_s));
          }
        }
      }

      if (deriv_coef != 0.) {
        // Skip the (potentially expensive) coupling calculation if
        // the coefficient is zero.
        accumulated_change +=
            deriv_coef * history.coupling(coupling, local_evaluation_step,
                                          remote_evaluation_step);
      }
    }  // for remote_evaluation_step
  }  // for local_evaluation_step

  return accumulated_change;
}

template <typename Vars, typename DerivVars>
bool AdamsBashforthN::can_change_step_size(
    const TimeStepId& time_id,
    const TimeSteppers::History<Vars, DerivVars>& history) const noexcept {
  // We need to forbid local time-stepping before initialization is
  // complete.  The self-start procedure itself should never consider
  // changing the step size, but we need to wait during the main
  // evolution until the self-start history has been replaced with
  // "real" values.
  const evolution_less<Time> less{time_id.time_runs_forward()};
  return history.size() == 0 or
         (less(history.back(), time_id.step_time()) and
          std::is_sorted(history.begin(), history.end(), less));
}

template <typename Iterator, typename Delta>
std::vector<double> AdamsBashforthN::get_coefficients(
    const Iterator& times_begin, const Iterator& times_end,
    const Delta& step) noexcept {
  if (times_begin == times_end) {
    return {};
  }
  std::vector<double> steps;
  // This may be slightly more space than we need, but we can't get
  // the exact amount without iterating through the iterators, which
  // is not necessarily cheap depending on the iterator type.
  steps.reserve(maximum_order);
  for (auto t = times_begin; std::next(t) != times_end; ++t) {
    steps.push_back((*std::next(t) - *t).value());
  }
  steps.push_back(step.value());
  return get_coefficients_impl(steps);
}
}  // namespace TimeSteppers


////////////////////////////////////////////////////////////////////////////////
//  Copyright (c) 2011 Bryce Adelstein-Lelbach
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
////////////////////////////////////////////////////////////////////////////////

#include <algorithm>

#include <boost/array.hpp>

struct accumulator
{
  private:
    unsigned& total_;

  public:
    accumulator(
        unsigned& total
        )
      : total_(total)
    {}

    void operator()(
        unsigned x
        )
    {
        total_ += x;
    }
};

int main()
{
    boost::array<unsigned, 10> fib { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 };

    unsigned total = 0;

    auto f = accumulator(total);

    std::for_each(fib.begin(), fib.end(), f);

    return !(88 == total);
}


//  Copyright (c) 2011 David Bellot
//
//  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_UBLAS_NO_ELEMENT_PROXIES
# define BOOST_UBLAS_NO_ELEMENT_PROXIES
#endif

#include <boost/numeric/ublas/assignment.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>
#include <boost/numeric/ublas/io.hpp>

#include "libs/numeric/ublas/test/utils.hpp"

using std::cout;
using std::endl;

const double TOL = 1e-15;

template <class AE>
typename AE::value_type mean_square(const boost::numeric::ublas::matrix_expression<AE> &me) {
    typename AE::value_type s(0);
    typename AE::size_type i, j;
    for (i=0; i!= me().size1(); i++) {
        for (j=0; j!= me().size2(); j++) {
          s += boost::numeric::ublas::scalar_traits<typename AE::value_type>::type_abs(me()(i,j));
        }
    }
    return s/me().size1()*me().size2();
}

template<typename T>
bool check_sortedness(const boost::numeric::ublas::coordinate_matrix<T>& matrix) {
  bool result = true;
  typedef boost::numeric::ublas::coordinate_matrix<T> matrix_type;
  typename matrix_type::index_array_type i1 = matrix.index1_data();
  typename matrix_type::index_array_type i2 = matrix.index2_data();
  typename matrix_type::array_size_type size = matrix.filled();

  for (typename matrix_type::array_size_type i = 0; i + 1 < size && result; ++ i) {
    result &= ( (i1[i] < i1[i + 1]) ||
                ((i1[i] == i1[i]) &&
                 (i2[i] < i2[i + 1])) );

  }
  return result;
}

void print_entries(size_t size_x, size_t size_y,
                   const std::vector<std::pair<size_t, size_t> >& entries)
{
  std::cerr << "Error - Size:" << size_x << " x " << size_y << ". Entries: ";
  for (size_t i = 0; i < entries.size(); ++ i) {
    std::cerr << entries[i].first << ", " << entries[i].second << "; ";
  }
  std::cerr << "\n";
}

BOOST_UBLAS_TEST_DEF( test_coordinate_matrix_inplace_merge_random )
{
  const size_t max_repeats = 100;
  const size_t max_size = 100;
  const size_t dim_var = 10;
  const size_t nr_entries = 10;

  for (size_t repeats = 1; repeats < max_repeats; ++repeats ) {
    for (size_t size = 1; size < max_size; size += 5) {
      size_t size_x = size + rand() % dim_var;
      size_t size_y = size + rand() % dim_var;

      boost::numeric::ublas::coordinate_matrix<double> matrix_coord(size_x, size_y);
      boost::numeric::ublas::matrix<double> matrix_dense(size_x, size_y, 0);

      matrix_coord.sort();

      std::vector<std::pair<size_t, size_t> > entries;
      for (int entry = 0; entry < nr_entries; ++ entry) {
        int x = rand() % size_x;
        int y = rand() % size_y;
        entries.push_back(std::make_pair(x, y));
        matrix_coord.append_element(x, y, 1);
        matrix_dense(x, y) += 1;
      }
      matrix_coord.sort();

      {
        bool sorted = check_sortedness(matrix_coord);
        bool identical = mean_square(matrix_coord - matrix_dense) < TOL;
        if (!(sorted && identical)) {
          print_entries(size_x, size_y, entries);
        }
        BOOST_UBLAS_TEST_CHECK( check_sortedness(matrix_coord) );
        BOOST_UBLAS_TEST_CHECK( mean_square(matrix_coord - matrix_dense) < TOL);
      }

      for (int entry = 0; entry < nr_entries; ++ entry) {
        int x = rand() % size_x;
        int y = rand() % size_y;
        entries.push_back(std::make_pair(x, y));
        matrix_coord(x, y) += 1;
        matrix_dense(x, y) += 1;
        matrix_coord.sort();
      }

      {
        bool sorted = check_sortedness(matrix_coord);
        bool identical = mean_square(matrix_coord - matrix_dense) < TOL;
        if (!(sorted && identical)) {
          print_entries(size_x, size_y, entries);
        }
        BOOST_UBLAS_TEST_CHECK( sorted );
        BOOST_UBLAS_TEST_CHECK( identical );
      }
    }
  }
}

int main()
{
    BOOST_UBLAS_TEST_BEGIN();

    BOOST_UBLAS_TEST_DO( test_coordinate_matrix_inplace_merge_random );

    BOOST_UBLAS_TEST_END();

    return EXIT_SUCCESS;;
}


#pragma once

#include <dfg/dfgDefs.hpp>

DFG_BEGIN_INCLUDE_WITH_DISABLED_WARNINGS
    #include <boost/version.hpp>
    #if (BOOST_VERSION >= 107000) // Histogram is available since 1.70 (2019-04-12)
        #include <boost/histogram.hpp>
    #endif

    #include <boost/accumulators/framework/accumulator_set.hpp>
    #include <boost/accumulators/statistics/variance.hpp>
    #include <boost/accumulators/statistics/stats.hpp>

    #include <QAction>
    #include <QCoreApplication>
    #include <QDateTime>
    #include <QFile>
    #include <QFileInfo>
    #include <QDialog>
    #include <QGridLayout>
    #include <QMetaMethod>
    #include <QMutex>
    #include <QMutexLocker>
    #include <QReadWriteLock>
    #include <QSortFilterProxyModel>
    #include <QSpinBox>
    #include <QSqlError>
    #include <QSqlQuery>
    #include <QSqlRecord>
    #include <QThread>
    #include <QUndoStack>

    #if defined(DFGQTE_USING_QCUSTOMPLOT) && DFGQTE_USING_QCUSTOMPLOT == 1
        #include <dfg/qt/qcustomplot/qcustomplot.h>
    #endif

DFG_END_INCLUDE_WITH_DISABLED_WARNINGS

#include <dfg/alg.hpp>
#include <dfg/cont/IntervalSet.hpp>
#include <dfg/cont/IntervalSetSerialization.hpp>
#include <dfg/cont/MapVector.hpp>
#include <dfg/cont/SetVector.hpp>
#include <dfg/cont/SortedSequence.hpp>
#include <dfg/cont/table.hpp>
#include <dfg/cont/tableCsv.hpp>
#include <dfg/dfgBase.hpp>
#include <dfg/io.hpp>
#include <dfg/io/DelimitedTextReader.hpp>
#include <dfg/io/OmcByteStream.hpp>
#include <dfg/math.hpp>
#include <dfg/math/FormulaParser.hpp>
#include <dfg/qt/containerUtils.hpp>
#include <dfg/qt/CsvTableView.hpp>
#include <dfg/qt/CsvItemModel.hpp>
#include <dfg/qt/CsvTableViewActions.hpp>
#include <dfg/qt/qtBasic.hpp>
#include <dfg/qt/sqlTools.hpp>
#include <dfg/rand/distributionHelpers.hpp>
#include <dfg/str/string.hpp>
#include <dfg/str/strTo.hpp>