<commit_before>#include <CoinMpsIO.hpp>

#include "DcoModel.hpp"
#include "DcoMessage.hpp"
#include "DcoTreeNode.hpp"
#include "DcoNodeDesc.hpp"
#include "DcoVariable.hpp"
#include "DcoLinearConstraint.hpp"
#include "DcoConicConstraint.hpp"

DcoModel::DcoModel() {
  // set parameters
  dcoPar_ = new DcoParams();
  dcoMessageHandler_ = new CoinMessageHandler();
#ifdef DISCO_DEBUG
  dcoMessageHandler_->setLogLevel(4);
#endif
  dcoMessages_ = new DcoMessage();
  // initialize other fields
  colLB_ = NULL;
  colUB_ = NULL;
  rowLB_ = NULL;
  rowUB_ = NULL;
  numCols_ = 0;
  numRows_ = 0;
  numElems_ = 0;
  matrix_ = NULL;
  objSense_ = 0.0;
  objCoef_ = NULL;
  numCones_ = 0;
  numIntegerCols_ = 0;
  intColIndices_ = NULL;
  numSolutions_ = 0;
  // todo(aykut) this might create problems.
  incObjValue_ = 0.0;
  incumbentSol_ = NULL;
  // todo(aykut) following two might create problems.
  cutoff_ = 0.0;
  cutoffInc_ = 0.0;
  branchStrategy_ = NULL;
  rampUpBranchStrategy_ = NULL;
  activeNode_ = NULL;
  numNodes_ = 0;
  /** Number of lp(Simplex) iterations. */
  numIterations_ = 0;;
  /** Average number of lp iterations to solve a subproblem. */
  aveIterations_ = 0;
  /** The number of passes during bounding procedure.*/
  boundingPass_ = 0;
  /** Current relative optimal gap. */
  currRelGap_ = 1e5;
  /** Current absolute optimal gap. */
  currAbsGap_ = 1e5;
  // todo(aykut) why are we keeping this in the DcoModel class.
  // It seems it is ony used in DcoTreeNode::installSubProblem()
  /** Temporary store old cuts at a node when installing a node. */
  oldConstraints_ = 0;
  /** The memory size allocated for oldConstraints_. */
  oldConstraintsSize_ = 0;
  /** Number of old constraints. */
  numOldConstraints_ = 0;
}

DcoModel::~DcoModel() {
  // solver_ is freed in main function.
  if (matrix_) {
    delete matrix_;
  }
  if (colLB_) {
    delete[] colLB_;
  }
  if (colUB_) {
    delete[] colUB_;
  }
  if (rowLB_) {
    delete[] rowLB_;
  }
  if (rowUB_) {
    delete[] rowUB_;
  }
  if (objCoef_) {
    delete[] objCoef_;
  }
  if (incumbentSol_) {
    delete[] incumbentSol_;
  }
  if (branchStrategy_) {
    delete branchStrategy_;
  }
  if (rampUpBranchStrategy_) {
    delete rampUpBranchStrategy_;
  }
  if (activeNode_) {
    delete activeNode_;
  }
  if (dcoPar_) {
    delete dcoPar_;
  }
  for (int i=0; i<numOldConstraints_; ++i) {
    delete oldConstraints_[i];
  }
  delete[] oldConstraints_;
  if (dcoMessageHandler_) {
    delete dcoMessageHandler_;
  }
  if (dcoMessages_) {
    delete dcoMessages_;
  }
}

#if defined(__OA__)
void DcoModel::setSolver(OsiSolverInterface * solver) {
  solver_ = solver;
}
#else
void DcoModel::setSolver(OsiConicSolverInterface * solver) {
  solver_ = solver;
}
#endif

// read conic mps
void DcoModel::readInstance(char const * dataFile) {
  // get log level parameters
  int dcoLogLevel =  dcoPar_->entry(DcoParams::logLevel);
  // get input file name
  std::string input_file(dataFile);
  std::string base_name = input_file.substr(0, input_file.rfind('.'));
  std::string extension = input_file.substr(input_file.rfind('.')+1);
  if (extension.compare("mps")) {
    dcoMessageHandler_->message(DISCO_READ_MPSFILEONLY,
				*dcoMessages_) << CoinMessageEol;
  }
  // read mps file
  CoinMpsIO * reader = new CoinMpsIO;
  reader->messageHandler()->setLogLevel(dcoLogLevel);
  reader->readMps(dataFile, "");
  numCols_ = reader->getNumCols();
  numRows_ = reader->getNumRows();
  numElems_ = reader->getNumElements();
  matrix_ = new CoinPackedMatrix(*(reader->getMatrixByCol()));
  // == allocate variable bounds
  colLB_ = new double [numCols_];
  colUB_ = new double [numCols_];
  // == allocate row bounds
  rowLB_ = new double [numRows_];
  rowUB_ = new double [numRows_];
  // == copy bounds
  std::copy(reader->getColLower(), reader->getColLower()+numCols_, colLB_);
  std::copy(reader->getColUpper(), reader->getColUpper()+numCols_, colUB_);
  std::copy(reader->getRowLower(), reader->getRowLower()+numRows_, rowLB_);
  std::copy(reader->getRowUpper(), reader->getRowUpper()+numRows_, rowUB_);
  // == set objective sense
  objSense_ = dcoPar_->entry(DcoParams::objSense);
  // == allocate objective coefficients
  objCoef_ = new double [numCols_];
  double const * reader_obj = reader->getObjCoefficients();
  if (objSense_ > 0.0) {
    std::copy(reader_obj, reader_obj+numCols_, objCoef_);
  }
  else {
    for (int i = 0; i<numCols_; ++i) {
      objCoef_[i] = -reader_obj[i];
    }
  }
  // == load data to solver
  solver_->loadProblem(*matrix_, colLB_, colUB_, objCoef_,
		       rowLB_, rowUB_);
  // == add variables to the model
  readAddVariables(reader);
  // == add linear constraints to the model
  readAddLinearConstraints(reader);
  // == add conic constraints to the model
  readAddConicConstraints(reader);
  delete reader;
}

// Add variables to *this.
void DcoModel::readAddVariables(CoinMpsIO * reader) {
  // get variable integrality constraints
  char const * is_integer = reader->integerColumns();
  DcoIntegralityType * i_type = new DcoIntegralityType[numCols_];
  for (int i=0; i<numCols_; ++i) {
    if (is_integer[i]) {
      i_type[i] = DcoIntegralityTypeInt;
    }
    else {
      i_type[i] = DcoIntegralityTypeCont;
    }
  }
  // add variables
  BcpsVariable ** variables = new BcpsVariable*[numCols_];
  for (int i=0; i<numCols_; ++i) {
    variables[i] = new DcoVariable(colLB_[i], colUB_[i], colLB_[i],
				   colLB_[i], i_type[i]);
  }
  setVariables(variables, numCols_);
  delete[] i_type;
  for (int i=0; i<numCols_; ++i) {
    delete variables[i];
  }
  delete[] variables;
}

void DcoModel::readAddLinearConstraints(CoinMpsIO * reader) {
  // == add constraints to *this
  BcpsConstraint ** constraints = new BcpsConstraint*[numRows_+numCones_];
  CoinPackedMatrix const * matrix = reader->getMatrixByRow();
  int const * indices = matrix->getIndices();
  double const * values = matrix->getElements();
  int const * lengths = matrix->getVectorLengths();
  int const * starts = matrix->getVectorStarts();
  for (int i=0; i<numRows_; ++i) {
    constraints[i] = new DcoLinearConstraint(lengths[i], indices+starts[i],
					     values+starts[i], rowLB_[i],
					     rowUB_[i]);
  }
  setConstraints(constraints, numRows_+numCones_);
  for (int i=0; i<numRows_+numCones_; ++i) {
    delete constraints[i];
  }
  delete[] constraints;
}

// read conic part and add conic constraints to the model.
void DcoModel::readAddConicConstraints(CoinMpsIO * reader) {
  int nOfCones = 0;
  int * coneStart = NULL;
  int * coneMembers = NULL;
  int * coneType = NULL;
  int reader_return = reader->readConicMps(NULL, coneStart, coneMembers,
				       coneType, nOfCones);
  // when there is no conic section status is -3.
  if (reader_return==-3) {
    dcoMessageHandler_->message(DISCO_READ_NOCONES,
				*dcoMessages_);
  }
  else if (reader_return!=0) {
    dcoMessageHandler_->message(DISCO_READ_MPSERROR,
				*dcoMessages_) << reader_return
					      << CoinMessageEol;
  }
  // store number of cones in the problem
  numCones_ = nOfCones;
  // log cone information messages
  if (nOfCones) {
    dcoMessageHandler_->message(DISCO_READ_CONESTATS1,
				*dcoMessages_) << nOfCones
					       << CoinMessageEol;
    for (int i=0; i<nOfCones; ++i) {
      dcoMessageHandler_->message(DISCO_READ_CONESTATS2,
				  *dcoMessages_)
	<< i
	<< coneStart[i+1] - coneStart[i]
	<< coneType[i]
	<< CoinMessageEol;
    }
  }
  // iterate over cones and add them to the model
  for (int i=0; i<nOfCones; ++i) {
    if (coneType[i]!=1 and coneType[i]!=2) {
      dcoMessageHandler_->message(DISCO_READ_CONEERROR,
				  *dcoMessages_) << CoinMessageEol;
    }
    int num_members = coneStart[i+1]-coneStart[i];
    if (coneType[i]==2 and num_members<3) {
      dcoMessageHandler_->message(DISCO_READ_ROTATEDCONESIZE,
				  *dcoMessages_) << CoinMessageEol;
    }
    DcoLorentzConeType type;
    if (coneType[i]==1) {
      type = DcoLorentzCone;
    }
    else if (coneType[i]==2) {
      type = DcoRotatedLorentzCone;
    }
    addConstraint(new DcoConicConstraint(type, num_members,
					 coneMembers+coneStart[i]));
    // cone_[i] = new OsiLorentzCone(type, num_members,
    //				  coneMembers+coneStart[i]);
#ifndef __OA__
    OsiLorentzConeType osi_type;
    if (coneType[i]==1) {
      type = OSI_QUAD;
    }
    else if (coneType[i]==2) {
      type = OSI_RQUAD;
    }
    solver_->addConicConstraint(type, coneStart[i+1]-coneStart[i],
				coneMembers+coneStart[i]);
#endif
  }
  delete[] coneStart;
  delete[] coneMembers;
  delete[] coneType;
}

void DcoModel::preprocess() {
#ifdef __OA__
  approximateCones();
  // update row information
  numRows_ = solver_->getNumRows();
  // update num elements
  numElems_ = solver_->getNumElements();
  // update row bounds
  delete[] rowLB_;
  delete[] rowUB_;
  rowLB_ = new double [numRows_];
  rowUB_ = new double [numRows_];
  std::copy(solver_->getRowLower(),
	    solver_->getRowLower()+numRows_,
	    rowLB_);
  std::copy(solver_->getRowUpper(),
	    solver_->getRowUpper()+numRows_,
	    rowUB_);
#endif
}

void DcoModel::approximateCones() {
}

