//---------------------------------Spheral++----------------------------------//
// QuadraticInterpolator
//
// Encapsulates the algorithm and data for parabolic interpolation in 1D
// Assumes the results is interpolated as y_interp = a + b*x + c*x^2
//
// Created by JMO, Fri Dec  4 14:28:08 PST 2020
//----------------------------------------------------------------------------//
#include "QuadraticInterpolator.hh"

#include <Eigen/Dense>

namespace Spheral {

//------------------------------------------------------------------------------
// Default constructor
//------------------------------------------------------------------------------
QuadraticInterpolator::QuadraticInterpolator():
  mN1(),
  mXmin(),
  mXmax(),
  mXstep(),
  mcoeffs() {
}

//------------------------------------------------------------------------------
// Construct with tabulated data
//------------------------------------------------------------------------------
QuadraticInterpolator::QuadraticInterpolator(const double xmin,
                                             const double xmax,
                                             const std::vector<double>& yvals):
  mN1(),
  mXmin(),
  mXmax(),
  mXstep(),
  mcoeffs() {
  this->initialize(xmin, xmax, yvals);
}

//------------------------------------------------------------------------------
// Initialize the interpolation to fit the given data
// Note, because we're doing a parabolic fit there are 2 fewer sets of coeficients
// than the size of the table we're fitting.
//------------------------------------------------------------------------------
void
QuadraticInterpolator::initialize(const double xmin,
                                  const double xmax,
                                  const std::vector<double>& yvals) {
  const auto n = yvals.size();
  REQUIRE(n > 2);      // Need at least 3 points to fit a parabola
  REQUIRE(xmax > xmin);

  mN1 = n - 3;  // Maximum index into arrays
  mXmin = xmin;
  mXmax = xmax;
  mXstep = (xmax - xmin)/(n - 1);
  mcoeffs.resize(3*(n - 2));

  typedef Eigen::Matrix<double, 3, 3, Eigen::RowMajor> EMatrix;
  typedef Eigen::Matrix<double, 3, 1> EVector;

  // We use simple least squares fitting for each 3-point interval, giving us an
  // exact parabolic fit for those three points.
  // Find the coefficient fits.
  double x0, x1, x2;
  EMatrix A;
  EVector B, C;
  for (auto i0 = 0u; i0 < n - 2; ++i0) {
    const auto i1 = i0 + 1u;
    const auto i2 = i0 + 2u;
    CHECK(i2 < n);
    x0 = xmin + i0*mXstep;
    x1 = x0 + mXstep;
    x2 = x1 + mXstep;
    A << 1.0, x0, x0*x0,
         1.0, x1, x1*x1,
         1.0, x2, x2*x2;
    B << yvals[i0], yvals[i1], yvals[i2];
    C = A.inverse()*B;
    mcoeffs[3*i0    ] = C(0);
    mcoeffs[3*i0 + 1] = C(1);
    mcoeffs[3*i0 + 2] = C(2);
  }
}

//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
QuadraticInterpolator::~QuadraticInterpolator() {
}

}


/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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.
 *
 */
#include <jni.h>
#include "HelloEigen.h"

#include <iostream>
#include <sstream>
#include <Eigen/Dense>
#include <string>

using namespace Eigen;

std::string helloMatrix(){
  std::stringstream ss;
  ss << __PRETTY_FUNCTION__ << std::endl;
  MatrixXd m(2,2);
  m(0,0) = 3;
  m(1,0) = 2.5;
  m(0,1) = -1;
  m(1,1) = m(1,0) + m(0,1);
  ss << "Here is the matrix m:\n" << m << std::endl;
  VectorXd v(2);
  v(0) = 4;
  v(1) = v(0) - 1;
  ss << "Here is the vector v:\n" << v << std::endl;
  return ss.str();
}
JNIEXPORT jstring JNICALL Java_com_theveganrobot_cmake_HelloEigen_helloMatrix
  (JNIEnv * env, jobject)
{
    return env->NewStringUTF( helloMatrix().c_str());
}


/*
 * EigenDecomposition.hpp
 *
 *  Created on: 11/01/2011
 *      Author: jimali
 */

#ifndef EIGENDECOMPOSITION_HPP_
#define EIGENDECOMPOSITION_HPP_

#if !defined(SWIG)
#include <Eigen/Core>
#include <vector>
#endif
namespace rw { namespace math {
    //! @brief Type representing a set of eigen values and eigen vectors.
    template< class T = double > class EigenDecomposition
    {
      public:
        /**
         * @brief Construct new decomposition.
         * @param vectors [in] the eigen vectors as columns in a matrix.
         * @param values [in] the corresponding eigen values.
         */
        EigenDecomposition (Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > vectors,
                            Eigen::Matrix< T, Eigen::Dynamic, 1 > values) :
            _vectors (vectors),
            _values (values)
        {}

        /**
         * @brief returns all eigenvectors as columns in a matrix
         * @return reference to the matrix.
         */
        const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& getEigenVectors ()
        {
            return _vectors;
        }

        /**
         * @brief returns the i'th eigenvector
         * @return the eigen vector.
         */
        Eigen::Matrix< T, Eigen::Dynamic, 1 > getEigenVector (size_t i) { return _vectors.col (i); }

        /**
         * @brief return all eigenvalues
         * @return the eigen values.
         */
        const Eigen::Matrix< T, Eigen::Dynamic, 1 >& getEigenValues () { return _values; }

        /**
         * @brief returns the i'th eigenvalue
         * @return the eigenvalue.
         */
        T getEigenValue (size_t i) { return _values (i); }

        //! @brief Sort function for ordering of eigen values and vectors.
        struct MapSort
        {
          private:
            Eigen::Matrix< T, Eigen::Dynamic, 1 >& _values;

          public:
            /**
             * @brief Construct new sort function struct.
             * @param values [in] the eigen values.
             */
            MapSort (Eigen::Matrix< T, Eigen::Dynamic, 1 >& values) : _values (values) {}

            /**
             * @brief Compare the eigen values with the given indices.
             * @param i0 [in] index of first eigenvalue.
             * @param i1 [in] index of second eigenvalue.
             * @return true if first eigenvalue comes before the second (it is smaller), false
             * otherwise.
             */
            bool operator() (const int& i0, const int& i1)
            {
                using namespace rw::math;
                return _values (i0) < _values (i1);
            }
        };

        /**
         * @brief sorts the eigen vectors according to their eigen value. The vector with smallest
         * eigen value has index 0
         */
        void sort ()
        {
            std::vector< int > map (_values.size ());
            for (size_t i = 0; i < map.size (); i++)
                map[i] = (int) i;

            std::sort (map.begin (), map.end (), MapSort (_values));
            // now the mapping determines how the new vectors are to be layed out
            Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > vectors = _vectors;
            Eigen::Matrix< T, Eigen::Dynamic, 1 > values               = _values;
            for (size_t i = 0; i < map.size (); i++) {
                _vectors.col (i) = vectors.col (map[i]);
                _values (i)      = values (map[i]);
            }
        }

      private:
        Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > _vectors;
        Eigen::Matrix< T, Eigen::Dynamic, 1 > _values;
    };

#if !defined(SWIG)
    using EigenDecompositiond = EigenDecomposition< double >;
    using EigenDecompositionf = EigenDecomposition< float >;
#else
#if SWIG_VERSION < 0x040000
    SWIG_DECLARE_TEMPLATE (EigenDecomposition_d, rw::math::EigenDecomposition< double >);
    ADD_DEFINITION (EigenDecomposition_d, EigenDecomposition)
#else
    SWIG_DECLARE_TEMPLATE (EigenDecomposition, rw::math::EigenDecomposition< double >);
#endif
    SWIG_DECLARE_TEMPLATE (EigenDecomposition_f, rw::math::EigenDecomposition< float >);
#endif
}}    // namespace rw::math

#endif /* EIGENDECOMPOSITION_HPP_ */


#include <mpp.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <functional>
#include <random>
#include <cstddef>

using namespace mpp::hamiltonian;
using namespace mpp::chains;
using namespace boost::numeric::ublas;

double log_posterior(vector<double> const & q){
    double log_post_val(0);
    for(std::size_t i=0;i<q.size();++i) {
        log_post_val -= q(i)*q(i);
    }
    return log_post_val;
}

vector<double> grad_log_posterior(vector<double> const & q) {
    vector<double> dq(q.size());
    for(std::size_t i=0;i<q.size();++i) {
        dq(i) = -q(i);
    }
    return dq;
}

int main() {
    std::size_t const num_dims(10);
    std::size_t const max_num_steps(10);
    double const max_eps(1);
    vector<double> inv_mass_mat(num_dims);
    for(std::size_t i=0;i<num_dims;++i) {
        inv_mass_mat(i) = double(1);
    }

    std::function<double(vector<double> const &)> lp = log_posterior;
    std::function<
        vector<double> (vector<double> const &) > glp = grad_log_posterior;

    hmc_sampler<double>  hmc_spr(
        lp,
        glp,
        num_dims,
        max_num_steps,
        max_eps,
        inv_mass_mat
    );

    std::size_t const num_samples(1000);
    std::mt19937 rng;
    std::normal_distribution<double> nrm_dist;
    vector<double> q_0(num_dims);
    for(size_t i=0;i<num_dims;++i) {
        q_0(i) = nrm_dist(rng);
    }
    mcmc_chain<double> chn = hmc_spr.run_sampler(num_samples,q_0);
    std::string chn_file_name("./eg_classic_hmc.chain");
    chn.write_samples_to_csv(chn_file_name);

    return 0;
}


#include <stdio.h>
#include <malloc.h>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

#define VUL_DEFINE
#include "vul_timer.h"

#include <Eigen/SVD>

using namespace Eigen;

int main( int argc, char **argv )
{
   if( argc < 3 ) {
      printf( "Usage: %s [path to image] [rank to reconstruct from] [iterations (optional)]\n", argv[ 0 ] );
      exit(1);
   }

   int w, h, n;
   unsigned char *data = stbi_load( argv[ 1 ], &w, &h, &n, 0 );

   // @TODO(thynn): Don't average into grayscale, do something useful (or each channel separately)
	MatrixXf A = MatrixXf( h, w );
   for( int y = 0; y < h; ++y ) {
      for( int x = 0; x < w; ++x ) {
         float v = ( float )data[ ( y * w + x ) * n ] / 255.f;
         for( int c = 1; c < n; ++c ) {
            v += ( float )data[ ( y * w + x ) * n + c ] / 255.f;
         }
			A( y, x ) = v / ( float )n;
      }
   }

   char *eptr;
   int rank = strtol( argv[ 2 ], &eptr, 10 );
   int wrank = rank;

   printf( "Computing SVD of %s (%dx%d)\n", argv[ 1 ], w, h );
   vul_timer *t = vul_timer_create( );
	JacobiSVD< MatrixXf > svd( A, ComputeThinU | ComputeThinV );
   uint64_t mms = vul_timer_get_micros( t );
   printf( "Completed in %lu.%lus\n", mms / 1000000, mms % 1000000 );

	VectorXf sigma = svd.singularValues();
   for( int i = 0; i < svd.rank(); ++i ) {
      printf( "S[%d]: %f\n", i, sigma[i] );
   }

   printf( "Rank of decomposition %d, wanted at most %d\n", svd.rank(), wrank );

	MatrixXf B = svd.matrixU() * svd.singularValues().asDiagonal() * svd.matrixV().transpose();

   unsigned char *odata = ( unsigned char* )malloc( sizeof( unsigned char ) * w * h * 3 );
   for( int y = 0; y < h; ++y ) {
      for( int x = 0; x < w; ++x ) {
         float v = B( y, x ) * 255.f;
         v = v < 0.f   ? 0.f
           : v > 255.f ? 255.f
           : v;
         odata[ ( y * w + x ) * 3     ] = v;
         odata[ ( y * w + x ) * 3 + 1 ] = v;
         odata[ ( y * w + x ) * 3 + 2 ] = v;
      }
   }
   stbi_write_bmp( "out.bmp", w, h, 3, odata );
   printf( "Wrote output to out.bmp.\n");
   for( int y = 0; y < h; ++y ) {
      for( int x = 0; x < w; ++x ) {
         float v = A( y, x ) * 255.f;
         v = v < 0.f   ? 0.f
           : v > 255.f ? 255.f
           : v;
         odata[ ( y * w + x ) * 3     ] = v;
         odata[ ( y * w + x ) * 3 + 1 ] = v;
         odata[ ( y * w + x ) * 3 + 2 ] = v;
      }
   }
   stbi_write_bmp( "source.bmp", w, h, 3, odata );
   printf( "Wrote input to source.bmp.\n");

   free( odata );
   free( data );
}


