// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2017 Sebastian Koch <s.koch@tu-berlin.de> and Daniele Panozzo <daniele.panozzo@gmail.com>
//
// 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 <Eigen/Dense>

#include "python_shared.h"

#include <igl/AABB.h>
#include <igl/ARAPEnergyType.h>
#include <igl/MeshBooleanType.h>
#include <igl/SolverStatus.h>
#include <igl/active_set.h>
#include <igl/adjacency_list.h>
#include <igl/arap.h>
#include <igl/avg_edge_length.h>
#include <igl/barycenter.h>
#include <igl/barycentric_coordinates.h>
#include <igl/barycentric_to_global.h>
#include <igl/bbw.h>
#include <igl/boundary_conditions.h>
#include <igl/boundary_facets.h>
#include <igl/boundary_loop.h>
#include <igl/cat.h>
#include <igl/collapse_edge.h>
#include <igl/colon.h>
#include <igl/column_to_quats.h>
#include <igl/comb_cross_field.h>
#include <igl/comb_frame_field.h>
#include <igl/compute_frame_field_bisectors.h>
#include <igl/cotmatrix.h>
#include <igl/covariance_scatter_matrix.h>
#include <igl/cross_field_missmatch.h>
#include <igl/cut_mesh_from_singularities.h>
#include <igl/deform_skeleton.h>
#include <igl/directed_edge_orientations.h>
#include <igl/directed_edge_parents.h>
#include <igl/doublearea.h>
#include <igl/dqs.h>
#include <igl/edge_lengths.h>
#include <igl/edge_topology.h>
#include <igl/eigs.h>
#include <igl/exact_geodesic.h>
#include <igl/find_cross_field_singularities.h>
#include <igl/fit_rotations.h>
#include <igl/floor.h>
#include <igl/forward_kinematics.h>
#include <igl/gaussian_curvature.h>
#include <igl/get_seconds.h>
#include <igl/grad.h>
#include <igl/harmonic.h>
#include <igl/hsv_to_rgb.h>
#include <igl/internal_angles.h>
#include <igl/invert_diag.h>
#include <igl/is_irregular_vertex.h>
#include <igl/jet.h>
#include <igl/lbs_matrix.h>
#include <igl/local_basis.h>
#include <igl/lscm.h>
#include <igl/map_vertices_to_circle.h>
#include <igl/massmatrix.h>
#include <igl/min_quad_with_fixed.h>
#include <igl/normalize_row_lengths.h>
#include <igl/normalize_row_sums.h>
#include <igl/parula.h>
#include <igl/per_corner_normals.h>
#include <igl/per_edge_normals.h>
#include <igl/per_face_normals.h>
#include <igl/per_vertex_normals.h>
#include <igl/planarize_quad_mesh.h>
#include <igl/point_mesh_squared_distance.h>
#include <igl/polar_svd.h>
#include <igl/principal_curvature.h>
#include <igl/quad_planarity.h>
#include <igl/randperm.h>
#include <igl/readDMAT.h>
#include <igl/readMESH.h>
#include <igl/readOBJ.h>
#include <igl/readOFF.h>
#include <igl/readTGF.h>
#include <igl/read_triangle_mesh.h>
#include <igl/remove_duplicate_vertices.h>
#include <igl/rotate_vectors.h>
#include <igl/setdiff.h>
#include <igl/signed_distance.h>
#include <igl/slice.h>
#include <igl/slice_into.h>
#include <igl/slice_mask.h>
#include <igl/slice_tets.h>
#include <igl/sortrows.h>
#include <igl/triangle_triangle_adjacency.h>
#include <igl/unique.h>
#include <igl/unproject_onto_mesh.h>
#include <igl/upsample.h>
#include <igl/winding_number.h>
#include <igl/writeMESH.h>
#include <igl/writeOBJ.h>
#include <igl/writePLY.h>
#include <igl/readPLY.h>
#include <igl/seam_edges.h>

void python_export_igl(py::module &m)
{
#include "modules/py_typedefs.cpp"

#include "py_igl/py_AABB.cpp"
#include "py_igl/py_ARAPEnergyType.cpp"
#include "py_igl/py_MeshBooleanType.cpp"
#include "py_igl/py_SolverStatus.cpp"
#include "py_igl/py_active_set.cpp"
#include "py_igl/py_adjacency_list.cpp"
#include "py_igl/py_arap.cpp"
#include "py_igl/py_avg_edge_length.cpp"
#include "py_igl/py_barycenter.cpp"
#include "py_igl/py_barycentric_coordinates.cpp"
#include "py_igl/py_barycentric_to_global.cpp"
#include "py_igl/py_bbw.cpp"
#include "py_igl/py_boundary_conditions.cpp"
#include "py_igl/py_boundary_facets.cpp"
#include "py_igl/py_boundary_loop.cpp"
#include "py_igl/py_cat.cpp"
#include "py_igl/py_collapse_edge.cpp"
#include "py_igl/py_colon.cpp"
#include "py_igl/py_column_to_quats.cpp"
#include "py_igl/py_comb_cross_field.cpp"
#include "py_igl/py_comb_frame_field.cpp"
#include "py_igl/py_compute_frame_field_bisectors.cpp"
#include "py_igl/py_cotmatrix.cpp"
#include "py_igl/py_covariance_scatter_matrix.cpp"
#include "py_igl/py_cross_field_missmatch.cpp"
#include "py_igl/py_cut_mesh_from_singularities.cpp"
#include "py_igl/py_deform_skeleton.cpp"
#include "py_igl/py_directed_edge_orientations.cpp"
#include "py_igl/py_directed_edge_parents.cpp"
#include "py_igl/py_doublearea.cpp"
#include "py_igl/py_dqs.cpp"
#include "py_igl/py_edge_lengths.cpp"
#include "py_igl/py_edge_topology.cpp"
#include "py_igl/py_eigs.cpp"
#include "py_igl/py_exact_geodesic.cpp"
#include "py_igl/py_find_cross_field_singularities.cpp"
#include "py_igl/py_fit_rotations.cpp"
#include "py_igl/py_floor.cpp"
#include "py_igl/py_forward_kinematics.cpp"
#include "py_igl/py_gaussian_curvature.cpp"
#include "py_igl/py_get_seconds.cpp"
#include "py_igl/py_grad.cpp"
#include "py_igl/py_harmonic.cpp"
#include "py_igl/py_hsv_to_rgb.cpp"
#include "py_igl/py_internal_angles.cpp"
#include "py_igl/py_invert_diag.cpp"
#include "py_igl/py_is_irregular_vertex.cpp"
#include "py_igl/py_jet.cpp"
#include "py_igl/py_lbs_matrix.cpp"
#include "py_igl/py_local_basis.cpp"
#include "py_igl/py_lscm.cpp"
#include "py_igl/py_map_vertices_to_circle.cpp"
#include "py_igl/py_massmatrix.cpp"
#include "py_igl/py_min_quad_with_fixed.cpp"
#include "py_igl/py_normalize_row_lengths.cpp"
#include "py_igl/py_normalize_row_sums.cpp"
#include "py_igl/py_parula.cpp"
#include "py_igl/py_per_corner_normals.cpp"
#include "py_igl/py_per_edge_normals.cpp"
#include "py_igl/py_per_face_normals.cpp"
#include "py_igl/py_per_vertex_normals.cpp"
#include "py_igl/py_planarize_quad_mesh.cpp"
#include "py_igl/py_point_mesh_squared_distance.cpp"
#include "py_igl/py_polar_svd.cpp"
#include "py_igl/py_principal_curvature.cpp"
#include "py_igl/py_quad_planarity.cpp"
#include "py_igl/py_randperm.cpp"
#include "py_igl/py_readDMAT.cpp"
#include "py_igl/py_readMESH.cpp"
#include "py_igl/py_readOBJ.cpp"
#include "py_igl/py_readOFF.cpp"
#include "py_igl/py_readTGF.cpp"
#include "py_igl/py_read_triangle_mesh.cpp"
#include "py_igl/py_remove_duplicate_vertices.cpp"
#include "py_igl/py_rotate_vectors.cpp"
#include "py_igl/py_setdiff.cpp"
#include "py_igl/py_signed_distance.cpp"
#include "py_igl/py_slice.cpp"
#include "py_igl/py_slice_into.cpp"
#include "py_igl/py_slice_mask.cpp"
#include "py_igl/py_slice_tets.cpp"
#include "py_igl/py_sortrows.cpp"
#include "py_igl/py_triangle_triangle_adjacency.cpp"
#include "py_igl/py_unique.cpp"
#include "py_igl/py_unproject_onto_mesh.cpp"
#include "py_igl/py_upsample.cpp"
#include "py_igl/py_winding_number.cpp"
#include "py_igl/py_writeMESH.cpp"
#include "py_igl/py_writeOBJ.cpp"
#include "py_igl/py_writePLY.cpp"
#include "py_igl/py_readPLY.cpp"
#include "py_igl/py_seam_edges.cpp"
}


#include <boost/test/unit_test.hpp>

#include <sway/math.h>

using namespace sway;

BOOST_AUTO_TEST_SUITE(TRectTestSuite)

/*!
 * \brief
 *    Убеждаемся, что конструктор по умолчанию приводит все компоненты к нулю.
 */