AlpsTreeNode * DcoModel::createRoot() {
  DcoTreeNode * root = new DcoTreeNode();
  DcoNodeDesc * desc = new DcoNodeDesc(this);
  root->setDesc(desc);
  std::vector<BcpsVariable *> cols = getVariables();
  std::vector<BcpsConstraint *> rows = getConstraints();
  int numCols = static_cast<int> (cols.size());
  int numRows = static_cast<int> (rows.size());
  int * varIndices1 = new int [numCols];
  int * varIndices2 = new int [numCols];
  int * varIndices3 = NULL;
  int * varIndices4 = NULL;
  double * vlhe = new double [numCols];
  double * vuhe = new double [numCols];
  double * vlse = NULL;
  double * vuse = NULL;
  int * conIndices1 = new int [numRows];
  int * conIndices2 = new int [numRows];
  int * conIndices3 = NULL;
  int * conIndices4 = NULL;
  double * clhe = new double [numRows];
  double * cuhe = new double [numRows];
  double * clse = NULL;
  double * cuse = NULL;
  //-------------------------------------------------------------
  // Get var bounds and indices.
  //-------------------------------------------------------------
  for (int i=0; i<numCols; ++i) {
    vlhe[i] = cols[i]->getLbHard();
    vuhe[i] = cols[i]->getUbHard();
    varIndices1[i] = i;
    varIndices2[i] = i;
  }
  //-------------------------------------------------------------
  // Get con bounds and indices.
  //-------------------------------------------------------------
  for (int i=0; i<numRows; ++i) {
    clhe[i] = rows[i]->getLbHard();
    cuhe[i] = rows[i]->getUbHard();
    conIndices1[i] = i;
    conIndices2[i] = i;
  }
  int * tempInd = NULL;
  BcpsObject ** tempObj = NULL;
  desc->assignVars(0, tempInd,
		   0, tempObj,
		   false, numCols, varIndices1, vlhe, /*Var hard lb*/
		   false, numCols, varIndices2, vuhe, /*Var hard ub*/
		   false, 0, varIndices3, vlse,       /*Var soft lb*/
		   false, 0, varIndices4, vuse);      /*Var soft ub*/
  desc->assignCons(0, tempInd,
		   0, tempObj,
		   false, numRows, conIndices1, clhe, /*Con hard lb*/
		   false, numRows, conIndices2, cuhe, /*Con hard ub*/
		   false, 0,conIndices3,clse,         /*Con soft lb*/
		   false, 0,conIndices4,cuse);        /*Con soft ub*/
  //-------------------------------------------------------------
  // Mark it as an explicit node.
  //-------------------------------------------------------------
  root->setExplicit(1);
  return root;
}
<commit_msg>bug fix.<commit_after>#include <CoinMpsIO.hpp>

#include "DcoModel.hpp"
#include "DcoMessage.hpp"
#include "DcoTreeNode.hpp"
#include "DcoNodeDesc.hpp"
#include "DcoVariable.hpp"
#include "DcoLinearConstraint.hpp"
#include "DcoConicConstraint.hpp"

DcoModel::DcoModel() {
  // set parameters
  dcoPar_ = new DcoParams();
  dcoMessageHandler_ = new CoinMessageHandler();
#ifdef DISCO_DEBUG
  dcoMessageHandler_->setLogLevel(4);
#endif
  dcoMessages_ = new DcoMessage();
  // initialize other fields
  colLB_ = NULL;
  colUB_ = NULL;
  rowLB_ = NULL;
  rowUB_ = NULL;
  numCols_ = 0;
  numRows_ = 0;
  numElems_ = 0;
  matrix_ = NULL;
  objSense_ = 0.0;
  objCoef_ = NULL;
  numCones_ = 0;
  numIntegerCols_ = 0;
  intColIndices_ = NULL;
  numSolutions_ = 0;
  // todo(aykut) this might create problems.
  incObjValue_ = 0.0;
  incumbentSol_ = NULL;
  // todo(aykut) following two might create problems.
  cutoff_ = 0.0;
  cutoffInc_ = 0.0;
  branchStrategy_ = NULL;
  rampUpBranchStrategy_ = NULL;
  activeNode_ = NULL;
  numNodes_ = 0;
  /** Number of lp(Simplex) iterations. */
  numIterations_ = 0;;
  /** Average number of lp iterations to solve a subproblem. */
  aveIterations_ = 0;
  /** The number of passes during bounding procedure.*/
  boundingPass_ = 0;
  /** Current relative optimal gap. */
  currRelGap_ = 1e5;
  /** Current absolute optimal gap. */
  currAbsGap_ = 1e5;
  // todo(aykut) why are we keeping this in the DcoModel class.
  // It seems it is ony used in DcoTreeNode::installSubProblem()
  /** Temporary store old cuts at a node when installing a node. */
  oldConstraints_ = 0;
  /** The memory size allocated for oldConstraints_. */
  oldConstraintsSize_ = 0;
  /** Number of old constraints. */
  numOldConstraints_ = 0;
}

DcoModel::~DcoModel() {
  // solver_ is freed in main function.
  if (matrix_) {
    delete matrix_;
  }
  if (colLB_) {
    delete[] colLB_;
  }
  if (colUB_) {
    delete[] colUB_;
  }
  if (rowLB_) {
    delete[] rowLB_;
  }
  if (rowUB_) {
    delete[] rowUB_;
  }
  if (objCoef_) {
    delete[] objCoef_;
  }
  if (incumbentSol_) {
    delete[] incumbentSol_;
  }
  if (branchStrategy_) {
    delete branchStrategy_;
  }
  if (rampUpBranchStrategy_) {
    delete rampUpBranchStrategy_;
  }
  if (activeNode_) {
    delete activeNode_;
  }
  if (dcoPar_) {
    delete dcoPar_;
  }
  for (int i=0; i<numOldConstraints_; ++i) {
    delete oldConstraints_[i];
  }
  delete[] oldConstraints_;
  if (dcoMessageHandler_) {
    delete dcoMessageHandler_;
  }
  if (dcoMessages_) {
    delete dcoMessages_;
  }
}

#if defined(__OA__)
void DcoModel::setSolver(OsiSolverInterface * solver) {
  solver_ = solver;
}
#else
void DcoModel::setSolver(OsiConicSolverInterface * solver) {
  solver_ = solver;
}
#endif

// read conic mps
void DcoModel::readInstance(char const * dataFile) {
  // get log level parameters
  int dcoLogLevel =  dcoPar_->entry(DcoParams::logLevel);
  // get input file name
  std::string input_file(dataFile);
  std::string base_name = input_file.substr(0, input_file.rfind('.'));
  std::string extension = input_file.substr(input_file.rfind('.')+1);
  if (extension.compare("mps")) {
    dcoMessageHandler_->message(DISCO_READ_MPSFILEONLY,
				*dcoMessages_) << CoinMessageEol;
  }
  // read mps file
  CoinMpsIO * reader = new CoinMpsIO;
  reader->messageHandler()->setLogLevel(dcoLogLevel);
  reader->readMps(dataFile, "");
  numCols_ = reader->getNumCols();
  numRows_ = reader->getNumRows();
  numElems_ = reader->getNumElements();
  matrix_ = new CoinPackedMatrix(*(reader->getMatrixByCol()));
  // == allocate variable bounds
  colLB_ = new double [numCols_];
  colUB_ = new double [numCols_];
  // == allocate row bounds
  rowLB_ = new double [numRows_];
  rowUB_ = new double [numRows_];
  // == copy bounds
  std::copy(reader->getColLower(), reader->getColLower()+numCols_, colLB_);
  std::copy(reader->getColUpper(), reader->getColUpper()+numCols_, colUB_);
  std::copy(reader->getRowLower(), reader->getRowLower()+numRows_, rowLB_);
  std::copy(reader->getRowUpper(), reader->getRowUpper()+numRows_, rowUB_);
  // == set objective sense
  objSense_ = dcoPar_->entry(DcoParams::objSense);
  // == allocate objective coefficients
  objCoef_ = new double [numCols_];
  double const * reader_obj = reader->getObjCoefficients();
  if (objSense_ > 0.0) {
    std::copy(reader_obj, reader_obj+numCols_, objCoef_);
  }
  else {
    for (int i = 0; i<numCols_; ++i) {
      objCoef_[i] = -reader_obj[i];
    }
  }
  // == load data to solver
  solver_->loadProblem(*matrix_, colLB_, colUB_, objCoef_,
		       rowLB_, rowUB_);
  // == add variables to the model
  readAddVariables(reader);
  // == add linear constraints to the model
  readAddLinearConstraints(reader);
  // == add conic constraints to the model
  readAddConicConstraints(reader);
  delete reader;
}

// Add variables to *this.
void DcoModel::readAddVariables(CoinMpsIO * reader) {
  // get variable integrality constraints
  char const * is_integer = reader->integerColumns();
  DcoIntegralityType * i_type = new DcoIntegralityType[numCols_];
  for (int i=0; i<numCols_; ++i) {
    if (is_integer[i]) {
      i_type[i] = DcoIntegralityTypeInt;
    }
    else {
      i_type[i] = DcoIntegralityTypeCont;
    }
  }
  // add variables
  BcpsVariable ** variables = new BcpsVariable*[numCols_];
  for (int i=0; i<numCols_; ++i) {
    variables[i] = new DcoVariable(colLB_[i], colUB_[i], colLB_[i],
				   colLB_[i], i_type[i]);
  }
  setVariables(variables, numCols_);
  delete[] i_type;
  // variables are now owned by BcpsModel, do not free them.
  // for (int i=0; i<numCols_; ++i) {
  //   delete variables[i];
  // }
  delete[] variables;
}

void DcoModel::readAddLinearConstraints(CoinMpsIO * reader) {
  // == add constraints to *this
  BcpsConstraint ** constraints = new BcpsConstraint*[numRows_+numCones_];
  CoinPackedMatrix const * matrix = reader->getMatrixByRow();
  int const * indices = matrix->getIndices();
  double const * values = matrix->getElements();
  int const * lengths = matrix->getVectorLengths();
  int const * starts = matrix->getVectorStarts();
  for (int i=0; i<numRows_; ++i) {
    constraints[i] = new DcoLinearConstraint(lengths[i], indices+starts[i],
					     values+starts[i], rowLB_[i],
					     rowUB_[i]);
  }
  setConstraints(constraints, numRows_+numCones_);
  // constraints are owned by BcpsModel. Do not free them here.
  // for (int i=0; i<numRows_+numCones_; ++i) {
  //   delete constraints[i];
  // }
  delete[] constraints;
}

