#include <boost/program_options.hpp>
#include <thread>
#include <chrono>

#include "EncryptedClient.hpp"
#include "ZkArgument.hpp"
#include "SecretSharingNTT.hpp"

#include "Ligero.hpp"

#include "Hash.hpp"
#include "Common.hpp"

#define NDEBUG

namespace po = boost::program_options;

using namespace ligero;
using namespace ligero::lattice;
using namespace std::chrono_literals;

// Parameters RSA Ceremony
// ===========================

constexpr auto degree = 1 << 16;
constexpr auto p = 9;
constexpr auto q = 21;
constexpr auto sigma = 8;
constexpr auto lambda = 128;
constexpr auto tau_limit_bit = 175;
constexpr auto tau = 1000;
constexpr auto numCandidates = 2048;

// throughput parties
constexpr auto wait_timeout = 1200 * 1000; /* wait 20 min when start */
constexpr auto timeout = 25 * 1000; /* a little longer than test */
constexpr auto data_size = 32 * 1024; /* 32 KB */
constexpr auto nb_max_send = 1024;

// general timeout
constexpr auto receive_timeout = 15min;

// Parameters Zero-Knowledge
// ============================

// Settings Zero-Knowledge
RegularInteger p_zk(10514644122014433281ULL);
typedef Fpp_Fixed<p_zk> FieldT;

zksnark::InterleavedRSCode irs;                     // Reed-Solomon Interleaved Code
ligero::MTParameters<FieldT> mtParams;              // Merkle Tree Parameters
constexpr size_t l = 4096;                                // Bloc size
constexpr size_t k = 8192;                                // Degree
constexpr size_t n = 16384;                               // # of Shares

Statements statement = Statements::RSACeremony;

constexpr size_t t = 256;                                 // Columns to Open Up (By default half the columns)
constexpr auto ptNumberEvaluation = 3;

// Stitching Proofs
constexpr int nbIterations     = 2;
constexpr int nbVarsStitched   = 4;
constexpr int nbBlocksPerVar   = degree/l;

expected<Unit> participateHelper(ZeroMQClientTransport& transport, SocketId socketId, std::string localIpAddr, bool passive) {

    auto client = new EncryptedClient<FieldT, uint64_t, degree, p, q>(socketId);
    expected<Unit> result = Unit{};

    if ((!passive)&&(statement == Statements::RSACeremony)) {
        Statements localStatement = statement;

        // Zero-Knowledge Argument

        // Setting Protocol Parameters
        // ===========================

        // Reed-Solomon Interleaved Code
        zksnark::InterleavedRSCode irs;

        irs.k       = k;            // Degree of the Polynomial
        irs.n       = n;            // Number of Shares

        // Merkle Tree Parameters
        ligero::MTParameters<FieldT> mtParams;

        mtParams.digestLength       = 32;
        mtParams.zkByteSize         = 8;
        mtParams.hashInnerNodeF     = hash::blake2bTwoToOneHash;
        mtParams.hashLeafContentF   = hash::blake2bFieldElementHash<FieldT>;
        mtParams.hashZKRandomnessF  = hash::blake2bZKElementHash;
        mtParams.leavesNumber       = irs.n;

        // Fiat-Shamir Seed Generators
        const hash::HashIntegerSeedGeneratorF<FieldT>& fieldGenerator   = hash::blake2bIntegerSeedGenerator<FieldT>;
        const hash::HashStringSeedGeneratorF& stringGenerator           = hash::blake2bStringHash;

        PublicData pdata;
        SigmaProtocolPublicData spdata;
        SecretData sdata;

        // No Fiat-Shamir in Early Witness
        std::string hashedPublicData("");

        // core
        pdata.degree            = degree;
        pdata.p                 = p;
        pdata.q                 = q;
        pdata.sigma             = sigma;
        pdata.lambda            = lambda;
        pdata.tau_limit_bit     = tau_limit_bit;
        pdata.tau               = tau;

        zksnark::Prover<FieldT> prover(localStatement, irs, t, l, fieldGenerator, stringGenerator, mtParams, pdata, spdata, sdata, permut<k>::compute, permut<n>::compute, transport, hashedPublicData);

        result = client->start(transport,sigma, lambda, localIpAddr, &prover);
    } else {
        result = client->start(transport, sigma, lambda, localIpAddr);
    }

    if (hasError(result)) {
        LOG(INFO) << "Party failed with error message: " << showError(getError(result));
        exit(EXIT_FAILURE);
    }

    if (passive) {
        delete client;
        return Unit{};
    }
    else {
        LOG(INFO) << "Generating Zero-Knowledge Argument.";
        transport.myTimers.begin(1,"Active Security", 1);
        // Zero-Knowledge Argument

        // Setting Protocol Parameters
        // ===========================

        // Reed-Solomon Interleaved Code
        zksnark::InterleavedRSCode irs;

        irs.k       = k;            // Degree of the Polynomial
        irs.n       = n;            // Number of Shares

        // Merkle Tree Parameters
        ligero::MTParameters<FieldT> mtParams;

        mtParams.digestLength       = 32;
        mtParams.zkByteSize         = 8;
        mtParams.hashInnerNodeF     = hash::blake2bTwoToOneHash;
        mtParams.hashLeafContentF   = hash::blake2bFieldElementHash<FieldT>;
        mtParams.hashZKRandomnessF  = hash::blake2bZKElementHash;
        mtParams.leavesNumber       = irs.n;

        // Fiat-Shamir Seed Generators
        const hash::HashIntegerSeedGeneratorF<FieldT>& fieldGenerator   = hash::blake2bIntegerSeedGenerator<FieldT>;
        const hash::HashStringSeedGeneratorF& stringGenerator           = hash::blake2bStringHash;

        PublicData                  pdata;
        SigmaProtocolPublicData     spdata;
        SecretData                  sdata;

        client->gatherData(pdata, spdata, sdata);
        transport.send(MessageType::GATHER_SIGMA_DATA, spdata);

        // Set all parameters for active and passive protocols

        delete client;

        // core
        pdata.degree            = degree;
        pdata.p                 = p;
        pdata.q                 = q;
        pdata.sigma             = sigma;
        pdata.lambda            = lambda;
        pdata.tau_limit_bit     = tau_limit_bit;
        pdata.tau               = tau;

        // Hashing Public Data
        pdata.modulusIdx = 0;
        pdata.roots.clear();
        pdata.ptNumberEvaluation = ptNumberEvaluation;

        ligero::dumpPublicData(pdata);
        ligero::dumpSigmaProtocolPublicData(spdata);

        std::string hashedPublicData = hash::hashPublicData(stringGenerator, pdata, spdata);

        // Primitive Roots of Unity for All Moduli
        nfl::poly_p<uint64_t, degree, q> roots({0});
        for (size_t idx = 0; idx < q; idx++) {roots(idx,1) = 1ull;}
        roots.ntt_pow_phi();

        LOG(INFO) << "Generating Zero-Knowledge Argument.";

        // Compute Stitching
        // Variables we store across proofs
        mpz_class alpha = math::generateRandomValue(mpz_class(std::random_device()()), 210);
        uint64_t W1 = ligero::math::scaleToPrime(math::generateRandomValue(mpz_class(std::random_device()()), 62).get_ui(),0);
        uint64_t W2 = ligero::math::scaleToPrime(math::generateRandomValue(mpz_class(std::random_device()()), 62).get_ui(),0);
        std::vector<uint64_t> rs(4 * degree);

        // Preliminary checks
        {
            // Compute Stitching
            std::vector<mpz_class> mods, alpha_CRT;
            for (size_t i =1; i < q; i++) {mods.emplace_back(params<uint64_t>::P[i]);}

            // CRT deconstruction
            alpha_CRT = math::crt_deconstruct(alpha*mpz_class(params<uint64_t>::P[0]), mods);
            LOG(INFO) << "CRT 1:" << alpha_CRT[0];
            LOG(INFO) << "CRT 2:" << alpha_CRT[1];

            // CRT reconstruction
            std::vector<mpz_class> coefs;
            mpz_class reconstructed_alpha = math::crt_reconstruct(alpha_CRT, coefs, mods);

            assert(math::mod(reconstructed_alpha - alpha*mpz_class(params<uint64_t>::P[0]), mpz_class(params<uint64_t>::P[0])) == mpz_class(0));
            LOG(INFO) << math::mod(reconstructed_alpha - alpha*mpz_class(params<uint64_t>::P[0]), mpz_class(params<uint64_t>::P[0]));
            LOG(INFO) << "CRT Check Successful";
        }

        // Dimensioning ai scalars
        sdata.ai.resize(nbIterations);
        for (size_t iter = 0; iter < nbIterations; iter++) {
            sdata.ai[iter].resize(nbVarsStitched);
            for (size_t var = 0; var < nbVarsStitched; var++) {
                sdata.ai[iter][var].resize(nbBlocksPerVar);
                for (size_t block = 0; block < nbBlocksPerVar; block++) {
                    sdata.ai[iter][var][block].resize(l);
                }
            }
        }

        for (pdata.modulusIdx = 0; pdata.modulusIdx < q; pdata.modulusIdx++) {
            Statements localStatement = statement;
            LOG(INFO) << "Generating proof for modulus idx:" << pdata.modulusIdx;

            // Roots of Unity
            pdata.roots.assign(roots.poly_obj().data()+pdata.modulusIdx*(size_t)roots.degree,roots.poly_obj().data()+(pdata.modulusIdx+1)*(size_t)roots.degree);

            // Zero-Knowledge
            p_zk = nfl::params<uint64_t>::P[pdata.modulusIdx];
            FieldT::modulusIdx_ = pdata.modulusIdx;
            FieldT::preprocessing(log2(n) + 1);

            // Cross-Moduli Integrity
            sdata.alpha = math::mod(alpha, mpz_class(p_zk)).get_ui();
            sdata.W1 = math::mod(W1, mpz_class(p_zk)).get_ui();
            sdata.W2 = math::mod(W2, mpz_class(p_zk)).get_ui();

            // For portions 7 to 12, only run the first 9 moduli
            if ((statement == Statements::RSACeremony)&&(pdata.modulusIdx>8)) localStatement = Statements::RSACeremony_Rounds3to6;

                zksnark::Prover<FieldT> prover(localStatement, irs, t, l, fieldGenerator, stringGenerator, mtParams, pdata, spdata, sdata, permut<k>::compute, permut<n>::compute, transport, hashedPublicData);
                prover.produceArgumentOfKnowledge(1, false);
            }

        LOG(INFO) << "Waiting for possible restart";
        auto command = transport.awaitReply();

        if (!hasError(command) && (getResult(command) == MessageType::END)) {
            transport.myTimers.end(2,"1.b. Overall speed", 1, true);
            transport.myTimers.end(1,"Active Security", 1, true);
            return Unit{};
        }
        else if (hasError(command) && (getError(command) == Error::RESTART)) {
            LOG(INFO) << "Restart protocol";
            transport.myTimers.reset();
            return participateHelper(transport, socketId, localIpAddr, passive);
        }
        else {
            LOG(INFO) << "Error happen, quit";
            exit(EXIT_FAILURE);
        }
    }
}

//==============================================================================
/** A small helper function for wrapping the construction of a client and
 *  contributing to the computation.
 *
 *  This is primarily to ensure the socket construction happens on the same thread
 *  as the socket usage.
 */
expected<Unit> participate (std::string ipAddr, std::string localIpAddr, int numBits, int numCandidates, bool passive) {
    try {

        // RSA Ceremony
        SocketId socketId = boost::uuids::random_generator()();
        ZeroMQClientTransport transport(std::string("tcp://") + ipAddr + std::string(":5555"), socketId, receive_timeout);

        auto proceed = transport.joinThroughputTest(wait_timeout, timeout, data_size, nb_max_send);

        if (hasError(proceed)) {
            LOG(INFO) << "Kicked out due to poor network connection";
            LOG(INFO) << "Error message is: " << showError(getError(proceed));
            return Error::KILLED_BY_COORDINATOR;
        }

        participateHelper(transport, socketId, localIpAddr, passive);
    }
    catch (zmq::error_t& e) {
        LOG(ERROR) << "Caught an error trying to participate... " << e.what();
    }
    return Unit{};
}