BOOST_AUTO_TEST_CASE(TRectTestCase_DefaultConstructor) {
	const math::rect4i_t rect;

	BOOST_CHECK_EQUAL(rect.getL(), 0);
	BOOST_CHECK_EQUAL(rect.getT(), 0);
	BOOST_CHECK_EQUAL(rect.getR(), 0);
	BOOST_CHECK_EQUAL(rect.getB(), 0);
}

/*!
 * \brief
 *    Убеждаемся, что конструктор устанавливает все значения компонентов в те,
 *    которые были заданы.
 */
BOOST_AUTO_TEST_CASE(TRectTestCase_ComponentConstructor) {
	const s32_t x = 8, y = 16, w = 32, h = 64;
	const math::rect4i_t rect(x, y, w, h);

	BOOST_CHECK_EQUAL(rect.getL(), x);
	BOOST_CHECK_EQUAL(rect.getT(), y);
	BOOST_CHECK_EQUAL(rect.getR(), x + w);
	BOOST_CHECK_EQUAL(rect.getB(), y + h);
	BOOST_CHECK_EQUAL(rect.getW(), w);
	BOOST_CHECK_EQUAL(rect.getH(), h);
}

BOOST_AUTO_TEST_CASE(TRectTestCase_Offset) {
	const s32_t x = 8, y = 16, w = 32, h = 64;
	const s32_t xoffset = 2, yoffset = 4;

	math::rect4i_t rect(x, y, w, h);
	rect.offset(xoffset, yoffset);

	BOOST_CHECK_EQUAL(rect.getL(), x + xoffset);
	BOOST_CHECK_EQUAL(rect.getT(), y + yoffset);
	BOOST_CHECK_EQUAL(rect.getR(), x + xoffset + w);
	BOOST_CHECK_EQUAL(rect.getB(), y + yoffset + h);
	BOOST_CHECK_EQUAL(rect.getW(), w);
	BOOST_CHECK_EQUAL(rect.getH(), h);
}

/*!
 * \brief
 *    Убеждаемся, что преобразование в TSize<type> проходит правильно.
 */
BOOST_AUTO_TEST_CASE(TRectTestCase_ConvertToSize) {
	const s32_t x = 8, y = 16, w = 32, h = 64;

	math::rect4i_t rect(x, y, w, h);
	math::size2i_t size = rect.toSize();

	BOOST_CHECK_EQUAL(size.getW(), w);
	BOOST_CHECK_EQUAL(size.getH(), h);
}

BOOST_AUTO_TEST_CASE(TRectTestCase_IsEmpty) {
	BOOST_CHECK(math::TRect<s32_t>(0, 0, 0, 32).isEmpty());
	BOOST_CHECK(math::TRect<s32_t>(0, 0, 32, 0).isEmpty());
	BOOST_CHECK_EQUAL(math::TRect<s32_t>(0, 0, 32, 32).isEmpty(), false);
}

BOOST_AUTO_TEST_SUITE_END()


/* Copyright (C) 2012-2019 IBM Corp.
 * This program is 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. See accompanying LICENSE file.
 */
// Test_tableLookup.cpp - test the table-lookup module
#include <iostream>
#include <cassert>
#include <NTL/BasicThreadPool.h>
#include "intraSlot.h"
#include "tableLookup.h"
#include "ArgMap.h"

NTL_CLIENT
using namespace helib;

#ifdef DEBUG_PRINTOUT
#include "debugging.h"
#endif

static std::vector<zzX> unpackSlotEncoding; // a global variable
static bool verbose=false;

static long mValues[][15] = {
// { p, phi(m),   m,   d, m1, m2, m3,    g1,   g2,   g3, ord1,ord2,ord3, B,c}
  {  2,    48,   105, 12,  3, 35,  0,    71,    76,    0,   2,  2,   0, 25, 2},
  {  2 ,  600,  1023, 10, 11, 93,  0,   838,   584,    0,  10,  6,   0, 25, 2},
  {  2,  2304,  4641, 24,  7,  3,221,  3979,  3095, 3760,   6,  2,  -8, 25, 3},
  {  2, 15004, 15709, 22, 23,683,  0,  4099, 13663,    0,  22, 31,   0, 25, 3},
  {  2, 27000, 32767, 15, 31,  7, 151, 11628, 28087,25824, 30,  6, -10, 28, 4}
};

// test function declerations
void testLookup(const FHESecKey& sKey, long insize, long outsize);
void testWritein(const FHESecKey& sKey, long insize, long nTests);

int main(int argc, char *argv[])
{
  ArgMap amap;
  long prm=1;
  amap.arg("prm", prm, "parameter size (0-tiny,...,4-huge)");
  long bitSize = 5;
  amap.arg("bitSize", bitSize, "bitSize of input integers (<=32)");
  long outSize = 0;
  amap.arg("outSize", outSize, "bitSize of output integers", "as many as needed");
  long nTests = 3;
  amap.arg("nTests", nTests, "number of tests to run");
  bool bootstrap = false;
  amap.arg("bootstrap", bootstrap, "test multiplication with bootstrapping");
  long seed=0;
  amap.arg("seed", seed, "PRG seed");
  long nthreads=1;
  amap.arg("nthreads", nthreads, "number of threads");
  amap.arg("verbose", verbose, "print more information");

  amap.parse(argc, argv);
  assert(prm >= 0 && prm < 5);
  assert(bitSize<=7);
  if (seed) NTL::SetSeed(ZZ(seed));
  if (nthreads>1) NTL::SetNumThreads(nthreads);

  if (bitSize<=0) bitSize=5;
  else if (bitSize>32) bitSize=32;

  long* vals = mValues[prm];
  long p = vals[0];
  //  long phim = vals[1];
  long m = vals[2];

  NTL::Vec<long> mvec;
  append(mvec, vals[4]);
  if (vals[5]>1) append(mvec, vals[5]);
  if (vals[6]>1) append(mvec, vals[6]);

  std::vector<long> gens;
  gens.push_back(vals[7]);
  if (vals[8]>1) gens.push_back(vals[8]);
  if (vals[9]>1) gens.push_back(vals[9]);

  std::vector<long> ords;
  ords.push_back(vals[10]);
  if (abs(vals[11])>1) ords.push_back(vals[11]);
  if (abs(vals[12])>1) ords.push_back(vals[12]);

  long B = vals[13];
  long c = vals[14];

  // Compute the number of levels
  long L;
  if (bootstrap) L=900; // that should be enough
  else           L = 30*(5 +bitSize);

  if (verbose) {
    cout <<"input bitSize="<<bitSize<<", output size bound="<<outSize
         <<", running "<<nTests<<" tests for each function\n";
    if (nthreads>1) cout << "  using "<<NTL::AvailableThreads()<<" threads\n";
    cout << "computing key-independent tables..." << std::flush;
  }
  FHEcontext context(m, p, /*r=*/1, gens, ords);
  buildModChain(context, L, c,/*willBeBootstrappable=*/bootstrap);
  if (bootstrap) {
    context.makeBootstrappable(mvec, /*t=*/0);
  }
  buildUnpackSlotEncoding(unpackSlotEncoding, *context.ea);
  if (verbose) {
    cout << " done.\n";
    context.zMStar.printout();
    cout << " L="<<L<<", B="<<B<<endl;
    cout << "\ncomputing key-dependent tables..." << std::flush;
  }
  FHESecKey secKey(context);
  secKey.GenSecKey();
  addSome1DMatrices(secKey); // compute key-switching matrices
  addFrbMatrices(secKey);
  if (bootstrap) secKey.genRecryptData();
  if (verbose) cout << " done\n";

  activeContext = &context; // make things a little easier sometimes
#ifdef DEBUG_PRINTOUT
  dbgEa = (EncryptedArray*) context.ea;
  dbgKey = &secKey;
#endif

  testLookup(secKey, bitSize, outSize);
  cout << "GOOD\n";

  testWritein(secKey, bitSize, nTests);
  cout << "GOOD\n";

  if (verbose) printAllTimers(cout);
  return 0;
}

static void encryptIndex(std::vector<Ctxt>& ei, long index,
                         const FHESecKey& sKey)
{
  for (long i=0; i<lsize(ei); i++)
    sKey.Encrypt(ei[i], to_ZZX((index>>i) &1)); // i'th bit of index
}

static long decryptIndex(std::vector<Ctxt>& ei, const FHESecKey& sKey)
{
  long num=0;
  for (long i=0; i<lsize(ei); i++) {
    ZZX poly;
    sKey.Decrypt(poly, ei[i]);
    num += to_long(NTL::ConstTerm(poly)) << i;
  }
  return num;
}

void testLookup(const FHESecKey& sKey, long insize, long outsize)
{
  // Build a table s.t. T[i] = 2^{outsize -1}/(i+1), i=0,...,2^insize -1
  std::vector<zzX> T;
  buildLookupTable(T, [](double x){ return 1/(x+1.0);},
                   insize,  /*scale_in=*/0, /*sign_in=*/0,
                   outsize, /*scale_out=*/1-outsize, /*sign_out=*/0,
                   *(sKey.getContext().ea));

  assert(lsize(T)==(1L<<insize));
  for (long i=0; i<lsize(T); i++) {
    Ctxt c(sKey);
    std::vector<Ctxt> ei(insize, c);
    encryptIndex(ei, i, sKey);              // encrypt the index
    tableLookup(c, T, CtPtrs_vectorCt(ei)); // get the encrypted entry
    // decrypt and compare
    ZZX poly;  sKey.Decrypt(poly, c); // decrypt
    zzX poly2; convert(poly2, poly);  // convert to zzX
    if (poly2 != T[i]) {
      cout << "BAD\n";
      if (verbose) cout << "testLookup error: decrypted T["<<i<<"]\n";
      exit(0);
    }
  }
}

