<commit_before>#include "RapidHistWriter.h"

#include "RapidParam.h"
#include "RapidParticle.h"

RapidHistWriter::~RapidHistWriter() {
	if(tree_) {
		tree_->AutoSave();
		treeFile_->Close();
	}
	while(!histos_.empty()) {
		delete histos_[histos_.size()-1];
		histos_.pop_back();
	}
}

void RapidHistWriter::setup(bool saveTree) {
	//get the subset of particles that have more than one mass hypothesis
	std::vector<RapidParticle*>::const_iterator it = parts_.begin();
	for( ; it!=parts_.end(); ++it) {
		RapidParticle* part = *it;
		if(part->nMassHypotheses()>1) {
			altHypothesisParts_.push_back(part);
		}
	}

	setupHistos();
	if(saveTree) setupTree(); //called after setupHistos so we know the number of parameters
}

void RapidHistWriter::fill() {
	unsigned int offset(0);

	//first fill for the default hypothesis
	offset = fillSingleHypothesis(offset);

	RapidParticle *part1(0), *part2(0);

	//now loop over all single mis-IDs
	std::vector<RapidParticle*>::const_iterator it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
			part1->setMassHypothesis(i);
			offset = fillSingleHypothesis(offset);
		}
		part1->setMassHypothesis(0);
	}

	//now loop over all double mis-IDs
	it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		std::vector<RapidParticle*>::const_iterator it2 = it1+1;
		for( ; it2!=altHypothesisParts_.end(); ++it2) {
			part2 = *it2;
			for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
				part1->setMassHypothesis(i);
				for(unsigned int j=1; j<part2->nMassHypotheses(); ++j) {
					part2->setMassHypothesis(j);
					offset = fillSingleHypothesis(offset);
				}
				part2->setMassHypothesis(0);
			}
			part1->setMassHypothesis(0);
		}
	}
}

void RapidHistWriter::save() {
	std::cout << "INFO in RapidHistWriter::save : saving histograms to file: " << name_ << "_hists.root" << std::endl;
	TFile* histFile = new TFile(name_+"_hists.root", "RECREATE");

	for(unsigned int i=0; i<histos_.size(); ++i) {
		histos_[i]->Write();
	}
	histFile->Close();

	if(tree_) {
		tree_->AutoSave();
	}
}

void RapidHistWriter::setupHistos() {
	//first setup histograms for default mass hypothesis
	setupSingleHypothesis();

	RapidParticle *part1(0), *part2(0);

	//now loop over all single mis-IDs
	std::vector<RapidParticle*>::const_iterator it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
			part1->setMassHypothesis(i);
			TString suffix("_"); suffix+=part1->name() + "2" + part1->massHypothesisName();
			setupSingleHypothesis(suffix);
		}
		part1->setMassHypothesis(0);
	}

	//now loop over all double mis-IDs
	it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		std::vector<RapidParticle*>::const_iterator it2 = it1+1;
		for( ; it2!=altHypothesisParts_.end(); ++it2) {
			part2 = *it2;
			for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
				part1->setMassHypothesis(i);
				for(unsigned int j=1; j<part2->nMassHypotheses(); ++j) {
					part2->setMassHypothesis(j);
					TString suffix("_"); suffix+=part1->name() + "2" + part1->massHypothesisName();
					suffix+="_"; suffix+=part2->name() + "2" + part2->massHypothesisName();
					setupSingleHypothesis(suffix);
				}
				part2->setMassHypothesis(0);
			}
			part1->setMassHypothesis(0);
		}
	}

	vars_ = std::vector<double>(histos_.size(), 0);
}

void RapidHistWriter::setupSingleHypothesis(TString suffix) {
	std::vector<RapidParam*>::iterator itParam;

	TString baseName;
	TString histName;
	TString axisTitle;
	TH1F* hist(0);

	double min(0), max(0);

	for(unsigned int i=0; i<parts_.size(); ++i) {
		RapidParticle* part = parts_[i];
		baseName = part->name();

		if(part->nDaughters()==0) {
			for(itParam=paramsStable_.begin(); itParam!=paramsStable_.end(); ++itParam) {
				RapidParam* param = *itParam;
				histName  = baseName+"_"+param->name();
				histName += suffix;
				axisTitle = param->name() + "(" + baseName + ")";
				param->getMinMax(part,min,max);
				hist = new TH1F(histName, "", 100, min, max);
				hist->GetXaxis()->SetTitle(axisTitle);
				histos_.push_back(hist);
			}
		} else {
			for(itParam=paramsDecaying_.begin(); itParam!=paramsDecaying_.end(); ++itParam) {
				RapidParam* param = *itParam;
				histName  = baseName+"_"+param->name();
				histName += suffix;
				axisTitle = param->name() + "(" + baseName + ")";
				param->getMinMax(part,min,max);
				hist = new TH1F(histName, "", 100, min, max);
				hist->GetXaxis()->SetTitle(axisTitle);
				histos_.push_back(hist);
			}

			//2-body IMs
			if(part->nDaughters() > 2) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						for(itParam=paramsTwoBody_.begin(); itParam!=paramsTwoBody_.end(); ++itParam) {
							RapidParam* param = *itParam;
							histName  = jDaug->name()+"_";
							histName += kDaug->name()+"_";
							histName += param->name();
							histName += suffix;
							axisTitle = param->name() + "(" + jDaug->name() + "_" + kDaug->name() + ")";
							param->getMinMax(jDaug,kDaug,min,max);
							hist = new TH1F(histName, "", 100, min, max);
							hist->GetXaxis()->SetTitle(axisTitle);
							histos_.push_back(hist);
						}
					}
				}
			}

			//3-body IMs
			if(part->nDaughters() > 3) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						for(RapidParticle* lDaug=kDaug->next(); lDaug!=0; lDaug=lDaug->next()) {
							for(itParam=paramsThreeBody_.begin(); itParam!=paramsThreeBody_.end(); ++itParam) {
								RapidParam* param = *itParam;
								histName  = jDaug->name()+"_";
								histName += kDaug->name()+"_";
								histName += lDaug->name()+"_";
								histName += param->name();
								histName += suffix;
								axisTitle = param->name() + "(" + jDaug->name() + "_" + kDaug->name() + "_" + lDaug->name() + ")";
								param->getMinMax(jDaug,kDaug,lDaug,min,max);
								hist = new TH1F(histName, "", 100, min, max);
								hist->GetXaxis()->SetTitle(axisTitle);
								histos_.push_back(hist);
							}
						}

					}
				}
			}
		}
	}

	for( itParam=params_.begin(); itParam!= params_.end(); ++itParam) {
		RapidParam* param = (*itParam);
		param->getMinMax(min,max,true);
		TH1F* hist = new TH1F(param->name()+suffix, "", 100, min, max);
		histos_.push_back(hist);
	}
}

void RapidHistWriter::setupTree() {
	std::cout << "INFO in RapidHistWriter::setupTree : tree will be saved to file: " << name_ << "_tree.root" << std::endl;
	std::cout << "                                     This will slow down generation." << std::endl;

	treeFile_ = new TFile(name_+"_tree.root", "RECREATE");
	tree_ = new TTree("DecayTree","DecayTree");
	tree_->SetDirectory(treeFile_);

	for(unsigned int i=0; i<histos_.size(); ++i) {
		tree_->Branch(histos_[i]->GetName(), &vars_[i]);
	}

}

unsigned int RapidHistWriter::fillSingleHypothesis(unsigned int offset) {

	std::vector<RapidParam*>::iterator itParam;
	TLorentzVector pSumTruth;
	TLorentzVector pSum;

	for(unsigned int i=0; i<parts_.size(); ++i) {
		RapidParticle* part = parts_[i];

		if(part->nDaughters() < 2) {
			for(itParam=paramsStable_.begin(); itParam!=paramsStable_.end(); ++itParam) {
				RapidParam* param = *itParam;
				if(param->truth()) {
					vars_[offset] = param->eval(part->getP());
				} else {
					vars_[offset] = param->eval(part->getPSmeared());
				}

				histos_[offset]->Fill(vars_[offset]);
				++offset;
			}
		} else {
			for(itParam=paramsDecaying_.begin(); itParam!=paramsDecaying_.end(); ++itParam) {
				RapidParam* param = *itParam;
				if(param->truth()) {
					vars_[offset] = param->eval(part->getP());
				} else {
					vars_[offset] = param->eval(part->getPSmeared());
				}
				histos_[offset]->Fill(vars_[offset]);
				++offset;
			}

			//2-body IMs
			if(part->nDaughters() > 2) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						pSumTruth = jDaug->getP() + kDaug->getP();
						pSum = jDaug->getPSmeared() + kDaug->getPSmeared();

						for(itParam=paramsTwoBody_.begin(); itParam!=paramsTwoBody_.end(); ++itParam) {
							RapidParam* param = *itParam;
							if(param->truth()) {
								vars_[offset] = param->eval(pSumTruth);
							} else {
								vars_[offset] = param->eval(pSum);
							}
							histos_[offset]->Fill(vars_[offset]);
							++offset;
						}
					}
				}
			}

			//3-body IMs
			if(part->nDaughters() > 3) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						for(RapidParticle* lDaug=kDaug->next(); lDaug!=0; lDaug=lDaug->next()) {
							pSumTruth = jDaug->getP() + kDaug->getP() + lDaug->getP();
							pSum = jDaug->getPSmeared() + kDaug->getPSmeared() + lDaug->getPSmeared();

							for(itParam=paramsThreeBody_.begin(); itParam!=paramsThreeBody_.end(); ++itParam) {
								RapidParam* param = *itParam;
								if(param->truth()) {
									vars_[offset] = param->eval(pSumTruth);
								} else {
									vars_[offset] = param->eval(pSum);
								}
								histos_[offset]->Fill(vars_[offset]);
								++offset;
							}
						}
					}
				}
			}
		}
	}

	std::vector<RapidParam*>::iterator it = params_.begin();
	for( ; it!= params_.end(); ++it) {
		vars_[offset] = (*it)->eval();
		histos_[offset]->Fill(vars_[offset]);
		++offset;
	}

	if(tree_) tree_->Fill();

	return offset;
}
<commit_msg>fixed bug in RapidHistWriter that lead to duplication of events in the TTree when using multiple mass hypotheses<commit_after>#include "RapidHistWriter.h"

#include "RapidParam.h"
#include "RapidParticle.h"

RapidHistWriter::~RapidHistWriter() {
	if(tree_) {
		tree_->AutoSave();
		treeFile_->Close();
	}
	while(!histos_.empty()) {
		delete histos_[histos_.size()-1];
		histos_.pop_back();
	}
}

