#include "Util.h"

#include "navtypes.h"

#include <iostream>
#include <random>
#include <time.h>

#include <Eigen/LU>
#include <sys/time.h>

using namespace navtypes;

namespace util {
bool almostEqual(double a, double b, double threshold) {
	return std::abs(a - b) < threshold;
}

double quatToHeading(double qw, double qx, double qy, double qz) {
	Eigen::Quaterniond quat(qw, qx, qy, qz);
	return quatToHeading(quat);
}

double quatToHeading(Eigen::Quaterniond quat) {
	quat.normalize();
	Eigen::Matrix3d rotMat = quat.toRotationMatrix();
	Eigen::Vector3d transformedX = rotMat * Eigen::Vector3d::UnitX();
	// flatten to xy-plane
	transformedX(2) = 0;
	// recover heading
	double heading = std::atan2(transformedX(1), transformedX(0));
	return heading;
}

ScopedTimer::ScopedTimer(std::string name)
	: startTime(std::chrono::high_resolution_clock::now()), name(std::move(name)) {}

ScopedTimer::ScopedTimer() : ScopedTimer("") {}

ScopedTimer::~ScopedTimer() {
	if (!name.empty()) {
		auto now = std::chrono::high_resolution_clock::now();
		auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - startTime);
		std::cout << "[" << name << "] ElapsedTime: " << elapsed.count() << "us\n";
	}
}

std::chrono::microseconds ScopedTimer::elapsedTime() const {
	auto now = std::chrono::high_resolution_clock::now();
	auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - startTime);
	return elapsed;
}

points_t transformReadings(const points_t& ps, const transform_t& tf) {
	transform_t tf_inv = tf.inverse();
	points_t readings({});
	for (point_t p : ps) {
		readings.push_back(tf_inv * p);
	}
	return readings;
}

trajectory_t transformTraj(const trajectory_t& traj, const transform_t& tf) {
	trajectory_t tf_traj({});
	for (const transform_t& tf_i : traj) {
		tf_traj.push_back(tf_i * tf);
	}
	return tf_traj;
}

bool collides(const transform_t& tf, const points_t& ps, double radius) {
	for (const point_t& p : ps) {
		if (p(2) == 0.0) {
			// This point is a "no data" point
			continue;
		}
		point_t tf_p = tf * p;
		tf_p(2) = 0;
		if (tf_p.norm() < radius)
			return true;
	}
	return false;
}

transform_t toTransformRotateFirst(double x, double y, double theta) {
	transform_t m;
	m << cos(theta), sin(theta), -x, -sin(theta), cos(theta), -y, 0, 0, 1;
	return m;
}

double closestHeading(double theta, double prev_theta) {
	while (theta < prev_theta - M_PI)
		theta += 2 * M_PI;
	while (theta > prev_theta + M_PI)
		theta -= 2 * M_PI;
	return theta;
}

pose_t toPose(const transform_t& trf, double prev_theta) {
	pose_t s = trf.inverse() * pose_t(0, 0, 1);
	double cos_theta = trf(0, 0);
	double sin_theta = -trf(1, 0);
	double theta = atan2(sin_theta, cos_theta);
	s(2) = closestHeading(theta, prev_theta);
	return s;
}

transform_t toTransform(const pose_t& pose) {
	return toTransformRotateFirst(0, 0, pose(2)) * toTransformRotateFirst(pose(0), pose(1), 0);
}

/**
 * There still might be some variation due to the dependence of the robot position
 * on when exactly each context switch occurs.
 *
 * For programs with more threads, a more sophisticated solution will be necessary.
 */
static std::normal_distribution<double> stdn_dist(0.0, 1.0);
static long seed = std::chrono::system_clock::now().time_since_epoch().count();
// long seed = 1626474823108702150;
static std::default_random_engine main_generator(seed);
static std::default_random_engine spin_generator(seed);

long getNormalSeed() {
	return seed;
}

double stdn(int thread_id) {
	return stdn_dist(thread_id == 0 ? main_generator : spin_generator);
}

} // namespace util


/*
# This file is part of the Astrometry.net suite.
# Licensed under a 3-clause BSD style license - see LICENSE
 */
//#include <iostream>
#include <Eigen/Dense>
//using namespace std;
using namespace Eigen;

extern "C" {

#include "eigen-math.h"
#include "stdio.h"

#if 0
} // fool emacs indenter
#endif

int eigen_solve_least_squares(ematrix_t* A, evector_t** B,
                               evector_t** X, int NB) {
    int i;
    int r,c;

    Map<Matrix<double, Dynamic, Dynamic, RowMajor> >
        mA(A->data, A->rows, A->cols);

    /*
     printf("mA:\n");
     for (r=0; r<mA.rows(); r++) {
     printf("[");
     for (c=0; c<mA.cols(); c++) {
     printf("%s %8.3g", c ? "," : " ", mA(r,c));
     }
     printf("]\n");
     }
     */

    /*
     for (i=0; i<NB; i++) {
     printf("mB(%i):\n", i);
     Map<VectorXd> mB(B[i]->data, B[i]->N, RowMajor);
     printf("[");
     for (c=0; c<mB.size(); c++) {
     printf("%s %8.3g", c ? "," : " ", mB(c));
     }
     printf("]\n");
     }
     */

    JacobiSVD<MatrixXd> svd(mA, ComputeThinU | ComputeThinV);
    for (i=0; i<NB; i++) {
        Map<VectorXd> b(B[i]->data, B[i]->N, RowMajor);
        VectorXd x = svd.solve(b);
        // copy results back to C space...
        for (r=0; r<x.size(); r++)
            evector_set(X[i], r, x[r]);
    }

    return 0;
}

#if 0
{ // fool emacs indenter
#endif
}


#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <NTL/ZZ.h>

using namespace std;
using namespace NTL;

#include "iterative.h"
#include "recursive.h"

using namespace std;
using namespace NTL;
using namespace chrono;

//#define ITERATIVE

void usage_example_zp(uint npoints, uint flen){
    long degree = npoints-1;

    ZZ prime;
    GenPrime(prime, flen);
    ZZ_p::init(prime);

//  interpolation points:
    ZZ_p* X = new ZZ_p[degree+1];
    ZZ_p* Y = new ZZ_p[degree+1];
    for(unsigned int i=0;i<=degree; i++) {
        random(X[i]);
        random(Y[i]);
    }

    ZZ_pX P;
#ifdef ITERATIVE
    poly_interpolate_zp_iterative(degree, X, Y, P);
#else
    poly_interpolate_zp_recursive(degree, X, Y, P);
#endif

    // EVALUATE
    ZZ_p* X2 = new ZZ_p[degree+1];
    ZZ_p* Y2 = new ZZ_p[degree+1];
    for(unsigned int i=0;i<=degree; i++) {
        random(X[i]);
    }
#ifdef ITERATIVE
    poly_evaluate_zp_iterative(degree, P, X2, Y2);
#else
    poly_evaluate_zp_recursive(degree, P, X2, Y2);
#endif

    delete[] X;
    delete[] Y;
    delete[] X2;
    delete[] Y2;
}

int main(int argc, char *argv[]) {
   uint num_points = pow(2,13)-1;
   uint field_bitlen = 400;
    if(1<argc)
	num_points = atoi(argv[1]);
    if(2<argc)
    	field_bitlen = atoi(argv[2]);
    cout << "num_points: " << num_points << ", field_bitlen: " << field_bitlen << endl;
    usage_example_zp(num_points, field_bitlen);

}


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

#include "math_unit_test.hpp"
#include <numeric>
#include <utility>
#include <random>
#include <boost/core/demangle.hpp>
#include <boost/math/distributions/empirical_cumulative_distribution_function.hpp>
#ifdef BOOST_HAS_FLOAT128
#include <boost/multiprecision/float128.hpp>
using boost::multiprecision::float128;
#endif

using boost::math::empirical_cumulative_distribution_function;

template<class Z>
void test_uniform_z()
{
    std::vector<Z> v{6,3,4,1,2,5};

    auto ecdf = empirical_cumulative_distribution_function(std::move(v));

    CHECK_ULP_CLOSE(1.0/6.0, ecdf(1), 1);
    CHECK_ULP_CLOSE(2.0/6.0, ecdf(2), 1);
    CHECK_ULP_CLOSE(3.0/6.0, ecdf(3), 1);
    CHECK_ULP_CLOSE(4.0/6.0, ecdf(4), 1);
    CHECK_ULP_CLOSE(5.0/6.0, ecdf(5), 1);
    CHECK_ULP_CLOSE(6.0/6.0, ecdf(6), 1);

    // Less trivial:

    v = {6,3,4,1,1,1,2,4};
    ecdf = empirical_cumulative_distribution_function(std::move(v));
    CHECK_ULP_CLOSE(3.0/8.0, ecdf(1), 1);
    CHECK_ULP_CLOSE(4.0/8.0, ecdf(2), 1);
    CHECK_ULP_CLOSE(5.0/8.0, ecdf(3), 1);
    CHECK_ULP_CLOSE(7.0/8.0, ecdf(4), 1);
    CHECK_ULP_CLOSE(7.0/8.0, ecdf(5), 1);
    CHECK_ULP_CLOSE(8.0/8.0, ecdf(6), 1);
}

template<class Real>
void test_uniform()
{
    size_t n = 128;
    std::vector<Real> v(n);
    for (size_t i = 0; i < n; ++i) {
      v[i] = Real(i+1)/Real(n);
    }

    auto ecdf = empirical_cumulative_distribution_function(std::move(v));

    for (size_t i = 0; i < n; ++i) {
      CHECK_ULP_CLOSE(Real(i+1)/Real(n), ecdf(Real(i+1)/Real(n)), 1);
    }
}

int main()
{
    test_uniform_z<int>();
    test_uniform<double>();
    return boost::math::test::report_errors();
}


/**
 * @file 	ex6.cpp
 * @author 	Fabian Wegscheider
 * @date 	Jun 20, 2017
 */

#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/heap/fibonacci_heap.hpp>
#include <boost/timer/timer.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/spirit/include/qi.hpp>

using namespace std;
using namespace boost;
namespace po = boost::program_options;

typedef adjacency_list<vecS, vecS, undirectedS,
		no_property, property<edge_weight_t, double>> Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef pair<int,int> Edge;
typedef pair<int, double> Pair;
typename graph_traits<Graph>::out_edge_iterator out_i, out_end;

/**
 * Data that is stored in one node of a heap. Contains an integer and a double.
 * Comparisons are made by the double, smaller has higher priority
 */
struct heap_data
{
    heap::fibonacci_heap<heap_data>::handle_type handle;
    Pair pair;

    heap_data(Pair p):
        pair(p)
    {}

    bool operator<(heap_data const & rhs) const {
        return pair.second > rhs.pair.second;
    }
};

using Heap = heap::fibonacci_heap<heap_data>;

/**
 * My own implementation of Dijkstra using a fibonacci heap from boost
 * @param g the graph which is an adjacency_list from boost
 * @param numVertices the number of vertices in g
 * @param source the source node for Dijkstra
 * @return vector of resulting distances to source
 */
vector<double> myDijkstra(Graph& g, int numVertices, int source) {

	vector<double> distances(numVertices);
	distances[0] = 0;

	Heap heap;

	Heap::handle_type *handles = new Heap::handle_type[numVertices];
	handles[0] = heap.push(make_pair(0,0.));

	//initialization of the heap
	for (int i = 1; i < numVertices; ++i) {
		handles[i] = heap.push(make_pair(i, numeric_limits<double>::infinity()));
		distances[i] = numeric_limits<double>::infinity();
	}

	property_map<Graph, edge_weight_t>::type weights = get(edge_weight, g);
	property_map<Graph, vertex_index_t>::type index = get(vertex_index, g);

	//the actual algorithm
	while (!heap.empty()) {
		Pair min = heap.top().pair;
		heap.pop();
		for (tie(out_i, out_end) = out_edges(*(vertices(g).first+min.first), g);
				out_i != out_end; ++out_i) {
			double tmp = min.second + weights[*out_i];
			int targetIndex = index[target(*out_i, g)];
			if (tmp < distances[targetIndex]) {
				distances[targetIndex] = tmp;
				(*handles[targetIndex]).pair.second = tmp;
				heap.increase(handles[targetIndex]);
			}
		}
	}

	delete[] handles;
	return distances;
}

/**
 * main function which reads a graph from a .gph file, then calculates shortest
 * paths from all vertices to the first vertex with the dijsktra algorithm
 * and prints the furthest vertex together with its distance
 * to the standard output
 * @param numargs number of inputs on command line
 * @param args array of * inputs on command line
 * @return whether the function operated successfully
 */