void testWritein(const FHESecKey& sKey, long size, long nTests)
{
  const EncryptedArray& ea = *(sKey.getContext().ea);
  long tSize = 1L << size; // table size

  // encrypt a random table
  vector<long> pT(tSize, 0);         // plaintext table
  vector<Ctxt> T(tSize, Ctxt(sKey)); // encrypted table
  for (long i=0; i<size; i++) {
    long bit = RandomBits_long(1);   // a random bit
    sKey.Encrypt(T[i], to_ZZX(bit));
    pT[i] = bit;
  }

  // Add 1 to 20 random entries in the table
  for (long count=0; count<nTests; count++) {
    // encrypt a random index into the table
    long index = RandomBnd(tSize); // 0 <= index < tSize
    vector<Ctxt> I(size, Ctxt(sKey));
    encryptIndex(I, index, sKey);

    // do the table write-in
    tableWriteIn(CtPtrs_vectorCt(T), CtPtrs_vectorCt(I), &unpackSlotEncoding);
    pT[index]++; // add 1 to entry 'index' in the plaintext table
  }

  // Check that the ciphertext and plaintext tables still match
  for (int i=0; i<tSize; i++) {
    ZZX poly;
    sKey.Decrypt(poly, T[i]);
    long decrypted = to_long(NTL::ConstTerm(poly));
    long p = T[i].getPtxtSpace();
    if ((pT[i] - decrypted) % p) { // not equal mod p
      cout << "BAD\n";
      if (verbose)
        cout << "  testWritein error: decrypted T["<<i<<"]="<<decrypted
             <<" but should be "<<pT[i]<<" (mod "<<p<<")\n";
      exit(0);
    }
  }
}


#ifndef IMAGE_HPP
#define IMAGE_HPP

#include <iostream>
#include <string>
#include <vector>

#include <Eigen/Core>

#include "color.hpp"
#include "log.hpp"

#include "stb_image.h"
#include "stb_image_write.h"

class Image {
  public:
    Image() {}
    Image(int width, int height);

    void setPixel(int row, int col, std::shared_ptr<Color> color);

    void save(std::string filename);
    void load(std::string filename);
    Eigen::Vector4d at(int width, int height);
    Eigen::Vector4d at(double u, double v);

  private:
    void writeMatrixToRGB(const Eigen::MatrixXd& R, const Eigen::MatrixXd& G, const Eigen::MatrixXd& B, const Eigen::MatrixXd& A, const std::string& filename);
    unsigned char doubleToUnsignedChar(const double d);
    double unsignedCharToDouble(const unsigned char x);

    Eigen::MatrixXd red_channel;
    Eigen::MatrixXd green_channel;
    Eigen::MatrixXd blue_channel;
    Eigen::MatrixXd alpha_channel;
};

#endif // IMAGE_HPP


//  (C) Copyright John Maddock 2006, 2021.
//  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 "test_gamma.hpp"
#ifdef TEST_MPFR
#include <boost/multiprecision/mpfr.hpp>
#endif
#ifdef TEST_MPF
#include <boost/multiprecision/gmp.hpp>
#endif
#ifdef TEST_CPP_BIN_FLOAT
#include <boost/multiprecision/cpp_bin_float.hpp>
#endif
#ifdef TEST_CPP_DEC_FLOAT
#include <boost/multiprecision/cpp_dec_float.hpp>
#endif

void expected_results()
{
   //
   // Define the max and mean errors expected for
   // various compilers and platforms.
   //
   add_expected_result(
       ".*",                                          // compiler
       ".*",                                          // stdlib
       ".*",                                          // platform
       ".*",                                          // test type(s)
       ".*near 1.*",                                  // test data group
       ".*lgamma.*", 100000000000LL, 100000000000LL); // test function
   add_expected_result(
       ".*",                          // compiler
       ".*",                          // stdlib
       ".*",                          // platform
       ".*",                          // test type(s)
       ".*near 0.*",                  // test data group
       ".*lgamma.*", 300000, 100000); // test function
   add_expected_result(
       ".*",                 // compiler
       ".*",                 // stdlib
       ".*",                 // platform
       ".*",                 // test type(s)
       ".*",                 // test data group
       ".*", 110000, 50000); // test function

   //
   // Finish off by printing out the compiler/stdlib/platform names,
   // we do this to make it easier to mark up expected error rates.
   //
   std::cout << "Tests run with " << BOOST_COMPILER << ", "
             << BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl;
}

#ifndef TEST_PRECISION
#define TEST_PRECISION 450
#endif

BOOST_AUTO_TEST_CASE(test_main)
{
   expected_results();
   BOOST_MATH_CONTROL_FP;

#ifdef TEST_MPFR
   typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<TEST_PRECISION> > mp_type;
   const char*                                                                            name = "number<mpfr_float_backend<" BOOST_STRINGIZE(TEST_PRECISION) "> >";
#endif
#ifdef TEST_MPF
   typedef boost::multiprecision::number<boost::multiprecision::gmp_float<TEST_PRECISION> > mp_type;
   const char*                                                                              name = "number<gmp_float<" BOOST_STRINGIZE(TEST_PRECISION) "> >";
#endif
#ifdef TEST_CPP_BIN_FLOAT
   typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<TEST_PRECISION> > mp_type;
   const char*                                                                                name = "number<cpp_bin_float<" BOOST_STRINGIZE(TEST_PRECISION) "> >";
#endif
#ifdef TEST_CPP_DEC_FLOAT
   typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<TEST_PRECISION> > mp_type;
   const char*                                                                                name = "number<cpp_dec_float<" BOOST_STRINGIZE(TEST_PRECISION) "> >";
#endif

   test_gamma(mp_type(0), name);
}


#ifndef FeaturesDistance_hpp
#define FeaturesDistance_hpp

#include <QVariantList>
#include <QAlgorithm.hpp>
#include <armadillo>

namespace AA {
	class FeaturesDistance;
}

class AA::FeaturesDistance : public QAlgorithm {

	Q_OBJECT

	QA_INPUT_LIST(QVector<double>, Features)
	QA_OUTPUT(double, Distance)

	QA_CTOR_INHERIT
	QA_IMPL_CREATE(FeaturesDistance)

private:
	arma::mat weightMean(const arma::mat& X,
						 const arma::mat& W);
	arma::mat weightCov(const arma::mat& X,
						const arma::vec& W);

public:
	void run();
};

#endif /* FeaturesDistance_hpp */


// (C) Copyright Andrew Sutton 2007
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

//[tiernan_print_cycles
#include <iostream>

#include <boost/graph/directed_graph.hpp>
#include <boost/graph/tiernan_all_cycles.hpp>

#include "helper.hpp"

using namespace std;
using namespace boost;

// The cycle_printer is a visitor that will print the path that comprises
// the cycle. Note that the back() vertex of the path is not the same as
// the front(). It is implicit in the listing of vertices that the back()
// vertex is connected to the front().
template < typename OutputStream > struct cycle_printer
{
    cycle_printer(OutputStream& stream) : os(stream) {}

    template < typename Path, typename Graph >
    void cycle(const Path& p, const Graph& g)
    {
        // Get the property map containing the vertex indices
        // so we can print them.
        typedef
            typename property_map< Graph, vertex_index_t >::const_type IndexMap;
        IndexMap indices = get(vertex_index, g);

        // Iterate over path printing each vertex that forms the cycle.
        typename Path::const_iterator i, end = p.end();
        for (i = p.begin(); i != end; ++i)
        {
            os << get(indices, *i) << " ";
        }
        os << endl;
    }
    OutputStream& os;
};

// Declare the graph type and its vertex and edge types.
typedef directed_graph<> Graph;
typedef graph_traits< Graph >::vertex_descriptor Vertex;
typedef graph_traits< Graph >::edge_descriptor Edge;

int main(int argc, char* argv[])
{
    // Create the graph and read it from standard input.
    Graph g;
    read_graph(g, cin);

    // Instantiate the visitor for printing cycles
    cycle_printer< ostream > vis(cout);

    // Use the Tiernan algorithm to visit all cycles, printing them
    // as they are found.
    tiernan_all_cycles(g, vis);

    return 0;
}
//]


//=======================================================================
// Copyright (c)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/**
 * @file simulated_annealing_test.cpp
 * @brief
 * @author Piotr Wygocki
 * @version 1.0
 * @date 2014-02-04
 */

#include "test_utils/simple_single_local_search_components.hpp"
#include "test_utils/logger.hpp"

#include "paal/local_search/simulated_annealing.hpp"
#include "paal/local_search/custom_components.hpp"
#include "paal/data_structures/components/components_replace.hpp"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(simulated_annealing)

namespace ls = paal::local_search;
using namespace paal;