//==============================================================================
int main(int argc, char** argv)
{
    std::string ipAddr("127.0.0.1");
    std::string localIpAddr("");
    int bitsize        = 100;
    int numCandidates  = 2048;

    bool passive = false;

    // Configuring Easylogging
    if (doesFileExist("logging")) {
        el::Configurations conf("logging");
        el::Loggers::reconfigureAllLoggers(conf);
    } else {
        el::Configurations conf;
        conf.setToDefault();
        conf.parseFromText("*GLOBAL:\n FORMAT = %datetime{%H:%m:%s} %msg\n TO_FILE = true\n TO_STANDARD_OUTPUT = false\n*DEBUG:\n \n TO_FILE = false\n TO_STANDARD_OUTPUT = false\n*INFO:\n \n TO_FILE = false\n TO_STANDARD_OUTPUT = true\n*ERROR:\n \n TO_FILE = false\n TO_STANDARD_OUTPUT = true");
        el::Loggers::reconfigureAllLoggers(conf);
    }

    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "produce help message")
        ("version", "show version")
        ("ip", po::value<std::string>(), "set the ip address for the coordinator")
        ("bitsize", po::value<int>(), "sets the bit size")
        ("localIPaddress", po::value<std::string>(), "sets the local IP address")
        ("numcandidates", po::value<int>(), "sets the number of shares attempted per participant")
        ("passive", "do not include a zero-knowledge argument");

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        LOG(INFO) << desc << "\n";
        LOG(INFO) << "bitsize 8 16 32 64 128 256";
        return 0;
    }

    if (vm.count("passive")) {
        passive = true;
    }

    if (vm.count("version")) {
        std::cout << "party version " << std::hex << PROTOCOL_VERSION_NUMBER << std::endl;
        return 0;
    }

    if (vm.count("ip")) {
        ipAddr = vm["ip"].as<std::string>();
        LOG(INFO) << "Coordinator resides at " << ipAddr;
    }

    if (vm.count("bitsize")) {
        bitsize = vm["bitsize"].as<int>();
        LOG(INFO) << "bitsize = " << bitsize;
    }

    if (vm.count("numcandidates")) {
        numCandidates = vm["numcandidates"].as<int>();
        LOG(INFO) << "Num candidates" << numCandidates;
    }

    if (vm.count("localIPaddress")) {
        localIpAddr = vm["localIPaddress"].as<std::string>();
        LOG(INFO) << "Local IP Address" << localIpAddr;
    }

    // Configure easylogging
    configureEasyLogging("party_full_protocol");

    auto result = participate(ipAddr, localIpAddr, bitsize, numCandidates, passive);
    if (hasError(result)) {
        return 1;
    }
    return 0;
}


/**
 * @file mgmpint.cpp This file contains the main class for unsigned big integers: ubint. Big
 * integers are represented as arrays of machine native unsigned integers. The
 * native integer type is supplied as a template parameter.  Currently
 * implementation based on uint32_t and uint64_t is
 * supported. a native double the base integer size is also needed.
 * @author  TPOC: palisade@njit.edu
 *
 * @copyright Copyright (c) 2017, New Jersey Institute of Technology (NJIT)
 * 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.
 * 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.
 *
 */
 /*
 *
 * This file contains the C++ code for implementing the main class for
 * big integers: ubint. Big integers are represented as arrays of
 * native usigned integers. The native integer type is supplied as a
 * template parameter.  Currently implementation based on uint32_t is
 * supported. One needs a native integer 2x the size of the chosen type for
 * certain math operations.
 */

#define _SECURE_SCL 0 // to speed up VS

#include <iostream>
#include <fstream>
#include <sstream>

#include "../backend.h"

#if defined(__linux__) && MATHBACKEND == 6

#include "gmpint.h"
#include "mgmpint.h"

//#include <NTL/ZZ.h>
//#include <NTL/ZZ_limbs.h>

namespace NTL {

  //define the static vriables
  myZZ myZZ_p::m_OTM = 0;
  myZZ_p::OTMState myZZ_p::m_OTM_state = GARBAGE;

  // may have difficulty with not inintializing modulo first.
  // const myZZ_p myZZ_p::ZERO=myZZ_p(0L);
  // const myZZ_p myZZ_p::ONE=myZZ_p(1);
  // const myZZ_p myZZ_p::TWO=myZZ_p(2);
  // const myZZ_p myZZ_p::THREE=myZZ_p(3);
  // const myZZ_p myZZ_p::FOUR=myZZ_p(4);
  // const
  // myZZ_p myZZ_p::FIVE=myZZ_p(5);

  //constructors without moduli
  myZZ_p::myZZ_p():ZZ_p() {}
  myZZ_p::myZZ_p(int a): ZZ_p(a) {}
  myZZ_p::myZZ_p(long a): ZZ_p(a) {}
  myZZ_p::myZZ_p(unsigned long a): ZZ_p(a) {}
  myZZ_p::myZZ_p(const unsigned int a): ZZ_p(a) {}
  //myZZ_p::myZZ_p(const unsigned int &a): ZZ_p(a) {}
  //myZZ_p::myZZ_p(unsigned int &a): ZZ_p(a) {}
  myZZ_p::myZZ_p(std::string s): ZZ_p() {this->_ZZ_p__rep=conv<ZZ>(s.c_str());}
  myZZ_p::myZZ_p(const char *s): ZZ_p() {this->_ZZ_p__rep=conv<ZZ>(s);}
  //constructors with explicit myZZ moduli
  myZZ_p::myZZ_p(int a, myZZ&q): ZZ_p(a) {m_setOTM(q);}
  myZZ_p::myZZ_p(long a, myZZ&q): ZZ_p(a) {m_setOTM(q);}
  myZZ_p::myZZ_p(unsigned long a, myZZ&q): ZZ_p(a) {m_setOTM(q);}
  myZZ_p::myZZ_p(const unsigned int &a, myZZ&q): ZZ_p(a) {m_setOTM(q);}
  myZZ_p::myZZ_p(unsigned int &a, myZZ&q): ZZ_p(a) {m_setOTM(q);}
  myZZ_p::myZZ_p(std::string s, myZZ&q): ZZ_p() {this->_ZZ_p__rep=conv<ZZ>(s.c_str()); m_setOTM(q);}
  myZZ_p::myZZ_p(const char *s, myZZ&q): ZZ_p() {this->_ZZ_p__rep=conv<ZZ>(s); m_setOTM(q);}

  //constructors with explicit string moduli
  myZZ_p::myZZ_p(int a, const char *sq): ZZ_p(a) {m_setOTM(sq);}
  myZZ_p::myZZ_p(long a, const char *sq): ZZ_p(a) {m_setOTM(sq);}
  myZZ_p::myZZ_p(unsigned long a, const char *sq): ZZ_p(a) {m_setOTM(sq);}
  myZZ_p::myZZ_p(const unsigned int &a, const char *sq): ZZ_p(a) {m_setOTM(sq);}
  myZZ_p::myZZ_p(unsigned int &a, const char *sq): ZZ_p(a) {m_setOTM(sq);}
  myZZ_p::myZZ_p(std::string s, const char *sq): ZZ_p() {this->_ZZ_p__rep=conv<ZZ>(s.c_str());m_setOTM(sq);}
  myZZ_p::myZZ_p(const char *s, const char *sq): ZZ_p() {this->_ZZ_p__rep=conv<ZZ>(s); m_setOTM(sq);}

  //copy constructors
  myZZ_p::myZZ_p(NTL::ZZ &a): ZZ_p() {this->_ZZ_p__rep=a;}
  myZZ_p::myZZ_p(const NTL::ZZ &a): ZZ_p() {this->_ZZ_p__rep=a;}
  myZZ_p::myZZ_p(NTL::ZZ_p &a): ZZ_p(a) {}
  myZZ_p::myZZ_p(const NTL::ZZ_p &a): ZZ_p(a) {}
  // copy constructors with myZZ moduli
  myZZ_p::myZZ_p(NTL::ZZ &a, myZZ&q): ZZ_p() {this->_ZZ_p__rep=a; m_setOTM(q);}
  myZZ_p::myZZ_p(const NTL::ZZ &a, myZZ&q): ZZ_p() {this->_ZZ_p__rep=a; m_setOTM(q);}
  myZZ_p::myZZ_p(NTL::ZZ_p &a, myZZ&q): ZZ_p(a) { m_setOTM(q);}
  myZZ_p::myZZ_p(const NTL::ZZ_p &a, myZZ&q): ZZ_p(a) { m_setOTM(q);}
  // copy constructors with string constant moduli
  myZZ_p::myZZ_p(NTL::ZZ &a, const char *sq): ZZ_p() {this->_ZZ_p__rep=a; m_setOTM(sq);}
  myZZ_p::myZZ_p(const NTL::ZZ &a, const char *sq): ZZ_p() {this->_ZZ_p__rep=a; m_setOTM(sq);}
  myZZ_p::myZZ_p(NTL::ZZ_p &a, const char *sq): ZZ_p(a) { m_setOTM(sq);}
  myZZ_p::myZZ_p(const NTL::ZZ_p &a, const char *sq): ZZ_p(a) { m_setOTM(sq);}
  // copy constructors with unsigned int moduli
  myZZ_p::myZZ_p(NTL::ZZ &a, unsigned int q): ZZ_p() {this->_ZZ_p__rep=a; m_setOTM(q);}
  myZZ_p::myZZ_p(const NTL::ZZ &a, unsigned int q): ZZ_p() {this->_ZZ_p__rep=a; m_setOTM(q);}
  myZZ_p::myZZ_p(NTL::ZZ_p &a, unsigned int q): ZZ_p(a) { m_setOTM(q);}
  myZZ_p::myZZ_p(const NTL::ZZ_p &a, unsigned int q): ZZ_p(a) { m_setOTM(q);}

  //move copy constructors
  myZZ_p::myZZ_p(NTL::ZZ &&a) : ZZ_p() {this->_ZZ_p__rep.swap(a);}
  myZZ_p::myZZ_p(NTL::ZZ_p &&a) : ZZ_p() {this->swap(a);}

  myZZ_p  myZZ_p::MultiplyAndRound(const myZZ &p, const myZZ &q) const
  {
    myZZ ans(this->_ZZ_p__rep);
    ans *= p;
    ans = ans.DivideAndRound(q);
    return myZZ_p(ans);
  }

  myZZ_p myZZ_p::DivideAndRound(const myZZ &q) const
  {
    myZZ ans(this->_ZZ_p__rep);
     ans = ans.DivideAndRound(q);
    return myZZ_p(ans);
  }

  usint myZZ_p::GetMSB() const {
    //note: originally I did not worry about this, and just set the
    //MSB whenever this was called, but then that violated constness in the
    // various libraries that used this heavily
    //this->SetMSB(); //note no one needs to SetMSB()
    //return m_MSB;

    //SO INSTEAD I am just regenerating the MSB each time
    size_t sz = this->_ZZ_p__rep.size();
    usint MSB;
    //std::cout<<"size "<<sz <<" ";
    if (sz==0) { //special case for empty data
      MSB = 0;
      return(MSB);
    }
    MSB = (sz-1) * NTL_ZZ_NBITS; //figure out bit location of all but last limb
    const ZZ_limb_t *zlp = ZZ_limbs_get(this->_ZZ_p__rep);
    usint tmp = GetMSBLimb_t(zlp[sz-1]); //add the value of that last limb.
    MSB+=tmp;
    return(MSB);
  }

  void myZZ_p::SetMSB()
  {
    size_t sz = this->_ZZ_p__rep.size();
    //std::cout<<"size "<<sz <<" ";
    if (sz==0) { //special case for empty data
      m_MSB = 0;
      return;
    }

    m_MSB = (sz-1) * NTL_ZZ_NBITS; //figure out bit location of all but last limb
    //std::cout<<"msb starts with "<<m_MSB<< " ";
    //could also try
    //m_MSB = NumBytes(*this)*8;
    const ZZ_limb_t *zlp = ZZ_limbs_get(this->_ZZ_p__rep);
    //for (usint i = 0; i < sz; i++){
    //std::cout<< "limb["<<i<<"] = "<<zlp[i]<<std::endl;
    //}

    usint tmp = GetMSBLimb_t(zlp[sz-1]); //add the value of that last limb.
    //std::cout<< "tmp = "<<tmp<<std::endl;
    m_MSB+=tmp;
    //std::cout<<"msb ends with "<<m_MSB<< " " <<std::endl;
  }

 // inline static usint GetMSBLimb_t(ZZ_limb_t x){
  usint myZZ_p::GetMSBLimb_t( ZZ_limb_t x) const{
    const usint bval[] =
    {0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4};

    uint64_t r = 0;
    if (x & 0xFFFFFFFF00000000) { r += 32/1; x >>= 32/1; }
    if (x & 0x00000000FFFF0000) { r += 32/2; x >>= 32/2; }
    if (x & 0x000000000000FF00) { r += 32/4; x >>= 32/4; }
    if (x & 0x00000000000000F0) { r += 32/8; x >>= 32/8; }
    return r + bval[x];
  }

  void myZZ_p::m_setOTM(const myZZ &q)
  {
    //should test first but for now just set
    ZZ_p::init(q);
    m_OTM = q;
    m_OTM_state = INITIALIZED;
  }

  bool myZZ_p::m_checkOTM(const myZZ &q) const
  {
#ifdef WARN_BAD_MODULUS
    if (m_OTM_state == GARBAGE){
      //throw std::logic_error("myZZ_p::m_checkOTM() called with uninitialized OTM");
      std::cout<<"myZZ_p::m_checkOTM() called with uninitialized OTM"<<std::endl;
#ifdef PAUSE_BAD_MODULUS
      std::string foo;
      std::cin >> foo;
#endif

    }
#endif
    return (m_OTM == q);
  }

