/*
    Copyright 2013 Adobe
    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 ADOBE_ALGORITHM_SORTED_HPP
#define ADOBE_ALGORITHM_SORTED_HPP

#include <algorithm>
#include <functional>
#include <iterator>

#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>

#include <adobe/functional/operator.hpp>

/**************************************************************************************************/

namespace adobe {

/**************************************************************************************************/
/*!
\defgroup sorted sorted
\ingroup sorting
*/

/*!
\ingroup sorted
*/
template <typename I, // I models InputIterator
          typename O>
// O models StrictWeakOrdering on value_type(I)
I sorted(I f, I l, O o) {

    f = std::adjacent_find(f, l,
                           std::bind(std::logical_not<bool>(),
                                     std::bind(o, std::placeholders::_1, std::placeholders::_2)));
    if (f != l)
        ++f;
    return f;
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I> // I models InputIterator, value_type(I) models LessThanComparable
I sorted(I f, I l) {
    return sorted(f, l, less());
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I, // I models InputIterator
          typename O>
// O models StrictWeakOrdering on value_type(I)
inline bool is_sorted(I f, I l, O o) {
    return std::adjacent_find(
               f, l,
               std::bind(std::logical_not<bool>(),
                         std::bind(o, std::placeholders::_1, std::placeholders::_2))) == l;
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I> // I models InputIterator, value_type(I) models LessThanComparable
inline bool is_sorted(I f, I l) {
    return is_sorted(f, l, less());
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I, // I models ForwardIterator
          typename C, // C models StrictWeakOrdering(T, T)
          typename P>
// P models UnaryFunction(value_type(I)) -> T
inline bool is_sorted(I f, I l, C c, P p) {
    return std::adjacent_find(f, l,
                              std::bind(std::logical_not<bool>(),
                                        std::bind(c, std::bind(p, std::placeholders::_1),
                                                  std::bind(p, std::placeholders::_2)))) == l;
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I, // I models ForwardRange
          typename C, // C models StrictWeakOrdering(T, T)
          typename P>
// P models UnaryFunction(value_type(I)) -> T
inline bool is_sorted(const I& r, C c, P p) {
    return is_sorted(boost::begin(r), boost::end(r), c, p);
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I, // I models ForwardRange
          typename C>
// C models StrictWeakOrdering(T, T)
inline bool is_sorted(const I& r, C c) {
    return is_sorted(boost::begin(r), boost::end(r), c,
                     identity<typename std::iterator_traits<I>::value_type>());
}

/**************************************************************************************************/

/*!
\ingroup sorted
*/
template <typename I> // I models ForwardRange
inline bool is_sorted(const I& r) {
    return is_sorted(boost::begin(r), boost::end(r), less());
}

/**************************************************************************************************/

} // namespace adobe

/**************************************************************************************************/

#endif

/**************************************************************************************************/


//  Copyright John Maddock 2011.
//  Use, modification and distribution are subject to the
//  Boost Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

//
// This tests that cpp_dec_float_50 meets our
// conceptual requirements.
//
#ifdef _MSC_VER
#  define _SCL_SECURE_NO_WARNINGS
#  pragma warning(disable:4800)
#  pragma warning(disable:4512)
#  pragma warning(disable:4127)
#  pragma warning(disable:4512)
#  pragma warning(disable:4503) // decorated name length exceeded, name was truncated
#endif

#if !defined(TEST_MPF_50) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) \
   && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR_50)\
   && !defined(TEST_MPFR_6) && !defined(TEST_MPFR_15) && !defined(TEST_MPFR_17) \
   && !defined(TEST_MPFR_30) && !defined(TEST_CPP_DEC_FLOAT_NO_ET) && !defined(TEST_LOGGED_ADAPTER)
#  define TEST_MPF_50
#  define TEST_BACKEND
#  define TEST_MPZ
#  define TEST_MPFR_50
#  define TEST_MPFR_6
#  define TEST_MPFR_15
#  define TEST_MPFR_17
#  define TEST_MPFR_30
#  define TEST_CPP_DEC_FLOAT
#  define TEST_CPP_DEC_FLOAT_NO_ET
#  define TEST_LOGGED_ADAPTER

#ifdef _MSC_VER
#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
#endif
#ifdef __GNUC__
#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
#endif

#endif

#if defined(TEST_MPF_50) || defined(TEST_MPZ)
#include <boost/multiprecision/gmp.hpp>
#endif
#ifdef TEST_BACKEND
#include <boost/multiprecision/concepts/mp_number_archetypes.hpp>
#endif
#if defined(TEST_CPP_DEC_FLOAT) || defined(TEST_CPP_DEC_FLOAT_NO_ET) || defined(TEST_LOGGED_ADAPTER)
#include <boost/multiprecision/cpp_dec_float.hpp>
#endif
#if defined(TEST_MPFR_50) || defined(TEST_MPFR_6) || defined(TEST_MPFR_15) || defined(TEST_MPFR_17) || defined(TEST_MPFR_30)
#include <boost/multiprecision/mpfr.hpp>
#endif
#ifdef TEST_LOGGED_ADAPTER
#include <boost/multiprecision/logged_adaptor.hpp>
#endif

#include <boost/math/concepts/real_type_concept.hpp>

template <class T>
void test_extra(T)
{
   T t = 1;
   t = abs(t);
   t = abs(t*t);

   t = fabs(t);
   t = fabs(t*t);

   t = sqrt(t);
   t = sqrt(t*t);

   t = floor(t);
   t = floor(t*t);

   t = ceil(t);
   t = ceil(t*t);

   t = trunc(t);
   t = trunc(t*t);

   t = round(t);
   t = round(t*t);

   t = exp(t);
   t = exp(t*t);

   t = log(t);
   t = log(t*t);

   t = log10(t);
   t = log10(t*t);

   t = cos(t);
   t = cos(t*t);

   t = sin(t);
   t = sin(t*t);

   t = tan(t);
   t = tan(t*t);

   t = asin(t);
   t = asin(t*t);

   t = atan(t);
   t = atan(t*t);

   t = acos(t);
   t = acos(t*t);

   t = cosh(t);
   t = cosh(t*t);

   t = sinh(t);
   t = sinh(t*t);

   t = tanh(t);
   t = tanh(t*t);

   double dval = 2;
   t = pow(t, t);
   t = pow(t, t*t);
   t = pow(t, dval);
   t = pow(t*t, t);
   t = pow(t*t, t*t);
   t = pow(t*t, dval);
   t = pow(dval, t);
   t = pow(dval, t*t);

   t = atan2(t, t);
   t = atan2(t, t*t);
   t = atan2(t, dval);
   t = atan2(t*t, t);
   t = atan2(t*t, t*t);
   t = atan2(t*t, dval);
   t = atan2(dval, t);
   t = atan2(dval, t*t);

   t = fmod(t, t);
   t = fmod(t, t*t);
   t = fmod(t, dval);
   t = fmod(t*t, t);
   t = fmod(t*t, t*t);
   t = fmod(t*t, dval);
   t = fmod(dval, t);
   t = fmod(dval, t*t);

   typedef typename T::backend_type backend_type;
   typedef typename backend_type::exponent_type exp_type;
   exp_type e = 0;
   int i = 0;

   t = ldexp(t, i);
   t = ldexp(t*t, i);
   t = ldexp(t, e);
   t = ldexp(t*t, e);

   t = frexp(t, &i);
   t = frexp(t*t, &i);
   t = frexp(t, &e);
   t = frexp(t*t, &e);
}

void foo()
{
#ifdef TEST_BACKEND
   test_extra(boost::multiprecision::concepts::mp_number_float_architype());
#endif
#ifdef TEST_MPF_50
   test_extra(boost::multiprecision::mpf_float_50());
#endif
#ifdef TEST_MPFR_50
   test_extra(boost::multiprecision::mpfr_float_50());
#endif
#ifdef TEST_MPFR_6
   test_extra(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<6> >());
#endif
#ifdef TEST_MPFR_15
   test_extra(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<15> >());
#endif
#ifdef TEST_MPFR_17
   test_extra(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<17> >());
#endif
#ifdef TEST_MPFR_30
   test_extra(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<30> >());
#endif
#ifdef TEST_CPP_DEC_FLOAT
   test_extra(boost::multiprecision::cpp_dec_float_50());
#endif
#ifdef TEST_CPP_DEC_FLOAT_NO_ET
   test_extra(boost::multiprecision::number<boost::multiprecision::cpp_dec_float<100>, boost::multiprecision::et_off>());
#endif
}

int main()
{
#ifdef TEST_BACKEND
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::concepts::mp_number_float_architype>));
#endif
#ifdef TEST_MPF_50
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::mpf_float_50>));
#endif
#ifdef TEST_MPFR_50
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::mpfr_float_50>));
#endif
#ifdef TEST_MPFR_6
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<6> > >));
#endif
#ifdef TEST_MPFR_15
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<15> > >));
#endif
#ifdef TEST_MPFR_17
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<17> > >));
#endif
#ifdef TEST_MPFR_30
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<30> > >));
#endif
#ifdef TEST_MPFR_50
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::mpfr_float_50>));
#endif
#ifdef TEST_CPP_DEC_FLOAT
   BOOST_CONCEPT_ASSERT((boost::math::concepts::RealTypeConcept<boost::multiprecision::cpp_dec_float_50>));
#endif
#ifdef TEST_LOGGED_ADAPTER
   typedef boost::multiprecision::number<boost::multiprecision::logged_adaptor<boost::multiprecision::cpp_dec_float<50> > > num_t;
   test_extra(num_t());
#endif

}


#pragma once

#include <type_traits>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include "el_def.hpp"

// Euler non-standard STL utilities
namespace estl {

// Integer container
template <int N>
struct integer {
  // For generic Lambda
  constexpr static inline int get() { return N; }
  constexpr static int value = N;
};

// Base sequence class
struct sequence {
  template <int I> constexpr static int get() { return 0; }
};

template <int... Is> struct integer_sequence_indexer;

// Integer sequence container
template <int... Ns> struct integer_sequence : sequence {
  template <int I> constexpr static int get()
  {
    return integer_sequence_indexer<Ns...>::template get<I>();
  }
};

// Make a sequence: entry
template <bool enabled, int from, int... Ns> struct make_integer_sequence {};

// Make a sequence: recursion
template <int from, int to, int... Ns>
struct make_integer_sequence<true, from, to, Ns...> {
  using type =
      typename make_integer_sequence<true, from, to - 1, to - 1, Ns...>::type;
};

// Make a sequence: end condition
template <int from, int... Ns>
struct make_integer_sequence<true, from, from, Ns...> {
  using type = integer_sequence<Ns...>;
};

// Assert invalid sequence
template <int from, int to, int... Ns>
struct make_integer_sequence<false, from, to, Ns...> {
  static_assert(from < to, "sequence (from, to) is invalid when from >= to!");
};

template <int from, int to>
using valid_range = typename make_integer_sequence <from < to, from, to>::type;

// Helper interfaces for make_interger_sequence
template <int from, int to> using range = valid_range<from, to>;
template <int to> using arange = valid_range<0, to>;

// Iterate the sequence
template <typename F, int... Ns>
inline void for_each(integer_sequence<Ns...>, F func)
{
#if __cpp_generic_lambdas && !__GCC_COMPILER
  (void)(int[]){ (func(integer<Ns>{}), 0)... };
#else
  // Workaround the lambda issue. XXX. It will depends on
  // compiler to optimize the runtime parameter passing.
  (void)(int[]){ (func(Ns), 0)... };
#endif
}

//
// Looping unrolling
//
// /* C++14 */
// estl::for_each (estl::range<4, 13>{}, [&](const auto n) {
//   constexpr N = n.get();
//   print<N>();
// });
//
// /* C++11 */
// estl::for_each (estl::range<4, 13>{}, [&](const int n) {
//   print(n);
// });
//

struct sequence_indexer {};

// Get sequece element by index
template <int...Vs>
struct integer_sequence_indexer : sequence_indexer {
  // Index, value pair
  template <int N, int V> struct pair {
    using type = decltype(integer<V>{});
  };

  // Base
  template <typename T, int ...Ms>
  struct zip;