// read conic part and add conic constraints to the model.
void DcoModel::readAddConicConstraints(CoinMpsIO * reader) {
  int nOfCones = 0;
  int * coneStart = NULL;
  int * coneMembers = NULL;
  int * coneType = NULL;
  int reader_return = reader->readConicMps(NULL, coneStart, coneMembers,
				       coneType, nOfCones);
  // when there is no conic section status is -3.
  if (reader_return==-3) {
    dcoMessageHandler_->message(DISCO_READ_NOCONES,
				*dcoMessages_);
  }
  else if (reader_return!=0) {
    dcoMessageHandler_->message(DISCO_READ_MPSERROR,
				*dcoMessages_) << reader_return
					      << CoinMessageEol;
  }
  // store number of cones in the problem
  numCones_ = nOfCones;
  // log cone information messages
  if (nOfCones) {
    dcoMessageHandler_->message(DISCO_READ_CONESTATS1,
				*dcoMessages_) << nOfCones
					       << CoinMessageEol;
    for (int i=0; i<nOfCones; ++i) {
      dcoMessageHandler_->message(DISCO_READ_CONESTATS2,
				  *dcoMessages_)
	<< i
	<< coneStart[i+1] - coneStart[i]
	<< coneType[i]
	<< CoinMessageEol;
    }
  }
  // iterate over cones and add them to the model
  for (int i=0; i<nOfCones; ++i) {
    if (coneType[i]!=1 and coneType[i]!=2) {
      dcoMessageHandler_->message(DISCO_READ_CONEERROR,
				  *dcoMessages_) << CoinMessageEol;
    }
    int num_members = coneStart[i+1]-coneStart[i];
    if (coneType[i]==2 and num_members<3) {
      dcoMessageHandler_->message(DISCO_READ_ROTATEDCONESIZE,
				  *dcoMessages_) << CoinMessageEol;
    }
    DcoLorentzConeType type;
    if (coneType[i]==1) {
      type = DcoLorentzCone;
    }
    else if (coneType[i]==2) {
      type = DcoRotatedLorentzCone;
    }
    addConstraint(new DcoConicConstraint(type, num_members,
					 coneMembers+coneStart[i]));
    // cone_[i] = new OsiLorentzCone(type, num_members,
    //				  coneMembers+coneStart[i]);
#ifndef __OA__
    OsiLorentzConeType osi_type;
    if (coneType[i]==1) {
      osi_type = OSI_QUAD;
    }
    else if (coneType[i]==2) {
      osi_type = OSI_RQUAD;
    }
    solver_->addConicConstraint(osi_type, coneStart[i+1]-coneStart[i],
				coneMembers+coneStart[i]);
#endif
  }
  delete[] coneStart;
  delete[] coneMembers;
  delete[] coneType;
}

void DcoModel::preprocess() {
#ifdef __OA__
  approximateCones();
  // update row information
  numRows_ = solver_->getNumRows();
  // update num elements
  numElems_ = solver_->getNumElements();
  // update row bounds
  delete[] rowLB_;
  delete[] rowUB_;
  rowLB_ = new double [numRows_];
  rowUB_ = new double [numRows_];
  std::copy(solver_->getRowLower(),
	    solver_->getRowLower()+numRows_,
	    rowLB_);
  std::copy(solver_->getRowUpper(),
	    solver_->getRowUpper()+numRows_,
	    rowUB_);
#endif
}

void DcoModel::approximateCones() {
}

AlpsTreeNode * DcoModel::createRoot() {
  DcoTreeNode * root = new DcoTreeNode();
  DcoNodeDesc * desc = new DcoNodeDesc(this);
  root->setDesc(desc);
  std::vector<BcpsVariable *> cols = getVariables();
  std::vector<BcpsConstraint *> rows = getConstraints();
  int numCols = static_cast<int> (cols.size());
  int numRows = static_cast<int> (rows.size());
  int * varIndices1 = new int [numCols];
  int * varIndices2 = new int [numCols];
  int * varIndices3 = NULL;
  int * varIndices4 = NULL;
  double * vlhe = new double [numCols];
  double * vuhe = new double [numCols];
  double * vlse = NULL;
  double * vuse = NULL;
  int * conIndices1 = new int [numRows];
  int * conIndices2 = new int [numRows];
  int * conIndices3 = NULL;
  int * conIndices4 = NULL;
  double * clhe = new double [numRows];
  double * cuhe = new double [numRows];
  double * clse = NULL;
  double * cuse = NULL;
  //-------------------------------------------------------------
  // Get var bounds and indices.
  //-------------------------------------------------------------
  for (int i=0; i<numCols; ++i) {
    vlhe[i] = cols[i]->getLbHard();
    vuhe[i] = cols[i]->getUbHard();
    varIndices1[i] = i;
    varIndices2[i] = i;
  }
  //-------------------------------------------------------------
  // Get con bounds and indices.
  //-------------------------------------------------------------
  for (int i=0; i<numRows; ++i) {
    clhe[i] = rows[i]->getLbHard();
    cuhe[i] = rows[i]->getUbHard();
    conIndices1[i] = i;
    conIndices2[i] = i;
  }
  int * tempInd = NULL;
  BcpsObject ** tempObj = NULL;
  desc->assignVars(0, tempInd,
		   0, tempObj,
		   false, numCols, varIndices1, vlhe, /*Var hard lb*/
		   false, numCols, varIndices2, vuhe, /*Var hard ub*/
		   false, 0, varIndices3, vlse,       /*Var soft lb*/
		   false, 0, varIndices4, vuse);      /*Var soft ub*/
  desc->assignCons(0, tempInd,
		   0, tempObj,
		   false, numRows, conIndices1, clhe, /*Con hard lb*/
		   false, numRows, conIndices2, cuhe, /*Con hard ub*/
		   false, 0,conIndices3,clse,         /*Con soft lb*/
		   false, 0,conIndices4,cuse);        /*Con soft ub*/
  //-------------------------------------------------------------
  // Mark it as an explicit node.
  //-------------------------------------------------------------
  root->setExplicit(1);
  return root;
}
<|endoftext|>


<commit_before>/*
 * AscEmu Framework based on ArcEmu MMORPG Server
 * Copyright (C) 2014-2015 AscEmu Team <http://www.ascemu.org/>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 * Copyright (C) 2005-2007 Ascent Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

initialiseSingleton(AddonMgr);

//#define DEBUG_PRINT_ADDON_PACKET            // Prints out Received addon packet when char logging in

// hacky key
static uint8 PublicKey[265] = { 0x02, 0x01, 0x01, 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00};

AddonMgr::AddonMgr()
{
    mKnownAddons.clear();
}

AddonMgr::~AddonMgr()
{
    KnownAddonsItr itr;
    for (itr = mKnownAddons.begin(); itr != mKnownAddons.end(); ++itr)
    {
        delete itr->second;
    }
    mKnownAddons.clear();
}

bool AddonMgr::IsAddonBanned(uint64 crc, std::string name)
{
    return false;    // bleh needs work
}

bool AddonMgr::IsAddonBanned(std::string name, uint64 crc)
{
    KnownAddonsItr itr = mKnownAddons.find(name);
    if (itr != mKnownAddons.end())
    {
        if (itr->second->banned)
        {
            LOG_DEBUG("Addon %s is banned.", name.c_str());
            return true;
        }
    }
    else
    {
        // New addon. It'll be saved to db at server shutdown.
        AddonEntry* ent = new AddonEntry;
        ent->name = name;
        ent->crc = crc;
        ent->banned = false;    // by default.. we can change this I guess..
        ent->isNew = true;
        ent->showinlist = true;

        LOG_DEBUG("Discovered new addon %s sent by client.", name.c_str());

        mKnownAddons[ent->name] = ent;
    }

    return false;
}

bool AddonMgr::ShouldShowInList(std::string name)
{
    KnownAddonsItr itr = mKnownAddons.find(name);

    if (itr != mKnownAddons.end())
    {
        if (itr->second->showinlist)
            return true;
        else
            return false;
    }
    else
    {
        // New addon. It'll be saved to db at server shutdown.
        AddonEntry* ent = new AddonEntry;
        ent->name = name;
        ent->crc = 0;
        ent->banned = false;    // by default.. we can change this I guess..
        ent->isNew = true;
        ent->showinlist = true;

        LOG_DEBUG("Discovered new addon %s sent by client.", name.c_str());

        mKnownAddons[ent->name] = ent;
    }

    return true;
}

void AddonMgr::SendAddonInfoPacket(WorldPacket* source, uint32 pos, WorldSession* m_session)
{
    WorldPacket returnpacket;
    returnpacket.Initialize(SMSG_ADDON_INFO);    // SMSG_ADDON_INFO

    uint32 realsize;
    uLongf rsize;

    try
    {
        *source >> realsize;
    }
    catch(ByteBuffer::error &)
    {
        LOG_DEBUG("Warning: Incomplete auth session sent.");
        return;
    }

    rsize = realsize;
    size_t position = source->rpos();

    ByteBuffer unpacked;
    unpacked.resize(realsize);

    if ((source->size() - position) < 4 || realsize == 0)
    {
        // we shouldn't get here.. but just in case this will stop any crash here.
        LOG_DEBUG("Warning: Incomplete auth session sent.");
        return;
    }

    int32 result = uncompress((uint8*)unpacked.contents(), &rsize, (uint8*)(*source).contents() + position, (uLong)((*source).size() - position));

    if (result != Z_OK)
    {
        LOG_ERROR("Decompression of addon section of CMSG_AUTH_SESSION failed.");
        return;
    }

    LOG_DETAIL("Decompression of addon section of CMSG_AUTH_SESSION succeeded.");

    uint8 Enable; // based on the parsed files from retool
    uint32 crc;
    uint32 unknown;

    std::string name;

    uint32 addoncount;
    unpacked >> addoncount;

    uint8 unk;
    uint8 unk1;
    uint8 unk2;
    for (uint32 i = 0; i < addoncount; ++i)
    {
        if (unpacked.rpos() >= unpacked.size())
            break;

        unpacked >> name;
        unpacked >> Enable;
        unpacked >> crc;
        unpacked >> unknown;

        // Hacky fix, Yea I know its a hacky fix I will make a proper handler one's I got the crc crap
        /*        if (crc != 0x4C1C776D) // CRC of public key version 2.0.1
                    returnpacket.append(PublicKey,264); // part of the hacky fix
                else
                    returnpacket << uint8(0x02) << uint8(0x01) << uint8(0x00) << uint32(0) << uint8(0);*/
        /*if (!AppendPublicKey(returnpacket, name, crc))
            returnpacket << uint8(1) << uint8(0) << uint8(0);*/

        unk = (Enable ? 2 : 1);
        returnpacket << unk;
        unk1 = (Enable ? 1 : 0);
        returnpacket << unk1;
        if (unk1)
        {
            if (crc != 0x4C1C776D)
            {
                returnpacket << uint8(1);
                returnpacket.append(PublicKey, 264);
            }
            else
                returnpacket << uint8(0);

            returnpacket << uint32(0);
        }

        unk2 = (Enable ? 0 : 1);
        returnpacket << unk2;
        if (unk2)
            returnpacket << uint8(0);
    }

    /*unknown 4 bytes at the end of the packet. Stays 0 for me. Tried custom addons, deleting, faulty etc. It stays 0.
    */
    returnpacket << uint32(0); //Some additional count for additional records, but we won't send them.

    m_session->SendPacket(&returnpacket);
}

bool AddonMgr::AppendPublicKey(WorldPacket & data, std::string & AddonName, uint32 CRC)
{
    if (CRC == 0x4C1C776D)
    {
        // Open public key file with that addon
        AddonDataItr itr = mAddonData.find(AddonName);

        if (itr != mAddonData.end())
            data.append(itr->second);
        else
        {
            // open the file
            char path[500];
            snprintf(path, 500, "addons\\%s.pub", AddonName.c_str());
            FILE* f = fopen(path, "rb");
            if (f != 0)
            {
                // read the file into a bytebuffer
                ByteBuffer buf;
                fseek(f, 0, SEEK_END);
                uint32 length = 264/*ftell(f)*/;
                fseek(f, 0, SEEK_SET);
                buf.resize(length);
                if (fread((void*)buf.contents(), length, 1, f) != 1)
                    return false;
                fclose(f);

                mAddonData[AddonName] = buf;
                data.append(buf);
            }
            else
            {
                ByteBuffer buf;
                buf.append(PublicKey, 264);
                mAddonData[AddonName] = buf;
                data.append(buf);
            }
        }
        return true;
    }
    return false;
}

