#include "DataStore.h"
#include <Eigen/Dense>
using namespace Eigen;

DataStore::DataStore()
{
	float_data.resize(1, 1);
	string_data.resize(1, 1);
}

DataStore::DataStore(Matrix<double, 1, Dynamic> data)
{
	store(data);
}

DataStore::DataStore(Matrix<std::string, 1, Dynamic> data)
{
	store(data);
}

void DataStore::store(Matrix<double, 1, Dynamic> data)
{
	data_type = "number";
	float_data = data;
	type = 1;
}

void DataStore::store(Matrix<std::string, 1, Dynamic> data)
{
	data_type = "string";
	string_data = data;
	type = 2;
}

std::string DataStore::GetType()
{
	return data_type;
}

void DataStore::AddData(float data)
{
	//float_data.conservativeResize(len + 1);
	len++;
	float_data[len - 1] = data;
}

void DataStore::AddData(double data)
{
	//float_data.conservativeResize(len + 1);
	len++;
	float_data[len - 1] = data;
}

void DataStore::AddData(std::string data)
{
	//string_data.conservativeResize(len + 1);
	len++;
	string_data[len - 1] = data;
}

void DataStore::GetData(Matrix<double, 1, Dynamic> &load)
{
	load = float_data;
}

void DataStore::GetData(Matrix<std::string, 1, Dynamic> &load)
{
	load = string_data;
}

void DataStore::resize(int num)
{
	float_data.resize(1, num);
	string_data.resize(1, num);
}

void DataStore::GetByIndex(Index index, double &load)
{
	load = float_data(index);
}

void DataStore::GetByIndex(Index index, std::string &load)
{
	load = string_data(index);
}


#include <sstream>
#include <iostream>
#include <vector>
#include <cassert>
#include <cmath>

#include "config.h"
#ifdef HAVE_MPI
#include <boost/mpi/timer.hpp>
#include <boost/mpi.hpp>
namespace mpi = boost::mpi;
#endif

#include <boost/shared_ptr.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "sentence_metadata.h"
#include "cllh_observer.h"
#include "verbose.h"
#include "hg.h"
#include "prob.h"
#include "inside_outside.h"
#include "ff_register.h"
#include "decoder.h"
#include "filelib.h"
#include "stringlib.h"
#include "optimize.h"
#include "fdict.h"
#include "weights.h"
#include "sparse_vector.h"

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

bool InitCommandLine(int argc, char** argv, po::variables_map* conf) {
  po::options_description opts("Configuration options");
  opts.add_options()
        ("input_weights,w",po::value<string>(),"Input feature weights file")
        ("training_data,t",po::value<string>(),"Training data")
        ("test_data,T",po::value<string>(),"(optional) test data")
        ("decoder_config,c",po::value<string>(),"Decoder configuration file")
        ("output_weights,o",po::value<string>()->default_value("-"),"Output feature weights file")
        ("optimization_method,m", po::value<string>()->default_value("lbfgs"), "Optimization method (sgd, lbfgs, rprop)")
	("correction_buffers,M", po::value<int>()->default_value(10), "Number of gradients for LBFGS to maintain in memory")
        ("gaussian_prior,p","Use a Gaussian prior on the weights")
        ("sigma_squared", po::value<double>()->default_value(1.0), "Sigma squared term for spherical Gaussian prior")
        ("means,u", po::value<string>(), "(optional) file containing the means for Gaussian prior");
  po::options_description clo("Command line options");
  clo.add_options()
        ("config", po::value<string>(), "Configuration file")
        ("help,h", "Print this help message and exit");
  po::options_description dconfig_options, dcmdline_options;
  dconfig_options.add(opts);
  dcmdline_options.add(opts).add(clo);

  po::store(parse_command_line(argc, argv, dcmdline_options), *conf);
  if (conf->count("config")) {
    ifstream config((*conf)["config"].as<string>().c_str());
    po::store(po::parse_config_file(config, dconfig_options), *conf);
  }
  po::notify(*conf);

  if (conf->count("help") || !conf->count("input_weights") || !(conf->count("training_data")) || !conf->count("decoder_config")) {
    cerr << dcmdline_options << endl;
    return false;
  }
  return true;
}

void ReadTrainingCorpus(const string& fname, int rank, int size, vector<string>* c) {
  ReadFile rf(fname);
  istream& in = *rf.stream();
  string line;
  int lc = 0;
  while(in) {
    getline(in, line);
    if (!in) break;
    if (lc % size == rank) c->push_back(line);
    ++lc;
  }
}

static const double kMINUS_EPSILON = -1e-6;

struct TrainingObserver : public DecoderObserver {
  void Reset() {
    acc_grad.clear();
    acc_obj = 0;
    total_complete = 0;
    trg_words = 0;
  }

  void SetLocalGradientAndObjective(vector<double>* g, double* o) const {
    *o = acc_obj;
    for (SparseVector<prob_t>::const_iterator it = acc_grad.begin(); it != acc_grad.end(); ++it)
      (*g)[it->first] = it->second.as_float();
  }

  virtual void NotifyDecodingStart(const SentenceMetadata&) {
    cur_model_exp.clear();
    cur_obj = 0;
    state = 1;
  }

  // compute model expectations, denominator of objective
  virtual void NotifyTranslationForest(const SentenceMetadata&, Hypergraph* hg) {
    assert(state == 1);
    state = 2;
    const prob_t z = InsideOutside<prob_t,
                                   EdgeProb,
                                   SparseVector<prob_t>,
                                   EdgeFeaturesAndProbWeightFunction>(*hg, &cur_model_exp);
    cur_obj = log(z);
    cur_model_exp /= z;
  }