int main(int numargs, char *args[]) {

	timer::cpu_timer t;
	bool useOwnMethod;

	/*parsing command line options*/
	po::options_description desc("Allowed options");
	desc.add_options()
			("help,h", "produce help message")
			("m1", "use my own dijkstra method")
			("m2", "use dijkstra method from boost")
			("input-file", po::value< string >(), "input file");
	po::positional_options_description p;
	p.add("input-file", -1);
	po::variables_map vm;
	po::store(po::command_line_parser(numargs, args).
			options(desc).positional(p).run(), vm);
	po::notify(vm);

	if (vm.count("help")) {
	    cout << desc << "\n";
	   	exit(EXIT_SUCCESS);
	}

	if (vm.count("m1") && !vm.count("m2")) {
		useOwnMethod = true;
		cout << "using my own method for calculation..." << endl << endl;
	} else if (vm.count("m2") && !vm.count("m1")) {
		useOwnMethod = false;
		cout << "using boost method for calculation..." << endl << endl;
	} else {
		cerr << "please specify the method you want to use (type -h for help)" << endl;
		exit(EXIT_FAILURE);
	}

	string input;
	if (vm.count("input-file")) {
	    input = vm["input-file"].as< string >();
	} else {
		cerr << "please specify an input file in the .gph format" << endl;
		exit(EXIT_FAILURE);
	}
	/*end of parsing command line options*/

	ifstream inputFile;
	inputFile.open(input);							//trying to read file
	if (inputFile.fail()) {
		cerr << "file could not be read" << endl;
		exit(EXIT_FAILURE);
	}

	int numVertices;
	int numEdges;

	string line;
	getline(inputFile, line);					//first line is read
	vector<string> parts;
	split(parts, line, is_any_of(" "));

	if (parts.size() != 2) {
		cerr << "error in file: first line should consist of two integers!" << endl;
		exit(EXIT_FAILURE);
	}

	try {
		numVertices = stoi(parts[0]);		//information from the first line
		numEdges = stoi(parts[1]);			//are stored
	} catch (...) {
		cerr << "error in file: first line should consist of two integers!" << endl;
		exit(EXIT_FAILURE);
	}

	Edge *edges =  new Edge[numEdges];			//in these arrays all information about
	double *weights = new double[numEdges];		//the edges are stored

	int i = 0;

	using namespace boost::spirit;
	using qi::int_;
	using qi::double_;
	using qi::phrase_parse;
	using ascii::space;

	//read line by line using boost to parse each line to int,int,double
	while (getline(inputFile, line)) {
		try {
			auto it = line.begin();
			int start;
			int end;
			double weight;
			bool success = phrase_parse(it, line.end(),
					int_[([&start](int j){ start = j; })]
					>> int_[([&end](int j){ end = j; })]
					>> double_[([&weight](double j){ weight = j; })], space);
			if (success && it == line.end()) {
				edges[i] = Edge(start-1, end-1);
				weights[i] = weight;
			} else {
				cerr << "error in line " << (i+2) << ": line should consists of "
						"two integers and a double!" << endl;
				exit(EXIT_FAILURE);
			}
		} catch(...) {
			cerr << "error in line " << (i+2) << ": line should consists of "
					"two integers and a double!" << endl;
			exit(EXIT_FAILURE);
		}
		++i;
	}

	//undirected graph is constructed with all edges and their weights
	Graph g(edges, edges + numEdges , weights, numVertices);

	//in this vector the resulting distances from dijkstra are stored
	vector<double> distances;

	//call of dijsktra depending on chosen option
	if (!useOwnMethod) {
		distances.resize(numVertices);
		dijkstra_shortest_paths(g, *(vertices(g).first), distance_map(&distances[0]));
	} else {
		distances = myDijkstra(g, numVertices, 0);
	}

	double maxDist = 0;
	int maxIdx = 0;

	//search for furthest vertex
	for (int i = 1; i < numVertices; i++) {
		double tmp = distances[i];
			if (tmp > maxDist) {
				maxDist = tmp;
				maxIdx = i;
			}
	}

	//results are printed to command line
	cout << "RESULT VERTEX " << (maxIdx+1) << endl;
	cout << "RESULT DIST " << maxDist << endl;
	cout << endl << "running time: " << t.format() <<  endl;

	delete[] edges;
	delete[] weights;

	exit(EXIT_SUCCESS);
}


// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <Eigen/LU>
#include <Eigen/Cholesky>
#include <Eigen/QR>

// This file test inplace decomposition through Ref<>, as supported by Cholesky, LU, and QR decompositions.

template<typename DecType,typename MatrixType> void inplace(bool square = false, bool SPD = false)
{
  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RhsType;
  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ResType;

  Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random<Index>(2,EIGEN_TEST_MAX_SIZE/2) : Index(MatrixType::RowsAtCompileTime);
  Index cols = MatrixType::ColsAtCompileTime==Dynamic ? (square?rows:internal::random<Index>(2,rows))    : Index(MatrixType::ColsAtCompileTime);

  MatrixType A = MatrixType::Random(rows,cols);
  RhsType b = RhsType::Random(rows);
  ResType x(cols);

  if(SPD)
  {
    assert(square);
    A.topRows(cols) = A.topRows(cols).adjoint() * A.topRows(cols);
    A.diagonal().array() += 1e-3;
  }

  MatrixType A0 = A;
  MatrixType A1 = A;

  DecType dec(A);

  // Check that the content of A has been modified
  VERIFY_IS_NOT_APPROX( A, A0 );

  // Check that the decomposition is correct:
  if(rows==cols)
  {
    VERIFY_IS_APPROX( A0 * (x = dec.solve(b)), b );
  }
  else
  {
    VERIFY_IS_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
  }

  // Check that modifying A breaks the current dec:
  A.setRandom();
  if(rows==cols)
  {
    VERIFY_IS_NOT_APPROX( A0 * (x = dec.solve(b)), b );
  }
  else
  {
    VERIFY_IS_NOT_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
  }

  // Check that calling compute(A1) does not modify A1:
  A = A0;
  dec.compute(A1);
  VERIFY_IS_EQUAL(A0,A1);
  VERIFY_IS_NOT_APPROX( A, A0 );
  if(rows==cols)
  {
    VERIFY_IS_APPROX( A0 * (x = dec.solve(b)), b );
  }
  else
  {
    VERIFY_IS_APPROX( A0.transpose() * A0 * (x = dec.solve(b)), A0.transpose() * b );
  }
}