void RapidHistWriter::setup(bool saveTree) {
	//get the subset of particles that have more than one mass hypothesis
	std::vector<RapidParticle*>::const_iterator it = parts_.begin();
	for( ; it!=parts_.end(); ++it) {
		RapidParticle* part = *it;
		if(part->nMassHypotheses()>1) {
			altHypothesisParts_.push_back(part);
		}
	}

	setupHistos();
	if(saveTree) setupTree(); //called after setupHistos so we know the number of parameters
}

void RapidHistWriter::fill() {
	unsigned int offset(0);

	//first fill for the default hypothesis
	offset = fillSingleHypothesis(offset);

	RapidParticle *part1(0), *part2(0);

	//now loop over all single mis-IDs
	std::vector<RapidParticle*>::const_iterator it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
			part1->setMassHypothesis(i);
			offset = fillSingleHypothesis(offset);
		}
		part1->setMassHypothesis(0);
	}

	//now loop over all double mis-IDs
	it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		std::vector<RapidParticle*>::const_iterator it2 = it1+1;
		for( ; it2!=altHypothesisParts_.end(); ++it2) {
			part2 = *it2;
			for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
				part1->setMassHypothesis(i);
				for(unsigned int j=1; j<part2->nMassHypotheses(); ++j) {
					part2->setMassHypothesis(j);
					offset = fillSingleHypothesis(offset);
				}
				part2->setMassHypothesis(0);
			}
			part1->setMassHypothesis(0);
		}
	}
	if(tree_) tree_->Fill();
}

void RapidHistWriter::save() {
	std::cout << "INFO in RapidHistWriter::save : saving histograms to file: " << name_ << "_hists.root" << std::endl;
	TFile* histFile = new TFile(name_+"_hists.root", "RECREATE");

	for(unsigned int i=0; i<histos_.size(); ++i) {
		histos_[i]->Write();
	}
	histFile->Close();

	if(tree_) {
		tree_->AutoSave();
	}
}

void RapidHistWriter::setupHistos() {
	//first setup histograms for default mass hypothesis
	setupSingleHypothesis();

	RapidParticle *part1(0), *part2(0);

	//now loop over all single mis-IDs
	std::vector<RapidParticle*>::const_iterator it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
			part1->setMassHypothesis(i);
			TString suffix("_"); suffix+=part1->name() + "2" + part1->massHypothesisName();
			setupSingleHypothesis(suffix);
		}
		part1->setMassHypothesis(0);
	}

	//now loop over all double mis-IDs
	it1 = altHypothesisParts_.begin();
	for( ; it1!=altHypothesisParts_.end(); ++it1) {
		part1 = *it1;
		std::vector<RapidParticle*>::const_iterator it2 = it1+1;
		for( ; it2!=altHypothesisParts_.end(); ++it2) {
			part2 = *it2;
			for(unsigned int i=1; i<part1->nMassHypotheses(); ++i) {
				part1->setMassHypothesis(i);
				for(unsigned int j=1; j<part2->nMassHypotheses(); ++j) {
					part2->setMassHypothesis(j);
					TString suffix("_"); suffix+=part1->name() + "2" + part1->massHypothesisName();
					suffix+="_"; suffix+=part2->name() + "2" + part2->massHypothesisName();
					setupSingleHypothesis(suffix);
				}
				part2->setMassHypothesis(0);
			}
			part1->setMassHypothesis(0);
		}
	}

	vars_ = std::vector<double>(histos_.size(), 0);
}

void RapidHistWriter::setupSingleHypothesis(TString suffix) {
	std::vector<RapidParam*>::iterator itParam;

	TString baseName;
	TString histName;
	TString axisTitle;
	TH1F* hist(0);

	double min(0), max(0);

	for(unsigned int i=0; i<parts_.size(); ++i) {
		RapidParticle* part = parts_[i];
		baseName = part->name();

		if(part->nDaughters()==0) {
			for(itParam=paramsStable_.begin(); itParam!=paramsStable_.end(); ++itParam) {
				RapidParam* param = *itParam;
				histName  = baseName+"_"+param->name();
				histName += suffix;
				axisTitle = param->name() + "(" + baseName + ")";
				param->getMinMax(part,min,max);
				hist = new TH1F(histName, "", 100, min, max);
				hist->GetXaxis()->SetTitle(axisTitle);
				histos_.push_back(hist);
			}
		} else {
			for(itParam=paramsDecaying_.begin(); itParam!=paramsDecaying_.end(); ++itParam) {
				RapidParam* param = *itParam;
				histName  = baseName+"_"+param->name();
				histName += suffix;
				axisTitle = param->name() + "(" + baseName + ")";
				param->getMinMax(part,min,max);
				hist = new TH1F(histName, "", 100, min, max);
				hist->GetXaxis()->SetTitle(axisTitle);
				histos_.push_back(hist);
			}

			//2-body IMs
			if(part->nDaughters() > 2) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						for(itParam=paramsTwoBody_.begin(); itParam!=paramsTwoBody_.end(); ++itParam) {
							RapidParam* param = *itParam;
							histName  = jDaug->name()+"_";
							histName += kDaug->name()+"_";
							histName += param->name();
							histName += suffix;
							axisTitle = param->name() + "(" + jDaug->name() + "_" + kDaug->name() + ")";
							param->getMinMax(jDaug,kDaug,min,max);
							hist = new TH1F(histName, "", 100, min, max);
							hist->GetXaxis()->SetTitle(axisTitle);
							histos_.push_back(hist);
						}
					}
				}
			}

			//3-body IMs
			if(part->nDaughters() > 3) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						for(RapidParticle* lDaug=kDaug->next(); lDaug!=0; lDaug=lDaug->next()) {
							for(itParam=paramsThreeBody_.begin(); itParam!=paramsThreeBody_.end(); ++itParam) {
								RapidParam* param = *itParam;
								histName  = jDaug->name()+"_";
								histName += kDaug->name()+"_";
								histName += lDaug->name()+"_";
								histName += param->name();
								histName += suffix;
								axisTitle = param->name() + "(" + jDaug->name() + "_" + kDaug->name() + "_" + lDaug->name() + ")";
								param->getMinMax(jDaug,kDaug,lDaug,min,max);
								hist = new TH1F(histName, "", 100, min, max);
								hist->GetXaxis()->SetTitle(axisTitle);
								histos_.push_back(hist);
							}
						}

					}
				}
			}
		}
	}

	for( itParam=params_.begin(); itParam!= params_.end(); ++itParam) {
		RapidParam* param = (*itParam);
		param->getMinMax(min,max,true);
		TH1F* hist = new TH1F(param->name()+suffix, "", 100, min, max);
		histos_.push_back(hist);
	}
}

void RapidHistWriter::setupTree() {
	std::cout << "INFO in RapidHistWriter::setupTree : tree will be saved to file: " << name_ << "_tree.root" << std::endl;
	std::cout << "                                     This will slow down generation." << std::endl;

	treeFile_ = new TFile(name_+"_tree.root", "RECREATE");
	tree_ = new TTree("DecayTree","DecayTree");
	tree_->SetDirectory(treeFile_);

	for(unsigned int i=0; i<histos_.size(); ++i) {
		tree_->Branch(histos_[i]->GetName(), &vars_[i]);
	}

}

unsigned int RapidHistWriter::fillSingleHypothesis(unsigned int offset) {

	std::vector<RapidParam*>::iterator itParam;
	TLorentzVector pSumTruth;
	TLorentzVector pSum;

	for(unsigned int i=0; i<parts_.size(); ++i) {
		RapidParticle* part = parts_[i];

		if(part->nDaughters() < 2) {
			for(itParam=paramsStable_.begin(); itParam!=paramsStable_.end(); ++itParam) {
				RapidParam* param = *itParam;
				if(param->truth()) {
					vars_[offset] = param->eval(part->getP());
				} else {
					vars_[offset] = param->eval(part->getPSmeared());
				}

				histos_[offset]->Fill(vars_[offset]);
				++offset;
			}
		} else {
			for(itParam=paramsDecaying_.begin(); itParam!=paramsDecaying_.end(); ++itParam) {
				RapidParam* param = *itParam;
				if(param->truth()) {
					vars_[offset] = param->eval(part->getP());
				} else {
					vars_[offset] = param->eval(part->getPSmeared());
				}
				histos_[offset]->Fill(vars_[offset]);
				++offset;
			}

			//2-body IMs
			if(part->nDaughters() > 2) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						pSumTruth = jDaug->getP() + kDaug->getP();
						pSum = jDaug->getPSmeared() + kDaug->getPSmeared();

						for(itParam=paramsTwoBody_.begin(); itParam!=paramsTwoBody_.end(); ++itParam) {
							RapidParam* param = *itParam;
							if(param->truth()) {
								vars_[offset] = param->eval(pSumTruth);
							} else {
								vars_[offset] = param->eval(pSum);
							}
							histos_[offset]->Fill(vars_[offset]);
							++offset;
						}
					}
				}
			}

			//3-body IMs
			if(part->nDaughters() > 3) {
				RapidParticle* jDaug = part->daughter(0);

				for( ; jDaug!=0; jDaug=jDaug->next()) {
					for(RapidParticle* kDaug=jDaug->next(); kDaug!=0; kDaug=kDaug->next()) {
						for(RapidParticle* lDaug=kDaug->next(); lDaug!=0; lDaug=lDaug->next()) {
							pSumTruth = jDaug->getP() + kDaug->getP() + lDaug->getP();
							pSum = jDaug->getPSmeared() + kDaug->getPSmeared() + lDaug->getPSmeared();

							for(itParam=paramsThreeBody_.begin(); itParam!=paramsThreeBody_.end(); ++itParam) {
								RapidParam* param = *itParam;
								if(param->truth()) {
									vars_[offset] = param->eval(pSumTruth);
								} else {
									vars_[offset] = param->eval(pSum);
								}
								histos_[offset]->Fill(vars_[offset]);
								++offset;
							}
						}
					}
				}
			}
		}
	}

	std::vector<RapidParam*>::iterator it = params_.begin();
	for( ; it!= params_.end(); ++it) {
		vars_[offset] = (*it)->eval();
		histos_[offset]->Fill(vars_[offset]);
		++offset;
	}

	return offset;
}
<|endoftext|>