  // compute "empirical" expectations, numerator of objective
  virtual void NotifyAlignmentForest(const SentenceMetadata& smeta, Hypergraph* hg) {
    assert(state == 2);
    state = 3;
    SparseVector<prob_t> ref_exp;
    const prob_t ref_z = InsideOutside<prob_t,
                                       EdgeProb,
                                       SparseVector<prob_t>,
                                       EdgeFeaturesAndProbWeightFunction>(*hg, &ref_exp);
    ref_exp /= ref_z;

    double log_ref_z;
#if 0
    if (crf_uniform_empirical) {
      log_ref_z = ref_exp.dot(feature_weights);
    } else {
      log_ref_z = log(ref_z);
    }
#else
    log_ref_z = log(ref_z);
#endif

    // rounding errors means that <0 is too strict
    if ((cur_obj - log_ref_z) < kMINUS_EPSILON) {
      cerr << "DIFF. ERR! log_model_z < log_ref_z: " << cur_obj << " " << log_ref_z << endl;
      exit(1);
    }
    assert(!std::isnan(log_ref_z));
    ref_exp -= cur_model_exp;
    acc_grad -= ref_exp;
    acc_obj += (cur_obj - log_ref_z);
    trg_words += smeta.GetReference().size();
  }

  virtual void NotifyDecodingComplete(const SentenceMetadata&) {
    if (state == 3) {
      ++total_complete;
    } else {
    }
  }

  int total_complete;
  SparseVector<prob_t> cur_model_exp;
  SparseVector<prob_t> acc_grad;
  double acc_obj;
  double cur_obj;
  unsigned trg_words;
  int state;
};

void ReadConfig(const string& ini, vector<string>* out) {
  ReadFile rf(ini);
  istream& in = *rf.stream();
  while(in) {
    string line;
    getline(in, line);
    if (!in) continue;
    out->push_back(line);
  }
}

void StoreConfig(const vector<string>& cfg, istringstream* o) {
  ostringstream os;
  for (int i = 0; i < cfg.size(); ++i) { os << cfg[i] << endl; }
  o->str(os.str());
}

template <typename T>
struct VectorPlus : public binary_function<vector<T>, vector<T>, vector<T> >  {
  vector<T> operator()(const vector<int>& a, const vector<int>& b) const {
    assert(a.size() == b.size());
    vector<T> v(a.size());
    transform(a.begin(), a.end(), b.begin(), v.begin(), plus<T>());
    return v;
  }
};

int main(int argc, char** argv) {
#ifdef HAVE_MPI
  mpi::environment env(argc, argv);
  mpi::communicator world;
  const int size = world.size();
  const int rank = world.rank();
#else
  const int size = 1;
  const int rank = 0;
#endif
  SetSilent(true);  // turn off verbose decoder output
  register_feature_functions();

  po::variables_map conf;
  if (!InitCommandLine(argc, argv, &conf)) return 1;

  // load cdec.ini and set up decoder
  vector<string> cdec_ini;
  ReadConfig(conf["decoder_config"].as<string>(), &cdec_ini);
  istringstream ini;
  StoreConfig(cdec_ini, &ini);
  if (rank == 0) cerr << "Loading grammar...\n";
  Decoder* decoder = new Decoder(&ini);
  if (decoder->GetConf()["input"].as<string>() != "-") {
    cerr << "cdec.ini must not set an input file\n";
    return 1;
  }
  if (rank == 0) cerr << "Done loading grammar!\n";

  // load initial weights
  if (rank == 0) { cerr << "Loading weights...\n"; }
  vector<weight_t>& lambdas = decoder->CurrentWeightVector();
  Weights::InitFromFile(conf["input_weights"].as<string>(), &lambdas);
  if (rank == 0) { cerr << "Done loading weights.\n"; }

  // freeze feature set (should be optional?)
  const bool freeze_feature_set = true;
  if (freeze_feature_set) FD::Freeze();

  const int num_feats = FD::NumFeats();
  if (rank == 0) cerr << "Number of features: " << num_feats << endl;
  lambdas.resize(num_feats);

  const bool gaussian_prior = conf.count("gaussian_prior");
  vector<weight_t> means(num_feats, 0);
  if (conf.count("means")) {
    if (!gaussian_prior) {
      cerr << "Don't use --means without --gaussian_prior!\n";
      exit(1);
    }
    Weights::InitFromFile(conf["means"].as<string>(), &means);
  }
  boost::shared_ptr<BatchOptimizer> o;
  if (rank == 0) {
    const string omethod = conf["optimization_method"].as<string>();
    if (omethod == "rprop")
      o.reset(new RPropOptimizer(num_feats));  // TODO add configuration
    else
      o.reset(new LBFGSOptimizer(num_feats, conf["correction_buffers"].as<int>()));
    cerr << "Optimizer: " << o->Name() << endl;
  }
  double objective = 0;
  vector<double> gradient(num_feats, 0.0);
  vector<double> rcv_grad;
  rcv_grad.clear();
  bool converged = false;

  vector<string> corpus, test_corpus;
  ReadTrainingCorpus(conf["training_data"].as<string>(), rank, size, &corpus);
  assert(corpus.size() > 0);
  if (conf.count("test_data"))
    ReadTrainingCorpus(conf["test_data"].as<string>(), rank, size, &test_corpus);

  TrainingObserver observer;
  ConditionalLikelihoodObserver cllh_observer;
  while (!converged) {
    observer.Reset();
    cllh_observer.Reset();
#ifdef HAVE_MPI
    mpi::timer timer;
    world.barrier();
#endif
    if (rank == 0) {
      cerr << "Starting decoding... (~" << corpus.size() << " sentences / proc)\n";
      cerr << "  Testset size: " << test_corpus.size() << " sentences / proc)\n";
    }
    for (int i = 0; i < corpus.size(); ++i)
      decoder->Decode(corpus[i], &observer);
    cerr << "  process " << rank << '/' << size << " done\n";
    fill(gradient.begin(), gradient.end(), 0);
    observer.SetLocalGradientAndObjective(&gradient, &objective);

    unsigned total_words = 0;
#ifdef HAVE_MPI
    double to = 0;
    rcv_grad.resize(num_feats, 0.0);
    mpi::reduce(world, &gradient[0], gradient.size(), &rcv_grad[0], plus<double>(), 0);
    swap(gradient, rcv_grad);
    rcv_grad.clear();

    reduce(world, observer.trg_words, total_words, std::plus<unsigned>(), 0);
    mpi::reduce(world, objective, to, plus<double>(), 0);
    objective = to;
#else
    total_words = observer.trg_words;
#endif
    if (rank == 0)
      cerr << "TRAINING CORPUS: ln p(f|e)=" << objective << "\t log_2 p(f|e) = " << (objective/log(2)) << "\t cond. entropy = " << (objective/log(2) / total_words) << "\t ppl = " << pow(2, (objective/log(2) / total_words)) << endl;

    for (int i = 0; i < test_corpus.size(); ++i)
      decoder->Decode(test_corpus[i], &cllh_observer);

    double test_objective = 0;
    unsigned test_total_words = 0;
#ifdef HAVE_MPI
    reduce(world, cllh_observer.acc_obj, test_objective, std::plus<double>(), 0);
    reduce(world, cllh_observer.trg_words, test_total_words, std::plus<unsigned>(), 0);
#else
    test_objective = cllh_observer.acc_obj;
    test_total_words = cllh_observer.trg_words;
#endif

    if (rank == 0) {  // run optimizer only on rank=0 node
      if (test_corpus.size())
        cerr << "    TEST CORPUS: ln p(f|e)=" << test_objective << "\t log_2 p(f|e) = " << (test_objective/log(2)) << "\t cond. entropy = " << (test_objective/log(2) / test_total_words) << "\t ppl = " << pow(2, (test_objective/log(2) / test_total_words)) << endl;
      if (gaussian_prior) {
        const double sigsq = conf["sigma_squared"].as<double>();
        double norm = 0;
        for (int k = 1; k < lambdas.size(); ++k) {
          const double& lambda_k = lambdas[k];
          if (lambda_k) {
            const double param = (lambda_k - means[k]);
            norm += param * param;
            gradient[k] += param / sigsq;
          }
        }
        const double reg = norm / (2.0 * sigsq);
        cerr << "REGULARIZATION TERM: " << reg << endl;
        objective += reg;
      }
      cerr << "EVALUATION #" << o->EvaluationCount() << " OBJECTIVE: " << objective << endl;
      double gnorm = 0;
      for (int i = 0; i < gradient.size(); ++i)
        gnorm += gradient[i] * gradient[i];
      cerr << "  GNORM=" << sqrt(gnorm) << endl;
      vector<weight_t> old = lambdas;
      int c = 0;
      while (old == lambdas) {
        ++c;
        if (c > 1) { cerr << "Same lambdas, repeating optimization\n"; }
        o->Optimize(objective, gradient, &lambdas);
        assert(c < 5);
      }
      old.clear();
      Weights::SanityCheck(lambdas);
      Weights::ShowLargestFeatures(lambdas);

      converged = o->HasConverged();
      if (converged) { cerr << "OPTIMIZER REPORTS CONVERGENCE!\n"; }

      string fname = "weights.cur.gz";
      if (converged) { fname = "weights.final.gz"; }
      ostringstream vv;
      vv << "Objective = " << objective << "  (eval count=" << o->EvaluationCount() << ")";
      const string svv = vv.str();
      Weights::WriteToFile(fname, lambdas, true, &svv);
    }  // rank == 0
    int cint = converged;
#ifdef HAVE_MPI
    mpi::broadcast(world, &lambdas[0], lambdas.size(), 0);
    mpi::broadcast(world, cint, 0);
    if (rank == 0) { cerr << "  ELAPSED TIME THIS ITERATION=" << timer.elapsed() << endl; }
#endif
    converged = cint;
  }
  return 0;
}