void test_inplace_decomposition()
{
  EIGEN_UNUSED typedef Matrix<double,4,3> Matrix43d;
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1(( inplace<LLT<Ref<MatrixXd> >, MatrixXd>(true,true) ));
    CALL_SUBTEST_1(( inplace<LLT<Ref<Matrix4d> >, Matrix4d>(true,true) ));

    CALL_SUBTEST_2(( inplace<LDLT<Ref<MatrixXd> >, MatrixXd>(true,true) ));
    CALL_SUBTEST_2(( inplace<LDLT<Ref<Matrix4d> >, Matrix4d>(true,true) ));

    CALL_SUBTEST_3(( inplace<PartialPivLU<Ref<MatrixXd> >, MatrixXd>(true,false) ));
    CALL_SUBTEST_3(( inplace<PartialPivLU<Ref<Matrix4d> >, Matrix4d>(true,false) ));

    CALL_SUBTEST_4(( inplace<FullPivLU<Ref<MatrixXd> >, MatrixXd>(true,false) ));
    CALL_SUBTEST_4(( inplace<FullPivLU<Ref<Matrix4d> >, Matrix4d>(true,false) ));

    CALL_SUBTEST_5(( inplace<HouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
    CALL_SUBTEST_5(( inplace<HouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));

    CALL_SUBTEST_6(( inplace<ColPivHouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
    CALL_SUBTEST_6(( inplace<ColPivHouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));

    CALL_SUBTEST_7(( inplace<FullPivHouseholderQR<Ref<MatrixXd> >, MatrixXd>(false,false) ));
    CALL_SUBTEST_7(( inplace<FullPivHouseholderQR<Ref<Matrix43d> >, Matrix43d>(false,false) ));

    CALL_SUBTEST_8(( inplace<CompleteOrthogonalDecomposition<Ref<MatrixXd> >, MatrixXd>(false,false) ));
    CALL_SUBTEST_8(( inplace<CompleteOrthogonalDecomposition<Ref<Matrix43d> >, Matrix43d>(false,false) ));
  }
}


/*-----------------------------------------------------------------------------+
Interval Container Library
Author: Joachim Faulhaber
Copyright (c) 2007-2009: Joachim Faulhaber
Copyright (c) 1999-2006: Cortex Software GmbH, Kantstrasse 57, Berlin
+------------------------------------------------------------------------------+
   Distributed under the Boost Software License, Version 1.0.
      (See accompanying file LICENCE.txt or copy at
           http://www.boost.org/LICENSE_1_0.txt)
+-----------------------------------------------------------------------------*/
/** Example man_power.cpp \file man_power.cpp
    \brief Using set style operators to compute with interval sets and maps.

    Interval sets and maps can be filled and manipulated using
    set style operation like union (+=), difference (-=) and intersection
    (&=).

    In this example 'man_power' a number of those operations are
    demonstrated in the process of calculation the available working
    times (man-power) of a company's employees accounting for weekends,
    holidays, sickness times and vacations.

    \include man_power_/man_power.cpp
*/
//[example_man_power
// The next line includes <boost/gregorian/date.hpp>
// and a few lines of adapter code.
#include <boost/icl/gregorian.hpp>
#include <iostream>
#include <boost/icl/discrete_interval.hpp>
#include <boost/icl/interval_map.hpp>

using namespace std;
using namespace boost::gregorian;
using namespace boost::icl;

// Function weekends returns the interval_set of weekends that are contained in
// the date interval 'scope'
interval_set<date> weekends(const discrete_interval<date>& scope)
{
    interval_set<date> weekends;

    date cur_weekend_sat
        = first(scope)
          + days(days_until_weekday(first(scope), greg_weekday(Saturday)))
          - weeks(1);
    week_iterator week_iter(cur_weekend_sat);

    for(; week_iter <= last(scope); ++week_iter)
        weekends += discrete_interval<date>::right_open(*week_iter, *week_iter + days(2));

    weekends &= scope; // cut off the surplus

    return weekends;
}

// The available working time for the employees of a company is calculated
// for a period of 3 months accounting for weekends and holidays.
//    The available daily working time for the employees is calculated
// using interval_sets and interval_maps demonstrating a number of
// addition, subtraction and intersection operations.
void man_power()
{
    date someday = from_string("2008-08-01");
    date thenday = someday + months(3);

    discrete_interval<date> scope = discrete_interval<date>::right_open(someday, thenday);

    // ------------------------------------------------------------------------
    // (1) In a first step, the regular working times are computed for the
    // company within the given scope. From all available days, the weekends
    // and holidays have to be subtracted:
    interval_set<date> worktime(scope);
    // Subtract the weekends
    worktime -= weekends(scope);
    // Subtract holidays
    worktime -= from_string("2008-10-03"); //German reunification ;)

    // company holidays (fictitious ;)
    worktime -= discrete_interval<date>::closed(from_string("2008-08-18"),
                                                from_string("2008-08-22"));

    //-------------------------------------------------------------------------
    // (2) Now we calculate the individual work times for some employees
    //-------------------------------------------------------------------------
    // In the company works Claudia.
    // This is the map of her regular working times:
    interval_map<date,int> claudias_working_hours;

    // Claudia is working 8 hours a day. So the next statement says
    // that every day in the whole scope is mapped to 8 hours worktime.
    claudias_working_hours += make_pair(scope, 8);

    // But Claudia only works 8 hours on regular working days so we do
    // an intersection of the interval_map with the interval_set worktime:
    claudias_working_hours &= worktime;

    // Yet, in addition Claudia has her own absence times like
    discrete_interval<date> claudias_seminar (from_string("2008-09-16"),
                                              from_string("2008-09-24"),
                                              interval_bounds::closed());
    discrete_interval<date> claudias_vacation(from_string("2008-08-01"),
                                              from_string("2008-08-14"),
                                              interval_bounds::closed());

    interval_set<date> claudias_absence_times(claudias_seminar);
    claudias_absence_times += claudias_vacation;

    // All the absence times have to subtracted from the map of her working times
    claudias_working_hours -= claudias_absence_times;

    //-------------------------------------------------------------------------
    // Claudia's boss is Bodo. He only works part time.
    // This is the map of his regular working times:
    interval_map<date,int> bodos_working_hours;

    // Bodo is working 4 hours a day.
    bodos_working_hours += make_pair(scope, 4);

    // Bodo works only on regular working days
    bodos_working_hours &= worktime;

    // Bodos additional absence times
    discrete_interval<date>      bodos_flu(from_string("2008-09-19"), from_string("2008-09-29"),
                                           interval_bounds::closed());
    discrete_interval<date> bodos_vacation(from_string("2008-08-15"), from_string("2008-09-03"),
                                           interval_bounds::closed());

    interval_set<date> bodos_absence_times(bodos_flu);
    bodos_absence_times += bodos_vacation;

    // All the absence times have to be subtracted from the map of his working times
    bodos_working_hours -= bodos_absence_times;

    //-------------------------------------------------------------------------
    // (3) Finally we want to calculate the available manpower of the company
    // for the selected time scope: This is done by adding up the employees
    // working time maps:
    interval_map<date,int> manpower;
    manpower += claudias_working_hours;
    manpower += bodos_working_hours;

    cout << first(scope) << " - " << last(scope)
         << "    available man-power:" << endl;
    cout << "---------------------------------------------------------------\n";

    for(interval_map<date,int>::iterator it = manpower.begin();
        it != manpower.end(); it++)
    {
        cout << first(it->first) << " - " << last(it->first)
             << " -> " << it->second << endl;
    }
}

int main()
{
    cout << ">>Interval Container Library: Sample man_power.cpp <<\n";
    cout << "---------------------------------------------------------------\n";
    man_power();
    return 0;
}

// Program output:
/*
>>Interval Container Library: Sample man_power.cpp <<
---------------------------------------------------------------
2008-Aug-01 - 2008-Oct-31    available man-power:
---------------------------------------------------------------
2008-Aug-01 - 2008-Aug-01 -> 4
2008-Aug-04 - 2008-Aug-08 -> 4
2008-Aug-11 - 2008-Aug-14 -> 4
2008-Aug-15 - 2008-Aug-15 -> 8
2008-Aug-25 - 2008-Aug-29 -> 8
2008-Sep-01 - 2008-Sep-03 -> 8
2008-Sep-04 - 2008-Sep-05 -> 12
2008-Sep-08 - 2008-Sep-12 -> 12
2008-Sep-15 - 2008-Sep-15 -> 12
2008-Sep-16 - 2008-Sep-18 -> 4
2008-Sep-25 - 2008-Sep-26 -> 8
2008-Sep-29 - 2008-Sep-29 -> 8
2008-Sep-30 - 2008-Oct-02 -> 12
2008-Oct-06 - 2008-Oct-10 -> 12
2008-Oct-13 - 2008-Oct-17 -> 12
2008-Oct-20 - 2008-Oct-24 -> 12
2008-Oct-27 - 2008-Oct-31 -> 12
*/
//]


#include "math/itf/vector_3d.h"

#include <cmath>
#include <boost/assert.hpp>

using namespace lb;

/// Adds the vector \a v to this vector.
Vector3d &Vector3d::operator+=(const Vector3d &v)
{
    x += v.x;
    y += v.y;
    z += v.z;

    return *this;
}

/// Returns whether this vector equals the given vector \a v.
bool Vector3d::operator==(const Vector3d &v) const
{
    return x == v.x && y == v.y && z == v.z;
}

/// Scales this vector by a factor \a f and returns a reference to itself.
Vector3d &Vector3d::operator*=(double f)
{
    x *= f;
    y *= f;
    z *= f;
    return *this;
}

/// Divides this vector by a factor \a f and returns the result vector.
Vector3d Vector3d::operator/(double f) const
{
    BOOST_ASSERT(f != 0);
    double inv = 1.f / f;
    return {x * inv, y * inv, z * inv};
}

/// Divides this vector by a factor \a f and returns a reference to itself.
Vector3d &Vector3d::operator/=(double f)
{
    BOOST_ASSERT(f != 0);
    double inv = 1.f / f;
    x *= inv;
    y *= inv;
    z *= inv;
    return *this;
}

/// Calculates the length of this vector and returns it.
double Vector3d::length() const
{
    return std::sqrt(lengthSquared());
}

/// Calculates the square of the length of this vector and returns it.
double Vector3d::lengthSquared() const
{
    return x * x + y * y + z * z;
}

/// Normalizes this vector to a vector with the same direction and magnitude
/// one.
void Vector3d::normalize()
{
    double oneOverLength = 1.0 / length();
    x *= oneOverLength;
    y *= oneOverLength;
    z *= oneOverLength;
}

/// Calculates a vector that points in the same direction as this vector with
/// length 1 and returns it.
Vector3d Vector3d::normalized() const
{
    return *this / length();
}

/// Streams a textual representation of the vector \a v to \a out.
std::ostream &lb::operator<<(std::ostream &out, const Vector3d &v)
{
    out << "(" << v.x << ", " << v.y << ", " << v.z << ")";
}

/// Returns the absolute value of the dot product of the two vectors \a v and \a
/// w.
double absDot(const Vector3d &v, const Vector3d &w)
{
    return std::fabs(dot(v, w));
}


#ifndef SM_NUMERICAL_DIFF_HPP
#define SM_NUMERICAL_DIFF_HPP

#include <Eigen/Core>
#include <sm/assert_macros.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

namespace sm { namespace eigen {

    template<typename RESULT_VEC_T, typename INPUT_VEC_T, typename JACOBIAN_T = Eigen::MatrixXd>
    struct NumericalDiffFunctor
    {
      typedef RESULT_VEC_T value_t;
      typedef typename value_t::Scalar scalar_t;
      typedef INPUT_VEC_T input_t;
      typedef JACOBIAN_T jacobian_t;

      NumericalDiffFunctor( boost::function< value_t(input_t) > f) : _f(f){}

      value_t operator()(const input_t & x) { return _f(x); }

      input_t update(const input_t & x, int c, scalar_t delta) { input_t xnew = x; xnew[c] += delta; return xnew; }
      boost::function<value_t(input_t)> _f;
    };

    // A simple implementation of central differences to estimate a Jacobian matrix
    template<typename FUNCTOR_T>
    struct NumericalDiff
    {
      typedef FUNCTOR_T functor_t;
      typedef typename functor_t::input_t input_t;
      typedef typename functor_t::value_t value_t;
      typedef typename functor_t::scalar_t scalar_t;
      typedef typename functor_t::jacobian_t jacobian_t;

      NumericalDiff(functor_t f, scalar_t eps = sqrt(std::numeric_limits<scalar_t>::epsilon())) : functor(f), eps(eps) {}

      jacobian_t estimateJacobian(input_t const & x0)
      {
        // evaluate the function at the operating point:
        value_t fx0 = functor(x0);
        size_t N = x0.size();
        size_t M = fx0.size();

        //std::cout << "Size: " << M << ", " << N << std::endl;
        jacobian_t J;
        J.resize(M, N);

        SM_ASSERT_EQ(std::runtime_error,x0.size(),J.cols(),"Unexpected number of columns for input size");
        SM_ASSERT_EQ(std::runtime_error,fx0.size(),J.rows(),"Unexpected number of columns for output size");

        for(unsigned c = 0; c < N; c++) {
          // Calculate a central difference.
          // This step size was stolen from cminpack: temp = eps * fabs(x[j]);
          scalar_t rcEps = std::max(static_cast<scalar_t>(fabs(x0(c))) * eps,eps);

          value_t fxp = functor(functor.update(x0,c,rcEps));
          value_t fxm = functor(functor.update(x0,c,-rcEps));
          J.block(0, c, M, 1) = (fxp - fxm).template cast<typename jacobian_t::Scalar>()/(typename jacobian_t::Scalar)(rcEps*(scalar_t)2.0);
        }
        return J;
      }

      functor_t functor;
      scalar_t eps;
    };

    template < typename ValueType_, typename InputType_>
    Eigen::MatrixXd numericalDiff(std::function<ValueType_ (const InputType_ &) > function, InputType_ const & input, double eps = sqrt(std::numeric_limits<typename NumericalDiffFunctor<ValueType_, InputType_>::scalar_t>::epsilon())){
      typedef NumericalDiffFunctor<ValueType_, InputType_> Functor;

      NumericalDiff<Functor> numDiff(Functor(function), eps);
      return numDiff.estimateJacobian(input);
    }

  }}

#endif /* SM_NUMERICAL_DIFF_HPP */


/*
 * Copyright 2021 MusicScience37 (Kenta Kabashima)
 *
 * 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.
 */
/*!
 * \file
 * \brief Test of make_jacobian function.
 */
#include "num_collect/auto_diff/forward/make_jacobian.h"

#include <Eigen/Core>
#include <catch2/catch_template_test_macros.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating.hpp>

#include "eigen_approx.h"
#include "num_collect/auto_diff/forward/create_diff_variable.h"

// NOLINTNEXTLINE
TEMPLATE_TEST_CASE(
    "num_collect::auto_diff::forward::make_jacobian", "", float, double) {
    using value_type = TestType;
    using diff_type = Eigen::Matrix<value_type, Eigen::Dynamic, 1>;
    using variable_vector_type =
        num_collect::auto_diff::forward::variable_vector_type<diff_type>;
    using jacobian_type =
        Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>;

    SECTION("make Jacobian") {
        const variable_vector_type vars =
            num_collect::auto_diff::forward::create_diff_variable_vector(
                (diff_type(2) << 1.234, 2.345).finished());
        const variable_vector_type res =
            (variable_vector_type(3) << vars(0) + vars(1), vars(0) - vars(1),
                vars(0) * vars(1))
                .finished();
        const jacobian_type coeff =
            num_collect::auto_diff::forward::make_jacobian(res);

        jacobian_type true_coeff = jacobian_type::Zero(3, 2);
        true_coeff(0, 0) = static_cast<value_type>(1);
        true_coeff(0, 1) = static_cast<value_type>(1);
        true_coeff(1, 0) = static_cast<value_type>(1);
        true_coeff(1, 1) = static_cast<value_type>(-1);
        true_coeff(2, 0) = vars[1].value();
        true_coeff(2, 1) = vars[0].value();
        REQUIRE_THAT(coeff, eigen_approx(true_coeff));
    }
}


// Copyright (c) 2021 Graphcore Ltd. All rights reserved.

#ifndef poplibs_test_MatrixTransforms_hpp
#define poplibs_test_MatrixTransforms_hpp

#include <boost/multi_array.hpp>

namespace poplibs_test {
namespace matrix {

template <typename FPType>
boost::multi_array<FPType, 2>
transpose(const boost::multi_array<FPType, 2> &in) {
  const auto inRows = in.shape()[0];
  const auto inColumns = in.shape()[1];
  boost::multi_array<FPType, 2> out(boost::extents[inColumns][inRows]);
  for (unsigned inRow = 0; inRow < inRows; inRow++) {
    for (unsigned inColumn = 0; inColumn < inColumns; inColumn++) {
      out[inColumn][inRow] = in[inRow][inColumn];
    }
  }
  return out;
}

} // End namespace matrix
} // End namespace poplibs_test

#endif // poplibs_test_MatrixTransforms_hpp


// Software License for MTL
//
// Copyright (c) 2007 The Trustees of Indiana University.
//               2008 Dresden University of Technology and the Trustees of Indiana University.
//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
// All rights reserved.
// Authors: Peter Gottschling and Andrew Lumsdaine
//
// This file is part of the Matrix Template Library
//
// See also license.mtl.txt in the distribution.

#include <boost/numeric/mtl/mtl.hpp>
# include "boost/rational.hpp"
# include "boost/range.hpp"

typedef boost::rational<long>                              t_Q;
typedef mtl::dense_vector<t_Q, mtl::vec::parameters<> > t_dVecQ;

//! Struct containing data about the refinment of a face.
struct st_test
{
    t_dVecQ vecQ;

    //! Constructor for refinement of a triangle.
    st_test( const t_dVecQ& vecQ_new )
    {
        vecQ = vecQ_new;
        std::cout << "vecQ: " << vecQ << "\n";       // uses size -> ambiguity with size in boost/range
        std::cout << mtl::size(vecQ_new) << "\n";
    }
};

// using test as function name causes ambiguities  on some compilers
// (type_traits/has_new_operator.hpp:24: error: ‘template<class U, U x> struct boost::detail::test' is not a function)
void assign_test( const t_dVecQ& vecQ )
{
    t_dVecQ vecQ_temp;
    vecQ_temp = vecQ;
    std::cout << "vecQ_temp: " << vecQ_temp << "\n";
}

void test2()
{
   t_dVecQ vQ0(2,3);
    t_dVecQ vQ1(2,2);
    t_dVecQ vQ2(2,1);
    std::cout << "vQ0: " << vQ0 << "\n";
    std::cout << "vQ1: " << vQ1 << "\n";
    std::cout << "size(vQ1): " << mtl::size(vQ1) << "\n";
    vQ0 = vQ1 + vQ2;
    vQ0 = vQ1 - vQ2;
    vQ0 += vQ1;
    vQ0 -= vQ1;
    std::cout << "vQ0: " << vQ0 << "\n";
    t_dVecQ vQ3( vQ0 - vQ1 );
    std::cout << "vQ2: " << vQ2 << "\n";
    std::cout << "size(vQ2): " << mtl::size(vQ2) << "\n";
}

int main(int , char**)
{
    t_Q Q0(1,3);
    std::cout << "Q0: " << Q0 << "\n";

    t_dVecQ vecQ0(2,Q0);
    std::cout << "vecQ0: " << vecQ0 << "\n";

    t_Q Q1(1,2);
    std::cout << "Q1: " << Q1 << "\n";
    t_dVecQ vecQ1(3,Q1);
    std::cout << "vecQ1: " << vecQ1 << "\n";
    vecQ1[mtl::irange(2)] = vecQ0;
    std::cout << "vecQ1: " << vecQ1 << "\n";

    assign_test(vecQ1);
    st_test test(vecQ1);

    // std::cout << "size(vecQ1): " << mtl::size(vecQ1) << "\n";

    test2();

    return 0;
}


//
// Project: Delaunay
// File: main.cpp
//
// Copyright (c) 2021 Miika 'Lehdari' Lehtimäki
// You may use, distribute and modify this code under the terms
// of the licence specified in file LICENSE which is distributed
// with this source code package.
//

#include <random>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <Eigen/Dense>

// 3x3 determinant
template <typename T_Scalar>
T_Scalar inline __attribute__((always_inline)) determinant(
    const T_Scalar& a, const T_Scalar& b, const T_Scalar& c,
    const T_Scalar& d, const T_Scalar& e, const T_Scalar& f,
    const T_Scalar& g, const T_Scalar& h, const T_Scalar& i)
{
    return a*e*i + b*f*g + c*d*h - c*e*g - b*d*i - a*f*h;
}

#ifndef DELAUNAY_BACKEND
// example implementation of a custom backend

// minimal 2D vector struct
template <typename T_Scalar>
struct Vec2 {
    T_Scalar  data[2];

    // access with functor operator required only for demo dataset construction
    // so it is identical with eigen
    T_Scalar& operator()(int d) { return data[d]; }
    const T_Scalar& operator()(int d) const { return data[d]; }

    Vec2(T_Scalar x, T_Scalar y) :
        data    {x,y}
    {}
};

// macros required for backend specification
#define DELAUNAY_VEC Vec2<T_Scalar>
#define DELAUNAY_VEC_ACCESS(V,D) V.data[D]
#define DELAUNAY_DETERMINANT determinant

#endif // ifndef DELAUNAY_BACKEND

#include "Delaunay.hpp"

#define RND ((rnd()%10000001)*0.0000001)

#if DELAUNAY_BACKEND == DELAUNAY_BACKEND_EIGEN

using Vec2d = Eigen::Matrix<double, 2, 1>;
using Vec2f = Eigen::Matrix<float, 2, 1>;
template <typename T>
using Vector = std::vector<T, Eigen::aligned_allocator<T>>;

#else // custom backend

using Vec2f = Vec2<float>;
using Vec2d = Vec2<double>;
template <typename T>
using Vector = std::vector<T>;

#endif

// generate some non-uniform data (not very fancy but does the job)
void createPoints(Vector<Vec2d>& v, const Vec2d& min, const Vec2d& max, int depth = 0)
{
    static std::default_random_engine rnd(7155178);

    double terminationProbability = 0.02*depth*depth;
    if (RND < terminationProbability) {
        v.emplace_back(min(0) + RND*(max(0)-min(0)), min(1) + RND*(max(1)-min(1)));
        v.emplace_back(min(0) + RND*(max(0)-min(0)), min(1) + RND*(max(1)-min(1)));
    }
    else {
        Vec2d half(min(0)+(0.3+0.4*RND)*(max(0)-min(0)), min(1)+(0.3+0.4*RND)*(max(1)-min(1)));
        createPoints(v, min, half, depth+1);
        createPoints(v, Vec2d(half(0), min(1)), Vec2d(max(0), half(1)), depth+1);
        createPoints(v, Vec2d(min(0), half(1)), Vec2d(half(0), max(1)), depth+1);
        createPoints(v, half, max, depth+1);
    }
}

template <typename T>
void createPointsUniform(Vector<T>& v, const T& min, const T& max, int n)
{
    std::default_random_engine rnd(1507715517);
    v.reserve(n);

    for (int i=0; i<n; ++i) {
        v.emplace_back(min(0) + RND*(max(0)-min(0)), min(1) + RND*(max(1)-min(1)));
    }
}

template <typename T>
void visualize(const Vector<T>& points, std::vector<int32_t>& triangulation,
    const std::string& windowName, const cv::Scalar& lineColor, int wait=0)
{
    cv::Mat img(1024, 1024, CV_8UC3, cv::Scalar(0, 0, 0));

    for (int i=0; i<triangulation.size(); i+=3) {
        cv::line(img,
            cv::Point(points[triangulation[i]](0), 1024-(int)points[triangulation[i]](1)),
            cv::Point(points[triangulation[i+1]](0), 1024-(int)points[triangulation[i+1]](1)),
            lineColor);
        if (triangulation[i+2] != -1) {
            cv::line(img,
                cv::Point(points[triangulation[i+1]](0), 1024-(int)points[triangulation[i+1]](1)),
                cv::Point(points[triangulation[i+2]](0), 1024-(int)points[triangulation[i+2]](1)),
                lineColor);
            cv::line(img,
                cv::Point(points[triangulation[i+2]](0), 1024-(int)points[triangulation[i+2]](1)),
                cv::Point(points[triangulation[i]](0), 1024-(int)points[triangulation[i]](1)),
                lineColor);
        }
    }

    for (auto& p : points) {
        img.at<cv::Vec3b>(1023-(int)p(1), (int)p(0)) = cv::Vec3b(255, 255, 255);
    }

    cv::imshow(windowName, img);
    cv::waitKey(wait);
}

template <typename T>
inline __attribute__((always_inline)) bool inCircle2(
    const T& a, const T& b, const T& c, const T& d)
{
    T dd(d(0)*d(0), d(1)*d(1));
    return determinant<double>(
        a(0)-d(0), a(1)-d(1), (a(0)*a(0)-dd(0))+(a(1)*a(1)-dd(1)),
        b(0)-d(0), b(1)-d(1), (b(0)*b(0)-dd(0))+(b(1)*b(1)-dd(1)),
        c(0)-d(0), c(1)-d(1), (c(0)*c(0)-dd(0))+(c(1)*c(1)-dd(1))) > 0.0;
}

template <typename T>
bool checkTriangulation(const Vector<T>& points, std::vector<int32_t>& triangulation)
{
    for (size_t i=0; i<triangulation.size(); i+=3) {
        int p1 = triangulation[i];
        int p2 = triangulation[i+1];
        int p3 = triangulation[i+2];
        if (p3 == -1)
            continue;

        for (size_t j=0; j<points.size(); ++j) {
            if (j == p1 || j == p2 || j == p3)
                continue;
            if (inCircle2(points[p1], points[p2], points[p3], points[j]))
                return false;
        }
    }

    return true;
}

void benchmark(void) {
    int nPoints = 10;
    bool breakLoop = false;
    while (true) {
        Vector<Vec2f> pointsFloat;
        Vector<Vec2d> pointsDouble;
        pointsFloat.clear();
        pointsDouble.clear();
        createPointsUniform(pointsFloat, Vec2f(0.0, 0.0), Vec2f(1024.0, 1024.0), nPoints);
        createPointsUniform(pointsDouble, Vec2d(0.0, 0.0), Vec2d(1024.0, 1024.0), nPoints);

        auto t1 = std::chrono::high_resolution_clock::now();
        auto triangulationFloat = delaunay::triangulate(pointsFloat);
        auto t2 = std::chrono::high_resolution_clock::now();
        auto triangulationDouble = delaunay::triangulate(pointsDouble);
        auto t3 = std::chrono::high_resolution_clock::now();

        printf("nPoints: %d, tFloat: %0.5f, tDouble: %0.5f\n", nPoints,
            std::chrono::duration<double, std::milli>(t2-t1).count(),
            std::chrono::duration<double, std::milli>(t3-t2).count());

        visualize(pointsDouble, triangulationDouble, "triangulationDouble", cv::Scalar(120, 120, 0), 20);
        visualize(pointsFloat, triangulationFloat, "triangulationFloat", cv::Scalar(0, 80, 160), 20);

        if (!checkTriangulation(pointsFloat, triangulationFloat)) {
            printf("Triangulation is non-delaunay!\n");
            breakLoop = true;
        }

        if (breakLoop) {
            cv::waitKey(0);
            break;
        }

        nPoints *= 1.1;
    }
}

int main()
{
#if 0
    Vector<Vec2d> points;
    createPoints(points, Vec2d(0.0f, 0.0f), Vec2d(1024.0f, 1024.0f));

    auto triangulation = delaunay::triangulate(points);

    visualize(points, triangulation, "delaunay demo", cv::Scalar(120, 120, 0));
#else
    benchmark();
#endif

    return 0;
}


///3
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
// BGL includes
#include <boost/graph/adjacency_list.hpp>
// BGL graph definitions
// =====================
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
  boost::no_property, boost::property<boost::edge_weight_t, long> >      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;
typedef  boost::graph_traits<weighted_graph>::out_edge_iterator      out_edge_it;

// Main
void testcase() {
  // build graph
  long n, m, x, k;
  std::cin >> n >> m >> x >> k;
  weighted_graph G(n);
  weight_map weights = boost::get(boost::edge_weight, G);

  edge_desc e;

  std::vector<int> num_outgoing(n, 0);

  for(int i = 0; i < m; i++) {
    long u, v, p;
    std::cin >> u >> v>> p;
    e = boost::add_edge(u, v, G).first; weights[e]=p;
    num_outgoing[u] += 1;
  }

  std::vector<std::vector<long>> maxpoints_after(k + 1);
  for(int i = 0; i <= k; i++) {
    maxpoints_after[i] = std::vector<long>(n, 0);
  }

  out_edge_it ebeg, eend;
  for(int j = 0; j < k; j++) {
    for(int i = 0; i < n; i++) {
      long maxpoints = 0;
      for (boost::tie(ebeg, eend) = boost::out_edges(i, G); ebeg != eend; ++ebeg) {
        const int v = boost::target(*ebeg, G);
        const long pi = weights[*ebeg];
        maxpoints = std::max(maxpoints, maxpoints_after[j][v] + pi);
        if(i == 0 && maxpoints >= x) {
          std::cout << j + 1 << std::endl;
          return;
        }
      }
      if(num_outgoing[i] == 0) {
        maxpoints_after[j + 1][i] = maxpoints_after[j + 1][0];
      } else {
        maxpoints_after[j + 1][i] = maxpoints;
      }
    }
  }
  std::cout << "Impossible" << std::endl;
}

int main() {
  std::ios_base::sync_with_stdio(false);
  std::size_t t;
  for (std::cin >> t; t > 0; --t) testcase();
  return 0;
}


//  Copyright John Maddock 2007.
//  Copyright Paul A. Bristow 2010
//  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)

// Note that this file contains quickbook mark-up as well as code
// and comments, don't change any of the special comment mark-ups!

//[policy_eg_10

/*`

To understand how the rounding policies for
the discrete distributions can be used, we'll
use the 50-sample binomial distribution with a
success fraction of 0.5 once again, and calculate
all the possible quantiles at 0.05 and 0.95.

Begin by including the needed headers (and some using statements for conciseness):

*/
#include <iostream>
using std::cout; using std::endl;
using std::left; using std::fixed; using std::right; using std::scientific;
#include <iomanip>
using std::setw;
using std::setprecision;

#include <boost/math/distributions/binomial.hpp>
/*`

Next we'll bring the needed declarations into scope, and
define distribution types for all the available rounding policies:

*/
// Avoid
// using namespace std; // and
// using namespace boost::math;
// to avoid potential ambiguity of names, like binomial.
// using namespace boost::math::policies; is small risk, but
// the necessary items are brought into scope thus:

using boost::math::binomial_distribution;
using boost::math::policies::policy;
using boost::math::policies::discrete_quantile;

using boost::math::policies::integer_round_outwards;
using boost::math::policies::integer_round_down;
using boost::math::policies::integer_round_up;
using boost::math::policies::integer_round_nearest;
using boost::math::policies::integer_round_inwards;
using boost::math::policies::real;

using boost::math::binomial_distribution; // Not std::binomial_distribution.

typedef binomial_distribution<
            double,
            policy<discrete_quantile<integer_round_outwards> > >
        binom_round_outwards;

typedef binomial_distribution<
            double,
            policy<discrete_quantile<integer_round_inwards> > >
        binom_round_inwards;

typedef binomial_distribution<
            double,
            policy<discrete_quantile<integer_round_down> > >
        binom_round_down;

typedef binomial_distribution<
            double,
            policy<discrete_quantile<integer_round_up> > >
        binom_round_up;

typedef binomial_distribution<
            double,
            policy<discrete_quantile<integer_round_nearest> > >
        binom_round_nearest;

typedef binomial_distribution<
            double,
            policy<discrete_quantile<real> > >
        binom_real_quantile;

/*`
Now let's set to work calling those quantiles:
*/

int main()
{
   cout <<
      "Testing rounding policies for a 50 sample binomial distribution,\n"
      "with a success fraction of 0.5.\n\n"
      "Lower quantiles are calculated at p = 0.05\n\n"
      "Upper quantiles at p = 0.95.\n\n";

   cout << setw(25) << right
      << "Policy"<< setw(18) << right
      << "Lower Quantile" << setw(18) << right
      << "Upper Quantile" << endl;

   // Test integer_round_outwards:
   cout << setw(25) << right
      << "integer_round_outwards"
      << setw(18) << right
      << quantile(binom_round_outwards(50, 0.5), 0.05)
      << setw(18) << right
      << quantile(binom_round_outwards(50, 0.5), 0.95)
      << endl;

   // Test integer_round_inwards:
   cout << setw(25) << right
      << "integer_round_inwards"
      << setw(18) << right
      << quantile(binom_round_inwards(50, 0.5), 0.05)
      << setw(18) << right
      << quantile(binom_round_inwards(50, 0.5), 0.95)
      << endl;

   // Test integer_round_down:
   cout << setw(25) << right
      << "integer_round_down"
      << setw(18) << right
      << quantile(binom_round_down(50, 0.5), 0.05)
      << setw(18) << right
      << quantile(binom_round_down(50, 0.5), 0.95)
      << endl;

   // Test integer_round_up:
   cout << setw(25) << right
      << "integer_round_up"
      << setw(18) << right
      << quantile(binom_round_up(50, 0.5), 0.05)
      << setw(18) << right
      << quantile(binom_round_up(50, 0.5), 0.95)
      << endl;

   // Test integer_round_nearest:
   cout << setw(25) << right
      << "integer_round_nearest"
      << setw(18) << right
      << quantile(binom_round_nearest(50, 0.5), 0.05)
      << setw(18) << right
      << quantile(binom_round_nearest(50, 0.5), 0.95)
      << endl;

   // Test real:
   cout << setw(25) << right
      << "real"
      << setw(18) << right
      << quantile(binom_real_quantile(50, 0.5), 0.05)
      << setw(18) << right
      << quantile(binom_real_quantile(50, 0.5), 0.95)
      << endl;
} // int main()

/*`

Which produces the program output:

[pre
  policy_eg_10.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\policy_eg_10.exe
  Testing rounding policies for a 50 sample binomial distribution,
  with a success fraction of 0.5.

  Lower quantiles are calculated at p = 0.05

  Upper quantiles at p = 0.95.

                     Policy    Lower Quantile    Upper Quantile
     integer_round_outwards                18                31
      integer_round_inwards                19                30
         integer_round_down                18                30
           integer_round_up                19                31
      integer_round_nearest                19                30
                       real            18.701            30.299
]

*/

//] //[policy_eg_10] ends quickbook import.


#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <iostream>
#include <mimkl/definitions.hpp>
#include <mimkl/kernels.hpp>
#include <mimkl/linear_algebra.hpp>
#include <stdexcept>

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

        auto console = spdlog::stdout_color_mt("console");

        Eigen::Matrix<double, 2, 3> X;
        Eigen::SparseMatrix<double> L(3, 3);
        double a = 0.01;
        double b = 0.01;
        Eigen::Matrix<double, 2, 2> K_reference;

        X << 1., 2., 3., 4., 5., 6.;
        mimkl::linear_algebra::fill_sparse_diagonal(L, 1.0);

        K_reference << std::tanh(0.15), std::tanh(0.33), std::tanh(0.33),
        std::tanh(.78);
        Eigen::Matrix<double, 2, 2> K =
        mimkl::induction::induce_sigmoidal_kernel<MATRIX(double)>(X, X, L, a, b);

        assert(((K - K_reference).norm() < 0.0000000001) && "Identity Inducer");

        Eigen::SparseMatrix<double> L1(3, 3);
        typedef Eigen::Triplet<double> TripletDouble; // (row,col,coef)
        std::vector<TripletDouble> triplet_list;
        triplet_list.reserve(4);
        triplet_list.push_back(TripletDouble(0, 1, 1.));
        triplet_list.push_back(TripletDouble(1, 2, 1.));
        triplet_list.push_back(TripletDouble(1, 0, 1.));
        triplet_list.push_back(TripletDouble(2, 1, 1.));
        L1.setFromTriplets(triplet_list.begin(), triplet_list.end());

        K_reference << std::tanh(0.17), std::tanh(0.41), std::tanh(0.41),
        std::tanh(1.01);
        ;

        K = mimkl::induction::induce_sigmoidal_kernel<MATRIX(double)>(X, X, L1,
                                                                      a, b);

        std::cout << K << std::endl;
        std::cout << K_reference << std::endl;
        std::cout << (K - K_reference).norm() << std::endl;
        assert(((K - K_reference).norm() < 0.0000000001) &&
               "unweighted Graph Inducer");

        MATRIX(double) random_mat1 = MATRIX(double)::Random(2, 3);
        MATRIX(double) random_mat2 = MATRIX(double)::Random(4, 3);
        MATRIX(double) random_kernel;

        random_kernel =
        mimkl::induction::induce_sigmoidal_kernel<MATRIX(double)>(random_mat1,
                                                                  random_mat2,
                                                                  L1, a, b);
        console->info(" a random sigmoidal kernel\n{}", random_kernel);

        return EXIT_SUCCESS;
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what();
        return EXIT_FAILURE;
    }
}


//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS
  @copyright 2016 J.T. Lapreste

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_FUNCTION_NEXTPOW2_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_NEXTPOW2_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

 /*!

    @ingroup group-ieee
    Function object implementing nextpow2 capabilities

    Returns the greatest integer n such that abss(x) is greater or equal to \f$2^n\f$

    @par Semantic:

    @code
    T n = nextpow2(x);
    @endcode

    is similar to:

    @code
    T n = floor(log2(abss(x)));
    @endcode

  **/
  const boost::dispatch::functor<tag::nextpow2_> nextpow2 = {};
} }
#endif