<commit_before>// -*- c++ -*-
/********************************************************************
 * AUTHORS: Vijay Ganesh
 *
 * BEGIN DATE: November, 2005
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/

#include "STP.h"
#include "DifficultyScore.h"
#include "../to-sat/AIG/ToSATAIG.h"
#include "../simplifier/constantBitP/ConstantBitPropagation.h"
#include "../simplifier/constantBitP/NodeToFixedBitsMap.h"
#include "../sat/SimplifyingMinisat.h"
#include "../sat/MinisatCore.h"
#include "../sat/CryptoMinisat.h"

namespace BEEV {

   // The absolute TopLevel function that invokes STP on the input
    // formula
  SOLVER_RETURN_TYPE STP::TopLevelSTP(const ASTNode& inputasserts,
				      const ASTNode& query)
  {
    ASTNode original_input = bm->CreateNode(AND,
					    inputasserts,
					    bm->CreateNode(NOT, query));

    //solver instantiated here
//#if defined CRYPTOMINISAT2
    //MINISAT::Solver NewSolver;

    //if(bm->UserFlags.print_cnf_flag)
      //{
	//NewSolver.needLibraryCNFFile(bm->UserFlags.cnf_dump_filename);
      //}
//#endif

    SATSolver *newS;
    if (bm->UserFlags.solver_to_use == UserDefinedFlags::SIMPLIFYING_MINISAT_SOLVER)
		newS = new SimplifyingMinisat();
    else if (bm->UserFlags.solver_to_use == UserDefinedFlags::CRYPTOMINISAT_SOLVER)
                    newS = new CryptoMinisat();
    else
      newS = new MinisatCore<Minisat::Solver>();

    SATSolver& NewSolver = *newS;

    if(bm->UserFlags.stats_flag)
      {
	NewSolver.setVerbosity(1);
      }

	SOLVER_RETURN_TYPE result;
    if(bm->UserFlags.num_absrefine_flag)
      {
     result =  UserGuided_AbsRefine(NewSolver,
				    original_input);
      }
    else
      {
	result = TopLevelSTPAux(NewSolver,
			      original_input, original_input);
      }

    delete newS;

    return result;

  } //End of TopLevelSTP()

  //Acceps a query, calls the SAT solver and generates Valid/InValid.
  //if returned 0 then input is INVALID if returned 1 then input is
  //VALID if returned 2 then UNDECIDED
  SOLVER_RETURN_TYPE STP::TopLevelSTPAux(SATSolver& NewSolver,
					 const ASTNode& modified_input,
					 const ASTNode& original_input)
  {
    ASTNode inputToSAT = modified_input;
    ASTNode orig_input = original_input;
    bm->ASTNodeStats("input asserts and query: ", inputToSAT);

    ASTNode simplified_solved_InputToSAT = inputToSAT;

    long initial_difficulty_score = DifficultyScore::score(original_input);

    //round of substitution, solving, and simplification. ensures that
    //DAG is minimized as much as possibly, and ideally should
    //garuntee that all liketerms in BVPLUSes have been combined.
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {

            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            //printf("##################################################\n");
            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);

            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }

      }
    while (inputToSAT != simplified_solved_InputToSAT);

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);
        simplifier::constantBitP::ConstantBitPropagation cb(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);
        simplified_solved_InputToSAT = cb.topLevelBothWays(simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb.isUnsatisfiable())
          simplified_solved_InputToSAT = bm->ASTFalse;

      }

    bm->ASTNodeStats("Before SimplifyWrites_Inplace begins: ",
                     simplified_solved_InputToSAT);

    bm->SimplifyWrites_InPlace_Flag = true;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);
            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        // The word level solver uses the simplifier to apply the rewrites it makes,
        // without optimisations enabled. It will enter infinite loops on some input.
        // Instead it could use the apply function of the substitution map, but it
        // doesn't yet...
        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }
      } while (inputToSAT != simplified_solved_InputToSAT);

    bm->ASTNodeStats("After SimplifyWrites_Inplace: ",
                     simplified_solved_InputToSAT);

    bm->start_abstracting =
      (bm->UserFlags.arraywrite_refinement_flag) ? true : false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = (bm->start_abstracting) ? false : true;
    if (bm->start_abstracting)
      {
        bm->ASTNodeStats("before abstraction round begins: ",
                         simplified_solved_InputToSAT);
      }

    bm->TermsAlreadySeenMap_Clear();
    if (bm->start_abstracting)
      {
        bm->ASTNodeStats("After abstraction: ", simplified_solved_InputToSAT);
      }
    bm->start_abstracting = false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;

    long final_difficulty_score = DifficultyScore::score(simplified_solved_InputToSAT);
    if (bm->UserFlags.stats_flag)
    {
    	cerr << "Initial Difficulty Score:" << initial_difficulty_score <<endl;
    	cerr << "Final Difficulty Score:" << final_difficulty_score <<endl;
    }

    const bool arrayops = containsArrayOps(original_input);
    bool optimize_enabled = bm->UserFlags.optimize_flag;
    if (final_difficulty_score > 2 *initial_difficulty_score  && !arrayops)
    {
    	// If the simplified problem is harder, than the
    	// initial problem we revert back to the initial
    	// problem.

    	if (bm->UserFlags.stats_flag)
    		cerr << "simplification made the problem harder, reverting."<<endl;
    	simplified_solved_InputToSAT = original_input;

    	// I do this to clear the substitution/solver map.
    	// Not sure what would happen if it contained simplifications
    	// that haven't been applied.
    	simp->ClearAllTables();

    	// The arrayTransformer calls simplify. We don't want
    	// it to put back in all the bad simplifications.
    	bm->UserFlags.optimize_flag = false;
    }

    simplified_solved_InputToSAT =
      arrayTransformer->TransformFormula_TopLevel(simplified_solved_InputToSAT);
    bm->ASTNodeStats("after transformation: ", simplified_solved_InputToSAT);
    bm->TermsAlreadySeenMap_Clear();

	bm->UserFlags.optimize_flag = optimize_enabled;

    SOLVER_RETURN_TYPE res;
    if (bm->UserFlags.arrayread_refinement_flag)
      {
        bm->counterexample_checking_during_refinement = true;
      }

    if(bm->UserFlags.stats_flag)
    	simp->printCacheStatus();

    simp->ClearCaches();
    bm->ClearAllTables();
    // Deleting it clears out all the buckets associated with hashmaps etc. too.
    delete bvsolver;
    bvsolver = new BVSolver(bm,simp);

    // If it doesn't contain array operations, use ABC's CNF generation.
    if (!arrayops)
    {
      simplifier::constantBitP::ConstantBitPropagation* cb = NULL;

#ifdef WITHCBITP
    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);

        cb = new simplifier::constantBitP::ConstantBitPropagation(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb->isUnsatisfiable())
           simplified_solved_InputToSAT = bm->ASTFalse;
      }
#endif

    ToSATAIG toSATAIG(bm,cb);

    res =
      Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                       simplified_solved_InputToSAT,
                                       orig_input,
                                       &toSATAIG
                                       );

    }
    else
      {
      res =
        Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                         simplified_solved_InputToSAT,
                                         orig_input,
                                         tosat
                                         );

      }

    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    assert(arrayops); // should only go to abstraction refinement if there are array ops.

    // res = SATBased_AllFiniteLoops_Refinement(NewSolver, orig_input);
    //     if (SOLVER_UNDECIDED != res)
    //       {
    //  CountersAndStats("print_func_stats");
    //         return res;
    //       }

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,
                                                tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayWriteRefinement(NewSolver, orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    if(!bm->UserFlags.num_absrefine_flag)
      {
	FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
		   "either a divide by zero in the input or a bug in STP");
	//bogus return to make the compiler shut up
	return SOLVER_ERROR;
      }
    else
      {
	return res;
      }
  } //End of TopLevelSTPAux

  //UserGuided abstraction refinement
  SOLVER_RETURN_TYPE
  STP::
  UserGuided_AbsRefine(SATSolver& NewSolver,
		       const ASTNode& original_input)
  {
    ASTVec v = bm->GetAsserts_WithKey(0);
    if(v.empty())
      {
	FatalError("UserGuided_AbsRefine: Something is seriously wrong."\
		   "The input set is empty");
      }
    ASTNode sureAddInput =
      (v.size() == 1) ? v[0] : bm->CreateNode(AND, v);

    SOLVER_RETURN_TYPE res = SOLVER_UNDECIDED;
    res = TopLevelSTPAux(NewSolver, sureAddInput, original_input);
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    //Do refinement here
    if(AND != original_input.GetKind())
      {
	FatalError("UserGuided_AbsRefine: The input must be an AND");
      }

    ASTVec RefineFormulasVec;
    ASTVec RemainingFormulasVec;
    ASTNode asttrue = bm->CreateNode(TRUE);
    ASTNode astfalse = bm->CreateNode(FALSE);
    for(int count=0; count < bm->UserFlags.num_absrefine; count++)
      {
	RemainingFormulasVec.clear();
	RemainingFormulasVec.push_back(asttrue);
	RefineFormulasVec.clear();
	RefineFormulasVec.push_back(asttrue);
	ASTVec InputKids = original_input.GetChildren();
	for(ASTVec::iterator it = InputKids.begin(), itend = InputKids.end();
	    it!=itend;it++)
	  {
	    Ctr_Example->ClearComputeFormulaMap();
	    if(astfalse == Ctr_Example->ComputeFormulaUsingModel(*it))
	      {
		RefineFormulasVec.push_back(*it);
	      }
	    else
	      {
		RemainingFormulasVec.push_back(*it);
	      }
	  }
	ASTNode RefineFormulas =
	  (RefineFormulasVec.size() == 1) ?
	  RefineFormulasVec[0] : bm->CreateNode(AND, RefineFormulasVec);
	res = TopLevelSTPAux(NewSolver, RefineFormulas, original_input);
	if(SOLVER_UNDECIDED != res)
	  {
	    return res;
	  }
      }

    ASTNode RemainingFormulas =
      (RemainingFormulasVec.size() == 1) ?
      RemainingFormulasVec[0] : bm->CreateNode(AND, RemainingFormulasVec);
    res = TopLevelSTPAux(NewSolver, RemainingFormulas, original_input);

    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
	       "either a divide by zero in the input or a bug in STP");
    return SOLVER_ERROR;
  } //End of UserGuided_AbsRefine()
}; //end of namespace
<commit_msg>Enable constant bit Propagation with CNF generation.<commit_after>// -*- c++ -*-
/********************************************************************
 * AUTHORS: Vijay Ganesh
 *
 * BEGIN DATE: November, 2005
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/

#include "STP.h"
#include "DifficultyScore.h"
#include "../to-sat/AIG/ToSATAIG.h"
#include "../simplifier/constantBitP/ConstantBitPropagation.h"
#include "../simplifier/constantBitP/NodeToFixedBitsMap.h"
#include "../sat/SimplifyingMinisat.h"
#include "../sat/MinisatCore.h"
#include "../sat/CryptoMinisat.h"

namespace BEEV {

   // The absolute TopLevel function that invokes STP on the input
    // formula
  SOLVER_RETURN_TYPE STP::TopLevelSTP(const ASTNode& inputasserts,
				      const ASTNode& query)
  {
    ASTNode original_input = bm->CreateNode(AND,
					    inputasserts,
					    bm->CreateNode(NOT, query));

    //solver instantiated here
//#if defined CRYPTOMINISAT2
    //MINISAT::Solver NewSolver;

    //if(bm->UserFlags.print_cnf_flag)
      //{
	//NewSolver.needLibraryCNFFile(bm->UserFlags.cnf_dump_filename);
      //}
//#endif

    SATSolver *newS;
    if (bm->UserFlags.solver_to_use == UserDefinedFlags::SIMPLIFYING_MINISAT_SOLVER)
		newS = new SimplifyingMinisat();
    else if (bm->UserFlags.solver_to_use == UserDefinedFlags::CRYPTOMINISAT_SOLVER)
                    newS = new CryptoMinisat();
    else
      newS = new MinisatCore<Minisat::Solver>();

    SATSolver& NewSolver = *newS;

    if(bm->UserFlags.stats_flag)
      {
	NewSolver.setVerbosity(1);
      }

	SOLVER_RETURN_TYPE result;
    if(bm->UserFlags.num_absrefine_flag)
      {
     result =  UserGuided_AbsRefine(NewSolver,
				    original_input);
      }
    else
      {
	result = TopLevelSTPAux(NewSolver,
			      original_input, original_input);
      }

    delete newS;

    return result;

  } //End of TopLevelSTP()

  //Acceps a query, calls the SAT solver and generates Valid/InValid.
  //if returned 0 then input is INVALID if returned 1 then input is
  //VALID if returned 2 then UNDECIDED
  SOLVER_RETURN_TYPE STP::TopLevelSTPAux(SATSolver& NewSolver,
					 const ASTNode& modified_input,
					 const ASTNode& original_input)
  {
    ASTNode inputToSAT = modified_input;
    ASTNode orig_input = original_input;
    bm->ASTNodeStats("input asserts and query: ", inputToSAT);

    ASTNode simplified_solved_InputToSAT = inputToSAT;

    long initial_difficulty_score = DifficultyScore::score(original_input);

    //round of substitution, solving, and simplification. ensures that
    //DAG is minimized as much as possibly, and ideally should
    //garuntee that all liketerms in BVPLUSes have been combined.
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {

            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            //printf("##################################################\n");
            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);

            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }

      }
    while (inputToSAT != simplified_solved_InputToSAT);

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);
        simplifier::constantBitP::ConstantBitPropagation cb(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);
        simplified_solved_InputToSAT = cb.topLevelBothWays(simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb.isUnsatisfiable())
          simplified_solved_InputToSAT = bm->ASTFalse;

      }

    bm->ASTNodeStats("Before SimplifyWrites_Inplace begins: ",
                     simplified_solved_InputToSAT);

    bm->SimplifyWrites_InPlace_Flag = true;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if(bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
            	simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            bm->ASTNodeStats("after pure substitution: ",
                             simplified_solved_InputToSAT);

            simplified_solved_InputToSAT =
              simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT,
                                             false);
            bm->ASTNodeStats("after simplification: ",
                             simplified_solved_InputToSAT);
          }

        // The word level solver uses the simplifier to apply the rewrites it makes,
        // without optimisations enabled. It will enter infinite loops on some input.
        // Instead it could use the apply function of the substitution map, but it
        // doesn't yet...
        if(bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT =
              bvsolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }
      } while (inputToSAT != simplified_solved_InputToSAT);

    bm->ASTNodeStats("After SimplifyWrites_Inplace: ",
                     simplified_solved_InputToSAT);

    bm->start_abstracting =
      (bm->UserFlags.arraywrite_refinement_flag) ? true : false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = (bm->start_abstracting) ? false : true;
    if (bm->start_abstracting)
      {
        bm->ASTNodeStats("before abstraction round begins: ",
                         simplified_solved_InputToSAT);
      }

    bm->TermsAlreadySeenMap_Clear();
    if (bm->start_abstracting)
      {
        bm->ASTNodeStats("After abstraction: ", simplified_solved_InputToSAT);
      }
    bm->start_abstracting = false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;

    long final_difficulty_score = DifficultyScore::score(simplified_solved_InputToSAT);
    if (bm->UserFlags.stats_flag)
    {
    	cerr << "Initial Difficulty Score:" << initial_difficulty_score <<endl;
    	cerr << "Final Difficulty Score:" << final_difficulty_score <<endl;
    }

    const bool arrayops = containsArrayOps(original_input);
    bool optimize_enabled = bm->UserFlags.optimize_flag;
    if (final_difficulty_score > 2 *initial_difficulty_score  && !arrayops)
    {
    	// If the simplified problem is harder, than the
    	// initial problem we revert back to the initial
    	// problem.

    	if (bm->UserFlags.stats_flag)
    		cerr << "simplification made the problem harder, reverting."<<endl;
    	simplified_solved_InputToSAT = original_input;

    	// I do this to clear the substitution/solver map.
    	// Not sure what would happen if it contained simplifications
    	// that haven't been applied.
    	simp->ClearAllTables();

    	// The arrayTransformer calls simplify. We don't want
    	// it to put back in all the bad simplifications.
    	bm->UserFlags.optimize_flag = false;
    }

    simplified_solved_InputToSAT =
      arrayTransformer->TransformFormula_TopLevel(simplified_solved_InputToSAT);
    bm->ASTNodeStats("after transformation: ", simplified_solved_InputToSAT);
    bm->TermsAlreadySeenMap_Clear();

	bm->UserFlags.optimize_flag = optimize_enabled;

    SOLVER_RETURN_TYPE res;
    if (bm->UserFlags.arrayread_refinement_flag)
      {
        bm->counterexample_checking_during_refinement = true;
      }

    if(bm->UserFlags.stats_flag)
    	simp->printCacheStatus();

    simp->ClearCaches();
    bm->ClearAllTables();
    // Deleting it clears out all the buckets associated with hashmaps etc. too.
    delete bvsolver;
    bvsolver = new BVSolver(bm,simp);

    // If it doesn't contain array operations, use ABC's CNF generation.
    if (!arrayops)
    {
      simplifier::constantBitP::ConstantBitPropagation* cb = NULL;

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ",
            simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);

        cb = new simplifier::constantBitP::ConstantBitPropagation(simp, bm->defaultNodeFactory,simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb->isUnsatisfiable())
           simplified_solved_InputToSAT = bm->ASTFalse;
      }

    ToSATAIG toSATAIG(bm,cb);

    res =
      Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                       simplified_solved_InputToSAT,
                                       orig_input,
                                       &toSATAIG
                                       );

    }
    else
      {
      res =
        Ctr_Example->CallSAT_ResultCheck(NewSolver,
                                         simplified_solved_InputToSAT,
                                         orig_input,
                                         tosat
                                         );

      }

    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    assert(arrayops); // should only go to abstraction refinement if there are array ops.

    // res = SATBased_AllFiniteLoops_Refinement(NewSolver, orig_input);
    //     if (SOLVER_UNDECIDED != res)
    //       {
    //  CountersAndStats("print_func_stats");
    //         return res;
    //       }

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,
                                                tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayWriteRefinement(NewSolver, orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res =
      Ctr_Example->SATBased_ArrayReadRefinement(NewSolver,
                                                simplified_solved_InputToSAT,
                                                orig_input,tosat);
    if (SOLVER_UNDECIDED != res)
      {
        CountersAndStats("print_func_stats", bm);
        return res;
      }

    if(!bm->UserFlags.num_absrefine_flag)
      {
	FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
		   "either a divide by zero in the input or a bug in STP");
	//bogus return to make the compiler shut up
	return SOLVER_ERROR;
      }
    else
      {
	return res;
      }
  } //End of TopLevelSTPAux

  //UserGuided abstraction refinement
  SOLVER_RETURN_TYPE
  STP::
  UserGuided_AbsRefine(SATSolver& NewSolver,
		       const ASTNode& original_input)
  {
    ASTVec v = bm->GetAsserts_WithKey(0);
    if(v.empty())
      {
	FatalError("UserGuided_AbsRefine: Something is seriously wrong."\
		   "The input set is empty");
      }
    ASTNode sureAddInput =
      (v.size() == 1) ? v[0] : bm->CreateNode(AND, v);

    SOLVER_RETURN_TYPE res = SOLVER_UNDECIDED;
    res = TopLevelSTPAux(NewSolver, sureAddInput, original_input);
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    //Do refinement here
    if(AND != original_input.GetKind())
      {
	FatalError("UserGuided_AbsRefine: The input must be an AND");
      }

    ASTVec RefineFormulasVec;
    ASTVec RemainingFormulasVec;
    ASTNode asttrue = bm->CreateNode(TRUE);
    ASTNode astfalse = bm->CreateNode(FALSE);
    for(int count=0; count < bm->UserFlags.num_absrefine; count++)
      {
	RemainingFormulasVec.clear();
	RemainingFormulasVec.push_back(asttrue);
	RefineFormulasVec.clear();
	RefineFormulasVec.push_back(asttrue);
	ASTVec InputKids = original_input.GetChildren();
	for(ASTVec::iterator it = InputKids.begin(), itend = InputKids.end();
	    it!=itend;it++)
	  {
	    Ctr_Example->ClearComputeFormulaMap();
	    if(astfalse == Ctr_Example->ComputeFormulaUsingModel(*it))
	      {
		RefineFormulasVec.push_back(*it);
	      }
	    else
	      {
		RemainingFormulasVec.push_back(*it);
	      }
	  }
	ASTNode RefineFormulas =
	  (RefineFormulasVec.size() == 1) ?
	  RefineFormulasVec[0] : bm->CreateNode(AND, RefineFormulasVec);
	res = TopLevelSTPAux(NewSolver, RefineFormulas, original_input);
	if(SOLVER_UNDECIDED != res)
	  {
	    return res;
	  }
      }

    ASTNode RemainingFormulas =
      (RemainingFormulasVec.size() == 1) ?
      RemainingFormulasVec[0] : bm->CreateNode(AND, RemainingFormulasVec);
    res = TopLevelSTPAux(NewSolver, RemainingFormulas, original_input);

    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }

    FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
	       "either a divide by zero in the input or a bug in STP");
    return SOLVER_ERROR;
  } //End of UserGuided_AbsRefine()
}; //end of namespace
<|endoftext|>


<commit_before>/*
 * SocketIOclient.cpp
 *
 *  Created on: May 12, 2018
 *      Author: links
 */