/*  _______________________________________________________________________

    DAKOTA: Design Analysis Kit for Optimization and Terascale Applications
    Copyright 2014 Sandia Corporation.
    This software is distributed under the GNU Lesser General Public License.
    For more information, see the README file in the top Dakota directory.
    _______________________________________________________________________ */

//- Class:        global_defs
//- Description:  Global object initializations and global function
//-               implementations
//- Owner:        Mike Eldred

#include <boost/system/system_error.hpp>
#include <boost/math/constants/constants.hpp>
#include "dakota_global_defs.hpp"
#include "ParamResponsePair.hpp"
#include "PRPMultiIndex.hpp"
#include "DakotaGraphics.hpp"
#include "DakotaInterface.hpp"
#include "ParallelLibrary.hpp"
#include "ProblemDescDB.hpp"
#include "ResultsManager.hpp"

// Toggle for MPI debug hold
//#define MPI_DEBUG

#if defined(MPI_DEBUG) && defined(MPICH_NAME)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif

static const char rcsId[]="@(#) $Id: dakota_global_defs.cpp 6716 2010-04-03 18:35:08Z wjbohnh $";

namespace Dakota {

// --------------------------
// Instantiate global objects
// --------------------------

double PI = boost::math::constants::pi<double>();
double HALF_LOG_2PI = std::log(2.0*PI)/2.0;

/// by default Dakota exits or calls MPI_Abort on errors
short abort_mode = ABORT_EXITS;

std::ostream* dakota_cout = &std::cout; ///< DAKOTA stdout initially points to
  ///< std::cout, but may be redirected to a tagged ofstream if there are
  ///< concurrent iterators.
std::ostream* dakota_cerr = &std::cerr; ///< DAKOTA stderr initially points to
  ///< std::cerr, but may be redirected to a tagged ofstream if there are
  ///< concurrent iterators.
PRPCache data_pairs;          ///< contains all parameter/response pairs.

/// Global results database for iterator results
ResultsManager iterator_results_db;

int write_precision = 10;     ///< used in ostream data output functions
                              ///< (restart_util.cpp overrides default value)

MPIManager      dummy_mpi_mgr; ///< dummy MPIManager for ref initialization
ProgramOptions  dummy_prg_opt; ///< dummy ProgramOptions for ref initialization
OutputManager   dummy_out_mgr; ///< dummy OutputManager for ref initialization
ParallelLibrary dummy_lib;     ///< dummy ParallelLibrary for ref initialization
ProblemDescDB   dummy_db;      ///< dummy ProblemDescDB for ref initialization

#ifdef DAKOTA_MODELCENTER
int mc_ptr_int = 0;           ///< global pointer for ModelCenter API
int dc_ptr_int = 0;           ///< global pointer for ModelCenter eval DB
#endif // DAKOTA_MODELCENTER

ProblemDescDB *Dak_pddb;      ///< set by ProblemDescDB, for use in parsing

// -----------------------
// Define global functions
// -----------------------
void abort_handler(int code)
{
  // WEH - uncomment this code if you want signals to generate a corefile.
  //       This is handy for debugging infinite loops ... which can be
  //       difficult to debug within GDB.
  //abort();

  // BMA TODO: do we want to maintain this?
  if (code > 1) // code = 2 (Cntl-C signal), 0 (normal), & -1/1 (abnormal)
    Cout << "Signal Caught!" << std::endl;

  // Clean up
  Cout << std::flush; // flush cout or ofstream redirection
  Cerr << std::flush; // flush cerr or ofstream redirection

  if (Dak_pddb) {
    // cleanup parameters/results files
    InterfaceList &ifaces = Dak_pddb->interface_list();
    for (InterfaceList::iterator It = ifaces.begin(); It != ifaces.end(); ++It)
      It->file_cleanup(); // virtual fn defined for ProcessApplicInterface
    // properly terminate in parallel
    Dak_pddb->parallel_library().abort_helper(code);
  }
  else {
    abort_throw_or_exit(code);
  }
}

/** Throw a Boost system_error or call std::exit, with (256 +
    dakota_code), where dakota_code < 0

    RATIONALE:
     * Avoid common "standard" exit codes and signals (signum.h) as
       well as uncaught signals / uncatchable SIGKILL which return 128
       + <signum> on Linux = [129, 192]

     * Return a value in [0,255] since some operating systems only
       return the 8 least significant bits, leaves [193, 255] for
       Dakota.  This should make return codes consistent
       cross-platform.  */
void abort_throw_or_exit(int dakota_code)
{
  int os_code = 256 + dakota_code;
  if (abort_mode == ABORT_THROWS) {
    // throw a Boost exception that inherits from std::runtime_error, but
    // embeds the error code (since system_error is C++11 and newer)
    boost::system::error_code ecode(os_code, boost::system::generic_category());
    throw(boost::system::system_error(ecode, "Dakota aborted"));
  }
  else {
    std::exit(os_code);  // or std::exit(EXIT_FAILURE) from /usr/include/stdlib.h
  }
}

/// Tie various signal handlers to Dakota's abort_handler function
void register_signal_handlers()
{
#if defined(__MINGW32__) || defined(_MSC_VER)
  std::signal(SIGBREAK, Dakota::abort_handler);
#else
  std::signal(SIGKILL, Dakota::abort_handler);
#endif
  std::signal(SIGTERM, Dakota::abort_handler);
  std::signal(SIGINT,  Dakota::abort_handler);
}

/** See details in code for details, depending on MPI implementation in use. */
void mpi_debug_hold() {

#ifdef MPI_DEBUG
  // hold parallel job prior to MPI_Init() in order to attach debugger to
  // master process.  Then step past ParallelLibrary instantiation and attach
  // debugger to other processes.
//#ifdef MPICH2
#ifdef MPICH_NAME
  // To use this approach, set $DAKOTA_DEBUGPIPE to a suitable name,
  // and create $DAKOTA_DEBUGPIPE by executing "mkfifo $DAKOTA_DEBUGPIPE".
  // After invoking "mpirun ... dakota ...", find the processes, invoke
  // a debugger on them, set breakpoints, and execute "echo >$DAKOTA_DEBUGPIPE"
  // to write something to $DAKOTA_DEBUGPIPE, thus releasing dakota from
  // a wait at the open invocation below.
  char *pname; int dfd;
  if ( ( pname = getenv("DAKOTA_DEBUGPIPE") ) &&
       ( dfd = open(pname,O_RDONLY) ) > 0 ) {
    char buf[80];
    read(dfd,buf,sizeof(buf));
    close(dfd);
  }
#else
  // This simple scheme has been observed to fail with MPICH2
  int test;
  std::cin >> test;
#endif // MPICH2
#endif // MPI_DEBUG

}

} // namespace Dakota