BOOST_AUTO_TEST_CASE(simulated_annealing_gain_adaptor_test) {
    int currentSolution{};
    int best{};
    auto sa_gain = ls::make_simulated_annealing_gain_adaptor(
        gain{}, ls::make_exponential_cooling_schema_dependant_on_time(
                    std::chrono::seconds(1), 10, 0.1));

    auto record_solution_commit = ls::make_record_solution_commit_adapter(
        best, commit(), paal::utils::make_functor_to_comparator(f));

    ls::first_improving(currentSolution,
                        ls::make_search_components(get_moves{}, sa_gain,
                                                   record_solution_commit));
    BOOST_CHECK_EQUAL(best, 6);
    LOGLN("solution " << best);
}

BOOST_AUTO_TEST_CASE(simulated_annealing_commit_adaptor_test) {
    int currentSolution{};
    int best{};
    auto sa_commit = ls::make_simulated_annealing_commit_adaptor(
        commit{}, gain{},
        ls::exponential_cooling_schema_dependant_on_iteration(1e3, 1-1e-3));

    auto record_solution_commit = ls::make_record_solution_commit_adapter(
        best, std::move(sa_commit), paal::utils::make_functor_to_comparator(f));

    ls::stop_condition_count_limit stop_cond_count(10);
    auto stop_cond = [&](int) { return !stop_cond_count(); };

    ls::local_search(
        currentSolution, ls::best_strategy{}, stop_cond, stop_cond,
        ls::make_search_components(get_moves{}, gain{},
                                   std::move(record_solution_commit)));
    BOOST_CHECK_EQUAL(best, 6);
    LOGLN("solution " << best);
}

BOOST_AUTO_TEST_CASE(start_temperature_test) {
    double t;

    int solution{};
    auto cooling = [&]() { return t; };
    auto set_temperature = [&](double _t) { t = _t; };
    auto sa_gain = ls::make_simulated_annealing_gain_adaptor(gain{}, cooling);

    auto get_success_rate = [&](double temp, int repeats_number = 1e3) {
        set_temperature(temp);
        get_moves gm{};

        int number_of_success{};
        int total_moves{};
        for (int i = 0; i < repeats_number; ++i) {
            for (auto move : gm(solution)) {
                ++total_moves;
                if (paal::local_search::detail::positive_delta(sa_gain(solution, move))) {
                    ++number_of_success;
                }
            }
        }
        return double(number_of_success) / total_moves;
    };

    // 0.5 success_rate is guarantied for this model
    auto temp =
        ls::start_temperature(solution, sa_gain, get_moves{}, set_temperature);
    BOOST_CHECK_EQUAL(temp, 0.);

    for (auto ratio : { 0.6, 0.7, 0.8, 0.9, 0.95, 0.99 }) {
        int repeat = 1e3;
        temp = ls::start_temperature(solution, sa_gain, get_moves{},
                                     set_temperature, ratio, repeat);
        auto succ_rate = get_success_rate(temp, repeat);
        BOOST_CHECK(std::abs(succ_rate - ratio) < 0.1);
        LOGLN("temp = " << temp << "; success rate = " << succ_rate
                        << "; expected = " << ratio
                        << "; error = " << std::abs(succ_rate - ratio));
    }
}

BOOST_AUTO_TEST_SUITE_END()


//
// Copyright (c) 2021 INRIA
//

#include "pinocchio/spatial/fwd.hpp"
#include "pinocchio/algorithm/parallel/rnea.hpp"
#include "pinocchio/algorithm/rnea.hpp"
#include "pinocchio/algorithm/joint-configuration.hpp"
#include "pinocchio/parsers/sample-models.hpp"
#include "pinocchio/utils/timer.hpp"

#include <iostream>

#include <boost/test/unit_test.hpp>
#include <boost/utility/binary.hpp>

using namespace pinocchio;

BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE(test_parallel_rnea)
{
  pinocchio::Model model; buildModels::humanoidRandom(model);
  Data data_ref(model);

  model.lowerPositionLimit.head<3>().fill(-1.);
  model.upperPositionLimit.head<3>().fill( 1.);

  const Eigen::DenseIndex batch_size = 128;
  const int num_thread = omp_get_max_threads();

  Eigen::MatrixXd q(model.nq,batch_size);
  Eigen::MatrixXd v(model.nv,batch_size);
  Eigen::MatrixXd a(model.nv,batch_size);
  Eigen::MatrixXd tau(model.nv,batch_size);
  Eigen::MatrixXd tau_ref(model.nv,batch_size);

  for(Eigen::DenseIndex i = 0; i < batch_size; ++i)
  {
    q.col(i) = randomConfiguration(model);
    v.col(i) = Eigen::VectorXd::Random(model.nv);
    a.col(i) = Eigen::VectorXd::Random(model.nv);
  }

  ModelPool pool(model,num_thread);
  rnea(num_thread,pool,q,v,a,tau);

  for(Eigen::DenseIndex i = 0; i < batch_size; ++i)
  {
    tau_ref.col(i) = rnea(model,data_ref,q.col(i),v.col(i),a.col(i));
  }

  BOOST_CHECK(tau == tau_ref);

}

BOOST_AUTO_TEST_SUITE_END()


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

#ifndef CRYPTO3_ZK_COMMITMENTS_KZG_HPP
#define CRYPTO3_ZK_COMMITMENTS_KZG_HPP

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

#include <boost/assert.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/accumulators/accumulators.hpp>

#include <nil/crypto3/math/polynomial/polynomial.hpp>
#include <nil/crypto3/algebra/type_traits.hpp>
#include <nil/crypto3/algebra/algorithms/pair.hpp>
#include <nil/crypto3/algebra/pairing/pairing_policy.hpp>

using namespace nil::crypto3::math;

#include <nil/crypto3/math/polynomial/polynomial.hpp>

namespace nil {
    namespace crypto3 {
        namespace zk {
            namespace commitments {
                template<typename CurveType>
                struct kzg {

                    typedef CurveType curve_type;
                    typedef algebra::pairing::pairing_policy<curve_type> pairing;
                    typedef typename curve_type::gt_type::value_type gt_value_type;

                    using base_field_value_type = typename curve_type::base_field_type::value_type;
                    using commitment_key_type = std::vector<typename curve_type::template g1_type<>::value_type>;
                    using verification_key_type = typename curve_type::template g2_type<>::value_type;
                    using commitment_type = typename curve_type::template g1_type<>::value_type;
                    using proof_type = commitment_type;

                    struct params_type {
                        std::size_t a;
                    };

                    static std::pair<commitment_key_type, verification_key_type> setup(const std::size_t n,
                                                                                params_type params) {

                        size_t a_scaled = params.a;
                        commitment_key_type commitment_key = {curve_type::template g1_type<>::value_type::one()};
                        verification_key_type verification_key =
                            curve_type::template g2_type<>::value_type::one() * params.a;

                        for (std::size_t i = 0; i < n; i++) {
                            commitment_key.emplace_back(a_scaled * (curve_type::template g1_type<>::value_type::one()));
                            a_scaled = a_scaled * params.a;
                        }

                        return std::make_pair(commitment_key, verification_key);
                    }

                    static commitment_type commit(const commitment_key_type &commitment_key,
                                                  const polynomial<base_field_value_type> &f) {

                        commitment_type commitment = f[0] * commitment_key[0];

                        for (std::size_t i = 0; i < f.size(); i++) {
                            commitment = commitment + commitment_key[i] * f[i];
                        }

                        return commitment;
                    }

                    static proof_type proof_eval(commitment_key_type commitment_key,
                                                 typename curve_type::base_field_type::value_type x,
                                                 typename curve_type::base_field_type::value_type y,
                                                 const polynomial<base_field_value_type> &f) {

                        const polynomial<base_field_value_type> denominator_polynom = {-x, 1};

                        const polynomial<base_field_value_type> q =
                            (f + polynomial<base_field_value_type> {-y}) / denominator_polynom;

                        proof_type p = kzg_commitment::commit(commitment_key, q);
                        return p;
                    }

                    static bool verify_eval(verification_key_type verification_key,
                                            commitment_type C_f,
                                            base_field_value_type x,
                                            base_field_value_type y,
                                            proof_type p) {

                        typename curve_type::gt_type::value_type gt1 =
                            algebra::pair<curve_type>(C_f - curve_type::template g1_type<>::value_type::one() * y,
                                                      curve_type::template g2_type<>::value_type::one());

                        typename curve_type::gt_type::value_type gt2 = algebra::pair<curve_type>(
                            p, verification_key - curve_type::template g2_type<>::value_type::one() * x);

                        return gt1 == gt2;
                    }
                };
            };    // namespace commitments
        }         // namespace zk
    }             // namespace crypto3
}    // namespace nil

#endif    // CRYPTO3_ZK_COMMITMENTS_KZG_HPP


/*-----------------------------------------------------------------------------+
Author: Joachim Faulhaber
Copyright (c) 2009-2009: Joachim Faulhaber
+------------------------------------------------------------------------------+
   Distributed under the Boost Software License, Version 1.0.
      (See accompanying file LICENCE.txt or copy at
           http://www.boost.org/LICENSE_1_0.txt)
+-----------------------------------------------------------------------------*/
#ifndef BOOST_LIBS_ICL_EXAMPLE_LARGE_BITSET__LARGE_BITSET_HPP_JOFA_091019
#define BOOST_LIBS_ICL_EXAMPLE_LARGE_BITSET__LARGE_BITSET_HPP_JOFA_091019