#include <iostream>
#include <vector>
#include <limits>
#include <cmath>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/pending/disjoint_sets.hpp>

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
  boost::no_property, boost::property<boost::edge_weight_t, int> >      weighted_graph;
typedef boost::property_map<weighted_graph, boost::edge_weight_t>::type weight_map;
typedef boost::graph_traits<weighted_graph>::edge_descriptor            edge_desc;
typedef boost::graph_traits<weighted_graph>::vertex_descriptor          vertex_desc;

using namespace std;

// Essentially, the tasks asks for the cost of the second best spanning tree.
// Leia performs Prims MST algorithm. We need at least one edge different to the MST,
// therefore, the best we can do is computing the second best spanning tree.
void solve() {
  // Tatooine is not needed for anything
  int n, tatooine;
  cin >> n >> tatooine;

  // Compute a MST (with any algorithm)
  weighted_graph G(n);

  int cost;
  vector<vector<int>> costs(n, vector<int>(n));
  for (int j = 0; j < n - 1; ++j) {
    for (int k = 0; k < n - j - 1; ++k) {
      int u = j;
      int v = j + k + 1;
      cin >> cost;
      costs[u][v] = cost;
      costs[v][u] = cost;
      boost::add_edge(u, v, cost, G);
    }
  }

  // Use Kurskal (we could also use Prim...does not make any difference)
  std::vector<edge_desc> mst;
  boost::kruskal_minimum_spanning_tree(G, std::back_inserter(mst));

  // Extract neighbors from MST and compute MST Value
  int mstValue = 0;
  vector<vector<int>> neighbors(n);
  vector<vector<int>> isMstEdge(n, vector<int>(n, false));
  for (auto edge : mst) {
    int u = boost::source(edge, G);
    int v = boost::target(edge, G);
    mstValue += costs[u][v];
    neighbors[u].push_back(v);
    neighbors[v].push_back(u);
    isMstEdge[u][v] = true;
    isMstEdge[v][u] = true;
  }

  // Compute the most expensive edge for every u-v path in the MST
  vector<vector<int>> uvMaxEdge(n, vector<int>(n, 0));

  for (int u = 0; u < n; ++u) {
    vector<int> stack;
    stack.push_back(u);
    vector<int> visited(n, false);
    visited[u] = true;

    while (!stack.empty()) {
      int v = *stack.rbegin();
      stack.pop_back();

      for (auto w : neighbors[v]) {
        if (!visited[w]) {
          visited[w] = true;
          uvMaxEdge[u][w] = max(costs[v][w], uvMaxEdge[u][v]);
          stack.push_back(w);
        }
      }
    }
  }

  // For all edges e = {u, v}, that are not in the MST, we will try adding e to the MST.
  // This will introduce a cycle. We remove the most expensive edge of the cycle that is
  // part of the MST. For this we can simply query the most expensive edge from u to v in the MST
  // and remove it. The cost of the MST changes by delta = cost[u][v] - cost[most expensive edge].
  // We simply find the best delta.
  int minVal = numeric_limits<int>::max();
  for (int u = 0; u < n; ++u) {
    for (int v = u + 1; v < n; ++v) {
      if (!isMstEdge[u][v]) {
        int val = costs[u][v] - uvMaxEdge[u][v];
        minVal = min(val, minVal);
      }
    }
  }

  cout << mstValue + minVal << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  int t; cin >> t;
  while(t--) {
    solve();
  }
}


#pragma once

#include <Eigen/Dense>
#include <Eigen/Sparse>

#include <array>
#include <boost/lexical_cast.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/multi_array.hpp>
#include <vector>

#include <cmath>
#include <fstream>
#include <iostream>

#include "mpfr/import_std_math.hpp"
#include "quadrature/qhermitew.hpp"
#include "spectral/hermitenw.hpp"
#include "spectral/lagrange_polynomial.hpp"

namespace boltzmann {

/**
 * @brief Nodal <-> Hermite transformation matrices in 1d.
 *
 * @remark
 * the nodal basis consists of Lagrange polynomials at Hermite quadrature nodes.
 * The underlying Lagrange polynomials satisfy:
 *
 * \f$ l_i(x_j) = 0 \quad \textrm{for } i  \neq j \f$
 *
 * and
 *
 * \f$ l_i(x_i) = 1/sqrt(w_i) \f$
 *
 * where \f$w_i\f$ are the Gauss-Hermite quadrature weights.
 *
 */
template <typename NUMERIC_T = double>
class H2N_1d
{
 public:
  typedef NUMERIC_T numeric_t;
  //  typedef Eigen::Matrix<numeric_t, Eigen::Dynamic, Eigen::Dynamic> matrix_t;

 public:
  /**
   *
   *
   * @param H2N  hermite to nodal matrix
   * @param N2H  nodal to hermite matrix
   * @param K    max. polynomial degree
   */
  template <typename MATRIX>
  static void create(MATRIX& H2N, MATRIX& N2H, const int K);
};

// --------------------------------------------------------------------------------
template <typename NUMERIC_T>
template <typename MATRIX>
void
H2N_1d<NUMERIC_T>::create(MATRIX& H2N, MATRIX& N2H, const int K)
{
  N2H.resize(K, K);
  H2N.resize(K, K);
  //  N2H_.resize(K,K);
  QHermiteW quad(1, K);
  HermiteNW<numeric_t> hermw(K);
  hermw.compute(quad.pts());

  for (int i = 0; i < K; ++i) {
    for (int j = 0; j < K; ++j) {
      const double wi = quad.wts(i);
      H2N(i, j) = hermw.get(j)[i] * ::math::sqrt(wi);
    }
  }

  N2H = H2N.transpose();
}

// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
/**
 * @brief Nodal <-> Hermite transformation matrices in 1d, nodes of the nodal basis can be
 * arbitrary.
 *
 * The nodes of the nodal basis are located at the nodes of the Gauss-Hermite quadrature rule
 * with weight function  \f$ exp(-\alpha r^2) \f$.
 *
 * @remark
 * ATTENTION: H2N(a=1) is orthonormal, but this is not the case when \f$ a \neq 1\f$!
 *
 *
 * If this class is used together with @a Hermite2Nodal (and alpha!=1), the transformation
 * `N->H` will give wrong results! Only use H->N.  TODO: update code such that BOTH forward AND
 * BACKWARD transformation works.
 *
 */
class H2NG_1d
{
 public:
  template <typename MATRIX>
  static void create(MATRIX& H2N, MATRIX& N2H, const int K, const double alpha)
  {
    typedef Eigen::VectorXd vec_t;

    H2N.resize(K, K);

    QHermiteW quad4nodes(alpha, K);
    QHermiteW quad(1, K);

    // Lagrange Poly
    vec_t xi = Eigen::Map<const vec_t>(quad4nodes.points_data(), K);
    vec_t li(K);  // lambda's (barycentric interpolation)
    vec_t yi(K);
    vec_t x = Eigen::Map<const vec_t>(quad.points_data(), K);
    vec_t w = Eigen::Map<const vec_t>(quad.weights_data(), K);
    vec_t y(K);
    // prepare barycentric interpol. weights
    LagrangePolynomial<>::compute_weights(li, xi);
    // evaluate hermite polynomials at quadrature points
    HermiteNW<double> hermw(K);
    hermw.compute(quad.pts());
    const double ah4 = std::pow(alpha, 0.25);

    Eigen::MatrixXd T(K, K);
    for (int i = 0; i < K; ++i) {
      yi.setZero();
      yi[i] = 1.0;
      LagrangePolynomial<>::evaluate(y, x, xi, yi, li);
      const double sqrtwi = std::sqrt(w[i]);
      for (int j = 0; j < K; ++j) {
        double sum = 0;
        // quadrature
        for (int q = 0; q < K; ++q) {
          sum += hermw.get(j)[q] * std::exp((x[i] * x[i] - x[q] * x[q]) / 2) * ah4 * y[q] * w[q] /
                 sqrtwi;
        }
        T(i, j) = sum;
      }
    }

    Eigen::MatrixXd M(K, K);
    vec_t y1(K);
    vec_t y2(K);
    const double ah2 = std::sqrt(alpha);
    // mass matrix (cf. notes in yellow notebook)
    for (int i = 0; i < K; ++i) {
      yi.setZero();
      yi[i] = 1.0;
      LagrangePolynomial<>::evaluate(y1, x, xi, yi, li);
      for (int j = 0; j < K; ++j) {
        yi.setZero();
        yi[j] = 1.0;
        LagrangePolynomial<>::evaluate(y2, x, xi, yi, li);
        double sum = 0;
        for (int q = 0; q < K; ++q) {
          sum += std::exp((x[i] * x[i] + x[j] * x[j]) / 2 - x[q] * x[q]) * y1[q] * y2[q] /
                 std::sqrt(w[i] * w[j]) * w[q];
        }
        M(i, j) = ah2 * sum;
      }
    }
    H2N = M.inverse() * T;
    N2H = T.transpose();
  }
};

}  // end namespace boltzmann


/*
* Copyright (c) 2019 Nobuyuki Umetani
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
 * @brief demo for visualizing eigenmodes
 */

#include <Eigen/Eigenvalues>
#if defined(_WIN32) // windows
#  define NOMINMAX   // to remove min,max macro
#  include <windows.h>  // should put before glfw3.h
#endif
#define GL_SILENCE_DEPRECATION
#include <GLFW/glfw3.h>

#include "delfem2/eigen/ls_dense.h"
#include "delfem2/lsitrsol.h"
#include "delfem2/mshprimitive.h"
#include "delfem2/mshuni.h"
#include "delfem2/points.h"
#include "delfem2/femsolidlinear.h"
#include "delfem2/glfw/viewer3.h"
#include "delfem2/glfw/util.h"
#include "delfem2/opengl/old/mshuni.h"

namespace dfm2 = delfem2;

void ShowEigen_SolidLinear_MeshQuad2(
    const std::vector<double>& aXY,
    const std::vector<unsigned int>& aQuad,
    double elen)
{
  const unsigned int np = aXY.size() / 2;
  Eigen::MatrixXd A(np * 2, np * 2);
  A.setZero();

  double emat[4][4][2][2];
  dfm2::EMat_SolidLinear2_QuadOrth_GaussInt(emat, elen, elen, 1.0, 1.0, 2);
  std::vector<unsigned int> tmp_buffer;
  for (unsigned int iq = 0; iq < aQuad.size() / 4; ++iq) {
    const unsigned int aIp[4] = {
        aQuad[iq * 4 + 0], aQuad[iq * 4 + 1], aQuad[iq * 4 + 2], aQuad[iq * 4 + 3]};
    delfem2::Merge<4,4,2,2,double>(A,aIp,aIp,emat,tmp_buffer);
  }

  {
    auto B = A;
    B(0,0) += 1.0;
    B(1,1) += 1.0;
    B(2,2) += 1.0;
    B(3,3) += 1.0;
    Eigen::VectorXd r(np*2), u(np*2), Ap(np*2), p(np*2);
    r.setRandom();
    std::vector<double> aConv = dfm2::Solve_CG(r,u,Ap,p,1.0e-5,300,B);
    std::cout << aConv.size() << std::endl;
  }

  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> s(A);
  const auto& evec = s.eigenvectors(); // somehow this takes time

  //
  delfem2::glfw::CViewer3 viewer;
  delfem2::glfw::InitGLOld();
  viewer.OpenWindow();

  std::vector<double> aDisp(np*2,0.0);

  for(unsigned int iframe=0;iframe<10;++iframe){
    std::cout << s.eigenvalues()(iframe) << std::endl;
    for(unsigned int i=0;i<np*2;++i){
      aDisp[i] = evec(i,iframe);
    }
    for(unsigned int i=0;i<100;++i) {
      viewer.DrawBegin_oldGL();
      dfm2::opengl::DrawMeshQuad2D_EdgeDisp(
          aXY.data(), aXY.size()/2,
          aQuad.data(), aQuad.size()/4,
          aDisp.data(),sin(i*0.1));
      viewer.SwapBuffers();
      glfwPollEvents();
    }
  }
  glfwDestroyWindow(viewer.window);
  glfwTerminate();
}