void AddonMgr::LoadFromDB()
{
    const char* loadClientAddons = "SELECT id, name, crc, banned, showinlist FROM clientaddons";
    bool success = false;
    QueryResult* result = CharacterDatabase.Query(&success, loadClientAddons);
    if (!success)
    {
        Log.Error("AddonMgr", "Query failed: %s", loadClientAddons);
        return;
    }
    if (!result)
    {
        Log.Notice("AddonMgr", "No defined ClientAddons");
        return;
    }

    Field* field;
    AddonEntry* ent;

    do
    {
        field = result->Fetch();
        ent = new AddonEntry;

        ent->name = field[1].GetString();
        ent->crc = field[2].GetUInt64();
        ent->banned = (field[3].GetUInt32() > 0 ? true : false);
        ent->isNew = false;

        // To avoid crashes for stilly nubs who don't update table :P
        if (result->GetFieldCount() == 5)
            ent->showinlist = (field[4].GetUInt32() > 0 ? true : false);

        mKnownAddons[ent->name] = ent;

    }
    while(result->NextRow());

    delete result;
}

void AddonMgr::SaveToDB()
{
    LOG_DETAIL("AddonMgr: Saving any new addons discovered in this session to database.");

    KnownAddonsItr itr;

    for (itr = mKnownAddons.begin(); itr != mKnownAddons.end(); ++itr)
    {
        if (itr->second->isNew)
        {
            LOG_DETAIL("Saving new addon %s", itr->second->name.c_str());
            std::stringstream ss;
            ss << "INSERT INTO clientaddons (name, crc, banned, showinlist) VALUES(\""
               << CharacterDatabase.EscapeString(itr->second->name) << "\",\""
               << itr->second->crc << "\",\""
               << itr->second->banned << "\",\""
               << itr->second->showinlist << "\");";

            CharacterDatabase.Execute(ss.str().c_str());
        }
    }
}
<commit_msg>Resolved CID108194 (Resource leak )<commit_after>/*
 * AscEmu Framework based on ArcEmu MMORPG Server
 * Copyright (C) 2014-2015 AscEmu Team <http://www.ascemu.org/>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 * Copyright (C) 2005-2007 Ascent Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

initialiseSingleton(AddonMgr);

//#define DEBUG_PRINT_ADDON_PACKET            // Prints out Received addon packet when char logging in

// hacky key
static uint8 PublicKey[265] = { 0x02, 0x01, 0x01, 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00};

AddonMgr::AddonMgr()
{
    mKnownAddons.clear();
}

AddonMgr::~AddonMgr()
{
    KnownAddonsItr itr;
    for (itr = mKnownAddons.begin(); itr != mKnownAddons.end(); ++itr)
    {
        delete itr->second;
    }
    mKnownAddons.clear();
}

bool AddonMgr::IsAddonBanned(uint64 crc, std::string name)
{
    return false;    // bleh needs work
}

bool AddonMgr::IsAddonBanned(std::string name, uint64 crc)
{
    KnownAddonsItr itr = mKnownAddons.find(name);
    if (itr != mKnownAddons.end())
    {
        if (itr->second->banned)
        {
            LOG_DEBUG("Addon %s is banned.", name.c_str());
            return true;
        }
    }
    else
    {
        // New addon. It'll be saved to db at server shutdown.
        AddonEntry* ent = new AddonEntry;
        ent->name = name;
        ent->crc = crc;
        ent->banned = false;    // by default.. we can change this I guess..
        ent->isNew = true;
        ent->showinlist = true;

        LOG_DEBUG("Discovered new addon %s sent by client.", name.c_str());

        mKnownAddons[ent->name] = ent;
    }

    return false;
}

bool AddonMgr::ShouldShowInList(std::string name)
{
    KnownAddonsItr itr = mKnownAddons.find(name);

    if (itr != mKnownAddons.end())
    {
        if (itr->second->showinlist)
            return true;
        else
            return false;
    }
    else
    {
        // New addon. It'll be saved to db at server shutdown.
        AddonEntry* ent = new AddonEntry;
        ent->name = name;
        ent->crc = 0;
        ent->banned = false;    // by default.. we can change this I guess..
        ent->isNew = true;
        ent->showinlist = true;

        LOG_DEBUG("Discovered new addon %s sent by client.", name.c_str());

        mKnownAddons[ent->name] = ent;
    }

    return true;
}

void AddonMgr::SendAddonInfoPacket(WorldPacket* source, uint32 pos, WorldSession* m_session)
{
    WorldPacket returnpacket;
    returnpacket.Initialize(SMSG_ADDON_INFO);    // SMSG_ADDON_INFO

    uint32 realsize;
    uLongf rsize;

    try
    {
        *source >> realsize;
    }
    catch(ByteBuffer::error &)
    {
        LOG_DEBUG("Warning: Incomplete auth session sent.");
        return;
    }

    rsize = realsize;
    size_t position = source->rpos();

    ByteBuffer unpacked;
    unpacked.resize(realsize);

    if ((source->size() - position) < 4 || realsize == 0)
    {
        // we shouldn't get here.. but just in case this will stop any crash here.
        LOG_DEBUG("Warning: Incomplete auth session sent.");
        return;
    }

    int32 result = uncompress((uint8*)unpacked.contents(), &rsize, (uint8*)(*source).contents() + position, (uLong)((*source).size() - position));

    if (result != Z_OK)
    {
        LOG_ERROR("Decompression of addon section of CMSG_AUTH_SESSION failed.");
        return;
    }

    LOG_DETAIL("Decompression of addon section of CMSG_AUTH_SESSION succeeded.");

    uint8 Enable; // based on the parsed files from retool
    uint32 crc;
    uint32 unknown;

    std::string name;

    uint32 addoncount;
    unpacked >> addoncount;

    uint8 unk;
    uint8 unk1;
    uint8 unk2;
    for (uint32 i = 0; i < addoncount; ++i)
    {
        if (unpacked.rpos() >= unpacked.size())
            break;

        unpacked >> name;
        unpacked >> Enable;
        unpacked >> crc;
        unpacked >> unknown;

        // Hacky fix, Yea I know its a hacky fix I will make a proper handler one's I got the crc crap
        /*        if (crc != 0x4C1C776D) // CRC of public key version 2.0.1
                    returnpacket.append(PublicKey,264); // part of the hacky fix
                else
                    returnpacket << uint8(0x02) << uint8(0x01) << uint8(0x00) << uint32(0) << uint8(0);*/
        /*if (!AppendPublicKey(returnpacket, name, crc))
            returnpacket << uint8(1) << uint8(0) << uint8(0);*/

        unk = (Enable ? 2 : 1);
        returnpacket << unk;
        unk1 = (Enable ? 1 : 0);
        returnpacket << unk1;
        if (unk1)
        {
            if (crc != 0x4C1C776D)
            {
                returnpacket << uint8(1);
                returnpacket.append(PublicKey, 264);
            }
            else
                returnpacket << uint8(0);

            returnpacket << uint32(0);
        }

        unk2 = (Enable ? 0 : 1);
        returnpacket << unk2;
        if (unk2)
            returnpacket << uint8(0);
    }

    /*unknown 4 bytes at the end of the packet. Stays 0 for me. Tried custom addons, deleting, faulty etc. It stays 0.
    */
    returnpacket << uint32(0); //Some additional count for additional records, but we won't send them.

    m_session->SendPacket(&returnpacket);
}

bool AddonMgr::AppendPublicKey(WorldPacket & data, std::string & AddonName, uint32 CRC)
{
    if (CRC == 0x4C1C776D)
    {
        // Open public key file with that addon
        AddonDataItr itr = mAddonData.find(AddonName);

        if (itr != mAddonData.end())
            data.append(itr->second);
        else
        {
            // open the file
            char path[500];
            snprintf(path, 500, "addons\\%s.pub", AddonName.c_str());
            FILE* f = fopen(path, "rb");
            if (f != 0)
            {
                // read the file into a bytebuffer
                ByteBuffer buf;
                fseek(f, 0, SEEK_END);
                uint32 length = 264/*ftell(f)*/;
                fseek(f, 0, SEEK_SET);
                buf.resize(length);
                if (fread((void*)buf.contents(), length, 1, f) != 1)
                {
                    fclose(f);
                    return false;
                }

                fclose(f);

                mAddonData[AddonName] = buf;
                data.append(buf);
            }
            else
            {
                ByteBuffer buf;
                buf.append(PublicKey, 264);
                mAddonData[AddonName] = buf;
                data.append(buf);
            }
        }
        return true;
    }
    return false;
}

void AddonMgr::LoadFromDB()
{
    const char* loadClientAddons = "SELECT id, name, crc, banned, showinlist FROM clientaddons";
    bool success = false;
    QueryResult* result = CharacterDatabase.Query(&success, loadClientAddons);
    if (!success)
    {
        Log.Error("AddonMgr", "Query failed: %s", loadClientAddons);
        return;
    }
    if (!result)
    {
        Log.Notice("AddonMgr", "No defined ClientAddons");
        return;
    }

    Field* field;
    AddonEntry* ent;

    do
    {
        field = result->Fetch();
        ent = new AddonEntry;

        ent->name = field[1].GetString();
        ent->crc = field[2].GetUInt64();
        ent->banned = (field[3].GetUInt32() > 0 ? true : false);
        ent->isNew = false;

        // To avoid crashes for stilly nubs who don't update table :P
        if (result->GetFieldCount() == 5)
            ent->showinlist = (field[4].GetUInt32() > 0 ? true : false);

        mKnownAddons[ent->name] = ent;

    }
    while(result->NextRow());

    delete result;
}

void AddonMgr::SaveToDB()
{
    LOG_DETAIL("AddonMgr: Saving any new addons discovered in this session to database.");

    KnownAddonsItr itr;

    for (itr = mKnownAddons.begin(); itr != mKnownAddons.end(); ++itr)
    {
        if (itr->second->isNew)
        {
            LOG_DETAIL("Saving new addon %s", itr->second->name.c_str());
            std::stringstream ss;
            ss << "INSERT INTO clientaddons (name, crc, banned, showinlist) VALUES(\""
               << CharacterDatabase.EscapeString(itr->second->name) << "\",\""
               << itr->second->crc << "\",\""
               << itr->second->banned << "\",\""
               << itr->second->showinlist << "\");";

            CharacterDatabase.Execute(ss.str().c_str());
        }
    }
}
<|endoftext|>


<commit_before>#include <glog/logging.h>
#include <transport/listen_tcp_socket.h>
#include <transport/curl_pool.h>
#include <rules_loader.h>
#include <external/real_external.h>
#include <core/real_core_helper.h>
#include <core/real_core.h>
#include <stdlib.h>
#include <string.h>
#include <util/util.h>
#include <unistd.h>

real_core::real_core(const config & conf)
  :
    config_(conf),

    instrumentation_(conf),

    executor_pool_(instrumentation_, conf),

    main_loop_(make_main_async_loop()),

    scheduler_(new real_scheduler()),

    externals_(new real_external(conf, instrumentation_)),

    streams_(new streams(instrumentation_)),

    pubsub_(new pub_sub()),

    index_(new real_index(*pubsub_, [=](e_t e) { streams_->push_event(e); },
                          conf.index_expire_interval, *scheduler_,
                          instrumentation_, detach_thread)),

    tcp_server_(init_tcp_server(conf, *main_loop_, *streams_,
                executor_pool_, instrumentation_)),

    udp_server_(init_udp_server(conf, streams_)),

    ws_server_(init_ws_server(conf, *main_loop_, *pubsub_, *index_))
{

  if (conf.enable_internal_metrics) {
    start_instrumentation(*scheduler_, instrumentation_, *streams_);
  }

}