//[large_bitset_includes
#include <iostream>                   // to organize output
#include <limits>                     // limits and associated constants
#include <boost/operators.hpp>        // to define operators with minimal effort
#include "meta_log.hpp"               // a meta logarithm
#include "bits.hpp"                   // a minimal bitset implementation
#include <boost/icl/interval_map.hpp> // base of large bitsets

namespace mini // minimal implementations for example projects
{
//]

//[large_bitset_natural_typedefs
typedef unsigned char      nat8; // nati i: number bits
typedef unsigned short     nat16;
typedef unsigned long      nat32;
typedef unsigned long long nat64;
typedef unsigned long      nat;

typedef bits<nat8>  bits8;
typedef bits<nat16> bits16;
typedef bits<nat32> bits32;
typedef bits<nat64> bits64;
//]

//[large_bitset_class_template_header
template
<
    typename    DomainT = nat64,
    typename    BitSetT = bits64,
    ICL_COMPARE Compare = ICL_COMPARE_INSTANCE(std::less, DomainT),
    ICL_INTERVAL(ICL_COMPARE) Interval = ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, DomainT, Compare),
    ICL_ALLOC   Alloc   = std::allocator
>
class large_bitset
    : boost::equality_comparable < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>
    , boost::less_than_comparable< large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>

    , boost::addable       < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>
    , boost::orable        < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>
    , boost::subtractable  < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>
    , boost::andable       < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>
    , boost::xorable       < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>

    , boost::addable2      < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, DomainT
    , boost::orable2       < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, DomainT
    , boost::subtractable2 < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, DomainT
    , boost::andable2      < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, DomainT
    , boost::xorable2      < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, DomainT

    , boost::addable2      < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, ICL_INTERVAL_TYPE(Interval,DomainT,Compare)
    , boost::orable2       < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, ICL_INTERVAL_TYPE(Interval,DomainT,Compare)
    , boost::subtractable2 < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, ICL_INTERVAL_TYPE(Interval,DomainT,Compare)
    , boost::andable2      < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, ICL_INTERVAL_TYPE(Interval,DomainT,Compare)
    , boost::xorable2      < large_bitset<DomainT,BitSetT,Compare,Interval,Alloc>, ICL_INTERVAL_TYPE(Interval,DomainT,Compare)
      > > > > > > > > > > > > > > > > >
    //^ & - | + ^ & - | + ^ & - | + < ==
    //segment   element   container
//]
{
public:
    //[large_bitset_associated_types
    typedef boost::icl::interval_map
        <DomainT, BitSetT, boost::icl::partial_absorber,
         std::less, boost::icl::inplace_bit_add, boost::icl::inplace_bit_and> interval_bitmap_type;

    typedef DomainT                                      domain_type;
    typedef DomainT                                      element_type;
    typedef BitSetT                                      bitset_type;
    typedef typename BitSetT::word_type                  word_type;
    typedef typename interval_bitmap_type::interval_type interval_type;
    typedef typename interval_bitmap_type::value_type    value_type;
    //]
//[large_bitset_operators
public:
    bool     operator ==(const large_bitset& rhs)const { return _map == rhs._map; }
    bool     operator < (const large_bitset& rhs)const { return _map <  rhs._map; }

    large_bitset& operator +=(const large_bitset& rhs) {_map += rhs._map; return *this;}
    large_bitset& operator |=(const large_bitset& rhs) {_map |= rhs._map; return *this;}
    large_bitset& operator -=(const large_bitset& rhs) {_map -= rhs._map; return *this;}
    large_bitset& operator &=(const large_bitset& rhs) {_map &= rhs._map; return *this;}
    large_bitset& operator ^=(const large_bitset& rhs) {_map ^= rhs._map; return *this;}

    large_bitset& operator +=(const element_type& rhs) {return add(interval_type(rhs));      }
    large_bitset& operator |=(const element_type& rhs) {return add(interval_type(rhs));      }
    large_bitset& operator -=(const element_type& rhs) {return subtract(interval_type(rhs)); }
    large_bitset& operator &=(const element_type& rhs) {return intersect(interval_type(rhs));}
    large_bitset& operator ^=(const element_type& rhs) {return flip(interval_type(rhs));     }

    large_bitset& operator +=(const interval_type& rhs){return add(rhs);      }
    large_bitset& operator |=(const interval_type& rhs){return add(rhs);      }
    large_bitset& operator -=(const interval_type& rhs){return subtract(rhs); }
    large_bitset& operator &=(const interval_type& rhs){return intersect(rhs);}
    large_bitset& operator ^=(const interval_type& rhs){return flip(rhs);     }
    //]
    //[large_bitset_fundamental_functions
    large_bitset& add      (const interval_type& rhs){return segment_apply(&large_bitset::add_,      rhs);}
    large_bitset& subtract (const interval_type& rhs){return segment_apply(&large_bitset::subtract_, rhs);}
    large_bitset& intersect(const interval_type& rhs){return segment_apply(&large_bitset::intersect_,rhs);}
    large_bitset& flip     (const interval_type& rhs){return segment_apply(&large_bitset::flip_,     rhs);}
    //]

    //[large_bitset_demo_functions
    size_t interval_count()const { return boost::icl::interval_count(_map); }

    void show_segments()const
    {
        for(typename interval_bitmap_type::const_iterator it_ = _map.begin();
            it_ != _map.end(); ++it_)
        {
            interval_type   itv  = it_->first;
            bitset_type     bits = it_->second;
            std::cout << itv << "->" << bits.as_string("01") << std::endl;
        }
    }

    void show_matrix(const char off_on[2] = " 1")const
    {
        using namespace boost;
        typename interval_bitmap_type::const_iterator iter = _map.begin();
        while(iter != _map.end())
        {
            element_type fst = icl::first(iter->first), lst = icl::last(iter->first);
            for(element_type chunk = fst; chunk <= lst; chunk++)
                std::cout << iter->second.as_string(off_on) << std::endl;
            ++iter;
        }
    }
    //]

//[large_bitset_impl_constants
private:                                      // Example value
    static const word_type                    //   8-bit case
        digits  = std::numeric_limits         // --------------------------------------------------------------
                  <word_type>::digits       , //   8           Size of the associated bitsets
        divisor = digits                    , //   8           Divisor to find intervals for values
        last    = digits-1                  , //   7           Last bit (0 based)
        shift   = log2_<divisor>::value     , //   3           To express the division as bit shift
        w1      = static_cast<word_type>(1) , //               Helps to avoid static_casts for long long
        mask    = divisor - w1              , //   7=11100000  Helps to express the modulo operation as bit_and
        all     = ~static_cast<word_type>(0), // 255=11111111  Helps to express a complete associated bitset
        top     = w1 << (digits-w1)      ;    // 128=00000001  Value of the most significant bit of associated bitsets
                                              //            !> Note: Most signigicant bit on the right.
    //]
    //[large_bitset_segment_combiner
    typedef void (large_bitset::*segment_combiner)(element_type, element_type, bitset_type);
    //]

    //[large_bitset_bitset_filler
    static word_type from_lower_to(word_type bit){return bit==last ? all : (w1<<(bit+w1))-w1;}
    static word_type to_upper_from(word_type bit){return bit==last ? top : ~((w1<<bit)-w1); }
    //]

    //[large_bitset_segment_apply
    large_bitset& segment_apply(segment_combiner combine, const interval_type& operand)
    {
        using namespace boost;
        if(icl::is_empty(operand))
            return *this;
                                                            // same as
        element_type   base = icl::first(operand) >> shift, // icl::first(operand) / divisor
                       ceil = icl::last (operand) >> shift; // icl::last (operand) / divisor
        word_type base_rest = icl::first(operand) &  mask , // icl::first(operand) % divisor
                  ceil_rest = icl::last (operand) &  mask ; // icl::last (operand) % divisor

        if(base == ceil) // [first, last] are within one bitset (chunk)
            (this->*combine)(base, base+1, bitset_type(  to_upper_from(base_rest)
                                                       & from_lower_to(ceil_rest)));
        else // [first, last] spread over more than one bitset (chunk)
        {
            element_type mid_low = base_rest == 0   ? base   : base+1, // first element of mid part
                         mid_up  = ceil_rest == all ? ceil+1 : ceil  ; // last  element of mid part

            if(base_rest > 0)    // Bitset of base interval has to be filled from base_rest to last
                (this->*combine)(base, base+1, bitset_type(to_upper_from(base_rest)));
            if(ceil_rest < all)  // Bitset of ceil interval has to be filled from first to ceil_rest
                (this->*combine)(ceil, ceil+1, bitset_type(from_lower_to(ceil_rest)));
            if(mid_low < mid_up) // For the middle part all bits have to set.
                (this->*combine)(mid_low, mid_up, bitset_type(all));
        }
        return *this;
    }
    //]

    //[large_bitmap_combiners
    void       add_(DomainT lo, DomainT up, BitSetT bits){_map += value_type(interval_type::right_open(lo,up), bits);}
    void  subtract_(DomainT lo, DomainT up, BitSetT bits){_map -= value_type(interval_type::right_open(lo,up), bits);}
    void intersect_(DomainT lo, DomainT up, BitSetT bits){_map &= value_type(interval_type::right_open(lo,up), bits);}
    void      flip_(DomainT lo, DomainT up, BitSetT bits){_map ^= value_type(interval_type::right_open(lo,up), bits);}
    //]

//[large_bitmap_impl_map
private:
    interval_bitmap_type _map;
//]
};

} // mini
#endif