void ShowEigen_SolidLinear_MeshTri2(
    const std::vector<double>& aXY,
    const std::vector<unsigned int>& aTri)
{
  const unsigned int np = aXY.size()/2;
  Eigen::MatrixXd A(np*2, np*2);
  A.setZero();

  std::vector<double> aDisp(np*2,0.0);
  std::vector<unsigned int> tmp_buffer;
  for(unsigned int it=0;it<aTri.size()/3;++it){
    const unsigned int aIp[3] = {aTri[it*3+0], aTri[it*3+1], aTri[it*3+2]};
    double disp[3][2]; dfm2::FetchData<3,2>(disp,aIp,aDisp.data());
    double coord[3][2]; dfm2::FetchData<3,2>(coord,aIp,aXY.data());
    double emat[3][3][2][2], eres[3][2];
    dfm2::EMat_SolidStaticLinear_Tri2D(
        eres,emat,
        1,1,0,0,0,
        disp,coord);
    delfem2::Merge<3,3,2,2,double>(A,aIp,aIp,emat,tmp_buffer);
  }

  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> s(A);
  const auto& evec = s.eigenvectors();
  //
  delfem2::glfw::CViewer3 viewer;
  delfem2::glfw::InitGLOld();
  viewer.OpenWindow();
  for(unsigned int iframe=0;iframe<10;++iframe){
    std::cout << s.eigenvalues()(iframe) << std::endl;
    for(unsigned int i=0;i<np*2;++i){
      aDisp[i] = evec(i,iframe);
    }
    for(unsigned int i=0;i<100;++i) {
      viewer.DrawBegin_oldGL();
      dfm2::opengl::DrawMeshTri2D_EdgeDisp(
          aXY.data(), aXY.size()/2,
          aTri.data(), aTri.size()/3,
          aDisp.data(),sin(i*0.1));
      viewer.SwapBuffers();
      glfwPollEvents();
    }
  }
  glfwDestroyWindow(viewer.window);
  glfwTerminate();
}

int main()
{
  std::cout << "Available :SIMD Instructions: "<< Eigen::SimdInstructionSetsInUse() << std::endl;
  //
  std::vector<double> aXY;
  std::vector<unsigned int> aQuad;
  unsigned int nx = 10;
  unsigned int ny = 5;
  dfm2::MeshQuad2D_Grid(
      aXY,aQuad,
      nx,ny);
  const double elen = 0.1;
  {
    dfm2::Scale_Points(aXY.data(), aXY.size() / 2, 2, elen);
    dfm2::Translate_Points2(aXY,-0.5*nx*elen, -0.5*ny*elen);
  }
  ShowEigen_SolidLinear_MeshQuad2(aXY, aQuad, elen);
  //
  std::vector<unsigned int> aTri;
  dfm2::convert2Tri_Quad(
      aTri,
      aQuad);
  ShowEigen_SolidLinear_MeshTri2(aXY,aTri);
}


/* Copyright (c) 2021 Grumpy Cat Software S.L.
 *
 * This Source Code is licensed under the MIT 2.0 license.
 * the terms can be found in  LICENSE.md at the root of
 * this project, or at http://mozilla.org/MPL/2.0/.
 */

#include <gauss/internal/scopedHostPtr.h>
#include <gauss/linalg.h>
#include <gauss/polynomial.h>

#include <Eigen/Eigenvalues>

using namespace Eigen;

constexpr auto EPSILON = 1e-8;

namespace {

af::array vandermonde(const af::array &x, int order, bool ascending) {
    af::array result = af::array(x.dims(0), order, x.type());
    gfor(af::seq i, order) { result(af::span, i) = af::pow(x, i); }
    if (!ascending) {
        result = af::flip(result, 1);
    }
    return result;
}

}  // namespace

af::array gauss::polynomial::polyfit(const af::array &x, const af::array &y, int deg) {
    int order = deg + 1;
    af::array lhs = vandermonde(x, order, false);
    const af::array &rhs = y;

    af::array scale = af::max(af::sqrt(af::sum(lhs * lhs, 0)), EPSILON);

    lhs /= af::tile(scale, static_cast<unsigned int>(lhs.dims(0)));

    af::array c = gauss::linalg::lls(lhs, rhs);
    c = af::transpose(c);
    c /= af::tile(scale, static_cast<unsigned int>(c.dims(0)));
    c = af::transpose(c);

    return c;
}

af::array gauss::polynomial::roots(const af::array &pp) {
    af::array result = af::array(pp.dims(0) - 1, pp.dims(1), af::dtype::c32);
    for (int i = 0; i < pp.dims(1); i++) {
        af::array p = pp(af::span, i);
        // Strip leading and trailing zeros
        p = p(p != 0);

        p = (-1 * p(af::seq(1, static_cast<double>(p.dims(0)) - 1), af::span)) /
            af::tile(p(0, af::span), static_cast<unsigned int>(p.dims(0)) - 1);

        auto coeffs = gauss::utils::makeScopedHostPtr(p.as(af::dtype::f32).host<float>());

        Eigen::VectorXf vec = Eigen::VectorXf::Ones(p.dims(0));
        Eigen::MatrixXf diag = vec.asDiagonal();

        Eigen::MatrixXf diag2(diag.rows(), diag.cols());
        int rest = static_cast<int>(diag.rows()) - 1;
        diag2.topRows(1) = Eigen::Map<Eigen::MatrixXf>(coeffs.get(), 1, p.dims(0));
        diag2.bottomRows(rest) = diag.topRows(rest);

        Eigen::VectorXcf eivals = diag2.eigenvalues();

        result(af::span, i) = af::array(p.dims(0), (af::cfloat *)eivals.data());
    }

    return result;
}


#ifndef RANDOMNUMBERGENERATOR_HPP_
#define RANDOMNUMBERGENERATOR_HPP_

// for random sampling
#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/math/distributions.hpp>
#include <cstdlib>
#include <mutex>
#include <Eigen/Core>

template<typename Dtype>
class RandomNumberGenerator {

 public:

  RandomNumberGenerator() {
  }

  ~RandomNumberGenerator() {
  }

  /* mean =0, std = 1*/
  Dtype sampleNormal() {
    auto dist = boost::random::normal_distribution<Dtype>(0.0, 1.0);
    return dist(rngGenerator);
  }

  /* from -1 to 1*/
  Dtype sampleUniform() {
    auto dist = boost::uniform_real<Dtype>(-1, 1);
    return dist(rngGenerator);
  }

  /* from 0 to 1*/
  Dtype sampleUniform01() {
    auto dist = boost::uniform_real<Dtype>(0, 1);
    return dist(rngGenerator);
  }

  bool forXPercent(float epsilon) {
    auto dist = boost::uniform_real<Dtype>(0, 1);
    return dist(rngGenerator) < epsilon;
  }

  int intRand(const int &min, const int &max) {
    {
      std::uniform_int_distribution<int> distribution(min, max);
      return distribution(rngGenerator);
    }
  }

  /* weighted random sampling where the weights are given by 1, r, r^2, ... */
  int intWeightedRand (const int &max, Dtype weightDecayFtr) {
    Dtype sum = (Dtype(1) - std::pow(weightDecayFtr, max+1)) / (Dtype(1)-weightDecayFtr);
    return std::ceil(log(Dtype(1) - sampleUniform01() * sum * (Dtype(1) - weightDecayFtr)) / log(weightDecayFtr)) - 1;
  }

  template<int dim>
  void sampleVectorInNormalUniform(Dtype *vector) {
    auto dist = boost::uniform_real<Dtype>(-1, 1);
    for (int i = 0; i < dim; i++)
      vector[i] = dist(rngGenerator);
  }

  template<int dim>
  void sampleInUnitSphere(Dtype *vector) {
    sampleVectorInNormalUniform<dim>(vector);
    Dtype sum = 0.0f;

    for (int i = 0; i < dim; i++)
      sum += vector[i] * vector[i];

    Dtype amplitudeOverSum = pow(std::abs(sampleUniform()), Dtype(1.0) / Dtype(dim)) / sqrtf(sum);

    for (int i = 0; i < dim; i++)
      vector[i] = vector[i] * amplitudeOverSum;
  }

  template<int dim>
  void sampleOnUnitSphere(Dtype *vector) {
    sampleVectorInNormalUniform<dim>(vector);
    Dtype sum = 0.0f;

    for (int i = 0; i < dim; i++)
      sum += vector[i] * vector[i];

    for (int i = 0; i < dim; i++)
      vector[i] = vector[i] / sqrtf(sum);
  }

  template<typename Derived>
  void shuffleSTDVector(std::vector<Derived> &order) {
    boost::variate_generator<boost::mt19937 &, boost::uniform_int<> >
        random_number_shuffler(rngGenerator, boost::uniform_int<>());
    std::random_shuffle(order.begin(), order.end(), random_number_shuffler);
  }

  /* this method is opitmized for memory use. The column should be dynamic size */
  template<typename Derived, int Rows, int Cols>
  void shuffleColumns(Eigen::Matrix<Derived, Rows, Cols> &matrix) {
    int colSize = int(matrix.cols());

    /// sampling the order
    std::vector<int> order;
    std::vector<bool> needSuffling(colSize, true);

    order.resize(colSize);
    for (int i = 0; i < colSize; i++) order[i] = i;
    shuffleSTDVector(order);
    Eigen::Matrix<Derived, Rows, 1> memoryCol(matrix.rows());

    int colID;

    for (int colStartID = 0; colStartID < colSize; colStartID++) {
      if (order[colStartID] == colStartID || !needSuffling[colStartID]) continue;

      colID = colStartID;
      memoryCol = matrix.col(colID);
      do {
        matrix.col(colID) = matrix.col(order[colID]);
        needSuffling[colID] = false;
        colID = order[colID];
      } while (colStartID != order[colID]);
      matrix.col(colID) = memoryCol;
      needSuffling[colID] = false;
    }
  }

  std::vector<unsigned> getNrandomSubsetIdx (unsigned nOfElem, unsigned nOfSubElem) {
    std::vector<unsigned> memoryIdx(nOfSubElem);
    ///// randomly sampling memory indeces
    for (unsigned i = 0; i < nOfSubElem; i++) {
      memoryIdx[i] = intRand(0, nOfElem - 1);
      for (unsigned j = 0; j < i; j++) {
        if (memoryIdx[i] == memoryIdx[j]) {
          i--;
          break;
        }
      }
    }
    return memoryIdx;
  }

  /*you can use this method to make the random samples the same*/
  void seed(uint32_t seed) {
    rngGenerator.seed(seed);
  }

 private:
  boost::random::mt19937 rngGenerator;

};

#endif /* RANDOMNUMBERGENERATOR_HPP_ */


#pragma once
#include "shape.hpp"
#include <Eigen/Core>
#include <tuple>

//! The gradient of the shape function (on the reference element) for LINEAR FEM
//!
//! We have three shape functions
//!
//! @param i integer between 0 and 2 (inclusive). Decides which shape function to return.
//! @param x x coordinate in the reference element.
//! @param y y coordinate in the reference element.
inline Eigen::Vector2d gradientLambda(const int i, double x, double y) {
	std::ignore = x;
	std::ignore = y;

	return Eigen::Vector2d(-1 + (i > 0) + (i == 1),
	                       -1 + (i > 0) + (i == 2));
	return Eigen::Vector2d(0, 0); //remove when implemented
}

//----------------gradshapefunBegin----------------
//! The gradient of the shape function (on the reference element) for QUADRATIC FEM
//!
//! We have six shape functions
//!
//! @param i integer between 0 and 5 (inclusive). Decides which shape function to return.
//! @param x x coordinate in the reference element.
//! @param y y coordinate in the reference element.
inline Eigen::Vector2d gradientShapefun(const int i, double x, double y) {
	// Eigen::Vector2d value;
	// (write your solution here)
	assert(0 <= i && i <= 5);
	switch (i) {
		case 0:
			return Eigen::Vector2d(-3 + 4 * x + 4 * y, -3 + 4 * x + 4 * y);
		case 1:
			return Eigen::Vector2d(4 * x - 1, 0);
		case 2:
			return Eigen::Vector2d(0, 4 * y - 1);
		case 3:
			return Eigen::Vector2d(4 - 8 * x - 4 * y, -4 * x);
		case 4:
			return Eigen::Vector2d(4 * y, 4 * x);
		case 5:
			return Eigen::Vector2d(-4 * y, 4 - 4 * x - 8 * y);
		default:
			throw std::domain_error("i not in {0,1,2,3,4,5}");
	}
	//return value;
}
//----------------gradshapefunEnd----------------


#include <cassert>
#include <cmath>

#include <functional>
#include <numeric>
#include <sstream>

#include <boost/multiprecision/gmp.hpp>

#include <QtDebug>

using s64 = int64_t;

using namespace std;

using boost::multiprecision::mpq_rational;

QDebug operator<<(QDebug d, const mpq_rational& r) {
    d.nospace();
    d.noquote();
    stringstream s;
    s << r;
    d << QString::fromStdString(s.str());
    return d.resetFormat();
}