  // Map index with value
  template <int ...Is>
  struct zip<integer_sequence<Is...>, Vs...> : pair<Is, Vs>... {};

  // Return value by index
  template <int N, int V> constexpr static int index(pair<N, V>) { return V; };

  template <int I> constexpr static int get()
  {
    static_assert(I < sizeof...(Vs), "Index overflow!");
    return index<I>(zip<arange<sizeof...(Vs)>, Vs...>{});
  }
};

// Helper interface to integer_sequence_indexer
// I: index, R: return type, T: sequence
template <int I, typename R, typename S>
static constexpr
typename std::enable_if<std::is_base_of<sequence, S>{}, R>::type get()
{
  return S::template get<I>();
}

// Indexing integer (bool, short, int, ...) sequence
//
// template <int ...Ns> struct {
//   using seq = integer_sequence<Ns...>;
//   constexpr auto a = estl::get<0, int, seq>();
// };
//

#define ONE_ITER(z, n, data)                                                   \
  {                                                                            \
    constexpr int(BOOST_PP_TUPLE_ELEM(2, 0, data)) = n;                        \
    BOOST_PP_TUPLE_ELEM(2, 1, data);                                           \
  }

// C-preprocessing based inline loop
//
// i: indexer
// from: loop lower bound, must be an immediate number
// to: loop upper bound, must be an immediate number
// ...: loop body
#define LOOP_FROM_TO(i, from, to, ...)                                         \
  do {                                                                         \
    BOOST_PP_REPEAT_FROM_TO(from, to, ONE_ITER, (i, __VA_ARGS__));             \
  } while (0)

// Loops using on LOOP_FROM_TO
//
// LOOP_FROM_TO(_O, 0, 3, {
//   LOOP_FROM_TO(_T, 0, 3, {
//     printf("_O=%d, _T=%d\n", _O, _T);
//   });
// });

template <typename T, int n>
struct mm_reg {
  T& get() { return t_; }
  using type = T;
  T t_;
};

template<typename... Types>
struct mm_regs;

template <typename R, typename... Rs> struct mm_regs<R, Rs...> {
  template <typename _R>
  inline typename std::enable_if<std::is_same<R, _R>::value, _R &>::type
  get_element()
  {
    return r_;
  }

  template <typename _R>
  inline typename std::enable_if<!std::is_same<R, _R>::value, _R &>::type
  get_element()
  {
    return rs_.template get_element<_R>();
  }

  template <typename T, int n> inline T &get()
  {
    return get_element<mm_reg<T, n>>().get();
  }

  R r_;
  mm_regs<Rs...> rs_;
};

template <typename R> struct mm_regs<R> {
  template <typename _R> inline R& get_element() { return r_; }

  template <typename T, int n> inline T& get()
  {
    return get_element<mm_reg<T, n>>().get();
  }

  R r_;
};

template <typename T, typename N>
struct make_mm_regs {};

template <typename T, int ...Ns>
struct make_mm_regs<T, integer_sequence<Ns...>> {
  using type = mm_regs<mm_reg<T, Ns>...>;
};

template <typename T, int N>
using make_mm_arange = typename make_mm_regs<T, arange<N>>::type;

template <typename T, int M, int N>
struct mm_regs_matrix {
  using regs_matrix = typename make_mm_regs<T, arange<M * N>>::type;

  template <int m, int n>
  T& get() {
    return matrix_.template get<T, m * N + n>();
  }
  regs_matrix matrix_;
};

template <typename T, int N>
struct mm_regs_arange {
  using regs_arange = typename make_mm_regs<T, arange<N>>::type;

  template <int n>
  T& get() {
    return arange_.template get<T, n>();
  }
  regs_arange arange_;
};

// Regs array/matrix
//
// /* Allocate a 4*8 ZMM matrix */
// mm_regs_matrix<__m<V>, 4, 8> mm;
//
// /* Indexing */
// mm.get<3, 4>() = _mm<V>::set1_ps(0.0f);
//

template <typename T, typename U> inline bool any_of(T val, U last)
{ return val == last; }
template <typename T, typename U, typename... Args> inline bool any_of(
    T val, U first, Args... rest) {
  return (val == first) || any_of(val, rest...);
}

template <typename T, typename... Args> inline bool none_of(
    T val, Args... args) {
  return !any_of(val, args...);
}

template <typename T, typename U> inline bool all_of(T val, U last) {
  return val == last;
}

template <typename T, typename U, typename... Args> inline bool all_of(
    T val, U first, Args... rest) {
  return (val == first) && all_of(val, rest...);
}

template<typename T>
inline const T& max(const T& m, const T& n) {
    return m > n ? m : n;
}

template<typename T>
inline const T& min(const T& m, const T& n) {
    return m < n ? m : n;
}

} // estl


/*
Copyright (c) 2017 InversePalindrome
InPal - CalculusPanel.cpp
InversePalindrome.com
*/

#include "CalculusPanel.hpp"

#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/stattext.h>

#include <boost/format.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>

CalculusPanel::CalculusPanel(wxWindow* parent, MathDataDefault* mathData) :
    wxPanel(parent, wxID_ANY),
    mathData(mathData),
    derivativeChoice(),
    derivativeEntry(new wxTextCtrl(this, wxID_ANY)),
    xPositionEntry(new wxTextCtrl(this, wxID_ANY)),
    derivativeSolution(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_READONLY)),
    integralEntry(new wxTextCtrl(this, wxID_ANY)),
    initialXEntry(new wxTextCtrl(this, wxID_ANY)),
    finalXEntry(new wxTextCtrl(this, wxID_ANY)),
    integralSolution(new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_READONLY))
{
    SetBackgroundColour(wxColor(128u, 128u, 128u));

    auto* topSizer = new wxBoxSizer(wxVERTICAL);
    auto* derivativeSizer = new wxBoxSizer(wxHORIZONTAL);
    auto* derivativeButtonSizer = new wxBoxSizer(wxHORIZONTAL);
    auto* integralSizer = new wxBoxSizer(wxHORIZONTAL);
    auto* integralButtonSizer = new wxBoxSizer(wxHORIZONTAL);

    auto* derivativeText = new wxStaticText(this, wxID_ANY, "Derivative");
    auto* derivativeFunctionText = new wxStaticText(this, wxID_ANY, "Function");
    auto* xPositionText = new wxStaticText(this, wxID_ANY, "Position(X):");

    auto* integralText = new wxStaticText(this, wxID_ANY, "Integral");
    auto* integralFunctionText = new wxStaticText(this, wxID_ANY, "Function");
    auto* integralInitialXText = new wxStaticText(this, wxID_ANY, "Starting Position(X):");
    auto* integralFinalXText = new wxStaticText(this, wxID_ANY, "Final Position(X):");

    auto& font = wxFont(8u, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);

    derivativeText->SetFont(font);
    xPositionText->SetFont(font);
    derivativeFunctionText->SetFont(font);
    integralText->SetFont(font);
    integralFunctionText->SetFont(font);
    integralInitialXText->SetFont(font);
    integralFinalXText->SetFont(font);

    wxArrayString derivativeChoices;
    derivativeChoices.Add("First Derivative");
    derivativeChoices.Add("Second Derivative");
    derivativeChoices.Add("Third Derivative");

    derivativeChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, derivativeChoices);
    derivativeChoice->SetStringSelection("First Derivative");

    auto* solveDerivativeButton = new wxButton(this, wxID_ANY, "Solve");
    auto* solveIntegralButton = new wxButton(this, wxID_ANY, "Solve");

    auto* clearDerivativeButton = new wxButton(this, wxID_ANY, "Clear");
    auto* clearIntegralButton = new wxButton(this, wxID_ANY, "Clear");

    derivativeSizer->Add(derivativeChoice, 0u, wxALL, 10u);
    derivativeSizer->Add(xPositionText, 0u, wxALL, 10u);
    derivativeSizer->Add(xPositionEntry, 0u, wxALL, 10u);

    derivativeButtonSizer->Add(solveDerivativeButton, 0u, wxALL, 5u);
    derivativeButtonSizer->Add(clearDerivativeButton, 0u, wxALL, 5u);

    integralSizer->Add(integralInitialXText, 0u, wxALL, 10u);
    integralSizer->Add(initialXEntry, 0u, wxALL, 10u);
    integralSizer->Add(integralFinalXText, 0u, wxALL, 10u);
    integralSizer->Add(finalXEntry, 0u, wxALL, 10u);

    integralButtonSizer->Add(solveIntegralButton, 0u, wxALL, 5u);
    integralButtonSizer->Add(clearIntegralButton, 0u, wxALL, 5u);

    topSizer->AddSpacer(55u);
    topSizer->Add(derivativeText, 0u, wxALL, 5u);
    topSizer->Add(derivativeSolution, 0u, wxEXPAND | wxALL, 5u);
    topSizer->Add(derivativeFunctionText, 0u, wxEXPAND | wxALL, 5u);
    topSizer->Add(derivativeEntry, 0u, wxEXPAND | wxALL, 5u);
    topSizer->Add(derivativeSizer, 0u, wxALIGN_CENTER | wxALL, 5u);
    topSizer->Add(derivativeButtonSizer, 0u, wxALIGN_CENTER | wxALL, 5u);
    topSizer->AddSpacer(30u);
    topSizer->Add(integralText, 0u, wxALL, 5u);
    topSizer->Add(integralSolution, 0u, wxEXPAND | wxALL, 5u);
    topSizer->Add(integralFunctionText, 0u, wxEXPAND | wxALL, 5u);
    topSizer->Add(integralEntry, 0u, wxEXPAND | wxALL, 5u);
    topSizer->Add(integralSizer, 0u, wxALIGN_CENTER | wxALL, 5u);
    topSizer->Add(integralButtonSizer, 0u, wxALIGN_CENTER | wxALL, 5u);

    topSizer->Fit(this);
    topSizer->SetSizeHints(this);

    SetSizer(topSizer);

    solveDerivativeButton->Bind(wxEVT_LEFT_DOWN, &CalculusPanel::OnSolveDerivative, this);
    solveIntegralButton->Bind(wxEVT_LEFT_DOWN, &CalculusPanel::OnSolveIntegral, this);

    clearDerivativeButton->Bind(wxEVT_LEFT_DOWN, &CalculusPanel::OnClearDerivative, this);
    clearIntegralButton->Bind(wxEVT_LEFT_DOWN, &CalculusPanel::OnClearIntegral, this);
}

void CalculusPanel::OnSolveDerivative(wxMouseEvent& event)
{
    auto& functionEquation = this->derivativeEntry->GetValue().ToStdString();

    boost::replace_all(functionEquation, "x", "derivativeVariable");

    this->mathData->mathSolver.setTask(functionEquation);

    long double derivativeVariable;
    try
    {
        derivativeVariable = std::stold(this->xPositionEntry->GetValue().ToStdString());
    }
    catch (const std::invalid_argument & e)
    {
        derivativeVariable = 0;
    }

    this->mathData->mathSolver.addVariable("derivativeVariable", derivativeVariable);

    if (this->mathData->mathSolver.solve())
    {
        long double derivative;

        if (this->derivativeChoice->GetStringSelection() == "First Derivative")
        {
            derivative = this->mathData->mathSolver.getDerivative(derivativeVariable);
        }
        else if (this->derivativeChoice->GetStringSelection() == "Second Derivative")
        {
            derivative = this->mathData->mathSolver.getSecondDerivative(derivativeVariable);
        }
        else if (this->derivativeChoice->GetStringSelection() == "Third Derivative")
        {
            derivative = this->mathData->mathSolver.getThirdDerivative(derivativeVariable);
        }

        auto& result = boost::str(boost::format("%.18f") %
            derivative);

        boost::trim_right_if(result, boost::is_any_of("0"));
        boost::trim_right_if(result, boost::is_any_of("."));

        this->derivativeSolution->SetValue(result);
    }
}