#include <boost/simd/function/scalar/nextpow2.hpp>
#include <boost/simd/function/simd/nextpow2.hpp>

#endif


#include <gtest/gtest.h>

#include <Eigen/Dense>
#include <stan/math/prim/fun.hpp>  // lgamma, lmgamma
#include <stan/math/prim/prob.hpp>

#include "marginal_state.pb.h"
#include "src/hierarchies/lin_reg_uni_hierarchy.h"
#include "src/hierarchies/nnig_hierarchy.h"
#include "src/hierarchies/nnw_hierarchy.h"
#include "src/utils/proto_utils.h"

TEST(lpdf, nnig) {
  NNIGHierarchy hier;
  bayesmix::NNIGPrior hier_prior;
  double mu0 = 5.0;
  double lambda0 = 0.1;
  double alpha0 = 2.0;
  double beta0 = 2.0;
  hier_prior.mutable_fixed_values()->set_mean(mu0);
  hier_prior.mutable_fixed_values()->set_var_scaling(lambda0);
  hier_prior.mutable_fixed_values()->set_shape(alpha0);
  hier_prior.mutable_fixed_values()->set_scale(beta0);
  hier.set_prior(hier_prior);
  hier.initialize();

  double mean = mu0;
  double var = beta0 / (alpha0 + 1);

  Eigen::VectorXd datum(1);
  datum << 4.5;

  // Compute posterior parameters
  double mu_n = (lambda0 * mu0 + datum(0)) / (lambda0 + 1);
  double alpha_n = alpha0 + 0.5;
  double lambda_n = lambda0 + 1;
  double beta_n = beta0 + (0.5 * lambda0 / (lambda0 + 1)) * (datum(0) - mu0) *
                              (datum(0) - mu0);
  // equiv.ly: beta0 + 0.5*(mu0^2*lambda0 + datum^2 - mu_n^2*lambda_n);

  // Compute pieces
  double prior1 = stan::math::inv_gamma_lpdf(var, alpha0, beta0);
  double prior2 = stan::math::normal_lpdf(mean, mu0, sqrt(var / lambda0));
  double prior = prior1 + prior2;
  double like = hier.like_lpdf(datum);
  double post1 = stan::math::inv_gamma_lpdf(var, alpha_n, beta_n);
  double post2 = stan::math::normal_lpdf(mean, mu_n, sqrt(var / lambda_n));
  double post = post1 + post2;

  // Bayes: logmarg(x) = logprior(phi) + loglik(x|phi) - logpost(phi|x)
  double sum = prior + like - post;
  double marg = hier.marg_lpdf(datum);

  ASSERT_DOUBLE_EQ(sum, marg);
}