  myZZ& myZZ_p::m_getOTM(void) const
  {
#ifdef WARN_BAD_MODULUS
    if (m_OTM_state == GARBAGE){
      //std::logic_error("myZZ_p::m_getOTM() called with uninitialized OTM");
      std::cout<<"myZZ_p::m_getOTM() called with uninitialized OTM"<<std::endl;
#ifdef PAUSE_BAD_MODULUS
      std::string foo;
      std::cin >> foo;
#endif
    }
#endif
    return m_OTM;
  }

  //adapter kit
  //static const myZZ_p& myZZ_p::zero() {return const myZZ_p(0);}

  // //palisade conversion methods
  // usint myZZ_p::ConvertToUsint() const{
  //   bool dbg_flag = false;

  //   DEBUG("in myZZ_p::ConvertToUsint() this "<<*this);

  //   return (conv<usint>(*this));
  // }
  uint64_t myZZ_p::ConvertToInt() const{
   bool dbg_flag = false;

    DEBUG("in myZZ_p::ConvertToInt() this "<<*this);

    uint64_t result = conv<uint64_t>(*this);
    if (this->GetMSB() >= 64) {
      std::cerr<<"Warning myZZ_p::ConvertToInt() Loss of precision. "<<std::endl;
      std::cerr<<"input  "<< *this<<std::endl;
      std::cerr<<"result  "<< result<<std::endl;
    }
    return result;
  }
  // uint32_t myZZ_p::ConvertToUint32() const { return (conv<uint32_t>(*this));}

 // warning on some platforms usint64_t is implemented as an unsigned
  // long long which is not included in the conv functions in tools.h
  // in which case the following does not compile.

  uint64_t myZZ_p::ConvertToUint64() const{
    static_assert(sizeof(uint64_t) == sizeof(long),
		  "sizeof(uint64_t) != sizeof(long), edit myZZ ConvertToUint64()");
    uint64_t result = conv<uint64_t>(*this);
    if (this->GetMSB() >= 64) {
      std::cerr<<"Warning myZZ_p::ConvertToInt() Loss of precision. "<<std::endl;
      std::cerr<<"input  "<< *this<<std::endl;
      std::cerr<<"result  "<< result<<std::endl;
    }
    return result;
  }
  //float myZZ_p::ConvertToFloat() const{ return (conv<float>(this->_ZZ_p__rep));}
  double myZZ_p::ConvertToDouble() const{ return (conv<double>(this->_ZZ_p__rep));}
  //long double myZZ_p::ConvertToLongDouble() const {
  //  std::cerr<<"can't convert to long double"<<std::endl;
  //  return 0.0L;
  //}

  std::ostream& operator<<(std::ostream& os, const myZZ_p& ptr_obj){
    os << (ZZ_p)ptr_obj;
    return os;
  }

  const std::string myZZ_p::ToString() const
  {
    //todo Not sure if this string is safe, it may be ephemeral if not returned  by value.
    std::stringstream result("");
    result << *this;
    return result.str();
  }

  //optimized ceiling function after division by number of bits in the limb data type.
  usint myZZ_p::ceilIntByUInt( const ZZ_limb_t Number) const{
    //mask to perform bitwise AND
    static ZZ_limb_t mask = NTL_ZZ_NBITS-1;

    if(!Number)
      return 1;
    if((Number&mask)!=0)
      return (Number>>myZZ::m_log2LimbBitLength)+1;
    else
      return Number>>myZZ::m_log2LimbBitLength;
  }
#if 0
  // friend or inherit this? it is the same as gmpint
 //the following code is new serialize/deserialize code from

  // the array and the next
  // two functions convert a ubint in and out of a string of
  // characters the encoding is Base64-like: the first 5 6-bit
  // groupings are Base64 encoded, and the last 2 bits are A-D

  // Note this is, sadly, hardcoded for 32 bit integers and needs Some
  // Work to handle arbitrary sizes

  // precomputed shift amounts for each 6 bit chunk
  static const usint b64_shifts[] = { 0, 6, 12, 18, 24, 30 };
  static const usint B64MASK = 0x3F;

  // this for encoding...
  static char to_base64_char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  // and this for decoding...
  static inline unsigned int base64_to_value(char b64) {
    if( isupper(b64) )
      return b64 - 'A';
    else if( islower(b64) )
      return b64 - 'a' + 26;
    else if( isdigit(b64) )
      return b64 - '0' + 52;
    else if( b64 == '+' )
      return 62;
    else
      return 63;
  }

#endif
  // serialization of myZZ_p, calls myZZ.Serialize,
  const std::string myZZ_p::Serialize(const myZZ &modulus) const {
    bool dbg_flag = false;

    //note this does simple serialization, other libraries store small special values for 0 or  -1
    //we ignore this
    DEBUG("mgmp ser "<<*this);
    return (myZZ(this->_ZZ_p__rep)).Serialize();
  }

  // deserialization of myZZ_p, calls myZZ.Deserialize,
  // sets modulus to input  modulus.
  const char * myZZ_p::Deserialize(const char *cp, const myZZ &modulus){
    bool dbg_flag = false;
    const char *cpout;
    clear(*this);
    myZZ(repZZ); //new value store decode

    //DEBUG("cp before in mgminp "<<cp);
    cpout = repZZ.Deserialize(cp);    //cpout is rest of cp after decode
    //DEBUG("cp after in mgminp "<<cpout);
    //save
    *this=myZZ_p(repZZ);
    this->SetModulus(modulus);
    DEBUG("mgmp deser "<<*this);
    SetMSB();

    return cpout;
  }

} // namespace NTL ends

#endif


//==================================================================================================
/*
  Copyright 2017 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)
*/
//==================================================================================================
//! [majority]
#include <boost/simd/predicates.hpp>
#include <boost/simd/pack.hpp>
#include <iostream>

namespace bs =  boost::simd;
using pack_ft = bs::pack <float, 4>;

int main()
{
  pack_ft pf = { 0.0f, 1.0f, -1.0f, -2.0f  };
  pack_ft qf = { 0.0f, 0.0f, -0.0f, -2.0f  };
  pack_ft rf = { 0.0f, 1.0f, -0.0f, -2.0f  };

  std::cout
    << "---- simd" << '\n'
    << "<- pf =                  " << pf << '\n'
    << "<- qf =                  " << qf << '\n'
    << "<- rf =                  " << rf << '\n'
    << "-> bs::majority(pf, qf, rf) = " << bs::majority(pf, qf, rf) << '\n';

  float xf = 1.0f;
  float yf = 2.0;
  float zf = 0.0;

  std::cout
    << "---- scalar"  << '\n'
    << "<- xf =                  " << xf << '\n'
    << "<- yf =                  " << yf << '\n'
    << "<- zf =                  " << zf << '\n'
    << "-> bs::majority(xf, yf, zf) = " << bs::majority(xf, yf, zf) << '\n';
  return 0;
}
//! [majority]


/*! \file dist_graphs.cpp
    \brief Produces Scalable Vector Graphic (.svg) files for all distributions.
    \details These files can be viewed using most browsers,
    though MS Internet Explorer requires a plugin from Adobe.
    These file can be converted to .png using Inkscape
    (see www.inkscape.org) Export Bit option which by default produces
    a Portable Network Graphic file with that same filename but .png suffix instead of .svg.
    Using Python, generate.sh does this conversion automatically for all .svg files in a folder.

    \author John Maddock and Paul A. Bristow
  */
//  Copyright John Maddock 2008.
//  Copyright Paul A. Bristow 2008, 2009
//  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)

#ifdef _MSC_VER
#  pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
#  pragma warning (disable : 4503) // decorated name length exceeded, name was truncated
#  pragma warning (disable : 4512) // assignment operator could not be generated
#  pragma warning (disable : 4224) // nonstandard extension used : formal parameter 'function_ptr' was previously defined as a type
#  pragma warning (disable : 4127) // conditional expression is constant
#endif

#define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error

#include <boost/math/distributions.hpp>
#include <boost/math/tools/roots.hpp>
#include <boost/svg_plot/svg_2d_plot.hpp>

#include <list>
#include <map>
#include <string>

template <class Dist>
struct is_discrete_distribution
   : public boost::mpl::false_{};

template<class T, class P>
struct is_discrete_distribution<boost::math::bernoulli_distribution<T,P> >
   : public boost::mpl::true_{};
template<class T, class P>
struct is_discrete_distribution<boost::math::binomial_distribution<T,P> >
   : public boost::mpl::true_{};
template<class T, class P>
struct is_discrete_distribution<boost::math::negative_binomial_distribution<T,P> >
   : public boost::mpl::true_{};
template<class T, class P>
struct is_discrete_distribution<boost::math::poisson_distribution<T,P> >
   : public boost::mpl::true_{};
template<class T, class P>
struct is_discrete_distribution<boost::math::hypergeometric_distribution<T,P> >
   : public boost::mpl::true_{};

template <class Dist>
struct value_finder
{
   value_finder(Dist const& d, typename Dist::value_type v)
      : m_dist(d), m_value(v) {}

   inline typename Dist::value_type operator()(const typename Dist::value_type& x)
   {
      return pdf(m_dist, x) - m_value;
   }

private:
   Dist m_dist;
   typename Dist::value_type m_value;
};

template <class Dist>
class distribution_plotter
{
public:
   distribution_plotter() : m_pdf(true), m_min_x(0), m_max_x(0), m_min_y(0), m_max_y(0) {}
   distribution_plotter(bool pdf) : m_pdf(pdf), m_min_x(0), m_max_x(0), m_min_y(0), m_max_y(0) {}

   void add(const Dist& d, const std::string& name)
   {
      //
      // Add to our list for later:
      //
      m_distributions.push_back(std::make_pair(name, d));
      //
      // Get the extent:
      //
      double a, b;
      std::tr1::tie(a, b) = support(d);
      //
      // PDF maximimum is at the mode:
      //
      double mod;
      try
      {
         mod = mode(d);
      }
      catch(const std::domain_error& )
      {
         mod = a;
      }
      if((mod <= a) && !is_discrete_distribution<Dist>::value)
      {
         if((a != 0) && (fabs(a) > 1e-2))
            mod = a * (1 + 1e-2);
         else
            mod = 1e-2;
      }
      double peek_y = pdf(d, mod);
      double min_y = peek_y / 20;
      //
      // If the extent is "infinite" then find out how large it
      // has to be for the PDF to decay to min_y:
      //
      if(a <= -(std::numeric_limits<double>::max)())
      {
         boost::uintmax_t max_iter = 500;
         double guess = mod;
         if((pdf(d, 0) > min_y) || (guess == 0))
            guess = -1e-3;
         a = boost::math::tools::bracket_and_solve_root(
            value_finder<Dist>(d, min_y),
            guess,
            8.0,
            true,
            boost::math::tools::eps_tolerance<double>(10),
            max_iter).first;
      }
      if(b >= (std::numeric_limits<double>::max)())
      {
         boost::uintmax_t max_iter = 500;
         double guess = mod;
         if(a <= 0)
            if((pdf(d, 0) > min_y) || (guess == 0))
               guess = 1e-3;
         b = boost::math::tools::bracket_and_solve_root(
            value_finder<Dist>(d, min_y),
            guess,
            8.0,
            false,
            boost::math::tools::eps_tolerance<double>(10),
            max_iter).first;
      }
      //
      // Recalculate peek_y and location of mod so that
      // it's not too close to one end of the graph:
      // otherwise we may be shooting off to infinity.
      //
      if(!is_discrete_distribution<Dist>::value)
      {
         if(mod <= a + (b-a)/50)
         {
            mod = a + (b-a)/50;
         }
         if(mod >= b - (b-a)/50)
         {
            mod = b - (b-a)/50;
         }
         peek_y = pdf(d, mod);
      }
      //
      // Now set our limits:
      //
      if(peek_y > m_max_y)
         m_max_y = peek_y;
      if(m_max_x == m_min_x)
      {
         m_max_x = b;
         m_min_x = a;
      }
      else
      {
         if(a < m_min_x)
            m_min_x = a;
         if(b > m_max_x)
            m_max_x = b;
      }
   }