QMap<int /*roll*/, s64 /*count*/> rolls(int sides, int repetitions) {

    std::function<void(int , int, QMap<int, s64>*)> traverse = [&traverse, sides, repetitions](int sum, int rep, QMap<int, s64>* ret) {
        if (rep == repetitions) {
            if (ret->contains(sum) == false) {
                (*ret)[sum] = 0;
            }
            (*ret)[sum] += 1;
            return;
        }

        for (int i = 1; i <= sides; i += 1) {
            traverse(sum + i, rep + 1, ret);
        }
    };

    QMap<int, s64> ret;

    traverse(0, 0, &ret);

    return ret;
}

mpq_rational winProbability(int sides1, int reps1, int sides2, int reps2) {
    auto rolls1 = rolls(sides1, reps1);
    auto rolls2 = rolls(sides2, reps2);

    auto values1 = rolls1.values();
    auto values2 = rolls2.values();

    s64 sum1 = accumulate(begin(values1), end(values1), 0);
    s64 sum2 = accumulate(begin(values2), end(values2), 0);

    mpq_rational ret(0);

    QMap<int, s64>::const_iterator i = rolls2.constBegin();
    while (i != rolls2.constEnd()) {
        mpq_rational pickProbability(i.value(), sum1);

        s64 winNumerator = 0;

        QMap<int, s64>::const_iterator j = rolls1.constBegin();
        while (j != rolls1.constEnd()) {

            if (j.key() < i.key()) {
                winNumerator += j.value();
                //qDebug() << "  +" << j.key() << j.value() << winNumerator;
            } else {
                //qDebug() << "  -" << j.key();
            }

            ++j;
        }

        ret += pickProbability*mpq_rational(winNumerator, sum2);

        //qDebug() << "sum" << i.key() << ", pick" << pickProbability << ", win this" << mpq_rational(winNumerator, sum2) << ", total" << ret;

        ++i;
    }

    return ret;
}

void testRolls();
void test1();

int main(int argc, char **args) {
    Q_UNUSED(argc); Q_UNUSED(args);

    testRolls();
    test1();

    return 0;
}

void testRolls() {

    auto a31 = rolls(3, 1);
        assert(a31.size() == 3);
        assert(a31[1] == 1);
        assert(a31[2] == 1);
        assert(a31[3] == 1);

    auto a22 = rolls(2, 2);
        assert(a22.size() == 3);
        assert(a22[2] == 1);
        assert(a22[3] == 2);
        assert(a22[4] == 1);

    auto a49 = rolls(4, 9).values(); assert(accumulate(begin(a49), end(a49), 0) == 262144);
    auto a66 = rolls(6, 6).values(); assert(accumulate(begin(a66), end(a66), 0) ==  46656);
}

void test1() {
    qDebug() << winProbability(6, 6, 4, 9);
}


#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
#include <Eigen/Dense>
#include <algorithm>
using namespace sf;
using namespace std;
using namespace Eigen;
typedef Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic > Mat;

void reset(Mat& mat) {
	//initialize matrix to zero matrix
	//행렬을 영행렬로 초기화합니다.
	for (int i = 0; i < mat.rows(); ++i)
		for (int j = 0; j < mat.cols(); ++j)
			mat(i, j) = 0;
}

bool compare(pair<double, Mat> a, pair<double, Mat> b) {
	//compare function for sorting eigen values in descending order
	//고유값을 내림차순으로 정렬하기 위한 비교함수
	return a.first * a.first > b.first * b.first;
}

class RGB {
public:
	enum { R, G, B };
	RGB() {
	}
	RGB(Mat red, Mat green, Mat blue) {
		size = red.rows();
		mat[R] = red;	mat[G] = green;	mat[B] = blue;
		empty = false;
	}
	Mat mat[3];
	int size;
	bool empty = true;

	vector<pair<double, Mat>> lists[3];
	bool processed[3] = { false,false,false };
	int added[3] = { -1,-1,-1 };
	void getEVDColor(int color, int rate) {
		if (!processed[color]) {
			SelfAdjointEigenSolver<Mat> eigensolver(mat[color]);
			if (eigensolver.info() != Success) abort();
			Mat eigenValues = eigensolver.eigenvalues();
			Mat eigenVectors = eigensolver.eigenvectors();
			eigenVectors = eigenVectors.householderQr().householderQ();//정규직교화
			int num = eigenValues.rows();//고유값의 개수

			for (int i = 0; i < num; ++i) {
				pair<double, Mat> element;
				element.first = eigenValues(i);
				element.second = eigenVectors.col(i);
				lists[color].push_back(element);
			}
			sort(lists[color].begin(), lists[color].end(), compare);
			processed[color] = true;
			mat[color] = Mat(size, size);
			reset(mat[color]);
			cout << endl;
		}
		if (added[color] <= rate) {
			for (int i = added[color] + 1; i < rate; ++i) {
				mat[color] += (lists[color][i].first * (lists[color][i].second * lists[color][i].second.transpose()));
			}
		}
		else {
			for (int i = added[color]; i >= rate; --i) {
				mat[color] -= (lists[color][i].first * (lists[color][i].second * lists[color][i].second.transpose()));
			}
		}
		added[color] = rate - 1;
	}
};

RGB getMatrixFromImage(Image& img) {
	//only square image available
	//it uses upper triangle part of the image only.
	if (img.getSize().x != img.getSize().y) return RGB();
	int size = img.getSize().x;

	Mat red(size, size);
	Mat green(size, size);
	Mat blue(size, size);
	for (int i = 0; i < size; ++i) {
		for (int j = 0; j < size; ++j) {
			if (j < i) {
				red(i, j) = img.getPixel(i, j).r;
				green(i, j) = img.getPixel(i, j).g;
				blue(i, j) = img.getPixel(i, j).b;
			}
			else if (i == j) red(i, j) = 0;
			else {
				red(i, j) = img.getPixel(j, i).r;
				green(i, j) = img.getPixel(j, i).g;
				blue(i, j) = img.getPixel(j, i).b;
			}
		}
	}
	return RGB(red, green, blue);
}

Image getImageFromRGB(RGB& rgb) {
	Image  result;
	result.create(rgb.size, rgb.size);
	for (int i = 0; i < rgb.size; ++i) {
		for (int j = 0; j < rgb.size; ++j) {
			Color color;
			color.r = rgb.mat[RGB::R](i, j);
			color.g = rgb.mat[RGB::G](i, j);
			color.b = rgb.mat[RGB::B](i, j);
			result.setPixel(i, j, color.toInteger() < 0 ? Color(0) : color);
		}
	}
	return result;
}

int main() {

	string input;
	cout << "input image file name including extension>";
	cin >> input;

	Image original;
	original.loadFromFile(input);
	if (original.getSize().x != original.getSize().y) {
		cout << "only square image available";
		return -1;
	}

	RenderWindow window(VideoMode(original.getSize().x, original.getSize().y), "Math channel Ssootube Eigen Value Decomposition");
	RGB mat;
	mat = getMatrixFromImage(original);
	Image applied = getImageFromRGB(mat);
	Texture t; t.loadFromImage(applied);
	Sprite output(t);
	int k = 0;
	cout << "only upper triangular part of the image will be used." << endl;
	while (window.isOpen()) {
		Event e;
		while (window.pollEvent(e)) {
			if (e.type == Event::Closed)
				window.close();
			if (e.type == Event::KeyPressed)
				if (e.key.code == Keyboard::Enter)
				{
					window.clear();
					window.draw(output);
					window.display();
					if (k <= mat.size) {
						mat.getEVDColor(RGB::R, k);
						mat.getEVDColor(RGB::G, k);
						mat.getEVDColor(RGB::B, k++);
					}
					applied = getImageFromRGB(mat);
					t.loadFromImage(applied);
					output.setTexture(t);
					cout << "press enter to continue. current rank:" << ((k - 2 == -1) ? 0 : k - 2) << endl;
					break;
				}
		}

	}
	return 0;
}


/**
 * @file pfasst/quadrature/interface.hpp
 * @since v0.3.0
 */
#ifndef _PFASST__QUADRATURE__INTERFACE_HPP_
#define _PFASST__QUADRATURE__INTERFACE_HPP_

#include <cassert>
#include <vector>
using namespace std;

#include <Eigen/Dense>
template<typename scalar>
using Matrix = Eigen::Matrix<scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;

template<typename scalar>
using Index = typename Matrix<scalar>::Index;

#include "pfasst/globals.hpp"
#include "pfasst/interfaces.hpp"
#include "pfasst/quadrature/polynomial.hpp"

namespace pfasst
{
  namespace quadrature
  {
    /**
     * Quadrature type descriptors.
     * @since v0.3.0
     */
    enum class QuadratureType : int {
        GaussLegendre   =  0  //!< @ref pfasst::quadrature::GaussLegendre "Gauss-Legendre" quadrature
      , GaussLobatto    =  1  //!< @ref pfasst::quadrature::GaussLobatto "Gauss-Lobatto" quadrature
      , GaussRadau      =  2  //!< @ref pfasst::quadrature::GaussRadau "Gauss-Radau" quadrature
      , ClenshawCurtis  =  3  //!< @ref pfasst::quadrature::ClenshawCurtis "Clenshaw-Curtis" quadrature
      , Uniform         =  4  //!< Uniform quadrature
      , UNDEFINED       = -1
    };

    template<typename scalar>
    static Polynomial<scalar> build_polynomial(const size_t node, const vector<scalar>& nodes)
    {
      const size_t num_nodes = nodes.size();
      Polynomial<scalar> p(num_nodes + 1), p1(num_nodes + 1);
      p[0] = 1.0;

      for (size_t m = 0; m < num_nodes; ++m) {
        if (m == node) { continue; }

        // p_{m+1}(x) = (x - x_j) * p_m(x)
        p1[0] = scalar(0.0);
        for (size_t j = 0; j < num_nodes;     ++j) { p1[j + 1]  = p[j]; }
        for (size_t j = 0; j < num_nodes + 1; ++j) { p1[j]     -= p[j] * nodes[m]; }
        for (size_t j = 0; j < num_nodes + 1; ++j) { p[j]       = p1[j]; }
      }

      return p;
    }

    /**
     * Compute quadrature matrix \\( Q \\) between two sets of nodes.
     *
     * Computing the quadrature matrix \\( Q \\) for polynomial-based integration from one set of
     * quadrature nodes (@p from) to another set of quadrature nodes (@p to).
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     * @param[in] from first set of quadrature nodes
     * @param[in] to second set of quadrature nodes
     * @returns quadrature matrix \\( Q \\) with `to.size()` rows and `from.size()` colums
     *
     * @pre For correctness of the algorithm it is assumed, that both sets of nodes are in the range
     *   \\( [0, 1] \\).
     *
     * @since v0.3.0
     */
    template<typename scalar>
    static Matrix<scalar> compute_q_matrix(const vector<scalar>& from, const vector<scalar>& to)
    {
      const size_t to_size = to.size();
      const size_t from_size = from.size();
      assert(to_size >= 1 && from_size >= 1);

      Matrix<scalar> q_mat = Matrix<scalar>::Zero(to_size, from_size);

      for (size_t m = 0; m < from_size; ++m) {
        Polynomial<scalar> p = build_polynomial(m, from);
        // evaluate integrals
        auto den = p.evaluate(from[m]);
        auto P = p.integrate();
        for (size_t j = 0; j < to_size; ++j) {
          q_mat(j, m) = (P.evaluate(to[j]) - P.evaluate(scalar(0.0))) / den;
        }
      }

      return q_mat;
    }

    /**
     * Compute quadrature matrix \\( Q \\) for one set of nodes.
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     * @param[in] nodes quadrature nodes to compute \\( Q \\) matrix for
     *
     * @since v0.3.0
     *
     * @overload
     */
    template<typename scalar>
    static Matrix<scalar> compute_q_matrix(const vector<scalar>& nodes)
    {
      return compute_q_matrix<scalar>(nodes, nodes);
    }

    /**
     * Compute quadrature matrix \\( Q \\) from a given node-to-node quadrature matrix \\( S \\).
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     * @param[in] s_mat \\( S \\) matrix to compute \\( Q \\) from
     * @see pfasst::quadrature::compute_s_matrix
     *
     * @since v0.3.0
     *
     * @overload
     */
    template<typename scalar>
    static Matrix<scalar> compute_q_matrix(const Matrix<scalar>& s_mat)
    {
      Matrix<scalar> q_mat = Matrix<scalar>::Zero(s_mat.rows(), s_mat.cols());
      q_mat.col(0) = s_mat.col(0);
      for (Index<scalar> q_mat_col = 1; q_mat_col < q_mat.cols(); ++q_mat_col) {
        q_mat.col(q_mat_col) = q_mat.col(q_mat_col - 1) + s_mat.col(q_mat_col);
      }
      return q_mat;
    }