void CalculusPanel::OnSolveIntegral(wxMouseEvent& event)
{
    auto& functionEquation = this->integralEntry->GetValue().ToStdString();

    boost::replace_all(functionEquation, "x", "integralVariable");

    this->mathData->mathSolver.setTask(functionEquation);

    long double integralVariable = 0.0;
    long double initialX;
    long double finalX;

    this->mathData->mathSolver.addVariable("integralVariable", integralVariable);

    try
    {
        initialX = std::stold(this->initialXEntry->GetValue().ToStdString());
        finalX = std::stold(this->finalXEntry->GetValue().ToStdString());
    }
    catch (const std::invalid_argument & e)
    {
        initialX = 0.0;
        finalX = 1.0;
    }

    if (this->mathData->mathSolver.solve())
    {
        auto& result = boost::str(boost::format("%.18f") %
            this->mathData->mathSolver.getIntegral(integralVariable, initialX, finalX));
        boost::trim_right_if(result, boost::is_any_of("0"));
        boost::trim_right_if(result, boost::is_any_of("."));

        this->integralSolution->SetValue(result);
    }
}

void CalculusPanel::OnClearDerivative(wxMouseEvent& event)
{
    this->derivativeSolution->Clear();
    this->derivativeEntry->Clear();
    this->xPositionEntry->Clear();
}

void CalculusPanel::OnClearIntegral(wxMouseEvent& event)
{
    this->integralSolution->Clear();
    this->integralEntry->Clear();
    this->initialXEntry->Clear();
    this->finalXEntry->Clear();
}


/**
 * @file adam_test.cpp
 * @author Vasanth Kalingeri
 * @author Vivek Pal
 * @author Sourabh Varshney
 * @author Haritha Nair
 *
 * Tests the Adam, AdaMax, AMSGrad, Nadam and NadaMax optimizer.
 *
 * mlpack is free software; you may redistribute it and/or modify it under the
 * terms of the 3-clause BSD license.  You should have received a copy of the
 * 3-clause BSD license along with mlpack.  If not, see
 * http://www.opensource.org/licenses/BSD-3-Clause for more information.
 */

#include <mlpack/core.hpp>

#include <mlpack/core/optimizers/adam/adam.hpp>

#include <mlpack/core/optimizers/problems/sgd_test_function.hpp>
#include <mlpack/core/optimizers/problems/colville_function.hpp>
#include <mlpack/core/optimizers/problems/booth_function.hpp>
#include <mlpack/core/optimizers/problems/sphere_function.hpp>
#include <mlpack/core/optimizers/problems/styblinski_tang_function.hpp>
#include <mlpack/core/optimizers/problems/mc_cormick_function.hpp>
#include <mlpack/core/optimizers/problems/matyas_function.hpp>
#include <mlpack/core/optimizers/problems/easom_function.hpp>
#include <mlpack/methods/logistic_regression/logistic_regression.hpp>

#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"

using namespace arma;
using namespace mlpack::optimization;
using namespace mlpack::optimization::test;

using namespace mlpack::distribution;
using namespace mlpack::regression;

using namespace mlpack;

BOOST_AUTO_TEST_SUITE(AdamTest);

/**
 * Test the Adam optimizer on the Sphere function.
 */
BOOST_AUTO_TEST_CASE(AdamSphereFunctionTest)
{
  SphereFunction f(2);
  Adam optimizer(0.5, 2, 0.7, 0.999, 1e-8, 500000, 1e-3, false);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
}

/**
 * Test the Adam optimizer on the Wood function.
 */
BOOST_AUTO_TEST_CASE(AdamStyblinskiTangFunctionTest)
{
  StyblinskiTangFunction f(2);
  Adam optimizer(0.5, 2, 0.7, 0.999, 1e-8, 500000, 1e-3, false);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_CLOSE(coordinates[0], -2.9, 1.0); // 1% error tolerance.
  BOOST_REQUIRE_CLOSE(coordinates[1], -2.9, 1.0); // 1% error tolerance.
}

/**
 * Test the Adam optimizer on the McCormick function.
 */
BOOST_AUTO_TEST_CASE(AdamMcCormickFunctionTest)
{
  McCormickFunction f;
  Adam optimizer(0.5, 1, 0.7, 0.999, 1e-8, 500000, 1e-5, false);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_CLOSE(coordinates[0], -0.547, 3.0); // 3% error tolerance.
  BOOST_REQUIRE_CLOSE(coordinates[1], -1.547, 3.0); // 3% error tolerance.
}

/**
 * Test the Adam optimizer on the Matyas function.
 */
BOOST_AUTO_TEST_CASE(AdamMatyasFunctionTest)
{
  MatyasFunction f;
  Adam optimizer(0.5, 1, 0.7, 0.999, 1e-8, 500000, 1e-5, false);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  // 3% error tolerance.
  BOOST_REQUIRE_CLOSE(std::trunc(100.0 * coordinates[0]) / 100.0, 0.0, 3.0);
  BOOST_REQUIRE_CLOSE(std::trunc(100.0 * coordinates[1]) / 100.0, 0.0, 3.0);
}

/**
 * Test the Adam optimizer on the Easom function.
 */
BOOST_AUTO_TEST_CASE(AdamEasomFunctionTest)
{
  EasomFunction f;
  Adam optimizer(0.2, 1, 0.7, 0.999, 1e-8, 500000, 1e-5, false);

  arma::mat coordinates = arma::mat("2.9; 2.9");
  optimizer.Optimize(f, coordinates);

  // 5% error tolerance.
  BOOST_REQUIRE_CLOSE(std::trunc(100.0 * coordinates[0]) / 100.0, 3.14, 3.0);
  BOOST_REQUIRE_CLOSE(std::trunc(100.0 * coordinates[1]) / 100.0, 3.14, 3.0);
}

/**
 * Test the Adam optimizer on the Booth function.
 */
BOOST_AUTO_TEST_CASE(AdamBoothFunctionTest)
{
  BoothFunction f;
  Adam optimizer(1e-1, 1, 0.7, 0.999, 1e-8, 500000, 1e-9, true);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_CLOSE(coordinates[0], 1.0, 0.2);
  BOOST_REQUIRE_CLOSE(coordinates[1], 3.0, 0.2);
}

/**
 * Tests the Adam optimizer using a simple test function.
 */
BOOST_AUTO_TEST_CASE(SimpleAdamTestFunction)
{
  SGDTestFunction f;
  Adam optimizer(1e-3, 1, 0.9, 0.999, 1e-8, 500000, 1e-9, true);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[2], 0.1);
}

/**
 * Tests the AdaMax optimizer using a simple test function.
 */
BOOST_AUTO_TEST_CASE(SimpleAdaMaxTestFunction)
{
  SGDTestFunction f;
  AdaMax optimizer(2e-3, 1, 0.9, 0.999, 1e-8, 500000, 1e-9, true);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[2], 0.1);
}

/**
 * Tests the AMSGrad optimizer using a simple test function.
 */
BOOST_AUTO_TEST_CASE(SimpleAMSGradTestFunction)
{
  SGDTestFunction f;
  AMSGrad optimizer(1e-3, 1, 0.9, 0.999, 1e-8, 500000, 1e-11, true);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[2], 0.1);
}

/**
 * Run Adam on logistic regression and make sure the results are acceptable.
 */
BOOST_AUTO_TEST_CASE(AdamLogisticRegressionTest)
{
  // Generate a two-Gaussian dataset.
  GaussianDistribution g1(arma::vec("1.0 1.0 1.0"), arma::eye<arma::mat>(3, 3));
  GaussianDistribution g2(arma::vec("9.0 9.0 9.0"), arma::eye<arma::mat>(3, 3));

  arma::mat data(3, 1000);
  arma::Row<size_t> responses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    data.col(i) = g1.Random();
    responses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    data.col(i) = g2.Random();
    responses[i] = 1;
  }

  // Shuffle the dataset.
  arma::uvec indices = arma::shuffle(arma::linspace<arma::uvec>(0,
      data.n_cols - 1, data.n_cols));
  arma::mat shuffledData(3, 1000);
  arma::Row<size_t> shuffledResponses(1000);
  for (size_t i = 0; i < data.n_cols; ++i)
  {
    shuffledData.col(i) = data.col(indices[i]);
    shuffledResponses[i] = responses[indices[i]];
  }

  // Create a test set.
  arma::mat testData(3, 1000);
  arma::Row<size_t> testResponses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    testData.col(i) = g1.Random();
    testResponses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    testData.col(i) = g2.Random();
    testResponses[i] = 1;
  }

  Adam adam;
  LogisticRegression<> lr(shuffledData, shuffledResponses, adam, 0.5);

  // Ensure that the error is close to zero.
  const double acc = lr.ComputeAccuracy(data, responses);
  BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance.

  const double testAcc = lr.ComputeAccuracy(testData, testResponses);
  BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance.
}

/**
 * Run AdaMax on logistic regression and make sure the results are acceptable.
 */
BOOST_AUTO_TEST_CASE(AdaMaxLogisticRegressionTest)
{
  // Generate a two-Gaussian dataset.
  GaussianDistribution g1(arma::vec("1.0 1.0 1.0"), arma::eye<arma::mat>(3, 3));
  GaussianDistribution g2(arma::vec("9.0 9.0 9.0"), arma::eye<arma::mat>(3, 3));

  arma::mat data(3, 1000);
  arma::Row<size_t> responses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    data.col(i) = g1.Random();
    responses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    data.col(i) = g2.Random();
    responses[i] = 1;
  }

  // Shuffle the dataset.
  arma::uvec indices = arma::shuffle(arma::linspace<arma::uvec>(0,
      data.n_cols - 1, data.n_cols));
  arma::mat shuffledData(3, 1000);
  arma::Row<size_t> shuffledResponses(1000);
  for (size_t i = 0; i < data.n_cols; ++i)
  {
    shuffledData.col(i) = data.col(indices[i]);
    shuffledResponses[i] = responses[indices[i]];
  }

  // Create a test set.
  arma::mat testData(3, 1000);
  arma::Row<size_t> testResponses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    testData.col(i) = g1.Random();
    testResponses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    testData.col(i) = g2.Random();
    testResponses[i] = 1;
  }

  AdaMax adamax(1e-3, 1, 0.9, 0.999, 1e-8, 5000000, 1e-9, true);
  LogisticRegression<> lr(shuffledData, shuffledResponses, adamax, 0.5);

  // Ensure that the error is close to zero.
  const double acc = lr.ComputeAccuracy(data, responses);
  BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance.

  const double testAcc = lr.ComputeAccuracy(testData, testResponses);
  BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance.
}

/**
 * Run AMSGrad on logistic regression and make sure the results are acceptable.
 */
BOOST_AUTO_TEST_CASE(AMSGradLogisticRegressionTest)
{
  // Generate a two-Gaussian dataset.
  GaussianDistribution g1(arma::vec("1.0 1.0 1.0"), arma::eye<arma::mat>(3, 3));
  GaussianDistribution g2(arma::vec("9.0 9.0 9.0"), arma::eye<arma::mat>(3, 3));

  arma::mat data(3, 1000);
  arma::Row<size_t> responses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    data.col(i) = g1.Random();
    responses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    data.col(i) = g2.Random();
    responses[i] = 1;
  }

  // Shuffle the dataset.
  arma::uvec indices = arma::shuffle(arma::linspace<arma::uvec>(0,
      data.n_cols - 1, data.n_cols));
  arma::mat shuffledData(3, 1000);
  arma::Row<size_t> shuffledResponses(1000);
  for (size_t i = 0; i < data.n_cols; ++i)
  {
    shuffledData.col(i) = data.col(indices[i]);
    shuffledResponses[i] = responses[indices[i]];
  }

  // Create a test set.
  arma::mat testData(3, 1000);
  arma::Row<size_t> testResponses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    testData.col(i) = g1.Random();
    testResponses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    testData.col(i) = g2.Random();
    testResponses[i] = 1;
  }

  AMSGrad amsgrad(1e-3, 1, 0.9, 0.999, 1e-8, 500000, 1e-11, true);
  LogisticRegression<> lr(shuffledData, shuffledResponses, amsgrad, 0.5);

  // Ensure that the error is close to zero.
  const double acc = lr.ComputeAccuracy(data, responses);
  BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance.

  const double testAcc = lr.ComputeAccuracy(testData, testResponses);
  BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance.
}

/**
 * Tests the Nadam optimizer using a simple test function.
 */
BOOST_AUTO_TEST_CASE(SimpleNadamTestFunction)
{
  SGDTestFunction f;
  Nadam optimizer(1e-3, 1, 0.9, 0.99, 1e-8, 500000, 1e-9, true);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[2], 0.1);
}