#include "WebSockets.h"
#include "WebSocketsClient.h"
#include "SocketIOclient.h"

SocketIOclient::SocketIOclient() {
}

SocketIOclient::~SocketIOclient() {
}

void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
    WebSocketsClient::beginSocketIO(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
    WebSocketsClient::beginSocketIO(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}
#if defined(HAS_SSL)
void SocketIOclient::beginSSL(const char * host, uint16_t port, const char * url, const char * protocol) {
    WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::beginSSL(String host, uint16_t port, String url, String protocol) {
    WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}
#if !defined(SSL_AXTLS)
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
    WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
    WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
    WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
}

void SocketIOclient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
    WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
}

#endif
#endif
/**
 * set callback function
 * @param cbEvent SocketIOclientEvent
 */
void SocketIOclient::onEvent(SocketIOclientEvent cbEvent) {
    _cbEvent = cbEvent;
}

bool SocketIOclient::isConnected(void) {
    return WebSocketsClient::isConnected();
}

/**
 * send text data to client
 * @param num uint8_t client id
 * @param type socketIOmessageType_t
 * @param payload uint8_t *
 * @param length size_t
 * @param headerToPayload bool (see sendFrame for more details)
 * @return true if ok
 */
bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t length, bool headerToPayload) {
    bool ret = false;
    if(length == 0) {
        length = strlen((const char *)payload);
    }
    if(clientIsConnected(&_client)) {
        if(!headerToPayload) {
            // webSocket Header
            ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true);
            // Engine.IO / Socket.IO Header
            if(ret) {
                uint8_t buf[3] = { eIOtype_MESSAGE, type, 0x00 };
                ret            = WebSocketsClient::write(&_client, buf, 2);
            }
            if(ret && payload && length > 0) {
                ret = WebSocketsClient::write(&_client, payload, length);
            }
            return ret;
        } else {
            // TODO implement
        }
    }
    return false;
}