    /**
     * Compute node-to-node quadrature matrix \\( S \\) from a given quadrature matrix \\( Q \\).
     *
     * The \\( S \\) matrix provides a node-to-node quadrature where the \\( i \\)-th row of
     * \\( S \\) represents a quadrature from the \\( i-1 \\)-th node to the \\( i \\)-th node.
     *
     * The procedure is simply subtracting the \\( i-1 \\)-th row of \\( Q \\) from the
     * \\( i \\)-th row of \\( Q \\).
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     * @param[in] q_mat \\( Q \\) matrix to compute \\( S \\) of
     * @returns \\( S \\) matrix
     *
     * @since v0.3.0
     */
    template<typename scalar>
    static Matrix<scalar> compute_s_matrix(const Matrix<scalar>& q_mat)
    {
      Matrix<scalar> s_mat = Matrix<scalar>::Zero(q_mat.rows(), q_mat.cols());
      s_mat.row(0) = q_mat.row(0);
      for (Index<scalar> row = 1; row < s_mat.rows(); ++row) {
        s_mat.row(row) = q_mat.row(row) - q_mat.row(row - 1);
      }
      return s_mat;
    }

    /**
     * Compute node-to-node quadrature matrix \\( S \\) from two given sets of nodes
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     * @param[in] from first set of quadrature nodes
     * @param[in] to second set of quadrature nodes
     *
     * @since v0.3.0
     *
     * @overload
     */
    template<typename scalar>
    static Matrix<scalar> compute_s_matrix(const vector<scalar>& from, const vector<scalar>& to)
    {
      return compute_s_matrix(compute_q_matrix(from, to));
    }

    /**
     * Compute vector \\( q \\) for integration from \\( 0 \\) to \\( 1 \\) for given set of nodes.
     *
     * This equals to the last row of the quadrature matrix \\( Q \\) for the given set of nodes.
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     * @param[in] nodes quadrature nodes to compute \\( Q \\) matrix for
     * @pre For correctness of the algorithm it is assumed, that the nodes are in the range
     *   \\( [0, 1] \\).
     *
     * @since v0.3.0
     */
    template<typename scalar>
    static vector<scalar> compute_q_vec(const vector<scalar>& nodes)
    {
      const size_t num_nodes = nodes.size();
      assert(num_nodes >= 1);

      vector<scalar> q_vec = vector<scalar>(num_nodes, scalar(0.0));

      for (size_t m = 0; m < num_nodes; ++m) {
        Polynomial<scalar> p = build_polynomial(m, nodes);
        // evaluate integrals
        auto den = p.evaluate(nodes[m]);
        auto P = p.integrate();
        q_vec[m] = (P.evaluate(scalar(1.0)) - P.evaluate(scalar(0.0))) / den;
      }

      return q_vec;
    }

    /**
     * Interface for quadrature handlers.
     *
     * Quadrature handlers provide \\( Q \\), \\( S \\) and \\( B \\) matrices respecting the left
     * and right nodes, i.e. whether \\( 0 \\) and \\( 1 \\) are part of the nodes or not.
     *
     * Computation of the quadrature nodes and matrices (i.e. quadrature weights) is done on
     * initialization.
     *
     * @tparam scalar precision of quadrature (i.e. `double`)
     *
     * @since v0.3.0
     */
    template<typename precision = pfasst::time_precision>
    class IQuadrature
    {
      protected:
        //! @{
        static const bool LEFT_IS_NODE = false;
        static const bool RIGHT_IS_NODE = false;

        size_t num_nodes;
        Matrix<precision> q_mat;
        Matrix<precision> s_mat;
        vector<precision> q_vec; // XXX: black spot
        Matrix<precision> b_mat;
        vector<precision> nodes;
        //! @}

      public:
        //! @{
        /**
         * @throws invalid_argument if number of nodes is invalid for quadrature type
         */
        explicit IQuadrature(const size_t num_nodes);
        /**
         * @throws invalid_argument if number of nodes is invalid for quadrature type
         */
        IQuadrature();
        virtual ~IQuadrature() = default;
        //! @}

        //! @{
        virtual const Matrix<precision>& get_q_mat() const;
        virtual const Matrix<precision>& get_s_mat() const;
        virtual const Matrix<precision>& get_b_mat() const;
        virtual const vector<precision>& get_q_vec() const;
        virtual const vector<precision>& get_nodes() const;
        virtual size_t get_num_nodes() const;

        /**
         * @throws pfasst::NotImplementedYet if not overwritten by implementation;
         *   required for quadrature of any kind
         */
        virtual bool left_is_node() const;
        /**
         * @throws pfasst::NotImplementedYet if not overwritten by implementation;
         *   required for quadrature of any kind
         */
        virtual bool right_is_node() const;
        //! @}

        /**
         * Compute a rough estimate of the numerical error... XXX
         */
        precision expected_error() const;

      protected:
        //! @{
        /**
         * @throws pfasst::NotImplementedYet if not overwritten by implementation;
         *   required for quadrature of any kind
         */
        virtual void compute_nodes();
        virtual void compute_weights();
        //! @}
    };
  }  // ::pfasst::quadrature
}  // ::pfasst

#include "pfasst/quadrature/interface_impl.hpp"

#endif  // _PFASST__QUADRATURE__INTERFACE_HPP_


/**
 * MIT License
 *
 * Copyright (c) 2019 Sean Crutchlow
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * @file utils_test.cpp
 * @brief Unit tests using Google Test framework to validate class
 *  implementation.
 * @author Sean Crutchlow <sean.GH1231@gmail.com>
 * @version 1.0
 */

/// System
#include <gtest/gtest.h>

#include <cmath>
#include <tuple>
#include <type_traits>
#include <vector>

/// Library
#include <Eigen/Dense>

/// Project
#include "kalman_filter/utils.h"

namespace kalman_filter {
class UtilsTest : public ::testing::Test {
 protected:
  double error;

  virtual void SetUp() {
    error = 1e-6;
  }

  virtual void TearDown() {}

  const bool Compare(const coord2D_t& _lhs,
                     const coord2D_t& _rhs,
                     const double _epsilon) {
    if (std::abs(std::get<0>(_lhs) - std::get<0>(_rhs)) > _epsilon)
      return false;
    if (std::abs(std::get<1>(_lhs) - std::get<1>(_rhs)) > _epsilon)
      return false;

    return true;
  }

  const bool Compare(const coord3D_t& _lhs,
                     const coord3D_t& _rhs,
                     const double _epsilon) {
    if (std::abs(std::get<0>(_lhs) - std::get<0>(_rhs)) > _epsilon)
      return false;
    if (std::abs(std::get<1>(_lhs) - std::get<1>(_rhs)) > _epsilon)
      return false;
    if (std::abs(std::get<2>(_lhs) - std::get<2>(_rhs)) > _epsilon)
      return false;

    return true;
  }
};

TEST_F(UtilsTest, Cartesian2Polar) {
  coord2D_t expected(5.0, 0.92729521800161);     /// r, theta
  coord2D_t result = Cartesian2Polar(3.0, 4.0);  /// x, y

  EXPECT_TRUE(Compare(result, expected, error));
}

TEST_F(UtilsTest, Polar2Cartesian) {
  coord2D_t expected(-2.0807341827357, 4.5464871341284);  /// x, y
  coord2D_t result = Polar2Cartesian(5.0, 2.0);           /// r, theta

  EXPECT_TRUE(Compare(result, expected, error));
}

TEST_F(UtilsTest, Cartesian2Spherical) {
  coord3D_t expected(7.6426435217142,
                     0.74847023342654,
                     0.90806681890191);                     /// rho, theta, phi
  coord3D_t result = Cartesian2Spherical(3.2, 4.1, 5.6);    /// x, y, z

  EXPECT_TRUE(Compare(result, expected, error));
}

TEST_F(UtilsTest, Cartesian2Cylindrical) {
  coord3D_t expected(5.3413481444295,
                     0.90482708941579,
                     5.7);                                    /// rho, theta, z
  coord3D_t result = Cartesian2Cylindrical(3.3, 4.2, 5.7);    /// x, y, z

  EXPECT_TRUE(Compare(result, expected, error));
}

TEST_F(UtilsTest, Spherical2Cartesian) {
  coord3D_t expected(-6.352477916,
                      0.9055237668,
                      3.265892074);                         /// x, y, z
  coord3D_t result = Spherical2Cartesian(7.2, 3.0, 1.1);    /// rho, theta, phi

  EXPECT_TRUE(Compare(result, expected, error));
}

TEST_F(UtilsTest, Cylindrical2Cartesian) {
  coord3D_t expected(-2.802096119,
                      2.566760086,
                      4.8);                                 /// x, y, z
  coord3D_t result = Cylindrical2Cartesian(3.8, 2.4, 4.8);  /// r, theta, z

  EXPECT_TRUE(Compare(result, expected, error));
}

TEST_F(UtilsTest, Deg2Rad) {
  double expected = 0.021537363;   /// radians
  double result = Deg2Rad(1.234);  /// degrees

  EXPECT_NEAR(result, expected, error);
}

TEST_F(UtilsTest, Rad2Deg) {
  double expected = 70.702992;     /// degrees
  double result = Rad2Deg(1.234);  /// radians

  EXPECT_NEAR(result, expected, error);
}

TEST_F(UtilsTest, Feet2Meters) {
  double expected = 0.3761232;         /// meters
  double result = Feet2Meters(1.234);  /// feet

  EXPECT_NEAR(result, expected, error);
}

TEST_F(UtilsTest, Meters2Feet) {
  double expected = 4.0485564;         /// feet
  double result = Meters2Feet(1.234);  /// meters

  EXPECT_NEAR(result, expected, error);
}

TEST_F(UtilsTest, CalcRMSE) {
  Eigen::VectorXd e1(2), e2(2), a1(2), a2(2);
  e1 << 0.00001234, 0.12340000;
  e2 << 0.00999900, 0.99990000;
  a1 << 0.00987600, 0.12000000;
  a2 << 0.00001200, 0.98760000;

  std::vector<Eigen::VectorXd> estimated = {e1, e2};
  std::vector<Eigen::VectorXd> actual = {a1, a2};

  Eigen::VectorXd expected(2);
  expected << 0.009925522,
              0.00902358;

  Eigen::VectorXd result = CalcRMSE(estimated, actual);  /// meters

  EXPECT_TRUE((result - expected).norm() < error);
}
}   //  namespace kalman_filter

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


//============================================================================
//
// This file is part of the Thea toolkit.
//
// This software is distributed under the BSD license, as detailed in the
// accompanying LICENSE.txt file. Portions are derived from other works:
// their respective licenses and copyright information are reproduced in
// LICENSE.txt and/or in the relevant source files.
//
// Author: Siddhartha Chaudhuri
// First version: 2011
//
//============================================================================

#ifndef __Thea_Algorithms_Zernike2_hpp__
#define __Thea_Algorithms_Zernike2_hpp__

// Currently Visual Studio 2010 fails to compile Boost multi_array in Debug mode: https://svn.boost.org/trac/boost/ticket/4874
#if defined(_MSC_VER) && _MSC_VER >= 1600
#  define THEA_NO_ZERNIKE
#endif

#ifndef THEA_NO_ZERNIKE

#include "../Common.hpp"
#include "../IAddressableMatrix.hpp"
#include "../MatVec.hpp"
#include <boost/multi_array.hpp>
#include <complex>

namespace Thea {
namespace Algorithms {

/**
 * Compute Zernike moments of a 2D distribution, represented as a matrix of density values. The density values may be
 * multidimensional, i.e. the matrix elements may be vectors or colors.
 *
 * This class adapts code for the LightField Descriptor from Ding-Yun Chen et al.,
 * http://3d.csie.ntu.edu.tw/~dynamic/3DRetrieval/index.html .
 */
class THEA_API Zernike2
{
  public:
    /** The matrix type storing N-dimensional moments. Each column is a moment. */
    template <int N, typename ScalarT> using MomentMatrix = Matrix< N, Eigen::Dynamic, std::complex<ScalarT> >;

    /** %Options for generating Zernike moments. */
    struct THEA_API Options
    {
      int angular_steps;  ///< Number of angular steps.
      int radial_steps;   ///< Number of radial steps.
      int lut_radius;     ///< Radius of Zernike basis function for lookup table.

      /** Constructor. */
      Options(int angular_steps_ = 12, int radial_steps_ = 3, int lut_radius_ = 50)
      : angular_steps(angular_steps_), radial_steps(radial_steps_), lut_radius(lut_radius_)
      {}

      /** Get the set of default options. */
      static Options const & defaults() { static Options const def; return def; }

    }; // struct Options