/**
 * Run Nadam on logistic regression and make sure the results are acceptable.
 */
BOOST_AUTO_TEST_CASE(NadamLogisticRegressionTest)
{
  // Generate a two-Gaussian dataset.
  GaussianDistribution g1(arma::vec("1.0 1.0 1.0"),
  arma::eye<arma::mat>(3, 3));
  GaussianDistribution g2(arma::vec("9.0 9.0 9.0"),
  arma::eye<arma::mat>(3, 3));

  arma::mat data(3, 1000);
  arma::Row<size_t> responses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    data.col(i) = g1.Random();
    responses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    data.col(i) = g2.Random();
    responses[i] = 1;
  }

  // Shuffle the dataset.
  arma::uvec indices = arma::shuffle(arma::linspace<arma::uvec>(0,
  data.n_cols - 1, data.n_cols));
  arma::mat shuffledData(3, 1000);
  arma::Row<size_t> shuffledResponses(1000);
  for (size_t i = 0; i < data.n_cols; ++i)
  {
    shuffledData.col(i) = data.col(indices[i]);
    shuffledResponses[i] = responses[indices[i]];
  }

  // Create a test set.
  arma::mat testData(3, 1000);
  arma::Row<size_t> testResponses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    testData.col(i) = g1.Random();
    testResponses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    testData.col(i) = g2.Random();
    testResponses[i] = 1;
  }

  Nadam nadam;
  LogisticRegression<> lr(shuffledData, shuffledResponses, nadam, 0.5);

  // Ensure that the error is close to zero.
  const double acc = lr.ComputeAccuracy(data, responses);
  BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance.

  const double testAcc = lr.ComputeAccuracy(testData, testResponses);
  BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance.
}

/**
 * Tests the NadaMax optimizer using a simple test function.
 */
BOOST_AUTO_TEST_CASE(SimpleNadaMaxTestFunction)
{
  SGDTestFunction f;
  NadaMax optimizer(1e-3, 1, 0.9, 0.99, 1e-8, 500000, 1e-9, true);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[2], 0.1);
}

/**
 * Run NadaMax on logistic regression and make sure the results are acceptable.
 */
BOOST_AUTO_TEST_CASE(NadaMaxLogisticRegressionTest)
{
  // Generate a two-Gaussian dataset.
  GaussianDistribution g1(arma::vec("1.0 1.0 1.0"),
  arma::eye<arma::mat>(3, 3));
  GaussianDistribution g2(arma::vec("9.0 9.0 9.0"),
  arma::eye<arma::mat>(3, 3));

  arma::mat data(3, 1000);
  arma::Row<size_t> responses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    data.col(i) = g1.Random();
    responses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    data.col(i) = g2.Random();
    responses[i] = 1;
  }

  // Shuffle the dataset.
  arma::uvec indices = arma::shuffle(arma::linspace<arma::uvec>(0,
  data.n_cols - 1, data.n_cols));
  arma::mat shuffledData(3, 1000);
  arma::Row<size_t> shuffledResponses(1000);
  for (size_t i = 0; i < data.n_cols; ++i)
  {
    shuffledData.col(i) = data.col(indices[i]);
    shuffledResponses[i] = responses[indices[i]];
  }

  // Create a test set.
  arma::mat testData(3, 1000);
  arma::Row<size_t> testResponses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    testData.col(i) = g1.Random();
    testResponses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    testData.col(i) = g2.Random();
    testResponses[i] = 1;
  }

  NadaMax nadamax;
  LogisticRegression<> lr(shuffledData, shuffledResponses, nadamax, 0.5);

  // Ensure that the error is close to zero.
  const double acc = lr.ComputeAccuracy(data, responses);
  BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance.

  const double testAcc = lr.ComputeAccuracy(testData, testResponses);
  BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance.
}

/**
 * Tests the OptimisticAdam optimizer using a simple test function.
 */
BOOST_AUTO_TEST_CASE(SimpleOptimisticAdamTestFunction)
{
  SGDTestFunction f;
  OptimisticAdam optimizer(1e-2, 1, 0.9, 0.99, 1e-8);

  arma::mat coordinates = f.GetInitialPoint();
  optimizer.Optimize(f, coordinates);

  BOOST_REQUIRE_SMALL(coordinates[0], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[1], 0.1);
  BOOST_REQUIRE_SMALL(coordinates[2], 0.1);
}

/**
 * Run OptimisticAdam on logistic regression and make sure the results are acceptable.
 */
BOOST_AUTO_TEST_CASE(OptimisticAdamLogisticRegressionTest)
{
  // Generate a two-Gaussian dataset.
  GaussianDistribution g1(arma::vec("1.0 1.0 1.0"),
  arma::eye<arma::mat>(3, 3));
  GaussianDistribution g2(arma::vec("9.0 9.0 9.0"),
  arma::eye<arma::mat>(3, 3));

  arma::mat data(3, 1000);
  arma::Row<size_t> responses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    data.col(i) = g1.Random();
    responses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    data.col(i) = g2.Random();
    responses[i] = 1;
  }

  // Shuffle the dataset.
  arma::uvec indices = arma::shuffle(arma::linspace<arma::uvec>(0,
  data.n_cols - 1, data.n_cols));
  arma::mat shuffledData(3, 1000);
  arma::Row<size_t> shuffledResponses(1000);
  for (size_t i = 0; i < data.n_cols; ++i)
  {
    shuffledData.col(i) = data.col(indices[i]);
    shuffledResponses[i] = responses[indices[i]];
  }

  // Create a test set.
  arma::mat testData(3, 1000);
  arma::Row<size_t> testResponses(1000);
  for (size_t i = 0; i < 500; ++i)
  {
    testData.col(i) = g1.Random();
    testResponses[i] = 0;
  }
  for (size_t i = 500; i < 1000; ++i)
  {
    testData.col(i) = g2.Random();
    testResponses[i] = 1;
  }

  OptimisticAdam optimisticAdam;
  LogisticRegression<> lr(shuffledData, shuffledResponses, optimisticAdam, 0.5);

  // Ensure that the error is close to zero.
  const double acc = lr.ComputeAccuracy(data, responses);
  BOOST_REQUIRE_CLOSE(acc, 100.0, 0.3); // 0.3% error tolerance.

  const double testAcc = lr.ComputeAccuracy(testData, testResponses);
  BOOST_REQUIRE_CLOSE(testAcc, 100.0, 0.6); // 0.6% error tolerance.
}

BOOST_AUTO_TEST_SUITE_END();


//
// Created by Alex Beccaro on 18/01/18.
//

#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include "../../src/problems/51-100/72/problem72.hpp"

BOOST_AUTO_TEST_SUITE( Problem72 )

    BOOST_AUTO_TEST_CASE( Example ) {
        auto res = problems::problem72::solve(8);
        BOOST_CHECK_EQUAL(res, 21);
    }

    BOOST_AUTO_TEST_CASE( Solution ) {
        auto res = problems::problem72::solve();
        BOOST_CHECK_EQUAL(res, 303963552391);
    }

BOOST_AUTO_TEST_SUITE_END()


// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm

#ifndef __BOUNDEDVALUE__
#define __BOUNDEDVALUE__

#include <array>
#include <memory>
#include <Eigen/Dense>

namespace VideoStitch {
namespace Calibration {

/**
@brief A bounded value is a value (real scalar) which is forced to lie on a bounded domain.
@details We use a 2D rotation matrix. This matrix is the "optimized" content.
@details This rotation matrix rotates the vector (0; 1).
@details Keeping only the X value, the initial domain is [-1;1].
@details This is then scaled and shifted so the final domain is [min;max]
*/
class BoundedValue {
 public:
  BoundedValue();
  virtual ~BoundedValue();

  /**
  @brief Returns whether the BoundedValue is constant
  */
  bool isConstant() const;

  /**
  @brief Set bounds to be min and max
  @param min the minimal allowed value
  @param max the maximal allowed value
  */
  void setBounds(double min, double max);

  /**
  @brief Estimate the double scalar from the matrix
  @return estimated value
  */
  double getValue() const;

  /**
  @brief Jacobian of value wrt matrix
  @param J the jacobian updated
  */
  void getJacobian(Eigen::Matrix<double, 1, 4> &J) const;

  /**
  @brief Update the rotation matrix so that the estimated value is val
  @param val the updated value
  */
  void setValue(double val);

  /**
  @brief Retrieve the content of the rotation matrix
  @return pointer to rotation matrix
  */
  double *getMinimizerPtr() const;

  /**
  @brief Update the content of the rotation matrix
  @param ptr the rotation matrix content to use
  */
  void setMinimizerValues(const double *ptr);

  /**
  @brief Tie the bounded value to another one (i.e. will share the underlying objects)
  @param other the other bounded value to be tied to
  */
  void tieTo(const BoundedValue &other);

  /**
  @brief Untie the bounded value (i.e. will have its own values independent from other objects)
  */
  void untie();

 private:
  double shift;
  double scale;
  std::shared_ptr<std::array<double, 4> > modifier;
};

}  // namespace Calibration
}  // namespace VideoStitch

#endif


//=======================================================================
// Copyright (c)
//
// 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)
//=======================================================================
/**
 *
 * @file n_queens_example.cpp
 * @brief
 * @author Piotr Wygocki
 * @version 1.0
 * @date 2014-01-02
 */

#include "paal/local_search/n_queens/n_queens_local_search.hpp"

#include <boost/range/algorithm_ext/iota.hpp>
#include <boost/range/algorithm/random_shuffle.hpp>

void print(const std::vector<int> &queens) {
    for (int q : queens) {
        for (int i = 0; i < q; ++i) {
            std::cout << "-";
        }
        std::cout << "x";
        for (int i = 0; i < int(queens.size()) - q - 1; ++i) {
            std::cout << "-";
        }
        std::cout << std::endl;
    }
}

int main() {
    namespace ls = paal::local_search;

    // creating initial solution
    std::vector<int> queens(9);
    boost::iota(queens, 0);
    boost::random_shuffle(queens);

    // print before
    std::cout << "start configuration" << std::endl;
    print(queens);

    // local search
    ls::n_queens_local_search_components<> comps;
    ls::n_queens_solution_first_improving(queens, comps);

    // print after
    std::cout << "final configuration" << std::endl;
    print(queens);
}


/**
 * \file dcs/math/random/uniform_real_adaptor.hpp
 *
 * \brief Adaptor for generating random numbers in [0,1] from a base generator.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 * <hr/>
 *
 * Copyright 2009 Marco Guazzone (marco.guazzone@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef DCS_MATH_RANDOM_UNIFORM_REAL_ADAPTOR_HPP
#define DCS_MATH_RANDOM_UNIFORM_REAL_ADAPTOR_HPP

#include <dcs/detail/config/boost.hpp>

#if !DCS_DETAIL_CONFIG_BOOST_CHECK_VERSION(101500) // 1.15
#	error "Required Boost library version >= 1.15"
#endif // DCS_DETAIL_CONFIG_BOOST_CHECK_VERSION

#include <boost/random/uniform_real_distribution.hpp>
#include <dcs/math/random/base_generator.hpp>
#include <dcs/type_traits/remove_reference.hpp>
#include <dcs/util/holder.hpp>
#include <limits>

namespace dcs { namespace math { namespace random {

/**
 * \brief Adaptor for generating random numbers uniformly distributed in a real
 *  interval from a base random number generator.
 *
 * \tparam BaseRandomGeneratorT The base random number generator type.
 * \tparam RealT The result type.
 *
 * Wraps a random number generator of type \a BaseGeneratorT for generating
 * random numbers uniformly distributed in real interval.
 * Random numbers are generated according the algorithm provided by
 * \a BaseRandomGeneratorT.
 *
 * \todo Make it a derived class of base_generator.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 */
template <typename BaseRandomGeneratorT, typename RealT>
class uniform_real_adaptor: public base_generator<RealT>
{
	private: typedef base_generator<RealT> base_type;
    public: typedef BaseRandomGeneratorT base_engine_type;
    public: typedef typename ::dcs::type_traits::remove_reference<BaseRandomGeneratorT>::type::result_type input_type;
    public: typedef typename base_type::result_type result_type;
    public: typedef typename base_type::ulonglong_type ulonglong_type;
    private: typedef ::boost::random::uniform_real_distribution<result_type> adaptor_impl_type;