// TEST(lpdf, nnw) {  // TODO
//   using namespace stan::math;
//   NNWHierarchy hier;
//   bayesmix::NNWPrior hier_prior;
//   Eigen::Vector2d mu0; mu0 << 5.5, 5.5;
//   bayesmix::Vector mu0_proto;
//   bayesmix::to_proto(mu0, &mu0_proto);
//   double lambda0 = 0.2;
//   double nu0 = 5.0;
//   Eigen::Matrix2d tau0 = Eigen::Matrix2d::Identity() / nu0;
//   bayesmix::Matrix tau0_proto;
//   bayesmix::to_proto(tau0, &tau0_proto);
//   *hier_prior.mutable_fixed_values()->mutable_mean() = mu0_proto;
//   hier_prior.mutable_fixed_values()->set_var_scaling(lambda0);
//   hier_prior.mutable_fixed_values()->set_deg_free(nu0);
//   *hier_prior.mutable_fixed_values()->mutable_scale() = tau0_proto;
//   hier.set_prior(hier_prior);
//   hier.initialize();
//
//   Eigen::VectorXd mu = mu0;
//   Eigen::MatrixXd tau = lambda0 * Eigen::Matrix2d::Identity();
//
//   Eigen::RowVectorXd datum(2);
//   datum << 4.5, 4.5;
//
//   // Compute prior parameters
//   Eigen::MatrixXd tau_pr = lambda0 * tau0;
//
//   // Compute posterior parameters
//   double mu_n = (lambda0 * mu0 + datum(0)) / (lambda0 + 1);
//   double alpha_n = alpha0 + 0.5;
//   double lambda_n = lambda0 + 1;
//   double nu_n = nu0 + 0.5;
//   Eigen::VectorXd mu_n =
//       (lambda0 * mu0 + datum.transpose()) / (lambda0 + 1);
//   Eigen::MatrixXd tau_temp =
//       stan::math::inverse_spd(tau0) + (0.5 * lambda0 / (lambda0 + 1)) *
//                                           (datum.transpose() - mu0) *
//                                           (datum - mu0.transpose());
//   Eigen::MatrixXd tau_n = stan::math::inverse_spd(tau_temp);
//   Eigen::MatrixXd tau_post = lambda_n * tau_n;
//
//   // Compute pieces
//   double prior1 = stan::math::wishart_lpdf(tau, nu0, tau0);
//   double prior2 = stan::math::multi_normal_prec_lpdf(mu, mu0, tau_pr);
//   double prior = prior1 + prior2;
//   double like = hier.like_lpdf(datum);
//   double post1 = stan::math::wishart_lpdf(tau, nu_n, tau_post);
//   double post2 = stan::math::multi_normal_prec_lpdf(mu, mu0, tau_post);
//   double post = post1 + post2;
//
//   // Bayes: logmarg(x) = logprior(phi) + loglik(x|phi) - logpost(phi|x)
//   double sum = prior + like - post;
//   double marg = hier.marg_lpdf(datum);
//
//   // Compute logdet's
//   Eigen::MatrixXd tauchol0 =
//       Eigen::LLT<Eigen::MatrixXd>(tau0).matrixL().transpose();
//   double logdet0 = 2 * log(tauchol0.diagonal().array()).sum();
//   Eigen::MatrixXd tauchol_n =
//       Eigen::LLT<Eigen::MatrixXd>(tau_n).matrixL().transpose();
//   double logdet_n = 2 * log(tauchol_n.diagonal().array()).sum();
//
//   // lmgamma(dim, x)
//   int dim = 2;
//   double marg_murphy = lmgamma(dim, 0.5 * nu_n) + 0.5 * nu_n * logdet_n +
//                        0.5 * dim * log(lambda0) + dim * NEG_LOG_SQRT_TWO_PI
//                        - lmgamma(dim, 0.5 * nu0) - 0.5 * nu0 * logdet0 - 0.5
//                        * dim * log(lambda_n);
//
//   // std::cout << "prior1=" << prior1 << std::endl;
//   // std::cout << "prior2=" << prior2 << std::endl;
//   // std::cout << "prior =" << prior << std::endl;
//   // std::cout << "like  =" << like << std::endl;
//   // std::cout << "post1 =" << post1 << std::endl;
//   // std::cout << "post2 =" << post2 << std::endl;
//   // std::cout << "post  =" << post << std::endl;
//   std::cout << "sum   =" << sum << std::endl;
//   std::cout << "marg  =" << marg << std::endl;
//   std::cout << "murphy=" << marg_murphy << std::endl;
//   ASSERT_DOUBLE_EQ(marg, marg_murphy);
// }