    /** Constructor. */
    Zernike2(Options const & opts_ = Options::defaults());

    /** Get the number of moments generated by a call to compute(). */
    intx numMoments() const { return opts.angular_steps * opts.radial_steps; }

    /**
     * Compute Zernike moments of a 2D distribution, represented as a matrix of single- or multi-dimensional density values
     * (such as reals, vectors or colors). If the density values have more than one dimension, they should allow array
     * addressing (operator[](intx i)). The template parameter N, inferred from the last argument, must be the same
     * as the number of dimensions of the input.
     *
     * @param distrib The distribution represented as an addressable matrix of density values.
     * @param center_x The x-coordinate (column) of the center of the non-zero region of the distribution, in matrix
     *   coordinates.
     * @param center_y The y-coordinate (row) of the center of the non-zero region of the distribution, in matrix coordinates.
     * @param radius The radius of the non-zero region of the distribution, measured from the center, in matrix coordinates. All
     *   zero elements can be ignored when specifying this number.
     * @param moments Used to return the Zernike moments, specified in "angle-major, radius-minor" order. Each moment is a
     *   column of the matrix.
     *
     * @return The number of pixels that have non-zero values and were used to compute the moments.
     */
    template <int N, typename T, typename ScalarT>
    intx compute(IAddressableMatrix<T> const & distrib, double center_x, double center_y, double radius,
                 MomentMatrix<N, ScalarT> & moments) const;

  private:
    /** Generate lookup table for moments. */
    void generateBasisLUT() const;

    /**
     * Check if an input element (type T) is zero. This is the generic implementation for multi-channel inputs. The
     * single-channel case is separately specialized.
    */
    template <int N> struct IsZero
    {
      template <typename T> static bool check(T const & t)
      {
        for (int i = 0; i < N; ++i)
          if (t[i] != 0) return false;

        return true;
      }
    };

    /**
     * Add a scaled increment to a moment. This is the generic implementation for multi-channel inputs. The single-channel case
     * is separately specialized.
     */
    template <int N, typename ScalarT> struct Accum
    {
      template <typename T>
      static void add(T const & t, std::complex<double> const & x, typename MomentMatrix<N, ScalarT>::ColXpr acc)
      {
        for (intx i = 0; i < acc.size(); ++i)
        {
          acc[i].real(acc[i].real() + static_cast<ScalarT>(x.real() * t[i]));
          acc[i].imag(acc[i].imag() - static_cast<ScalarT>(x.imag() * t[i]));
        }
      }
    };

    typedef boost::multi_array< std::complex<double>, 4 > LUT;  ///< Lookup table class.

    Options opts;                ///< Set of options.
    mutable LUT lut;             ///< Coefficient lookup table.
    mutable bool lut_generated;  ///< Has the LUT been generated?

}; // class Zernike2

// Specializations for single-channel input.
template <>
struct Zernike2::IsZero<1>
{
  template <typename T> static bool check(T const & t)
  {
    return t != 0;
  }
};

template <typename ScalarT>
struct Zernike2::Accum<1, ScalarT>
{
  template <typename T>
  static void add(T const & t, std::complex<double> const & x, typename MomentMatrix<1, ScalarT>::ColXpr & acc)
  {
    acc[0].real(acc[0].real() + static_cast<ScalarT>(x.real() * t));
    acc[0].imag(acc[0].imag() - static_cast<ScalarT>(x.imag() * t));
  }
};

template <int N, typename T, typename ScalarT>
intx
Zernike2::compute(IAddressableMatrix<T> const & distrib, double center_x, double center_y, double radius,
                  Zernike2::MomentMatrix<N, ScalarT> & moments) const
{
  alwaysAssertM(radius > 0, "Zernike2: Radius must be greater than zero");

  this->generateBasisLUT();

  moments.resize(Eigen::NoChange, numMoments());
  moments.setZero();

  intx ncols = distrib.cols();
  intx nrows = distrib.rows();

  // Don't go outside the specified radius
  intx min_x = std::max(0L,        (intx)std::ceil (center_x - radius));
  intx max_x = std::min(ncols - 1, (intx)std::floor(center_x + radius));

  intx min_y = std::max(0L,        (intx)std::ceil (center_y - radius));
  intx max_y = std::min(nrows - 1, (intx)std::floor(center_y + radius));

  double r_radius = opts.lut_radius / radius;

  std::complex<double> x1, x2, x3;
  double dx, dy, tx, ty;
  intx ix, iy;
  intx count = 0;
  for (intx y = min_y; y <= max_y; ++y)
  {
    for (intx x = min_x; x <= max_x; ++x)
    {
      T const & density = distrib.at(y, x);
      if (!IsZero<N>::check(density))
      {
        dx = x - center_x;
        dy = y - center_y;
        tx = dx * r_radius + opts.lut_radius;
        ty = dy * r_radius + opts.lut_radius;
        ix = (intx)tx;
        iy = (intx)ty;
        dx = tx - ix;
        dy = ty - iy;

        // Summation of basis function
        for (intx p = 0; p < opts.angular_steps; ++p)
        {
          for (intx r = 0; r < opts.radial_steps; ++r)
          {
            x1 = lut[p][r][ix][iy    ] + (lut[p][r][ix + 1][iy    ] - lut[p][r][ix][iy    ]) * dx;
            x2 = lut[p][r][ix][iy + 1] + (lut[p][r][ix + 1][iy + 1] - lut[p][r][ix][iy + 1]) * dx;
            x3 = x1 + (x2 - x1) * dy;

            Accum<N, ScalarT>::add(density, x3, moments.col(p * opts.radial_steps + r));
          }
        }

        count++;
      }
    }
  }

  if (count > 0)
    moments /= (ScalarT)count;

  return count;
}

} // namespace Algorithms
} // namespace Thea

#endif // !defined(THEA_NO_ZERNIKE)

#endif


//var_model.cpp

#include <math.h>
#include <algorithm>
#include <functional>

#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>

#include "var_model.h"

using namespace std;
using namespace boost::accumulators;

//Define container for muliple criteria sorting
struct Container{
                double _return; //returns
                double _prob; //weighted prob,
            };

bool sortByReturn(const Container &lhs, const Container &rhs) { return lhs._return < rhs._return; }

VaR::VaR(double _alpha):alpha(_alpha){}

//copy constructor implementation
VaR::VaR(const VaR& other):
	alpha(other.alpha)
{}

double VaR::getAlpha() const {return alpha;}

void VaR::setAlpha(double _alpha) {alpha = _alpha;}

ParametricVaR::ParametricVaR(double _alpha, bool _logNormal):VaR(_alpha),logNormal(_logNormal)
{}

//copy constructor implementation
ParametricVaR::ParametricVaR(const ParametricVaR& other):
	VaR(other),logNormal(other.logNormal)
{}

double ParametricVaR::NormalVaR(double u, double sigma) const{

		double za;

		za =  boost::math::quantile(snd, getAlpha());

		return (u + sigma * za);
}

double ParametricVaR::LogNormalVaR(double u, double sigma) const {

		double za;

		za =  boost::math::quantile(snd, getAlpha());

		return -(1. - exp(u + sigma * za));
}

RiskMetricsVaR::RiskMetricsVaR(double _alpha, double _lambda, bool _logNormal)
:ParametricVaR(_alpha, _logNormal), lambda(_lambda){}

//copy constructor implementation
RiskMetricsVaR::RiskMetricsVaR(const RiskMetricsVaR& other):
	ParametricVaR(other), lambda(other.lambda)
{}

double RiskMetricsVaR::operator()(double _meanReturn,
                                  double _sigmatminus1, double _returnt) const{

    double sigmat = sqrt(lambda * _sigmatminus1 * _sigmatminus1 + (1. - lambda) * _returnt * _returnt);

	double tmp = logNormal ? LogNormalVaR(_meanReturn, sigmat) : NormalVaR(_meanReturn, sigmat);

	return tmp >= 0 ? 0. : tmp;

}

double RiskMetricsVaR::operator()(double _meanReturn, const Vec& returns) const
{
	double sigmaT = 0.;
    size_t T(returns.size());

    for(size_t i = 1; i < T;++i){
        sigmaT = sqrt(lambda * sigmaT * sigmaT + (1. - lambda) * returns[i] * returns[i]);
    }

	double tmp = logNormal ? LogNormalVaR(_meanReturn, sigmaT) : NormalVaR(_meanReturn, sigmaT);

	return tmp >= 0 ? 0. : tmp;
}

double RiskMetricsVaR::operator()(const Vec& returns) const
{
    double sigmaT = 0.;
    double _meanReturn =0;
    size_t T(returns.size());

    for(size_t i = 1; i < T;++i){
        sigmaT = sqrt(lambda * sigmaT * sigmaT + (1. - lambda) * returns[i] * returns[i]);
        _meanReturn += returns[i];
    }

    _meanReturn =_meanReturn/(T-1);

    double tmp = logNormal ? LogNormalVaR(_meanReturn, sigmaT) : NormalVaR(_meanReturn, sigmaT);

	return tmp >= 0 ? 0. : tmp;
}

GarchVaR::GarchVaR(double _alpha, double _a, double _b,  double _c,bool _logRtns)
:ParametricVaR(_alpha, _logRtns), a(_a), b(_b), c(_c){}

//copy constructor implementation
GarchVaR::GarchVaR(const GarchVaR& other):
	ParametricVaR(other), a(other.a), b(other.b),c(other.c)
{}

double GarchVaR::operator()(double _meanReturn,
                            double _sigmatminus1, double _returntminus1) const{

    double sigmat = sqrt(a + c * _sigmatminus1 * _sigmatminus1 + b * _returntminus1 * _returntminus1);

	double tmp = logNormal ? LogNormalVaR(_meanReturn, sigmat) : NormalVaR(_meanReturn, sigmat);

	return tmp >= 0 ? 0. : tmp;

}

double GarchVaR::operator()(double _meanReturn, const Vec& returns) const
{
	double sigmaT = 0.;

    for(size_t i = 0; i < returns.size();++i)
        sigmaT += pow(c,static_cast<double>(i)) * returns[i] * returns[i];

    sigmaT *= b;
    sigmaT += a/(1.-c);

	double tmp = logNormal ? LogNormalVaR(_meanReturn, sqrt(sigmaT)) : NormalVaR(_meanReturn, sqrt(sigmaT));

	return tmp >= 0 ? 0. : tmp;
}

double GarchVaR::operator()(const Vec& returns) const
{
    double sigmaT = 0.;
    double _meanReturn =0;
    size_t T(returns.size());

    for(size_t i = 0; i < T;++i){
        sigmaT += pow(c,static_cast<double>(i)) * returns[i] * returns[i];
        _meanReturn += returns[i];
    }

    sigmaT *= b;
    sigmaT += a/(1.-c);
    _meanReturn =_meanReturn/(T-1);

	double tmp = logNormal ? LogNormalVaR(_meanReturn, sigmaT) : NormalVaR(_meanReturn, sigmaT);

	return tmp >= 0 ? 0 : tmp;
}

NoneParametricVaR::NoneParametricVaR(double _alpha):VaR(_alpha){}

NoneParametricVaR::NoneParametricVaR(const NoneParametricVaR& other)
:VaR(other)
{}

HistoricalVaR::HistoricalVaR(double _alpha, double _lambda, WeightingScheme _ws)
:NoneParametricVaR(_alpha), lambda(_lambda), ws(_ws){}

//copy constructor implementation
HistoricalVaR::HistoricalVaR(const HistoricalVaR& other):
	NoneParametricVaR(other), lambda(other.lambda), ws(other.ws)
{}

double HistoricalVaR::operator()(double _sigmatminus1,
                                 const Vec& returns) const
{
 	double T = returns.size();

	double alpha(getAlpha());

	unsigned int c(alpha * T);
	c == 0 ? c : c-= 1;

	double tmp;

	int input(ws);

	std::vector<double> _returns(returns);

	switch(input){

	case 0:
        {
            // sort returns find cth arg - Histogram method
            std::sort(_returns.begin(), _returns.end());

            tmp = _returns[c];
        }

        break;

	case 1:
        {
            std::vector<Container> prob(T);

            double a = (1. - lambda)/(1. - pow(lambda, T));

            for(size_t i = 0; i < T; ++i){
                prob[i]._return = _returns[T -1 - i];
                prob[i]._prob = a * pow(lambda, i);
            }

            // Sort Container by return function
            std::sort(prob.begin(), prob.end(),sortByReturn);

            double sumProb(0);

            for(size_t i = 0; i < T; ++i){
                sumProb += prob[i]._prob;

                if(sumProb >= alpha){
                    tmp = prob[i]._return;
                    break;
                }
            }

        }

        break;

    case 2:

        {
            std::vector<double> sigma;

            sigma.push_back(_sigmatminus1 * _sigmatminus1);

            for(size_t i = 1; i < T;++i)
                sigma.push_back(lambda * sigma[i - 1] + (1. - lambda) * returns[i - 1] * returns[i - 1]);

            double sigmaT(sigma.back());

            std::vector<double> _wgthRtns;

            for(size_t i = 0; i < T; ++i){

                if(sigma[i] <= 0) _wgthRtns.push_back(_returns[i]);
                else _wgthRtns.push_back(sqrt(sigmaT / sigma[i]) * _returns[i] );
            }

            // sort returns find cth arg - Histogram method
            std::sort(_wgthRtns.begin(), _wgthRtns.end());

            tmp = _wgthRtns[c];
        }

        break;

    default:
        break;

	}

	return tmp >= 0 ? 0. : tmp;
}