    public: explicit uniform_real_adaptor(result_type min_arg = 0.0, result_type max_arg = 1.0)
        : base_type(),
		  rng_(),
		  impl_(min_arg, max_arg)
//		  min_(min_arg),
//		  max_(max_arg)
    {
		// empty
    }

	/// Seed constructor.
    public: uniform_real_adaptor(input_type seed, result_type min_arg, result_type max_arg)
        : base_type(),
		  rng_(seed),
		  impl_(min_arg, max_arg)
//		  min_(min_arg),
//		  max_(max_arg)
    {
		// empty
    }

	/// Seed constructor.
    public: uniform_real_adaptor(input_type seed)
        : base_type(),
		  rng_(seed),
		  impl_()
    {
//		min_ = static_cast<result_type>((rng_.min)());
//		max_ = static_cast<result_type>((rng_.max)());
    }

	/// Copy constructor.
    public: uniform_real_adaptor(uniform_real_adaptor const& that)
        : base_type(that),
		  rng_(that.rng_),
		  impl_(that.impl_)
//		  min_(that.min_),
//		  max_(that.max_)
    {
		// empty
    }

	/// A Constructor: copy the base generator.
	public: uniform_real_adaptor(base_engine_type rng, result_type min_arg, result_type max_arg)
		: base_type(),
		  rng_(rng),
		  impl_(min_arg, max_arg)
//		  min_(min_arg),
//		  max_(max_arg)
	{
		// empty
	}

	/// A Constructor: copy the base generator.
	public: uniform_real_adaptor(base_engine_type rng)
		: base_type(),
		  rng_(rng),
		  impl_()
//		  min_((rng.min)()),
//		  max_((rng.max)())
	{
		// empty
	}

// Support of reference-to-refernce qualifier is only available from C++0x.
#if __cplusplus >= 201103L

	/// A constructor: move the base generator.
    //public: uniform_real_adaptor(base_engine_type&& rng)
    public: uniform_real_adaptor(base_engine_type& rng, result_type min_arg, result_type max_arg)
        : base_type(),
		  rng_(rng),
		  impl_(min_arg, max_arg)
//		  min_(min_arg),
//		  max_(max_arg)
    {
		// empty
    }

	/// A constructor: move the base generator.
    //public: uniform_real_adaptor(base_engine_type&& rng)
    public: uniform_real_adaptor(base_engine_type& rng)
        : base_type(),
		  rng_(rng),
		  impl_()
//		  min_((rng.min)()),
//		  max_((rng.max)())
    {
		// empty
    }

#else

	/// A constructor: move the base generator.
    public: uniform_real_adaptor(::dcs::util::holder<base_engine_type>& rng, result_type min_arg, result_type max_arg)
        : base_type(),
		  rng_(rng),
		  impl_(min_arg, max_arg)
//		  min_(min_arg),
//		  max_(max_arg)
    {
		// empty
    }

	/// A constructor: move the base generator.
    public: uniform_real_adaptor(::dcs::util::holder<base_engine_type>& rng)
        : base_type(),
		  rng_(rng),
		  impl_()
//		  min_((rng.min)()),
//		  max_((rng.max)())
    {
		// empty
    }

#endif

	public: base_engine_type base() const
	{
		return rng_;
	}

    private: result_type do_generate()
    {
//		result_type factor;
//		result_type result;
//
//		do
//		{
//			factor = (max_-min_)
//					 / (
//							static_cast<result_type>(
//							(rng_.max)()-(rng_.min)()
//						)
//						+ static_cast<result_type>(
//							::std::numeric_limits<input_type>::is_integer
//							? 1
//							: 0
//						)
//			);
//			result = static_cast<result_type>(rng_()-(rng_.min)()) * factor + min_;
//		}
//		while (result >= max_);
//
//		return result;

		return impl_(rng_);
    }

	private: void do_seed()
	{
		this->rng_.seed();
	}

	private: void do_seed(result_type s)
	{
		rng_.seed(s);
	}

	private: void do_discard(ulonglong_type z)
	{
		while (z--)
		{
			rng_();
		}
	}

	private: result_type do_min() const
	{
		return impl_.min();
	}

	private: result_type do_max() const
	{
		return impl_.max();
	}

    private: base_engine_type rng_;
	private: adaptor_impl_type impl_;
};

// Template specialization for avoid auto-wrapping (i.e., when the base
// generator is itself a uniform_real_adaptor)
template <typename RandomNumberGeneratorT, typename RealT>
class uniform_real_adaptor< uniform_real_adaptor<RandomNumberGeneratorT,RealT>, RealT >: public uniform_real_adaptor<RandomNumberGeneratorT,RealT>
{
    public: typedef RandomNumberGeneratorT base_engine_type;
    public: typedef typename ::dcs::type_traits::remove_reference<RandomNumberGeneratorT>::type::result_type input_type;
    public: typedef RealT result_type;
};

}}} // Namespace dcs::math::random

#endif // DCS_MATH_RANDOM_UNIFORM_REAL_ADAPTOR_HPP


//==================================================================================================
/*!

  Copyright 2015 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#include <boost/simd/function/scalar/remquo.hpp>
#include <simd_test.hpp>
#include <boost/dispatch/meta/as_integer.hpp>
#include <boost/simd/constant/inf.hpp>
#include <boost/simd/constant/minf.hpp>
#include <boost/simd/constant/mone.hpp>
#include <boost/simd/constant/nan.hpp>
#include <boost/simd/constant/one.hpp>
#include <boost/simd/constant/zero.hpp>
#include <utility>

#ifndef STF_NO_INVALIDS
STF_CASE_TPL(" remquo invalid", STF_IEEE_TYPES)
{
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;
  using bs::remquo;

  using iT =  bd::as_integer_t<T,signed>;

  STF_EXPR_IS( (remquo(T(), T()))
                  , (std::pair<T,iT>)
                  );

  T inf_  = bs::Inf<T>();
  T nan_  = bs::Nan<T>();
  T zero_ = bs::Zero<T>();
  T one_  = bs::One<T>();

  {
    // n is unspecified by the standard so we don't test it
    iT n;
    T  r;

    remquo(one_,nan_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(one_,inf_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(one_,zero_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(inf_,zero_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(nan_,zero_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(nan_,one_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(nan_,nan_, r, n);
    STF_IEEE_EQUAL(r, nan_);

    remquo(nan_,inf_, r, n);
    STF_IEEE_EQUAL(r, nan_);
  }

  {
    // n is unspecified by the standard so we don't test it
    iT n;
    T  r;

    r = remquo(one_,nan_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(one_,inf_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(one_,zero_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(inf_,zero_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(nan_,zero_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(nan_,one_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(nan_,nan_, n);
    STF_IEEE_EQUAL(r, nan_);

    r = remquo(nan_,inf_, n);
    STF_IEEE_EQUAL(r, nan_);
  }

  {
    // n is unspecified by the standard so we don't test it
    std::pair<T,iT> p;

    p =  remquo(one_,nan_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(one_,inf_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(one_,zero_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(inf_,zero_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(nan_,zero_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(nan_,one_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(nan_,nan_);
    STF_IEEE_EQUAL(p.first, nan_);

    p =  remquo(nan_,inf_);
    STF_IEEE_EQUAL(p.first, nan_);
  }
}
#endif

STF_CASE_TPL(" remquo valid", STF_IEEE_TYPES)
{
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;
  using bs::remquo;

  using iT =  bd::as_integer_t<T,signed>;

  STF_EXPR_IS( (remquo(T(), T()))
                  , (std::pair<T,iT>)
                  );

  T a0[] = { T(1), T(2), T(3), T(4.5) };
  T a1[] = { T(2), T(1), T(7), T(3.2) };

  std::size_t nb = sizeof(a0)/sizeof(T);

  {
    iT n;
    T  r;

    for(std::size_t i=0;i<nb;++i)
    {
      remquo(a0[i],a1[i], r, n);
      STF_EQUAL(n, iT(a0[i] / a1[i]));
      STF_EQUAL(r, a0[i] - n*a1[i]);
    }
  }

  {
    iT n;
    T  r;

    for(std::size_t i=0;i<nb;++i)
    {
      r = remquo(a0[i],a1[i], n);
      STF_EQUAL(n, iT(a0[i] / a1[i]));
      STF_EQUAL(r, a0[i] - n*a1[i]);
    }
  }

  {

    std::pair<T,iT> p;

    for(std::size_t i=0;i<nb;++i)
    {
      p = remquo(a0[i],a1[i]);
      STF_EQUAL(p.second, iT(a0[i] / a1[i]));
      STF_EQUAL(p.first, a0[i] - p.second*a1[i]);
    }
  }
}


//---------------------------------------------------------------------------//
//!
//! \file   tstInverseAreaConversion.cpp
//! \author Alex Robinson
//! \brief  The inverse area conversion unit tests
//!
//---------------------------------------------------------------------------//

// Boost Includes
#include <boost/units/quantity.hpp>

// Trilinos Includes
#include <Teuchos_UnitTestHarness.hpp>

// FRENSIE Includes
#include "Utility_InverseSquareAngstromUnit.hpp"
#include "Utility_InverseSquareCentimeterUnit.hpp"

using namespace Utility::Units;
using boost::units::quantity;

//---------------------------------------------------------------------------//
// Tests
//---------------------------------------------------------------------------//
// Check that the inverse area units can be converted
TEUCHOS_UNIT_TEST( InverseAreaConversion, convert )
{
  quantity<InverseSquareAngstrom>
    inverse_sqr_angstrom( 1.0*inverse_square_centimeter );

  quantity<InverseSquareCentimeter>
    inverse_sqr_centimeter( 1.0*inverse_square_angstrom );

  TEST_FLOATING_EQUALITY( inverse_sqr_angstrom.value(), 1e-16, 1e-15 );
  TEST_FLOATING_EQUALITY( inverse_sqr_centimeter.value(), 1e16, 1e-15 );
}

//---------------------------------------------------------------------------//
// end tstInverseAreaConversion.cpp
//---------------------------------------------------------------------------//


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

namespace boost { namespace simd { namespace tag
  {
   /*!
     @brief is_odd generic tag

     Represents the is_odd function in generic contexts.

     @par Models:
        Hierarchy
   **/
    struct is_odd_ : ext::elementwise_<is_odd_>
    {
      /// @brief Parent hierarchy
      typedef ext::elementwise_<is_odd_> parent;
      template<class... Args>
      static BOOST_FORCEINLINE BOOST_AUTO_DECLTYPE dispatch(Args&&... args)
      BOOST_AUTO_DECLTYPE_BODY( dispatching_is_odd_( ext::adl_helper(), static_cast<Args&&>(args)... ) )
    };}
  namespace ext
  {
   template<class Site>
   BOOST_FORCEINLINE generic_dispatcher<tag::is_odd_, Site> dispatching_is_odd_(adl_helper, boost::dispatch::meta::unknown_<Site>, ...)
   {
     return generic_dispatcher<tag::is_odd_, Site>();
   }
   template<class... Args>
   struct impl_is_odd_;
  }
  /*!
    Returns True or False according a0 is odd or not.

    @par Semantic:

    @code
    logical<T> r = is_odd(a0);
    @endcode

    is similar to:

    @code
    logical<T> r = (abs(a0)/2)*2 == abs(a0)-1;
    @endcode

    @par Note:

    A floating number a0 is odd if a0-1 is even

    @param a0

    @return a logical value
  **/
  BOOST_DISPATCH_FUNCTION_IMPLEMENTATION(tag::is_odd_, is_odd, 1)
} }

#endif


/**
 * @file
 * @license BSD 3-clause
 * @copyright Copyright (c) 2020, New York University and Max Planck
 * Gesellschaft
 *
 * @brief Implements the "Walking Control Based on Step Timing Adaptation" foot
 * trajectory QP. The pdf can be found in https://arxiv.org/abs/1704.01271, and
 * in the `doc/` folder in this repository.
 */

#pragma once

#include <eigen-quadprog/QuadProg.h>
#include <Eigen/Eigen>