   void plot(const std::string& title, const std::string& file)
   {
      using namespace boost::svg;

      static const svg_color colors[5] =
      {
         darkblue,
         darkred,
         darkgreen,
         darkorange,
         chartreuse
      };

      if(m_pdf == false)
      {
         m_min_y = 0;
         m_max_y = 1;
      }

      svg_2d_plot plot;
      plot.image_x_size(750);
      plot.image_y_size(400);
      plot.coord_precision(4); // Avoids any visible steps.
      plot.title_font_size(20);
      plot.legend_title_font_size(15);
      plot.title(title);
      if((m_distributions.size() == 1) && (m_distributions.begin()->first == ""))
         plot.legend_on(false);
      else
         plot.legend_on(true);
      plot.title_on(true);
      //plot.x_major_labels_on(true).y_major_labels_on(true);
      //double x_delta = (m_max_x - m_min_x) / 10;
      double y_delta = (m_max_y - m_min_y) / 10;
      if(is_discrete_distribution<Dist>::value)
         plot.x_range(m_min_x - 0.5, m_max_x + 0.5)
             .y_range(m_min_y, m_max_y + y_delta);
      else
         plot.x_range(m_min_x, m_max_x)
             .y_range(m_min_y, m_max_y + y_delta);
      plot.x_label_on(true).x_label("Random Variable");
      plot.y_label_on(true).y_label("Probability");
      plot.plot_border_color(lightslategray)
          .background_border_color(lightslategray)
          .legend_border_color(lightslategray)
          .legend_background_color(white);
      //
      // Work out axis tick intervals:
      //
      double l = std::floor(std::log10((m_max_x - m_min_x) / 10) + 0.5);
      double interval = std::pow(10.0, (int)l);
      if(((m_max_x - m_min_x) / interval) > 10)
         interval *= 5;
      if(is_discrete_distribution<Dist>::value)
      {
         interval = interval > 1 ? std::floor(interval) : 1;
         plot.x_num_minor_ticks(0);
      }
      plot.x_major_interval(interval);
      l = std::floor(std::log10((m_max_y - m_min_y) / 10) + 0.5);
      interval = std::pow(10.0, (int)l);
      if(((m_max_y - m_min_y) / interval) > 10)
         interval *= 5;
      plot.y_major_interval(interval);

      int color_index = 0;

      if(!is_discrete_distribution<Dist>::value)
      {
         //
         // Continuous distribution:
         //
         for(std::list<std::pair<std::string, Dist> >::const_iterator i = m_distributions.begin();
            i != m_distributions.end(); ++i)
         {
            double x = m_min_x;
            double interval = (m_max_x - m_min_x) / 200;
            std::map<double, double> data;
            while(x <= m_max_x)
            {
               data[x] = m_pdf ? pdf(i->second, x) : cdf(i->second, x);
               x += interval;
            }
            plot.plot(data, i->first)
               .line_on(true)
               .line_color(colors[color_index])
               .line_width(1.)
               .shape(none);
               //.bezier_on(true) // Bezier can't cope with badly behaved like uniform & triangular.
            ++color_index;
            color_index = color_index % (sizeof(colors)/sizeof(colors[0]));
         }
      }
      else
      {
         //
         // Discrete distribution:
         //
         double x_width = 0.75 / m_distributions.size();
         double x_off = -0.5 * 0.75;
         for(std::list<std::pair<std::string, Dist> >::const_iterator i = m_distributions.begin();
            i != m_distributions.end(); ++i)
         {
            double x = ceil(m_min_x);
            double interval = 1;
            std::map<double, double> data;
            while(x <= m_max_x)
            {
               double p;
               try{
                  p = m_pdf ? pdf(i->second, x) : cdf(i->second, x);
               }
               catch(const std::domain_error&)
               {
                  p = 0;
               }
               data[x + x_off] = 0;
               data[x + x_off + 0.00001] = p;
               data[x + x_off + x_width] = p;
               data[x + x_off + x_width + 0.00001] = 0;
               x += interval;
            }
            x_off += x_width;
            svg_2d_plot_series& s = plot.plot(data, i->first);
            s.line_on(true)
               .line_color(colors[color_index])
               .line_width(1.)
               .shape(none)
               .area_fill(colors[color_index]);
            ++color_index;
            color_index = color_index % (sizeof(colors)/sizeof(colors[0]));
         }
      }
      plot.write(file);
   }

private:
   bool m_pdf;
   std::list<std::pair<std::string, Dist> > m_distributions;
   double m_min_x, m_max_x, m_min_y, m_max_y;
};