ExtremeValueVaR::ExtremeValueVaR(double _alpha):VaR(_alpha){}

//copy constructor implementation
ExtremeValueVaR::ExtremeValueVaR(const ExtremeValueVaR& other):
	VaR(other)
{}

PoTVaR::PoTVaR(double _u,double _beta, double _xi,double _alpha)
: ExtremeValueVaR(_alpha),xi(_xi),beta(_beta),u(_u){

}

//copy constructor implementation
PoTVaR::PoTVaR(const PoTVaR& other):
	ExtremeValueVaR(other), xi(other.xi), beta(other.beta), u(other.u)
{}

double PoTVaR::operator()(const double& ratio) const
{
	double a = 1./ratio * getAlpha();

	return -(u +  beta * (pow(a,- xi) - 1.)/ xi );
}

double PoTVaR::expectedShortfall(const double& ratio) const
{
	return ((this->operator()(ratio) - (beta - xi * u)))/(1. - xi);

}

double PoTVaR::expectedShortfall(const Vec& returns) const{

	double ratio(0.);

	for(size_t i =0;i < returns.size();++i){
        if(returns[i] < 0)
            if(-returns[i] > u) ratio +=1;
	}

	ratio /= returns.size();
    if(ratio < .05) ratio = .05;

	return this->expectedShortfall(ratio);
}

double PoTVaR::operator()(const Vec& returns) const{

	double ratio(0.);

	for(size_t i =0;i < returns.size();++i){
        if(returns[i] < 0)
            if(-returns[i] > u) ratio +=1;
	}

	ratio /= returns.size();
    if(ratio < .05) ratio = .05;

	return this->operator()(ratio);
}


//
//  MathUtil.cpp
//  edgeRuntime
//
//  Created by Abdelrahaman Aly on 04/02/14.
//
//

//Library Headers
#include <NTL/ZZ.h>
#include <NTL/ZZ_p.h>

//Custom Headers
#include "List.h"
#include "MathUtil.h"
using namespace NTL;
namespace Utilities
{
    //less significative bit on the left always most significative bit on the right always
    int * MathUtil::obtainBits(long number, int size)
    {
        int * bits= new int[size];
        for (int i=0; i<size; i++)
        {

            if (number&1)
            {

                bits[i]=1;
            }
            else
            {
                bits[i]=0;
            }

            number>>=1;

        }
        return bits;
    };

    //Calculates the lagrangian interpolation. Currently optimized for 3 players
    long MathUtil::lagrangianInterpolation( long * values, int size)
    {
        //TODO: build the lagrangian interpolation

        ZZ_p  result;
        result=2*conv<ZZ_p>(values[0]) -conv<ZZ_p>(values[1]);
        long resultLong =conv<long>(result);
        return  resultLong;
    };

    //calculates the complement 2 adding first aone and then decomposing into bits
    int* MathUtil::obtainComplementTwo(long  value, int size)
    {
        value=~value;
        value++;
        return MathUtil::obtainBits(value, size);
    };

    //obtains the additive of 2 mod values
    long MathUtil::additionMod(long a, long b)
    {
        ZZ_p ap= conv<ZZ_p>(a);
        ZZ_p bp= conv<ZZ_p>(b);
        return conv<long>(a+b);
    };

    //Obteins the multiplicative of 2 mod values
    long MathUtil::multiplyMod(long a, long b)
    {
        ZZ_p ap= conv<ZZ_p>(a);
        ZZ_p bp= conv<ZZ_p>(b);
        return conv<long>(a*b);
    };

    //An specification on generic multiplier of polynomials
    ZZ_pX MathUtil::multiplyLagrangePolynomials(vec_ZZ_p x_v, ZZ_p x_j)
    {

        ZZ_p x_d= x_j-x_v[0];
        ZZ_p a= 1/x_d;
        ZZ_pX p;
        p.SetLength(2);
        p[0]= (-1)*x_v[0]*a;
        p[1]= a;

        for (int k=1; k< x_v.length(); k++)
        {
            ZZ_p x_k =x_v[k];
            x_d= x_j-x_k;
            a= 1/x_d;

            ZZ_pX auxP;
            auxP.SetLength(2);
            auxP[0]= (-1)*x_k*a;
            auxP[1]=a;

            p=p*auxP;
        }
        return p;
    };

    //Interpolations:
    ZZ_pX MathUtil::multiplyLagrangePolynomials(int x_s, int x_k,int x_j)
    {
        vec_ZZ_p values;
        values.SetLength((x_k+1)-x_s -1);
        int j=0;
        for (int i = x_s; i<=x_k; i++)
        {
            if (i!= x_j) {
               values[j]= conv<ZZ_p>(i);
               j++;
            }

        }
        return MathUtil::multiplyLagrangePolynomials(values, conv<ZZ_p>(x_j));
    };

    int MathUtil::pow2roundup (int value)
    {
        int x=value;
        if (x < 0)
            return 0;
        --x;
        x |= x >> 1;
        x |= x >> 2;
        x |= x >> 4;
        x |= x >> 8;
        x |= x >> 16;
        return x+1;
    }
}


#include <Eigen/Eigenvalues>
#include <boost/timer/timer.hpp>
#include <iostream>

#include "eigen-qp.hpp"

using namespace std;
using namespace Eigen;
using namespace EigenQP;
/*
 *  min 0.5 x.Q.x + c.x
 *
 *  Ax <= b
 *  Ex = d
 *
 * See: http://etd.dtu.dk/thesis/220437/ep08_19.pdf
 */
// #define NV_FIXED 8
// #define NC_FIXED 16
// #define NE_FIXED 3

#define PROB_VARS 8
#define PROB_INEQ 16
#define PROB_EQ 3

#define N_TEST   (1<<16)

template<typename Scalar, int NV_FIXED, int NC_FIXED, int NE_FIXED>
void test()
{

    typedef Eigen::Matrix<Scalar,-1,-1> MatrixXs;
    typedef Eigen::Matrix<Scalar,-1,1> VectorXs;

    // Make a random problem
    int num_vars = NV_FIXED;
    int num_ineq = NC_FIXED;
    int num_eq   = NE_FIXED;

    // Random matrices
    MatrixXs Q = MatrixXs::Random(num_vars,num_vars);
    Q *= Q.adjoint()/sqrt(num_vars); // Make it pos def

    VectorXs c = VectorXs::Random(num_vars);

    MatrixXs A = MatrixXs::Random(num_ineq,num_vars);
    VectorXs b = VectorXs::Random(num_ineq);

    MatrixXs E = MatrixXs::Random(num_eq,num_vars);
    VectorXs f = VectorXs::Random(num_eq);

    VectorXs x_unc;
    // Solve unconstrainted system
    cout << "Unconstrained..." << endl;
    {
        boost::timer::auto_cpu_timer t;
        for (int ii=0; ii < N_TEST; ii++)
          x_unc = -Q.ldlt().solve(c);
    }
    VectorXs x(num_vars);
    // Generate inequality constraints
    b.array() = (A*x_unc).array() - 0.15;
    // Inequality constrained problem
    cout << "quadprog, dynamic code" << endl;
    {
        boost::timer::auto_cpu_timer t;
        for (int ii=0; ii < N_TEST; ii++)
            quadprog(Q,c,A,b,x);
    }
    cout << "    error: " << (x - x_unc).norm() << endl;
    {
        QPIneqSolver<Scalar,-1,-1> *solver;
        cout <<"QPIneqSolver, dynamic, obj creation" << endl;
        {
            boost::timer::auto_cpu_timer t;
            for (int ii=0; ii < N_TEST; ii++)
            {
                solver = new QPIneqSolver<Scalar,-1,-1>(num_vars,num_ineq);
                solver->solve(Q,c,A,b,x);
            }
        }
        cout << "    error: " << (x - x_unc).norm() << endl;
        cout << "QPIneqSolver, dynamic, object reuse" << endl;
        {
            boost::timer::auto_cpu_timer t;
            for (int ii=0; ii < N_TEST; ii++)
                solver->solve(Q,c,A,b,x);
        }
        cout << "    error: " << (x - x_unc).norm() << endl;
    }

    // Fixed size
    Matrix<Scalar, NV_FIXED,NV_FIXED> Q_fixed(Q);
    Matrix<Scalar, NV_FIXED, 1> c_fixed(c);
    Matrix<Scalar, NC_FIXED,NV_FIXED> A_fixed(A);
    Matrix<Scalar, NC_FIXED,1> b_fixed(b);

    // Q_fixed.setRandom();
    // c_fixed.setRandom();
    // A_fixed.setRandom();

    x_unc = -Q_fixed.ldlt().solve(c_fixed);

    b_fixed.array() = (A_fixed*x_unc).array() - 0.12;

    Matrix<Scalar, NV_FIXED, 1> x_fixed;
    cout << "quadprog, fixed code" << endl;
    {
        boost::timer::auto_cpu_timer t;
        for (int ii=0; ii < N_TEST; ii++)
            quadprog(Q_fixed,c_fixed,A_fixed,b_fixed,x_fixed);
    }
    cout << "    error: " << (x_fixed - x_unc).norm() << endl;
    {
        QPIneqSolver<Scalar,NV_FIXED,NC_FIXED> *solver;
        cout << "QPIneqSolver, fixed" << endl;
        {
            boost::timer::auto_cpu_timer t;
            for (int ii=0; ii < N_TEST; ii++)
            {
                solver = new QPIneqSolver<Scalar,NV_FIXED,NC_FIXED>(num_vars,num_ineq);
                solver->solve(Q_fixed,c_fixed,A_fixed,b_fixed,x_fixed);
            }
        }
        cout << "    error: " << (x_fixed - x_unc).norm() << endl;
        cout << "QPIneqSolver, fixed, object reuse" << endl;
        {
            boost::timer::auto_cpu_timer t;
            for (int ii=0; ii < N_TEST; ii++)
                solver->solve(Q_fixed,c_fixed,A_fixed,b_fixed,x_fixed);
        }
        cout << "    error: " << (x_fixed - x_unc).norm() << endl;
    }

    cout << "QPEqSolver, equality constraints, dynamic" << endl;
    {
        QPEqSolver<Scalar> solver(num_vars,num_eq);
        {
            boost::timer::auto_cpu_timer t;
            for (int ii=0; ii < N_TEST; ii++)
                solver.solve(Q,c,E,f,x);
        }
    }

    /*
    // known to be broken
    cout << "quadprog, ineq/eq constraints, dynamic" << endl;
    {
        //b = A*x - 0.12;
        QPGenSolver<Scalar> solver(num_vars,num_ineq,num_eq);
        {
            boost::timer::auto_cpu_timer t;
            for (int ii=0; ii < N_TEST; ii++)
                solver.solve(Q,c,A,b,E,f,x);
        }
    }
    */
}

int main(int argc, char ** argv)
{
    srand((unsigned int) time(0));
    cout << "TESTING DOUBLE" << endl;
    test<double,PROB_VARS,PROB_INEQ,PROB_EQ>();
    cout << "TESTING FLOAT" << endl;
    test<float,PROB_VARS,PROB_INEQ,PROB_EQ>();
    return 0;
}


/**
 * \file
 *
 * \author Nicholas J. Curtis
 * \date 04/29/2016
 *
 * \brief Defines an interface for boost's runge_kutta_fehlberg78 solver
 *
*/

#ifndef RK78_TYPEDEFS_HPP
#define RK78_TYPEDEFS_HPP

#include <boost/numeric/odeint.hpp>
using namespace boost::numeric::odeint;

//our code
extern "C" {
	#include "dydt.h"
	#include "header.h"
	#include "solver_options.h"
}