#pragma once

#include <Eigen/Dense>
#include <vector>

// quadrature rules
#include "quadrature/qhermite.hpp"
#include "quadrature/qmaxwell.hpp"
#include "spectral/lagrange_polynomial.hpp"

namespace boltzmann {
namespace impl {

/**
 * @brief stores integrals over Lagrange polynomials
 *        on the Hermite Quadrature nodes
 */
class outflow_helper
{
 private:
  typedef Eigen::VectorXd vec_t;

 public:
  outflow_helper(int K);

  /**
   *
   *
   * @param hw  Hermite weights
   * @param hx  Hermite nodes
   *
   * Note: both weights and nodes are wrt weight \f$ e^{-x^2} \f$
   */
  outflow_helper(const vec_t& hw, const vec_t& hx);

  /**
   * @brief returns \f$ \int_{\mathbb{R}^+} y l_i(y) e^{-y^2/2} dy\f$
   *
   * @param i the i-th lagrange polynomial
   *
   * @return
   */
  inline double get_y(unsigned int i) const
  {
    assert(i < ly_.size());
    return ly_[i];
  }

  /**
   * @brief returns \f$ \int_{\mathbb{R}} l_i(x) e^{-x^2/2} dx\f$
   *
   * @param i
   *
   * @return
   */
  inline double get_x(unsigned int i) const
  {
    assert(i < lx_.size());
    return lx_[i];
  }

  inline const vec_t& lx() const { return lx_; }

  inline const vec_t& ly() const { return ly_; }

  template <typename DERIVED>
  inline double compute(const Eigen::DenseBase<DERIVED>& src) const;

 private:
  vec_t ly_;
  vec_t lx_;
};

template <typename DERIVED>
inline double
outflow_helper::compute(const Eigen::DenseBase<DERIVED>& src) const
{
  assert(src.rows() == ly_.size());
  assert(src.cols() == lx_.size());

  int K = ly_.size();

  // compute outflow
  double rho_p = 0;
  for (int i = 0; i < K; ++i) {
    for (int j = 0; j < K; ++j) {
      rho_p += src(i, j) * get_x(j) * get_y(i);
    }
  }
  return rho_p;
}

}  // end namespace impl
}  // end namespace boltzmann


#include "SLIC.hpp"

#include <iostream>
#include <string>
#include <filesystem>
#include <chrono>
#include <cmath>
#include <boost/filesystem/convenience.hpp>

Slic::Slic(std::string filename){
  if_path = filename;
  std::cout << "Loading " << filename << " pixel data..." << std::endl;
  if(!image.loadFromFile(filename)){
    std::cout << "Problem loading filename: " << filename << std::endl;
    ready = false;
  }
  greyscale = false;
  ready = true;
  height = image.getSize().y;
  width = image.getSize().x;
  total_pixels = height * width;
  num_cuts = 0;
  std::cout << "Loaded " << width << "x" << height << " file " << filename << std::endl
    << "Total pixels: " << total_pixels << std::endl;
}

Slic::~Slic(){

}

//O(1) constant
double Slic::getColorDistance(HSV c1, HSV c2){
  //Remember, these are coming in as
  // Hue 0-360
  // Saturation 0-100
  // Value 0 - 100
  double h1 = c1.hue * deg_to_rad;
  double h2 = c2.hue * deg_to_rad;
  double s1 = c1.saturation/100.0;
  double s2 = c2.saturation/100.0;
  double v1 = c1.value / 100.0;
  double v2 = c2.value / 100.0;

  //We're going to project the color value into the HSV color space and then measure the distance.
  double p1 = std::pow(std::sin(h1)*s1*v1 - std::sin(h2)*s2*v2,2);
  double p2 = std::pow(std::cos(h1)*s1*v1 - std::cos(h2)*s2*v2,2);
  double p3 = std::pow(v1 - v2,2);
  double dist2 = p1 + p2 + p3; //Our distance squared.
  return sqrt(dist2);
}

//O(1) constant
HSV Slic::rgb2hsv(RGBA rgb){
	float MAX = std::max(std::max(rgb.r,rgb.g), rgb.b);
	float MIN = std::min(std::min(rgb.r,rgb.g), rgb.b);
	float hue=0;

  float eps = 0.00001;
	if(std::abs(MAX-MIN)<eps){
		hue = 0;
  }
	else if(std::abs(MAX-rgb.r)<eps){
		hue = 60*((rgb.g - rgb.b)/(MAX-MIN));
  }
	else if(std::abs(MAX-rgb.g)<eps){
		hue = 60*(2 + (rgb.b - rgb.r)/(MAX-MIN));
  }
	else if(std::abs(MAX-rgb.b)<eps){
		hue = 60*(4 + (rgb.r - rgb.g)/(MAX-MIN));
  }
	if(hue < 0)
		hue+=360;
	int saturation = 0;
	if(MAX==0)
		saturation = 0;
	else
		saturation = (MAX-MIN)/MAX * 100;
	int value = (MAX + MIN)/2.0 * 100;
	return HSV{hue,saturation,value};
}

// O(n) operation. Passes each pixel once.
void Slic::convertToGreyscale(){
  if(!ready)
    return;
  for(unsigned int i=0; i<height; i++){
    for(unsigned int j=0; j<width; j++){
      sf::Color pixel_color = image.getPixel(j,i);
      float gs = (pixel_color.r + pixel_color.g + pixel_color.b)/3; // Averages the pixel color in rgb. Which converts it to grey.
      image.setPixel(j,i, sf::Color(gs,gs,gs,255));
    }
  }
  greyscale = true;
}

void Slic::loadToGraph(){
  //Pixels are stored in a c style array in RGBA pixel format made of 8 bit integers.
  const sf::Uint8 *pixel_data = image.getPixelsPtr();
  for(unsigned int i=0; i<height; i++){
    for(unsigned int j=0; j<width; j++){
      //We're i units down height wise, and for each we have passed the width once. Then we're j units over on the current line.
      // 0 0 0 1
      // 1 0 2 0
      // 2 0 X 0
      // X is at spot (2,2), with a width of 4, and j of 2, we would have index = (2*4)+2 = 10. Which is correct.
      unsigned int index = (i*width) + j;
      //Extract our colors from the index
      sf::Uint8 r = pixel_data[4*index];
      sf::Uint8 g = pixel_data[4*index+1];
      sf::Uint8 b = pixel_data[4*index+2];
      sf::Uint8 a = pixel_data[4*index+3];
      //Convert to HSV colorspace.
      RGBA rgba = { int(r)/255.0, int(g)/255.0, int(b)/255.0, int(a)/255.0};
      HSV hsv = rgb2hsv(rgba);
      boost::add_vertex(vertex_data{rgba, hsv, std::vector<int>()}, graph);
    }
  }
  graph_loaded = true;
}
#include <cstdlib>
#include <ctime>
sf::Color getComponentColor(int component_id){
	int some_prime = 31907;
	srand(component_id * some_prime);
	int r = rand() % 256;
	int g = rand() % 256;
	int b = rand() % 256;
	return sf::Color(r,g,b,255);
}

struct rgb{
  double r;
  double g;
  double b;
};
//I legit yoinked this one from online.
RGBA hsv2rgb(HSV in)
{
    double      hh, p, q, t, ff;
    long        i;
    RGBA         out;
    in.saturation /= 100.0;
    in.value /= 100.0;
    if(in.saturation <= 0.0) {       // < is bogus, just shuts up warnings
        out.r = in.value;
        out.g = in.value;
        out.b = in.value;
        return out;
    }
    hh = in.hue;
    if(hh >= 360.0) hh = 0.0;
    hh /= 60.0;
    i = (long)hh;
    ff = hh - i;
    p = in.value * (1.0 - in.saturation);
    q = in.value * (1.0 - (in.saturation * ff));
    t = in.value * (1.0 - (in.saturation * (1.0 - ff)));

    switch(i) {
    case 0:
        out.r = in.value;
        out.g = t;
        out.b = p;
        break;
    case 1:
        out.r = q;
        out.g = in.value;
        out.b = p;
        break;
    case 2:
        out.r = p;
        out.g = in.value;
        out.b = t;
        break;

    case 3:
        out.r = p;
        out.g = q;
        out.b = in.value;
        break;
    case 4:
        out.r = t;
        out.g = p;
        out.b = in.value;
        break;
    case 5:
    default:
        out.r = in.value;
        out.g = p;
        out.b = q;
        break;
    }
    out.a = 255;
    return out;
}