#ifndef STAN_MATH_TORSTEN_MIXODE1CPTMODEL_RK45_HPP
#define STAN_MATH_TORSTEN_MIXODE1CPTMODEL_RK45_HPP

#include <Eigen/Dense>
#include <stan/math/torsten/PKModel/PKModel.hpp>
#include <stan/math/torsten/PKModel/functors/mix1_functor.hpp>
#include <stan/math/torsten/PKModel/Pred/Pred1_mix1.hpp>
#include <stan/math/torsten/PKModel/Pred/PredSS_mix1.hpp>
// #include <stan/math/torsten/PKModel/Pred/PredSS_err.hpp>
#include <boost/math/tools/promotion.hpp>
#include <vector>

namespace torsten {

/**
 * Compute the predicted amounts in each compartment at each event
 * of an ODEs model. The model contains a base 1 Compartment PK
 * component which gets solved analytically, while the other ODEs
 * are solved numerically using stan::math::integrate_ode_rk45. This
 * amounts to using the mixed solver method.
 *
 * <b>Warning:</b> This prototype does not handle steady state events.
 *
 * @tparam T0 type of scalar for time of events.
 * @tparam T1 type of scalar for amount at each event.
 * @tparam T2 type of scalar for rate at each event.
 * @tparam T3 type of scalar for inter-dose inteveral at each event.
 * @tparam T4 type of scalars for the model parameters.
 * @tparam T5 type of scalars for the bio-variability parameters.
 * @tparam T6 type of scalars for the model tlag parameters.
 * @tparam F type of ODE system function.
 * @param[in] f functor for base ordinary differential equation
 *            which gets solved numerically.
 * @param[in] nOde number of ODEs we solve numerically.
 * @param[in] time times of events
 * @param[in] amt amount at each event
 * @param[in] rate rate at each event
 * @param[in] ii inter-dose interval at each event
 * @param[in] evid event identity:
 *                    (0) observation
 *                    (1) dosing
 *                    (2) other
 *                    (3) reset
 *                    (4) reset AND dosing
 * @param[in] cmt compartment number at each event
 * @param[in] addl additional dosing at each event
 * @param[in] ss steady state approximation at each event (0: no, 1: yes)
 * @param[in] theta vector of ODE parameters
 * @param[in] biovar bio-availability in each compartment
 * @param[in] tlag lag time in each compartment
 * @param[in] rel_tol relative tolerance for the Boost ode solver
 * @param[in] abs_tol absolute tolerance for the Boost ode solver
 * @param[in] max_num_steps maximal number of steps to take within
 *            the Boost ode solver
 * @return a matrix with predicted amount in each compartment
 *         at each event.
 *
 * FIX ME: msg should be passed on to functor (allows use of
 * print statement inside ODE system).
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<std::vector<T4> >& theta,
                     const std::vector<std::vector<T5> >& biovar,
                     const std::vector<std::vector<T6> >& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  using std::vector;
  using Eigen::Dynamic;
  using Eigen::Matrix;
  using boost::math::tools::promote_args;

  int nPK = 2;

  // check arguments
  static const char* function("mixOde1CptModel_rk45");
  torsten::pmetricsCheck(time, amt, rate, ii, evid, cmt, addl, ss,
                theta, biovar, tlag, function);

  // Construct dummy array of matrix for last argument of pred
  Matrix<T4, Dynamic, Dynamic> dummy_system;
  vector<Matrix<T4, Dynamic, Dynamic> > dummy_systems(1, dummy_system);

  typedef mix1_functor<F> F0;

  return Pred(time, amt, rate, ii, evid, cmt, addl, ss,
              theta, biovar, tlag, nPK + nOde, dummy_systems,
              Pred1_mix1<F0>(F0(f), rel_tol, abs_tol, max_num_steps, msgs,
                             "rk45"),
              PredSS_mix1<F0>(F0(f), rel_tol, abs_tol, max_num_steps, msgs,
                              "rk45", nOde));
}

/**
 * Overload function to allow user to pass an std::vector for
 * theta.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
  typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<T4>& theta,
                     const std::vector<std::vector<T5> >& biovar,
                     const std::vector<std::vector<T6> >& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T4> > vec_theta(1, theta);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              vec_theta, biovar, tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

/**
 * Overload function to allow user to pass an std::vector for
 * theta and biovar.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<T4>& theta,
                     const std::vector<T5>& biovar,
                     const std::vector<std::vector<T6> >& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T4> > vec_theta(1, theta);
  std::vector<std::vector<T5> > vec_biovar(1, biovar);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              vec_theta, vec_biovar, tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

/**
 * Overload function to allow user to pass an std::vector for
 * theta, biovar, and tlag.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<T4>& theta,
                     const std::vector<T5>& biovar,
                     const std::vector<T6>& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T4> > vec_theta(1, theta);
  std::vector<std::vector<T5> > vec_biovar(1, biovar);
  std::vector<std::vector<T6> > vec_tlag(1, tlag);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              vec_theta, vec_biovar, vec_tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

/**
 * Overload function to allow user to pass an std::vector for
 * theta and tlag.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<T4>& theta,
                     const std::vector<std::vector<T5> >& biovar,
                     const std::vector<T6>& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T4> > vec_theta(1, theta);
  std::vector<std::vector<T6> > vec_tlag(1, tlag);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              vec_theta, biovar, vec_tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

/**
 * Overload function to allow user to pass an std::vector for
 * biovar.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<std::vector<T4> >& theta,
                     const std::vector<T5>& biovar,
                     const std::vector<std::vector<T6> >& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T5> > vec_biovar(1, biovar);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              theta, vec_biovar, tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

/**
 * Overload function to allow user to pass an std::vector for
 * biovar and tlag.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<std::vector<T4> >& theta,
                     const std::vector<T5>& biovar,
                     const std::vector<T6>& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T5> > vec_biovar(1, biovar);
  std::vector<std::vector<T6> > vec_tlag(1, tlag);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              theta, vec_biovar, vec_tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

/**
 * Overload function to allow user to pass an std::vector for
 * tlag.
 */
template <typename T0, typename T1, typename T2, typename T3, typename T4,
          typename T5, typename T6, typename F>
Eigen::Matrix <typename boost::math::tools::promote_args<T0, T1, T2, T3,
  typename boost::math::tools::promote_args<T4, T5, T6>::type>::type,
  Eigen::Dynamic, Eigen::Dynamic>
mixOde1CptModel_rk45(const F& f,
                     const int nOde,
                     const std::vector<T0>& time,
                     const std::vector<T1>& amt,
                     const std::vector<T2>& rate,
                     const std::vector<T3>& ii,
                     const std::vector<int>& evid,
                     const std::vector<int>& cmt,
                     const std::vector<int>& addl,
                     const std::vector<int>& ss,
                     const std::vector<std::vector<T4> >& theta,
                     const std::vector<std::vector<T5> >& biovar,
                     const std::vector<T6>& tlag,
                     std::ostream* msgs = 0,
                     double rel_tol = 1e-6,
                     double abs_tol = 1e-6,
                     long int max_num_steps = 1e6) {  // NOLINT(runtime/int)
  std::vector<std::vector<T6> > vec_tlag(1, tlag);

  return mixOde1CptModel_rk45(f, nOde,
                              time, amt, rate, ii, evid, cmt, addl, ss,
                              theta, biovar, vec_tlag,
                              msgs, rel_tol, abs_tol, max_num_steps);
}

}
#endif


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