void real_core::start() {

  for (const auto & stream : load_rules(config_.rules_directory)) {
    add_stream(stream);
  }

  LOG(INFO) << "Brace for impact, starting nuclear core.";

  signal(SIGPIPE, SIG_IGN);

  main_loop_->start();

  VLOG(3) << "Stopping services";

  scheduler_->stop();
  executor_pool_.stop();
  streams_->stop();
  tcp_server_->stop();
  udp_server_->stop();
  ws_server_->stop();
  externals_->stop();

  LOG(INFO) << "Screw you guys, I'm going home.";
}

void real_core::add_stream(std::shared_ptr<streams_t> stream) {

  if (stream) {

    sh_streams_.push_back(stream);

    streams_->add_stream(*stream);

  }

}

real_core::~real_core() {
  VLOG(3) << "~real_core";
}

index_interface & real_core::idx() {
  return *index_;
}

scheduler_interface & real_core::sched() {
  return *scheduler_;
}

external_interface & real_core::externals() {
  return *externals_;
}

void start_core(int argc, char **argv) {

  int orig_argc = argc;
  char **orig_argv = copy_args(argc, argv);

  FLAGS_stderrthreshold = 0;
  FLAGS_colorlogtostderr = true;
  FLAGS_logbuflevel = -1;

  google::ParseCommandLineFlags(&argc, &argv, true);

  google::InitGoogleLogging(argv[0]);

  auto conf = create_config();

  ld_environment(orig_argv, conf.rules_directory);

  free_args(orig_argc, orig_argv);

  log_config(conf);

  g_core = make_real_core(conf);

  g_core->start();

  g_core.reset();
}
<commit_msg>Remove FLAGS_colorlogtostderr<commit_after>#include <glog/logging.h>
#include <transport/listen_tcp_socket.h>
#include <transport/curl_pool.h>
#include <rules_loader.h>
#include <external/real_external.h>
#include <core/real_core_helper.h>
#include <core/real_core.h>
#include <stdlib.h>
#include <string.h>
#include <util/util.h>
#include <unistd.h>

real_core::real_core(const config & conf)
  :
    config_(conf),

    instrumentation_(conf),

    executor_pool_(instrumentation_, conf),

    main_loop_(make_main_async_loop()),

    scheduler_(new real_scheduler()),

    externals_(new real_external(conf, instrumentation_)),

    streams_(new streams(instrumentation_)),

    pubsub_(new pub_sub()),

    index_(new real_index(*pubsub_, [=](e_t e) { streams_->push_event(e); },
                          conf.index_expire_interval, *scheduler_,
                          instrumentation_, detach_thread)),

    tcp_server_(init_tcp_server(conf, *main_loop_, *streams_,
                executor_pool_, instrumentation_)),

    udp_server_(init_udp_server(conf, streams_)),

    ws_server_(init_ws_server(conf, *main_loop_, *pubsub_, *index_))
{

  if (conf.enable_internal_metrics) {
    start_instrumentation(*scheduler_, instrumentation_, *streams_);
  }

}

void real_core::start() {

  for (const auto & stream : load_rules(config_.rules_directory)) {
    add_stream(stream);
  }

  LOG(INFO) << "Brace for impact, starting nuclear core.";

  signal(SIGPIPE, SIG_IGN);

  main_loop_->start();

  VLOG(3) << "Stopping services";

  scheduler_->stop();
  executor_pool_.stop();
  streams_->stop();
  tcp_server_->stop();
  udp_server_->stop();
  ws_server_->stop();
  externals_->stop();

  LOG(INFO) << "Screw you guys, I'm going home.";
}

void real_core::add_stream(std::shared_ptr<streams_t> stream) {

  if (stream) {

    sh_streams_.push_back(stream);

    streams_->add_stream(*stream);

  }

}

real_core::~real_core() {
  VLOG(3) << "~real_core";
}

index_interface & real_core::idx() {
  return *index_;
}

scheduler_interface & real_core::sched() {
  return *scheduler_;
}

external_interface & real_core::externals() {
  return *externals_;
}

void start_core(int argc, char **argv) {

  int orig_argc = argc;
  char **orig_argv = copy_args(argc, argv);

  FLAGS_stderrthreshold = 0;
  FLAGS_logbuflevel = -1;

  google::ParseCommandLineFlags(&argc, &argv, true);

  google::InitGoogleLogging(argv[0]);

  auto conf = create_config();

  ld_environment(orig_argv, conf.rules_directory);

  free_args(orig_argc, orig_argv);

  log_config(conf);

  g_core = make_real_core(conf);

  g_core->start();

  g_core.reset();
}
<|endoftext|>


<commit_before>#include "pink_epoll.h"
#include "pink_define.h"
#include "xdebug.h"
#include "status.h"

PinkEpoll::PinkEpoll()
{
    epfd_ = epoll_create(1024);
    events_ = (struct epoll_event *)malloc(sizeof(struct epoll_event) * PINK_MAX_CLIENTS);
    if (!events_) {
        log_err("init epoll_event error");
    }
    timeout_ = 1000;

    firedevent_ = (PinkFiredEvent *)malloc(sizeof(PinkFiredEvent) * PINK_MAX_CLIENTS);
}

PinkEpoll::~PinkEpoll()
{
    free(events_);
    close(epfd_);
}

Status PinkEpoll::PinkAddEvent(int fd, int mask)
{
    struct epoll_event ee;
    ee.data.fd = fd;
    /*
     * log_info("PinkAddEvent mask %d", mask);
     */
    ee.events = mask;
    if (epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ee) == -1) {
        log_info("Epoll add error");
        return Status::Corruption("epollAdd error");
    }
    return Status::OK();
}

Status PinkEpoll::PinkModEvent(int fd, int oMask, int mask)
{
    /*
     * log_info("PinkModEvent mask %d %d", fd, (oMask | mask));
     */
    struct epoll_event ee;
    ee.data.u64 = 0;
    ee.data.fd = fd;
    ee.events = (oMask | mask);
    if (epoll_ctl(epfd_, EPOLL_CTL_MOD, fd, &ee) == -1) {
        log_info("Epoll ctl error");
        return Status::Corruption("epollCtl error");
    }
    return Status::OK();
}

void PinkEpoll::PinkDelEvent(int fd)
{
    /*
     * Kernel < 2.6.9 need a non null event point to EPOLL_CTL_DEL
     */
    struct epoll_event ee;
    ee.data.fd = fd;
    epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, &ee);
}

int PinkEpoll::PinkPoll()
{
    int retval, numevents = 0;
    retval = epoll_wait(epfd_, events_, PINK_MAX_CLIENTS, 500);
    if (retval > 0) {
        numevents = retval;
        for (int i = 0; i < numevents; i++) {
            int mask = 0;
            firedevent_[i].fd_ = (events_ + i)->data.fd;
            /*
             * log_info("events + i events %d", (events_ + i)->events);
             */
            if ((events_ + i)->events & EPOLLIN) {
                mask |= EPOLLIN;
            }
            if ((events_ + i)->events & EPOLLOUT) {
                mask |= EPOLLOUT;
            }
            if ((events_ + i)->events & EPOLLERR) {
                mask |= EPOLLERR;
            }
            if ((events_ + i)->events & EPOLLHUP) {
                mask |= EPOLLHUP;
            }
            firedevent_[i].mask_ = mask;
        }
    }
    return numevents;
}
<commit_msg>add src pink_epoll<commit_after>#include "pink_epoll.h"
#include "pink_define.h"
#include "xdebug.h"
#include "status.h"

PinkEpoll::PinkEpoll()
{
  epfd_ = epoll_create(1024);
  events_ = (struct epoll_event *)malloc(sizeof(struct epoll_event) * PINK_MAX_CLIENTS);
  if (!events_) {
    log_err("init epoll_event error");
  }
  timeout_ = 1000;

  firedevent_ = (PinkFiredEvent *)malloc(sizeof(PinkFiredEvent) * PINK_MAX_CLIENTS);
}

PinkEpoll::~PinkEpoll()
{
  free(events_);
  close(epfd_);
}

Status PinkEpoll::PinkAddEvent(int fd, int mask)
{
  struct epoll_event ee;
  ee.data.fd = fd;
  /*
   * log_info("PinkAddEvent mask %d", mask);
   */
  ee.events = mask;
  if (epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ee) == -1) {
    log_info("Epoll add error");
    return Status::Corruption("epollAdd error");
  }
  return Status::OK();
}

Status PinkEpoll::PinkModEvent(int fd, int oMask, int mask)
{
  /*
   * log_info("PinkModEvent mask %d %d", fd, (oMask | mask));
   */
  struct epoll_event ee;
  ee.data.u64 = 0;
  ee.data.fd = fd;
  ee.events = (oMask | mask);
  if (epoll_ctl(epfd_, EPOLL_CTL_MOD, fd, &ee) == -1) {
    log_info("Epoll ctl error");
    return Status::Corruption("epollCtl error");
  }
  return Status::OK();
}

void PinkEpoll::PinkDelEvent(int fd)
{
  /*
   * Kernel < 2.6.9 need a non null event point to EPOLL_CTL_DEL
   */
  struct epoll_event ee;
  ee.data.fd = fd;
  epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, &ee);
}

int PinkEpoll::PinkPoll()
{
  int retval, numevents = 0;
  retval = epoll_wait(epfd_, events_, PINK_MAX_CLIENTS, 500);
  if (retval > 0) {
    numevents = retval;
    for (int i = 0; i < numevents; i++) {
      int mask = 0;
      firedevent_[i].fd_ = (events_ + i)->data.fd;
      /*
       * log_info("events + i events %d", (events_ + i)->events);
       */
      if ((events_ + i)->events & EPOLLIN) {
        mask |= EPOLLIN;
      }
      if ((events_ + i)->events & EPOLLOUT) {
        mask |= EPOLLOUT;
      }
      if ((events_ + i)->events & EPOLLERR) {
        mask |= EPOLLERR;
      }
      if ((events_ + i)->events & EPOLLHUP) {
        mask |= EPOLLHUP;
      }
      firedevent_[i].mask_ = mask;
    }
  }
  return numevents;
}
<|endoftext|>


<commit_before>#include "core/ctree.h"
#include "core/textbox.h"

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

using namespace euphoria::core;

struct T
{
    std::string name;
    std::vector<T> children;

    T(const std::string& n) : name(n) {}
    T(const std::string& n, std::initializer_list<T> t) : name(n), children(t) {}
};