TEST(lpdf, lin_reg_uni) {
  // Create hierarchy objects
  LinRegUniHierarchy hier;
  bayesmix::LinRegUniPrior prior;
  int dim = 3;

  // Generate data
  Eigen::VectorXd datum(1);
  datum << 1.5;
  Eigen::VectorXd cov = Eigen::VectorXd::Random(dim);

  // Create parameters, both Eigen and proto
  Eigen::VectorXd mu0(dim);
  for (int i = 0; i < dim; i++) {
    mu0(i) = 2 * i;
  }
  bayesmix::Vector mu0_proto;
  bayesmix::to_proto(mu0, &mu0_proto);
  auto Lambda0 = Eigen::MatrixXd::Identity(dim, dim);
  bayesmix::Matrix Lambda0_proto;
  bayesmix::to_proto(Lambda0, &Lambda0_proto);
  double alpha0 = 2.0;
  double beta0 = 2.0;
  // Set parameters
  *prior.mutable_fixed_values()->mutable_mean() = mu0_proto;
  *prior.mutable_fixed_values()->mutable_var_scaling() = Lambda0_proto;
  prior.mutable_fixed_values()->set_shape(alpha0);
  prior.mutable_fixed_values()->set_scale(beta0);
  // Initialize hierarchy
  hier.set_prior(prior);
  hier.initialize();

  // Compute prior parameters
  Eigen::VectorXd mean = mu0;
  double var = beta0 / (alpha0 + 1);

  // Compute posterior parameters
  Eigen::MatrixXd Lambda_n = Lambda0 + cov * cov.transpose();
  Eigen::VectorXd mu_n =
      stan::math::inverse_spd(Lambda_n) * (datum(0) * cov + Lambda0 * mu0);
  double alpha_n = alpha0 + 0.5;
  double beta_n =
      beta0 + 0.5 * (datum(0) * datum(0) + mu0.transpose() * Lambda0 * mu0 -
                     mu_n.transpose() * Lambda_n * mu_n);
  // Compute pieces
  double prior1 = stan::math::inv_gamma_lpdf(var, alpha0, beta0);
  double prior2 = stan::math::multi_normal_prec_lpdf(mean, mu0, Lambda0 / var);
  double pr = prior1 + prior2;
  double like = hier.like_lpdf(datum, cov);
  double post1 = stan::math::inv_gamma_lpdf(var, alpha_n, beta_n);
  double post2 =
      stan::math::multi_normal_prec_lpdf(mean, mu_n, Lambda_n / var);
  double post = post1 + post2;

  // Bayes: logmarg(x) = logprior(phi) + loglik(x|phi) - logpost(phi|x)
  double sum = pr + like - post;
  double marg = hier.marg_lpdf(datum, cov);

  ASSERT_FLOAT_EQ(sum, marg);
}


#include <iostream>
#include <vector>

#include <dlib/clustering.h>
#include <dlib/rand.h>

#include <fstream>

using namespace std;
using namespace dlib;

int main(int argc, char **argv) {
    if (argc != 2) {
        std::cerr << "Неверное число параметров\nФормат вызова: kkmeans <n>" << std::endl;
        return 1;
    }

    std::string str_clusters_num = argv[1];
    if (!std::all_of(str_clusters_num.begin(), str_clusters_num.end(), ::isdigit)) {
        std::cerr << "Параметр <n> должен быть типа int" << std::endl;
        return 1;
    }

    size_t cluster_num = std::stoull(str_clusters_num);
    if (cluster_num == 0) {
        std::cerr << "Параметр <n> должен быть больше нуля." << std::endl;
        return 1;
    }

    typedef matrix<double, 2, 1>             sample_type;
    typedef radial_basis_kernel<sample_type> kernel_type;

    kcentroid<kernel_type> kc(kernel_type(0.0001), 0.1, 8);

    kkmeans<kernel_type> test(kc);

    std::vector<sample_type> samples;
    std::vector<sample_type> initial_centers;

    sample_type      m;
    for (std::string line; std::getline(std::cin, line);) {
        auto pos_x = line.find(';');
        auto pos_y = line.find('\n', pos_x + 1);
        m(0) = std::stod(line.substr(0, pos_x));
        m(1) = std::stod(line.substr(pos_x + 1, pos_y));
        samples.emplace_back(m);
    }

    test.set_number_of_centers(cluster_num);

    pick_initial_centers(cluster_num, initial_centers, samples, test.get_kernel());

    test.train(samples, initial_centers);

    for (auto const &sample: samples) {
        std::cout << sample(0) << ";" << sample(1) << ";cluster" << test(sample) + 1 << std::endl;
    }
    return 0;
}


#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>

#include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>

#include <boost/version.hpp>

// Domain
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::FT FT;
typedef K::Point_3 Point;
typedef FT (Function)(const Point&);
typedef CGAL::Labeled_mesh_domain_3<K> Mesh_domain;

typedef CGAL::Parallel_if_available_tag Concurrency_tag;

// Triangulation
typedef CGAL::Mesh_triangulation_3<Mesh_domain,K,Concurrency_tag>::type Tr;

typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;

// Criteria
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;

// To avoid verbose function and named parameters call
using namespace CGAL::parameters;

// Function, a capsule:
//   a cylinder centered at x=y=0, with z in [-5, -5]
//   with radius 1 and "round ends".
FT capsule_function(const Point& p)
{
  const FT base = CGAL::square(p.x())+CGAL::square(p.y()) - 1;
  const FT z = p.z();
  if(z > FT(5)) return base+CGAL::square(z-5);
  else if(z < FT(-5)) return base+CGAL::square(z+5);
  else return base;
}
#if BOOST_VERSION >= 106600
auto field = [](const Point& p, const int, const Mesh_domain::Index)
             {
               if(p.z() > 2) return 0.025;
               if(p.z() < -3) return 0.01;
               else return 1.;
             };
#else
struct Field {
  typedef ::FT FT;

  FT operator()(const Point& p, const int, const Mesh_domain::Index) const {
    if(p.z() > 2) return 0.025;
    if(p.z() < -3) return 0.01;
    else return 1;
  }
} field;
#endif

int main()
{
  Mesh_domain domain =
    Mesh_domain::create_implicit_mesh_domain(capsule_function,
                                             K::Sphere_3(CGAL::ORIGIN, 49.));

  // Mesh criteria
  Mesh_criteria criteria(facet_angle=30, facet_size=0.5,
                         facet_distance=field);

  // Mesh generation
  C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria);

  // Output
  std::ofstream medit_file("out.mesh");
  c3t3.output_to_medit(medit_file);

  return 0;
}


/* test_poisson.cpp
 *
 * Copyright Steven Watanabe 2010
 * 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)
 *
 * $Id$
 *
 */

#include <boost/random/poisson_distribution.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/math/distributions/poisson.hpp>

#define BOOST_RANDOM_DISTRIBUTION boost::random::poisson_distribution<>
#define BOOST_RANDOM_DISTRIBUTION_NAME poisson
#define BOOST_MATH_DISTRIBUTION boost::math::poisson
#define BOOST_RANDOM_ARG1_TYPE double
#define BOOST_RANDOM_ARG1_NAME mean
#define BOOST_RANDOM_ARG1_DEFAULT 100000.0
#define BOOST_RANDOM_ARG1_DISTRIBUTION(n) boost::uniform_real<>(1e-15, n)
#define BOOST_RANDOM_DISTRIBUTION_MAX static_cast<int>(mean * 4)

#include "test_real_distribution.ipp"


#include <boost/test/unit_test.hpp>
#include <stdexcept>

#include "io/DataMatrix.hpp" // TODO don't cross namespace!
#include "it/EntropyCalculator.hpp"

using namespace mist;

io::DataMatrix::data_t test_data[12] = { 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0 };

BOOST_AUTO_TEST_CASE(EntropyCalculator_constructor_default)
{
  int n = 3;
  int m = 4;
  io::DataMatrix test_matrix(test_data, n, m);
  it::EntropyCalculator ec(
      it::EntropyCalculator::variables_ptr(test_matrix.variables()));
}

BOOST_AUTO_TEST_CASE(EntropyCalculator_entropy_bounds)
{
  int n = 3;
  int m = 4;
  io::DataMatrix test_matrix(test_data, n, m);

  it::EntropyCalculator ec(
      it::EntropyCalculator::variables_ptr(test_matrix.variables()));

  // run through some entropies
  for (Variable::index_t i = 0; i < n; i++) {
    ec.entropy({ i });
  }
  ec.entropy({ 0, 1 });
  ec.entropy({ 0, 2 });
  ec.entropy({ 1, 0 });
  ec.entropy({ 1, 2 });
  ec.entropy({ 0, 1, 2 });

  // XXX: memory error, doesn't throw because counters don't check variable
  // indexes impossible in practice because indexes are deterministic & safe
  // BOOST_CHECK_THROW(
  //    ec.entropy({6}), std::exception
  //);
}

BOOST_AUTO_TEST_CASE(EntropyCalculator_entropy_correct1)
{
  int n = 3;
  int m = 4;
  io::DataMatrix test_matrix(test_data, n, m);

  it::EntropyCalculator ec(
      it::EntropyCalculator::variables_ptr(test_matrix.variables()));

  BOOST_TEST(ec.entropy({ 0 }) == 0.8112781244591328);
  BOOST_TEST(ec.entropy({ 1 }) == 1);
  BOOST_TEST(ec.entropy({ 2 }) == 0.8112781244591328);
  BOOST_TEST(ec.entropy({ 0, 1 }) == 1.5);
  BOOST_TEST(ec.entropy({ 0, 2 }) == 1.5);
  BOOST_TEST(ec.entropy({ 1, 2 }) == 1.5);
  BOOST_TEST(ec.entropy({ 0, 1, 2 }) == 2);
}

BOOST_AUTO_TEST_CASE(EntropyCalculator_entropy_correct_d4)
{
  int n = 4;
  int m = 3;
  io::DataMatrix test_matrix(test_data, n, m);

  it::EntropyCalculator ec(
      it::EntropyCalculator::variables_ptr(test_matrix.variables()));

  // 1.58496250072115
  BOOST_TEST(ec.entropy({ 0, 1, 2, 3 }) == 1.5849625007211561);
}


/*
 * Copyright (c) 2015, The Regents of the University of California (Regents).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *    3. Neither the name of the copyright holder nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Please contact the author(s) of this library if you have any questions.
 * Authors: Erik Nelson            ( eanelson@eecs.berkeley.edu )
 *          David Fridovich-Keil   ( dfk@eecs.berkeley.edu )
 */

#include "triangulation.h"

#include <Eigen/Core>
#include <Eigen/SVD>
#include <glog/logging.h>

#include "../util/types.h"