#include <physics/World.h>
#include <physics/objects/ObjectsFactory.h>

using namespace Physics;

struct ObjectsFactoryTestFixture {
	ObjectsFactoryTestFixture() :
		w(b2Vec2(0.0f, 9.8f), 4, 8),
		obj(ObjectsFactory::init(w.getWorld())){
	}
	World w;
	ObjectsFactory& obj;
};

BOOST_FIXTURE_TEST_SUITE(ObjectsFactoryTests, ObjectsFactoryTestFixture);

BOOST_AUTO_TEST_CASE( Check_createCircleBody_world_equals_to_loops_world)
{
	b2Body* b = obj.createCircle(5.0f, 4.5f, 3.5f);
	BOOST_CHECK_EQUAL(b->GetWorld(), w.getWorld());
}

BOOST_AUTO_TEST_CASE(Check_circle_position_is_zero)
{
	b2Body* b = obj.createCircle(5.0f, 4.5f, 3.5f);
	BOOST_CHECK_EQUAL(b->GetPosition().x, 0.0f);
	BOOST_CHECK_EQUAL(b->GetPosition().y, 0.0f);
}

BOOST_AUTO_TEST_CASE(Check_createPolygon_body_world_equals_to_loops_world)
{
	b2Body* b = obj.createPolygon({
			{1.0f, 1.0f},
			{0.0f, 0.0f},
			{1.0f, -1.0f}
		},
		4.5f,
		3.5f);
	BOOST_CHECK_EQUAL(b->GetWorld(), w.getWorld());
}