int
main(int, char**)
{
    const auto simple_tree = T("a", { T{"1"}, T{"2"}, T{"3"} });

    const auto root_tree =
        T{"Tolkien characters", {
            T{"Heroes", {
                T{"Humans", {
                    T{"Aragon"},
                    T{"Boromir"}
                }},
                T{"Hobbits", {
                    T{"Frodo"},
                    T{"Samwise"},
                    T{"Merry"},
                    T{"Pippin"},
                }},
                T{"Other", {
                    T{"Legolas"},
                    T{"Gandalf"},
                    T{"Gimli"}
                }}
            }},
            T{"Enemies", {
                T{"Sauron"},
                T{"orcs"},
                T{"Sauruman"}
            }}
        }};

    const auto trees = std::vector<T>{simple_tree, root_tree};

    bool first = true;

    for(auto t: trees)
    {
        if(first) first = false;
        else std::cout << "\n-----------------------------------------\n\n";

        PrintHierarchy(t, [](const T& t) {return t.name; }, [](const T& t) {return t.children; }, [](const std::string& s) {std::cout << s << "\n"; });

        std::cout << "\n-----------------------------------------\n\n";

        {
            auto result = TextBox::Empty();
            result.PutBox(2,0, TextBox::CreateTreeGraph(t, 132-2,
                [](const T& e)
                {
                    return e.name;
                },
                [](const T& e) { return std::make_pair(e.children.cbegin(), e.children.cend()); },
                [](const T& e) { return e.children.size() >= 1; }, // whether simplified horizontal layout can be used
                [](const T&  ) { return true; },                 // whether extremely simplified horiz layout can be used
                [](const T&  ) { return false; }));
            auto strings = result.ToString();
            for(auto s: strings)
            {
                std::cout << s << "\n";
            }
        }
    }

    std::cout << "\n\n";
}
<commit_msg>simple test is simpler<commit_after>#include "core/ctree.h"
#include "core/textbox.h"

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

using namespace euphoria::core;

struct T
{
    std::string name;
    std::vector<T> children;

    T(const std::string& n) : name(n) {}
    T(const std::string& n, std::initializer_list<T> t) : name(n), children(t) {}
};

int
main(int, char**)
{
    const auto simple_tree = T("a", { T{"1"} });

    const auto root_tree =
        T{"Tolkien characters", {
            T{"Heroes", {
                T{"Humans", {
                    T{"Aragon"},
                    T{"Boromir"}
                }},
                T{"Hobbits", {
                    T{"Frodo"},
                    T{"Samwise"},
                    T{"Merry"},
                    T{"Pippin"},
                }},
                T{"Other", {
                    T{"Legolas"},
                    T{"Gandalf"},
                    T{"Gimli"}
                }}
            }},
            T{"Enemies", {
                T{"Sauron"},
                T{"orcs"},
                T{"Sauruman"}
            }}
        }};

    const auto trees = std::vector<T>{simple_tree, root_tree};

    bool first = true;

    for(auto t: trees)
    {
        if(first) first = false;
        else std::cout << "\n-----------------------------------------\n\n";

        PrintHierarchy(t, [](const T& t) {return t.name; }, [](const T& t) {return t.children; }, [](const std::string& s) {std::cout << s << "\n"; });

        std::cout << "\n-----------------------------------------\n\n";

        {
            auto result = TextBox::Empty();
            result.PutBox(2,0, TextBox::CreateTreeGraph(t, 132-2,
                [](const T& e)
                {
                    return e.name;
                },
                [](const T& e) { return std::make_pair(e.children.cbegin(), e.children.cend()); },
                [](const T& e) { return e.children.size() >= 1; }, // whether simplified horizontal layout can be used
                [](const T&  ) { return true; },                 // whether extremely simplified horiz layout can be used
                [](const T&  ) { return false; }));
            auto strings = result.ToString();
            for(auto s: strings)
            {
                std::cout << s << "\n";
            }
        }
    }

    std::cout << "\n\n";
}
<|endoftext|>


<commit_before>#ifndef EVENT_SET_HPP
#define EVENT_SET_HPP

/* This class provides an interface for a specific Event Set
 */

namespace warped {

class EventSet {
public:

    bool insert(const Event* event) = 0;

    bool handleAntiMessage(SimulationObject* reclaimer, const NegativeEvent* cancelEvent);

    const Event* getEvent(SimulationObject*, uint64_t);

    const Event* peekEvent(SimulationObject*, uint64_t);

    void fossilCollect(SimulationObject*, uint64_t);

    void fossilCollect(const Event*);

    void rollback(SimulationObject* object, uint64_t rollbackTime);

};

} // warped namespace

#endif
<commit_msg>Modifications to support different types of LTSF queues by overriding some of the APIs. Also corrected the data type of timestamp.<commit_after>#ifndef EVENT_SET_HPP
#define EVENT_SET_HPP

/* This class provides an interface for a specific Event Set
 */

namespace warped {

class EventSet {
public:

    virtual bool insert(const Event* event) = 0;

    virtual bool handleAntiMessage(SimulationObject* reclaimer, const NegativeEvent* cancelEvent);

    virtual const Event* getEvent(SimulationObject*, unsigned int);

    virtual const Event* peekEvent(SimulationObject*, unsigned int);

    virtual void fossilCollect(SimulationObject*, unsigned int);

    virtual void fossilCollect(const Event*);

    virtual void rollback(SimulationObject* object, unsigned int rollbackTime);

protected:
    EventSet(){};
};

} // warped namespace

#endif
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once
#include <string>
#include <mutex>
#include <map>
#include <memory>
#include <kernel_headers/ireduce_first.hpp>
#include <kernel_headers/ireduce_dim.hpp>
#include <kernel_headers/iops.hpp>
#include <program.hpp>
#include <traits.hpp>
#include <dispatch.hpp>
#include <Param.hpp>
#include <cache.hpp>
#include <debug_opencl.hpp>
#include <type_util.hpp>
#include "names.hpp"
#include "config.hpp"
#include <memory.hpp>

using cl::Buffer;
using cl::Program;
using cl::Kernel;
using cl::make_kernel;
using cl::EnqueueArgs;
using cl::NDRange;
using std::string;
using std::unique_ptr;

namespace opencl
{

namespace kernel
{

    template<typename T, af_op_t op>
    void ireduce_dim_launcher(Param out, cl::Buffer *oidx,
                              Param in, cl::Buffer *iidx,
                              const int dim,
                              const int threads_y,
                              const bool is_first,
                              const uint groups_all[4])
    {
        std::string ref_name =
            std::string("ireduce_") +
            std::to_string(dim) +
            std::string("_") +
            std::string(dtype_traits<T>::getName()) +
            std::string("_") +
            std::to_string(op) +
            std::string("_") +
            std::to_string(is_first) +
            std::string("_") +
            std::to_string(threads_y);

        int device = getActiveDeviceId();
        kc_t::iterator idx = kernelCaches[device].find(ref_name);

        kc_entry_t entry;
        if (idx == kernelCaches[device].end()) {

                Binary<T, op> ireduce;
                ToNum<T> toNum;

                std::ostringstream options;
                options << " -D T=" << dtype_traits<T>::getName()
                        << " -D dim=" << dim
                        << " -D DIMY=" << threads_y
                        << " -D THREADS_X=" << THREADS_X
                        << " -D init=" << toNum(ireduce.init())
                        << " -D " << binOpName<op>()
                        << " -D CPLX=" << af::iscplx<T>()
                        << " -D IS_FIRST=" << is_first;

                if (std::is_same<T, double>::value ||
                    std::is_same<T, cdouble>::value) {
                    options << " -D USE_DOUBLE";
                }

                const char *ker_strs[] = {iops_cl, ireduce_dim_cl};
                const int   ker_lens[] = {iops_cl_len, ireduce_dim_cl_len};
                Program prog;
                buildProgram(prog, 2, ker_strs, ker_lens, options.str());
                entry.prog = new Program(prog);
                entry.ker = new Kernel(*entry.prog, "ireduce_dim_kernel");

                kernelCaches[device][ref_name] = entry;
        } else {
            entry = idx->second;
        }

        NDRange local(THREADS_X, threads_y);
        NDRange global(groups_all[0] * groups_all[2] * local[0],
                       groups_all[1] * groups_all[3] * local[1]);

        auto ireduceOp = make_kernel<Buffer, KParam, Buffer,
                                     Buffer, KParam, Buffer,
                                     uint, uint, uint>(*entry.ker);

        ireduceOp(EnqueueArgs(getQueue(), global, local),
                  *out.data, out.info, *oidx,
                  *in.data, in.info, *iidx,
                  groups_all[0],
                  groups_all[1],
                  groups_all[dim]);

        CL_DEBUG_FINISH(getQueue());
    }

    template<typename T, af_op_t op, int dim>
    void ireduce_dim(Param out, cl::Buffer *oidx, Param in)
    {
        uint threads_y = std::min(THREADS_Y, nextpow2(in.info.dims[dim]));
        uint threads_x = THREADS_X;

        uint groups_all[] = {(uint)divup(in.info.dims[0], threads_x),
                             (uint)in.info.dims[1],
                             (uint)in.info.dims[2],
                             (uint)in.info.dims[3]};

        groups_all[dim] = divup(in.info.dims[dim], threads_y * REPEAT);

        Param tmp = out;
        cl::Buffer *tidx = oidx;

        int tmp_elements = 1;
        if (groups_all[dim] > 1) {
            tmp.info.dims[dim] = groups_all[dim];

            for (int k = 0; k < 4; k++) tmp_elements *= tmp.info.dims[k];

            tmp.data = bufferAlloc(tmp_elements * sizeof(T));
            tidx = bufferAlloc(tmp_elements * sizeof(uint));

            for (int k = dim + 1; k < 4; k++) tmp.info.strides[k] *= groups_all[dim];
        }

        ireduce_dim_launcher<T, op>(tmp, tidx, in, tidx, dim, threads_y, true, groups_all);

        if (groups_all[dim] > 1) {
            groups_all[dim] = 1;

            ireduce_dim_launcher<T, op>(out, oidx, tmp, tidx, dim, threads_y, false, groups_all);
            bufferFree(tmp.data);
            bufferFree(tidx);
        }

    }

    template<typename T, af_op_t op>
    void ireduce_first_launcher(Param out, cl::Buffer *oidx,
                                Param in, cl::Buffer *iidx,
                                const int threads_x,
                                const bool is_first,
                                const uint groups_x,
                                const uint groups_y)
    {
        std::string ref_name =
            std::string("ireduce_0_") +
            std::string(dtype_traits<T>::getName()) +
            std::string("_") +
            std::to_string(op) +
            std::string("_") +
            std::to_string(is_first);
            std::string("_") +
            std::to_string(threads_x);

        int device = getActiveDeviceId();
        kc_t::iterator idx = kernelCaches[device].find(ref_name);

        kc_entry_t entry;
        if (idx == kernelCaches[device].end()) {

            Binary<T, op> ireduce;
            ToNum<T> toNum;

            std::ostringstream options;
            options << " -D T=" << dtype_traits<T>::getName()
                    << " -D DIMX=" << threads_x
                    << " -D THREADS_PER_GROUP=" << THREADS_PER_GROUP
                    << " -D init=" << toNum(ireduce.init())
                    << " -D " << binOpName<op>()
                    << " -D CPLX=" << af::iscplx<T>()
                    << " -D IS_FIRST=" << is_first;

            if (std::is_same<T, double>::value ||
                std::is_same<T, cdouble>::value) {
                options << " -D USE_DOUBLE";
            }

            const char *ker_strs[] = {iops_cl, ireduce_first_cl};
            const int   ker_lens[] = {iops_cl_len, ireduce_first_cl_len};
            Program prog;
            buildProgram(prog, 2, ker_strs, ker_lens, options.str());
            entry.prog = new Program(prog);
            entry.ker = new Kernel(*entry.prog, "ireduce_first_kernel");

            kernelCaches[device][ref_name] = entry;
        } else {
            entry = idx->second;
        }

        NDRange local(threads_x, THREADS_PER_GROUP / threads_x);
        NDRange global(groups_x * in.info.dims[2] * local[0],
                       groups_y * in.info.dims[3] * local[1]);

        uint repeat = divup(in.info.dims[0], (local[0] * groups_x));

        auto ireduceOp = make_kernel<Buffer, KParam, Buffer,
                                     Buffer, KParam, Buffer,
                                     uint, uint, uint>(*entry.ker);

        ireduceOp(EnqueueArgs(getQueue(), global, local),
                  *out.data, out.info, *oidx,
                  *in.data, in.info, *iidx,
                  groups_x, groups_y, repeat);

        CL_DEBUG_FINISH(getQueue());
    }