void Slic::writeToDisk(std::string out_dir){
  if(!ready || !graph_loaded){
    std::cout << "Shit isn't ready:" << std::endl;
    return;
  }
  //Create a new pixel array.
	sf::Uint8 out_pixels[total_pixels*4];
  // const sf::Uint8 *pixel_data = image.getPixelsPtr();
	//Filling our pixel array with new colors based on our connected components vector.
	auto vp = boost::vertices(graph);
  std::cout << "Writing to disk" << std::endl;
	for(auto iter = vp.first; iter!=vp.second; iter++){
		unsigned int index = *iter;
    // std::cout << graph[index].cluster_ids[0] << std::endl;
    sf::Color col = getComponentColor(graph[index].cluster_ids[0]);
    // std::cout << graph[index].cluster_ids[0] << col.r << " " << col.g << std::endl;

    out_pixels[4*index] = col.r;
		out_pixels[4*index+1] = col.g;
		out_pixels[4*index+2] = col.b;
		out_pixels[4*index+3] = 255;
		// out_pixels[4*index] = graph[index].rgba.r;
		// out_pixels[4*index+1] = graph[index].rgba.g;
		// out_pixels[4*index+2] = graph[index].rgba.b;
		// out_pixels[4*index+3] = graph[index].rgba.a;
    // HSV hs = clusters[graph[index].cluster_ids[0]].color;
    // RGBA col = hsv2rgb(hs);
    // out_pixels[4*index] = col.r*255;
    // out_pixels[4*index+1] = col.g*255;
    // out_pixels[4*index+2] = col.b*255;
    // out_pixels[4*index+3] = 255;
	}

  //Strip path from input
  std::filesystem::path input_path(if_path);
  std::string no_path = input_path.filename();
  //Strip extension from pathless input
  std::filesystem::path pathless_path(no_path);
  std::string base_path = pathless_path.stem();
  std::string extension = "";
  if(pathless_path.has_extension())
    extension += pathless_path.extension().string();

  //Create our output filename
  base_path += "_output";
  if(greyscale)
    base_path += "_greyscale";
  if(extension.size()>0)
    base_path += extension;
  std::string out_path = out_dir + base_path;

  //Create our image to write and write it.
  sf::Image out_image;
  out_image.create(width, height, out_pixels);
  out_image.saveToFile(out_path);
}

void Slic::cleanEdges(){
  auto vp = boost::vertices(graph);
  //For every vertex/pixel.
  for(auto iter = vp.first; iter!=vp.second; iter++){
    //Check it against all associated cluster ids.
    edge_data best_fit = { -1 , -1 };
    if(graph[*iter].cluster_ids.size()==0)
      continue;
    for(int id : graph[*iter].cluster_ids){
      //It might be less costly to just remove each edge as we check it then add the last one. The other option is to loop twice.
      //Convert cluster coordinates to an indice
      int ci = clusters[id].cpos.y * width + clusters[id].cpos.x;

      auto e = boost::edge(*iter, ci, graph).first;
      //Find the best fitting edge and remove all of the rest.
      if(best_fit.distance == -1){
        best_fit = graph[e];
        boost::remove_edge(e,graph);
      }
      else if(best_fit.distance > graph[e].distance){
        best_fit = graph[e];
        boost::remove_edge(e,graph);
      }
    }
    graph[*iter].cluster_ids.clear();
    //Reinsert the best edge. wasteful but fuck it.
    int ci = clusters[best_fit.cluster_id].cpos.y * width + clusters[best_fit.cluster_id].cpos.x;
    boost::add_edge(*iter, ci, best_fit, graph);
    graph[*iter].cluster_ids.push_back(best_fit.cluster_id);
  }
}

//O(n) - We hit every pixel or vertex in this algorithm.
void Slic::updateClusterAverages(){
  // 1. Generate connected component vector to find which
  // 2.
  if(!graph_loaded)
    return;
  auto vp = boost::vertices(graph);
  //Containers to store shit in
  std::vector<HSV> colors(clusters.size(),{0,0,0});
  std::vector<int> color_count(clusters.size(),0);
  //Loop through and add up all of the color values for each cluster.
  for(auto iter = vp.first; iter!=vp.second; iter++){
    auto v = graph[*iter];
    if(v.cluster_ids.size()==0){
      return;
    }
    colors[v.cluster_ids[0]].hue+= v.hsv.hue;
    colors[v.cluster_ids[0]].saturation += v.hsv.saturation;
    colors[v.cluster_ids[0]].value += v.hsv.value;
    color_count[v.cluster_ids[0]]++;
  }
  //since we used the cluster id as the index, we can loop through just once to average it all and set it.
  for(unsigned int i=0; i<clusters.size(); i++){
    if(color_count[i]!=0){
      clusters[i].color.hue = colors[i].hue / color_count[i];
      clusters[i].color.saturation = colors[i].saturation / color_count[i];
      clusters[i].color.value = colors[i].value / color_count[i];
    }
  }
}

bool Slic::inBounds(unsigned int x, unsigned int y){
  //Can't be less than 0 since unsigned.
  //If our width is 10, then index 9 is on the edge.
//  std::cout << "Checking if : " << x << " " << y << " - " << width << " " << height << std::endl;
  if(x >= width || y >= height)
    return false;
  return true;
}
bool Slic::isEdge(unsigned int x, unsigned int y){
  if(x == width-1 || y == height-1)
    return true;
  if(x == 0 || y == 0)
    return true;
  return false;
}
void Slic::generateSuperpixels(unsigned int K, unsigned int error){
  this->K = K;
  unsigned int S = std::sqrt(total_pixels / K);
  std::cout << "S Value: " << S << " " << width << " " << height << std::endl;
  //Generate cluster centers.
  for(unsigned int i=0; i*S < height; i++){
    for(unsigned int j=0; j*S < width; j++){
      int x = j*S; // We're just j*S units over.
      int y = i*S; //We're i*S units down
      int indice = y*width + x;
      if(inBounds(x,y)){
        //Get cluster center color.
        HSV hsv = graph[indice].hsv;
        clusters.push_back(Cluster{hsv,vec2<int>{x,y}, clusters.size()});
        std::cout << "Cluster center(" << clusters.size() << "): " << x << " " << y << " | Color: " << hsv.hue << " " << hsv.saturation << " " << hsv.value <<  std::endl;
      }
    }
  }
  //todo - make these slightly more accurate and move off of edges.

  //So every pass we're going to do the following
  //Check every pixel around the cluster centers in a radius of 2S.
  //Draw edges between detected pixels and the cluster centers.
  //Clean edges
  //Calculate cluster color

  while(clusterPass(S*2,error)){
    /*
    How's it going today?
    For me...I just wrote almost 10000 lines of code for a graphics project that probably won't get a B and now I'm cramming this on may 12th and it's 9pm.
    Also it's my birthday yesterday and I think I spent it on caffeine and programming. Honestly not too bad. I got to learn a lot about opengl.
    I just started getting into geometry shaders yesterday and water stuff too. My water is super ghetto, I have like 3 implementations lmao. the first one was a
    mesh that I pulled the vertices on a sinfunction using elapsed time to simulate waves. I don't have much faith in this new algorithm, but I did do some research.
    Hopefully it's sufficient. I kinda wish I found a way to do graph cuts using boost graph library. I think if I had like 2 more days I could do this projecvt so much better.
    I'd probably do my own graph library and probably auto remove edges lmao.
    */
  }

}

bool Slic::clusterPass(int radius, unsigned int error){
  //For each cluster
  for(Cluster cluster : clusters){
    //Check every pixel in a square radius around it.
    for(int y=-radius; y<=radius; y++){
      for(int x=-radius; x<=radius; x++){
        int xpos = cluster.cpos.x + x;
        int ypos = cluster.cpos.y + y;
        if(inBounds(xpos,ypos)){
          int indice1 = ypos*width + xpos;
          int indice2 = cluster.cpos.y * width + cluster.cpos.x;
          //Add edge
          boost::add_edge(indice1,indice2, { getColorDistance(graph[indice1].hsv, graph[indice2].hsv), cluster.id},graph);
          //Update our node cluster id list.
          graph[indice1].cluster_ids.push_back(cluster.id);
        }
      }
    }
  }
  cleanEdges();
  updateClusterAverages();
  return updateClusterPositions(error);
}