BOOST_AUTO_TEST_CASE(Check_polygon_position_is_zero)
{
	b2Body* b = obj.createPolygon({
		{ 1.0f, 1.0f },
		{ 0.0f, 0.0f },
		{ 1.0f, -1.0f }
	},
		4.5f,
		3.5f);
	BOOST_CHECK_EQUAL(b->GetPosition().x, 0.0f);
	BOOST_CHECK_EQUAL(b->GetPosition().y, 0.0f);
}

BOOST_AUTO_TEST_CASE(Check_createGround_world_equals_to_loops_world)
{
	b2Body* b = obj.createGround({
		{0.0f, 0.0f},
		{1.0f, 1.0f}
	});
	BOOST_CHECK_EQUAL(b->GetWorld(), w.getWorld());
}

BOOST_AUTO_TEST_CASE(Check_ground_position_is_zero)
{
	b2Body* b = obj.createGround({
		{ 0.0f, 0.0f },
		{ 1.0f, 1.0f }
	});
	BOOST_CHECK_EQUAL(b->GetPosition().x, 0.0f);
	BOOST_CHECK_EQUAL(b->GetPosition().y, 0.0f);
}

BOOST_AUTO_TEST_SUITE_END();


// Copyright (c) 2012-2014 The Bitcoin Core developers
// Copyright (c) 2017-2019 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "script/script.h"
#include "test/test_qrax.h"

#include <boost/test/unit_test.hpp>
#include <limits.h>
#include <stdint.h>

BOOST_FIXTURE_TEST_SUITE(scriptnum_tests, BasicTestingSetup)

/** A selection of numbers that do not trigger int64_t overflow
 *  when added/subtracted. */
static const int64_t values[] = { 0, 1, -2, 127, 128, -255, 256, (1LL << 15) - 1, -(1LL << 16), (1LL << 24) - 1, (1LL << 31), 1 - (1LL << 32), 1LL << 40 };

static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000};

static void CheckCreateVch(const long& num)
{

}

static void CheckCreateInt(const long& num)
{

}

static void CheckAdd(const long& num1, const long& num2)
{

}

static void CheckNegate(const long& num)
{

}

static void CheckSubtract(const long& num1, const long& num2)
{

}

static void CheckCompare(const long& num1, const long& num2)
{

}

static void RunCreate(const long& num)
{
    CheckCreateInt(num);
    CScriptNum scriptnum(num);
    if (scriptnum.getvch().size() <= CScriptNum::nDefaultMaxNumSize)
        CheckCreateVch(num);
    else
    {
        BOOST_CHECK_THROW (CheckCreateVch(num), scriptnum_error);
    }
}

static void RunOperators(const long& num1, const int64_t& num2)
{
    CheckAdd(num1, num2);
    CheckSubtract(num1, num2);
    CheckNegate(num1);
    CheckCompare(num1, num2);
}

BOOST_AUTO_TEST_CASE(creation)
{
    for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
    {
        for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
        {
            RunCreate(values[i]);
            RunCreate(values[i] + offsets[j]);
            RunCreate(values[i] - offsets[j]);
        }
    }
}

BOOST_AUTO_TEST_CASE(operators)
{
    for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
    {
        for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
        {
            RunOperators(values[i], values[i]);
            RunOperators(values[i], -values[i]);
            RunOperators(values[i], values[j]);
            RunOperators(values[i], -values[j]);
            RunOperators(values[i] + values[j], values[j]);
            RunOperators(values[i] + values[j], -values[j]);
            RunOperators(values[i] - values[j], values[j]);
            RunOperators(values[i] - values[j], -values[j]);
            RunOperators(values[i] + values[j], values[i] + values[j]);
            RunOperators(values[i] + values[j], values[i] - values[j]);
            RunOperators(values[i] - values[j], values[i] + values[j]);
            RunOperators(values[i] - values[j], values[i] - values[j]);
        }
    }
}

BOOST_AUTO_TEST_SUITE_END()


// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html

#ifndef BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP

#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance/services.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>