    template<typename T, af_op_t op>
    void ireduce_first(Param out, cl::Buffer *oidx, Param in)
    {
        uint threads_x = nextpow2(std::max(32u, (uint)in.info.dims[0]));
        threads_x = std::min(threads_x, THREADS_PER_GROUP);
        uint threads_y = THREADS_PER_GROUP / threads_x;

        uint groups_x = divup(in.info.dims[0], threads_x * REPEAT);
        uint groups_y = divup(in.info.dims[1], threads_y);

        Param tmp = out;
        cl::Buffer *tidx = oidx;

        if (groups_x > 1) {

            tmp.data = bufferAlloc(groups_x *
                                in.info.dims[1] *
                                in.info.dims[2] *
                                in.info.dims[3] *
                                sizeof(T));

            tidx = bufferAlloc(groups_x *
                               in.info.dims[1] *
                               in.info.dims[2] *
                               in.info.dims[3] *
                               sizeof(uint));

            tmp.info.dims[0] = groups_x;
            for (int k = 1; k < 4; k++) tmp.info.strides[k] *= groups_x;
        }

        ireduce_first_launcher<T, op>(tmp, tidx, in, tidx, threads_x, true, groups_x, groups_y);

        if (groups_x > 1) {
            ireduce_first_launcher<T, op>(out, oidx, tmp, tidx, threads_x, false, 1, groups_y);

            bufferFree(tmp.data);
            bufferFree(tidx);
        }
    }

    template<typename T, af_op_t op>
    void ireduce(Param out, cl::Buffer *oidx, Param in, int dim)
    {
        try {
            switch (dim) {
            case 0: return ireduce_first<T, op   >(out, oidx, in);
            case 1: return ireduce_dim  <T, op, 1>(out, oidx, in);
            case 2: return ireduce_dim  <T, op, 2>(out, oidx, in);
            case 3: return ireduce_dim  <T, op, 3>(out, oidx, in);
            }
        } catch(cl::Error ex) {
            CL_TO_AF_ERROR(ex);
        }
    }

    template<typename T> double cabs(const T in) { return (double)in; }
    static double cabs(const cfloat in) { return (double)abs(in); }
    static double cabs(const cdouble in) { return (double)abs(in); }

    template<af_op_t op, typename T>
    struct MinMaxOp
    {
        T m_val;
        uint m_idx;
        MinMaxOp(T val, uint idx) :
            m_val(val), m_idx(idx)
        {
        }

        void operator()(T val, uint idx)
        {
            if (cabs(val) < cabs(m_val) ||
                (cabs(val) == cabs(m_val) &&
                 idx > m_idx)) {
                m_val = val;
                m_idx = idx;
            }
        }
    };

    template<typename T>
    struct MinMaxOp<af_max_t, T>
    {
        T m_val;
        uint m_idx;
        MinMaxOp(T val, uint idx) :
            m_val(val), m_idx(idx)
        {
        }

        void operator()(T val, uint idx)
        {
            if (cabs(val) > cabs(m_val) ||
                (cabs(val) == cabs(m_val) &&
                 idx <= m_idx)) {
                m_val = val;
                m_idx = idx;
            }
        }
    };

    template<typename T, af_op_t op>
    T ireduce_all(uint *loc, Param in)
    {
        try {
            int in_elements = in.info.dims[3] * in.info.strides[3];

            // FIXME: Use better heuristics to get to the optimum number
            if (in_elements > 4096) {

                bool is_linear = (in.info.strides[0] == 1);
                for (int k = 1; k < 4; k++) {
                    is_linear &= (in.info.strides[k] == (in.info.strides[k - 1] * in.info.dims[k - 1]));
                }

                if (is_linear) {
                    in.info.dims[0] = in_elements;
                    for (int k = 1; k < 4; k++) {
                        in.info.dims[k] = 1;
                        in.info.strides[k] = in_elements;
                    }
                }

                uint threads_x = nextpow2(std::max(32u, (uint)in.info.dims[0]));
                threads_x = std::min(threads_x, THREADS_PER_GROUP);
                uint threads_y = THREADS_PER_GROUP / threads_x;

                Param tmp;
                uint groups_x = divup(in.info.dims[0], threads_x * REPEAT);
                uint groups_y = divup(in.info.dims[1], threads_y);

                tmp.info.offset = 0;
                tmp.info.dims[0] = groups_x;
                tmp.info.strides[0] = 1;

                for (int k = 1; k < 4; k++) {
                    tmp.info.dims[k] = in.info.dims[k];
                    tmp.info.strides[k] = tmp.info.dims[k - 1] * tmp.info.strides[k - 1];
                }

                int tmp_elements = tmp.info.strides[3] * tmp.info.dims[3];
                tmp.data = bufferAlloc(tmp_elements * sizeof(T));
                cl::Buffer *tidx = bufferAlloc(tmp_elements * sizeof(uint));

                ireduce_first_launcher<T, op>(tmp, tidx, in, tidx, threads_x, true, groups_x, groups_y);

                unique_ptr<T> h_ptr(new T[tmp_elements]);
                unique_ptr<uint> h_iptr(new uint[tmp_elements]);

                getQueue().enqueueReadBuffer(*tmp.data, CL_TRUE, 0, sizeof(T) * tmp_elements, h_ptr.get());
                getQueue().enqueueReadBuffer(*tidx, CL_TRUE, 0, sizeof(uint) * tmp_elements, h_iptr.get());

                T* h_ptr_raw = h_ptr.get();
                uint* h_iptr_raw = h_iptr.get();
                MinMaxOp<op, T> Op(h_ptr_raw[0], h_iptr_raw[0]);

                for (int i = 1; i < (int)tmp_elements; i++) {
                    Op(h_ptr_raw[i], h_iptr_raw[i]);
                }

                bufferFree(tmp.data);
                bufferFree(tidx);

                *loc = Op.m_idx;
                return Op.m_val;

            } else {

                unique_ptr<T> h_ptr(new T[in_elements]);
                T* h_ptr_raw = h_ptr.get();
                getQueue().enqueueReadBuffer(*in.data, CL_TRUE, 0, sizeof(T) * in_elements, h_ptr_raw);

                MinMaxOp<op, T> Op(h_ptr_raw[0], 0);
                for (int i = 1; i < (int)in_elements; i++) {
                    Op(h_ptr_raw[i], i);
                }

                *loc = Op.m_idx;
                return Op.m_val;
            }
        } catch(cl::Error ex) {
            CL_TO_AF_ERROR(ex);
        }
    }

}

}
<commit_msg>Removing unnecessary switch case from opencl ireduce<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once
#include <string>
#include <mutex>
#include <map>
#include <memory>
#include <kernel_headers/ireduce_first.hpp>
#include <kernel_headers/ireduce_dim.hpp>
#include <kernel_headers/iops.hpp>
#include <program.hpp>
#include <traits.hpp>
#include <dispatch.hpp>
#include <Param.hpp>
#include <cache.hpp>
#include <debug_opencl.hpp>
#include <type_util.hpp>
#include "names.hpp"
#include "config.hpp"
#include <memory.hpp>

using cl::Buffer;
using cl::Program;
using cl::Kernel;
using cl::make_kernel;
using cl::EnqueueArgs;
using cl::NDRange;
using std::string;
using std::unique_ptr;

namespace opencl
{

namespace kernel
{

    template<typename T, af_op_t op>
    void ireduce_dim_launcher(Param out, cl::Buffer *oidx,
                              Param in, cl::Buffer *iidx,
                              const int dim,
                              const int threads_y,
                              const bool is_first,
                              const uint groups_all[4])
    {
        std::string ref_name =
            std::string("ireduce_") +
            std::to_string(dim) +
            std::string("_") +
            std::string(dtype_traits<T>::getName()) +
            std::string("_") +
            std::to_string(op) +
            std::string("_") +
            std::to_string(is_first) +
            std::string("_") +
            std::to_string(threads_y);

        int device = getActiveDeviceId();
        kc_t::iterator idx = kernelCaches[device].find(ref_name);

        kc_entry_t entry;
        if (idx == kernelCaches[device].end()) {

                Binary<T, op> ireduce;
                ToNum<T> toNum;

                std::ostringstream options;
                options << " -D T=" << dtype_traits<T>::getName()
                        << " -D dim=" << dim
                        << " -D DIMY=" << threads_y
                        << " -D THREADS_X=" << THREADS_X
                        << " -D init=" << toNum(ireduce.init())
                        << " -D " << binOpName<op>()
                        << " -D CPLX=" << af::iscplx<T>()
                        << " -D IS_FIRST=" << is_first;

                if (std::is_same<T, double>::value ||
                    std::is_same<T, cdouble>::value) {
                    options << " -D USE_DOUBLE";
                }

                const char *ker_strs[] = {iops_cl, ireduce_dim_cl};
                const int   ker_lens[] = {iops_cl_len, ireduce_dim_cl_len};
                Program prog;
                buildProgram(prog, 2, ker_strs, ker_lens, options.str());
                entry.prog = new Program(prog);
                entry.ker = new Kernel(*entry.prog, "ireduce_dim_kernel");

                kernelCaches[device][ref_name] = entry;
        } else {
            entry = idx->second;
        }

        NDRange local(THREADS_X, threads_y);
        NDRange global(groups_all[0] * groups_all[2] * local[0],
                       groups_all[1] * groups_all[3] * local[1]);

        auto ireduceOp = make_kernel<Buffer, KParam, Buffer,
                                     Buffer, KParam, Buffer,
                                     uint, uint, uint>(*entry.ker);

        ireduceOp(EnqueueArgs(getQueue(), global, local),
                  *out.data, out.info, *oidx,
                  *in.data, in.info, *iidx,
                  groups_all[0],
                  groups_all[1],
                  groups_all[dim]);

        CL_DEBUG_FINISH(getQueue());
    }

    template<typename T, af_op_t op>
    void ireduce_dim(Param out, cl::Buffer *oidx, Param in, int dim)
    {
        uint threads_y = std::min(THREADS_Y, nextpow2(in.info.dims[dim]));
        uint threads_x = THREADS_X;

        uint groups_all[] = {(uint)divup(in.info.dims[0], threads_x),
                             (uint)in.info.dims[1],
                             (uint)in.info.dims[2],
                             (uint)in.info.dims[3]};

        groups_all[dim] = divup(in.info.dims[dim], threads_y * REPEAT);

        Param tmp = out;
        cl::Buffer *tidx = oidx;

        int tmp_elements = 1;
        if (groups_all[dim] > 1) {
            tmp.info.dims[dim] = groups_all[dim];

            for (int k = 0; k < 4; k++) tmp_elements *= tmp.info.dims[k];

            tmp.data = bufferAlloc(tmp_elements * sizeof(T));
            tidx = bufferAlloc(tmp_elements * sizeof(uint));

            for (int k = dim + 1; k < 4; k++) tmp.info.strides[k] *= groups_all[dim];
        }

        ireduce_dim_launcher<T, op>(tmp, tidx, in, tidx, dim, threads_y, true, groups_all);

        if (groups_all[dim] > 1) {
            groups_all[dim] = 1;

            ireduce_dim_launcher<T, op>(out, oidx, tmp, tidx, dim, threads_y, false, groups_all);
            bufferFree(tmp.data);
            bufferFree(tidx);
        }

    }