namespace bsfm {

using Eigen::MatrixXd;

// Triangulates a single 3D point from > 2 views using the inhomogeneous DLT
// method from H&Z: Multi-View Geometry, Ch 2.2.
bool Triangulate(const FeatureList& features,
                 const std::vector<Camera>& cameras,
                 Point3D& point,
                 double& uncertainty) {
  if (features.size() != cameras.size()) {
    LOG(WARNING)
        << "Number of features does not match number of cameras.";
    return false;
  }

  if (features.size() < 2) {
    LOG(WARNING) << "Need at least two features and cameras to triangulate.";
    return false;
  }

  // Construct the A matrix on page 312.
  MatrixXd A;
  A.resize(features.size() * 2, 4);
  for (size_t ii = 0; ii < features.size(); ++ii) {
    double u = features[ii].u_;
    double v = features[ii].v_;

    const Matrix34d P = cameras[ii].P();
    A.row(2*ii+0) = u * P.row(2) - P.row(0);
    A.row(2*ii+1) = v * P.row(2) - P.row(1);
  }

  // Get svd(A). Save some time and compute a thin U. We still need a full V.
  Eigen::JacobiSVD<MatrixXd> svd;
  svd.compute(A, Eigen::ComputeThinU | Eigen::ComputeFullV);
  if (!svd.computeV()) {
    VLOG(1) << "Failed to compute a singular value decomposition of A matrix.";
    return false;
  }

  // The 3D point is the eigenvector corresponding to the minimum eigenvalue.
  point = Point3D(svd.matrixV().block(0, 3, 3, 1) / svd.matrixV()(3,3));

  // Return false if the point is not visible from all cameras.
  for (size_t ii = 0; ii < cameras.size(); ++ii) {
    double u = 0.0, v = 0.0;
    if (!cameras[ii].WorldToImage(point.X(), point.Y(), point.Z(), &u, &v)) {
      return false;
    }
  }

  // Store the uncertainty as the inverse of the triangulation angle.
  const double angle = MaximumAngle(cameras, point);
  if (angle == 0.0) {  // we actually do want floating point comparison.
    uncertainty = std::numeric_limits<double>::max();
  } else {
    uncertainty = 1.0 / angle;
  }

  return true;
}

// Triangulate the 3D position of a point from a 2D correspondence and two sets
// of camera extrinsics and intrinsics.
bool Triangulate(const FeatureMatch& feature_match, const Camera& camera1,
                 const Camera& camera2, Point3D& point, double& uncertainty) {
  FeatureList features;
  features.push_back(feature_match.feature1_);
  features.push_back(feature_match.feature2_);

  std::vector<Camera> cameras;
  cameras.push_back(camera1);
  cameras.push_back(camera2);

  return Triangulate(features, cameras, point, uncertainty);
}

// Repeats the above function on a list of feature matches, returning a list of
// triangulated 3D points, where each point is computed from a single 2D <--> 2D
// correspondence.
bool Triangulate(const FeatureMatchList& feature_matches, const Camera& camera1,
                 const Camera& camera2, Point3DList& points, double& uncertainty) {
  // Clear output.
  points.clear();

  bool triangulated_all_points = true;
  for (size_t ii = 0; ii < feature_matches.size(); ++ii) {
    Point3D point;

    // Continue on failure, but store (0, 0, 0).
    double point_uncertainty = 0.0;
    if (!Triangulate(feature_matches[ii],
                     camera1,
                     camera2,
                     point,
                     point_uncertainty)) {
      uncertainty += point_uncertainty;
      triangulated_all_points = false;
      point = Point3D();
    }
    uncertainty += point_uncertainty;
    points.push_back(point);
  }

  return triangulated_all_points;
}

// Compute the maximum angle between each pair of observation angles.
double MaximumAngle(const std::vector<Camera>& cameras, const Point3D& point) {
  std::vector<Vector3d> vecs;
  for (const auto& camera : cameras)
    vecs.push_back((point.Get() - camera.Translation()).normalized());

  double largest_angle = 0.0;
  for (size_t ii = 0; ii < cameras.size() - 1; ++ii) {
    for (size_t jj = ii + 1; jj < cameras.size(); ++jj) {
      double angle = std::acos(vecs[ii].dot(vecs[jj]) - 1e-8);
      if (std::isnan(angle) || std::isinf(angle)) {
        LOG(WARNING) << "Observation angle is NaN.";
        continue;
      }

      // We want two 90 degree observations to have the maximum possible angle.
      // Two observations with a 180 degree angle should map back to 0, as the
      // triangulated point will be colinear with the translation between the
      // two cameras, which makes it unobservable.
      if (angle > M_PI_2) {
        angle = M_PI - angle;
      }

      if (angle > largest_angle) {
        largest_angle = angle;
      }
    }
  }
  return largest_angle;
}

}  //\namespace bsfm


//==================================================================================================
/*!
  @file

  @copyright 2016 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)
*/
//==================================================================================================
#ifndef BOOST_SIMD_CONSTANT_PIO_6_HPP_INCLUDED
#define BOOST_SIMD_CONSTANT_PIO_6_HPP_INCLUDED

/*!
  @ingroup group-constant
  @defgroup constant-Pio_6 Pio_6 (function template)

  Generates the constant \f$\frac\pi{6}\f$.

  @headerref{<boost/simd/constant/pio_6.hpp>}

  @par Description

  1.  @code
      template<typename T> T Pio_6();
      @endcode

  2.  @code
      template<typename T> T Pio_6( boost::simd::as_<T> const& target );
      @endcode

  Generates a value of type @c T that evaluates to \f$\frac\pi{6}\f$.

  @par Parameters

  | Name                | Description                                                         |
  |--------------------:|:--------------------------------------------------------------------|
  | **target**          | a [placeholder](@ref type-as) value encapsulating the constant type |

  @par Return Value
  A value of type @c T that evaluates to `T(0.52359877559829887307710723054658)`

  @par Requirements
  - **T** models IEEEValue
**/

#include <boost/simd/constant/scalar/pio_6.hpp>
#include <boost/simd/constant/simd/pio_6.hpp>

#endif


#include "nlmatode.h"

#include <Eigen/Core>
#include <Eigen/LU>
#include <cmath>
#include <iostream>
#include <limits>

// Supplies class Ode45
#include "../../../lecturecodes/Ode45/ode45.h"
// Supplied auxiliary function for linear regression
#include "../../../lecturecodes/helperfiles/polyfit.h"

namespace NLMatODE {

/* SAM_LISTING_BEGIN_1 */
Eigen::MatrixXd matode(const Eigen::MatrixXd &Y0, double T) {
  // Use the Ode45 class to find an approximation
  // of the matrix IVP $Y' = -(Y-Y')*Y$ at time $T$
  Eigen::MatrixXd YT;
  //====================
  // Your code goes here
  //====================
  return YT;
}
/* SAM_LISTING_END_1 */

/* SAM_LISTING_BEGIN_2 */
bool checkinvariant(const Eigen::MatrixXd &M, double T) {
  // Check if $Y'*Y$ is preserved at the time $T$ by matode.
  //====================
  // Your code goes here
  //====================

  return false;
}
/* SAM_LISTING_END_2 */

/* SAM_LISTING_BEGIN_3 */
double cvgDiscreteGradientMethod() {
  // Compute the fitted convergence rate of the Discrete
  // gradient method. Also tabulate the values M and the errors.
  double conv_rate = 0;
  //====================
  // Your code goes here
  //====================
  return conv_rate;
}
/* SAM_LISTING_END_3 */

}  // namespace NLMatODE


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

namespace faa = fern::algorithm::accumulator;

// TODO Once we have a full blown square algorithm we must use that
//      instead of this one.
template<
    typename T>
inline constexpr T square(
    T const& value)
{
    return value * value;
}

BOOST_AUTO_TEST_CASE(default_construct)
{
    faa::StandardDeviation<int> standard_deviation;
}

BOOST_AUTO_TEST_CASE(accumulate)
{
    {
        faa::StandardDeviation<int> standard_deviation(5);
        // 5
        BOOST_CHECK_EQUAL(standard_deviation(), static_cast<int>(std::sqrt((
            square(5 - 5)) / 1)));

        standard_deviation(2);
        // 5 2
        BOOST_CHECK_EQUAL(standard_deviation(), static_cast<int>(std::sqrt((
            square(3 - 5) +
            square(3 - 2)) / 2)));

        standard_deviation(3);
        // 5 2 3
        BOOST_CHECK_EQUAL(standard_deviation(), static_cast<int>(std::sqrt((
            square(3 - 5) +
            square(3 - 2) +
            square(3 - 3)) / 3)));

        standard_deviation = 8;
        // 8
        BOOST_CHECK_EQUAL(standard_deviation(), static_cast<int>(std::sqrt((
            square(8 - 8)) / 1)));
    }

    {
        faa::StandardDeviation<int, double> standard_deviation(5);
        // 5
        BOOST_CHECK_EQUAL(standard_deviation(), std::sqrt((
            square(5.0 - 5.0)) / 1.0));

        standard_deviation(2);
        // 5 2
        BOOST_CHECK_EQUAL(standard_deviation(), std::sqrt((
            square(3.5 - 5.0) +
            square(3.5 - 2.0)) / 2.0));

        standard_deviation = 3;
        // 3
        BOOST_CHECK_EQUAL(standard_deviation(), std::sqrt((
            square(3.0 - 3.0)) / 1.0));
    }
}

BOOST_AUTO_TEST_CASE(merge)
{
    {
        auto standard_deviation(faa::StandardDeviation<int>(15) |
            faa::StandardDeviation<int>(5));
        // 15 5
        BOOST_CHECK_EQUAL(standard_deviation(), static_cast<int>(std::sqrt((
            square(10 - 15) +
            square(10 - 5)) / 2)));
    }

    {
        auto standard_deviation(faa::StandardDeviation<int, double>(5) |
            faa::StandardDeviation<int, double>(20));
        // 5 20
        BOOST_CHECK_EQUAL(standard_deviation(), std::sqrt((
            square(12.5 - 5.0) +
            square(12.5 - 20.0)) / 2.0));
    }
}


#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE LinearSolve

#include <iostream>
#include <random>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <geomc/linalg/LUDecomp.h>
#include <geomc/linalg/Orthogonal.h>

using namespace geom;
using namespace std;

typedef std::mt19937_64 rng_t;

// test: check that PLU = M, actually
//       (is P what it says it is?)

template <typename T>
void randomize(T* v, index_t n, rng_t* rng) {
    typedef std::normal_distribution<T> d_normal_t;
    d_normal_t gauss = d_normal_t(0., 1); // (ctr, variance)

    for (index_t i = 0; i < n; ++i) {
        v[i] = gauss(*rng);
    }
}

template <typename T, index_t N>
void solve_vectors(rng_t* rng) {
    Vec<T,N> bases[N]; // destroyed by the factorization
    Vec<T,N> vi[N];
    Vec<T,N> b;
    Vec<T,N> x;
    randomize<T>(bases[0].begin(), N * N, rng);
    randomize<T>(b.begin(), N, rng);
    std::copy(bases, bases + N, vi); // copy the bases, so we can check them

    // we should be able to write b as x[i] * bases[i].
    if (linear_solve(bases, &x, b, 0)) {
        Vec<T,N> b0;
        for (index_t i = 0; i < N; ++i) {
            b0 += x[i] * vi[i];
        }
        // check that the components of b0 and b are close.
        for (index_t i = 0; i < N; ++i) {
            BOOST_CHECK_CLOSE(b[i], b0[i], 1e-5);
        }
    } else {
        // ↓ very unlikely
        std::cerr << "Singular test matrix\n";
    }
}

template <typename T, index_t N>
void exercise_solve_vectors(rng_t* rng, index_t trials) {
    for (index_t i = 0; i < trials; ++i) {
        solve_vectors<T,N>(rng);
    }
}

template <typename T>
void exercise_plu(rng_t* rng, index_t n, index_t trials) {
    SimpleMatrix<T,0,0> mx(n, n);
    SimpleMatrix<T,0,0>  L(n,n);
    SimpleMatrix<T,0,0>  U(n,n);
    SimpleMatrix<T,0,0> LU(n,n);
    PLUDecomposition<T,0,0> plu(mx);

    for (index_t i = 0; i < trials; ++i) {
        randomize(mx.begin(), n * n, rng);
        plu.decompose(mx);
        plu.get_L(&L);
        plu.get_U(&U);
        mul(&LU, L, U);     // LU <- L * U
        mul(&L, plu.P, mx); // L  <- P * M
        // check that LU = PM
        for (index_t j = 0; j < n * n; ++j) {
            BOOST_CHECK_CLOSE(LU.begin()[j], L.begin()[j], 1e-5);
        }
    }
}

template <typename T, index_t N>
void exercise_orthogonalize(rng_t* rng, index_t trials) {
    Vec<T,N> vs[N];
    for (index_t i = 0; i < trials; ++i) {
        randomize(vs[0].begin(), N * N, rng);
        orthogonalize(vs, N);
        // check that each of the orthogonalized bases have ~= 0 dot
        // product with all the others:
        for (index_t j = 0; j < N - 1; ++j) {
            for (index_t k = j + 1; k < N; ++k) {
                BOOST_CHECK_SMALL(vs[j].dot(vs[k]), 1e-5);
            }
        }
    }
}

template <typename T, index_t N>
void exercise_nullspace(rng_t* rng, index_t trials) {
    auto urnd = std::uniform_int_distribution<index_t>(1, N - 1);
    Vec<T,N> bases[N];
    for (index_t i = 0; i < trials; ++i) {
        index_t n = urnd(*rng);
        randomize(bases[0].begin(), n * N, rng);
        nullspace(bases, n, bases + n);

        // verify that each of the null bases have
        // zero dot product with the source bases.
        // (they are not guaranteed to be orthogonal to each other)
        for (index_t j = 0; j < n; ++j) {
            for (index_t k = n; k < N; ++k) {
                BOOST_CHECK_SMALL(bases[j].dot(bases[k]), 1e-5);
            }
        }
    }
}

BOOST_AUTO_TEST_SUITE(linear_solve_tests)

BOOST_AUTO_TEST_CASE(verify_nullspace) {
    rng_t rng(16512485420001724907ULL);
    exercise_nullspace<double,  2>(&rng, 250);
    exercise_nullspace<double,  3>(&rng, 250);
    exercise_nullspace<double,  4>(&rng, 250);
    exercise_nullspace<double,  5>(&rng, 250);
    exercise_nullspace<double, 10>(&rng, 250);
}

BOOST_AUTO_TEST_CASE(verify_orthogonal) {
    rng_t rng(15794404771588593305ULL);
    exercise_orthogonalize<double,  2>(&rng, 250);
    exercise_orthogonalize<double,  3>(&rng, 250);
    exercise_orthogonalize<double,  4>(&rng, 250);
    exercise_orthogonalize<double,  5>(&rng, 250);
    exercise_orthogonalize<double, 10>(&rng, 250);
}