namespace boost { namespace geometry
{

namespace resolve_strategy
{

// TODO: This utility could be entirely implemented as:
//       decltype(geometry::comparable_distance(std::declval<Geometry1>(), std::declval<Geometry2>(), std::declval<Strategy>()))
//       however then the algorithm would have to be compiled.

template
<
    typename Geometry1, typename Geometry2, typename Strategy,
    bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct comparable_distance_strategy2_type
{
    typedef decltype(std::declval<Strategy>().distance(
        std::declval<Geometry1>(), std::declval<Geometry2>())) type;
};

template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_strategy2_type<Geometry1, Geometry2, Strategy, false>
{
    typedef Strategy type;
};

template
<
    typename Geometry1, typename Geometry2, typename Strategy,
    bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct comparable_distance_strategy_type
    : strategy::distance::services::comparable_type
        <
            typename comparable_distance_strategy2_type
                <
                    Geometry1, Geometry2, Strategy
                >::type
        >
{};

template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_strategy_type<Geometry1, Geometry2, Strategy, true>
    : comparable_distance_strategy_type<Geometry2, Geometry1, Strategy, false>
{};

template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_result
    : strategy::distance::services::return_type
        <
            typename comparable_distance_strategy_type<Geometry1, Geometry2, Strategy>::type,
            typename point_type<Geometry1>::type,
            typename point_type<Geometry2>::type
        >
{};

template <typename Geometry1, typename Geometry2>
struct comparable_distance_result<Geometry1, Geometry2, default_strategy>
    : comparable_distance_result
        <
            Geometry1,
            Geometry2,
            typename strategies::distance::services::default_strategy
                <
                    Geometry1, Geometry2
                >::type
        >
{};

} // namespace resolve_strategy

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{

template <typename Strategy = geometry::default_strategy>
struct more_precise_comparable_distance_result
{
    template <typename Curr, typename Next>
    struct predicate
        : std::is_same
            <
                typename resolve_strategy::comparable_distance_result
                    <
                        typename util::sequence_element<0, Curr>::type,
                        typename util::sequence_element<1, Curr>::type,
                        Strategy
                    >::type,
                typename geometry::select_most_precise
                    <
                        typename resolve_strategy::comparable_distance_result
                            <
                                typename util::sequence_element<0, Curr>::type,
                                typename util::sequence_element<1, Curr>::type,
                                Strategy
                            >::type,
                        typename resolve_strategy::comparable_distance_result
                            <
                                typename util::sequence_element<0, Next>::type,
                                typename util::sequence_element<1, Next>::type,
                                Strategy
                            >::type
                    >::type
            >
    {};
};

}} // namespace detail::distance
#endif //DOXYGEN_NO_DETAIL

namespace resolve_dynamic
{

template
<
    typename Geometry1, typename Geometry2, typename Strategy,
    bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry1>::value
                              || util::is_dynamic_geometry<Geometry2>::value
                              || util::is_geometry_collection<Geometry1>::value
                              || util::is_geometry_collection<Geometry2>::value
>
struct comparable_distance_result
    : resolve_strategy::comparable_distance_result
        <
            Geometry1,
            Geometry2,
            Strategy
        >
{};

template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_result<Geometry1, Geometry2, Strategy, true>
{
    // Select the most precise distance strategy result type
    //   for all variant type combinations.
    // TODO: We should ignore the combinations that are not valid
    //   but is_implemented is not ready for prime time.
    using selected_types = typename detail::select_geometry_types
        <
            Geometry1, Geometry2,
            detail::distance::more_precise_comparable_distance_result<Strategy>::template predicate
        >::type;

    using type = typename resolve_strategy::comparable_distance_result
        <
            typename util::sequence_element<0, selected_types>::type,
            typename util::sequence_element<1, selected_types>::type,
            Strategy
        >::type;
};

} // namespace resolve_dynamic

/*!
\brief Meta-function defining return type of comparable_distance function
\ingroup distance
*/
template
<
    typename Geometry1,
    typename Geometry2 = Geometry1,
    typename Strategy = void
>
struct comparable_distance_result
    : resolve_dynamic::comparable_distance_result
        <
            Geometry1, Geometry2, Strategy
        >
{};

template <typename Geometry1, typename Geometry2>
struct comparable_distance_result<Geometry1, Geometry2, void>
    : comparable_distance_result<Geometry1, Geometry2, default_strategy>
{};

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP


#include <armadillo>
#include <iostream>

#include "armadillo.h"
#include "util.h"
template <typename T, typename JavaFormat, typename Transformation>
void jni_to_vec(JNIEnv &env, jobject obj, std::vector<T> & vec, Transformation tr, JavaFormat)
{
    int size = env.GetDirectBufferCapacity(obj);
    JavaFormat *buff = static_cast<JavaFormat*>(env.GetDirectBufferAddress(obj));
    std::transform(buff, buff + size, std::back_inserter(vec), tr);
}

template <class T>
class lshift_inserter_class
{
private:
    T &_vec;
public:
    lshift_inserter_class(T & vec_) : _vec(vec_){}

    inline lshift_inserter_class<T> & operator++(){return *this;}
    inline lshift_inserter_class<T> & operator++(int){return *this;}
    inline lshift_inserter_class<T> & operator*(){ return *this; }
    template <typename U>
    lshift_inserter_class<T> operator=(U const & val) {
        _vec << val;
        return *this;
    }
};

template <class T>
lshift_inserter_class<T> lshift_inserter(T & vec)
{
    return lshift_inserter_class<T>(vec);
}

template <class Iterator>
class pointer_initializer_list_class : public std::initializer_list<typename ITER_UTIL::it_value_type<Iterator>::elem>
{
private:
    Iterator _begin;
    Iterator _end;
public:
    pointer_initializer_list_class(Iterator begin_, Iterator end_)
    {
        _begin(begin_);
        _end(end_);
    }

    Iterator begin(){return _begin;};
    Iterator end(){return _end;};
    size_t size() const{return std::distance(_begin, _end);}
};

template <class Iterator>
pointer_initializer_list_class<Iterator> pointer_initializer_list(Iterator begin, Iterator end)
{
    return pointer_initializer_list<Iterator>(begin, end);
}

template <typename JavaFormat, typename Transformation, typename T>
void jni_to_arma_vec(JNIEnv &env, jobject obj, T & vec, Transformation tr, JavaFormat)
{
    size_t size = env.GetDirectBufferCapacity(obj);
    JavaFormat *buff = static_cast<JavaFormat*>(env.GetDirectBufferAddress(obj));
    for (size_t i = 0; i < size; ++i)
    {
        vec[i] = tr(buff[i]);
    }
}

template <typename T, typename JavaFormat, typename Transformation>
void vec_to_jni(JNIEnv &env, jobject obj, std::vector<T> const & vec, Transformation tr, JavaFormat)
{
    JavaFormat *buff = static_cast<JavaFormat*>(env.GetDirectBufferAddress(obj));
    std::transform(vec.begin(), vec.end(), buff, tr);
}

template <typename T, typename JavaFormat, typename Transformation>
void arma_vec_to_jni(JNIEnv &env, jobject obj, T const & vec, Transformation tr, JavaFormat)
{
    JavaFormat *buff = static_cast<JavaFormat*>(env.GetDirectBufferAddress(obj));
    for (size_t i = 0; i < vec.size(); ++i)
    {
        buff[i] = tr(vec[i]);
    }
}

JNIEXPORT void JNICALL Java_maths_Armadillo_spsolve (JNIEnv *env, jclass, jobject mat_values, jobject IA, jobject JA, jobject javab, jobject result)
{
    arma::urowvec IA_vec(env->GetDirectBufferCapacity(IA));
    jni_to_arma_vec(*env, IA, IA_vec, UTIL::identity_function, (jint)0);
    arma::urowvec JA_vec(env->GetDirectBufferCapacity(JA));
    jni_to_arma_vec(*env, JA, JA_vec, UTIL::identity_function, (jint)0);
    arma::vec value_vec(env->GetDirectBufferCapacity(mat_values));
    jni_to_arma_vec(*env, mat_values, value_vec, UTIL::identity_function, (jdouble)0);
    arma::sp_mat A(JA_vec, IA_vec,value_vec, env->GetDirectBufferCapacity(result), env->GetDirectBufferCapacity(javab));

    arma::vec b(env->GetDirectBufferCapacity(javab));
    jni_to_arma_vec(*env, javab, b, UTIL::identity_function, (jdouble)0);
    arma::vec x(env->GetDirectBufferCapacity(result));
    arma::superlu_opts opts;

    opts.equilibrate = true;

    bool status = arma::spsolve(x, A, b, "superlu", opts);
    if(status == false)  { std::cout << "no solution" << std::endl; }
    arma_vec_to_jni(*env, result, x, UTIL::identity_function, (jdouble)0);
}


// Copyright (c) 2014 The Bitcoin Core developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
// Copyright (c) 2018-2019 The BLTG developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "primitives/transaction.h"
#include "main.h"
#include "test_bltg.h"

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)