    template<typename T, af_op_t op>
    void ireduce_first_launcher(Param out, cl::Buffer *oidx,
                                Param in, cl::Buffer *iidx,
                                const int threads_x,
                                const bool is_first,
                                const uint groups_x,
                                const uint groups_y)
    {
        std::string ref_name =
            std::string("ireduce_0_") +
            std::string(dtype_traits<T>::getName()) +
            std::string("_") +
            std::to_string(op) +
            std::string("_") +
            std::to_string(is_first);
            std::string("_") +
            std::to_string(threads_x);

        int device = getActiveDeviceId();
        kc_t::iterator idx = kernelCaches[device].find(ref_name);

        kc_entry_t entry;
        if (idx == kernelCaches[device].end()) {

            Binary<T, op> ireduce;
            ToNum<T> toNum;

            std::ostringstream options;
            options << " -D T=" << dtype_traits<T>::getName()
                    << " -D DIMX=" << threads_x
                    << " -D THREADS_PER_GROUP=" << THREADS_PER_GROUP
                    << " -D init=" << toNum(ireduce.init())
                    << " -D " << binOpName<op>()
                    << " -D CPLX=" << af::iscplx<T>()
                    << " -D IS_FIRST=" << is_first;

            if (std::is_same<T, double>::value ||
                std::is_same<T, cdouble>::value) {
                options << " -D USE_DOUBLE";
            }

            const char *ker_strs[] = {iops_cl, ireduce_first_cl};
            const int   ker_lens[] = {iops_cl_len, ireduce_first_cl_len};
            Program prog;
            buildProgram(prog, 2, ker_strs, ker_lens, options.str());
            entry.prog = new Program(prog);
            entry.ker = new Kernel(*entry.prog, "ireduce_first_kernel");

            kernelCaches[device][ref_name] = entry;
        } else {
            entry = idx->second;
        }

        NDRange local(threads_x, THREADS_PER_GROUP / threads_x);
        NDRange global(groups_x * in.info.dims[2] * local[0],
                       groups_y * in.info.dims[3] * local[1]);

        uint repeat = divup(in.info.dims[0], (local[0] * groups_x));

        auto ireduceOp = make_kernel<Buffer, KParam, Buffer,
                                     Buffer, KParam, Buffer,
                                     uint, uint, uint>(*entry.ker);

        ireduceOp(EnqueueArgs(getQueue(), global, local),
                  *out.data, out.info, *oidx,
                  *in.data, in.info, *iidx,
                  groups_x, groups_y, repeat);

        CL_DEBUG_FINISH(getQueue());
    }

    template<typename T, af_op_t op>
    void ireduce_first(Param out, cl::Buffer *oidx, Param in)
    {
        uint threads_x = nextpow2(std::max(32u, (uint)in.info.dims[0]));
        threads_x = std::min(threads_x, THREADS_PER_GROUP);
        uint threads_y = THREADS_PER_GROUP / threads_x;

        uint groups_x = divup(in.info.dims[0], threads_x * REPEAT);
        uint groups_y = divup(in.info.dims[1], threads_y);

        Param tmp = out;
        cl::Buffer *tidx = oidx;

        if (groups_x > 1) {

            tmp.data = bufferAlloc(groups_x *
                                in.info.dims[1] *
                                in.info.dims[2] *
                                in.info.dims[3] *
                                sizeof(T));

            tidx = bufferAlloc(groups_x *
                               in.info.dims[1] *
                               in.info.dims[2] *
                               in.info.dims[3] *
                               sizeof(uint));

            tmp.info.dims[0] = groups_x;
            for (int k = 1; k < 4; k++) tmp.info.strides[k] *= groups_x;
        }

        ireduce_first_launcher<T, op>(tmp, tidx, in, tidx, threads_x, true, groups_x, groups_y);

        if (groups_x > 1) {
            ireduce_first_launcher<T, op>(out, oidx, tmp, tidx, threads_x, false, 1, groups_y);

            bufferFree(tmp.data);
            bufferFree(tidx);
        }
    }

    template<typename T, af_op_t op>
    void ireduce(Param out, cl::Buffer *oidx, Param in, int dim)
    {
        try {
            if (dim == 0)
                return ireduce_first<T, op>(out, oidx, in);
            else
                return ireduce_dim  <T, op>(out, oidx, in, dim);
        } catch(cl::Error ex) {
            CL_TO_AF_ERROR(ex);
        }
    }

    template<typename T> double cabs(const T in) { return (double)in; }
    static double cabs(const cfloat in) { return (double)abs(in); }
    static double cabs(const cdouble in) { return (double)abs(in); }

    template<af_op_t op, typename T>
    struct MinMaxOp
    {
        T m_val;
        uint m_idx;
        MinMaxOp(T val, uint idx) :
            m_val(val), m_idx(idx)
        {
        }

        void operator()(T val, uint idx)
        {
            if (cabs(val) < cabs(m_val) ||
                (cabs(val) == cabs(m_val) &&
                 idx > m_idx)) {
                m_val = val;
                m_idx = idx;
            }
        }
    };

    template<typename T>
    struct MinMaxOp<af_max_t, T>
    {
        T m_val;
        uint m_idx;
        MinMaxOp(T val, uint idx) :
            m_val(val), m_idx(idx)
        {
        }

        void operator()(T val, uint idx)
        {
            if (cabs(val) > cabs(m_val) ||
                (cabs(val) == cabs(m_val) &&
                 idx <= m_idx)) {
                m_val = val;
                m_idx = idx;
            }
        }
    };

    template<typename T, af_op_t op>
    T ireduce_all(uint *loc, Param in)
    {
        try {
            int in_elements = in.info.dims[3] * in.info.strides[3];

            // FIXME: Use better heuristics to get to the optimum number
            if (in_elements > 4096) {

                bool is_linear = (in.info.strides[0] == 1);
                for (int k = 1; k < 4; k++) {
                    is_linear &= (in.info.strides[k] == (in.info.strides[k - 1] * in.info.dims[k - 1]));
                }

                if (is_linear) {
                    in.info.dims[0] = in_elements;
                    for (int k = 1; k < 4; k++) {
                        in.info.dims[k] = 1;
                        in.info.strides[k] = in_elements;
                    }
                }

                uint threads_x = nextpow2(std::max(32u, (uint)in.info.dims[0]));
                threads_x = std::min(threads_x, THREADS_PER_GROUP);
                uint threads_y = THREADS_PER_GROUP / threads_x;

                Param tmp;
                uint groups_x = divup(in.info.dims[0], threads_x * REPEAT);
                uint groups_y = divup(in.info.dims[1], threads_y);

                tmp.info.offset = 0;
                tmp.info.dims[0] = groups_x;
                tmp.info.strides[0] = 1;

                for (int k = 1; k < 4; k++) {
                    tmp.info.dims[k] = in.info.dims[k];
                    tmp.info.strides[k] = tmp.info.dims[k - 1] * tmp.info.strides[k - 1];
                }

                int tmp_elements = tmp.info.strides[3] * tmp.info.dims[3];
                tmp.data = bufferAlloc(tmp_elements * sizeof(T));
                cl::Buffer *tidx = bufferAlloc(tmp_elements * sizeof(uint));

                ireduce_first_launcher<T, op>(tmp, tidx, in, tidx, threads_x, true, groups_x, groups_y);

                unique_ptr<T> h_ptr(new T[tmp_elements]);
                unique_ptr<uint> h_iptr(new uint[tmp_elements]);

                getQueue().enqueueReadBuffer(*tmp.data, CL_TRUE, 0, sizeof(T) * tmp_elements, h_ptr.get());
                getQueue().enqueueReadBuffer(*tidx, CL_TRUE, 0, sizeof(uint) * tmp_elements, h_iptr.get());

                T* h_ptr_raw = h_ptr.get();
                uint* h_iptr_raw = h_iptr.get();
                MinMaxOp<op, T> Op(h_ptr_raw[0], h_iptr_raw[0]);

                for (int i = 1; i < (int)tmp_elements; i++) {
                    Op(h_ptr_raw[i], h_iptr_raw[i]);
                }

                bufferFree(tmp.data);
                bufferFree(tidx);

                *loc = Op.m_idx;
                return Op.m_val;

            } else {

                unique_ptr<T> h_ptr(new T[in_elements]);
                T* h_ptr_raw = h_ptr.get();
                getQueue().enqueueReadBuffer(*in.data, CL_TRUE, 0, sizeof(T) * in_elements, h_ptr_raw);

                MinMaxOp<op, T> Op(h_ptr_raw[0], 0);
                for (int i = 1; i < (int)in_elements; i++) {
                    Op(h_ptr_raw[i], i);
                }

                *loc = Op.m_idx;
                return Op.m_val;
            }
        } catch(cl::Error ex) {
            CL_TO_AF_ERROR(ex);
        }
    }

}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>

#include "function.hxx"
#include "variable.hxx"
#include "coreutils.hxx"

double sum(std::vector<double> & args)
{
  double res(0.);
  for (unsigned i = 0; i < args.size(); ++i) {
    res += double(args[i]);
  }
  return res;
}

int main()
{
  double array[3] = {1, 2, 3};

  function &myfunc = make_function(sum, 3, array);

  std::cout << "automatic conversion: myfunc: " << myfunc << std::endl;

  auto& vars = myfunc.components();
  vars[1] = fnbase_ptr(new variable(3));
  vars[2] = fnbase_ptr(new variable(5));
  std::cout << "parameter change (direct): myfunc: " << myfunc << std::endl;

  try {
    myfunc.replace(0, fnbase_ptr(new variable(2)));
    myfunc.replace(1, fnbase_ptr(new variable(4)));
    myfunc.replace(2, fnbase_ptr(new variable(6)));
    std::cout << "parameter change (setter): myfunc: " << myfunc << std::endl;
    myfunc.replace(3, fnbase_ptr(new variable(2)));
  } catch (std::out_of_range &exc) {
    std::cout << "exception handling: "<< exc.what() << std::endl;
  }

  return 0;
}
<commit_msg>Function test re-formatting<commit_after>#include <iostream>
#include <stdexcept>

#include "function.hxx"
#include "variable.hxx"
#include "coreutils.hxx"

double sum(std::vector<double> & args)
{
  double res(0.);
  for (unsigned i = 0; i < args.size(); ++i) {
    res += double(args[i]);
  }
  return res;
}

int main()
{
  double array[3] = {1, 2, 3};

  function &myfunc = make_function(sum, 3, array);

  std::cout << "automatic conversion: myfunc: 1+2+3 = " << myfunc << std::endl;

  auto& vars = myfunc.components();
  vars[1] = fnbase_ptr(new variable(3));
  vars[2] = fnbase_ptr(new variable(5));
  std::cout << "parameter change (direct): myfunc: 1+3+5 = " << myfunc << std::endl;

  try {
    for (unsigned i = 0; i < 3; ++i) {
      myfunc.replace(i, fnbase_ptr(new variable((i+1) * 2)));
    }
    std::cout << "parameter change (setter): myfunc: 2+4+6 = " << myfunc << std::endl;
    myfunc.replace(3, fnbase_ptr(new variable(2)));
  } catch (std::out_of_range &exc) {
    std::cout << "exception handling: "<< exc.what() << std::endl;
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Stop running tests if more than 5 time out.<commit_after><|endoftext|>