int main()
{
   distribution_plotter<boost::math::gamma_distribution<> >
      gamma_plotter;
   gamma_plotter.add(boost::math::gamma_distribution<>(0.75), "shape = 0.75");
   gamma_plotter.add(boost::math::gamma_distribution<>(1), "shape = 1");
   gamma_plotter.add(boost::math::gamma_distribution<>(3), "shape = 3");
   gamma_plotter.plot("Gamma Distribution PDF With Scale = 1", "gamma1_pdf.svg");

   distribution_plotter<boost::math::gamma_distribution<> >
      gamma_plotter2;
   gamma_plotter2.add(boost::math::gamma_distribution<>(2, 0.5), "scale = 0.5");
   gamma_plotter2.add(boost::math::gamma_distribution<>(2, 1), "scale = 1");
   gamma_plotter2.add(boost::math::gamma_distribution<>(2, 2), "scale = 2");
   gamma_plotter2.plot("Gamma Distribution PDF With Shape = 2", "gamma2_pdf.svg");

   distribution_plotter<boost::math::normal>
      normal_plotter;
   normal_plotter.add(boost::math::normal(0, 1), "μ = 0, σ = 1");
   normal_plotter.add(boost::math::normal(0, 0.5), "μ = 0, σ = 0.5");
   normal_plotter.add(boost::math::normal(0, 2), "μ = 0, σ = 2");
   normal_plotter.add(boost::math::normal(-1, 1), "μ = -1, σ = 1");
   normal_plotter.add(boost::math::normal(1, 1), "μ = 1, σ = 1");
   normal_plotter.plot("Normal Distribution PDF", "normal_pdf.svg");

   distribution_plotter<boost::math::laplace>
      laplace_plotter;
   laplace_plotter.add(boost::math::laplace(0, 1), "μ = 0, σ = 1");
   laplace_plotter.add(boost::math::laplace(0, 0.5), "μ = 0, σ = 0.5");
   laplace_plotter.add(boost::math::laplace(0, 2), "μ = 0, σ = 2");
   laplace_plotter.add(boost::math::laplace(-1, 1), "μ = -1, σ = 1");
   laplace_plotter.add(boost::math::laplace(1, 1), "μ = 1, σ = 1");
   laplace_plotter.plot("Laplace Distribution PDF", "laplace_pdf.svg");

   distribution_plotter<boost::math::non_central_chi_squared>
      nc_cs_plotter;
   nc_cs_plotter.add(boost::math::non_central_chi_squared(20, 0), "v=20, λ=0");
   nc_cs_plotter.add(boost::math::non_central_chi_squared(20, 1), "v=20, λ=1");
   nc_cs_plotter.add(boost::math::non_central_chi_squared(20, 5), "v=20, λ=5");
   nc_cs_plotter.add(boost::math::non_central_chi_squared(20, 10), "v=20, λ=10");
   nc_cs_plotter.add(boost::math::non_central_chi_squared(20, 20), "v=20, λ=20");
   nc_cs_plotter.add(boost::math::non_central_chi_squared(20, 100), "v=20, λ=100");
   nc_cs_plotter.plot("Non Central Chi Squared PDF", "nccs_pdf.svg");

   distribution_plotter<boost::math::non_central_beta>
      nc_beta_plotter;
   nc_beta_plotter.add(boost::math::non_central_beta(10, 15, 0), "α=10, β=15, δ=0");
   nc_beta_plotter.add(boost::math::non_central_beta(10, 15, 1), "α=10, β=15, δ=1");
   nc_beta_plotter.add(boost::math::non_central_beta(10, 15, 5), "α=10, β=15, δ=5");
   nc_beta_plotter.add(boost::math::non_central_beta(10, 15, 10), "α=10, β=15, δ=10");
   nc_beta_plotter.add(boost::math::non_central_beta(10, 15, 40), "α=10, β=15, δ=40");
   nc_beta_plotter.add(boost::math::non_central_beta(10, 15, 100), "α=10, β=15, δ=100");
   nc_beta_plotter.plot("Non Central Beta PDF", "nc_beta_pdf.svg");

   distribution_plotter<boost::math::non_central_f>
      nc_f_plotter;
   nc_f_plotter.add(boost::math::non_central_f(10, 20, 0), "v1=10, v2=20, λ=0");
   nc_f_plotter.add(boost::math::non_central_f(10, 20, 1), "v1=10, v2=20, λ=1");
   nc_f_plotter.add(boost::math::non_central_f(10, 20, 5), "v1=10, v2=20, λ=5");
   nc_f_plotter.add(boost::math::non_central_f(10, 20, 10), "v1=10, v2=20, λ=10");
   nc_f_plotter.add(boost::math::non_central_f(10, 20, 40), "v1=10, v2=20, λ=40");
   nc_f_plotter.add(boost::math::non_central_f(10, 20, 100), "v1=10, v2=20, λ=100");
   nc_f_plotter.plot("Non Central F PDF", "nc_f_pdf.svg");

   distribution_plotter<boost::math::non_central_t>
      nc_t_plotter;
   nc_t_plotter.add(boost::math::non_central_t(10, -10), "v=10, δ=-10");
   nc_t_plotter.add(boost::math::non_central_t(10, -5), "v=10, δ=-5");
   nc_t_plotter.add(boost::math::non_central_t(10, 0), "v=10, δ=0");
   nc_t_plotter.add(boost::math::non_central_t(10, 5), "v=10, δ=5");
   nc_t_plotter.add(boost::math::non_central_t(10, 10), "v=10, δ=10");
   nc_t_plotter.plot("Non Central T PDF", "nc_t_pdf.svg");

   distribution_plotter<boost::math::beta_distribution<> >
      beta_plotter;
   beta_plotter.add(boost::math::beta_distribution<>(0.5, 0.5), "alpha=0.5, beta=0.5");
   beta_plotter.add(boost::math::beta_distribution<>(5, 1), "alpha=5, beta=1");
   beta_plotter.add(boost::math::beta_distribution<>(1, 3), "alpha=1, beta=3");
   beta_plotter.add(boost::math::beta_distribution<>(2, 2), "alpha=2, beta=2");
   beta_plotter.add(boost::math::beta_distribution<>(2, 5), "alpha=2, beta=5");
   beta_plotter.plot("Beta Distribution PDF", "beta_pdf.svg");

   distribution_plotter<boost::math::cauchy_distribution<> >
      cauchy_plotter;
   cauchy_plotter.add(boost::math::cauchy_distribution<>(-5, 1), "location = -5");
   cauchy_plotter.add(boost::math::cauchy_distribution<>(0, 1), "location = 0");
   cauchy_plotter.add(boost::math::cauchy_distribution<>(5, 1), "location = 5");
   cauchy_plotter.plot("Cauchy Distribution PDF (scale = 1)", "cauchy_pdf1.svg");

   distribution_plotter<boost::math::cauchy_distribution<> >
      cauchy_plotter2;
   cauchy_plotter2.add(boost::math::cauchy_distribution<>(0, 0.5), "scale = 0.5");
   cauchy_plotter2.add(boost::math::cauchy_distribution<>(0, 1), "scale = 1");
   cauchy_plotter2.add(boost::math::cauchy_distribution<>(0, 2), "scale = 2");
   cauchy_plotter2.plot("Cauchy Distribution PDF (location = 0)", "cauchy_pdf2.svg");

   distribution_plotter<boost::math::chi_squared_distribution<> >
      chi_squared_plotter;
   //chi_squared_plotter.add(boost::math::chi_squared_distribution<>(1), "v=1");
   chi_squared_plotter.add(boost::math::chi_squared_distribution<>(2), "v=2");
   chi_squared_plotter.add(boost::math::chi_squared_distribution<>(5), "v=5");
   chi_squared_plotter.add(boost::math::chi_squared_distribution<>(10), "v=10");
   chi_squared_plotter.plot("Chi Squared Distribution PDF", "chi_squared_pdf.svg");

   distribution_plotter<boost::math::exponential_distribution<> >
      exponential_plotter;
   exponential_plotter.add(boost::math::exponential_distribution<>(0.5), "λ=0.5");
   exponential_plotter.add(boost::math::exponential_distribution<>(1), "λ=1");
   exponential_plotter.add(boost::math::exponential_distribution<>(2), "λ=2");
   exponential_plotter.plot("Exponential Distribution PDF", "exponential_pdf.svg");

   distribution_plotter<boost::math::extreme_value_distribution<> >
      extreme_value_plotter;
   extreme_value_plotter.add(boost::math::extreme_value_distribution<>(-5), "location=-5");
   extreme_value_plotter.add(boost::math::extreme_value_distribution<>(0), "location=0");
   extreme_value_plotter.add(boost::math::extreme_value_distribution<>(5), "location=5");
   extreme_value_plotter.plot("Extreme Value Distribution PDF (shape=1)", "extreme_value_pdf1.svg");

   distribution_plotter<boost::math::extreme_value_distribution<> >
      extreme_value_plotter2;
   extreme_value_plotter2.add(boost::math::extreme_value_distribution<>(0, 0.5), "shape=0.5");
   extreme_value_plotter2.add(boost::math::extreme_value_distribution<>(0, 1), "shape=1");
   extreme_value_plotter2.add(boost::math::extreme_value_distribution<>(0, 2), "shape=2");
   extreme_value_plotter2.plot("Extreme Value Distribution PDF (location=0)", "extreme_value_pdf2.svg");

   distribution_plotter<boost::math::fisher_f_distribution<> >
      fisher_f_plotter;
   fisher_f_plotter.add(boost::math::fisher_f_distribution<>(4, 4), "n=4, m=4");
   fisher_f_plotter.add(boost::math::fisher_f_distribution<>(10, 4), "n=10, m=4");
   fisher_f_plotter.add(boost::math::fisher_f_distribution<>(10, 10), "n=10, m=10");
   fisher_f_plotter.add(boost::math::fisher_f_distribution<>(4, 10), "n=4, m=10");
   fisher_f_plotter.plot("F Distribution PDF", "fisher_f_pdf.svg");

   distribution_plotter<boost::math::lognormal_distribution<> >
      lognormal_plotter;
   lognormal_plotter.add(boost::math::lognormal_distribution<>(-1), "location=-1");
   lognormal_plotter.add(boost::math::lognormal_distribution<>(0), "location=0");
   lognormal_plotter.add(boost::math::lognormal_distribution<>(1), "location=1");
   lognormal_plotter.plot("Lognormal Distribution PDF (scale=1)", "lognormal_pdf1.svg");

   distribution_plotter<boost::math::lognormal_distribution<> >
      lognormal_plotter2;
   lognormal_plotter2.add(boost::math::lognormal_distribution<>(0, 0.5), "scale=0.5");
   lognormal_plotter2.add(boost::math::lognormal_distribution<>(0, 1), "scale=1");
   lognormal_plotter2.add(boost::math::lognormal_distribution<>(0, 2), "scale=2");
   lognormal_plotter2.plot("Lognormal Distribution PDF (location=0)", "lognormal_pdf2.svg");

   distribution_plotter<boost::math::pareto_distribution<> >
      pareto_plotter; // Rely on 2nd parameter shape = 1 default.
   pareto_plotter.add(boost::math::pareto_distribution<>(1), "scale=1");
   pareto_plotter.add(boost::math::pareto_distribution<>(2), "scale=2");
   pareto_plotter.add(boost::math::pareto_distribution<>(3), "scale=3");
   pareto_plotter.plot("Pareto Distribution PDF (shape=1)", "pareto_pdf1.svg");

   distribution_plotter<boost::math::pareto_distribution<> >
      pareto_plotter2;
   pareto_plotter2.add(boost::math::pareto_distribution<>(1, 0.5), "shape=0.5");
   pareto_plotter2.add(boost::math::pareto_distribution<>(1, 1), "shape=1");
   pareto_plotter2.add(boost::math::pareto_distribution<>(1, 2), "shape=2");
   pareto_plotter2.plot("Pareto Distribution PDF (scale=1)", "pareto_pdf2.svg");

   distribution_plotter<boost::math::rayleigh_distribution<> >
      rayleigh_plotter;
   rayleigh_plotter.add(boost::math::rayleigh_distribution<>(0.5), "σ=0.5");
   rayleigh_plotter.add(boost::math::rayleigh_distribution<>(1), "σ=1");
   rayleigh_plotter.add(boost::math::rayleigh_distribution<>(2), "σ=2");
   rayleigh_plotter.add(boost::math::rayleigh_distribution<>(4), "σ=4");
   rayleigh_plotter.add(boost::math::rayleigh_distribution<>(10), "σ=10");
   rayleigh_plotter.plot("Rayleigh Distribution PDF", "rayleigh_pdf.svg");

   distribution_plotter<boost::math::rayleigh_distribution<> >
      rayleigh_cdf_plotter(false);
   rayleigh_cdf_plotter.add(boost::math::rayleigh_distribution<>(0.5), "σ=0.5");
   rayleigh_cdf_plotter.add(boost::math::rayleigh_distribution<>(1), "σ=1");
   rayleigh_cdf_plotter.add(boost::math::rayleigh_distribution<>(2), "σ=2");
   rayleigh_cdf_plotter.add(boost::math::rayleigh_distribution<>(4), "σ=4");
   rayleigh_cdf_plotter.add(boost::math::rayleigh_distribution<>(10), "σ=10");
   rayleigh_cdf_plotter.plot("Rayleigh Distribution CDF", "rayleigh_cdf.svg");

   distribution_plotter<boost::math::triangular_distribution<> >
      triangular_plotter;
   triangular_plotter.add(boost::math::triangular_distribution<>(-1,0,1), "{-1,0,1}");
   triangular_plotter.add(boost::math::triangular_distribution<>(0,1,1), "{0,1,1}");
   triangular_plotter.add(boost::math::triangular_distribution<>(0,1,3), "{0,1,3}");
   triangular_plotter.add(boost::math::triangular_distribution<>(0,0.5,1), "{0,0.5,1}");
   triangular_plotter.add(boost::math::triangular_distribution<>(-2,0,3), "{-2,0,3}");
   triangular_plotter.plot("Triangular Distribution PDF", "triangular_pdf.svg");

   distribution_plotter<boost::math::triangular_distribution<> >
      triangular_cdf_plotter(false);
   triangular_cdf_plotter.add(boost::math::triangular_distribution<>(-1,0,1), "{-1,0,1}");
   triangular_cdf_plotter.add(boost::math::triangular_distribution<>(0,1,1), "{0,1,1}");
   triangular_cdf_plotter.add(boost::math::triangular_distribution<>(0,1,3), "{0,1,3}");
   triangular_cdf_plotter.add(boost::math::triangular_distribution<>(0,0.5,1), "{0,0.5,1}");
   triangular_cdf_plotter.add(boost::math::triangular_distribution<>(-2,0,3), "{-2,0,3}");
   triangular_cdf_plotter.plot("Triangular Distribution CDF", "triangular_cdf.svg");

   distribution_plotter<boost::math::students_t_distribution<> >
      students_t_plotter;
   students_t_plotter.add(boost::math::students_t_distribution<>(1), "v=1");
   students_t_plotter.add(boost::math::students_t_distribution<>(5), "v=5");
   students_t_plotter.add(boost::math::students_t_distribution<>(30), "v=30");
   students_t_plotter.plot("Students T Distribution PDF", "students_t_pdf.svg");

   distribution_plotter<boost::math::weibull_distribution<> >
      weibull_plotter;
   weibull_plotter.add(boost::math::weibull_distribution<>(0.75), "shape=0.75");
   weibull_plotter.add(boost::math::weibull_distribution<>(1), "shape=1");
   weibull_plotter.add(boost::math::weibull_distribution<>(5), "shape=5");
   weibull_plotter.add(boost::math::weibull_distribution<>(10), "shape=10");
   weibull_plotter.plot("Weibull Distribution PDF (scale=1)", "weibull_pdf1.svg");

   distribution_plotter<boost::math::weibull_distribution<> >
      weibull_plotter2;
   weibull_plotter2.add(boost::math::weibull_distribution<>(3, 0.5), "scale=0.5");
   weibull_plotter2.add(boost::math::weibull_distribution<>(3, 1), "scale=1");
   weibull_plotter2.add(boost::math::weibull_distribution<>(3, 2), "scale=2");
   weibull_plotter2.plot("Weibull Distribution PDF (shape=3)", "weibull_pdf2.svg");

   distribution_plotter<boost::math::uniform_distribution<> >
      uniform_plotter;
   uniform_plotter.add(boost::math::uniform_distribution<>(0, 1), "{0,1}");
   uniform_plotter.add(boost::math::uniform_distribution<>(0, 3), "{0,3}");
   uniform_plotter.add(boost::math::uniform_distribution<>(-2, 3), "{-2,3}");
   uniform_plotter.add(boost::math::uniform_distribution<>(-1, 1), "{-1,1}");
   uniform_plotter.plot("Uniform Distribution PDF", "uniform_pdf.svg");

   distribution_plotter<boost::math::uniform_distribution<> >
      uniform_cdf_plotter(false);
   uniform_cdf_plotter.add(boost::math::uniform_distribution<>(0, 1), "{0,1}");
   uniform_cdf_plotter.add(boost::math::uniform_distribution<>(0, 3), "{0,3}");
   uniform_cdf_plotter.add(boost::math::uniform_distribution<>(-2, 3), "{-2,3}");
   uniform_cdf_plotter.add(boost::math::uniform_distribution<>(-1, 1), "{-1,1}");
   uniform_cdf_plotter.plot("Uniform Distribution CDF", "uniform_cdf.svg");

   distribution_plotter<boost::math::bernoulli_distribution<> >
      bernoulli_plotter;
   bernoulli_plotter.add(boost::math::bernoulli_distribution<>(0.25), "p=0.25");
   bernoulli_plotter.add(boost::math::bernoulli_distribution<>(0.5), "p=0.5");
   bernoulli_plotter.add(boost::math::bernoulli_distribution<>(0.75), "p=0.75");
   bernoulli_plotter.plot("Bernoulli Distribution PDF", "bernoulli_pdf.svg");

   distribution_plotter<boost::math::bernoulli_distribution<> >
      bernoulli_cdf_plotter(false);
   bernoulli_cdf_plotter.add(boost::math::bernoulli_distribution<>(0.25), "p=0.25");
   bernoulli_cdf_plotter.add(boost::math::bernoulli_distribution<>(0.5), "p=0.5");
   bernoulli_cdf_plotter.add(boost::math::bernoulli_distribution<>(0.75), "p=0.75");
   bernoulli_cdf_plotter.plot("Bernoulli Distribution CDF", "bernoulli_cdf.svg");

   distribution_plotter<boost::math::binomial_distribution<> >
      binomial_plotter;
   binomial_plotter.add(boost::math::binomial_distribution<>(5, 0.5), "n=5 p=0.5");
   binomial_plotter.add(boost::math::binomial_distribution<>(20, 0.5), "n=20 p=0.5");
   binomial_plotter.add(boost::math::binomial_distribution<>(50, 0.5), "n=50 p=0.5");
   binomial_plotter.plot("Binomial Distribution PDF", "binomial_pdf_1.svg");

   distribution_plotter<boost::math::binomial_distribution<> >
      binomial_plotter2;
   binomial_plotter2.add(boost::math::binomial_distribution<>(20, 0.1), "n=20 p=0.1");
   binomial_plotter2.add(boost::math::binomial_distribution<>(20, 0.5), "n=20 p=0.5");
   binomial_plotter2.add(boost::math::binomial_distribution<>(20, 0.9), "n=20 p=0.9");
   binomial_plotter2.plot("Binomial Distribution PDF", "binomial_pdf_2.svg");

   distribution_plotter<boost::math::negative_binomial_distribution<> >
      negative_binomial_plotter;
   negative_binomial_plotter.add(boost::math::negative_binomial_distribution<>(20, 0.25), "n=20 p=0.25");
   negative_binomial_plotter.add(boost::math::negative_binomial_distribution<>(20, 0.5), "n=20 p=0.5");
   negative_binomial_plotter.add(boost::math::negative_binomial_distribution<>(20, 0.75), "n=20 p=0.75");
   negative_binomial_plotter.plot("Negative Binomial Distribution PDF", "negative_binomial_pdf_1.svg");

   distribution_plotter<boost::math::negative_binomial_distribution<> >
      negative_binomial_plotter2;
   negative_binomial_plotter2.add(boost::math::negative_binomial_distribution<>(10, 0.5), "n=10 p=0.5");
   negative_binomial_plotter2.add(boost::math::negative_binomial_distribution<>(20, 0.5), "n=20 p=0.5");
   negative_binomial_plotter2.add(boost::math::negative_binomial_distribution<>(70, 0.5), "n=70 p=0.5");
   negative_binomial_plotter2.plot("Negative Binomial Distribution PDF", "negative_binomial_pdf_2.svg");

   distribution_plotter<boost::math::poisson_distribution<> >
      poisson_plotter;
   poisson_plotter.add(boost::math::poisson_distribution<>(5), "λ=5");
   poisson_plotter.add(boost::math::poisson_distribution<>(10), "λ=10");
   poisson_plotter.add(boost::math::poisson_distribution<>(20), "λ=20");
   poisson_plotter.plot("Poisson Distribution PDF", "poisson_pdf_1.svg");

   distribution_plotter<boost::math::hypergeometric_distribution<> >
      hypergeometric_plotter;
   hypergeometric_plotter.add(boost::math::hypergeometric_distribution<>(30, 50, 500), "N=500, r=50, n=30");
   hypergeometric_plotter.add(boost::math::hypergeometric_distribution<>(30, 100, 500), "N=500, r=100, n=30");
   hypergeometric_plotter.add(boost::math::hypergeometric_distribution<>(30, 250, 500), "N=500, r=250, n=30");
   hypergeometric_plotter.add(boost::math::hypergeometric_distribution<>(30, 400, 500), "N=500, r=400, n=30");
   hypergeometric_plotter.add(boost::math::hypergeometric_distribution<>(30, 450, 500), "N=500, r=450, n=30");
   hypergeometric_plotter.plot("Hypergeometric Distribution PDF", "hypergeometric_pdf_1.svg");

   distribution_plotter<boost::math::hypergeometric_distribution<> >
      hypergeometric_plotter2;
   hypergeometric_plotter2.add(boost::math::hypergeometric_distribution<>(50, 50, 500), "N=500, r=50, n=50");
   hypergeometric_plotter2.add(boost::math::hypergeometric_distribution<>(100, 50, 500), "N=500, r=50, n=100");
   hypergeometric_plotter2.add(boost::math::hypergeometric_distribution<>(250, 50, 500), "N=500, r=50, n=250");
   hypergeometric_plotter2.add(boost::math::hypergeometric_distribution<>(400, 50, 500), "N=500, r=50, n=400");
   hypergeometric_plotter2.add(boost::math::hypergeometric_distribution<>(450, 50, 500), "N=500, r=50, n=450");
   hypergeometric_plotter2.plot("Hypergeometric Distribution PDF", "hypergeometric_pdf_2.svg");

}