bool SocketIOclient::send(socketIOmessageType_t type, const uint8_t * payload, size_t length) {
    return send(type, (uint8_t *)payload, length);
}

bool SocketIOclient::send(socketIOmessageType_t type, char * payload, size_t length, bool headerToPayload) {
    return send(type, (uint8_t *)payload, length, headerToPayload);
}

bool SocketIOclient::send(socketIOmessageType_t type, const char * payload, size_t length) {
    return send(type, (uint8_t *)payload, length);
}

bool SocketIOclient::send(socketIOmessageType_t type, String & payload) {
    return send(type, (uint8_t *)payload.c_str(), payload.length());
}

/**
 * send text data to client
 * @param num uint8_t client id
 * @param payload uint8_t *
 * @param length size_t
 * @param headerToPayload bool  (see sendFrame for more details)
 * @return true if ok
 */
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
    return send(sIOtype_EVENT, payload, length, headerToPayload);
}

bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
    return sendEVENT((uint8_t *)payload, length);
}

bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) {
    return sendEVENT((uint8_t *)payload, length, headerToPayload);
}

bool SocketIOclient::sendEVENT(const char * payload, size_t length) {
    return sendEVENT((uint8_t *)payload, length);
}

bool SocketIOclient::sendEVENT(String & payload) {
    return sendEVENT((uint8_t *)payload.c_str(), payload.length());
}

void SocketIOclient::loop(void) {
    WebSocketsClient::loop();
    unsigned long t = millis();
    if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) {
        _lastConnectionFail = t;
        DEBUG_WEBSOCKETS("[wsIOc] send ping\n");
        WebSocketsClient::sendTXT(eIOtype_PING);
    }
}

void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t length) {
    switch(type) {
        case WStype_DISCONNECTED:
            runIOCbEvent(sIOtype_DISCONNECT, NULL, 0);
            DEBUG_WEBSOCKETS("[wsIOc] Disconnected!\n");
            break;
        case WStype_CONNECTED: {
            DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
            // send message to server when Connected
            // Engine.io upgrade confirmation message (required)
            WebSocketsClient::sendTXT(eIOtype_UPGRADE);
            runIOCbEvent(sIOtype_CONNECT, payload, length);
        } break;
        case WStype_TEXT: {
            if(length < 1) {
                break;
            }

            engineIOmessageType_t eType = (engineIOmessageType_t)payload[0];
            switch(eType) {
                case eIOtype_PING:
                    payload[0] = eIOtype_PONG;
                    DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload);
                    WebSocketsClient::sendTXT(payload, length, false);
                    break;
                case eIOtype_PONG:
                    DEBUG_WEBSOCKETS("[wsIOc] get pong\n");
                    break;
                case eIOtype_MESSAGE: {
                    if(length < 2) {
                        break;
                    }
                    socketIOmessageType_t ioType = (socketIOmessageType_t)payload[1];
                    uint8_t * data               = &payload[2];
                    size_t lData                 = length - 2;
                    switch(ioType) {
                        case sIOtype_EVENT:
                            DEBUG_WEBSOCKETS("[wsIOc] get event (%d): %s\n", lData, data);
                            break;
                        case sIOtype_CONNECT:
                        case sIOtype_DISCONNECT:
                        case sIOtype_ACK:
                        case sIOtype_ERROR:
                        case sIOtype_BINARY_EVENT:
                        case sIOtype_BINARY_ACK:
                        default:
                            DEBUG_WEBSOCKETS("[wsIOc] Socket.IO Message Type %c (%02X) is not implemented\n", ioType, ioType);
                            DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
                            break;
                    }

                    runIOCbEvent(ioType, data, lData);
                } break;
                case eIOtype_OPEN:
                case eIOtype_CLOSE:
                case eIOtype_UPGRADE:
                case eIOtype_NOOP:
                default:
                    DEBUG_WEBSOCKETS("[wsIOc] Engine.IO Message Type %c (%02X) is not implemented\n", eType, eType);
                    DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
                    break;
            }
        } break;
        case WStype_ERROR:
        case WStype_BIN:
        case WStype_FRAGMENT_TEXT_START:
        case WStype_FRAGMENT_BIN_START:
        case WStype_FRAGMENT:
        case WStype_FRAGMENT_FIN:
        case WStype_PING:
        case WStype_PONG:
            break;
    }
}
<commit_msg>only try to send socket.io messages in WSC_CONNECTED state handle sIOtype_CONNECT messages send 2probe on websocket connect (#574)<commit_after>/*
 * SocketIOclient.cpp
 *
 *  Created on: May 12, 2018
 *      Author: links
 */

#include "WebSockets.h"
#include "WebSocketsClient.h"
#include "SocketIOclient.h"

SocketIOclient::SocketIOclient() {
}

SocketIOclient::~SocketIOclient() {
}

void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
    WebSocketsClient::beginSocketIO(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
    WebSocketsClient::beginSocketIO(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}
#if defined(HAS_SSL)
void SocketIOclient::beginSSL(const char * host, uint16_t port, const char * url, const char * protocol) {
    WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::beginSSL(String host, uint16_t port, String url, String protocol) {
    WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}
#if !defined(SSL_AXTLS)
void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
    WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
    WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
    WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
}

void SocketIOclient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
    WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
}

void SocketIOclient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
    WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
}

#endif
#endif
/**
 * set callback function
 * @param cbEvent SocketIOclientEvent
 */
void SocketIOclient::onEvent(SocketIOclientEvent cbEvent) {
    _cbEvent = cbEvent;
}

bool SocketIOclient::isConnected(void) {
    return WebSocketsClient::isConnected();
}

/**
 * send text data to client
 * @param num uint8_t client id
 * @param type socketIOmessageType_t
 * @param payload uint8_t *
 * @param length size_t
 * @param headerToPayload bool (see sendFrame for more details)
 * @return true if ok
 */
bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t length, bool headerToPayload) {
    bool ret = false;
    if(length == 0) {
        length = strlen((const char *)payload);
    }
    if(clientIsConnected(&_client) && _client.status == WSC_CONNECTED) {
        if(!headerToPayload) {
            // webSocket Header
            ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true);
            // Engine.IO / Socket.IO Header
            if(ret) {
                uint8_t buf[3] = { eIOtype_MESSAGE, type, 0x00 };
                ret            = WebSocketsClient::write(&_client, buf, 2);
            }
            if(ret && payload && length > 0) {
                ret = WebSocketsClient::write(&_client, payload, length);
            }
            return ret;
        } else {
            // TODO implement
        }
    }
    return false;
}

bool SocketIOclient::send(socketIOmessageType_t type, const uint8_t * payload, size_t length) {
    return send(type, (uint8_t *)payload, length);
}

bool SocketIOclient::send(socketIOmessageType_t type, char * payload, size_t length, bool headerToPayload) {
    return send(type, (uint8_t *)payload, length, headerToPayload);
}

bool SocketIOclient::send(socketIOmessageType_t type, const char * payload, size_t length) {
    return send(type, (uint8_t *)payload, length);
}

bool SocketIOclient::send(socketIOmessageType_t type, String & payload) {
    return send(type, (uint8_t *)payload.c_str(), payload.length());
}

/**
 * send text data to client
 * @param num uint8_t client id
 * @param payload uint8_t *
 * @param length size_t
 * @param headerToPayload bool  (see sendFrame for more details)
 * @return true if ok
 */
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
    return send(sIOtype_EVENT, payload, length, headerToPayload);
}

bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
    return sendEVENT((uint8_t *)payload, length);
}

bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) {
    return sendEVENT((uint8_t *)payload, length, headerToPayload);
}

bool SocketIOclient::sendEVENT(const char * payload, size_t length) {
    return sendEVENT((uint8_t *)payload, length);
}

bool SocketIOclient::sendEVENT(String & payload) {
    return sendEVENT((uint8_t *)payload.c_str(), payload.length());
}

void SocketIOclient::loop(void) {
    WebSocketsClient::loop();
    unsigned long t = millis();
    if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) {
        _lastConnectionFail = t;
        DEBUG_WEBSOCKETS("[wsIOc] send ping\n");
        WebSocketsClient::sendTXT(eIOtype_PING);
    }
}

