text:
#include <tradelayer/operators_algo_clearing.h>

#include <tradelayer/externfns.h>
#include <tradelayer/log.h>
#include <tradelayer/mdex.h>
#include <tradelayer/parse_string.h>
#include <tradelayer/tradelayer.h>
#include <tradelayer/tradelayer_matrices.h>
#include <tradelayer/uint256_extensions.h>

#include <amount.h>
#include <iostream>
#include <limits>
#include <unordered_set>

#include <boost/multiprecision/cpp_dec_float.hpp>

int n_cols = 10;
int N = 2;
int M = 4;

typedef boost::multiprecision::cpp_dec_float_100 dec_float;
MatrixTLS *pt_ndatabase;

// initialization using new class constructors
VectorTLS *pt_open_incr_long  = new VectorTLS(N, "OpenLongPosition", "LongPosIncreased");
VectorTLS *pt_open_incr_short  =  new VectorTLS(N, "OpenShortPosition", "ShortPosIncreased");
VectorTLS *pt_netted_npartly_long  = new VectorTLS(N,"LongPosNetted", "LongPosNettedPartly");
VectorTLS *pt_netted_npartly_short  =  new VectorTLS(N, "ShortPosNetted", "ShortPosNettedPartly");
VectorTLS *pt_open_incr_anypos =  new VectorTLS(M,"OpenLongPosition", "LongPosIncreased", "OpenShortPosition", "ShortPosIncreased");
VectorTLS *pt_netted_npartly_anypos = new VectorTLS(M, "LongPosNetted", "LongPosNettedPartly", "ShortPosNetted", "ShortPosNettedPartly");
VectorTLS *pt_changepos_status = new VectorTLS(2, "OpenLongPosByShortPosNetted", "OpenShortPosByLongPosNetted");

// NOTE: better approach: use the template class to initialize!
// VectorTLS *pt_expiration_dates = new VectorTLS(12*NYears);
// VectorTLS &expiration_dates = *pt_expiration_dates;
// for ( int i = 0; i < NYears; i++ )
//   {
//     expiration_dates[i+11*i]    = "ALL F" + std::to_string(i+initYear);
//     expiration_dates[i+1+11*i]  = "ALL G" + std::to_string(i+initYear);
//     expiration_dates[i+2+11*i]  = "ALL H" + std::to_string(i+initYear);
//     expiration_dates[i+3+11*i]  = "ALL J" + std::to_string(i+initYear);
//     expiration_dates[i+4+11*i]  = "ALL K" + std::to_string(i+initYear);
//     expiration_dates[i+5+11*i]  = "ALL M" + std::to_string(i+initYear);
//     expiration_dates[i+6+11*i]  = "ALL N" + std::to_string(i+initYear);
//     expiration_dates[i+7+11*i]  = "ALL Q" + std::to_string(i+initYear);
//     expiration_dates[i+8+11*i]  = "ALL U" + std::to_string(i+initYear);
//     expiration_dates[i+9+11*i]  = "ALL V" + std::to_string(i+initYear);
//     expiration_dates[i+10+11*i] = "ALL X" + std::to_string(i+initYear);
//     expiration_dates[i+11+11*i] = "ALL Z" + std::to_string(i+initYear);
//   }
/**********************************************************/
/** Functions for Settlement Algorithm */
struct status_amounts *get_status_amounts_open_incr(VectorTLS &v, int q)
{
  struct status_amounts *pt_status = new status_amounts;
  VectorTLS status_z(2);
  VectorTLS status_q = status_open_incr(status_z, q);

  if ( finding(v[1], status_q) )
    {
      pt_status->addrs_trk  = v[0];
      pt_status->status_trk = v[1];
      pt_status->lives_trk  = stol(v[2].c_str());
      pt_status->addrs_src  = v[3];
      pt_status->status_src = v[4];
      pt_status->lives_src  = stol(v[5].c_str());
      pt_status->nlives_trk = stol(v[8].c_str());
      pt_status->nlives_src = stol(v[9].c_str());
    }
  else
    {
      pt_status->addrs_src  = v[0];
      pt_status->status_src = v[1];
      pt_status->lives_src  = stol(v[2].c_str());
      pt_status->addrs_trk  = v[3];
      pt_status->status_trk = v[4];
      pt_status->lives_trk  = stol(v[5].c_str());
      pt_status->nlives_src = stol(v[8].c_str());
      pt_status->nlives_trk = stol(v[9].c_str());
    }
  pt_status->amount_trd    = stol(v[6].c_str());
  pt_status->matched_price = stod(v[7].c_str());
  return pt_status;
}

struct status_amounts *get_status_amounts_byaddrs(VectorTLS &v, std::string addrs)
{
  struct status_amounts *pt_status = new status_amounts;

  if ( addrs == v[0] )
    {
      pt_status->addrs_trk  = v[0];
      pt_status->status_trk = v[1];
      pt_status->lives_trk  = stol(v[2].c_str());
      pt_status->addrs_src  = v[3];
      pt_status->status_src = v[4];
      pt_status->lives_src  = stol(v[5].c_str());
      pt_status->nlives_trk = stol(v[8].c_str());
      pt_status->nlives_src = stol(v[9].c_str());
    }
  else
    {
      pt_status->addrs_src  = v[0];
      pt_status->status_src = v[1];
      pt_status->lives_src  = stol(v[2].c_str());
      pt_status->addrs_trk  = v[3];
      pt_status->status_trk = v[4];
      pt_status->lives_trk  = stol(v[5].c_str());
      pt_status->nlives_src = stol(v[8].c_str());
      pt_status->nlives_trk = stol(v[9].c_str());
    }
  pt_status->amount_trd    = stol(v[6].c_str());
  pt_status->matched_price = stod(v[7].c_str());

  return pt_status;
}

struct status_amounts_edge *get_status_byedge(std::map<std::string, std::string> &edge)
{
  struct status_amounts_edge *pt_status = new status_amounts_edge;

  pt_status->addrs_src   = edge["addrs_src"];
  pt_status->addrs_trk   = edge["addrs_trk"];
  pt_status->status_src  = edge["status_src"];
  pt_status->status_trk  = edge["status_trk"];
  pt_status->entry_price = stod(edge["entry_price"]);
  pt_status->exit_price  = stod(edge["exit_price"]);
  pt_status->lives_src   = stol(edge["lives_src"]);
  pt_status->lives_trk   = stol(edge["lives_trk"]);
  pt_status->amount_trd  = stol(edge["amount_trd"]);
  pt_status->edge_row    = stol(edge["edge_row"]);
  pt_status->path_number = stol(edge["path_number"]);
  pt_status->ghost_edge  = stol(edge["ghost_edge"]);

  return pt_status;
}

struct EdgeInfo *GetEdgeInfo(std::map<std::string, std::string> &edge)
{
  struct EdgeInfo *pt_status = new EdgeInfo;

  pt_status->addrs_src       = edge["addrs_src"];
  pt_status->addrs_trk       = edge["addrs_trk"];
  pt_status->status_src      = edge["status_src"];
  pt_status->status_trk      = edge["status_trk"];
  pt_status->entry_price     = stod(edge["entry_price"]);
  pt_status->exit_price      = stod(edge["exit_price"]);
  pt_status->lives_src       = stol(edge["lives_src"]);
  pt_status->lives_trk       = stol(edge["lives_trk"]);
  pt_status->amount_trd_src  = stol(edge["amount_trd_src"]);
  pt_status->amount_trd_trk  = stol(edge["amount_trd_trk"]);
  pt_status->edge_row        = stol(edge["edge_row"]);
  pt_status->path_number     = stol(edge["path_number"]);
  pt_status->ghost_edge      = stol(edge["ghost_edge"]);

  return pt_status;
}

struct status_lives_edge *get_status_bylivesedge(std::map<std::string, std::string> &edge)
{
  struct status_lives_edge *pt_status = new status_lives_edge;

  pt_status->addrs       = edge["addrs"];
  pt_status->status      = edge["status"];
  pt_status->lives       = stol(edge["lives"]);
  pt_status->entry_price = stod(edge["entry_price"]);
  pt_status->edge_row    = stol(edge["edge_row"]);
  pt_status->path_number = stol(edge["path_number"]);

  return pt_status;
}

VectorTLS status_open_incr(VectorTLS &status_q, int q)
{
  VectorTLS &open_incr_long = *pt_open_incr_long;
  VectorTLS &open_incr_short = *pt_open_incr_short;

  if (q == 0)
  {
      status_q[0] = open_incr_long[0];
      status_q[1] = open_incr_long[1];
  } else {
      status_q[0] = open_incr_short[0];
      status_q[1] = open_incr_short[1];
  }

  return status_q;
}

VectorTLS status_netted_npartly(VectorTLS &status_q, int q)
{
    VectorTLS &netted_npartly_long  = *pt_netted_npartly_long;
    VectorTLS &netted_npartly_short = *pt_netted_npartly_short;

    if (q == 0)
    {
        status_q[0] = netted_npartly_long[0];
        status_q[1] = netted_npartly_long[1];
    } else {
        status_q[0] = netted_npartly_short[0];
        status_q[1] = netted_npartly_short[1];
    }

    return status_q;
}

void adding_newtwocols_trdamount(MatrixTLS &M_file, MatrixTLS &database)
{
    int N =  size(database, 1);
    for (int i = 0; i < size(database, 0); ++i)
    {
        for (int j = 0; j < N; ++j) M_file[i][j] = database[i][j];
        M_file[i][N] = database[i][6].c_str();
        M_file[i][N+1] = database[i][6].c_str();
    }
}