CAmount nMoneySupplyEnd = 33000000 * COIN;

BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
    CAmount nSum = 0;
    for (int nHeight = 0; nHeight < 12; nHeight += 1) {
        /* premine in block 1-11 (33,000,000 BLTG) */
        CAmount nSubsidy = GetBlockValue(nHeight);
        BOOST_CHECK(nSubsidy <= 3000000 * COIN);
        BOOST_CHECK(MoneyRange(nSubsidy));
        nSum += nSubsidy;
        BOOST_CHECK(nSum > 0 && nSum <= nMoneySupplyEnd);
}
    BOOST_CHECK(nSum == 3300000000000000ULL);
}

BOOST_AUTO_TEST_SUITE_END()


/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <boost/make_shared.hpp>
#include <ored/portfolio/builders/fxoption.hpp>
#include <ored/portfolio/enginefactory.hpp>
#include <ored/portfolio/fxoption.hpp>
#include <ored/portfolio/legdata.hpp>
#include <ored/utilities/log.hpp>
#include <ql/errors.hpp>
#include <ql/exercise.hpp>
#include <ql/instruments/compositeinstrument.hpp>
#include <ql/instruments/vanillaoption.hpp>

using namespace QuantLib;

namespace ore {
namespace data {

void FxOption::build(const boost::shared_ptr<EngineFactory>& engineFactory) {

    const boost::shared_ptr<Market>& market = engineFactory->market();

    // If automatic exercise, check that we have a non-empty FX index string, parse it and attach curves from market.
    if (option_.automaticExercise()) {

        QL_REQUIRE(!fxIndex_.empty(),
                   "FX option trade " << id() << " has automatic exercise so the FXIndex node needs to be populated.");

        // The strike is the number of units of sold currency (currency_) per unit of bought currency (assetName_).
        // So, the convention here is that the sold currency is domestic and the bought currency is foreign.
        // Note: intentionally use null calendar and 0 day fixing lag here because we will ask the FX index for its
        //       value on the expiry date without adjustment.
        index_ = buildFxIndex(fxIndex_, currency_, assetName_, market,
                              engineFactory->configuration(MarketContext::pricing), "NullCalendar", 0);

        // Populate the external index name so that fixings work.
        indexName_ = fxIndex_;
    }

    // Build the trade using the shared functionality in the base class.
    VanillaOptionTrade::build(engineFactory);

    // LOG the volatility if the trade expiry date is in the future.
    if (expiryDate_ > Settings::instance().evaluationDate()) {
        const string& ccyPairCode = assetName_ + currency_;
        DLOG("Implied vol for " << tradeType_ << " on " << ccyPairCode << " with expiry " << expiryDate_
                                << " and strike " << strike_ << " is "
                                << market->fxVol(ccyPairCode)->blackVol(expiryDate_, strike_));
    }
}

void FxOption::fromXML(XMLNode* node) {
    VanillaOptionTrade::fromXML(node);
    XMLNode* fxNode = XMLUtils::getChildNode(node, "FxOptionData");
    QL_REQUIRE(fxNode, "No FxOptionData Node");
    option_.fromXML(XMLUtils::getChildNode(fxNode, "OptionData"));
    assetName_ = XMLUtils::getChildValue(fxNode, "BoughtCurrency", true);
    currency_ = XMLUtils::getChildValue(fxNode, "SoldCurrency", true);
    double boughtAmount = XMLUtils::getChildValueAsDouble(fxNode, "BoughtAmount", true);
    double soldAmount = XMLUtils::getChildValueAsDouble(fxNode, "SoldAmount", true);
    strike_ = soldAmount / boughtAmount;
    quantity_ = boughtAmount;
    fxIndex_ = XMLUtils::getChildValue(fxNode, "FXIndex", false);
}

XMLNode* FxOption::toXML(XMLDocument& doc) {
    // TODO: Should call parent class to xml?
    XMLNode* node = Trade::toXML(doc);
    XMLNode* fxNode = doc.allocNode("FxOptionData");
    XMLUtils::appendNode(node, fxNode);

    XMLUtils::appendNode(fxNode, option_.toXML(doc));
    XMLUtils::addChild(doc, fxNode, "BoughtCurrency", boughtCurrency());
    XMLUtils::addChild(doc, fxNode, "BoughtAmount", boughtAmount());
    XMLUtils::addChild(doc, fxNode, "SoldCurrency", soldCurrency());
    XMLUtils::addChild(doc, fxNode, "SoldAmount", soldAmount());

    if (!fxIndex_.empty())
        XMLUtils::addChild(doc, fxNode, "FXIndex", fxIndex_);

    return node;
}
} // namespace data
} // namespace ore