namespace reactive_planners
{
/**
 * @brief
 */
class PolynomialEndEffectorTrajectory
{
    /*
     * Private methods
     */
public:
    /** @brief Constructor. */
    PolynomialEndEffectorTrajectory();

    /** @brief Destructor. */
    ~PolynomialEndEffectorTrajectory();

    bool compute(const Eigen::Ref<const Eigen::Vector3d> &start_pose,
                 const Eigen::Ref<const Eigen::Vector3d> &current_pose,
                 const Eigen::Ref<const Eigen::Vector3d> &current_velocity,
                 const Eigen::Ref<const Eigen::Vector3d> &current_acceleration,
                 const Eigen::Ref<const Eigen::Vector3d> &target_pose,
                 const double &start_time,
                 const double &current_time,
                 const double &end_time);

    void get_next_state(const double &next_time,
                        Eigen::Ref<Eigen::Vector3d> next_pose,
                        Eigen::Ref<Eigen::Vector3d> next_velocity,
                        Eigen::Ref<Eigen::Vector3d> next_acceleration);

    /** @brief Display the matrices of the Problem. */
    void print_solver() const;

    /** @brief Convert the inner data to a string format. */
    std::string to_string() const;

    /*
     * Getters
     */

    /** @brief Get the height of the flying foot. */
    double get_mid_air_height()
    {
        return mid_air_height_;
    }

    /** @brief Get the last end time taken into account during the foot
     * trajectory computation. */
    double get_last_end_time_taken_into_account()
    {
        return last_end_time_seen_;
    }

    /*
     * Setters
     */

    /** @brief Set the height of the flying foot.
     *
     * @param mid_air_height
     */
    void set_mid_air_height(double mid_air_height)
    {
        mid_air_height_ = mid_air_height;
    }
    /** @brief Set the costs of x, y, z axes, and hessian regularization.
     *
     * @param cost_x
     * @param cost_y
     * @param cost_z
     * @param hess_regularization
     */
    void set_costs(double cost_x,
                   double cost_y,
                   double cost_z,
                   double hess_regularization)
    {
        cost_x_ = cost_x;
        cost_y_ = cost_y;
        cost_z_ = cost_z;
        Q_regul_ =
            Eigen::MatrixXd::Identity(nb_var_, nb_var_) * hess_regularization;
    }
    /*
     * Private methods
     */
private:
    /**
     * @brief Compute the time vector: \f$ [1, t, ..., t^{ORDER}] \f$.
     *
     * @param time
     * @param time_vec
     */
    void t_vec(const double &time, Eigen::VectorXd &time_vec)
    {
        time_vec(0) = 1.0;
        for (int i = 1; i < time_vec.size(); ++i)
        {
            time_vec(i) = std::pow(time, i);
        }
    }

    /**
     * @brief Compute the time vector first derivative.
     *
     * \f[ t_vec =  [0, 1, 2*t, ..., ORDER * t^{ORDER-1}] \f]
     *
     * @param time
     * @param time_vec
     */
    void dt_vec(const double &time, Eigen::VectorXd &time_vec)
    {
        time_vec(0) = 0.0;
        time_vec(1) = 1.0;
        for (int i = 2; i < time_vec.size(); ++i)
        {
            double id = i;
            time_vec(i) = id * std::pow(time, i - 1);
        }
    }

    /**
     * @brief Compute the time vector second derivative:
     *
     * \f[ t_vec =  [0, 0, 2, 3*2*t..., ORDER * (ORDER-1) * t^{ORDER-2}] \f]
     *
     * @param time
     * @param time_vec
     */
    void ddt_vec(const double &time, Eigen::VectorXd &time_vec)
    {
        time_vec(0) = 0.0;
        time_vec(1) = 0.0;
        time_vec(2) = 2.0;
        for (int i = 3; i < time_vec.size(); ++i)
        {
            double id = i;
            time_vec(i) = id * (id - 1.0) * std::pow(time, i - 2);
        }
    }

    /*
     * Attributes
     */
private:
    /*
     * Constant problem parameters.
     */

    /** @brief Flying foot apex to be reach mid-air. */
    double mid_air_height_;

    /** @brief Number of the polynome coefficient for the trajectory on the
     * X-axis. */
    int nb_var_x_;

    /** @brief Number of the polynome coefficient for the trajectory on the
     * Y-axis. */
    int nb_var_y_;

    /** @brief Number of the polynome coefficient for the trajectory on the
     * Z-axis. */
    int nb_var_z_;

    /*
     * Variable problem parameters.
     */

    /** @brief Time vector used to compute X(t). */
    Eigen::VectorXd time_vec_x_;

    /** @brief Time vector used to compute Y(t). */
    Eigen::VectorXd time_vec_y_;

    /** @brief Time vector used to compute Z(t). */
    Eigen::VectorXd time_vec_z_;

    /** @brief Initial position before the motion. */
    Eigen::Vector3d start_pose_;

    /** @brief Current position. */
    Eigen::Vector3d current_pose_;

    /** @brief Previous computed position from the QP. */
    Eigen::Vector3d previous_solution_pose_;

    /** @brief Current velocity. */
    Eigen::Vector3d current_velocity_;

    /** @brief Current acceleration. */
    Eigen::Vector3d current_acceleration_;

    /** @brief Target pose after the motion. */
    Eigen::Vector3d target_pose_;

    /** @brief Initial time. */
    double start_time_;

    /** @brief Current time. */
    double current_time_;

    /** @brief Final time and the end of the motion. */
    double end_time_;

    /** @brief Last end time register when we computed the QP. */
    double last_end_time_seen_;

    /*
     * QP variables
     */

    /** @brief Number of variabes in the optimization problem. */
    int nb_var_;

    /** @brief Number of equality constraints in the optimization problem. */
    int nb_eq_;

    /** @brief Number of inequality in the optimization problem. */
    int nb_ineq_;

    /** @brief Quadratic program solver.
     *
     * This is an eigen wrapper around the quad_prog fortran solver.
     */
    Eigen::QuadProgDense qp_solver_;

    /** @brief Solution of the optimization problem.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::VectorXd x_opt_;

    /** @brief Lower Bound on the solution of the optimization problem.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::VectorXd x_opt_lb_;

    /** @brief Upper Bound on the solution of the optimization problem.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::VectorXd x_opt_ub_;

    /** @brief Quadratic term of the quadratic cost.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::MatrixXd Q_;

    /** @brief Quadratic term added to the quadratic cost in order regularize
     * the system.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::MatrixXd Q_regul_;

    /** @brief Cost weights for the X-axis. */
    double cost_x_;

    /** @brief Cost weights for the Y-axis. */
    double cost_y_;

    /** @brief Cost weights for the Z-axis. */
    double cost_z_;

    /** @brief Linear term of the quadratic cost.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::VectorXd q_;

    /** @brief Linear equality matrix.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::MatrixXd A_eq_;

    /** @brief Linear equality vector.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::VectorXd B_eq_;

    /** @brief Linear inequality matrix.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::MatrixXd A_ineq_;

    /** @brief Linear inequality vector.
     * @see PolynomialEndEffectorTrajectory */
    Eigen::VectorXd B_ineq_;
};

}  // namespace reactive_planners


/*
 * PACDEncrypter.cpp
 *
 *  Created on: 25 Jun 2018
 *      Author: scsjd
 */

#include "PolyACDEncrypter.h"

#include <NTL/ZZ.h>
#include <NTL/ZZX.h>
#include <jsoncpp/json/json.h>
#include <string>
#include <sstream>

/*
 * \param lambda the bit length of k1
 * \param mu the size of the polynomial coefficients in bits
 * \param the degree of the polynomial k2
 */
PolyACDEncrypter::PolyACDEncrypter(int lambda, int mu, int d) {
	this->mu = mu;
	RandomLen(k1,lambda);
	k2.SetLength(d+1);
	for(int i =0; i < d; i++){
		NTL::ZZ tmp;
		RandomBits(tmp,mu);
		SetCoeff(k2,i,tmp);
	}
	SetCoeff(k2,d,1);
}

PolyACDEncrypter::PolyACDEncrypter(int mu, std::string& secrets) {
	this->mu = mu;
	Json::Value root;   // will contains the root value after parsing.
	Json::Reader reader;
	bool parsingSuccessful = reader.parse(secrets,root);
	if (parsingSuccessful){
		std::istringstream k1buf(root["k1"].asString());
		k1buf >> k1;
		std::istringstream k2buf(root["k2"].asString());
		k2buf >> k2;
	}
}

PolyACDEncrypter::~PolyACDEncrypter() {
}

/*
 * Converts the key k1 (a large integer) to a string and k2 (a polynomial) to an array of strings, then writes JSON string
 */
std::string PolyACDEncrypter::writeSecretsToJSON(){
	Json::Value root;
	std::ostringstream k1buf;
	k1buf << k1;
	root["k1"]= k1buf.str();
	std::ostringstream k2buf;
	k2buf << k2;
	root["k2"]= k2buf.str();
	Json::FastWriter writer;
	return writer.write(root);
}

NTL::ZZX PolyACDEncrypter::encrypt(NTL::ZZX& plaintext){
	NTL::ZZX p = k2*plaintext;
	long degree = deg(p);
	NTL::ZZ m_n = LeadCoeff(plaintext);
	NTL::ZZX p2;
	p2.SetLength(degree-1);
	for (int i = 0; i < degree-1; i++){
		SetCoeff(p2,i,NTL::coeff(p,i));
	}
	SetCoeff(p2,degree-1,p[degree-1]+k1*m_n);
	NTL::ZZX r;
	long d = deg(k2);
	r.SetLength(d-1);
	for(int i =0; i < d; i++){
		NTL::ZZ tmp;
		RandomBits(tmp,mu);
		SetCoeff(r,i,tmp);
	}
	return p2+r;
}

NTL::ZZX PolyACDEncrypter::encrypt(NTL::vec_ZZ& plaintext){
	NTL::ZZX ptext = to_ZZX(plaintext);
	return encrypt(ptext);
}

std::pair<NTL::ZZ,NTL::ZZX> PolyACDEncrypter::getKey(){
	return (std::pair<NTL::ZZ,NTL::ZZX>(k1,k2));
}


// Persistent Homology code by Hubert Wagner based on an implementation by Chao Chen
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <deque>
#include <cstring>
#include <ctime>
#include <blitz/array.h>
#include <blitz/tinyvec-et.h>

using namespace std;

const int BIG_INT = 0x7FFFFFFF;	//be careful, could be too small compared to # of cubes

// python thingy
#include <pybind11/pybind11.h>

namespace py = pybind11;

#include <pybind11/stl.h>

// std::vector<std::vector<double> > kw_func4(std::vector<std::vector<double> > &entries) {
//     std::vector<std::vector<double> > try_vec(2);
//     std::cout << "kw_func4: " << std::endl;
//     for (std::vector<double> i : entries){
//         for (double j : i){
//             std::cout << j << " ";
//             try_vec[0].push_back(j);
//             try_vec[1].push_back(j*j);
//         }
//         std::cout << endl;
//     }
//     return try_vec;
// }
//