void settlement_algorithm_fifo(MatrixTLS &M_file, int64_t interest, int64_t twap_price)
{
  VectorTLS &open_incr_long  = *pt_open_incr_long;
  VectorTLS &open_incr_short = *pt_open_incr_short;

  std::vector<std::vector<std::map<std::string, std::string>>> path_main;
  std::vector<std::vector<std::map<std::string, std::string>>>::iterator it_path_main;
  std::vector<std::map<std::string, std::string>>::iterator it_path_maini;
  std::map<std::string, std::string> edge_source;

  int path_number = 0;
  VectorTLS vdata(n_cols);

  for (int i = 0; i < n_rows; ++i)
  {
    for (int j = 0; j < n_cols; ++j) vdata[j] = M_file[i][j];

    struct status_amounts *pt_vdata_long  = get_status_amounts_open_incr(vdata, 0);
    struct status_amounts *pt_vdata_short = get_status_amounts_open_incr(vdata, 1);

 		std::vector<std::map<std::string, std::string>> path_maini; /** ith Path element for Main Graph **/
 		int idx_b = 0; /** Branch Index: idx_b = 1 (Branch) idx_b = 0 (Source Edge) **/
    if (finding(pt_vdata_long->status_trk, open_incr_long) || finding(pt_vdata_short->status_trk, open_incr_short))
		{
      path_number += 1;

      if(msc_debug_settlement_algorithm_fifo) PrintToLog("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
	  	/** First Edge for this new Path/Branch **/

	  	building_edge(edge_source,
                    pt_vdata_long->addrs_src, pt_vdata_long->addrs_trk,
                    pt_vdata_long->status_src, pt_vdata_long->status_trk,
                    pt_vdata_long->matched_price, pt_vdata_long->matched_price,
                    pt_vdata_long->lives_src, pt_vdata_long->lives_trk,
                    i, path_number, pt_vdata_long->amount_trd, 0);

	  	if (finding(pt_vdata_long->status_trk, open_incr_long) && finding(pt_vdata_short->status_trk, open_incr_short)){
          if(msc_debug_settlement_algorithm_fifo) PrintToLog("New Edge Source: Row #%d\n\n", i);
	  	} else {
        idx_b = 1;
	  		if(msc_debug_settlement_algorithm_fifo) PrintToLog("Posible Branch Source: Row #%d\n\n", i);
	  	}

	  	path_maini.push_back(edge_source);
	  	if(msc_debug_settlement_algorithm_fifo) PrintingEdge(edge_source);

	  	if (finding(pt_vdata_long->status_trk, open_incr_long))
	  	{
        int counting_netted_long = 0;
	    	long int amount_trd_sum_long = 0;

        if(msc_debug_settlement_algorithm_fifo) {
	    	    PrintToLog("\n*************************************************");
	    	    PrintToLog("\nTracking Long Position for: %s", pt_vdata_long->addrs_trk);
        }

	    	clearing_operator_fifo(vdata, M_file, i, pt_vdata_long, 0, counting_netted_long, amount_trd_sum_long, path_maini,
					     			           path_number, pt_vdata_long->nlives_trk, idx_b);
	  	}

	  	if(finding(pt_vdata_short->status_trk, open_incr_short))
	  	{
        int counting_netted_short = 0;
	    	long int amount_trd_sum_short = 0;
        if(msc_debug_settlement_algorithm_fifo) {
	    	    PrintToLog("\n*************************************************");
	    	    PrintToLog("\nTracking Short Position for: %s", pt_vdata_short->addrs_trk);
        }

	    	clearing_operator_fifo(vdata, M_file, i, pt_vdata_short, 1, counting_netted_short, amount_trd_sum_short, path_maini,
	    							           path_number, pt_vdata_short->nlives_trk, idx_b);
	  	}

      if (path_maini.size() != 0)
	  	{
        if(msc_debug_settlement_algorithm_fifo) PrintToLog("\nPath Element #%d of the Main Graph:\n\n", path_number);
  			for (it_path_maini = path_maini.begin(); it_path_maini != path_maini.end(); ++it_path_maini)
          if(msc_debug_settlement_algorithm_fifo) PrintingEdge(*it_path_maini);
      }

      path_main.push_back(path_maini);
		}
  }

  if(msc_debug_settlement_algorithm_fifo) PrintToLog("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
  if (path_main.size() != 0)
  {
    if(msc_debug_settlement_algorithm_fifo) PrintToLog("\n\nMain Graph for Settlement:\n\n");
  	for (it_path_main = path_main.begin(); it_path_main != path_main.end(); ++it_path_main)
      PrintingGraph(*it_path_main);
  }

  if(msc_debug_settlement_algorithm_fifo) {
      PrintToLog("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
      PrintToLog("Second Part: Lives Vectors and Ghost Nodes\n\n");

      PrintToLog("\n*************************************************");
      PrintToLog("\nAddresses with Lives Non Zero\n\n");
  }

  std::vector<std::string> AddrsV = AddressesList(path_main);
  std::vector<std::string> AddrsLivesNonZero = LivesNonZero(path_main, AddrsV);
  for (std::vector<std::string>::iterator it = AddrsLivesNonZero.begin(); it != AddrsLivesNonZero.end(); ++it)
    if(msc_debug_settlement_algorithm_fifo) PrintToLog("%s\n", *it);

  if(msc_debug_settlement_algorithm_fifo) {
      PrintToLog("\n*************************************************");
      PrintToLog("\nComputing Lives contracts in the Main Graph\n");
  }

  std::vector<std::map<std::string, std::string>> LivesLongs;
  std::vector<std::map<std::string, std::string>> LivesShorts;
  std::map<std::string, std::string> LivesLongsEle;
  std::map<std::string, std::string> LivesShortsEle;

  std::vector<std::vector<std::map<std::string, std::string>>>::reverse_iterator rit_path_main;
  std::vector<std::map<std::string, std::string>>::reverse_iterator rit_path_maini;

  for (std::vector<std::string>::iterator it_addrs = AddrsV.begin(); it_addrs != AddrsV.end(); ++it_addrs)
    {
      std::string &AddrsLives = *it_addrs;

      std::string Status  = "None";
      long int NLives 	  = 0;
      long int EdgeRow 	  = 0;
      long int PathNumber = 0;
      double EntryPrice   = 0;
      int IdPosition 	  = 0;
      int NEvents         = 0;
      bool Loop = true;

      for (rit_path_main = path_main.rbegin(); rit_path_main != path_main.rend() && Loop; ++rit_path_main)
	{
	  for (rit_path_maini = (*rit_path_main).rbegin(); rit_path_maini != (*rit_path_main).rend() && Loop; ++rit_path_maini)
	    {
	      std::map<std::string, std::string> &GraphEdge = *rit_path_maini;
	      struct EdgeInfo *PtStatusByEdge = GetEdgeInfo(GraphEdge);

	      if (PtStatusByEdge->addrs_src == AddrsLives)
		{
		  NEvents += 1;
		  IdPosition = finding_string("Long", PtStatusByEdge->status_src) ? 0 : 1;
		  Status = PtStatusByEdge->status_src;
		  NLives = PtStatusByEdge->lives_src;
		  EntryPrice = PtStatusByEdge->entry_price;
		  EdgeRow = PtStatusByEdge->edge_row;
		  PathNumber = PtStatusByEdge->path_number;

		  if (finding_string("Open", PtStatusByEdge->status_src))
		    {
		      // PrintToLog("\n* Open. Last Action for: %s = %s; Edge Row = %d\n", AddrsLives, Status, EdgeRow);
		      PushBackLives(IdPosition, AddrsLives, Status, NLives, EntryPrice, EdgeRow, PathNumber, LivesLongsEle,
				    LivesLongs, LivesShortsEle, LivesShorts);
		      Loop = false;
		    }
		  else if (finding_string("Increased", PtStatusByEdge->status_src))
		    {
		      // PrintToLog("\n* Increased. Last Action for: %s = %s; Edge Row = %d\n", AddrsLives, Status, EdgeRow);
		      IncreasedLastPos(path_main, EdgeRow, AddrsLives, LivesLongsEle, LivesLongs, LivesShortsEle, LivesShorts);
		      Loop =  false;
		    }
		  else if (finding_string("NettedPartly", PtStatusByEdge->status_src))
		    {
		      // PrintToLog("\n* NettedPartly. Last Action for: %s = %s; Edge Row = %d\n", AddrsLives, Status, EdgeRow);
		      PushBackLives(IdPosition, AddrsLives, Status, NLives, EntryPrice, EdgeRow, PathNumber, LivesLongsEle,
				    LivesLongs, LivesShortsEle, LivesShorts);
		      Loop =  false;
		    }
		}
	      else if (PtStatusByEdge->addrs_trk == AddrsLives)
		{
		  NEvents += 1;
		  IdPosition = finding_string("Long", PtStatusByEdge->status_trk) ? 0 : 1;
		  Status = PtStatusByEdge->status_trk;
		  NLives = PtStatusByEdge->lives_trk;
		  EntryPrice = PtStatusByEdge->entry_price;
		  EdgeRow = PtStatusByEdge->edge_row;
		  PathNumber = PtStatusByEdge->path_number;

		  if (finding_string("Open", PtStatusByEdge->status_trk))
		    {
		      // PrintToLog("\n* Open. Last Action for: %s = %s; Edge Row = %d\n", AddrsLives, Status, EdgeRow);
		      PushBackLives(IdPosition, AddrsLives, Status, NLives, EntryPrice, EdgeRow, PathNumber, LivesLongsEle,
				    LivesLongs, LivesShortsEle, LivesShorts);
		      Loop = false;
		    }
		  else if (finding_string("Increased", PtStatusByEdge->status_trk))
		    {
		      IncreasedLastPos(path_main, EdgeRow, AddrsLives, LivesLongsEle, LivesLongs, LivesShortsEle, LivesShorts);
		      // PrintToLog("\n* Increased. Last Action for: %s = %s; Edge Row = %d\n", AddrsLives, Status, EdgeRow);
		      Loop =  false;
		    }
		  else if (finding_string("NettedPartly", PtStatusByEdge->status_trk))
		    {
		      // PrintToLog("\n* NettedPartly. Last Action for: %s = %s; Edge Row = %d\n", AddrsLives, Status, EdgeRow);
		      PushBackLives(IdPosition, AddrsLives, Status, NLives, EntryPrice, EdgeRow, PathNumber, LivesLongsEle,
				    LivesLongs, LivesShortsEle, LivesShorts);
		      Loop =  false;
		    }
		}
	      else
		continue;
	    }
	  }
  }

  if(msc_debug_settlement_algorithm_fifo) PrintToLog("\n*************************************************\n");
  double exit_price_desired = 0;
  long int sum_oflives 	    = 0;
  double PNL_total 	    = 0;
  double gamma_p 	    = 0;
  double gamma_q 	    = 0;
  double sum_gamma_p 	    = 0;
  double sum_gamma_q 	    = 0;

  for (it_path_main = path_main.begin(); it_path_main != path_main.end(); ++it_path_main)
  {
    computing_settlement_exitprice(*it_path_main, sum_oflives, PNL_total, gamma_p, gamma_q, interest, twap_price);
    sum_gamma_p += gamma_p;
    sum_gamma_q += gamma_q;
  }

  exit_price_desired = sum_gamma_p/sum_gamma_q;
  if(msc_debug_settlement_algorithm_fifo) PrintToLog("\nexit_price_desired = %d\n", exit_price_desired);
  counting_lives_longshorts(LivesLongs, LivesShorts);

  if(msc_debug_settlement_algorithm_fifo) {
      PrintToLog("\n*************************************************");
      PrintToLog("\nGhost Edges Vector:\n\n");
  }

  std::vector<std::map<std::string, std::string>> GhostEdgesArray;
  GhostEdgesComputing(LivesLongs, LivesShorts, exit_price_desired, GhostEdgesArray);

  std::vector<std::map<std::string, std::string>>::iterator it_ghost;
  for (it_ghost = GhostEdgesArray.begin(); it_ghost != GhostEdgesArray.end(); ++it_ghost) PrintingGhostEdge(*it_ghost);

  if(msc_debug_settlement_algorithm_fifo) PrintToLog("\n*************************************************");

  std::unordered_set<std::string> addrs_set;
  std::vector<std::string> addrsv;
  int k = 0;
  long int nonzero_lives = 0;
  double PNL_totalit = 0;

  /** Total PNL for Main Path **/
  for (it_path_main = path_main.begin(); it_path_main != path_main.end(); ++it_path_main)
  {
    k += 1;
    if(msc_debug_settlement_algorithm_fifo) {
        PrintToLog("\nPath #%d: PNL computation for the main path\n", k);
        printing_path_maini(*it_path_main);
    }

    nonzero_lives = checkpath_livesnonzero(*it_path_main);
    listof_addresses_bypath(*it_path_main, addrsv);

    if(msc_debug_settlement_algorithm_fifo) PrintToLog("\nComputing PNL in this Path\n");
    calculate_pnltrk_bypath(*it_path_main, PNL_totalit, addrs_set, addrsv, interest, twap_price);
    PNL_total += PNL_totalit;
    if(msc_debug_settlement_algorithm_fifo) PrintToLog("\nPNL_total_main sum: %f\n", PNL_total);
    addrs_set.clear();
  }

  /** Total PNL for Ghost Nodes **/
  if(msc_debug_settlement_algorithm_fifo) {
      PrintToLog("\n*************************************************");
      PrintToLog("\nChecking PNL for Ghost Nodes:\n");
  }

  calculate_pnl_forghost(GhostEdgesArray, PNL_total);

  if(msc_debug_settlement_algorithm_fifo) {
      PrintToLog("\nPNL_total_main = %f", PNL_total);
      PrintToLog("\n\n");
  }

  if(msc_debug_settlement_algorithm_fifo) PrintToLog("\nnonzero_lives : %d\n",nonzero_lives);

}

void PushBackLives(int IdPosition, std::string AddrsLives, std::string Status, long int NLives, double EntryPrice, long int EdgeRow, long int PathNumber, std::map<std::string, std::string> LivesLongsEle, std::vector<std::map<std::string, std::string>> &LivesLongs, std::map<std::string, std::string> LivesShortsEle, std::vector<std::map<std::string, std::string>> &LivesShorts)
{
  if (IdPosition == 0)
    {
      building_lives_edges(LivesLongsEle, AddrsLives, Status, NLives, EntryPrice, EdgeRow, PathNumber);
      LivesLongs.push_back(LivesLongsEle);
    }
  else
    {
      building_lives_edges(LivesShortsEle, AddrsLives, Status, NLives, EntryPrice, EdgeRow, PathNumber);
      LivesShorts.push_back(LivesShortsEle);
    }
}

void IncreasedLastPos(std::vector<std::vector<std::map<std::string, std::string>>> path_main, long int LastEdgeRow, std::string AddrsLives, std::map<std::string, std::string> LivesLongsEle, std::vector<std::map<std::string, std::string>> &LivesLongs, std::map<std::string, std::string> LivesShortsEle, std::vector<std::map<std::string, std::string>> &LivesShorts)
{
  std::vector<std::vector<std::map<std::string, std::string>>>::reverse_iterator rit_path_main;
  std::vector<std::map<std::string, std::string>>::reverse_iterator rit_path_maini;

  std::string Status  = "None";
  long int EdgeRow    = 0;
  long int PathNumber = 0;
  long int AmountTrd  = 0;
  double EntryPrice   = 0;
  int IdPosition      = 0;
  bool Loop = true;

  for (rit_path_main = path_main.rbegin(); rit_path_main != path_main.rend() && Loop; ++rit_path_main)
    {
      for (rit_path_maini = (*rit_path_main).rbegin(); rit_path_maini != (*rit_path_main).rend() && Loop; ++rit_path_maini)
	{
	  std::map<std::string, std::string> &GraphEdge = *rit_path_maini;
	  struct EdgeInfo *PtStatusByEdge = GetEdgeInfo(GraphEdge);

	  EdgeRow = PtStatusByEdge->edge_row;

	  /*******************************************************/
	  /** Look back for Increase Events Until Open is Found **/
	  if (EdgeRow <= LastEdgeRow)
	    {
	      if (PtStatusByEdge->addrs_src == AddrsLives)
		{
		  // PrintToLog("\nEdgeRow = %d\n", EdgeRow);
		  // PrintingEdge(GraphEdge);

		  IdPosition = finding_string("Long", PtStatusByEdge->status_src) ? 0 : 1;
		  Status     = PtStatusByEdge->status_src;
		  AmountTrd  = PtStatusByEdge->amount_trd_src; /** AmountTrd Represent Lives Increased Events **/
		  EntryPrice = PtStatusByEdge->entry_price;
		  EdgeRow    = PtStatusByEdge->edge_row;
		  PathNumber = PtStatusByEdge->path_number;
		  Loop = finding_string("Open", PtStatusByEdge->status_src) ? false : true; /** When Open appear Finish**/

		  PushBackLives(IdPosition, AddrsLives, Status, AmountTrd, EntryPrice, EdgeRow, PathNumber, LivesLongsEle,
				LivesLongs, LivesShortsEle, LivesShorts);
		}
	      else if (PtStatusByEdge->addrs_trk == AddrsLives)
		{
		  // PrintToLog("\nEdgeRow = %d\n", EdgeRow);
		  // PrintingEdge(GraphEdge);

		  IdPosition = finding_string("Long", PtStatusByEdge->status_trk) ? 0 : 1;
		  Status     = PtStatusByEdge->status_trk;
		  AmountTrd  = PtStatusByEdge->amount_trd_trk; /** AmountTrd Represent Lives Increased Events **/
		  EntryPrice = PtStatusByEdge->entry_price;
		  EdgeRow    = PtStatusByEdge->edge_row;
		  PathNumber = PtStatusByEdge->path_number;
		  Loop = finding_string("Open", PtStatusByEdge->status_trk) ? false : true; /** When Open appear Finish**/

		  PushBackLives(IdPosition, AddrsLives, Status, AmountTrd, EntryPrice, EdgeRow, PathNumber, LivesLongsEle,
				LivesLongs, LivesShortsEle, LivesShorts);
		}
	    }
	}
    }
}

void clearing_operator_fifo(VectorTLS &vdata, MatrixTLS &M_file, int index_init, struct status_amounts *pt_pos, int idx_long_short, int &counting_netted, long int amount_trd_sum, std::vector<std::map<std::string, std::string>> &path_main, int path_number, long int opened_contracts, int idx_b)
{
  VectorTLS status_z(2);
  std::string addrs_opening = pt_pos->addrs_trk;
  long int d_amounts = 0;
  std::map<std::string, std::string> path_first;

  if(msc_debug_clearing_operator_fifo) {
      PrintToLog("\n---------------------------------------------------\n");
      PrintToLog("LAUNCHING FIFO CLEARING\n");
      PrintToLog("...\n");
  }

  for (int i = index_init + 1; i < n_rows; ++i)
  {
    VectorTLS jrow_database(n_cols);
    sub_row(jrow_database, M_file, i);

    if ( finding(addrs_opening, jrow_database) )
    {
	  	struct status_amounts *pt_status_addrs_trk = get_status_amounts_byaddrs(jrow_database, addrs_opening);
	  	VectorTLS status_netted = status_netted_npartly(status_z, idx_long_short);

	  	if ( finding(pt_status_addrs_trk->status_trk, status_netted) && pt_status_addrs_trk->nlives_trk != 0 )
	    {
        counting_netted +=1;
	      amount_trd_sum += pt_status_addrs_trk->nlives_trk;

        if(msc_debug_clearing_operator_fifo) {
            PrintToLog("\n\nNetted Event in the Row #%d\t Address Tracked: %s\n", i, addrs_opening.c_str());
	          printing_vector(jrow_database);
	          PrintToLog("\n\nopened_contracts = %d, nlives_trk = %d, amount_trd_sum = %d\n", opened_contracts, pt_status_addrs_trk->nlives_trk, amount_trd_sum);
        }

	      d_amounts = opened_contracts - amount_trd_sum;

        if(msc_debug_clearing_operator_fifo) PrintToLog("\n\nReview of d_amounts before cases:\t%ld", d_amounts);

	      if ( d_amounts > 0 )
				{
          if(msc_debug_clearing_operator_fifo) PrintToLog("\n\nd_amounts = %ld > 0", d_amounts);
		  		updating_lasttwocols_fromdatabase(addrs_opening, M_file, i, 0);

          if(msc_debug_clearing_operator_fifo) {
		  		    PrintToLog("\n\nCheck last two columns Updated: Row #%d \n %s \t %s", i, M_file[i][8], M_file[i][9]);
		  		    PrintToLog("\nOpened contrats: %ld > Sum amounts traded: %ld\n", opened_contracts, amount_trd_sum);
          }

		  		building_edge(path_first,
                        pt_status_addrs_trk->addrs_src, pt_status_addrs_trk->addrs_trk,
					              pt_status_addrs_trk->status_src, pt_status_addrs_trk->status_trk,
                        pt_pos->matched_price, pt_status_addrs_trk->matched_price,
                        pt_status_addrs_trk->lives_src, d_amounts,
                        i, path_number, pt_status_addrs_trk->nlives_trk, 0);

          path_main.push_back(path_first);

          if(msc_debug_clearing_operator_fifo) {
		  		    PrintToLog("\nEdge:\n");
		  		    PrintingEdge(path_first);
          }
		  		continue;
				}

	      if ( d_amounts < 0)
				{
		  		if(msc_debug_clearing_operator_fifo) PrintToLog("\n\nd_amounts = %ld < 0", d_amounts);
		  		updating_lasttwocols_fromdatabase(addrs_opening, M_file, i, labs(d_amounts));

          if(msc_debug_clearing_operator_fifo) {
		  		      PrintToLog("\n\nCheck last two columns Updated: Row #%d \n %s \t %s", i, M_file[i][8], M_file[i][9]);
		  		      PrintToLog("\nOpened contrats: %ld < Sum amounts traded: %ld\n", opened_contracts, amount_trd_sum);
          }

		  		building_edge(path_first,
                        pt_status_addrs_trk->addrs_src, pt_status_addrs_trk->addrs_trk,
                        pt_status_addrs_trk->status_src, pt_status_addrs_trk->status_trk,
                        pt_pos->matched_price, pt_status_addrs_trk->matched_price,
                        pt_status_addrs_trk->lives_src, 0,
                        i, path_number, pt_status_addrs_trk->nlives_trk-labs(d_amounts), 0);
		  		path_main.push_back(path_first);

          if(msc_debug_clearing_operator_fifo) {
		  		    PrintToLog("\nEdge:\n");
		  		    PrintingEdge(path_first);
          }

		  		break;
				}

	      if ( d_amounts == 0)
				{
		  		if(msc_debug_clearing_operator_fifo) PrintToLog("\n\nd_amounts = %ld = 0", d_amounts);
		  		updating_lasttwocols_fromdatabase(addrs_opening, M_file, i, 0);

          if(msc_debug_clearing_operator_fifo) {
		  		    PrintToLog("\n\nCheck last two columns Updated: Row #%d \n %s \t %s", i, M_file[i][8], M_file[i][9]);
		  		    PrintToLog("\nOpened contrats: %ld = Sum amounts traded: %ld\n", opened_contracts, amount_trd_sum);
          }

		  		building_edge(path_first,
                        pt_status_addrs_trk->addrs_src, pt_status_addrs_trk->addrs_trk,
					              pt_status_addrs_trk->status_src, pt_status_addrs_trk->status_trk,
                        pt_pos->matched_price, pt_status_addrs_trk->matched_price,
                        pt_status_addrs_trk->lives_src, 0,
                        i, path_number, pt_status_addrs_trk->nlives_trk, 0);
		  		path_main.push_back(path_first);

          if(msc_debug_clearing_operator_fifo) {
              PrintToLog("\nEdge:\n");
		  		    PrintingEdge(path_first);
          }

		  		break;
				}
	   	}
    }
  }

  if (idx_b == 1) path_main.erase(path_main.begin());;

  if(msc_debug_clearing_operator_fifo) {
      PrintToLog("\nFINISHING FIFO SEARCH");
      PrintToLog("\n---------------------------------------------------\n");
  }

}

void updating_lasttwocols_fromdatabase(std::string addrs, MatrixTLS &M_file, int i, long int live_updated)
{
  if ( addrs == M_file[i][0] )
    M_file[i][8] = std::to_string(live_updated);
  else
    M_file[i][9] = std::to_string(live_updated);
}

void building_edge(std::map<std::string, std::string> &path_first, std::string addrs_src, std::string addrs_trk, std::string status_src, std::string status_trk, double entry_price, double exit_price, long int lives, int index_row, int path_number, long int amount_path, int ghost_edge)
{
  path_first["addrs_src"]   = addrs_src;
  path_first["addrs_trk"]   = addrs_trk;
  path_first["status_src"]  = status_src;
  path_first["status_trk"]  = status_trk;
  path_first["entry_price"] = std::to_string(entry_price);
  path_first["exit_price"]  = std::to_string(exit_price);
  path_first["lives_src"]   = std::to_string(lives);
  path_first["lives_trk"]   = std::to_string(lives);
  path_first["amount_trd"]  = std::to_string(amount_path);
  path_first["edge_row"]    = std::to_string(index_row);
  path_first["path_number"] = std::to_string(path_number);
  path_first["ghost_edge"]  = std::to_string(ghost_edge);
}

void building_edge(std::map<std::string, std::string> &path_first, std::string addrs_src, std::string addrs_trk, std::string status_src, std::string status_trk, double entry_price, double exit_price, long int lives_src, long int lives_trk, int index_row, int path_number, long int amount_path, int ghost_edge)
{
  path_first["addrs_src"]      = addrs_src;
  path_first["addrs_trk"]      = addrs_trk;
  path_first["status_src"]     = status_src;
  path_first["status_trk"]     = status_trk;
  path_first["entry_price"]    = std::to_string(entry_price);
  path_first["exit_price"]     = std::to_string(exit_price);
  path_first["lives_src"]      = std::to_string(lives_src);
  path_first["lives_trk"]      = std::to_string(lives_trk);
  path_first["amount_trd_src"] = std::to_string(amount_path);
  path_first["amount_trd_trk"] = std::to_string(amount_path);
  path_first["edge_row"]       = std::to_string(index_row);
  path_first["path_number"]    = std::to_string(path_number);
  path_first["ghost_edge"]     = std::to_string(ghost_edge);
}

void BuildingGhostEdges(std::map<std::string, std::string> &path_first, std::string addrs_src, std::string addrs_trk, std::string status_src, std::string status_trk, string entry_price_src, string entry_price_trk, double exit_price, long int amount_path)
{
  path_first["addrs_src"]       = addrs_src;
  path_first["addrs_trk"]       = addrs_trk;
  path_first["status_src"]      = status_src;
  path_first["status_trk"]      = status_trk;
  path_first["entry_price_src"] = entry_price_src;
  path_first["entry_price_trk"] = entry_price_trk;
  path_first["exit_price"]      = std::to_string(exit_price);
  path_first["amount_trd"]      = std::to_string(amount_path);
}

void building_lives_edges(std::map<std::string, std::string> &path_first, std::string addrs, std::string status, long int lives, double entry_price, struct status_amounts_edge *pt_status_byedge)
{
  path_first["addrs"] 	    = addrs;
  path_first["status"] 	    = status;
  path_first["lives"] 	    = std::to_string(lives);
  path_first["entry_price"] = std::to_string(entry_price);
  path_first["edge_row"]    = std::to_string(pt_status_byedge->edge_row);
  path_first["path_number"] = std::to_string(pt_status_byedge->path_number);
}

void building_lives_edges(std::map<std::string, std::string> &path_first, std::string addrs, std::string status, long int lives, double entry_price, long int edge_row, long int path_number)
{
  path_first["addrs"] 	    = addrs;
  path_first["status"] 	    = status;
  path_first["lives"]  	    = std::to_string(lives);
  path_first["entry_price"] = std::to_string(entry_price);
  path_first["edge_row"]    = std::to_string(edge_row);
  path_first["path_number"] = std::to_string(path_number);
}

void printing_edges(std::map<std::string, std::string> &path_first)
{
  PrintToLog("{ addrs_src : %s , status_src : %s, lives_src : %d, addrs_trk : %s , status_trk : %s, lives_trk : %d, entry_price : %d, exit_price : %d, amount_trd : %d, edge_row : %d, path_number : %d, ghost_edge : %d }\n", path_first["addrs_src"], path_first["status_src"], path_first["lives_src"], path_first["addrs_trk"], path_first["status_trk"], path_first["lives_trk"], path_first["entry_price"], path_first["exit_price"], path_first["amount_trd"], path_first["edge_row"], path_first["path_number"], path_first["ghost_edge"]);
}

void PrintingEdge(std::map<std::string, std::string> &path_first)
{
  PrintToLog("{ addrs_src : %s , status_src : %s, lives_src : %d, amount_trd_src : %d, addrs_trk : %s , status_trk : %s, lives_trk : %d, amount_trd_trk : %d, entry_price : %d, exit_price : %d, edge_row : %d, path_number : %d, ghost_edge : %d }\n", path_first["addrs_src"], path_first["status_src"], path_first["lives_src"], path_first["amount_trd_src"], path_first["addrs_trk"], path_first["status_trk"], path_first["lives_trk"], path_first["amount_trd_trk"], path_first["entry_price"], path_first["exit_price"], path_first["edge_row"], path_first["path_number"], path_first["ghost_edge"]);
}

void PrintingGhostEdge(std::map<std::string, std::string> &path_first)
{
  PrintToLog("{ addrs_src : %s , status_src : %s, entry_price_src : %d, addrs_trk : %s , status_trk : %s, entry_price_trk : %d, exit_price : %d, amount_trd : %d}\n", path_first["addrs_src"], path_first["status_src"], path_first["entry_price_src"], path_first["addrs_trk"], path_first["status_trk"], path_first["entry_price_trk"], path_first["exit_price"], path_first["amount_trd"]);
}

void printing_edges_lives(std::map<std::string, std::string> &path_first)
{
  PrintToLog("{ addrs : %s , status : %s, lives : %d, entry_price : %d, edge_row : %d, path_number : %d }\n", path_first["addrs"], path_first["status"], path_first["lives"], path_first["entry_price"], path_first["edge_row"], path_first["path_number"]);
}

bool find_open_incr_anypos(std::string &s, VectorTLS *v)
{
  VectorTLS open_incr_anypos(4);
  VectorTLS &u = *v;
  for (int i = 0; i < length(open_incr_anypos); i++) open_incr_anypos[i] = u[i];
  return finding(s, open_incr_anypos);
}

bool find_netted_npartly_anypos(std::string &s, VectorTLS *v)
{
  VectorTLS netted_npartly_anypos(4);
  VectorTLS &u = *v;
  for (int i = 0; i < length(netted_npartly_anypos); i++) netted_npartly_anypos[i] = u[i];
  return finding(s, netted_npartly_anypos);
}

bool find_open_incr_long(std::string &s, VectorTLS *v)
{
  VectorTLS open_incr_long(2);
  VectorTLS &u = *v;
  for (int i = 0; i < length(open_incr_long); i++) open_incr_long[i] = u[i];
  return finding(s, open_incr_long);
}

void looking_netted_events(std::string &addrs_obj, std::vector<std::map<std::string, std::string>> &it_path_main, int q, long int amount_opened, int index_src_trk, std::string status_opening)
{
  long int sum_amount_trd = 0;
  int netted_counter = 0;
  unsigned index_netted = 0;

  for (unsigned i = q; i < it_path_main.size(); ++i)
    {
      struct status_amounts_edge *pt_status_byedge = get_status_byedge(it_path_main[i]);

      if ( sum_amount_trd > amount_opened ) break;

      if ( pt_status_byedge->addrs_trk == addrs_obj )
      	{
	  if ( finding_string("Long", status_opening) && finding_string("Long", pt_status_byedge->status_trk) )
	    {
	      index_netted = i;
	      netted_counter += 1;
	      sum_amount_trd += pt_status_byedge->amount_trd;
	    }
	  if ( finding_string("Short", status_opening) && finding_string("Short", pt_status_byedge->status_trk) )
	    {
	      index_netted = i;
	      netted_counter += 1;
	      sum_amount_trd += pt_status_byedge->amount_trd;
	    }
	}
    }

  bool check = sum_amount_trd <= amount_opened;
  if ( netted_counter != 0 )
    it_path_main[index_netted]["lives_trk"] = check ? std::to_string(amount_opened - sum_amount_trd) : std::to_string(0);
  else
    {
      PrintToLog("\nindex q = %d\n", q);
      if ( index_src_trk == 0 )
	it_path_main[q-1]["lives_src"] = std::to_string(amount_opened);
      else if ( index_src_trk == 1 )
	it_path_main[q-1]["lives_trk"] = std::to_string(amount_opened);
    }
}

void printing_path_maini(std::vector<std::map<std::string, std::string>> &it_path_maini)
{
  for (std::vector<std::map<std::string, std::string>>::iterator it = it_path_maini.begin(); it != it_path_maini.end(); ++it)
    printing_edges(*it);
}

void PrintingGraph(std::vector<std::map<std::string, std::string>> &it_path_maini)
{
  for (std::vector<std::map<std::string, std::string>>::iterator it = it_path_maini.begin(); it != it_path_maini.end(); ++it)
    PrintingEdge(*it);
}

void checking_zeronetted_bypath(std::vector<std::map<std::string, std::string>> path_maini)
{
  long int contracts_closed = 0;
  long int contracts_opened = 0;

  VectorTLS &open_incr_anypos = *pt_open_incr_anypos;

  if (finding(path_maini[0]["status_src"], open_incr_anypos) && finding(path_maini[0]["status_trk"], open_incr_anypos))
    contracts_opened = 2*std::stol(path_maini[0]["amount_trd"]);
  else
    contracts_opened = std::stol(path_maini[0]["amount_trd"]);

  long int contracts_lives = std::stol(path_maini[0]["lives_src"])+std::stol(path_maini[0]["lives_trk"]);

  int idx_q = 0;
  // Counting closed contracts. Netted eventes are followed by addrs_trk!!
  for (std::vector<std::map<std::string, std::string>>::iterator it = path_maini.begin()+1; it != path_maini.end(); ++it)
    {
      idx_q += 1;
      struct status_amounts_edge *pt_status_byedge = get_status_byedge(*it);
      if (path_maini[0]["addrs_trk"] == pt_status_byedge->addrs_trk)
	{
	  if (find_netted_npartly_anypos(pt_status_byedge->status_trk, pt_netted_npartly_anypos))
	    {
	      path_maini[idx_q]["addrs_src"]   = std::string();
	      path_maini[idx_q]["addrs_trk"]   = std::string();
	      path_maini[idx_q]["status_src"]  = std::string();
	      path_maini[idx_q]["status_trk"]  = std::string();
	      path_maini[idx_q]["entry_price"] = std::to_string(0);
	      path_maini[idx_q]["exit_price"]  = std::to_string(0);
	      path_maini[idx_q]["lives_src"]   = std::to_string(0);
	      path_maini[idx_q]["lives_trk"]   = std::to_string(0);
	      path_maini[idx_q]["amount_trd"]  = std::to_string(0);
	      path_maini[idx_q]["edge_row"]    = std::to_string(0);
	      path_maini[idx_q]["path_number"] = std::to_string(0);
	      path_maini[idx_q]["ghost_edge"]  = std::to_string(0);
	      contracts_closed += pt_status_byedge->amount_trd;
	    }
	}
    }

  for (std::vector<std::map<std::string, std::string>>::iterator it = path_maini.begin()+1; it != path_maini.end(); ++it)
    {
      struct status_amounts_edge *pt_status_byedge = get_status_byedge(*it);
      if (path_maini[0]["addrs_src"] == pt_status_byedge->addrs_trk)
      	{
      	  if (find_netted_npartly_anypos(pt_status_byedge->status_trk, pt_netted_npartly_anypos))
	    contracts_closed += pt_status_byedge->amount_trd;
      	}
    }

  PrintToLog("\ncontracts_opened = %d, contracts_closed = %d, contracts_lives = %d\n",
  	     contracts_opened, contracts_closed, contracts_lives);
  if ( (contracts_opened - contracts_closed)-contracts_lives == 0 )
    PrintToLog("\nChecking Zero Netted by Path:\n(contracts_opened - contracts_closed)-contracts_lives = %d\n",
  	       (contracts_opened - contracts_closed)-contracts_lives);
  else
    PrintToLog("¡¡Warning!! There is no zero netted event in the path");
}

void computing_livesvectors_forlongshort(std::vector<std::map<std::string, std::string>> &it_path_main, std::vector<std::map<std::string, std::string>> &lives_longs, std::vector<std::map<std::string, std::string>> &lives_shorts)
{
	std::map<std::string, std::string> path_ele;

  	for (std::vector<std::map<std::string, std::string>>::iterator it = it_path_main.begin(); it != it_path_main.end(); ++it)
    {
    	struct status_amounts_edge *pt_status_byedge = get_status_byedge(*it);
      	if ( pt_status_byedge->lives_src != 0 )
		{
	  		building_lives_edges(path_ele, pt_status_byedge->addrs_src, pt_status_byedge->status_src, pt_status_byedge->lives_src, pt_status_byedge->exit_price, pt_status_byedge);

	  		if ( finding_string("Long", pt_status_byedge->status_src) )
	    		lives_longs.push_back(path_ele);
	  		else if ( finding_string("Short", pt_status_byedge->status_src) )
	    		lives_shorts.push_back(path_ele);
		}
      	if ( pt_status_byedge->lives_trk != 0 )
		{
	  		building_lives_edges(path_ele, pt_status_byedge->addrs_trk, pt_status_byedge->status_trk, pt_status_byedge->lives_trk, pt_status_byedge->entry_price, pt_status_byedge);

	  		if ( finding_string("Long", pt_status_byedge->status_trk) )
	    		lives_longs.push_back(path_ele);
	  		else if ( finding_string("Short", pt_status_byedge->status_trk) )
	    		lives_shorts.push_back(path_ele);
		}
    }
}

void counting_lives_longshorts(std::vector<std::map<std::string, std::string>> &lives_longs, std::vector<std::map<std::string, std::string>> &lives_shorts)
{
  long int nlives_longs = 0;
  long int nlives_shorts = 0;

  if(msc_debug_counting_lives_longshorts) PrintToLog("\nList of Long Lives:\n");
  for (std::vector<std::map<std::string, std::string>>::iterator it = lives_longs.begin(); it != lives_longs.end(); ++it)
    {
      if(msc_debug_counting_lives_longshorts) printing_edges_lives(*it);
      nlives_longs += stol((*it)["lives"]);
    }
  if(msc_debug_counting_lives_longshorts) PrintToLog("\nList of Short Lives:\n");
  for (std::vector<std::map<std::string, std::string>>::iterator it = lives_shorts.begin(); it != lives_shorts.end(); ++it)
    {
      if(msc_debug_counting_lives_longshorts) printing_edges_lives(*it);
      nlives_shorts += stol((*it)["lives"]);
    }
  if(msc_debug_counting_lives_longshorts) PrintToLog("\n|nlives_longs| : %d, \n|nlives_shorts| : %d\n", nlives_longs, nlives_shorts);
  if (nlives_longs != nlives_shorts) PrintToLog("\n\nWarning!! Lives Longs sould be equal to Lives Shorts\n\n");
}

void computing_livesvector_global(std::vector<std::map<std::string, std::string>> lives_longs, std::vector<std::map<std::string, std::string>> lives_shorts, std::vector<std::map<std::string, std::string>> &lives_longs_vg, std::vector<std::map<std::string, std::string>> &lives_shorts_vg)
{
  getting_globallives_long_short(lives_longs, lives_longs_vg);
  getting_globallives_long_short(lives_shorts, lives_shorts_vg);
}

void printing_lives_vector(std::vector<std::map<std::string, std::string>> lives)
{
  for (std::vector<std::map<std::string, std::string>>::iterator it = lives.begin(); it != lives.end(); ++it)
    {
      printing_edges_lives(*it);
    }
}

void getting_globallives_long_short(std::vector<std::map<std::string, std::string>> lives, std::vector<std::map<std::string, std::string>> &lives_vg)
{
  for (std::vector<std::map<std::string, std::string>>::iterator it = lives.begin(); it != lives.end(); ++it)
    lives_vg.push_back(*it);
}

bool find_address_lives_vector(std::vector<std::map<std::string, std::string>> lives_v, std::string address)
{
  for (std::vector<std::map<std::string, std::string>>::iterator it = lives_v.begin(); it != lives_v.end(); ++it)
    {
      struct status_lives_edge *pt_status_bylivesedge = get_status_bylivesedge(*it);
      if (pt_status_bylivesedge->addrs == address)
	{
	  return true;
	}
    }
  return false;
}

int find_posaddress_lives_vector(std::vector<std::map<std::string, std::string>> lives_v, std::string address)
{
  int idx_q = 0;
  for (std::vector<std::map<std::string, std::string>>::iterator it = lives_v.begin(); it != lives_v.end(); ++it)
    {
      idx_q += 1;
      struct status_lives_edge *pt_status_bylivesedge = get_status_bylivesedge(*it);
      if (pt_status_bylivesedge->addrs == address)
	{
	  return idx_q-1;
	}
    }
  return idx_q-1;
}

void computing_settlement_exitprice(std::vector<std::map<std::string, std::string>> &it_path_main, long int &sum_oflives, double &PNL_total, double &gamma_p, double &gamma_q, int64_t interest, int64_t twap_price)
{
  long int sum_oflivesh = 0;
  std::unordered_set<std::string> addrs_set;
  std::vector<std::string> addrsv;

  for (std::vector<std::map<std::string, std::string>>::iterator it = it_path_main.begin(); it != it_path_main.end(); ++it)
    {
      std::map<std::string, std::string> &it_ele = *it;
      sum_oflivesh += stol(it_ele["lives_src"]) + stol(it_ele["lives_trk"]);
    }
  sum_oflives = sum_oflivesh;

  if (sum_oflives == 0) PrintToLog("\nThis path does not have lives contracts!!\n");
  else
    {
      listof_addresses_bypath(it_path_main, addrsv);
      calculate_pnltrk_bypath(it_path_main, PNL_total, addrs_set, addrsv, interest, twap_price);
      getting_gammapq_bypath(it_path_main, PNL_total, gamma_p, gamma_q, addrs_set);
      addrs_set.clear();
    }
}

void calculate_pnltrk_bypath(std::vector<std::map<std::string, std::string>> &path_main, double &PNL_total, std::unordered_set<std::string> &addrs_set, std::vector<std::string> addrsv, int64_t interest, int64_t twap_price)
{
  std::vector<std::map<std::string, std::string>>::iterator it_path;
  std::string addrsit;
  double PNL_trk;
  double sumPNL_trk = 0;
  MatrixTLS &ndatabase = *pt_ndatabase;
  VectorTLS jrow_database(n_cols);

  for (std::vector<std::string>::iterator it_addrs = addrsv.begin(); it_addrs != addrsv.end(); ++it_addrs)
    {
      addrsit = *it_addrs;
      for (it_path = path_main.begin()+1; it_path != path_main.end(); ++it_path)
	{
	  std::map<std::string, std::string> &edge_path = *it_path;
	  if ( addrsit == edge_path["addrs_trk"] )
	    {
	      sub_row(jrow_database, ndatabase, stol(edge_path["edge_row"]));
	      struct status_amounts *pt_jrow_database = get_status_amounts_byaddrs(jrow_database, addrsit);
	      addrs_set.insert(addrsit);

	      PNL_trk = PNL_function(stod(edge_path["entry_price"]), stod(edge_path["exit_price"]), stol(edge_path["amount_trd"]),
				     pt_jrow_database);
	      sumPNL_trk += PNL_trk;

	      std::string addrssr = edge_path["addrs_src"];
	      int64_t PNL_trkInt64 = mastercore::DoubleToInt64(PNL_trk);

	      struct FutureContractObject *pfuture = getFutureContractObject("ALL F18");
	      uint32_t NotionalSize = pfuture->fco_notional_size;

	      arith_uint256 volumeALL256_t = mastercore::ConvertTo256(NotionalSize)*mastercore::ConvertTo256(PNL_trkInt64)/COIN;
	      int64_t volumeALL64_t = mastercore::ConvertTo64(volumeALL256_t);

	      struct TokenDataByName *pfuture_ALL = getTokenDataByName("ALL");
	      uint32_t ALLId = pfuture_ALL->data_propertyId;

	      // int64_t entry_priceh =  mastercore::StrToInt64(edge_path["entry_price"], true);
	      // PrintToLog("\nInterest Payment: Entry Price = %s, Twap Price = %s\n",
	      // 		 FormatDivisibleMP(entry_priceh), FormatDivisibleMP(twap_price));

	      if (volumeALL64_t != 0 && volumeALL64_t < getMPbalance(addrssr, ALLId, BALANCE))
		{
		  PrintToLog("\nRebalancing Settlement\n");
		  assert(mastercore::update_tally_map(addrssr, ALLId, -volumeALL64_t, BALANCE)); /** Change in testnet **/
		  assert(mastercore::update_tally_map(addrsit, ALLId,  volumeALL64_t, BALANCE)); /** Change in testnet**/
	       	}
	    }
	}
    }
  PNL_total = sumPNL_trk;
}

void calculate_pnltrk_bypath(std::vector<std::map<std::string, std::string>> path_main, double &PNL_total)
{
  std::vector<std::map<std::string, std::string>>::iterator it_path;
  double sumPNL_trk = 0;
  double PNL_trk;
  MatrixTLS &ndatabase = *pt_ndatabase;
  VectorTLS jrow_database(n_cols);

  //PrintToLog("\nChecking PNL in this Path:\n");
  for (it_path = path_main.begin(); it_path != path_main.end(); ++it_path)
    {
      sub_row(jrow_database, ndatabase, stol((*it_path)["edge_row"]));
      struct status_amounts *pt_jrow_database = get_status_amounts_byaddrs(jrow_database, (*it_path)["addrs_trk"]);
      PNL_trk = PNL_function(stod((*it_path)["entry_price"]), stod((*it_path)["exit_price"]), stol((*it_path)["amount_trd"]), pt_jrow_database);
      //PrintToLog("\nPNL_trk = %f\n", PNL_trk);
      sumPNL_trk += PNL_trk;
    }
  PNL_total = sumPNL_trk;
  //PrintToLog("\nPNL_total_thispath = %f\n", PNL_total);
}

void calculate_pnl_forghost(std::vector<std::map<std::string, std::string>> path_ghost, double &PNL_total)
{
  std::vector<std::map<std::string, std::string>>::iterator it_path;
  double sumPNL_trk = 0;
  double PNL_src;
  double PNL_trk;

  if(msc_debug_calculate_pnl_forghost) PrintToLog("\nChecking PNL for Ghosts\n");
  for (it_path = path_ghost.begin(); it_path != path_ghost.end(); ++it_path)
  {
    PNL_src = PNL_ghosts(stod((*it_path)["entry_price_src"]), stod((*it_path)["exit_price"]), stol((*it_path)["amount_trd"]), (*it_path)["status_src"]);
    PNL_trk = PNL_ghosts(stod((*it_path)["entry_price_trk"]), stod((*it_path)["exit_price"]), stol((*it_path)["amount_trd"]), (*it_path)["status_trk"]);
    sumPNL_trk += PNL_src + PNL_trk;
    if(msc_debug_calculate_pnl_forghost) PrintToLog("\nPNL_src = %f\t PNL_trk = %f\t sumPNL_trk = %f\n", PNL_src, PNL_trk, sumPNL_trk);
  }
}

void listof_addresses_lives(std::vector<std::map<std::string, std::string>> lives, std::vector<std::string> &addrsv)
{
	std::vector<std::string> addrsvh;
	for (std::vector<std::map<std::string, std::string>>::iterator it = lives.begin(); it != lives.end(); ++it)
    {
    	std::map<std::string, std::string> &it_ele = *it;
    	if ( !find_string_strv(it_ele["addrs"], addrsvh) )
    		addrsvh.push_back(it_ele["addrs"]);
    	else
    		continue;
    }
    addrsv = addrsvh;
}

std::vector<std::string> AddressesList(std::vector<std::vector<std::map<std::string, std::string>>> &path_main)
{
	std::vector<std::string> AddrsV;
	std::vector<std::map<std::string, std::string>>::iterator it_in;
	std::vector<std::vector<std::map<std::string, std::string>>>::iterator it_out;

	for (it_out = path_main.begin(); it_out != path_main.end(); ++it_out)
	{
		for (it_in = (*it_out).begin(); it_in != (*it_out).end(); ++it_in)
		{
			std::map<std::string, std::string> &it_ele = *it_in;

			if ( !find_string_strv(it_ele["addrs_src"], AddrsV))
			{
				AddrsV.push_back(it_ele["addrs_src"]);
			}

			if ( !find_string_strv(it_ele["addrs_trk"], AddrsV) )
			{
				AddrsV.push_back(it_ele["addrs_trk"]);
			}
		}
	}

  return AddrsV;
}

std::vector<std::string> LivesNonZero(std::vector<std::vector<std::map<std::string, std::string>>> &path_main, std::vector<std::string> AddrsV)
{
  std::vector<std::string> Result;
  std::vector<std::map<std::string, std::string>>::reverse_iterator it_in;
  std::vector<std::vector<std::map<std::string, std::string>>>::reverse_iterator it_out;

  for (std::vector<std::string>::iterator it_addrs = AddrsV.begin(); it_addrs != AddrsV.end(); ++it_addrs)
    {
      bool Loop = true;
      std::string &Addrsh = *it_addrs;

      for (it_out = path_main.rbegin(); it_out != path_main.rend() && Loop; ++it_out)
	{
	  for (it_in = (*it_out).rbegin(); it_in != (*it_out).rend() && Loop; ++it_in)
	    {
	      std::map<std::string, std::string> &it_ele = *it_in;
	      LivesNotZeroHelper(it_ele["addrs_src"], Addrsh, it_ele["lives_src"], Result, Loop);
	      LivesNotZeroHelper(it_ele["addrs_trk"], Addrsh, it_ele["lives_trk"], Result, Loop);
	    }
	}
    }

  return Result;
}

void LivesNotZeroHelper(std::string AddrsTrk, std::string AddrsI, std::string LivesTrk, std::vector<std::string> &Result, bool &Loop)
{
  if (finding_string(AddrsTrk, AddrsI))
    {
      if (stol(LivesTrk) != 0)
	{
	  Result.push_back(AddrsI);
	  Loop = false;
	}
      else Loop = false;
    }
}

void listof_addresses_bypath(std::vector<std::map<std::string, std::string>> &it_path_main, std::vector<std::string> &addrsv)
{
	std::vector<std::string> addrsvh;
	for (std::vector<std::map<std::string, std::string>>::iterator it = it_path_main.begin(); it != it_path_main.end(); ++it)
	{
		std::map<std::string, std::string> &it_ele = *it;
		if ( !find_string_strv(it_ele["addrs_src"], addrsv) )
		{
			addrsv.push_back(it_ele["addrs_src"]);
		}
		if ( !find_string_strv(it_ele["addrs_trk"], addrsv) )
		{
			addrsv.push_back(it_ele["addrs_trk"]);
		}
	}
	addrsv = addrsvh;
	for (std::vector<std::string>::iterator it = addrsvh.begin(); it != addrsvh.end(); ++it)
	{
		PrintToLog("\nAddress %s\n", *it);
	}
}

double PNL_function(double entry_price, double exit_price, long int amount_trd, struct status_amounts *pt_jrow_database)
{
  double PNL = 0;

  if ( finding_string("Long", pt_jrow_database->status_trk) )
    PNL = (double)amount_trd*(1/entry_price-1/exit_price);
  else if ( finding_string("Short", pt_jrow_database->status_trk) )
    PNL = (double)amount_trd*(1/exit_price-1/entry_price);

  return PNL;
}

double PNL_ghosts(double entry_price, double exit_price, long int amount_trd, std::string status)
{
  double PNL = 0;

  if (finding_string("Long", status))
    PNL = (double)amount_trd*(1/entry_price-1/exit_price);
  else if (finding_string("Short", status))
    PNL = (double)amount_trd*(1/exit_price-1/entry_price);

  return PNL;
}

void getting_gammapq_bypath(std::vector<std::map<std::string, std::string>> &path_main, double PNL_total, double &gamma_p, double &gamma_q, std::unordered_set<std::string> addrs_set)
{
  MatrixTLS &ndatabase = *pt_ndatabase;
  VectorTLS jrow_database(n_cols);
  long int sum_alpha_beta_i = 0;
  long int sum_alpha_i = 0;
  long int sum_alpha_beta_j = 0;
  long int sum_alpha_j = 0;

  std::vector<std::map<std::string, std::string>>::iterator it_path_main;
  for (it_path_main = path_main.begin(); it_path_main != path_main.end(); ++it_path_main)
    {
      std::map<std::string, std::string> &edge_ele = *it_path_main;
      if ( stol(edge_ele["lives_src"]) != 0 )
	{
	  sub_row(jrow_database, ndatabase, stol(edge_ele["edge_row"]));
	  struct status_amounts *pt_jrow_database = get_status_amounts_byaddrs(jrow_database, edge_ele["addrs_src"]);
	  if ( finding_string("Long", pt_jrow_database->status_trk) )
	    {
	      sum_alpha_beta_i += stol(edge_ele["lives_src"])*stod(edge_ele["exit_price"]);
	      sum_alpha_i += stol(edge_ele["lives_src"]);
	    }
	  else
	    {
	      sum_alpha_beta_j += stol(edge_ele["lives_src"])*stod(edge_ele["exit_price"]);
	      sum_alpha_j += stol(edge_ele["lives_src"]);
	    }
	}
      if ( stol(edge_ele["lives_trk"]) != 0 )
	{
	  sub_row(jrow_database, ndatabase, stol(edge_ele["edge_row"]));
	  struct status_amounts *pt_jrow_database = get_status_amounts_byaddrs(jrow_database, edge_ele["addrs_trk"]);
	  if ( finding_string("Long", pt_jrow_database->status_trk) )
	    {
	      sum_alpha_beta_i += stol(edge_ele["lives_trk"])*stod(edge_ele["entry_price"]);
	      sum_alpha_i += stol(edge_ele["lives_trk"]);
	    }
	  else
	    {
	      sum_alpha_beta_j += stol(edge_ele["lives_trk"])*stod(edge_ele["entry_price"]);
	      sum_alpha_j += stol(edge_ele["lives_trk"]);
	    }
	}
    }
  gamma_p = PNL_total-sum_alpha_beta_i+sum_alpha_beta_j;
  gamma_q = sum_alpha_j-sum_alpha_i;
}

void GhostEdgesComputing(std::vector<std::map<std::string, std::string>> lives_longs, std::vector<std::map<std::string, std::string>> lives_shorts, double exit_price_desired, std::vector<std::map<std::string, std::string>> &GhostEdgesArray)
{
  long int amount_itlongs  = 0;
  long int amount_itshorts = 0;
  unsigned index_start = 0;

  std::vector<std::map<std::string, std::string>>::iterator it_longs;
  std::vector<std::map<std::string, std::string>>::iterator it_shorts;
  std::map<std::string, std::string> short_ele;
  std::map<std::string, std::string> long_ele;
  std::map<std::string, std::string> edge_ele;

  for (unsigned i = 0; i < lives_longs.size(); i++)
  {
    long_ele = lives_longs[i];
    amount_itlongs = stol(long_ele["lives"]);

    for (unsigned j = index_start; j < lives_shorts.size(); j++)
    {
      short_ele = lives_shorts[j];
	    amount_itshorts = stol(short_ele["lives"]);

      if (amount_itlongs > amount_itshorts)
      {
        amount_itlongs = amount_itlongs - amount_itshorts;
	      // PrintToLog("\namount_itshorts = %d\t amount_itlongs = %d\n", amount_itshorts, amount_itlongs);

        BuildingGhostEdges(edge_ele, long_ele["addrs"], short_ele["addrs"], long_ele["status"], short_ele["status"], long_ele["entry_price"], short_ele["entry_price"], exit_price_desired, amount_itlongs);
	      GhostEdgesArray.push_back(edge_ele);

        continue;
      }
      if (amount_itlongs < amount_itshorts)
      {
        index_start = j;
	      lives_shorts[j]["lives"] = std::to_string(amount_itshorts - amount_itlongs);
	      // PrintToLog("\namount_itshorts = %d\t amount_itlongs = %d\n", amount_itshorts - amount_itlongs, amount_itlongs);

        BuildingGhostEdges(edge_ele, long_ele["addrs"], short_ele["addrs"], long_ele["status"], short_ele["status"], long_ele["entry_price"], short_ele["entry_price"], exit_price_desired, amount_itlongs);
	      GhostEdgesArray.push_back(edge_ele);

        break;
      }
	    if ( amount_itlongs == amount_itshorts )
      {
        index_start = j + 1;
	      // PrintToLog("\namount_itshorts = %d\t amount_itlongs = %d\n", amount_itshorts, amount_itlongs);

        BuildingGhostEdges(edge_ele, long_ele["addrs"], short_ele["addrs"], long_ele["status"], short_ele["status"], long_ele["entry_price"], short_ele["entry_price"], exit_price_desired, amount_itlongs);
	      GhostEdgesArray.push_back(edge_ele);

        break;
      }
    }
  }
}

void updating_lives_tozero(std::vector<std::vector<std::map<std::string, std::string>>> &path_main)
{
  std::vector<std::vector<std::map<std::string, std::string>>>::iterator it_path_main;
  std::vector<std::map<std::string, std::string>>::iterator it_path_maini;

  for (it_path_main = path_main.begin(); it_path_main != path_main.end(); ++it_path_main)
    {
      for (it_path_maini = (*it_path_main).begin(); it_path_maini != (*it_path_main).end(); ++it_path_maini)
	{
	  std::map<std::string, std::string> &edge_ele = *it_path_maini;
	  edge_ele["lives_src"] = std::to_string(0);
	  edge_ele["lives_trk"] = std::to_string(0);
	  printing_edges(*it_path_maini);
	}
    }
}

void joining_pathmain_ghostedges(std::vector<std::vector<std::map<std::string, std::string>>> &path_main, std::vector<std::map<std::string, std::string>> GhostEdgesArray)
{
  std::vector<std::vector<std::map<std::string, std::string>>>::iterator it_path_main;
  std::vector<std::map<std::string, std::string>>::iterator it_ghosts;
  long int index_path = 0;

  for (it_path_main = path_main.begin(); it_path_main != path_main.end(); ++it_path_main)
    {
      index_path = stol((*it_path_main).front()["path_number"]);
      for (it_ghosts = GhostEdgesArray.begin(); it_ghosts != GhostEdgesArray.end(); ++it_ghosts)
	{
	  if ( stol((*it_ghosts)["path_number"]) == index_path )
	    {
	      (*it_path_main).push_back(*it_ghosts);
	    }
	}
    }
}

void checkzeronetted_bypath_ghostedges(std::vector<std::map<std::string, std::string>> path_maini, long int nonzero_lives)
{
  std::vector<std::map<std::string, std::string>>::iterator it_path_maini;
  long int lives_settled = 0;

  if ( nonzero_lives != 0 )
    {
      for (it_path_maini = path_maini.begin(); it_path_maini != path_maini.end(); ++it_path_maini)
	{
	  if ( stol((*it_path_maini)["ghost_edge"]) == 1 )
	    {
	      lives_settled += stol((*it_path_maini)["amount_trd"]);
	    }
	}
    }
  //PrintToLog("\nLives in the Path - Lives settled : (%ld - %ld) = %ld\n", nonzero_lives, lives_settled, nonzero_lives - lives_settled);
}

long int checkpath_livesnonzero(std::vector<std::map<std::string, std::string>> path_maini)
{
  std::vector<std::map<std::string, std::string>>::iterator it_path_maini;
  long int lives = 0;

  for (it_path_maini = path_maini.begin(); it_path_maini != path_maini.end(); ++it_path_maini)
    {
      lives += stol((*it_path_maini)["lives_src"])+stol((*it_path_maini)["lives_trk"]);
    }
  return lives;
}

max_stars_repo_name: patrickdugan/BlockPo-to-Tradelayer

max_issues_repo_name: patrickdugan/BlockPo-to-Tradelayer

max_forks_repo_name: patrickdugan/BlockPo-to-Tradelayer


text:
//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: 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.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
#include <DTK_C_API.h>
#include <DTK_DBC.hpp>
#include <DTK_EntityCenteredField.hpp>
#include <DTK_EntityCenteredShapeFunction.hpp>
#include <DTK_FieldMultiVector.hpp>
#include <DTK_POD_PointCloudEntitySet.hpp>
#include <DTK_POD_PointCloudLocalMap.hpp>
#include <DTK_POD_Types.hpp>
#include <DTK_PointCloudOperatorFactory.hpp>

#include <Teuchos_DefaultMpiComm.hpp>

#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include <iostream>
#include <sstream>
#include <string>

//----------------------------------------------------------------------------//
Teuchos::RCP<Tpetra::Map<int, DataTransferKit::EntityId> const>
build_contiguous_map( Teuchos::RCP<Teuchos::Comm<int> const> const &comm,
                      DataTransferKit::EntityId local_num )
{
    DataTransferKit::EntityId global_num = 0;
    Teuchos::reduceAll<int, DataTransferKit::EntityId>(
        *comm, Teuchos::REDUCE_SUM, 1, &local_num, &global_num );
    return Tpetra::createContigMap<int, DataTransferKit::EntityId>(
        global_num, local_num, comm );
}

//---------------------------------------------------------------------------//
DataTransferKit::DataLayout getLayout( DTK_Data_layout layout )
{
    if ( DTK_BLOCKED == layout )
    {
        return DataTransferKit::BLOCKED;
    }
    else if ( DTK_INTERLEAVED == layout )
    {
        return DataTransferKit::INTERLEAVED;
    }
    else
    {
        // Will always throw if we get a bad layout.
        DTK_INSIST( DTK_BLOCKED == layout || DTK_INTERLEAVED == layout );
        return DataTransferKit::BLOCKED;
    }
}

//---------------------------------------------------------------------------//
Teuchos::RCP<DataTransferKit::FunctionSpace> createFunctionSpace(
    const Teuchos::RCP<const Teuchos::Comm<int>> &comm, const double *coord,
    const Teuchos::ArrayView<const DataTransferKit::EntityId> &global_ids,
    DTK_Data_layout layout, unsigned num, int space_dim )
{
    // Get the data layout
    DataTransferKit::DataLayout data_layout = getLayout( layout );

    // Build the entity set.
    auto entity_set =
        Teuchos::rcp( new DataTransferKit::POD_PointCloudEntitySet(
            comm, coord, global_ids.getRawPtr(), num, space_dim,
            data_layout ) );

    // Build the local map.
    auto local_map =
        Teuchos::rcp( new DataTransferKit::POD_PointCloudLocalMap() );

    // Build the shape function.
    auto shape_function =
        Teuchos::rcp( new DataTransferKit::EntityCenteredShapeFunction() );

    // Build the function space.
    return Teuchos::rcp( new DataTransferKit::FunctionSpace(
        entity_set, local_map, shape_function, Teuchos::null ) );
}

//----------------------------------------------------------------------------//
DTK_Map *DTK_Map_create_f( MPI_Fint fint, double const *src_coord,
                           unsigned src_num, DTK_Data_layout src_layout,
                           double const *tgt_coord, unsigned tgt_num,
                           DTK_Data_layout tgt_layout, int space_dim,
                           char const *options )
{
    MPI_Comm comm = MPI_Comm_f2c( fint );
    return DTK_Map_create( comm, src_coord, src_num, src_layout, tgt_coord,
                           tgt_num, tgt_layout, space_dim, options );
}

//----------------------------------------------------------------------------//
DTK_Map *DTK_Map_create( MPI_Comm comm, double const *src_coord,
                         unsigned src_num, DTK_Data_layout src_layout,
                         double const *tgt_coord, unsigned tgt_num,
                         DTK_Data_layout tgt_layout, int space_dim,
                         char const *options )
{
    // Parse the options and build the parameter list
    std::stringstream ss;
    ss.str( options );
    boost::property_tree::ptree ptree;
    boost::property_tree::read_json( ss, ptree );
    Teuchos::ParameterList parameters;
    std::string const map_type( ptree.get<std::string>(
        "Map Type", "Moving Least Square Reconstruction" ) );
    parameters.set( "Map Type", map_type );
    parameters.set( "Spatial Dimension", space_dim );
    if ( map_type.compare( "Node To Node" ) != 0 )
    {
        parameters.set( "Basis Type",
                        ptree.get<std::string>( "Basis Type", "Wendland" ) );
        parameters.set( "Basis Order", ptree.get<int>( "Basis Order", 2 ) );
        parameters.set( "Type of Search",
                        ptree.get<std::string>( "Search Type", "Radius" ) );
        if ( "Radius" == ptree.get<std::string>( "Search Type", "Radius" ) )
        {
            parameters.set( "RBF Radius", ptree.get<double>( "RBF Radius" ) );
        }
        else if ( "Nearest Neighbor" ==
                  ptree.get<std::string>( "Search Type" ) )
        {
            parameters.set( "Num Neighbors",
                            ptree.get<int>( "Num Neighbors" ) );
        }
    }

    // Wrap the communicator.
    Teuchos::RCP<const Teuchos::Comm<int>> teuchos_comm =
        Teuchos::createMpiComm<int>( Teuchos::opaqueWrapper<MPI_Comm>( comm ) );

    // Create the domain and range maps
    auto domain_map = build_contiguous_map( teuchos_comm, src_num );
    auto range_map = build_contiguous_map( teuchos_comm, tgt_num );

    // Build the actual DTK map operator
    auto factory = DataTransferKit::PointCloudOperatorFactory();
    auto map_operator = factory.create( domain_map, range_map, parameters );

    // Create the function spaces.
    auto domain_space = createFunctionSpace( teuchos_comm, src_coord,
                                             domain_map->getNodeElementList(),
                                             src_layout, src_num, space_dim );

    auto range_space = createFunctionSpace( teuchos_comm, tgt_coord,
                                            range_map->getNodeElementList(),
                                            tgt_layout, tgt_num, space_dim );

    // Set up the map.
    map_operator->setup( domain_space, range_space );

    // Return an opaque pointer. User is responsible for calling delete_map(...)
    return static_cast<DTK_Map *>( map_operator.release().get() );
}

//----------------------------------------------------------------------------//
void DTK_Map_apply( DTK_Map *dtk_map, double const *src_data,
                    DTK_Data_layout src_layout, double *tgt_data,
                    DTK_Data_layout tgt_layout, int field_dim, bool transpose )
{
    // Cast the opaque pointer back to a DTK map operator
    auto map_operator = static_cast<DataTransferKit::MapOperator *>( dtk_map );

    // Helper function to map data layouts
    auto dtk_entity_centered_field_layout = []( DTK_Data_layout data_layout ) {
        if ( data_layout == DTK_BLOCKED )
            return DataTransferKit::EntityCenteredField::BLOCKED;
        else if ( data_layout == DTK_INTERLEAVED )
            return DataTransferKit::EntityCenteredField::INTERLEAVED;
        else
            throw std::runtime_error( "Invalid data layout" );
    };

    // Wrap the source vector
    auto domain_map = map_operator->getDomainMap();

    DataTransferKit::EntityCenteredField src_field(
        domain_map->getNodeElementList(), field_dim,
        Teuchos::ArrayRCP<double>( const_cast<double *>( src_data ), 0,
                                   field_dim * domain_map->getNodeNumElements(),
                                   false ),
        dtk_entity_centered_field_layout( src_layout ) );

    DataTransferKit::FieldMultiVector domain_vector(
        domain_map->getComm(), Teuchos::rcpFromRef( src_field ) );

    // Wrap the target vector
    auto range_map = map_operator->getRangeMap();

    DataTransferKit::EntityCenteredField tgt_field(
        range_map->getNodeElementList(), field_dim,
        Teuchos::ArrayRCP<double>(
            tgt_data, 0, field_dim * range_map->getNodeNumElements(), false ),
        dtk_entity_centered_field_layout( tgt_layout ) );

    DataTransferKit::FieldMultiVector range_vector(
        range_map->getComm(), Teuchos::rcpFromRef( tgt_field ) );

    // Apply the map operator
    map_operator->apply( domain_vector, range_vector,
                         transpose ? Teuchos::TRANS : Teuchos::NO_TRANS );
}

//----------------------------------------------------------------------------//
void DTK_Map_delete( DTK_Map *dtk_map )
{
    delete static_cast<DataTransferKit::MapOperator *>( dtk_map );
}

//---------------------------------------------------------------------------//
// end DTK_C_API.cpp
//---------------------------------------------------------------------------//

ext: cpp


text:
#include <boost/test/unit_test.hpp>

#include <voilk/protocol/exceptions.hpp>
#include <voilk/protocol/hardfork.hpp>

#include <voilk/chain/database.hpp>
#include <voilk/chain/voilk_objects.hpp>

#include <fc/crypto/digest.hpp>

#include "../db_fixture/database_fixture.hpp"

#include <iostream>

using namespace voilk;
using namespace voilk::chain;
using namespace voilk::protocol;

#ifndef IS_TEST_NET

BOOST_FIXTURE_TEST_SUITE( live_tests, live_database_fixture )

/*
BOOST_AUTO_TEST_CASE( coins_stock_split )
{
   try
   {
      BOOST_TEST_MESSAGE( "Gathering state prior to split" );

      uint32_t magnitude = 1000000;

      flat_map< string, share_type > account_coins;
      flat_map< string, share_type > account_vsf_votes;
      const auto& acnt_idx = db->get_index< account_index >().indices().get< by_name >();
      auto acnt_itr = acnt_idx.begin();

      BOOST_TEST_MESSAGE( "Saving account coining shares" );

      while( acnt_itr != acnt_idx.end() )
      {
         account_coins[acnt_itr->name] = acnt_itr->coining_shares.amount;
         account_vsf_votes[acnt_itr->name] = acnt_itr->proxied_vsf_votes_total().value;
         acnt_itr++;
      }

      auto old_virtual_supply = db->get_dynamic_global_properties().virtual_supply;
      auto old_current_supply = db->get_dynamic_global_properties().current_supply;
      auto old_coining_fund = db->get_dynamic_global_properties().total_coining_fund_voilk;
      auto old_coining_shares = db->get_dynamic_global_properties().total_coining_shares;
      auto old_rshares2 = db->get_dynamic_global_properties().total_reward_shares2;
      auto old_reward_fund = db->get_dynamic_global_properties().total_reward_fund_voilk;

      flat_map< std::tuple< account_name_type, string >, share_type > comment_net_rshares;
      flat_map< std::tuple< account_name_type, string >, share_type > comment_abs_rshares;
      flat_map< comment_id_type, uint64_t > total_vote_weights;
      flat_map< comment_id_type, uint64_t > orig_vote_weight;
      flat_map< comment_id_type, uint64_t > expected_reward;
      fc::uint128_t total_rshares2 = 0;
      const auto& com_idx = db->get_index< comment_index >().indices().get< by_permlink >();
      auto com_itr = com_idx.begin();
      auto gpo = db->get_dynamic_global_properties();

      BOOST_TEST_MESSAGE( "Saving comment rshare values" );

      while( com_itr != com_idx.end() )
      {
         comment_net_rshares[ std::make_tuple( com_itr->author, com_itr->permlink ) ] = com_itr->net_rshares;
         comment_abs_rshares[ std::make_tuple( com_itr->author, com_itr->permlink ) ] = com_itr->abs_rshares;
         total_vote_weights[ com_itr->id ] = 0;
         orig_vote_weight[ com_itr->id ] = com_itr->total_vote_weight;

         if( com_itr->net_rshares.value > 0 )
         {
            total_rshares2 += com_itr->net_rshares.value > 0 ? fc::uint128_t( com_itr->net_rshares.value ) * com_itr->net_rshares.value * magnitude * magnitude : 0;
            u256 rs( com_itr->net_rshares.value );
            u256 rf( gpo.total_reward_fund_voilk.amount.value );
            auto rs2 = rs * rs;
            u256 rshares2 = old_rshares2.hi;
            rshares2 = rshares2 << 64;
            rshares2 += old_rshares2.lo;
            expected_reward[ com_itr->id ] = static_cast< uint64_t >( rf * rs2 / rshares2 );
         }
         com_itr++;
      }

      BOOST_TEST_MESSAGE( "Saving category rshares" );

      const auto& cat_idx = db->get_index< category_index >().indices();
      flat_map< category_id_type, share_type > category_rshares;

      for( auto cat_itr = cat_idx.begin(); cat_itr != cat_idx.end(); cat_itr++ )
      {
         category_rshares[ cat_itr->id ] = cat_itr->abs_rshares;
      }

      BOOST_TEST_MESSAGE( "Perform split" );
      fc::time_point start = fc::time_point::now();
      db->perform_coining_share_split( magnitude );
      fc::time_point end = fc::time_point::now();
      ilog( "Coining split execution time: ${t} us", ("t",end - start) );

      BOOST_TEST_MESSAGE( "Verify split took place correctly" );

      BOOST_REQUIRE( db->get_dynamic_global_properties().current_supply == old_current_supply );
      BOOST_REQUIRE( db->get_dynamic_global_properties().virtual_supply == old_virtual_supply );
      BOOST_REQUIRE( db->get_dynamic_global_properties().total_coining_fund_voilk == old_coining_fund );
      BOOST_REQUIRE( db->get_dynamic_global_properties().total_coining_shares.amount == old_coining_shares.amount * magnitude );
      BOOST_REQUIRE( db->get_dynamic_global_properties().total_reward_shares2 == total_rshares2 );
      BOOST_REQUIRE( db->get_dynamic_global_properties().total_reward_fund_voilk == old_reward_fund );

      BOOST_TEST_MESSAGE( "Check accounts were updated" );
      acnt_itr = acnt_idx.begin();
      while( acnt_itr != acnt_idx.end() )
      {
         BOOST_REQUIRE( acnt_itr->coining_shares.amount == account_coins[ acnt_itr->name ] * magnitude );
         BOOST_REQUIRE( acnt_itr->proxied_vsf_votes_total().value == account_vsf_votes[ acnt_itr->name ] * magnitude );
         acnt_itr++;
      }

      gpo = db->get_dynamic_global_properties();

      com_itr = com_idx.begin();
      while( com_itr != com_idx.end() )
      {
         BOOST_REQUIRE( com_itr->net_rshares == comment_net_rshares[ std::make_tuple( com_itr->author, com_itr->permlink ) ] * magnitude );
         BOOST_REQUIRE( com_itr->abs_rshares == comment_abs_rshares[ std::make_tuple( com_itr->author, com_itr->permlink ) ] * magnitude );
         BOOST_REQUIRE( com_itr->total_vote_weight == total_vote_weights[ com_itr->id ] );

         if( com_itr->net_rshares.value > 0 )
         {
            u256 rs( com_itr->net_rshares.value );
            u256 rf( gpo.total_reward_fund_voilk.amount.value );
            u256 rshares2 = total_rshares2.hi;
            rshares2 = ( rshares2 << 64 ) + total_rshares2.lo;
            auto rs2 = rs * rs;

            BOOST_REQUIRE( static_cast< uint64_t >( ( rf * rs2 ) / rshares2 ) == expected_reward[ com_itr->id] );
         }
         com_itr++;
      }

      for( auto cat_itr = cat_idx.begin(); cat_itr != cat_idx.end(); cat_itr++ )
      {
         BOOST_REQUIRE( cat_itr->abs_rshares.value == category_rshares[ cat_itr->id ].value * magnitude );
      }

      validate_database();
   }
   FC_LOG_AND_RETHROW()
}*/

BOOST_AUTO_TEST_CASE( retally_votes )
{
   try
   {
      flat_map< account_name_type, share_type > expected_votes;

      const auto& by_account_witness_idx = db->get_index< witness_vote_index >().indices();

      for( const auto& vote: by_account_witness_idx )
      {
         if( expected_votes.find( vote.witness ) == expected_votes.end() )
            expected_votes[ vote.witness ] = db->get< account_object, by_name >( vote.account ).witness_vote_weight();
         else
            expected_votes[ vote.witness ] += db->get< account_object, by_name >( vote.account ).witness_vote_weight();
      }

      db->retally_witness_votes();

      const auto& witness_idx = db->get_index< witness_index, by_name >();

      for( const auto& witness : witness_idx )
      {
         BOOST_REQUIRE_EQUAL( witness.votes.value, expected_votes[ witness.owner ].value );
      }
   }
   FC_LOG_AND_RETHROW()
}

BOOST_AUTO_TEST_SUITE_END()

#endif

max_stars_repo_name: voilknetwork/voilk

max_issues_repo_name: voilknetwork/voilk

max_forks_repo_name: voilknetwork/voilk


text:
//==============================================================================
//         Copyright 2003 - 2011   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
/*!
 * \file
**/
#ifndef BOOST_SIMD_OPERATOR_FUNCTIONS_UNALIGNED_STORE_HPP_INCLUDED
#define BOOST_SIMD_OPERATOR_FUNCTIONS_UNALIGNED_STORE_HPP_INCLUDED
#include <boost/simd/include/functor.hpp>
#include <boost/dispatch/include/functor.hpp>

////////////////////////////////////////////////////////////////////////////////
// Store a value in memory functor and function
// Documentation: http://nt2.lri.fr/sdk/memory/functions/store.html
////////////////////////////////////////////////////////////////////////////////
#include <boost/dispatch/functor/preprocessor/function.hpp>

namespace boost { namespace simd
{
  namespace tag { struct unaligned_store_ : ext::elementwise_<unaligned_store_> { typedef ext::elementwise_<unaligned_store_> parent; }; }

  BOOST_DISPATCH_FUNCTION_IMPLEMENTATION(tag::unaligned_store_, unaligned_store,2)
  BOOST_DISPATCH_FUNCTION_IMPLEMENTATION(tag::unaligned_store_, unaligned_store,3)
} }

#endif

ext: hpp


text:
//  Copyright John Maddock 2006.
//  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)

#define BOOST_MATH_ASSERT_UNDEFINED_POLICY false

#include <boost/math/distributions.hpp>
#include <boost/math/concepts/distributions.hpp>

template <class RealType>
void instantiate(RealType)
{
   using namespace boost;
   using namespace boost::math;
   using namespace boost::math::concepts;

   function_requires<DistributionConcept<normal_distribution<RealType> > >();
   function_requires<DistributionConcept<beta_distribution<RealType> > >();
   function_requires<DistributionConcept<binomial_distribution<RealType> > >();
   function_requires<DistributionConcept<cauchy_distribution<RealType> > >();
   function_requires<DistributionConcept<bernoulli_distribution<RealType> > >();
   function_requires<DistributionConcept<chi_squared_distribution<RealType> > >();
   function_requires<DistributionConcept<exponential_distribution<RealType> > >();
   function_requires<DistributionConcept<extreme_value_distribution<RealType> > >();
   function_requires<DistributionConcept<fisher_f_distribution<RealType> > >();
   function_requires<DistributionConcept<gamma_distribution<RealType> > >();
   function_requires<DistributionConcept<students_t_distribution<RealType> > >();
   function_requires<DistributionConcept<pareto_distribution<RealType> > >();
   function_requires<DistributionConcept<poisson_distribution<RealType> > >();
   function_requires<DistributionConcept<rayleigh_distribution<RealType> > >();
   function_requires<DistributionConcept<weibull_distribution<RealType> > >();
   function_requires<DistributionConcept<lognormal_distribution<RealType> > >();
   function_requires<DistributionConcept<triangular_distribution<RealType> > >();
   function_requires<DistributionConcept<uniform_distribution<RealType> > >();
   function_requires<DistributionConcept<negative_binomial_distribution<RealType> > >();
   function_requires<DistributionConcept<non_central_chi_squared_distribution<RealType> > >();
}

int main()
{
   instantiate(float(0));
   instantiate(double(0));
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
   instantiate((long double)(0));
#endif
}

max_stars_repo_name: zyiacas/boost-doc-zh

max_issues_repo_name: sdfict/boost-doc-zh

max_forks_repo_name: sdfict/boost-doc-zh


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_ARCH_COMMON_DETAIL_SCALAR_TRIG_BASE_HPP_INCLUDED
#define BOOST_SIMD_ARCH_COMMON_DETAIL_SCALAR_TRIG_BASE_HPP_INCLUDED
#include <boost/simd/arch/common/detail/tags.hpp>
#include <boost/simd/arch/common/detail/scalar/trig_reduction.hpp>
#include <boost/simd/function/is_invalid.hpp>
#include <boost/simd/function/is_nan.hpp>
#include <boost/simd/function/is_eqz.hpp>
#include <boost/simd/function/is_nez.hpp>
#include <boost/simd/function/shift_left.hpp>
#include <boost/simd/function/sqr.hpp>
#include <boost/simd/function/rec.hpp>
#include <boost/simd/function/oneminus.hpp>
#include <boost/simd/function/bitofsign.hpp>
#include <boost/simd/function/bitwise_xor.hpp>
#include <boost/simd/function/bitwise_or.hpp>
#include <boost/simd/function/shift_left.hpp>
#include <boost/simd/function/abs.hpp>
#include <boost/simd/function/is_invalid.hpp>
#include <boost/simd/constant/pio_4.hpp>
#include <boost/simd/constant/one.hpp>
#include <boost/simd/constant/quarter.hpp>
#include <boost/simd/constant/pi.hpp>
#include <boost/simd/constant/deginrad.hpp>
#include <boost/simd/constant/inf.hpp>
#include <boost/simd/constant/nan.hpp>
#include <boost/simd/constant/two.hpp>
#include <boost/simd/constant/mtwo.hpp>
#include <boost/simd/constant/ratio.hpp>
#include <boost/config.hpp>
#include <boost/simd/detail/dispatch/meta/as_integer.hpp>

// trigonometric functions are implemented using the classical cephes/fdlibm/libc principles
// however the formal reduce/eval/return is properly divided to allow choices versus
// speed, accuracy and  SIMD vectorisation
//
// On small ranges performance can be obtained with almost full accuracy (1 ulp) at 1 to 2
// cycles per element for a cosine computation using SIMD. But if one require full accuracy
// on the full float or double range, the prize can grow up to few hundreds of cycle for
// some big values of input.
// See the boost/simd technical documentation for more insights

namespace boost { namespace simd
{
  namespace detail
  {
    // in the class defined below:
    // A0 is the argument type of the trigonometric functions
    //
    // Up to now, only floating real based on IEEE 754 float or double are supported
    // (sorry no long double for lack of portability)

    template < typename A0, typename unit_tag> struct trig_ranges;
    template < typename A0>  struct trig_ranges<A0, tag::radian_tag>
    {
      static BOOST_FORCEINLINE A0    max_range() BOOST_NOEXCEPT {return Pio_4<A0>(); }
      static BOOST_FORCEINLINE A0    scale()     BOOST_NOEXCEPT {return One<A0>(); }
    };
    template < typename A0>  struct trig_ranges<A0, tag::pi_tag>
    {
      static BOOST_FORCEINLINE A0    max_range() BOOST_NOEXCEPT {return Quarter<A0>(); }
      static BOOST_FORCEINLINE A0    scale()     BOOST_NOEXCEPT {return Pi<A0>(); }
    };
    template < typename A0>  struct trig_ranges<A0, tag::degree_tag>
    {
      static BOOST_FORCEINLINE A0    max_range() BOOST_NOEXCEPT {return Ratio<A0, 45>(); }
      static BOOST_FORCEINLINE A0    scale()     BOOST_NOEXCEPT {return Deginrad<A0>(); }
    };

    // This class expose the public static members:
    // cosa     x -> cos(a*x)
    // sina     x -> sin(a*x)
    // tana     x -> tan(a*x)
    // cota     x -> cot(a*x)
    // sincosa  x -> cos(a*x) and sin(a*x)
    // "a" is not a run time parameter !
    // It stands as a remainder that according the Tag it can be considered
    // as a scale factor for the input of values:
    //   1           radian_tag,
    //   pi          pi_tag
    //   pi/180      degree_tag,
    // but the scaling is internal to the algorithm to provide better accuracy
    // and better performance.

    // It heritates of a reduction and an evaluation class to perform
    // the appropriate range reductions and function evaluations.

    // In this file stands the scalar version !
    // Some definitions are useless but provide facilities of comparaison with
    // the SIMD implementation
    //
    template < typename A0,
               typename unit_tag,
               typename style,
               typename mode =  tag::big_tag>
    struct trig_base{};

    template < typename A0,
               typename unit_tag,
               typename mode>
     struct trig_base<A0,unit_tag,tag::not_simd_type,mode>
     {
       using redu_t = trig_reduction<A0,unit_tag,tag::not_simd_type, mode>;
       using eval_t = trig_evaluation<A0,tag::not_simd_type>;
       using i_t    = bd::as_integer_t<A0, signed>;           // signed integer type associated to A0
       using style_t = typename mode::type;

       // for all functions the scalar algorithm is:
       // * quick return (or exception raising TODO) for inf and nan or specific invalid cases inputs
       // * range reduction
       // * computation of sign and evaluation selections flags
       // * evaluations
       // * return with flag based corrections

       static BOOST_FORCEINLINE A0 cosa(A0 a0){ return cosa(a0, style_t()); }
       static BOOST_FORCEINLINE A0 sina(A0 a0){ return sina(a0, style_t()); }
       static BOOST_FORCEINLINE A0 tana(A0 a0){ return tana(a0, style_t()); }
       static BOOST_FORCEINLINE A0 cota(A0 a0){ return cota(a0, style_t()); }
       static BOOST_FORCEINLINE std::pair<A0,A0> sincosa(const A0& a0){ return sincosa(a0,style_t()); }

       static BOOST_FORCEINLINE A0 cosa(A0 a0, const tag::regular&)
       {
         if (is_invalid(a0)) return Nan<A0>(); //Nan or Inf input
         const A0 x =  abs(a0);
         A0 xr = Nan<A0>();
         const i_t n = toint(redu_t::reduce(x, xr));
         const i_t swap_bit = n&One<i_t>();
         const i_t sign_bit = shift_left(bitwise_xor(swap_bit, (n&Two<i_t>())>>1), sizeof(i_t)*8-1);
         A0 z = sqr(xr);
         if (swap_bit)
           z = eval_t::sin_eval(z, xr);
         else
           z = eval_t::cos_eval(z);
         return bitwise_xor(z,sign_bit);
       }

       static BOOST_FORCEINLINE A0 sina(A0 a0, const tag::regular&) BOOST_NOEXCEPT
       {
         if (is_invalid(a0)) return Nan<A0>();
         const A0 x =  abs(a0);
         A0 xr = Nan<A0>();
         const i_t n = toint(redu_t::reduce(x, xr));
         const i_t swap_bit = n&One<i_t>();
         const A0 sign_bit = bitwise_xor(bitofsign(a0), shift_left(n&Two<i_t>(), sizeof(i_t)*8-2));
         A0 z = sqr(xr);
         if (swap_bit)
           z = eval_t::cos_eval(z);
         else
           z = eval_t::sin_eval(z, xr);
         return bitwise_xor(z,sign_bit);
       }

       static BOOST_FORCEINLINE A0 tana(A0 a0, const tag::regular&) BOOST_NOEXCEPT
       {
         if (is_invalid(a0)||redu_t::tan_invalid(a0)) return Nan<A0>();
         if (is_eqz(a0)) return a0;
         const A0 x =  abs(a0);
         A0 xr = Nan<A0>(), y;
         const i_t n = toint(redu_t::reduce(x, xr));
         y = eval_t::tan_eval(xr, 1-((n&1)<<1));
         // 1 -- n even
         //-1 -- n odd
         return bitwise_xor(y, bitofsign(a0));
       }

       static BOOST_FORCEINLINE A0 cota(A0 a0, const tag::regular&) BOOST_NOEXCEPT
       {
         if (is_invalid(a0)||redu_t::cot_invalid(a0)) return Nan<A0>();
         const A0 x = abs(a0);
         const A0 bos =  bitofsign(a0);
         if (!a0) return bitwise_or(Inf<A0>(), bos);
         A0 xr = Nan<A0>();
         const i_t n = toint(redu_t::reduce(x, xr));
         const A0 y = eval_t::cot_eval(xr, 1-((n&1)<<1));
         return bitwise_xor(y, bos);
       }

       static BOOST_FORCEINLINE std::pair<A0,A0> sincosa(A0 a0, const tag::regular&) BOOST_NOEXCEPT
       {
         A0 s, c;
         if (is_invalid(a0)) return {Nan<A0>(), Nan<A0>()};
         const A0 x =  abs(a0);
         constexpr i_t de = static_cast<i_t>(sizeof(i_t)*8-1);
         A0 xr;
         const i_t n = toint(redu_t::reduce(x, xr));
         const i_t swap_bit = n&One<i_t>();
         const A0 z = sqr(xr);
         const i_t cos_sign_bit = shift_left(bitwise_xor(swap_bit, (n&Two<i_t>())>>1), de);
         const A0 sin_sign_bit = bitwise_xor(bitofsign(a0), shift_left(n&Two<i_t>(), de-1));

         if (is_nez(swap_bit))
         {
           c = eval_t::sin_eval(z, xr);
           s = eval_t::cos_eval(z);
         }
         else
         {
           c = eval_t::cos_eval(z);
           s = eval_t::sin_eval(z, xr);
         }
         return {bitwise_xor(s,sin_sign_bit), bitwise_xor(c,cos_sign_bit)};
       }

       static BOOST_FORCEINLINE A0 cosa(A0 a0, const tag::restricted &) BOOST_NOEXCEPT
       {
         A0 x =  scale(a0);
         if(not_in_range(a0))
           return Nan<A0>();
         else
           return eval_t::cos_eval(sqr(x));
       }

       static BOOST_FORCEINLINE A0 sina(A0 a0, const tag::restricted&) BOOST_NOEXCEPT
       {
         if (is_eqz(a0)) return a0;
         A0 x =  scale(a0);
         if(not_in_range(a0))
           return Nan<A0>();
         else
           return eval_t::sin_eval(sqr(x), x);
       }

       static BOOST_FORCEINLINE A0 tana(A0 a0, const tag::restricted&) BOOST_NOEXCEPT
       {
         if (is_eqz(a0)) return a0;
         A0 x =  scale(a0);
         if(not_in_range(a0))
           return Nan<A0>();
         else
           return eval_t::base_tan_eval(x);
       }

       static BOOST_FORCEINLINE A0 cota(A0 a0, const tag::restricted&) BOOST_NOEXCEPT
       {
         if (is_eqz(a0)) return rec(a0);
          if(not_in_range(a0))
           return Nan<A0>();
          else
          {

            A0 x =  scale(a0);
            return rec(eval_t::base_tan_eval(x));
          }
       }

       static BOOST_FORCEINLINE std::pair<A0, A0>sincosa(A0 a0, const tag::restricted&) BOOST_NOEXCEPT
       {
         if (is_eqz(a0))       return {a0, One<A0>()} ;
         if(not_in_range(a0))  return {Nan<A0>(), Nan<A0>()};
         A0 x =  scale(a0);
         A0 z =  sqr(x);
         return { eval_t::sin_eval(z, x), eval_t::cos_eval(z)};
       }

       static BOOST_FORCEINLINE bool not_in_range(A0 a0) BOOST_NOEXCEPT
       {
         return bs::abs(a0) > trig_ranges<A0,unit_tag>::max_range();
       }
       static BOOST_FORCEINLINE A0 scale (A0 a0) BOOST_NOEXCEPT
       {
         return a0*trig_ranges<A0,unit_tag>::scale();
       }
    };
  }
} }
#endif

max_stars_repo_name: SylvainCorlay/pythran

max_issues_repo_name: SylvainCorlay/pythran

max_forks_repo_name: SylvainCorlay/pythran


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

#include <boost/tuple/tuple.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>

#if defined(BOOST_NO_CXX17_STRUCTURED_BINDINGS)

BOOST_PRAGMA_MESSAGE("Skipping structured bindings test, not supported")
int main() {}

#else

int main()
{
    // make_tuple

    {
        auto [x1] = boost::make_tuple( 1 );
        BOOST_TEST_EQ( x1, 1 );
    }

    {
        auto [x1, x2] = boost::make_tuple( 1, 2 );
        BOOST_TEST_EQ( x1, 1 );
        BOOST_TEST_EQ( x2, 2 );
    }

    {
        auto [x1, x2, x3] = boost::make_tuple( 1, 2, 3 );
        BOOST_TEST_EQ( x1, 1 );
        BOOST_TEST_EQ( x2, 2 );
        BOOST_TEST_EQ( x3, 3 );
    }

    {
        auto [x1, x2, x3, x4] = boost::make_tuple( 1, 2, 3, 4 );
        BOOST_TEST_EQ( x1, 1 );
        BOOST_TEST_EQ( x2, 2 );
        BOOST_TEST_EQ( x3, 3 );
        BOOST_TEST_EQ( x4, 4 );
    }

    // tuple

    {
        auto [x1] = boost::tuple<int>( 1 );
        BOOST_TEST_EQ( x1, 1 );
    }

    {
        auto [x1, x2] = boost::tuple<int, int>( 1, 2 );
        BOOST_TEST_EQ( x1, 1 );
        BOOST_TEST_EQ( x2, 2 );
    }

    {
        auto [x1, x2, x3] = boost::tuple<int, int, int>( 1, 2, 3 );
        BOOST_TEST_EQ( x1, 1 );
        BOOST_TEST_EQ( x2, 2 );
        BOOST_TEST_EQ( x3, 3 );
    }

    {
        auto [x1, x2, x3, x4] = boost::tuple<int, int, int, int>( 1, 2, 3, 4 );
        BOOST_TEST_EQ( x1, 1 );
        BOOST_TEST_EQ( x2, 2 );
        BOOST_TEST_EQ( x3, 3 );
        BOOST_TEST_EQ( x4, 4 );
    }

    return boost::report_errors();
}

#endif


text:
// Copyright (c) by respective owners including Yahoo!, Microsoft, and
// individual contributors. All rights reserved. Released under a BSD (revised)
// license as described in the file LICENSE.

#ifndef STATIC_LINK_VW
#  define BOOST_TEST_DYN_LINK
#endif

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

#include "test_common.h"
#include "metric_sink.h"
#include "simulator.h"
#include "reductions_fwd.h"
#include "constant.h"

#include <functional>
#include <map>

using simulator::callback_map;
using simulator::cb_sim;

namespace ut_helper
{
void assert_metric(const std::string& metric_name, const size_t value, const VW::metric_sink& metrics)
{
  auto it = std::find_if(metrics.int_metrics_list.begin(), metrics.int_metrics_list.end(),
      [&metric_name](const std::pair<std::string, size_t>& element) { return element.first == metric_name; });

  if (it == metrics.int_metrics_list.end()) { BOOST_FAIL("could not find metric. fatal."); }
  else
  {
    BOOST_CHECK_EQUAL(it->second, value);
  }
}
}  // namespace ut_helper

BOOST_AUTO_TEST_CASE(assert_0th_event)
{
  const auto metric_name = std::string("total_learn_calls");
  const size_t zero = 0;
  const size_t num_iterations = 10;
  callback_map test_hooks;

  // technically runs after the 0th example is learned
  test_hooks.emplace(zero, [&metric_name, &zero](cb_sim&, vw& all, multi_ex&) {
    VW::metric_sink metrics;
    all.l->persist_metrics(metrics);

    ut_helper::assert_metric(metric_name, zero, metrics);
    return true;
  });

  // test executes right after learn call of the 10th example
  test_hooks.emplace(num_iterations, [&metric_name, &num_iterations](cb_sim&, vw& all, multi_ex&) {
    VW::metric_sink metrics;
    all.l->persist_metrics(metrics);

    ut_helper::assert_metric(metric_name, num_iterations, metrics);
    return true;
  });

  auto ctr = simulator::_test_helper_hook(
      "--extra_metrics ut_metrics.json --cb_explore_adf --quiet --epsilon 0.2 --random_seed 5", test_hooks,
      num_iterations);

  BOOST_CHECK_GT(ctr.back(), 0.1f);
}

ext: cc