BOOST_AUTO_TEST_CASE(verify_PLU) {
    rng_t rng(1013126187766094264ULL);
    exercise_plu<double>(&rng, 2,  250);
    exercise_plu<double>(&rng, 3,  250);
    exercise_plu<double>(&rng, 4,  250);
    exercise_plu<double>(&rng, 5,  250);
    exercise_plu<double>(&rng, 7,  250);
    exercise_plu<double>(&rng, 10, 100);
}

BOOST_AUTO_TEST_CASE(linear_solve_tests) {
    rng_t rng(7301667549950575693ULL);
    exercise_solve_vectors<double,2>(&rng, 250);
    exercise_solve_vectors<double,3>(&rng, 250);
    exercise_solve_vectors<double,4>(&rng, 250);
    exercise_solve_vectors<double,5>(&rng, 250);
    exercise_solve_vectors<double,6>(&rng, 250);
    exercise_solve_vectors<double,7>(&rng, 250);
}

BOOST_AUTO_TEST_SUITE_END()


#include <stdio.h>
#include <math.h>
#include <iostream>
#include <Eigen/Eigen>

using namespace Eigen;

/*
 * Function shape
 *
 * @desript Display shape information of given matrix.
 */
void shape(const char *msg, Matrix<float, Dynamic, Dynamic> in)
{
  std::cout << msg << "("  << in.rows() << "," << in.cols() << ")" << std::endl;
}

/*
 * Function loge()
 *
 * @desript Calculate logf() for each items in given matrix.
 */
Matrix<float, Dynamic, Dynamic> loge(Matrix<float, Dynamic, Dynamic> in)
{
  Matrix<float, Dynamic, Dynamic> out = in;

  out = out.array() + 1e-7f;

  for(int i=0; i<in.cols(); i++)
    {
      out(0, i) = logf(out(0,i));
    }

  return out;
}

/*
 * Function cross_entropy()
 *
 * @desript Calculate Cross Entropy Loss value from 2 input matrix.
 */
float cross_entropy(Matrix<float, Dynamic, Dynamic> output, Matrix<float, Dynamic, Dynamic> expect)
{
  Matrix<float, Dynamic, Dynamic> tmp;
  float out = 0.f;
  tmp = expect.array() * loge(output).array();
  out = tmp.sum();
  return -out;
};

/*
 * Class NNLayer
 *
 * @desript Base class of Neural Network Layer.
 */
class NNLayer {
  protected:
    NNLayer *next;
    NNLayer *back;

  public:
    NNLayer() : next(NULL), back(NULL)
      {
      };

    virtual ~NNLayer() {};

    virtual Matrix<float, Dynamic, Dynamic> forward(Matrix<float, Dynamic, Dynamic> m) = 0;
    virtual Matrix<float, Dynamic, Dynamic> backward(float train_ratio, Matrix<float, Dynamic, Dynamic> m) = 0;
    virtual void resize(int rows, int cols) = 0;

    void setNext(NNLayer *n)
      {
        next = n;
        n->back = this;
      };

    NNLayer * getNext()
      {
        return next;
      };

};

/*
 * Class LastActivation
 *
 * @desript Base class of Final Activation Layer. This has loss() method function.
 */
class LastActivation : public NNLayer {
  public:
    LastActivation() : NNLayer()
      {
      };
    virtual ~LastActivation(){};

    virtual float loss(Matrix<float, Dynamic, Dynamic> expect) = 0;
};

/*
 * Class SoftMaxLayer
 *
 * @desript A kind of LastActivation Layer.
 */
class SoftMaxLayer : public LastActivation {
  Matrix<float, 1, Dynamic> output;
  public:
    SoftMaxLayer() : LastActivation()
      {
      };

    ~SoftMaxLayer() {};

    Matrix<float, Dynamic, Dynamic> forward(Matrix<float, Dynamic, Dynamic> m)
      {
        float sum;
        float max = m.maxCoeff(); // Maxvalue in the matrix.

        output = m.array() - max; // Measures of overflow.

        output = output.array().exp();
        sum = output.sum();
        output = output.array() / sum;

        if (next != NULL)
          return next->forward(output);
        else
          return output;
      };

    Matrix<float, Dynamic, Dynamic> backward(float train_ratio, Matrix<float, Dynamic, Dynamic> m)
      {
        Matrix<float, Dynamic, Dynamic> ret = output - m;
        if (back != NULL)
          return back->backward(train_ratio, ret);
        else
          return ret;
      };

    float loss(Matrix<float, Dynamic, Dynamic> expect)
      {
        return cross_entropy(output, expect);
      };

    void resize(int rows, int cols)
      {
      };
};

/*
 * Class ReLULayer
 *
 * @desript A kind of Activation Layer.
 */
class ReLULayer : public NNLayer {
  Matrix<float, 1, Dynamic> output;
  public:
    ReLULayer() : NNLayer()
      {
      };

    ~ReLULayer() {}

    Matrix<float, Dynamic, Dynamic> forward(Matrix<float, Dynamic, Dynamic> m)
      {
        output = m;
        for(int i=0; i<output.cols(); i++)
          {
            output(0, i) = output(0, i) <= 0 ? 0 : output(0,i);
          }

        if (next != NULL)
          return next->forward(output);
        else
          return output;
      };

    Matrix<float, Dynamic, Dynamic> backward(float train_ratio, Matrix<float, Dynamic, Dynamic> m)
      {
        Matrix<float, Dynamic, Dynamic> ret = m;
        for(int i=0; i<ret.cols(); i++)
          {
            ret(0, i) = output(0, i) <= 0 ? 0 : ret(0,i);
          }

        if (back != NULL)
          return back->backward(train_ratio, ret);
        else
          return ret;
      };

    void resize(int rows, int cols)
      {
        output = Matrix<float, 1, Dynamic>::Random(1, cols);
      };
};

/*
 * Class AffineLayer
 *
 * @desript A kind of Neural Network Layer.
 */
class AffineLayer : public NNLayer {
  Matrix<float, Dynamic, Dynamic> w;
  Matrix<float, 1, Dynamic> bias;
  Matrix<float, 1, Dynamic> output;
  Matrix<float, 1, Dynamic> inputx;

  public:
    AffineLayer() : NNLayer()
      {
      }

    AffineLayer(int rows, int cols) : NNLayer()
      {
        resize(rows, cols);
      }

    ~AffineLayer() {};

    void resize(int rows, int cols)
      {
        w.resize(rows, cols);
        bias.resize(1, cols);
        output.resize(1, cols);

        w      = Matrix<float, Dynamic, Dynamic>::Random(rows, cols);
        bias   = Matrix<float, 1, Dynamic>::Random(1, cols);
        output = Matrix<float, 1, Dynamic>::Random(1, cols);
      }

    Matrix<float, Dynamic, Dynamic> forward(Matrix<float, Dynamic, Dynamic> m)
      {
        inputx = m;
        output = (m * w) + bias;

        if (next != NULL)
          {
            return next->forward(output);
          }
        else
          {
            return output;
          }
      }

    Matrix<float, Dynamic, Dynamic> backward(float train_ratio, Matrix<float, Dynamic, Dynamic> m)
      {
        Matrix<float, Dynamic, Dynamic> ret;
        Matrix<float, Dynamic, Dynamic> dw;
        float db;

        ret = m * w.transpose();
        dw = inputx.transpose() * m;
        db = m.sum();

        w = w - (dw * train_ratio);
        bias = bias.array() - (db * train_ratio);

        if (back != NULL)
          return back->backward(train_ratio, ret);
        else
          return ret;
      };
};

/*
 * Class AffineLayer
 *
 * @desript A kind of Neural Network Layer.
 */
class NeuralNetwork {
  NNLayer *top_layer;
  NNLayer *last_layer;
  Matrix<float, Dynamic, Dynamic> output;

  public:
    NeuralNetwork() : top_layer(NULL), last_layer(NULL)
      {
      };
    ~NeuralNetwork()
      {
        NNLayer *tmp;
        for(NNLayer *layer = top_layer; layer != NULL; )
          {
            tmp = layer->getNext();
            delete layer;
            layer = tmp;
          }
      };

    void createNewLayer(int innum, int outnum, bool is_last=false)
      {
        NNLayer *new_affine;
        NNLayer *activation;

        new_affine = new AffineLayer(innum, outnum);

        if (is_last)
          {
            activation = new SoftMaxLayer();
          }
        else
          {
            activation = new ReLULayer();
          }

        new_affine->setNext(activation);

        if( last_layer == NULL )
          {
            top_layer = new_affine;
          }
        else
          {
            last_layer->setNext(new_affine);
          }

        last_layer = activation;
      };

    void print_layers()
      {
        for(NNLayer *layer = top_layer; layer != NULL; layer = layer->getNext())
          {
            std::cout << layer << " --> ";
          };
        std::cout << "NULL" << std::endl;
      };

    Matrix<float, Dynamic, Dynamic> forward(Matrix<float, Dynamic, Dynamic> input)
      {
        output = top_layer->forward(input);
        return output;
      };

    float backward(float train_ratio, Matrix<float, Dynamic, Dynamic> m)
      {
        float ret = ((LastActivation *)last_layer)->loss(m);
        last_layer->backward(train_ratio, m);
        return ret;
      };

};

int main(void)
{
  NeuralNetwork nn;

  float loss;
  Matrix<float, Dynamic, Dynamic> out;

#if 1
  Matrix<float, 1, 2> input[4];
  Matrix<float, 1, 1> expect[4];

  input[0] << 0, 0; expect[0] << 0;
  input[1] << 0, 1; expect[1] << 1;
  input[2] << 1, 0; expect[2] << 1;
  input[3] << 1, 1; expect[3] << 0;

  nn.createNewLayer(2,2);
  nn.createNewLayer(2,1, true);

  loss = 100.f;
  while (loss > 0.001f)
    {
      loss = 0.f;
      for(int i=0; i<4; i++)
        {
          // std::cout << "==== " << i+1 << " ===="  << std::endl;
          out = nn.forward( input[i] );
          loss += nn.backward(0.1f, expect[i]);
          // std::cout << "   out = " << out << std::endl;
        }
      loss /= 4;
      std::cout << "loss = " << loss << std::endl;
    }

  for(int i=0; i<4; i++)
    {
      std::cout << "Expect = " << expect[i] << " Input  = " << input[i] << std::endl;
      out = nn.forward( input[i] );
      std::cout << "Output = " << out << std::endl;
    }

#else
  Matrix<float, 1, 2> input;
  Matrix<float, 1, 2> expect;

  input << 3, 3;
  expect << 0, 1;

  nn.createNewLayer(2, 5);
  nn.createNewLayer(5, 3);
  nn.createNewLayer(3, 2, true);

  std::cout << "tmp input = " << input << std::endl;
  std::cout << "expect = " << expect << std::endl;
  std::cout << "input * expect = " << input.array() * expect.array() << std::endl;

  std::cout << "input = " << input << std::endl;
  input = input.array() + 1;
  std::cout << "input = " << input << std::endl;

  out = nn.forward( input );
  std::cout << "out.rows = " << out.rows() << std::endl;
  std::cout << "out.cols = " << out.cols() << std::endl;
  std::cout << "out = " << out << std::endl;

  loss = 100.f;
  while (loss > 0.001f)
    {
      out = nn.forward( input );
      loss = nn.backward(0.1f, expect);
      std::cout << "out = " << out << std::endl;
      std::cout << "loss = " << loss << std::endl;
    }
#endif

  return 0;
}


#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <vector>

using namespace std;
using boost::multiprecision::cpp_int;

/*
Using the partition generating function..
p(n) = p(n – 1)  + p(k – 2) – p(k – 5) – p(k – 7) + p(k – 12) + p(k – 15) – p(k – 22)…
Where p(0) = 1 and p(n) = 0 for n < 0..
and k = m / 2 + 1 (k % 2 == 0) || -m / 2 + 1.
*/

int main(int argc, char *argv[]) {
	// We will need the generalized pentagonal numbers first.
	vector<cpp_int> k;
	k.push_back(1);
	int n = 1;
	// Loop through everything until we get something that fits our requirement.
	while(true) {
		int i = 0;
		int penta = 1;
		k.push_back(0);
		while(penta <= n) {
			int sign = (i % 4 > 1) ? -1 : 1;
			k[n] += sign * k[n - penta];
			k[n] %= 1'000'000;
			i++;
			// Generate the next pentagonal (generalized number).
			int j = (i % 2 == 0) ? i / 2 + 1 : -(i / 2 + 1);
			penta = j * (3 * j - 1) / 2;
		}
		if(!k[n]) {
			break;
		}
		n++;
	}
	cout << n << endl;
	return 0;
}