void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t length) {
    switch(type) {
        case WStype_DISCONNECTED:
            runIOCbEvent(sIOtype_DISCONNECT, NULL, 0);
            DEBUG_WEBSOCKETS("[wsIOc] Disconnected!\n");
            break;
        case WStype_CONNECTED: {
            DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
            // send message to server when Connected
            // Engine.io upgrade confirmation message (required)
            WebSocketsClient::sendTXT("2probe");
            WebSocketsClient::sendTXT(eIOtype_UPGRADE);
            runIOCbEvent(sIOtype_CONNECT, payload, length);
        } break;
        case WStype_TEXT: {
            if(length < 1) {
                break;
            }

            engineIOmessageType_t eType = (engineIOmessageType_t)payload[0];
            switch(eType) {
                case eIOtype_PING:
                    payload[0] = eIOtype_PONG;
                    DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload);
                    WebSocketsClient::sendTXT(payload, length, false);
                    break;
                case eIOtype_PONG:
                    DEBUG_WEBSOCKETS("[wsIOc] get pong\n");
                    break;
                case eIOtype_MESSAGE: {
                    if(length < 2) {
                        break;
                    }
                    socketIOmessageType_t ioType = (socketIOmessageType_t)payload[1];
                    uint8_t * data               = &payload[2];
                    size_t lData                 = length - 2;
                    switch(ioType) {
                        case sIOtype_EVENT:
                            DEBUG_WEBSOCKETS("[wsIOc] get event (%d): %s\n", lData, data);
                            break;
                        case sIOtype_CONNECT:
                            DEBUG_WEBSOCKETS("[wsIOc] connected (%d): %s\n", lData, data);
                            return;
                        case sIOtype_DISCONNECT:
                        case sIOtype_ACK:
                        case sIOtype_ERROR:
                        case sIOtype_BINARY_EVENT:
                        case sIOtype_BINARY_ACK:
                        default:
                            DEBUG_WEBSOCKETS("[wsIOc] Socket.IO Message Type %c (%02X) is not implemented\n", ioType, ioType);
                            DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
                            break;
                    }

                    runIOCbEvent(ioType, data, lData);
                } break;
                case eIOtype_OPEN:
                case eIOtype_CLOSE:
                case eIOtype_UPGRADE:
                case eIOtype_NOOP:
                default:
                    DEBUG_WEBSOCKETS("[wsIOc] Engine.IO Message Type %c (%02X) is not implemented\n", eType, eType);
                    DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
                    break;
            }
        } break;
        case WStype_ERROR:
        case WStype_BIN:
        case WStype_FRAGMENT_TEXT_START:
        case WStype_FRAGMENT_BIN_START:
        case WStype_FRAGMENT:
        case WStype_FRAGMENT_FIN:
        case WStype_PING:
        case WStype_PONG:
            break;
    }
}
<|endoftext|>


<commit_before>#include "StackAllocator.h"
#include "Utils.h"		/* CalculatePadding */
#include <stdlib.h>     /* malloc, free */

#ifdef _DEBUG
	#include <iostream>
#endif

StackAllocator::StackAllocator(const std::size_t totalSize)
	: Allocator(totalSize) {

}

void StackAllocator::Init() {
	if (m_start_ptr != nullptr){
		free(m_start_ptr);
	}
	m_start_ptr = malloc(m_totalSize);
	m_offset = 0;
}

StackAllocator::~StackAllocator() {
	free(m_start_ptr);
	m_start_ptr = nullptr;
}
void* StackAllocator::Allocate(const std::size_t size, const std::size_t alignment){
	const std::size_t currentAddress = (std::size_t)m_start_ptr + m_offset;

	std::size_t padding = Utils::CalculatePaddingWithHeader(currentAddress, alignment, sizeof(AllocationHeader));

	if (m_offset + padding + size > m_totalSize){
		return nullptr;
	}
	m_offset += padding;

	const std::size_t nextAddress = currentAddress + padding;
	const std::size_t headerAddress = nextAddress - sizeof(AllocationHeader);
	const AllocationHeader allocationHeader {padding};
	*(AllocationHeader *) headerAddress = allocationHeader;
	m_offset +=size;

#ifdef _DEBUG
	std::cout << "A" << "\t@C " << (void*) currentAddress << "\t@R " << (void*) nextAddress << "\tO " << m_offset << "\tP " << padding << std::endl;
#endif
	m_used = m_offset;
	return (void*) nextAddress;
}

void StackAllocator::Free(void *ptr) {
	// Move offset back to clear address
	const std::size_t currentAddress = (std::size_t) ptr;
	const std::size_t headerAddress = currentAddress - sizeof(AllocationHeader);
	const AllocationHeader * allocationHeader { (AllocationHeader *) headerAddress};

	m_offset = currentAddress - allocationHeader->padding - (std::size_t) m_start_ptr;
	m_used = m_offset;

#ifdef _DEBUG
	std::cout << "F" << "\t@C " << (void*) currentAddress << "\t@F " << (void*) m_start_ptr + m_offset << "\tO " << m_offset << std::endl;
#endif
}

void LinearAllocator::Reset() {
	m_offset = 0;
	m_used = 0;
}<commit_msg>Added Reset() method<commit_after>#include "StackAllocator.h"
#include "Utils.h"		/* CalculatePadding */
#include <stdlib.h>     /* malloc, free */

#ifdef _DEBUG
	#include <iostream>
#endif

StackAllocator::StackAllocator(const std::size_t totalSize)
	: Allocator(totalSize) {

}

void StackAllocator::Init() {
	if (m_start_ptr != nullptr){
		free(m_start_ptr);
	}
	m_start_ptr = malloc(m_totalSize);
	m_offset = 0;
}

StackAllocator::~StackAllocator() {
	free(m_start_ptr);
	m_start_ptr = nullptr;
}
void* StackAllocator::Allocate(const std::size_t size, const std::size_t alignment){
	const std::size_t currentAddress = (std::size_t)m_start_ptr + m_offset;

	std::size_t padding = Utils::CalculatePaddingWithHeader(currentAddress, alignment, sizeof(AllocationHeader));

	if (m_offset + padding + size > m_totalSize){
		return nullptr;
	}
	m_offset += padding;

	const std::size_t nextAddress = currentAddress + padding;
	const std::size_t headerAddress = nextAddress - sizeof(AllocationHeader);
	const AllocationHeader allocationHeader {padding};
	*(AllocationHeader *) headerAddress = allocationHeader;
	m_offset +=size;

#ifdef _DEBUG
	std::cout << "A" << "\t@C " << (void*) currentAddress << "\t@R " << (void*) nextAddress << "\tO " << m_offset << "\tP " << padding << std::endl;
#endif
	m_used = m_offset;
	return (void*) nextAddress;
}

void StackAllocator::Free(void *ptr) {
	// Move offset back to clear address
	const std::size_t currentAddress = (std::size_t) ptr;
	const std::size_t headerAddress = currentAddress - sizeof(AllocationHeader);
	const AllocationHeader * allocationHeader { (AllocationHeader *) headerAddress};

	m_offset = currentAddress - allocationHeader->padding - (std::size_t) m_start_ptr;
	m_used = m_offset;

#ifdef _DEBUG
	std::cout << "F" << "\t@C " << (void*) currentAddress << "\t@F " << (void*) m_start_ptr + m_offset << "\tO " << m_offset << std::endl;
#endif
}

void StackAllocator::Reset() {
	m_offset = 0;
	m_used = 0;
}<|endoftext|>


<commit_before>extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
#include <libavutil/channel_layout.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}

#include <cstring>
#include <iostream>
#include "SubtitleStream.hpp"
#include "Log.hpp"
#include <sfeMovie/Movie.hpp>

namespace sfe {
	SubtitleStream::SubtitleStream(AVFormatContext* formatCtx, AVStream* stream, DataSource& dataSource, Timer& timer,Delegate& delegate) :
		Stream(formatCtx, stream, dataSource, timer), m_delegate(delegate)
	{
	}

	/** Default destructor
	*/
	SubtitleStream::~SubtitleStream()
	{

	}

	MediaType SubtitleStream::getStreamKind() const
	{
		return MEDIA_TYPE_SUBTITLE;
	}

	void SubtitleStream::update()
	{
		//only get new subtitles if we are running low
		if (m_status == Status::Playing && m_inactive.size()<m_buffersize)
		{
			if (!onGetData()) {
				setStatus(Stopped);
			}
		}

		for (uint32_t i = 0; i < m_inactive.size(); ++i)
		{
			//activate subtitle
			if (m_inactive[i]->pts + m_inactive[i]->sub.start_display_time < m_timer.getOffset().asMilliseconds())
			{
				SubImage* c = m_inactive[i];
				c->out = SubToSprites(&c->sub);
				m_delegate.didUpdateSubtitle(*this, c->out);
				m_active.push_back(c);
				m_inactive.erase(m_inactive.begin() + i);

			}
		}

		for (uint32_t i = 0; i < m_active.size(); ++i)
		{
			if (m_active[i]->pts + m_active[i]->sub.end_display_time < m_timer.getOffset().asMilliseconds())
			{
				m_active.erase(m_active.begin() + i);
				if (m_active.size() == 0)
				{
					std::vector<sf::Sprite*> empty;
					m_delegate.didUpdateSubtitle(*this, empty);
					delete m_texture;
				}
			}
		}
	}

	bool SubtitleStream::onGetData()
	{
		AVPacket* packet = popEncodedData();
		AVSubtitle sub;
		int32_t gotSub = 0;
		int32_t goOn = 0;
		int64_t pts = 0;

		if (packet) {
			goOn = true;

			while (!gotSub && packet && goOn) {
				bool needsMoreDecoding = false;

				CHECK(packet != NULL, "inconsistency error");
				goOn = avcodec_decode_subtitle2(m_codecCtx, &sub, &gotSub, packet);

				pts = 0;
				if (packet->pts != AV_NOPTS_VALUE)
					pts =  packet->pts;

				if (gotSub && pts) {
					SubImage* subimg = new SubImage();
					subimg->sub = sub;
					subimg->pts = pts;

					m_inactive.push_back(subimg);
				}

				if (needsMoreDecoding) {
					prependEncodedData(packet);
				}
				else {
					av_free_packet(packet);
					av_free(packet);
				}

				if (!gotSub && goOn) {
					sfeLogDebug("no image in this packet, reading further");
					packet = popEncodedData();
				}
			}
		}

		return static_cast<bool>(goOn);
	}