#ifndef DLS_PERCEPTION_CAMERA_MARKER_TRANSFORM_HPP__
#define DLS_PERCEPTION_CAMERA_MARKER_TRANSFORM_HPP__

#include <opencv2/core.hpp>
#include <Eigen/Dense>

namespace dls {
namespace perception {

/**
 * @brief The CameraMarkerTransform class computes the full 3D Transform between
 * the camera frame and an aruco marker, given a single camera image.
 */
class CameraMarkerTransform {

public:
    typedef typename cv::Matx33d CameraMatrix;
    typedef typename cv::Vec<double,5> DistortionCoeff;
    typedef typename Eigen::Affine3d Transform;
    typedef typename cv::Mat Image;
    typedef std::vector<cv::Point2f> Corners;
    typedef std::vector<Corners> CornerList;

public:
    CameraMarkerTransform();

    void setCameraParameters(const CameraMatrix& camera_matrix,
                             const DistortionCoeff& distortion_coeff);

    bool getCameraMarkerTransform(const Image& image,
                                  Transform& cTm);

    CameraMarkerTransform(const CameraMatrix& camera_matrix,
                          const DistortionCoeff& distortion_coeff);

    void setDebug(const bool& debug);
    void setVerbose(const bool& verbose);

private:
    CameraMatrix camera_matrix_;
    DistortionCoeff distortion_coeff_;
    bool verbose_ = false;
    bool debug_ = false;

    Transform camera_marker_transform_ = Transform::Identity();
};

}
}

#endif // DLS_PERCEPTION_CAMERA_MARKER_TRANSFORM_HPP__


// ----------------------------------------------------------------------------
//                              Apache License
//                        Version 2.0, January 2004
//                     http://www.apache.org/licenses/
//
// This file is part of binapi(https://github.com/niXman/binapi) project.
//
// Copyright (c) 2019-2021 niXman (github dot nixman dog pm.me). All rights reserved.
// ----------------------------------------------------------------------------

#include <binapi/tools.hpp>
#include <binapi/pairslist.hpp>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/trim.hpp>

namespace binapi {

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

std::size_t num_fractions_from_double_type(const double_type &v) {
    if ( v == 1 ) return 1u;

    double_type r{v};
    std::size_t n = 0u;
    for ( ; r != 1; ++n ) {
        r *= 10;
    }

    return n;
}

double_type adjust_to_step(const double_type &v, const double_type &s, bool increase) {
    std::int64_t step1 = (v * 100000000).convert_to<std::int64_t>();
    std::int64_t step2 = step1 % (s * 100000000).convert_to<std::int64_t>();
    std::int64_t step3 = step1 - step2;
    double_type res    = double_type(step3) / 100000000;
    res += (increase ? s : 0.0);

    return res;
}

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

std::vector<std::string> split_string(const std::string &str, const char *sep) {
    std::vector<std::string> res{};

    boost::algorithm::split(res, str, boost::is_any_of(sep));
    for ( auto &it: res ) {
        boost::algorithm::trim(it);
    }

    return res;
}

std::string join_string(const std::vector<std::string> &vec, const char *sep) {
    return boost::algorithm::join(vec, sep);
}

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

double_type percents_diff(const double_type &a, const double_type &b) {
    if ( a == b ) return 0;

    return ((b - a) / a) * 100;
}

double_type percents_add(const double_type &v, const double_type &p) {
    if ( p == 0 ) return v;

    return v + ((v / 100) * p);
}

double_type percents_sub(const double_type &v, const double_type &p) {
    if ( p == 0 ) return v;

    return v - ((v / 100) * p);
}

double_type percents_val_by_percent(const double_type &v, const double_type &p) {
    return (v / 100) * p;
}

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

bool is_my_orderid(const char *client_order_id) {
    const char *start = client_order_id;
    const char *p = std::strchr(client_order_id, '-');
    if ( !p ) {
        return false;
    }

#define __STRCMP_CSTR(x) std::strncmp(start, x, sizeof(x)-1) == 0

    const auto len = p - start;
    switch ( len ) {
        case 3: return __STRCMP_CSTR("FIX");
        case 4: return __STRCMP_CSTR("SRSI");
        case 5: return __STRCMP_CSTR("AROON") || __STRCMP_CSTR("SLOSS") || __STRCMP_CSTR("TAKEP");
        case 6: return __STRCMP_CSTR("SRSI_U") || __STRCMP_CSTR("SRSI_D") || __STRCMP_CSTR("SRSI_C");
        case 7: return __STRCMP_CSTR("HOLEBUY") || __STRCMP_CSTR("INASELL");
        case 8: return __STRCMP_CSTR("CYCLEBUY") || __STRCMP_CSTR("SPREDBUY") || __STRCMP_CSTR("SLOSSBUY");
        default: return false;
    }

#undef __STRCMP_CSTR

    return false;
}

bool is_my_orderid(const std::string &client_order_id) {
    return is_my_orderid(client_order_id.c_str());
}

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

} // ns binapi


// Copyright (c) 2018 by University Paris-Est Marne-la-Vallee
// Constants.hpp
// This file is part of the Garamon for e3ga.
// Authors: Stephane Breuils and Vincent Nozick
// Contact: vincent.nozick@u-pem.fr
//
// Licence MIT
// A a copy of the MIT License is given along with this program

/// \file Constants.hpp
/// \author Stephane Breuils, Vincent Nozick
/// \brief Constant values and data related to the specified geometric algebra (e3ga)

// Doxygen
/// \version 0.1
/// \mainpage
/// \tableofcontents
/// \section instroduction_sec What for?
/// Garamon is a C++ library to represent an manipulate the geometric algebra objects.
/// \section install_bigsec How to install
/// \subsection dependencies_sec Dependecies
/// \li cmake (at least version 3.10)
/// \li Eigen (at least version 3.3.4)
/// \li Doxygen (if you want the documentation)
/// \subsection install_sec Install with cmake (Linux / MacOs)
/// \li go to garamon dir
/// \li mkdir build
/// \li cd build
/// \li cmake ..
/// \li make
/// \li (optional) sudo make install
/// \li (optional for documentation) make html
/// \li The documentation is located in [path to build]/doc/doc-doxygen/html/index.html

#ifndef E3GA_CONSTANTS_HPP__
#define E3GA_CONSTANTS_HPP__
#pragma once

#include <array>
#include <vector>
#include <utility>
#include <string>
#include <Eigen/Sparse>

#include "e3ga/Utility.hpp"
#include "e3ga/BasisTransformations.hpp"
#include "e3ga/DualCoefficients.hpp"

/*!
 * @namespace e3ga
 */
namespace e3ga{

    constexpr unsigned int algebraDimension = 3; /*!< dimension of the algebra (number of  basis vectors of grade 1) */

    constexpr unsigned int perGradeStartingIndex[4] = {0,1,4,7};  /*!< array specifying the index of each first element of grade k in the full multivector */

    constexpr unsigned int binomialArray[4] = {1,3,3,1};  /*!< array of the (dimension + 1) first binomial coefficients */

    constexpr unsigned int xorIndexToGrade[] = {0,1,1,2,1,2,2,3}; /*!< given a Xor index in a multivector, this array indicates the corresponding grade*/

    constexpr unsigned int xorIndexToHomogeneousIndex[] = {0,0,1,0,2,1,2,0}; /*!< given a Xor index in a multivector, this array indicates the corresponding index in the whole homogeneous vector*/

//    std::array<std::vector<unsigned int>, 4> dualPermutations = {{ { 0}, {{ 2, 1, 0}}, {{ 2, 1, 0}}, {0} }};

    const std::array<Eigen::Matrix<double, Eigen::Dynamic,1>, 4> dualCoefficients = loadFastDualArray<double>(); /*!< array containing the coefficients needed to compute the dual */

    template<typename T>
    std::array<T, 8> recursiveDualCoefficients = {{ 1.000000, 1.000000, -1.000000, -1.000000, 1.000000, 1.000000, -1.000000, 1.000000}}; /*!< array containing the coefficients needed to compute the recursive product like (primal^dual) */

    constexpr double pseudoScalarInverse = -1.000000; /*!< compute the inverse of the pseudo scalar */

    const int signReversePerGrade[4] = {1,1,-1,-1}; /*!< array of signs to avoid the computation of (-1)^k*(k-1)/2 during the reverse operation */

    const std::vector<std::string> basisVectors = {"1", "2", "3"}; /*!< name of the basis vectors (of grade 1) */

    const std::string metric =
"\
	e1	e2	e3	\n\
e1	1	0	0	\n\
e2	0	1	0	\n\
e3	0	0	1	\n\
"; /*!< metric / quadratic form of the algebra (inner product between basis vectors) */

    template<class T>
    const T zero = 0;

    const unsigned int scalar = 0;
    const unsigned int E1 = 1;
    const unsigned int E2 = 2;
    const unsigned int E3 = 4;
    const unsigned int E12 = 3;
    const unsigned int E13 = 5;
    const unsigned int E23 = 6;
    const unsigned int E123 = 7;
    /*!< defines the constants for the cga */

    template<typename T>
    Eigen::Matrix<T, Eigen::Dynamic, 1> diagonalMetric = []()->Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>{Eigen::Matrix<T, Eigen::Dynamic, 1> tmp(3);tmp<<1.000000,1.000000,1.000000; return tmp;}();   /*!< defines the diagonal metric (stored as a vector) */

}  // namespace

#endif // E3GA_CONSTANTS_HPP__


#include "stdafx.h"
#include "VectorProcessor.h"
#include <algorithm>
#include <numeric>
#include <functional>
#include <boost/range/algorithm/transform.hpp>
#pragma warning (push, 3)
#include <boost/phoenix.hpp>
#pragma warning (pop)

using namespace std;
using namespace std::placeholders;
using namespace boost::phoenix::placeholders;
using namespace boost::phoenix;
using boost::transform;

void ProcessVector(std::vector<double> & numbers)
{
	if (!numbers.empty())
	{
		double minNum = numbers[0];

		double minNum2 = *(std::min_element(numbers.begin(), numbers.end()));
		boost::transform(numbers, numbers.begin(), arg1 * minNum2);
		sort(numbers.begin(), numbers.end());
	}
}


#pragma once

#include <Eigen/Core>

#include <ipc/broad_phase/collision_candidate.hpp>