std::vector<std::vector<double> > TreeShift(std::vector< double > &entries, std::vector<int> dims, double thd, int delta, bool verbose_mode ) {

        int dim = dims.size();
        assert(dim <= 2);
        assert(dim > 0);
        if (dim < 2)
            dims.append(1);

        std::vector<std::vector< double > > ret(dim[0] std::vector<double>(dim[1]));

        int counter = 0;
        if  (verbose_mode){
            cout << " thd = " << thd << endl;
            cout << " delta = " << delta << endl;
            cout << " verbose = " << verbose_mode << endl;
            cout << " matrix size = " << dims[0] << " X " << dims[1] << endl;
            cout << "Matrix: " << endl;
            counter = 0;
            for(int i = 0; i < dims[0]; ++i){
                for(int j = 0; j < dims[1]; ++j){
                    cout << entries[counter++];
                }
            }
	    cout << "All calculations computed !" << endl;
        }

            counter = 0;
            for(int i = 0; i < dims[0]; ++i){
                for(int j = 0; j < dims[1]; ++j){
                    ret[i][j] = entries[counter++];
	return ret;
}

PYBIND11_PLUGIN(TreeShiftPython) {
        py::module m("TreeShiftPython", "python binding for tree shift algorithm");

//    m.def("kw_func4", &kw_func4, py::arg("myList") = list);
    m.def("TreeShift", &TreeShift);
    return m.ptr();
}


/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb
 Copyright (C) 2005, 2006 StatPro Italia srl
 Copyright (C) 2015 Peter Caspers

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <http://quantlib.org/license.shtml>.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

/*! \file timegrid.hpp
    \brief discrete time grid
*/

#ifndef quantlib_time_grid_hpp
#define quantlib_time_grid_hpp

#include <ql/errors.hpp>
#include <ql/math/comparison.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_float.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <vector>
#include <numeric>

namespace QuantLib {

    //! time grid class
    class TimeGrid {
      public:
        //! \name Constructors
        //@{
        TimeGrid() {}
        //! Regularly spaced time-grid
        TimeGrid(Time end, Size steps, Time start = 0.0);
        //! Time grid with mandatory time points
        /*! Mandatory points are guaranteed to belong to the grid.
            No additional points are added.
        */
        template <class Iterator>
        TimeGrid(Iterator begin, Iterator end)
            : mandatoryTimes_(begin, end) {
            initialize(begin, end, 0.0);
        }
        template <class Iterator, class T>
        TimeGrid(Iterator begin, Iterator end, T start,
                 typename boost::enable_if<boost::is_float<T> >::type* = 0)
            : mandatoryTimes_(begin, end) {
            initialize(begin, end, start);
        }
        //! Time grid with mandatory time points
        /*! Mandatory points are guaranteed to belong to the grid.
            Additional points are then added with regular spacing
            between pairs of mandatory times in order to reach the
            desired number of steps.
        */
        template <class Iterator, class T>
        TimeGrid(Iterator begin, Iterator end, T steps, Time start = 0.0,
                 typename boost::enable_if<boost::is_integral<T> >::type* = 0)
            : mandatoryTimes_(begin, end) {
            initialize(begin, end, steps, start);
        }
        //@}
        //! \name Time grid interface
        //@{
        //! returns the index i such that grid[i] = t
        Size index(Time t) const;
        //! returns the index i such that grid[i] is closest to t
        Size closestIndex(Time t) const;
        //! returns the time on the grid closest to the given t
        Time closestTime(Time t) const {
            return times_[closestIndex(t)];
        }
        const std::vector<Time>& mandatoryTimes() const {
            return mandatoryTimes_;
        }
        Time dt(Size i) const { return dt_[i]; }
        //@}
        //! \name sequence interface
        //@{
        typedef std::vector<Time>::const_iterator const_iterator;
        typedef std::vector<Time>::const_reverse_iterator
                                          const_reverse_iterator;

        Time operator[](Size i) const { return times_[i]; }
        Time at(Size i) const { return times_.at(i); }
        Size size() const { return times_.size(); }
        bool empty() const { return times_.empty(); }
        const_iterator begin() const { return times_.begin(); }
        const_iterator end() const { return times_.end(); }
        const_reverse_iterator rbegin() const { return times_.rbegin(); }
        const_reverse_iterator rend() const { return times_.rend(); }
        Time front() const { return times_.front(); }
        Time back() const { return times_.back(); }
        //@}
      private:
        template <class Iterator>
        void initialize(Iterator begin, Iterator end, Time start);
        template <class Iterator>
        void initialize(Iterator begin, Iterator end, Size steps, Time start);
        std::vector<Time> times_;
        std::vector<Time> dt_;
        std::vector<Time> mandatoryTimes_;
    };

    template <class Iterator>
    void TimeGrid::initialize(Iterator begin, Iterator end, Time start) {
        std::sort(mandatoryTimes_.begin(), mandatoryTimes_.end());
        QL_REQUIRE(mandatoryTimes_.front() >= start,
                   "times (" << mandatoryTimes_.front() << ") less than start ("
                             << start << ") not allowed");
        std::vector<Time>::iterator e =
            std::unique(mandatoryTimes_.begin(), mandatoryTimes_.end(),
                        std::ptr_fun(close_enough));
        mandatoryTimes_.resize(e - mandatoryTimes_.begin());

        if (mandatoryTimes_[0] > start)
            times_.push_back(start);

        times_.insert(times_.end(), mandatoryTimes_.begin(),
                      mandatoryTimes_.end());

        std::adjacent_difference(times_.begin() + 1, times_.end(),
                                 std::back_inserter(dt_));
    }

    template <class Iterator>
    void TimeGrid::initialize(Iterator begin, Iterator end, Size steps, Time start) {
        std::sort(mandatoryTimes_.begin(), mandatoryTimes_.end());
        QL_REQUIRE(mandatoryTimes_.front() >= start,
                   "times less than start (" << start << ") not allowed");
        std::vector<Time>::iterator e =
            std::unique(mandatoryTimes_.begin(), mandatoryTimes_.end(),
                        std::ptr_fun(close_enough));
        mandatoryTimes_.resize(e - mandatoryTimes_.begin());

        Time last = mandatoryTimes_.back();
        Time dtMax;
        // The resulting timegrid have points at times listed in the input
        // list. Between these points, there are inner-points which are
        // regularly spaced.
        if (steps == 0) {
            std::vector<Time> diff;
            std::adjacent_difference(mandatoryTimes_.begin(),
                                     mandatoryTimes_.end(),
                                     std::back_inserter(diff));
            if (diff.front() == 0.0)
                diff.erase(diff.begin());
            dtMax = *(std::min_element(diff.begin(), diff.end()));
        } else {
            dtMax = (last - start) / steps;
        }

        Time periodBegin = start;
        times_.push_back(periodBegin);
        for (std::vector<Time>::const_iterator t = mandatoryTimes_.begin();
             t < mandatoryTimes_.end(); t++) {
            Time periodEnd = *t;
            if (periodEnd != start) {
                // the nearest integer
                Size nSteps = Size((periodEnd - periodBegin) / dtMax + 0.5);
                // at least one time step!
                nSteps = (nSteps != 0 ? nSteps : 1);
                Time dt = (periodEnd - periodBegin) / nSteps;
                times_.reserve(times_.size() + nSteps);
                for (Size n = 1; n <= nSteps; ++n)
                    times_.push_back(periodBegin + n * dt);
            }
            periodBegin = periodEnd;
        }

        std::adjacent_difference(times_.begin() + 1, times_.end(),
                                 std::back_inserter(dt_));
    }

} // namespace QuantLib

#endif


/*
Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/)
Copyright 2017-2019 University of Huddersfield.
Licensed under the BSD-3 License.
See license.md file in the project root for full license information.
This project has received funding from the European Research Council (ERC)
under the European Union’s Horizon 2020 research and innovation programme
(grant agreement No 725899).
*/

#pragma once

#include "WindowFuncs.hpp"
#include "../util/AlgorithmUtils.hpp"
#include "../util/ConvolutionTools.hpp"
#include "../util/FFT.hpp"
#include "../util/FluidEigenMappings.hpp"
#include "../util/PartialTracking.hpp"
#include "../util/PeakDetection.hpp"
#include "../../data/FluidIndex.hpp"
#include "../../data/TensorTypes.hpp"
#include <Eigen/Core>
#include <cmath>
#include <queue>

namespace fluid {
namespace algorithm {

class SineExtraction
{
  using ArrayXd = Eigen::ArrayXd;
  using VectorXd = Eigen::VectorXd;
  using ArrayXcd = Eigen::ArrayXcd;
  template <typename T>
  using vector = std::vector<T>;

public:
  void init(index windowSize, index fftSize, index transformSize)
  {
    mBins = fftSize / 2 + 1;
    mCurrentFrame = 0;
    mBuf = std::queue<ArrayXcd>();
    mScale = 1.0 / (windowSize / 4.0); // scale to original amplitude
    computeWindowTransform(windowSize, transformSize);
    mTracking.init();
    mWindowBinIncr = mWindowTransform.size() / (mBins - 1) / 2;
    mInvWindowBinIncr = 1.0 / mWindowBinIncr;
    mInitialized = true;
  }

  void processFrame(const ComplexVectorView in, ComplexMatrixView out,
                    double sampleRate, double detectionThreshold,
                    index minTrackLength, double birthLowThreshold,
                    double birthHighThreshold, index trackMethod, double zetaA,
                    double zetaF, double delta, index bandwidth)
  {
    assert(mInitialized);
    using namespace Eigen;
    index    fftSize = 2 * (mBins - 1);
    ArrayXcd frame = _impl::asEigen<Array>(in);
    if (minTrackLength != mTracking.minTrackLength())
    { mBuf = std::queue<ArrayXcd>(); }
    mBuf.push(frame);
    ArrayXd mag = frame.abs().real();
    mag = mag * mScale;
    ArrayXd          logMag = 20 * mag.max(epsilon).log10();
    vector<SinePeak> peaks;
    auto tmpPeaks = mPeakDetection.process(logMag, 0, -infinity, true, false);
    for (auto p : tmpPeaks)
    {
      if (p.second > detectionThreshold)
      {
        double hz = sampleRate * p.first / fftSize;
        peaks.push_back({hz, p.second, false});
      }
    }
    double maxAmp = 20 * std::log10(mag.maxCoeff());
    mTracking.processFrame(peaks, maxAmp, minTrackLength, birthLowThreshold,
                           birthHighThreshold, trackMethod, zetaA, zetaF,
                           delta);
    vector<SinePeak> sinePeaks = mTracking.getActivePeaks();
    ArrayXd          frameSines = ArrayXd::Zero(mBins);
    for (auto& p : sinePeaks)
    { frameSines += synthesizePeak(p, sampleRate, bandwidth); }
    ArrayXXcd result(mBins, 2);
    if (asSigned(mBuf.size()) <= mTracking.minTrackLength())
    {
      result.col(0) = ArrayXd::Zero(mBins);
      result.col(1) = ArrayXd::Zero(mBins);
    }
    else
    {
      ArrayXcd resultFrame = mBuf.front();
      ArrayXd  resultMag = resultFrame.abs().real();
      for (index i = 0; i < mBins; i++)
      {
        if (frameSines(i) >= resultMag(i))
        {
          result(i, 0) = resultFrame(i);
          result(i, 1) = 0;
        }
        else
        {
          double sineWeight = frameSines(i) / resultMag(i);
          result(i, 0) = resultFrame(i) * sineWeight;
          result(i, 1) = resultFrame(i) * (1 - sineWeight);
        }
      }
      mBuf.pop();
    }
    mTracking.prune();
    out <<= _impl::asFluid(result);
    mCurrentFrame++;
  }

  void reset() { mCurrentFrame = 0; }

  bool initialized() { return mInitialized; }

private:
  void computeWindowTransform(index windowSize, index transformSize)
  {
    index halfBW = transformSize / 2;
    mWindowTransform = ArrayXd::Zero(transformSize);
    ArrayXd window = ArrayXd::Zero(windowSize);
    FFT     fft(transformSize);
    WindowFuncs::map()[WindowFuncs::WindowTypes::kHann](windowSize, window);
    ArrayXcd transform =
        fft.process(Eigen::Map<ArrayXd>(window.data(), windowSize));
    for (index i = 0; i < halfBW; i++)
    {
      mWindowTransform(halfBW + i) = mWindowTransform(halfBW - i) =
          std::abs(transform(i));
    }
  }

  double interpolateWindow(double pos)
  {
    index  floor = std::lrint(std::floor(pos));
    double frac = pos - floor;
    double dY = mWindowTransform(floor + 1) - mWindowTransform(floor);
    return mWindowTransform(floor) + frac * mInvWindowBinIncr * dY;
  }

  ArrayXd synthesizePeak(SinePeak p, double sampleRate, index bandwidth)
  {
    using namespace std;
    index   halfBW = bandwidth / 2;
    ArrayXd sine = ArrayXd::Zero(mBins);
    double  freqBin = p.freq * 2 * (mBins - 1) / sampleRate;
    if (freqBin >= mBins - 1) freqBin = mBins - 1;
    if (freqBin < 0) freqBin = 0;
    index  freqBinFloor = lrint(floor(freqBin));
    index  freqBinCeil = freqBinFloor + 1;
    double amp = 0.5 * pow(10, p.logMag / 20);
    double pos = mWindowTransform.size() / 2 +
                 ((freqBinCeil - freqBin) * mWindowBinIncr);
    for (index i = freqBinCeil; pos < mWindowTransform.size() - 2 &&
                                i < min(freqBinCeil + halfBW, mBins - 1);
         i++, pos += mWindowBinIncr)
    { sine[i] = amp * interpolateWindow(pos); }
    pos = (mWindowTransform.size() / 2) -
          ((freqBin - freqBinFloor) * mWindowBinIncr);
    for (index i = freqBinFloor;
         pos > 1 && i > max(freqBinFloor - halfBW, asSigned(0));
         i--, pos -= mWindowBinIncr)
    { sine[i] = amp * interpolateWindow(pos); }
    return sine;
  }

  PeakDetection        mPeakDetection;
  PartialTracking      mTracking;
  index                mBins{513};
  index                mCurrentFrame{0};
  std::queue<ArrayXcd> mBuf;
  ArrayXd              mWindowTransform;
  double               mScale{1.0};
  bool                 mInitialized{false};
  double               mWindowBinIncr;
  double               mInvWindowBinIncr;
};
} // namespace algorithm
} // namespace fluid


// Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
// HavoqGT Project Developers. See the top-level LICENSE file for details.
//
// SPDX-License-Identifier: MIT

#include <math.h>
#include <stdint.h>
#include <assert.h>
#include <utility>
#include <boost/random.hpp>

namespace havoqgt { namespace detail {

template <typename DUMMY=uint64_t>
class preferential_attachment_helper {
public:
  typedef uint64_t                  vertex_descriptor;
  typedef typename std::pair<uint64_t,uint64_t> edge_type;

  preferential_attachment_helper(uint64_t k, uint64_t m, double beta, uint64_t rng_seed=5489)
    : m_rng(rng_seed)
  {
    m_k = k;
    m_num_edges = m;
    m_koffset = m_k*(m_k+1)/2;
    m_ptr_mask =  ~(std::numeric_limits<vertex_descriptor>::max() >> 1);
    m_alpha = (beta / double(m_k) + double(1)) / (beta / double(m_k) + 2);
    //std::cout << "beta = " << beta << ", alpha = " << m_alpha << std::endl;
  }

  edge_type gen_edge(uint64_t _edge_index) {
    edge_type to_return;
    to_return.first = calc_source(_edge_index);
    if(_edge_index >= m_koffset)  {
      //
      // Generate random edge_list location based on beta model
      boost::random::uniform_01<boost::random::mt19937> rand_prob(m_rng);
      boost::random::uniform_int_distribution<uint64_t> uid(0,_edge_index-1);
      uint64_t rand = uid(m_rng) * 2;
      if(rand_prob() > m_alpha) {
        ++rand;
      }
      if(rand % 2 == 0) { //this is a source vertex, we can calc!
        to_return.second = calc_source(rand/2);
      } else {
        uint64_t edge_rand = rand/2;
        if(edge_rand < m_koffset) {  //this is an early edge we can calc!
          to_return.second = calc_target(edge_rand);
        } else {
          to_return.second = make_pointer(edge_rand);
        }
      }
    } else {
      to_return.second = calc_target(_edge_index);
    }
    return to_return;
  }

  uint64_t calc_source(uint64_t i) {
    uint64_t to_return;
    if(i+1>m_koffset) {
      to_return = ((i-m_koffset)/m_k)+m_k+1;
    } else {
      to_return = (uint64_t) floor(double(-0.5f) +
                  sqrt(double(0.25f)+double(2)*double(i))+1);
    }
    return to_return;
  }

  uint64_t calc_target(uint64_t i) {
    uint64_t to_return;
    if(i+1>m_koffset) {
      assert(false);
      to_return = i;
    } else {
      double tmp = double(-0.5f) + sqrt(double(0.25f)+double(2)*double(i))+1;
      to_return = (uint64_t) ((tmp - floor(tmp)) * floor(tmp));
    }
    return to_return;
  }

  vertex_descriptor make_pointer(vertex_descriptor i) {
    return i | m_ptr_mask;
  }

  bool is_pointer(vertex_descriptor i) {
    return (i & m_ptr_mask) > 0;
  }

  //dereferences point
  uint64_t value_of_pointer(vertex_descriptor i, uint64_t _num_partitions=1) {
    i = i & ~m_ptr_mask;
    uint64_t my_partition = i%_num_partitions;
    uint64_t my_partition_offset = i/_num_partitions;
    uint64_t edges_per_partition = m_num_edges / _num_partitions;
    return my_partition * edges_per_partition + my_partition_offset;
  }

private:
  boost::random::mt19937 m_rng;
  uint64_t               m_k;
  uint64_t               m_koffset;
  vertex_descriptor      m_ptr_mask;
  uint64_t               m_num_edges;
  double                 m_alpha;
};

}} //end namespace havoqgt::detail


#pragma once

#include "GNAObject.hh"
#include "GNAObjectBind1N.hh"
#include <Eigen/Dense>
#include <boost/optional.hpp>

class IntegratorBase : public GNAObjectBind1N<double>,
                       public TransformationBind<IntegratorBase>
{
public:
  void set_edges(OutputDescriptor& hist);
  TransformationDescriptor add_transformation(const std::string& name="");

  void dump();

  const Eigen::ArrayXd& getWeights() { return m_weights; }
  const Eigen::ArrayXi& getOrders() { return m_orders; }
protected:
  IntegratorBase(int order, bool shared_edge=false);
  IntegratorBase(size_t bins, int orders, double* edges=nullptr, bool shared_edge=false);
  IntegratorBase(size_t bins, int* orders, double* edges=nullptr, bool shared_edge=false);

  Eigen::ArrayXi m_orders;
  Eigen::ArrayXd m_weights;
  Eigen::ArrayXd m_edges;

  boost::optional<size_t> m_order;

  virtual void sample(FunctionArgs&)=0;

protected:
  void init_sampler();
  void check_sampler(TypesFunctionArgs& fargs);

private:
  void init_base(double* edges);
  void check_base(TypesFunctionArgs&);
  void integrate(FunctionArgs&);

  size_t m_shared_edge{0};
};


#pragma once
#include <memory>
#define EIGEN_MPL2_ONLY
#include <Eigen/Core>
typedef Eigen::Matrix<double, 6, 6> Matrix6d;
typedef Matrix6d PoseCovariance;
typedef Eigen::Matrix3d PosisitonCovariance;
typedef Eigen::Vector3d Position;
typedef Eigen::Vector4d Quat;

namespace amcl_3d
{
struct State
{
  Position position; // x,y,z
  Quat quat;     // x,y,z,w
};

class ParticleFilterInterface
{
public:
  enum class MeasurementType
  {
    IMU,
    ODOMETRY,
    PC2,
    VELOCITY,
    ACCEL,
    POSITION,
    QUATERNION
  };
  virtual bool init(const Position &position, const Quat &quat, const PoseCovariance &covariance, const size_t particle_num) = 0;
  virtual bool resample() = 0;
  virtual bool predict(std::function<bool()> func) = 0;
  virtual bool measure(std::function<bool()> func) = 0;

protected:
  std::shared_ptr<State> particles_ptr_;
};

} // namespace amcl_3d


#include <iostream>
#include <fstream>
#include <string>
#include <Eigen/Dense>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cassert>
#include <math.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <experimental/filesystem>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/opencv.hpp"
#include <limits>
#include <chrono>
#include <omp.h>
#include <array>

using namespace std;
using namespace Eigen;
using namespace std::chrono;
namespace fs = std::experimental::filesystem;
namespace ba = boost::algorithm;

string LIDAR_FILE = "";

class projection{
public:
  projection(){
    Eigen::initParallel();
    Eigen::setNbThreads(12);
    MatrixXf data = readbinfile(LIDAR_FILE);

    MatrixXf P;
    P.resize(3, 4);
    P << 609.6954, -721.4216, -1.2513,   -123.0418,
         180.3842,  7.6448,   -719.6515, -101.0167,
         0.9999,    1.2437e-4, 0.0105,   -0.2694;
    auto start = high_resolution_clock::now();

    data = points_filter(P, data);
    cv::Mat result = DenseMap(data, 4);
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
    cout << duration.count() << " microseconds" << endl;

    double minVal, maxVal;
    cv::Point minLoc, maxLoc;
    cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
    result = 255 * (result - minVal) / (maxVal - minVal);
    result.convertTo(result, CV_8UC1);
    cv::imshow("result", result);
    cv::waitKey(0);
  }

  MatrixXf readbinfile(const string dir){

    ifstream fin(dir.c_str(), ios::binary);
    assert(fin);

    fin.seekg(0, ios::end);
    const size_t num_elements = fin.tellg() / sizeof(float);
    fin.seekg(0, ios::beg);

    vector<float> l_data(num_elements);
    fin.read(reinterpret_cast<char*>(&l_data[0]), num_elements*sizeof(float));

    MatrixXf data = Map<MatrixXf>(l_data.data(), 4, l_data.size()/4);

    return data;
  }

  MatrixXf points_filter(MatrixXf &P, MatrixXf &data){
    data = P * data;
    vector<int> v;
    omp_set_num_threads(16);
    #pragma omp parallel
    {
      vector<int> v1;
      #pragma omp for nowait
      for (int j = 0; j < data.cols(); j++){
        if (data(2, j) > 0){
          float x = data(0, j) / data(2, j);
          float y = data(1, j) / data(2, j);
          if ( (x > 0 && x < COL - 0.5) && (y > 0 && y < ROW - 0.5) )
            v1.push_back(j);
        }
      }
      #pragma omp critical
      v.insert(v.end(), v1.begin(), v1.end());
    }
    MatrixXf result;
    result.resize(3, v.size());
    result.fill(0.);
    cout << data.rows() << " " << data.cols() << endl;
    omp_set_num_threads(16);
    #pragma omp parallel
    {
      MatrixXf res_private;
      res_private.resize(3, v.size());
      res_private.fill(0.);
      #pragma omp for nowait
      for (auto i = 0; i < v.size(); i++){
        res_private(0, i) = data(0, v[i]) / data(2, v[i]);
        res_private(1, i) = data(1, v[i]) / data(2, v[i]);
        res_private(2, i) = data(2, v[i]);

      }
      #pragma omp critical
      result += res_private;
    }
    return result;
  }

  cv::Mat DenseMap(MatrixXf &data, int grid){
    int ng = 2 * grid + 1;

    cv::Mat map, mD;
    map = cv::Mat::zeros(ROW, COL, CV_32FC1);
    mD = cv::Mat::zeros(ROW, COL, CV_32FC1);
    omp_set_num_threads(8);
    #pragma omp parallel
    {
      #pragma omp for nowait
      for (auto i = 0; i < data.cols(); i++){
        map.at<float>(round(data(1, i)), round(data(0, i))) =
          sqrt(pow(data(0, i) - round(data(0, i)), 2) +
               pow(data(1, i) - round(data(1, i)), 2));
        mD.at<float>(round(data(1, i)), round(data(0, i))) = data(2, i);
      }
    }

    cv::Mat output;
    output = cv::Mat::zeros(ROW, COL, CV_32FC1);
    omp_set_num_threads(128);
    #pragma omp parallel
    {
      #pragma omp for nowait
      for (auto i = 0; i < ROW; i++){
        for (auto j = 0; j < COL; j++){
          if (i - grid < 0 || i + grid >= ROW)
            continue;
          if (j - grid < 0 || j + grid >= COL)
            continue;
          float s = 0;
          for (auto r = -grid; r < grid + 1; r++){
            for (auto c = -grid; c < grid + 1; c++){
              float map_val = map.at<float>(i+r, j+c);
              if (map_val != 0){
                output.at<float>(i, j) +=
                  mD.at<float>(i+r, j+c) / map.at<float>(i+r, j+c);
                s += 1 / map.at<float>(i+r, j+c);
              }
            }
          }
          if (s == 0){
            s = 1;
          }
          output.at<float>(i, j) /= s;
        }
      }
    }
    return output;
  }

private:
  const int ROW = 375;
  const int COL = 1242;

};

int main(){
  projection p;
}