	std::vector<sf::Sprite*> SubtitleStream::SubToSprites(AVSubtitle* sub)
	{
		std::vector<sf::Sprite*> sprites;

		for (int i = 0; i < sub->num_rects; ++i)
		{
			sf::Sprite* sprite = new sf::Sprite();
			sprite->setOrigin(sf::Vector2f(sub->rects[i]->x, sub->rects[i]->y));
			sprite->setPosition(sf::Vector2f(sub->rects[i]->x * 2, sub->rects[i]->y * 1.75f));
			uint32_t* palette = new uint32_t[sub->rects[i]->nb_colors];
			for(int j = 0; j < sub->rects[i]->nb_colors; j++)
			{
				 palette[j] = *(uint32_t*)&sub->rects[i]->pict.data[1][j*4];
			}

			sf::Texture* tex = new sf::Texture();
			m_texture = tex;
			tex->create(sub->rects[i]->w, sub->rects[i]->h);

			uint32_t* data = new uint32_t[sub->rects[i]->w* sub->rects[i]->h];
			for (int j = 0; j < sub->rects[i]->w* sub->rects[i]->h; ++j)
			{
				data[j] = palette[sub->rects[i]->pict.data[0][j]];
			}
			tex->update((uint8_t*)data);
			sprite->setTexture(*tex);
			sprites.push_back(sprite);
			delete[] data;
			delete[] palette;
		}

		return sprites;
	}
}<commit_msg>Fixed an issue that was breaking the build on Clang compiler<commit_after>extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
#include <libavutil/channel_layout.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}

#include <cstring>
#include <iostream>
#include "SubtitleStream.hpp"
#include "Log.hpp"
#include <sfeMovie/Movie.hpp>

namespace sfe {
	SubtitleStream::SubtitleStream(AVFormatContext* formatCtx, AVStream* stream, DataSource& dataSource, Timer& timer,Delegate& delegate) :
		Stream(formatCtx, stream, dataSource, timer), m_delegate(delegate)
	{
	}

	/** Default destructor
	*/
	SubtitleStream::~SubtitleStream()
	{

	}

	MediaType SubtitleStream::getStreamKind() const
	{
		return MEDIA_TYPE_SUBTITLE;
	}

	void SubtitleStream::update()
	{
		//only get new subtitles if we are running low
		if (m_status == Playing && m_inactive.size()<m_buffersize)
		{
			if (!onGetData()) {
				setStatus(Stopped);
			}
		}

		for (uint32_t i = 0; i < m_inactive.size(); ++i)
		{
			//activate subtitle
			if (m_inactive[i]->pts + m_inactive[i]->sub.start_display_time < m_timer.getOffset().asMilliseconds())
			{
				SubImage* c = m_inactive[i];
				c->out = SubToSprites(&c->sub);
				m_delegate.didUpdateSubtitle(*this, c->out);
				m_active.push_back(c);
				m_inactive.erase(m_inactive.begin() + i);

			}
		}

		for (uint32_t i = 0; i < m_active.size(); ++i)
		{
			if (m_active[i]->pts + m_active[i]->sub.end_display_time < m_timer.getOffset().asMilliseconds())
			{
				m_active.erase(m_active.begin() + i);
				if (m_active.size() == 0)
				{
					std::vector<sf::Sprite*> empty;
					m_delegate.didUpdateSubtitle(*this, empty);
					delete m_texture;
				}
			}
		}
	}

	bool SubtitleStream::onGetData()
	{
		AVPacket* packet = popEncodedData();
		AVSubtitle sub;
		int32_t gotSub = 0;
		int32_t goOn = 0;
		int64_t pts = 0;

		if (packet) {
			goOn = true;

			while (!gotSub && packet && goOn) {
				bool needsMoreDecoding = false;

				CHECK(packet != NULL, "inconsistency error");
				goOn = avcodec_decode_subtitle2(m_codecCtx, &sub, &gotSub, packet);

				pts = 0;
				if (packet->pts != AV_NOPTS_VALUE)
					pts =  packet->pts;

				if (gotSub && pts) {
					SubImage* subimg = new SubImage();
					subimg->sub = sub;
					subimg->pts = pts;

					m_inactive.push_back(subimg);
				}

				if (needsMoreDecoding) {
					prependEncodedData(packet);
				}
				else {
					av_free_packet(packet);
					av_free(packet);
				}

				if (!gotSub && goOn) {
					sfeLogDebug("no image in this packet, reading further");
					packet = popEncodedData();
				}
			}
		}

		return static_cast<bool>(goOn);
	}

	std::vector<sf::Sprite*> SubtitleStream::SubToSprites(AVSubtitle* sub)
	{
		std::vector<sf::Sprite*> sprites;

		for (int i = 0; i < sub->num_rects; ++i)
		{
			sf::Sprite* sprite = new sf::Sprite();
			sprite->setOrigin(sf::Vector2f(sub->rects[i]->x, sub->rects[i]->y));
			sprite->setPosition(sf::Vector2f(sub->rects[i]->x * 2, sub->rects[i]->y * 1.75f));
			uint32_t* palette = new uint32_t[sub->rects[i]->nb_colors];
			for(int j = 0; j < sub->rects[i]->nb_colors; j++)
			{
				 palette[j] = *(uint32_t*)&sub->rects[i]->pict.data[1][j*4];
			}

			sf::Texture* tex = new sf::Texture();
			m_texture = tex;
			tex->create(sub->rects[i]->w, sub->rects[i]->h);

			uint32_t* data = new uint32_t[sub->rects[i]->w* sub->rects[i]->h];
			for (int j = 0; j < sub->rects[i]->w* sub->rects[i]->h; ++j)
			{
				data[j] = palette[sub->rects[i]->pict.data[0][j]];
			}
			tex->update((uint8_t*)data);
			sprite->setTexture(*tex);
			sprites.push_back(sprite);
			delete[] data;
			delete[] palette;
		}

		return sprites;
	}
}<|endoftext|>