namespace ipc {

/// Find all static collisions in one time step using brute-force.
void detect_collision_candidates_brute_force(
    const Eigen::MatrixXd& V,
    const Eigen::MatrixXi& E,
    const Eigen::MatrixXi& F,
    Candidates& candidates,
    bool detect_edge_vertex = false,
    bool detect_edge_edge = true,
    bool detect_face_vertex = true,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_edge_vertex_collision_candidates_brute_force(
    const Eigen::MatrixXd& V,
    const Eigen::MatrixXi& E,
    std::vector<EdgeVertexCandidate>& ev_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_edge_edge_collision_candidates_brute_force(
    const Eigen::MatrixXd& V,
    const Eigen::MatrixXi& E,
    std::vector<EdgeEdgeCandidate>& ee_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_face_vertex_collision_candidates_brute_force(
    const Eigen::MatrixXd& V,
    const Eigen::MatrixXi& F,
    std::vector<FaceVertexCandidate>& fv_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_edge_face_collision_candidates_brute_force(
    const Eigen::MatrixXd& V,
    const Eigen::MatrixXi& E,
    const Eigen::MatrixXi& F,
    std::vector<EdgeFaceCandidate>& ef_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

/// Find all continous collisions in one time step using brute-force.
void detect_collision_candidates_brute_force(
    const Eigen::MatrixXd& V0,
    const Eigen::MatrixXd& V1,
    const Eigen::MatrixXi& E,
    const Eigen::MatrixXi& F,
    Candidates& candidates,
    bool detect_edge_vertex = false,
    bool detect_edge_edge = true,
    bool detect_face_vertex = true,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_edge_vertex_collision_candidates_brute_force(
    const Eigen::MatrixXd& V0,
    const Eigen::MatrixXd& V1,
    const Eigen::MatrixXi& E,
    std::vector<EdgeVertexCandidate>& ev_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_edge_edge_collision_candidates_brute_force(
    const Eigen::MatrixXd& V0,
    const Eigen::MatrixXd& V1,
    const Eigen::MatrixXi& E,
    std::vector<EdgeEdgeCandidate>& ee_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

void detect_face_vertex_collision_candidates_brute_force(
    const Eigen::MatrixXd& V0,
    const Eigen::MatrixXd& V1,
    const Eigen::MatrixXi& F,
    std::vector<FaceVertexCandidate>& fv_candidates,
    bool perform_aabb_check = false,
    double aabb_inflation_radius = 0,
    const std::function<bool(size_t, size_t)>& can_collide =
        [](size_t, size_t) { return true; });

} // namespace ipc


//==================================================================================================
/*!
  @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)
*/
//==================================================================================================
#include <boost/simd/pack.hpp>
#include <boost/simd/function/clz.hpp>
#include <boost/simd/function/max.hpp>
#include <boost/simd/meta/cardinal_of.hpp>
#include <simd_test.hpp>
#include <boost/simd/detail/dispatch/meta/as_integer.hpp>
#include <boost/simd/constant/inf.hpp>
#include <boost/simd/constant/minf.hpp>
#include <boost/simd/constant/mone.hpp>
#include <boost/simd/constant/nan.hpp>
#include <boost/simd/constant/one.hpp>
#include <boost/simd/constant/zero.hpp>
#include <boost/simd/constant/signmask.hpp>
#include <boost/simd/constant/valmax.hpp>

template <typename T, std::size_t N, typename Env>
void test(Env& $)
{
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;
  using p_t = bs::pack<T, N>;
  using iT =  bd::as_integer_t<T>;
  using i_t=  bs::pack<iT, N>;

  T a1[N];
  iT b[N];
  for(std::size_t i = 0; i < N; ++i)
  {
    a1[i] = i == 0 ? T(1) : T(bs::max(T(a1[i-1]*3), T(1)));
    b[i] = bs::clz(a1[i]);
   }
  p_t aa1(&a1[0], &a1[0]+N);
  i_t bb(&b[0], &b[0]+N);
  STF_EQUAL(bs::clz(aa1), bb);
}

STF_CASE_TPL("Check clz on pack", STF_NUMERIC_TYPES)
{
  namespace bs = boost::simd;
  using p_t = bs::pack<T>;
  static const std::size_t N = bs::cardinal_of<p_t>::value;
  test<T, N>($);
   test<T, N/2>($);
   test<T, N*2>($);
}

STF_CASE_TPL (" clz real",  STF_IEEE_TYPES)
{
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;

  using bs::clz;
  using p_t = bs::pack<T>;
  using r_t = decltype(clz(p_t()));

  // return type conformity test
  STF_TYPE_IS(r_t, bd::as_integer_t<p_t>);

  // specific values tests
#ifndef BOOST_SIMD_NO_INVALIDS
  STF_EQUAL(clz(bs::Nan<p_t>()), bs::Zero<r_t>());
#endif
  STF_EQUAL(clz(bs::Mone<p_t>()), bs::Zero<r_t>());
  STF_EQUAL(clz(bs::Signmask<p_t>()),bs::Zero<r_t>());
} // end of test for real_

STF_CASE_TPL (" clz signed_int",  STF_SIGNED_INTEGRAL_TYPES)
{
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;

  using bs::clz;
  using p_t = bs::pack<T>;
  using r_t = decltype(clz(p_t()));

  // return type conformity test
  STF_TYPE_IS(r_t, bd::as_integer_t<p_t>);

  // specific values tests
  STF_EQUAL(clz(bs::One<p_t>()), r_t(sizeof(T)*8 -1));
  STF_EQUAL(clz(bs::Signmask<p_t>()), bs::Zero<r_t>());
} // end of test for signed_int_

 STF_CASE_TPL (" clz unsigned_int",  STF_UNSIGNED_INTEGRAL_TYPES)
 {
  namespace bs = boost::simd;
  namespace bd = boost::dispatch;

  using bs::clz;
  using p_t = bs::pack<T>;
  using r_t = decltype(clz(p_t()));

  // return type conformity test
  STF_TYPE_IS(r_t, bd::as_integer_t<p_t>);

  // specific values tests
  STF_EQUAL(clz(bs::One<p_t>()),  r_t(sizeof(T)*8-bs::One<r_t>()));

  T j = 1;
  for(int i=1; i < bs::Valmax<char>(); i*= 2)
    {
      STF_EQUAL(clz(p_t(i)),r_t(sizeof(T)*8- T(j)));
      ++j;
    }
 } // end of test for unsigned_int_


//
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
//
// 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 <boost/gil/algorithm.hpp>
#include <boost/gil/gray.hpp>
#include <boost/gil/image_processing/threshold.hpp>
#include <boost/gil/image_view.hpp>

#include <boost/core/lightweight_test.hpp>

namespace gil = boost::gil;

int height = 2;
int width = 2;

gil::gray8_image_t original_gray(width, height), otsu_gray(width, height),
    expected_gray(width, height);

gil::rgb8_image_t original_rgb(width, height), otsu_rgb(width, height),
    expected_rgb(width, height);

void fill_gray() {
  gil::view(original_gray)(0, 0) = gil::gray8_pixel_t(56);
  gil::view(original_gray)(1, 0) = gil::gray8_pixel_t(89);
  gil::view(original_gray)(0, 1) = gil::gray8_pixel_t(206);
  gil::view(original_gray)(1, 1) = gil::gray8_pixel_t(139);
}

void fill_rgb() {
  gil::view(original_rgb)(0, 0) = gil::rgb8_pixel_t(15, 158, 150);
  gil::view(original_rgb)(1, 0) = gil::rgb8_pixel_t(200, 175, 150);
  gil::view(original_rgb)(0, 1) = gil::rgb8_pixel_t(230, 170, 150);
  gil::view(original_rgb)(1, 1) = gil::rgb8_pixel_t(25, 248, 150);
}

void test_gray_regular() {
  gil::view(expected_gray)(0, 0) = gil::gray8_pixel_t(0);
  gil::view(expected_gray)(1, 0) = gil::gray8_pixel_t(0);
  gil::view(expected_gray)(0, 1) = gil::gray8_pixel_t(255);
  gil::view(expected_gray)(1, 1) = gil::gray8_pixel_t(255);

  gil::threshold_optimal(gil::view(original_gray), gil::view(otsu_gray),
                         gil::threshold_optimal_value::otsu);

  BOOST_TEST(gil::equal_pixels(gil::view(otsu_gray), gil::view(expected_gray)));
}

void test_gray_inverse() {
  gil::view(expected_gray)(0, 0) = gil::gray8_pixel_t(255);
  gil::view(expected_gray)(1, 0) = gil::gray8_pixel_t(255);
  gil::view(expected_gray)(0, 1) = gil::gray8_pixel_t(0);
  gil::view(expected_gray)(1, 1) = gil::gray8_pixel_t(0);

  gil::threshold_optimal(gil::view(original_gray), gil::view(otsu_gray),
                         gil::threshold_optimal_value::otsu,
                         gil::threshold_direction::inverse);

  BOOST_TEST(gil::equal_pixels(gil::view(otsu_gray), gil::view(expected_gray)));
}

void test_rgb_regular() {
  gil::view(expected_rgb)(0, 0) = gil::rgb8_pixel_t(0, 0, 255);
  gil::view(expected_rgb)(1, 0) = gil::rgb8_pixel_t(255, 0, 255);
  gil::view(expected_rgb)(0, 1) = gil::rgb8_pixel_t(255, 0, 255);
  gil::view(expected_rgb)(1, 1) = gil::rgb8_pixel_t(0, 255, 255);

  gil::threshold_optimal(gil::view(original_rgb), gil::view(otsu_rgb),
                         gil::threshold_optimal_value::otsu);

  BOOST_TEST(gil::equal_pixels(gil::view(otsu_rgb), gil::view(expected_rgb)));
}

void test_rgb_inverse() {
  gil::view(expected_rgb)(0, 0) = gil::rgb8_pixel_t(255, 255, 0);
  gil::view(expected_rgb)(1, 0) = gil::rgb8_pixel_t(0, 255, 0);
  gil::view(expected_rgb)(0, 1) = gil::rgb8_pixel_t(0, 255, 0);
  gil::view(expected_rgb)(1, 1) = gil::rgb8_pixel_t(255, 0, 0);

  gil::threshold_optimal(gil::view(original_rgb), gil::view(otsu_rgb),
                         gil::threshold_optimal_value::otsu,
                         gil::threshold_direction::inverse);

  BOOST_TEST(gil::equal_pixels(gil::view(otsu_rgb), gil::view(expected_rgb)));
}

int main() {
  fill_gray();
  fill_rgb();

  test_gray_regular();
  test_gray_inverse();
  test_rgb_regular();
  test_rgb_inverse();

  return boost::report_errors();
}


/*
  [auto_generated]
  libs/numeric/odeint/test/dummy_boost_units.hpp

  [begin_description]
  tba.
  [end_description]

  Copyright 2009-2012 Karsten Ahnert
  Copyright 2009-2012 Mario Mulansky

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE_1_0.txt or
  copy at http://www.boost.org/LICENSE_1_0.txt)
*/

#ifndef LIBS_NUMERIC_ODEINT_TEST_DUMMY_BOOST_UNITS_HPP_DEFINED
#define LIBS_NUMERIC_ODEINT_TEST_DUMMY_BOOST_UNITS_HPP_DEFINED

#include <boost/units/systems/si/length.hpp>
#include <boost/units/systems/si/time.hpp>
#include <boost/units/systems/si/velocity.hpp>
#include <boost/units/systems/si/acceleration.hpp>
#include <boost/units/systems/si/io.hpp>

#include <boost/fusion/container.hpp>

typedef double value_type;
typedef boost::units::quantity< boost::units::si::time , value_type > time_type;
typedef boost::units::quantity< boost::units::si::length , value_type > length_type;
typedef boost::units::quantity< boost::units::si::velocity , value_type > velocity_type;
typedef boost::units::quantity< boost::units::si::acceleration , value_type > acceleration_type;

struct oscillator_mom_func_units
{
    template< class Coor , class MomDeriv >
    void operator()( const Coor &q , MomDeriv &dp ) const
    {
        const boost::units::quantity< boost::units::si::frequency , value_type > omega = 1.0 * boost::units::si::hertz;
        boost::fusion::at_c< 0 >( dp ) = - omega * omega * boost::fusion::at_c< 0 >( q );
    }
};

struct oscillator_coor_func_units
{
    template< class Mom , class CoorDeriv >
    void operator()( const Mom &p , CoorDeriv &dq ) const
    {
        boost::fusion::at_c< 0 >( dq ) = boost::fusion::at_c< 0 >( p );
    }
};

#endif // LIBS_NUMERIC_ODEINT_TEST_DUMMY_BOOST_UNITS_HPP_DEFINED


#ifndef BOOST_HASH2_DETAIL_ROT_HPP_INCLUDED
#define BOOST_HASH2_DETAIL_ROT_HPP_INCLUDED

// Copyright 2017, 2018 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.

#include <boost/hash2/byte_type.hpp>
#include <boost/cstdint.hpp>
#include <boost/config.hpp>
#include <cstring>
#include <cstdlib>

namespace boost
{
namespace hash2
{
namespace detail
{

#if defined( _MSC_VER )

BOOST_FORCEINLINE boost::uint32_t rotl( boost::uint32_t v, int k )
{
    return _rotl( v, k );
}

BOOST_FORCEINLINE boost::uint64_t rotl( boost::uint64_t v, int k )
{
    return _rotl64( v, k );
}

#else

// k must not be 0
BOOST_FORCEINLINE boost::uint32_t rotl( boost::uint32_t v, int k )
{
    return ( v << k ) + ( v >> ( 32 - k ) );
}

// k must not be 0
BOOST_FORCEINLINE boost::uint64_t rotl( boost::uint64_t v, int k )
{
    return ( v << k ) + ( v >> ( 64 - k ) );
}

#endif

} // namespace detail
} // namespace hash2
} // namespace boost

#endif // #ifndef BOOST_HASH2_DETAIL_ROT_HPP_INCLUDED


/* boost random/uniform_real.hpp header file
 *
 * Copyright Jens Maurer 2000-2001
 * 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)
 *
 * See http://www.boost.org for most recent version including documentation.
 *
 * $Id: uniform_real.hpp 41369 2007-11-25 18:07:19Z bemandawes $
 *
 * Revision history
 *  2001-04-08  added min<max assertion (N. Becker)
 *  2001-02-18  moved to individual header files
 */

#ifndef BOOST_RANDOM_UNIFORM_REAL_HPP
#define BOOST_RANDOM_UNIFORM_REAL_HPP

#include <cassert>
#include <iostream>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>

namespace boost {

// uniform distribution on a real range
template<class RealType = double>
class uniform_real
{
public:
  typedef RealType input_type;
  typedef RealType result_type;

  explicit uniform_real(RealType min_arg = RealType(0),
                        RealType max_arg = RealType(1))
    : _min(min_arg), _max(max_arg)
  {
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
#endif
    assert(min_arg < max_arg);
  }

  // compiler-generated copy ctor and assignment operator are fine

  result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
  result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
  void reset() { }

  template<class Engine>
  result_type operator()(Engine& eng) {
    return static_cast<result_type>(eng() - eng.min BOOST_PREVENT_MACRO_SUBSTITUTION())
           / static_cast<result_type>(eng.max BOOST_PREVENT_MACRO_SUBSTITUTION() - eng.min BOOST_PREVENT_MACRO_SUBSTITUTION())
           * (_max - _min) + _min;
  }

#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  template<class CharT, class Traits>
  friend std::basic_ostream<CharT,Traits>&
  operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_real& ud)
  {
    os << ud._min << " " << ud._max;
    return os;
  }

  template<class CharT, class Traits>
  friend std::basic_istream<CharT,Traits>&
  operator>>(std::basic_istream<CharT,Traits>& is, uniform_real& ud)
  {
    is >> std::ws >> ud._min >> std::ws >> ud._max;
    return is;
  }
#endif

private:
  RealType _min, _max;
};

} // namespace boost

#endif // BOOST_RANDOM_UNIFORM_REAL_HPP


#include <yaml-cpp/yaml.h>

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

#include "NumpySaver.hpp"

int main(int argc, char const *argv[]) {
  YAML::Node config = YAML::LoadFile("config.yaml");

  Eigen::ArrayXd array;
  std::string name;

  if (config["dim"] && config["name"]) {
    array = Eigen::ArrayXd::LinSpaced(config["dim"].as<int>(), 0, 10);
    name = config["name"].as<std::string>();
  } else {
    throw std::range_error("Config file must include 'dim_x' and 'dim_y'.");
  }

  NumpySaver("build/output/" + name + ".npy")
      << "This is a test array" << array << (array * array * 2 + 10.);

  std::cout << "build/output/test.npy saved!";

  return 0;
}


#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Poly2triTest
#include <boost/test/unit_test.hpp>
#include <poly2tri/poly2tri.h>
#include <fstream>
#include <iostream>
#include <iterator>

BOOST_AUTO_TEST_CASE(BasicTest)
{
  std::vector<p2t::Point*> polyline{
    new p2t::Point(0, 0),
    new p2t::Point(1, 0),
    new p2t::Point(1, 1),
  };
  p2t::CDT cdt{ polyline };
  cdt.Triangulate();
  const auto result = cdt.GetTriangles();
  BOOST_REQUIRE_EQUAL(result.size(), 1);
  BOOST_CHECK_EQUAL(*result[0]->GetPoint(0), *polyline[0]);
  BOOST_CHECK_EQUAL(*result[0]->GetPoint(1), *polyline[1]);
  BOOST_CHECK_EQUAL(*result[0]->GetPoint(2), *polyline[2]);
  BOOST_CHECK(p2t::IsDelaunay(result));
  for (const auto p : polyline) {
    delete p;
  }
}

BOOST_AUTO_TEST_CASE(QuadTest)
{
  std::vector<p2t::Point*> polyline{ new p2t::Point(0, 0), new p2t::Point(0, 1),
                                     new p2t::Point(1, 1), new p2t::Point(1, 0) };
  p2t::CDT cdt{ polyline };
  cdt.Triangulate();
  const auto result = cdt.GetTriangles();
  BOOST_REQUIRE_EQUAL(result.size(), 2);
  BOOST_CHECK(p2t::IsDelaunay(result));
  for (const auto p : polyline) {
    delete p;
  }
}

BOOST_AUTO_TEST_CASE(TestbedFilesTest)
{
  for (const auto& filename : { "custom.dat", "diamond.dat", "star.dat", "test.dat" }) {
    std::vector<p2t::Point*> polyline;
    // Load pointset from file
    // Parse and tokenize data file
    std::string line;
    const std::string src(__FILE__); // ../unittest/main.cpp
    auto folder = src.substr(0, src.find_last_of('/')) + "/../testbed/data/";
    std::ifstream myfile(folder + filename);
    BOOST_REQUIRE(myfile.is_open());
    while (!myfile.eof()) {
      getline(myfile, line);
      if (line.empty()) {
        break;
      }
      std::istringstream iss(line);
      std::vector<std::string> tokens;
      copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
           std::back_inserter<std::vector<std::string>>(tokens));
      double x = std::stod(tokens[0]);
      double y = std::stod(tokens[1]);
      polyline.push_back(new p2t::Point(x, y));
    }
    p2t::CDT cdt{ polyline };
    cdt.Triangulate();
    const auto result = cdt.GetTriangles();
    BOOST_REQUIRE(result.size() * 3 > polyline.size());
    BOOST_CHECK_MESSAGE(p2t::IsDelaunay(result), filename + std::to_string(polyline.size()));
    for (const auto p : polyline) {
      delete p;
    }
  }
}


#include "processor.h"

#include <armadillo>

#include "linux_parser.h"

float Processor::Utilization() {
long unsigned totalJiffiesStart = LinuxParser::Jiffies();
long unsigned activeJiffiesStart = LinuxParser::ActiveJiffies();

usleep(10000); // microseconds --> 10 milliseconds

long unsigned totalJiffiesEnd = LinuxParser::Jiffies();
long unsigned activeJiffiesEnd = LinuxParser::ActiveJiffies();

long totalDelta = totalJiffiesEnd - totalJiffiesStart;
long activeDelta = activeJiffiesEnd - activeJiffiesStart;

if (totalDelta != 0) {
  return activeDelta / (1.0f * totalDelta);  // float conversion
}
return 0.0;
}


#include "../common/range_tools.hpp"

#include "util/permutation.hpp"

#include <boost/test/unit_test.hpp>

#include <algorithm>
#include <numeric>
#include <random>

BOOST_AUTO_TEST_SUITE(permutation_test)

using namespace osrm;
using namespace osrm::util;

BOOST_AUTO_TEST_CASE(basic_permuation)
{
    // cycles (0 3 2 1 4 8) (5) (6 9 7)
    //                                            0  1  2  3  4  5  6  7   8   9
    std::vector<std::uint32_t> values{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    const std::vector<std::uint32_t> permutation{3, 4, 1, 2, 8, 5, 9, 6, 0, 7};
    std::vector<std::uint32_t> reference{9, 3, 4, 1, 2, 6, 8, 10, 5, 7};

    inplacePermutation(values.begin(), values.end(), permutation);

    CHECK_EQUAL_COLLECTIONS(values, reference);
}

BOOST_AUTO_TEST_SUITE_END()


#include <iostream>
#include <Eigen/Core>

int main() {
    std::cout << "Hello from Fenix!" << std::endl;
    Eigen::Vector3d vector(1, 3, 9);
    std::cout << "vector:" << vector << std::endl;
    vector /= 3.0;
    std::cout << "normalized vector:" << vector << std::endl;
}


/*!
@file
Defines `boost::hana::SearchableSet`.

@copyright Louis Dionne 2014
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_HANA_SANDBOX_SEARCHABLE_SET_HPP
#define BOOST_HANA_SANDBOX_SEARCHABLE_SET_HPP

#include <boost/hana/applicative/mcd.hpp>
#include <boost/hana/comparable/equal_mcd.hpp>
#include <boost/hana/core/datatype.hpp>
#include <boost/hana/detail/constexpr.hpp>
#include <boost/hana/functor/fmap_mcd.hpp>
#include <boost/hana/logical/logical.hpp>
#include <boost/hana/maybe.hpp>
#include <boost/hana/monad/flatten_mcd.hpp>

namespace boost { namespace hana {
    //! @ingroup group-datatypes
    //! A `Monad` for searching infinite sets in finite time.
    //!
    //! Taken from http://math.andrej.com/2008/11/21/a-haskell-monad-for-infinite-search-in-finite-time/.
    struct SearchableSet;

    template <typename Find, typename = operators<Comparable, Monad>>
    struct _sset {
        Find find;
        using hana_datatype = SearchableSet;
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto searchable_set = [](auto pred) {
        return _sset<decltype(pred)>{pred};
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto search = [](auto set, auto pred) {
        auto x = set.find(pred);
        return if_(pred(x), just(x), nothing);
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto forsome = [](auto set, auto pred) {
        return pred(set.find(pred));
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto forall = [](auto set, auto pred) {
        return not_(forsome(set, [=](auto x) { return not_(pred(x)); }));
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto contains = [](auto element, auto set) {
        return forsome(set, [=](auto x) { return equal(x, element); });
    };

    // Whether xs is a subset of ys.
    BOOST_HANA_CONSTEXPR_LAMBDA auto subset = [](auto xs, auto ys) {
        return forall(xs, [=](auto x) { return contains(x, ys); });
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto singleton = [](auto x) {
        return searchable_set([=](auto p) { return x; });
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto doubleton = [](auto x, auto y) {
        return searchable_set([=](auto p) {
            return if_(p(x), x, y);
        });
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto image = [](auto f, auto set) {
        return searchable_set([=](auto q) {
            return f(set.find([=](auto x) { return q(f(x)); }));
        });
    };

    BOOST_HANA_CONSTEXPR_LAMBDA auto union_ = [](auto xs, auto ys) {
        return flatten(doubleton(xs, ys));
    };

    template <>
    struct Comparable::instance<SearchableSet, SearchableSet>
        : Comparable::equal_mcd
    {
        template <typename Xs, typename Ys>
        static constexpr auto equal_impl(Xs xs, Ys ys)
        { return and_(subset(xs, ys), subset(ys, xs)); }
    };

    template <>
    struct Functor::instance<SearchableSet> : Functor::fmap_mcd {
        template <typename F, typename Set>
        static constexpr auto fmap_impl(F f, Set set)
        { return image(f, set); }
    };

    template <>
    struct Applicative::instance<SearchableSet> : Applicative::mcd {
        template <typename X>
        static constexpr auto lift_impl(X x)
        { return singleton(x); }

        template <typename F, typename Set>
        static constexpr auto ap_impl(F fset, Set set) {
            return flatten(image(
                [=](auto f) { return image(f, set); },
                fset
            ));
        }
    };

    template <>
    struct Monad::instance<SearchableSet> : Monad::flatten_mcd<SearchableSet> {
        template <typename SSet>
        static constexpr auto flatten_impl(SSet sset) {
            return searchable_set([=](auto p) {
                return sset.find([=](auto set) {
                    return forsome(set, p);
                }).find(p);
            });
        }
    };
}} // end namespace boost::hana

#endif // !BOOST_HANA_SANDBOX_SEARCHABLE_SET_HPP


#pragma once

#include <gpusim/util_func.h>
#include <gtest/gtest.h>

#include <Eigen/Core>

#include "../util/util.hpp"

static Eigen::VectorXcd copy_cpu_from_gpu(
    void* gpu_state, ITYPE dim, void* cuda_stream, UINT device_number) {
    CPPCTYPE* cpu_state = (CPPCTYPE*)malloc(sizeof(CPPCTYPE) * dim);
    Eigen::VectorXcd state(dim);
    get_quantum_state_host(
        gpu_state, cpu_state, dim, cuda_stream, device_number);
    for (ITYPE i = 0; i < dim; ++i) state[i] = cpu_state[i];
    free(cpu_state);
    return state;
}
static void state_equal_gpu(void* state, const Eigen::VectorXcd& test_state,
    ITYPE dim, std::string gate_string, void* cuda_stream, UINT device_number) {
    const double eps = 1e-14;
    Eigen::VectorXcd vec =
        copy_cpu_from_gpu(state, dim, cuda_stream, device_number);
    for (ITYPE ind = 0; ind < dim; ++ind) {
        ASSERT_NEAR(abs(vec[ind] - test_state[ind]), 0, eps)
            << gate_string << " at " << ind << std::endl
            << "Eigen : " << test_state.transpose() << std::endl
            << "GPUSIM : "
            << copy_cpu_from_gpu(state, dim, cuda_stream, device_number)
            << std::endl;
    }
}


//
// Test for BOOST_TEST_WITH
//
// Copyright (c) 2020 Bjorn Reese
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/core/lightweight_test.hpp>
#include <cmath>

template <typename T>
struct with_tolerance
{
    with_tolerance(T tolerance) : tolerance(tolerance) {}
    bool operator()(T lhs, T rhs) const
    {
        return (std::abs(lhs - rhs) <= tolerance);
    }

private:
    T tolerance;
};

void test_tolerance_predicate()
{
    BOOST_TEST_WITH( 1.0, 1.0, with_tolerance<double>(1e-5) );
    BOOST_TEST_WITH( 1.0, 1.0 - 1e-6, with_tolerance<double>(1e-5) );
    BOOST_TEST_WITH( 1.0, 1.0 + 1e-6, with_tolerance<double>(1e-5) );
}

int main()
{
    test_tolerance_predicate();

    return boost::report_errors();
}