//Updates cluster positions and calculates the error threshhold for stopping our loop.
bool Slic::updateClusterPositions(unsigned int error){
  if(!graph_loaded)
    return false;
  auto vp = boost::vertices(graph);
  //Containers to store shit in
  std::vector<vec2<int>> pos(clusters.size(),{0,0});
  std::vector<int> count(clusters.size(),0);
  //Loop through all of the vertices
  for(auto iter = vp.first; iter!=vp.second; iter++){
    auto v = graph[*iter];
    pos[v.cluster_ids[0]].x += clusters[v.cluster_ids[0]].cpos.x;
    pos[v.cluster_ids[0]].y += clusters[v.cluster_ids[0]].cpos.y;
    count[v.cluster_ids[0]]++;
  }
  for(unsigned int i = 0; i<count.size(); i++){
    if(count[i]!=0){
      //Compute error vector.
      vec2<int> npos;
      npos.x = pos[i].x / count[i];
      npos.y = pos[i].y / count[i];
      double l1 = std::sqrt(std::pow((npos.x),2) + std::pow(npos.y,2) + pow(clusters[i].color.hue,2) + pow(clusters[i].color.saturation,2) + pow(clusters[i].color.value,2));
      double l2 = std::sqrt(std::pow((clusters[i].cpos.x),2) + std::pow(clusters[i].cpos.y,2)+ pow(clusters[i].color.hue,2) + pow(clusters[i].color.saturation,2) + pow(clusters[i].color.value,2));

       std::cout << "v1: " << npos.x << " " << npos.y << " v2 " << clusters[i].cpos.x << " " << clusters[i].cpos.y << std::endl;
       if((l1-l2) < error && (npos.x !=0 && npos.y!=0)){
         std::cout << "Error distance reached: " << l1-l2 << std::endl;
         return false;
       }
      clusters[i].cpos = npos;
    }
    else{
      std::cout << "Sir we've encountered a critical error. DIV/0. Somehow there's a pixel with no shit associated." << std::endl;
    }
  }
  return true;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <fstream>
#include <Eigen/Eigenvalues>
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <math.h>

#include "information.h"
#include "functionn.h"
#include "read.h"

using namespace std;
using Eigen::MatrixXd;
using Eigen::EigenSolver;
using Eigen::VectorXcd;
using Eigen::MatrixXcd;

string input,indicator1,indicator2 ;
string dataset = "ATT/";
string dash = "_";
string file_type = ".png";

double all_image_matrix[number_of_dataset][figure_height*figure_width] = { 0 };             //Create a vector*vector to store all image
vector<double> average_face;
vector<double> each_eigenvector(figure_height*figure_width,0);
vector<vector<double>> eigenvectors(number_of_eigenvectors,each_eigenvector);
double class_average_face[number_of_face_class][figure_height*figure_width] = { 0 };
double class_w[number_of_face_class][number_of_eigenvectors] = { 0 };
int test_index;
int main() {

	image_content image;                                                   //Create a class call "image_content" to store the information of image
	double each[figure_height*figure_width] = {0};                       //Create a vector to store one image

	//Data all_data;

	//Read and store the data from figure and store it into to image_matrix
	for (int i = 0, q = 1, w = 1; i < number_of_dataset && q < 41 && w < 11; i++) {
		indicator1 = to_string(q);
		indicator2 = to_string(w);
		input = dataset + indicator1 + dash + indicator2 + file_type;      //Read the file by substituting the character.
		image = read::figure(input);                                       //Via opencv to read the image and acquire the data in class "image_content" form.
		for (int j = 0; j < figure_height*figure_width; j++) {
			each[j] = (image.content[j]);                                  // Assign the data from class "image_content" to vector variable "each".
		}

		//This part is saving the image to a txt, in order to double check the matrix of input figure is correctly save into class "image_content" or not.
		//We save all data into a txt, then display it to check whether it is the original image or not.
		/*
		ofstream file;
		for (int i=0; i < image.height*image.width; i++) {

		file.open("test1.txt",fstream::app);
		file << image.content[i];
		file << "\n";
		file.close();
		cout << i << endl;
		cout << "\n";
		}
		cout << endl;
		*/

		//Store information of each figure to the image_matrix
		for (int k = 0; k < figure_height*figure_width; k++) {
			all_image_matrix[i][k] = each[k];
		}

		//This is just for the pointer.
		if (w < 11) { w++; }
		if (w == 11) { w = 1; q++; }
	}

	average_face = functionn::averagee(all_image_matrix);    //Feed the image_matrix to the function and acquire the average face.

	functionn::save_one_face(average_face);                     //This part is saving the average face to a txt, in order to double check the average face is normal or not.

	//********
	vector<vector<double>> A_matrix = functionn::calculate_A(all_image_matrix, average_face);
	//We got A!  (A = A_matrix)
	//********

	///////////////////////////////////////////////////////////////////////////////
	// Let's calculate eigenvectors!

	//We have two ways to calculate eigenvectors, first is via Matlab, the other is eigen.

	//This part is reading the eigenvector and eigenvalue which are calculated from matlab.
	//Read 6 eigenvalues and its relevant eigenvetors.
	string file_name = "For_matlab/eigenvector";
	string file_type = ".txt";
	ifstream eigenvector_file;
	for (int i = 1; i <= number_of_eigenvectors; i++) {
		int j = 0;
		cout << file_name + to_string(i) + file_type << endl;
		eigenvector_file.open(file_name + to_string(i) + file_type, ios::in);
		string line;
		double tem;
		while (getline(eigenvector_file, line)) {
			tem = stod(line);
			eigenvectors[i - 1][j] = tem;
			j++;
		}
		eigenvector_file.close();
	}

	//********
	//This is the eigen way
	//vector<vector<complex<double>>> eigenvectors = functionn::calculate_eigenvalues_and_eigenvectors(A_matrix);
	//********

	//Now we have the eigenvector(eigenface)!
	//Let's display our eigenface !

	//////////////////////////////////////////////////////////////////////////////////
	/*
	//This part is reflecting the pixel value to (0,1), then reflect it to (0,255)

	cout << eigenvectors[0][100] << endl;
	double maximum = 0;
	double minimum = 1;
	for (int count = 0; count < figure_height*figure_width; count++) {
		maximum = max(maximum, eigenvectors[display_index][count]);
		minimum = min(minimum, eigenvectors[display_index][count]);
	}

	for (int count = 0; count < figure_height*figure_width; count++) {
		eigenvectors[display_index][count] = (eigenvectors[display_index][count] - minimum) / (maximum - minimum) * 255;
	}

	//Finish reflecting to (0,255)!
	//////////////////////////////////////////////////////////////////////////////////

	//Assign the value in eigenface to file m (opencv Mat form) in order to display.
	if (eigenvectors[display_index].size() == figure_height*figure_width) // check that the rows and cols match the size of your vector
	{
		cv::Mat m(figure_height, figure_width, CV_8U); // initialize matrix of uchar of 1-channel where you will store vec data

		int p3 = 0;
		for (int p1 = 0; p1 < figure_height; p1++) {
			for (int p2 = 0; p2 < figure_width; p2++) {
				m.at<uchar>(p1, p2) = eigenvectors[display_index].at(p3);
				p3++;
			}
		}

		cv::imwrite("Eigenface.jpg", m);               //Save the eigenface!
	}

	*/
	//Now we have the essiential item to recognize face!
	cout << "Please tell me which image do you want to test? (0~49)" << endl;
	cin >> test_index;
	cout << endl;
	class_information all;
	//First calculate the aveverge face of each class
	all.calculate_all_average_face();

	//Let's calculate each omega of all classes
	all.calculate_all_w();

	//Now we got 40 omega(each omega indicates the weights of each class and has 6 dimensions(number_of_eigenvectors))
	//Definition of Omega refers to equation(8) in "Eigenfaces for Recognition" 1991.

	//Let's classify our image from class A, B and C!
	//Use equation(8) in "Eigenfaces for Recognition" 1991.

	classify result;

	result.calculate_w(all_image_matrix[test_index]);
	result.criteria_each();                          //Calculate the Euclidian distance
	result.determine_result();

	int ans;
	if (test_index < 10) {
		ans = 0;
	}
	else if (test_index < 20) {
		ans = 1;
	}
	else if (test_index < 30) {
		ans = 2;
	}
	else if (test_index < 40) {
		ans = 3;
	}
	else if (test_index < 50) {
		ans = 4;
	}
	cout << "And the ground truth is " << ans << " !" << endl;

	cout << endl;
	system("pause");
}


#include <iostream>
#include <boost/array.hpp>
//#include <libs/random/example/poisson_speed.hpp>
//#include <libs/random/example/poisson_convergence.hpp>
#include <boost/random/poisson_ext/devroye/q_function/cross_check.hpp>
#include <boost/random/poisson_ext/devroye/q_function/self_checking.hpp>
#include <boost/random/poisson_ext/devroye/crtp/crtp.hpp>

//#include <boost/random/poisson_ext/devroye/detail/test_convergence.hpp>

	std::string say_int(int){ return "int"; }
	std::string say_int(long int){ return "long int"; }
	std::string say_int(...){ return "unknown"; }

int main(){

	// Also see sandbox/statistics/distribution_toolkit
	typedef std::string str_;
	typedef long int int_; // either of int or long int (important for high mean)

    std::cout << "result_type = " << say_int(int_()) << std::endl;

    using namespace boost::random::poisson::devroye;

     //boost::random::poisson::devroye::q::cross_check<double,int_>(4,1,10,0.001);

     typedef boost::numeric::converter<double,int_> conv_;
     typedef boost::math::policies::policy<> pol_;
     typedef q::self_checking<q::using_sum> self_;

     boost::random::poisson::devroye::q::fun<double,int_>(200,1000,pol_(),conv_(),self_());

    // mean *= factor1 at each of n1 iterations
/*
	{
    	int mean = 1;
    	const int n1 = 7;
    	const int factor1 = 4;

    	example_poisson_speed<int_>(
        	std::cout,
        	10 * 1000, 	// sample size
        	n1,
        	mean,
        	factor1
    	);
    }
	{
    	int mean = 1;
		// sample_sz *= factor2 at each of n2 iterations
    	int sample_sz = 1;
    	const int n1 = 7;
    	const int factor1 = 10;
		const int n2 = 5;
		const int factor2 = 100;

		std::cout << "poisson convergence{ " << std::endl;
    	std::cout << "(sample size,statistic) :" << std::endl;
		for(int i = 0; i<n1; i++){
    		example_poisson_convergence<int_>(
        		std::cout,
        		mean,
        		n2,
        		sample_sz,
        		factor2
    		);
        	mean *= factor1;
    	}
		std::cout << "} " << std::endl;
	}
*/
    return 0;
}