<commit_before>// TransformTools.cpp
/*
 * Copyright (c) 2009, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include "TransformTools.h"
#include "MarkedList.h"
#include "HLine.h"
#include "HILine.h"

static double from[3];
static double centre[3];

static void on_move_translate(const double* to)
{
	wxGetApp().m_drag_matrix.SetTranslationPart(gp_Vec(make_point(from), make_point(to)));
	wxGetApp().Repaint(true);
}

//static
void TransformTools::RemoveUncopyable()
{
	std::list<HeeksObj*> uncopyable_objects;
	for(std::list<HeeksObj*>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
	{
		HeeksObj* object = *It;
		if(!object->CanBeCopied())uncopyable_objects.push_back(object);
	}
	if(uncopyable_objects.size() > 0)wxGetApp().m_marked_list->Remove(uncopyable_objects, true);
}

//static
void TransformTools::Translate(bool copy)
{
	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to move"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	// get number of copies
	int ncopies = 1;
	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	// pick "from" position
	if(!wxGetApp().PickPosition(_("Click position to move from"), from))return;

	// pick "to" position
	wxGetApp().CreateTransformGLList(selected_items, false);
	wxGetApp().m_drag_matrix = gp_Trsf();
	if(!copy)
	{
		for(std::list<HeeksObj*>::const_iterator It = selected_items.begin(); It != selected_items.end(); It++){
			HeeksObj* object = *It;
			if(object->m_visible)wxGetApp().m_hidden_for_drag.push_back(object);
			object->m_visible = false;
		}
	}
	double to[3];
	wxGetApp().PickPosition(_("Click position to move to"), to, on_move_translate);
	if(!copy)
	{
		for(std::list<HeeksObj*>::iterator It = wxGetApp().m_hidden_for_drag.begin(); It != wxGetApp().m_hidden_for_drag.end(); It++)
		{
			HeeksObj* object = *It;
			object->m_visible = true;
		}
		wxGetApp().m_hidden_for_drag.clear();
	}
	wxGetApp().DestroyTransformGLList();

	// transform the objects
	if(copy)
	{
		for(int i = 0; i<ncopies; i++)
		{
			gp_Trsf mat;
			mat.SetTranslationPart(make_vector(make_point(from), make_point(to)) * (i + 1));
			double m[16];
			extract(mat, m);
			for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
			{
				HeeksObj* object = *It;
				HeeksObj* new_object = object->MakeACopy();
				object->Owner()->Add(new_object, NULL);
				new_object->ModifyByMatrix(m);
			}
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		gp_Trsf mat;
		mat.SetTranslationPart(make_vector(make_point(from), make_point(to)));
		double m[16];
		extract(mat, m);
		wxGetApp().Transform(selected_items, m);
	}
}

//static
void TransformTools::Rotate(bool copy)
{
	//rotation axis - Z axis by default
	gp_Dir axis_Dir = gp_Dir(0,0,1);
	gp_Pnt line_Pos = gp_Pnt(0,0,0);

	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to rotate"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	// get number of copies
	int ncopies = 1;
	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	if(wxGetApp().allow3DRotaion)
	{
		// pick a line to use as rotation axis
		bool line_found = false;
		gp_Lin line;
		int save_filter = wxGetApp().m_marked_list->m_filter;
		wxGetApp().m_marked_list->m_filter = MARKING_FILTER_LINE | MARKING_FILTER_ILINE;
		wxGetApp().PickObjects(_("Pick line for rotation axis"), true);
		wxGetApp().m_marked_list->m_filter = save_filter;
		for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
		{
			HeeksObj* object = *It;
			if(object->GetType() == LineType)
			{
				line = ((HLine*)object)->GetLine();
				line_found = true;
			}
			else if(object->GetType() == ILineType)
			{
				line = ((HILine*)object)->GetLine();
				line_found = true;
			}
		}
		if(!line_found)return;
		axis_Dir=line.Direction();
		line_Pos= line.Location();
	}
	else
	{
		// pick "centre" position
		if(!wxGetApp().PickPosition(_("Click centre position to rotate about"), centre))return;
		line_Pos.SetXYZ(gp_XYZ(centre[0],centre[1],centre[2]));
	}

	// enter angle
	double angle = 45.0;
	if(!wxGetApp().InputDouble(_("Enter angle to rotate by"), _("angle"), angle))return;

	// transform the objects
	if(copy)
	{
		for(int i = 0; i<ncopies; i++)
		{
			gp_Trsf mat;
			mat.SetRotation(gp_Ax1(line_Pos, axis_Dir), angle * Pi/180 * (i+1));
			double m[16];
			extract(mat, m);
			for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
			{
				HeeksObj* object = *It;
				object->ModifyByMatrix(m);
			}
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		gp_Trsf mat;
		mat.SetRotation(gp_Ax1(line_Pos, axis_Dir), angle * Pi/180);
		double m[16];
		extract(mat, m);
		wxGetApp().Transform(selected_items, m);
	}
}

//static
void TransformTools::Mirror(bool copy)
{
	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to mirror"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		int ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	// pick a line to mirror about
	bool line_found = false;
	gp_Lin line;
	int save_filter = wxGetApp().m_marked_list->m_filter;
	wxGetApp().m_marked_list->m_filter = MARKING_FILTER_LINE | MARKING_FILTER_ILINE;
	wxGetApp().PickObjects(_("Pick line to mirror about"), true);
	wxGetApp().m_marked_list->m_filter = save_filter;
	for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
	{
		HeeksObj* object = *It;
		if(object->GetType() == LineType)
		{
			line = ((HLine*)object)->GetLine();
			line_found = true;
		}
		else if(object->GetType() == ILineType)
		{
			line = ((HILine*)object)->GetLine();
			line_found = true;
		}
	}
	if(!line_found)return;

	// transform the objects
	gp_Trsf mat;
	mat.SetMirror(gp_Ax1(line.Location(), line.Direction()));
	double m[16];
	extract(mat, m);

	if(copy)
	{
		for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
		{
			HeeksObj* object = *It;
			HeeksObj* new_object = object->MakeACopy();
			object->Owner()->Add(new_object, NULL);
			new_object->ModifyByMatrix(m);
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		wxGetApp().Transform(selected_items, m);
	}
}

void TransformTools::Scale(bool copy)
{
	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to scale"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	// get number of copies
	int ncopies = 1;
	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	// pick "centre" position
	if(!wxGetApp().PickPosition(_("Click centre position to scale about"), centre))return;

	// enter scale factor
	double scale = 2.0;
	if(!wxGetApp().InputDouble(_("Enter scale factor"), _("scale factor"), scale))return;

	// transform the objects
	if(copy)
	{
		for(int i = 0; i<ncopies; i++)
		{
			gp_Trsf mat;
			mat.SetScale(make_point(centre), scale * (i+1));
			double m[16];
			extract(mat, m);
			for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
			{
				HeeksObj* object = *It;
				HeeksObj* new_object = object->MakeACopy();
				object->Owner()->Add(new_object, NULL);
				new_object->ModifyByMatrix(m);
			}
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		gp_Trsf mat;
		mat.SetScale(make_point(centre), scale);
		double m[16];
		extract(mat, m);
		wxGetApp().Transform(selected_items, m);
	}
}
<commit_msg>"copy rotate" was doing "move rotate", since new undo/redo. Some code had been accidentally removed.<commit_after>// TransformTools.cpp
/*
 * Copyright (c) 2009, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include "TransformTools.h"
#include "MarkedList.h"
#include "HLine.h"
#include "HILine.h"

static double from[3];
static double centre[3];

static void on_move_translate(const double* to)
{
	wxGetApp().m_drag_matrix.SetTranslationPart(gp_Vec(make_point(from), make_point(to)));
	wxGetApp().Repaint(true);
}

//static
void TransformTools::RemoveUncopyable()
{
	std::list<HeeksObj*> uncopyable_objects;
	for(std::list<HeeksObj*>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
	{
		HeeksObj* object = *It;
		if(!object->CanBeCopied())uncopyable_objects.push_back(object);
	}
	if(uncopyable_objects.size() > 0)wxGetApp().m_marked_list->Remove(uncopyable_objects, true);
}

//static
void TransformTools::Translate(bool copy)
{
	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to move"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	// get number of copies
	int ncopies = 1;
	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	// pick "from" position
	if(!wxGetApp().PickPosition(_("Click position to move from"), from))return;

	// pick "to" position
	wxGetApp().CreateTransformGLList(selected_items, false);
	wxGetApp().m_drag_matrix = gp_Trsf();
	if(!copy)
	{
		for(std::list<HeeksObj*>::const_iterator It = selected_items.begin(); It != selected_items.end(); It++){
			HeeksObj* object = *It;
			if(object->m_visible)wxGetApp().m_hidden_for_drag.push_back(object);
			object->m_visible = false;
		}
	}
	double to[3];
	wxGetApp().PickPosition(_("Click position to move to"), to, on_move_translate);
	if(!copy)
	{
		for(std::list<HeeksObj*>::iterator It = wxGetApp().m_hidden_for_drag.begin(); It != wxGetApp().m_hidden_for_drag.end(); It++)
		{
			HeeksObj* object = *It;
			object->m_visible = true;
		}
		wxGetApp().m_hidden_for_drag.clear();
	}
	wxGetApp().DestroyTransformGLList();

	// transform the objects
	if(copy)
	{
		for(int i = 0; i<ncopies; i++)
		{
			gp_Trsf mat;
			mat.SetTranslationPart(make_vector(make_point(from), make_point(to)) * (i + 1));
			double m[16];
			extract(mat, m);
			for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
			{
				HeeksObj* object = *It;
				HeeksObj* new_object = object->MakeACopy();
				object->Owner()->Add(new_object, NULL);
				new_object->ModifyByMatrix(m);
			}
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		gp_Trsf mat;
		mat.SetTranslationPart(make_vector(make_point(from), make_point(to)));
		double m[16];
		extract(mat, m);
		wxGetApp().Transform(selected_items, m);
	}
}

//static
void TransformTools::Rotate(bool copy)
{
	//rotation axis - Z axis by default
	gp_Dir axis_Dir = gp_Dir(0,0,1);
	gp_Pnt line_Pos = gp_Pnt(0,0,0);

	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to rotate"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	// get number of copies
	int ncopies = 1;
	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	if(wxGetApp().allow3DRotaion)
	{
		// pick a line to use as rotation axis
		bool line_found = false;
		gp_Lin line;
		int save_filter = wxGetApp().m_marked_list->m_filter;
		wxGetApp().m_marked_list->m_filter = MARKING_FILTER_LINE | MARKING_FILTER_ILINE;
		wxGetApp().PickObjects(_("Pick line for rotation axis"), true);
		wxGetApp().m_marked_list->m_filter = save_filter;
		for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
		{
			HeeksObj* object = *It;
			if(object->GetType() == LineType)
			{
				line = ((HLine*)object)->GetLine();
				line_found = true;
			}
			else if(object->GetType() == ILineType)
			{
				line = ((HILine*)object)->GetLine();
				line_found = true;
			}
		}
		if(!line_found)return;
		axis_Dir=line.Direction();
		line_Pos= line.Location();
	}
	else
	{
		// pick "centre" position
		if(!wxGetApp().PickPosition(_("Click centre position to rotate about"), centre))return;
		line_Pos.SetXYZ(gp_XYZ(centre[0],centre[1],centre[2]));
	}

	// enter angle
	double angle = 45.0;
	if(!wxGetApp().InputDouble(_("Enter angle to rotate by"), _("angle"), angle))return;

	// transform the objects
	if(copy)
	{
		for(int i = 0; i<ncopies; i++)
		{
			gp_Trsf mat;
			mat.SetRotation(gp_Ax1(line_Pos, axis_Dir), angle * Pi/180 * (i+1));
			double m[16];
			extract(mat, m);
			for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
			{
				HeeksObj* object = *It;
				HeeksObj* new_object = object->MakeACopy();
				object->Owner()->Add(new_object, NULL);
				object->ModifyByMatrix(m);
			}
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		gp_Trsf mat;
		mat.SetRotation(gp_Ax1(line_Pos, axis_Dir), angle * Pi/180);
		double m[16];
		extract(mat, m);
		wxGetApp().Transform(selected_items, m);
	}
}

//static
void TransformTools::Mirror(bool copy)
{
	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to mirror"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		int ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	// pick a line to mirror about
	bool line_found = false;
	gp_Lin line;
	int save_filter = wxGetApp().m_marked_list->m_filter;
	wxGetApp().m_marked_list->m_filter = MARKING_FILTER_LINE | MARKING_FILTER_ILINE;
	wxGetApp().PickObjects(_("Pick line to mirror about"), true);
	wxGetApp().m_marked_list->m_filter = save_filter;
	for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
	{
		HeeksObj* object = *It;
		if(object->GetType() == LineType)
		{
			line = ((HLine*)object)->GetLine();
			line_found = true;
		}
		else if(object->GetType() == ILineType)
		{
			line = ((HILine*)object)->GetLine();
			line_found = true;
		}
	}
	if(!line_found)return;

	// transform the objects
	gp_Trsf mat;
	mat.SetMirror(gp_Ax1(line.Location(), line.Direction()));
	double m[16];
	extract(mat, m);

	if(copy)
	{
		for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
		{
			HeeksObj* object = *It;
			HeeksObj* new_object = object->MakeACopy();
			object->Owner()->Add(new_object, NULL);
			new_object->ModifyByMatrix(m);
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		wxGetApp().Transform(selected_items, m);
	}
}

void TransformTools::Scale(bool copy)
{
	// pick items
	if(wxGetApp().m_marked_list->size() == 0){
		wxGetApp().PickObjects(_("Pick objects to scale"));
	}
	if(wxGetApp().m_marked_list->size() == 0)return;

	// get number of copies
	int ncopies = 1;
	if(copy)
	{
		// check for uncopyable objects
		RemoveUncopyable();
		if(wxGetApp().m_marked_list->size() == 0)return;

		// input "number of copies"
		double number_of_copies = 1.0;
		wxGetApp().InputDouble(_("Enter number of copies"), _("number of copies"), number_of_copies);
		ncopies = (int)(number_of_copies + 0.5);
		if(ncopies < 1)return;
	}

	// clear the selection
	std::list<HeeksObj *> selected_items = wxGetApp().m_marked_list->list();
	wxGetApp().m_marked_list->Clear(true);

	// pick "centre" position
	if(!wxGetApp().PickPosition(_("Click centre position to scale about"), centre))return;

	// enter scale factor
	double scale = 2.0;
	if(!wxGetApp().InputDouble(_("Enter scale factor"), _("scale factor"), scale))return;

	// transform the objects
	if(copy)
	{
		for(int i = 0; i<ncopies; i++)
		{
			gp_Trsf mat;
			mat.SetScale(make_point(centre), scale * (i+1));
			double m[16];
			extract(mat, m);
			for(std::list<HeeksObj*>::iterator It = selected_items.begin(); It != selected_items.end(); It++)
			{
				HeeksObj* object = *It;
				HeeksObj* new_object = object->MakeACopy();
				object->Owner()->Add(new_object, NULL);
				new_object->ModifyByMatrix(m);
			}
		}
		wxGetApp().m_marked_list->Clear(true);
	}
	else
	{
		gp_Trsf mat;
		mat.SetScale(make_point(centre), scale);
		double m[16];
		extract(mat, m);
		wxGetApp().Transform(selected_items, m);
	}
}
<|endoftext|>