#ifdef GENERATE_DOCS
namespace rk78 {
#endif

//! state vector
typedef std::vector< double > state_type;

//! solver type
typedef runge_kutta_fehlberg78< state_type , double > stepper;

//! controller type
typedef controlled_runge_kutta< stepper > controller;

//stiffness measure for project
//do a binary search to find the maximum available stepsize
#ifdef LOG_OUTPUT
//#define STIFFNESS_MEASURE
#endif
#ifdef STIFFNESS_MEASURE
#include <boost/numeric/odeint/stepper/controlled_step_result.hpp>
#endif

/**
   \brief A wrapper class to evaluate the rhs function y' = f(y)
   stores the state variable, and provides to dydt
*/
class rhs_eval {
	double m_statevar;
public:
	rhs_eval() {
		this->m_statevar = -1;
	}

	void set_state_var(const double state_var)
	{
		this->m_statevar = state_var;
	}

	//wrapper for the pyJac RHS fn
	void operator() (const state_type &y , state_type &fy , const double t) const
	{
		dydt(t, this->m_statevar, &y[0], &fy[0]);
	}
};

#ifdef GENERATE_DOCS
}
#endif

#endif


#include "NuiMatrixUtilities.h"

#include <Eigen/Geometry>

namespace NuiMatrixUtilities
{
	Vector3f rodrigues2(const Eigen::Matrix3f& matrix)
	{
		Eigen::JacobiSVD<Eigen::Matrix3f> svd(matrix, Eigen::ComputeFullV | Eigen::ComputeFullU);
		Eigen::Matrix3f R = svd.matrixU() * svd.matrixV().transpose();

		double rx = R(2, 1) - R(1, 2);
		double ry = R(0, 2) - R(2, 0);
		double rz = R(1, 0) - R(0, 1);

		double s = sqrt((rx*rx + ry*ry + rz*rz)*0.25);
		double c = (R.trace() - 1) * 0.5;
		c = c > 1. ? 1. : c < -1. ? -1. : c;

		double theta = acos(c);

		if( s < 1e-5 )
		{
			double t;

			if( c > 0 )
				rx = ry = rz = 0;
			else
			{
				t = (R(0, 0) + 1)*0.5;
				rx = sqrt( std::max(t, 0.0) );
				t = (R(1, 1) + 1)*0.5;
				ry = sqrt( std::max(t, 0.0) ) * (R(0, 1) < 0 ? -1.0 : 1.0);
				t = (R(2, 2) + 1)*0.5;
				rz = sqrt( std::max(t, 0.0) ) * (R(0, 2) < 0 ? -1.0 : 1.0);

				if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R(1, 2) > 0) != (ry*rz > 0) )
					rz = -rz;
				theta /= sqrt(rx*rx + ry*ry + rz*rz);
				rx *= theta;
				ry *= theta;
				rz *= theta;
			}
		}
		else
		{
			double vth = 1/(2*s);
			vth *= theta;
			rx *= vth; ry *= vth; rz *= vth;
		}
		return Eigen::Vector3d(rx, ry, rz).cast<float>();
	}
}


#ifndef EXPSUM_LSQR_HPP
#define EXPSUM_LSQR_HPP

#include <armadillo>

namespace expsum
{
///
/// lsqr
///
/// `lsqr` solves a least squares problem
///
/// ``` math
///   \min \| A\bm{x} - \bm{b} \|_{2},
/// ```
///
/// where ``$A \in \mathcal{C}^{m \times n}, \, \bm{b} \in \mathcal{C}^{n} $``
/// with ``$m \geq n$``.
///
/// @param[in]  matvec A function object that compute matrix-vector product
///   `y += A * x`
/// @param[in]  matvec_trans A function object that compute matrix-vector
///   product `y += A.t() * x`
/// @param[inout] u A vector of length m. On input the right hand side vector
///     ``$b$``, on exit, `u` is overwritten.
/// @param[out] x A vector of length n. On input and initial guess of solution,
///    on exit, the computed solution.
/// @param[in] precond_solve Functor for applying preconditioner to a vector.
/// @param[out] work A matrix of size ``$n \times 3$`` used as workspace.
/// @param[inout] iterations  On input the max number of iteration, on exit the
///    number of performed iterations.
/// @param[inout] tol_error  On input the tolerance error, on exit as estimation
///    of the relative error.
///

template <typename MatVec, typename MatVecTrans, typename VectorU,
          typename VectorX, typename Preconditioner, typename MatrixWork>
void lsqr(MatVec matvec, MatVecTrans matvec_trans, VectorU& u, VectorX& x,
          const Preconditioner& apply_preconditioner, MatrixWork& work,
          arma::uword& iterations, typename VectorX::pod_type& tol_error)
{
    using value_type = typename VectorX::elem_type;
    using real_type  = typename VectorX::pod_type;
    using size_type  = arma::uword;

    using std::sqrt;
    using std::real;
    using std::abs;
    using std::norm;

    const real_type atol = tol_error;
    const real_type btol = tol_error;

    auto p = work.col(0);
    auto v = work.col(1);
    auto w = work.col(2);
    //
    // --- Initialization
    //
    x.zeros();
    real_type alpha = real_type();
    real_type beta  = arma::norm(u);
    if (beta > real_type())
    {
        u *= real_type(1) / beta;         // normalize
        matvec_trans(u, value_type(), p); // p <-- A.t() * u;
        apply_preconditioner(p, v);       // v <-- M.inv() * p
        alpha = sqrt(real(arma::cdot(v, p)));
        if (alpha > real_type())
        {
            v *= real_type(1) / alpha; // normalize
            w = v;
        }
    }

    // Estimation of the norm of `A.t() * r`
    real_type norm_Atr = alpha * beta;
    if (norm_Atr == real_type())
    {
        // x = 0 is the exact solution
        return;
    }

    real_type rhobar = alpha;
    real_type phibar = beta;

    // Estimations of the Frobenius norm of matrix A
    real_type norm_A = real_type();
    // Norm of r.h.s. vector b
    real_type norm_b = beta;
    // Estimation of the norm of residual vector `r = b - A * x`.
    real_type norm_r = beta;
    // Estimation of the norm of solution vector x.
    real_type norm_x = real_type();

    real_type cs2     = real_type(-1);
    real_type sn2     = real_type();
    real_type z       = real_type();
    real_type norm_bb = real_type();
    real_type norm_xx = real_type();

    size_type iter = 0;
    while (++iter <= iterations)
    {
        //
        // --- Bidiagonalization
        //
        // Perform the next step of the bidiagonalization with M-weighted inner
        // product.  `beta, u, alpha, v`. These satisfy the relations
        //
        // ``` math
        //  \beta_{i+1} \bm{u}_{i+1}
        //    &= A \bm{v}_{i} - \alpha_{i} \bm{u}_{i},
        //  \alpha_{i+1} \bm{v}_{i+1}
        //    &= M^{-1} A^{H} \bm{u}_{i+1} - \beta_{i+1} \bm{v}_{i},
        //  \alpha_{i+1} &= (\bm{v}_{i+1}^{H} M \bm{v}_{i+1}^{})^{1/2}
        // ```
        //
        matvec(v, -alpha, u); // u <-- A * v - alpha * u
        beta = arma::norm(u);
        norm_bb += norm(alpha) + norm(beta);

        if (beta > real_type())
        {
            u *= real_type(1) / beta;
            matvec_trans(u, -beta, p);  // p <-- A.t() * u - beta * p
            apply_preconditioner(p, v); // v <-- M.inv() * p
            alpha = sqrt(real(arma::cdot(v, p)));
            if (alpha > real_type())
            {
                v *= real_type(1) / alpha;
            }
        }
        //
        // --- Orthogonal transformation
        //
        // Construct and apply next orthogonal transformation (plane rotation)
        // to eliminate the subdiagonal element (beta) of the lower-bidiagonal
        // matrix, giving an upper-bidiagonal matrix. The explicit form of the
        // transformation is given as
        //
        // [cs  sn][rhobar      0  phibar]   [rho   theta     phi ]
        // [sn -cs][  beta  alpha       0] = [  0  rhobar' phibar']
        //
        real_type rho   = sqrt(norm(rhobar) + norm(beta));
        real_type cs    = rhobar / rho;
        real_type sn    = beta / rho;
        real_type theta = sn * alpha;
        rhobar          = -cs * alpha;
        real_type phi   = cs * phibar;
        phibar *= sn;
        //
        // Update vectors
        //
        // norm_dd += (w / rho).squaredNorm();
        x += (phi / rho) * w;
        w = v - (theta / rho) * w;
        //
        // Estimate norm of x using the result of plane rotation
        //
        real_type delta     = sn2 * rho;
        real_type gamma_bar = -cs2 * rho;
        real_type rhs       = phi - delta * z;
        real_type zbar      = rhs / gamma_bar;
        norm_x              = sqrt(norm_xx + norm(zbar));
        real_type gamma     = sqrt(norm(gamma_bar) + norm(theta));
        cs2                 = gamma_bar / gamma;
        sn2                 = theta / gamma;
        z                   = rhs / gamma;
        norm_xx += norm(z);

        //
        // Test for convergence.
        //
        norm_A = sqrt(norm_bb);
        // cond_A   = norm_A * sqrt(norm_dd);
        norm_r   = phibar;
        norm_Atr = phibar * alpha * abs(cs);
        //
        // Stop iteration if
        //
        // |A^{T} \bm{r}|_{F} / |A^{T}|_F |\bm{r}| < tol
        //
        // if (norm_Atr <= norm_A * norm_r * tol_error)
        // {
        //     break;
        // }
        if (norm_r <= btol * norm_b + atol * norm_A * norm_x)
        {
            break;
        }
    }

    tol_error  = norm_r;
    iterations = iter;
}

} // namespace expsum

#endif /* EXPSUM_LSQR_HPP */


#include <iostream>
#include <iomanip>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/math/constants/constants.hpp>
typedef boost::multiprecision::cpp_dec_float_50 decfloat;

int main()
{
    const decfloat ln_two = boost::math::constants::ln_two<decfloat>();
    decfloat numerator = 1, denominator = ln_two;

    for(int n = 1; n <= 17; n++) {
        decfloat h = (numerator *= n) / (denominator *= ln_two) / 2;
        decfloat tenths_dig = floor((h - floor(h)) * 10);
        std::cout << "h(" << std::setw(2) << n << ") = " << std::setw(25) << std::fixed << h <<
            (tenths_dig == 0 || tenths_dig == 9 ? " is " : " is NOT ") << "an almost-integer.\n";
    }
}


/**
 * @file uniformcubicspline.cc
 * @brief NPDE exam problem summer 2019 "CLEmpiricFlux" code
 * @author Oliver Rietmann
 * @date 18.07.2019
 * @copyright Developed at ETH Zurich
 */

#include "uniformcubicspline.h"

#include <Eigen/Core>
#include <cassert>

namespace {

template <typename T>
constexpr T Square(T x) {
  return x * x;
}

template <typename T>
constexpr T Cube(T x) {
  return x * x * x;
}

constexpr int getJ(double a, double b, unsigned int n, double u) {
  return u < b ? (int)(n * ((u - a) / (b - a)) + 1.0) : n;
}

constexpr double zeta(double a, double b, unsigned int n, double j) {
  return a + j * (b - a) / n;
}

}  // namespace

namespace CLEmpiricFlux {

UniformCubicSpline::UniformCubicSpline(double a, double b, Eigen::VectorXd f,
                                       Eigen::VectorXd M)
    : _n(f.size() - 1), _a(a), _b(b), _f(std::move(f)), _M(std::move(M)) {
  assert(b >= a);
  assert(_f.size() >= 2);
  assert(_f.size() == _M.size());
}

double UniformCubicSpline::operator()(double u) const {
  assert((u >= _a) && (u <= _b));
  int j = getJ(_a, _b, _n, u);
  double h = (_b - _a) / _n;
  double tau = (u - zeta(_a, _b, _n, j - 1)) / h;

  return _f(j) * tau + _f(j - 1) * (1.0 - tau) +
         Square(h) / 6.0 *
             (_M(j) * (Cube(tau) - tau) +
              _M(j - 1) * (-Cube(tau) + 3.0 * Square(tau) - 2.0 * tau));
}

double UniformCubicSpline::derivative(double u) const {
  assert((u >= _a) && (u <= _b));
  int j = getJ(_a, _b, _n, u);
  double h = (_b - _a) / _n;
  double tau = (u - zeta(_a, _b, _n, j - 1)) / h;

  return (_f(j) - _f(j - 1) +
          Square(h) / 6.0 *
              (_M(j) * (3.0 * Square(tau) - 1.0) +
               _M(j - 1) * (-3.0 * Square(tau) + 6.0 * tau - 2.0))) *
         (1.0 / h);
}

}  // namespace CLEmpiricFlux