<commit_before>#include "realgen.h"

// Constructors
RealGen::RealGen(int np, int nx, float *lb, float *ub) {
	Np = np;
	Nx = nx;
	LB = lb;
	UB = ub;
	if(Np != population.size()) {
		population.resize(Np,Nx);
		newPopulation.resize(Np,Nx);
	}
	// Initialize standars deviations or gaussian mutation
	sigma = new float[nx];
	for(int i=0; i<Nx; i++) {
		sigma[i] = options.mutation.gaussianScale;
	}
	// Tournment indices array
	tourIndex = NULL;
	maxGenerations = 100*Nx;

	// statistics
	minFitness = -1;
	iminFitness = -1;
	maxFitness = -1;
	imaxFitness = -1;
	meanFitness = -1;
}

RealGen::RealGen(int np, int nx, float *lb, float *ub, GAOptions opt) : RealGen(np, nx, lb, ub) {
	setOptions(opt);

	if(options.verbose) {
		checkOptions();
	}
}

// Destructor
RealGen::~RealGen() {
	if(tourIndex) {
		delete []tourIndex;
	}
	delete [] sigma;
}

void RealGen::setOptions(GAOptions opt) {
	options = opt;
	if (tourIndex) {
		delete []tourIndex;
		tourIndex = new int[options.selection.tournmentP];
	} else {
		tourIndex = new int[options.selection.tournmentP];
	}
}

void RealGen::checkOptions() {
	cout << "------ checkOptions ------" << endl << endl;
	switch (options.selection.type) {
		case ROULETTE_WHEEL_SELECTION:
			cout << "-> Selection: ROULETTE_WHEEL_SELECTION" << endl;
		break;
		case TOURNMENT_SELECTION:
			if(options.selection.tournmentP >= 2 && options.selection.tournmentP <= Np) {
				cout << "-> Selection: TOURNMENT_SELECTION : tournmentP = " << options.selection.tournmentP << endl;
			} else {
				cerr << "ERROR: options.selection.tournmentP must be an unsigned number between 2 and Np" << endl;
				exit(-1);
			}
		break;
	}

	if (options.selection.elitismFactor >= 0.0 && options.selection.elitismFactor <= 1.0) {
		cout << "-> Elitism Factor: " << options.selection.elitismFactor << endl;
	} else {
		cerr << "ERROR: options.selection.elitismFactor must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}

	if (options.selection.sorting) {
		cout << "-> Population Sorting : true" << endl;
	} else {
		cout << "-> Population Sorting : false" << endl;
	}

	cout << endl;

	switch (options.crossover.type) {
		case UNIFORM_CROSSOVER:
			cout << "-> Crossover: UNIFORM_CROSSOVER" << endl;
		break;
		case FIXED_CROSSOVER:
			if(options.crossover.fixedIndex >= 0 && options.crossover.fixedIndex < Np) {
				cout << "-> Crossover: FIXED_CROSSOVER : fixedIndex = " << options.crossover.fixedIndex << endl;
			} else {
				cerr << "ERROR: options.crossover.fixedIndex must be a number between 0 and Nx" << endl;
				exit(-1);
			}

		break;
		case SINGLE_POINT_CROSSOVER:
			cout << "-> Crossover: SINGLE_POINT_CROSSOVER" << endl;
		break;
		case TWO_POINT_CROSSOVER:
			cout << "-> Crossover: TWO_POINT_CROSSOVER" << endl;
		break;
	}

	cout << endl;

	switch (options.mutation.type) {
		case UNIFORM_MUTATION:
			if (options.mutation.uniformPerc >= 0.0 && options.mutation.uniformPerc <= 1.0) {
				cout << "-> Mutation: UNIFORM_MUTATION : uniformPerc = " << options.mutation.uniformPerc << endl;
			} else {
				cerr << "ERROR: options.selection.uniformPerc must be a number between 0.0 and 1.0" << endl;
				exit(-1);
			}

		break;
		case GAUSSIAN_MUTATION:
			cout << "-> Mutation: GAUSSIAN_MUTATION : gaussianScale = " << options.mutation.gaussianScale << endl;
			cout << "-> Mutation: GAUSSIAN_MUTATION : gaussianShrink = " << options.mutation.gaussianShrink << endl;
		break;
	}

	if (options.mutation.mutationRate >= 0.0 && options.mutation.mutationRate <= 1.0) {
		cout << "-> MutationRate = " << options.mutation.mutationRate << endl;
	} else {
		cerr << "ERROR: options.mutation.mutationRate must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}
	cout << endl;
}

// ========================================= Setter ======================================
void RealGen::setFitnessFunction(double (*f)(RealGenotype &, void *), void *par) {
	fitnessFcn = f;
	fitnessPar = par;
}

void RealGen::setSorting(bool value) {
	options.selection.sorting = value;
}

void RealGen::setPopulationSize(int n) {
	Np = n;
	population.clear();
	newPopulation.clear();
	if(Np != population.size()) {
		population.resize(Np,Nx);
	}
}

void RealGen::setMutationRate(float value) {
	if(value >= 0 && value <= 1) {
		options.mutation.mutationRate = value;
	} else {
		cerr << "ERROR: options.mutation.mutationRate must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}
}

void RealGen::setElitismFactor(float value) {
	if(value >= 0.0 && value <= 1.0) {
		options.selection.elitismFactor = value;
	} else {
		cerr << "ERROR: options.selection.elitismFactor must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}
}

void RealGen::setMaxGenerations(int maxG) {
	maxGenerations = maxG;
}

// ========================================= Getter ======================================

int RealGen::getGeneration() {
	return generation;
}

double RealGen::evalFitness(RealGenotype &x) {
	RealGenotype g(x);
	g.bound(LB, UB);
	return fitnessFcn(g, fitnessPar);
}

double RealGen::getMeanFitness() {
	double meanF = 0.0;
	for(int i=0; i<Np; i++) {
		meanF += population[i].fitness;
	}
	return meanF / (double)Np;
}

RealGenotype RealGen::getBestChromosome() {
	RealGenotype best;
	best = population[iminFitness];
	best.bound(LB, UB);
	return best;
}

double RealGen::getMinFitness() {
	return minFitness;
}

double RealGen::diversity() {  // TODO
	/*
	// Calculate centroid
	for(size_t j=0; j<Nx; j++) {
		double c = 0.0;
		for(int i=0; i<Np; i++) {
			c += population[i].gene[j];
		}
		c /= Np;
	}*/
}

void RealGen::evalMinFitness(){
	minFitness = population[0].fitness;
	iminFitness = 0;
	for(int i=0; i<Np; i++) {
		if(population[i].fitness < minFitness) {
			minFitness = population[i].fitness;
			iminFitness = i;
		}
	}
}

void RealGen::evalMaxFitness(){
	maxFitness = population[0].fitness;
	imaxFitness = 0;
	for(int i=0; i<Np; i++) {
		if(population[i].fitness > imaxFitness) {
			imaxFitness = population[i].fitness;
			imaxFitness = i;
		}
	}
}

string RealGen::populationToString() {
	std::ostringstream os;
	RealGenotype x_scaled;
	os << "============== Generation: " << generation << " ===================" << endl;
	for(int i=0; i<Np; i++) {
		x_scaled = population[i];
		x_scaled.bound(LB, UB);
		os << "[" << (i+1) << "] : "<< x_scaled.toString() << " -> Fitness " << x_scaled.fitness << endl;
	}
	return os.str();
}

void RealGen::evolve() {
	RealGenotype offspring(Nx);

	int index1, index2;
	size_t k=0;

	if(options.selection.type == ROULETTE_WHEEL_SELECTION) {
		sumFitnessRoulette();
	}

	if(options.selection.sorting) {
		while(k< options.selection.elitismFactor*Np) {
			newPopulation[k] = population[k];
			++k;
		}
	} else {
		// Keep only the best one
		newPopulation[k] = population[iminFitness];
		++k;
	}

	while(k < Np) {
		// Selection
		switch(options.selection.type) {
			case ROULETTE_WHEEL_SELECTION:
				rouletteWheelSelection(index1, index2);
			break;
			case TOURNMENT_SELECTION:
				tournmentSelection(options.selection.tournmentP, index1, index2);
			break;
		}

		// Crossover
		crossoverUniform(index1, index2, offspring);
		// Mutation
		switch(options.mutation.type) {
			case UNIFORM_MUTATION:
				uniformMutate(offspring, options.mutation.uniformPerc);
			break;
			case GAUSSIAN_MUTATION:
				gaussianLocalMutate(offspring);
			break;
		}

		offspring.fitness  = evalFitness(offspring);
		newPopulation[k] = offspring;
		++k;
	}

	if(options.selection.sorting) {
		partial_sort(newPopulation.begin(), newPopulation.begin()+int(options.selection.elitismFactor*Np), newPopulation.end());
	}

	if(options.mutation.type == GAUSSIAN_MUTATION) {
		for(int i=0; i<Nx; i++) {
			sigma[i] = options.mutation.gaussianScale*(1.0 - options.mutation.gaussianShrink*((float)generation/(float)maxGenerations))*0.1;
		}
	}

	evalMinFitness();
	evalMaxFitness();
	meanFitness = getMeanFitness();
	newPopulation.swap(population);
	generation++;
}

// ===================================== Init function =============================
void RealGen::initRandom() {
	generation=0;
	for(int i=0; i<Np; i++) {
		population[i].uniformRandom();
		population[i].fitness = evalFitness(population[i]);
	}
	if(options.selection.sorting) {
		sort(population.begin(), population.end());
	}

	// evaluate statistics
	evalMinFitness();
	evalMaxFitness();
	meanFitness = getMeanFitness();
}

void RealGen::evalPopulationFitness() {
	generation=0;
	for(int i=0; i<Np; i++) {
		population[i].fitness = evalFitness(population[i]);
	}
	if(options.selection.sorting) {
		partial_sort(population.begin(), population.begin()+int(options.selection.elitismFactor*Np), population.end());
	}
}

// ================= Selection =================================
void RealGen::rouletteWheelSelection(int &index1, int &index2) {
	rouletteWheel(index1, sumFitnessR*stat.uniformRand());
	rouletteWheel(index2, sumFitnessR*stat.uniformRand());
	if(index1 == index2) {
		if(index1 != Np-1)
			index2 = index1 + 1;
		else
			index2 = index1 - 1;
	}
}

double RealGen::sumFitnessRoulette() {
	double s=0.0;
	for(int i=0; i<Np; i++) {
		s += population[i].fitness;
	}
	sumFitnessR = Np*maxFitness-s;
}

void RealGen::rouletteWheel(int &index, float stop) {
	float sumP = 0.0;
	index = 0;
	for(int i=0; i<Np; i++) {
		sumP += (maxFitness-population[i].fitness);
		if(sumP > stop) {
			index = i;
			break;
		}
	}
}

void RealGen::tournmentSelection(int p, int &index1, int &index2) {
	tournmentSelect(p, index1);
	tournmentSelect(p, index2);
	if(index1 == index2) {
		if(index1 != Np-1)
			index2 = index1 + 1;
		else
			index2 = index1 - 1;
	}
}

void RealGen::tournmentSelect(int p, int &iMin) {
	iMin = 0;
	double fMin = population[0].fitness;
	for(int i=0; i<p; i++) {
		tourIndex[i] = stat.uniformIndex(Np);
	}
	for(int i=0; i<p; i++) {
		double f=population[tourIndex[i]].fitness;
		if(f < fMin) {
			fMin = f;
			iMin = tourIndex[i];
		}
	}
}
//==================================== Crossover ==================
void RealGen::crossoverUniform(int index1, int index2, RealGenotype &c) {
	for(size_t i=0; i<Nx; i++) {
		if(stat.uniformRand()<0.5) {
			c.gene[i] = population[index1].gene[i];
		} else {
			c.gene[i] = population[index2].gene[i];
		}
	}
}

void RealGen::crossoverFixed(int index1, int index2, RealGenotype &c, int n) {
	for(size_t i=0; i<n; i++) {
		c.gene[i] = population[index1].gene[i];
	}
	for(size_t i=n; i<Nx; i++) {
		c.gene[i] = population[index2].gene[i];
	}
}
//===================================== Mutation ======================
void RealGen::uniformMutate(RealGenotype &g, float perc) {
	for (size_t i=0; i<Nx; i++) {
		if(stat.uniformRand() < options.mutation.mutationRate) {
			g.uniformLocalRandom(i, perc);
		}
	}
}

void RealGen::gaussianLocalMutate(RealGenotype &g) {
	for (size_t i=0; i<Nx; i++) {
		if(stat.uniformRand() < options.mutation.mutationRate) {
			g.gaussianLocalRandom(i, sigma[i]);
		}
	}
}
<commit_msg>Fixed initmutate bug<commit_after>#include "realgen.h"

// Constructors
RealGen::RealGen(int np, int nx, float *lb, float *ub) {
	Np = np;
	Nx = nx;
	LB = lb;
	UB = ub;
	if(Np != population.size()) {
		population.resize(Np,Nx);
		newPopulation.resize(Np,Nx);
	}
	// Initialize standars deviations or gaussian mutation
	sigma = new float[nx];
	for(int i=0; i<Nx; i++) {
		sigma[i] = options.mutation.gaussianScale;
	}
	// Tournment indices array
	tourIndex = NULL;
	maxGenerations = 100*Nx;

	// statistics
	minFitness = -1;
	iminFitness = -1;
	maxFitness = -1;
	imaxFitness = -1;
	meanFitness = -1;
}

RealGen::RealGen(int np, int nx, float *lb, float *ub, GAOptions opt) : RealGen(np, nx, lb, ub) {
	setOptions(opt);

	if(options.verbose) {
		checkOptions();
	}
}

// Destructor
RealGen::~RealGen() {
	if(tourIndex) {
		delete []tourIndex;
	}
	delete [] sigma;
}

void RealGen::setOptions(GAOptions opt) {
	options = opt;
	if (tourIndex) {
		delete []tourIndex;
		tourIndex = new int[options.selection.tournmentP];
	} else {
		tourIndex = new int[options.selection.tournmentP];
	}
}

void RealGen::checkOptions() {
	cout << "------ checkOptions ------" << endl << endl;
	switch (options.selection.type) {
		case ROULETTE_WHEEL_SELECTION:
			cout << "-> Selection: ROULETTE_WHEEL_SELECTION" << endl;
		break;
		case TOURNMENT_SELECTION:
			if(options.selection.tournmentP >= 2 && options.selection.tournmentP <= Np) {
				cout << "-> Selection: TOURNMENT_SELECTION : tournmentP = " << options.selection.tournmentP << endl;
			} else {
				cerr << "ERROR: options.selection.tournmentP must be an unsigned number between 2 and Np" << endl;
				exit(-1);
			}
		break;
	}

	if (options.selection.elitismFactor >= 0.0 && options.selection.elitismFactor <= 1.0) {
		cout << "-> Elitism Factor: " << options.selection.elitismFactor << endl;
	} else {
		cerr << "ERROR: options.selection.elitismFactor must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}

	if (options.selection.sorting) {
		cout << "-> Population Sorting : true" << endl;
	} else {
		cout << "-> Population Sorting : false" << endl;
	}

	cout << endl;

	switch (options.crossover.type) {
		case UNIFORM_CROSSOVER:
			cout << "-> Crossover: UNIFORM_CROSSOVER" << endl;
		break;
		case FIXED_CROSSOVER:
			if(options.crossover.fixedIndex >= 0 && options.crossover.fixedIndex < Np) {
				cout << "-> Crossover: FIXED_CROSSOVER : fixedIndex = " << options.crossover.fixedIndex << endl;
			} else {
				cerr << "ERROR: options.crossover.fixedIndex must be a number between 0 and Nx" << endl;
				exit(-1);
			}

		break;
		case SINGLE_POINT_CROSSOVER:
			cout << "-> Crossover: SINGLE_POINT_CROSSOVER" << endl;
		break;
		case TWO_POINT_CROSSOVER:
			cout << "-> Crossover: TWO_POINT_CROSSOVER" << endl;
		break;
	}

	cout << endl;

	switch (options.mutation.type) {
		case UNIFORM_MUTATION:
			if (options.mutation.uniformPerc >= 0.0 && options.mutation.uniformPerc <= 1.0) {
				cout << "-> Mutation: UNIFORM_MUTATION : uniformPerc = " << options.mutation.uniformPerc << endl;
			} else {
				cerr << "ERROR: options.selection.uniformPerc must be a number between 0.0 and 1.0" << endl;
				exit(-1);
			}

		break;
		case GAUSSIAN_MUTATION:
			cout << "-> Mutation: GAUSSIAN_MUTATION : gaussianScale = " << options.mutation.gaussianScale << endl;
			cout << "-> Mutation: GAUSSIAN_MUTATION : gaussianShrink = " << options.mutation.gaussianShrink << endl;
		break;
	}

	if (options.mutation.mutationRate >= 0.0 && options.mutation.mutationRate <= 1.0) {
		cout << "-> MutationRate = " << options.mutation.mutationRate << endl;
	} else {
		cerr << "ERROR: options.mutation.mutationRate must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}
	cout << endl;
}

// ========================================= Setter ======================================
void RealGen::setFitnessFunction(double (*f)(RealGenotype &, void *), void *par) {
	fitnessFcn = f;
	fitnessPar = par;
}

void RealGen::setSorting(bool value) {
	options.selection.sorting = value;
}

void RealGen::setPopulationSize(int n) {
	Np = n;
	population.clear();
	newPopulation.clear();
	if(Np != population.size()) {
		population.resize(Np,Nx);
	}
}

void RealGen::setMutationRate(float value) {
	if(value >= 0 && value <= 1) {
		options.mutation.mutationRate = value;
	} else {
		cerr << "ERROR: options.mutation.mutationRate must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}
}

void RealGen::setElitismFactor(float value) {
	if(value >= 0.0 && value <= 1.0) {
		options.selection.elitismFactor = value;
	} else {
		cerr << "ERROR: options.selection.elitismFactor must be a number between 0.0 and 1.0" << endl;
		exit(-1);
	}
}

void RealGen::setMaxGenerations(int maxG) {
	maxGenerations = maxG;
}

// ========================================= Getter ======================================

int RealGen::getGeneration() {
	return generation;
}

double RealGen::evalFitness(RealGenotype &x) {
	RealGenotype g(x);
	g.bound(LB, UB);
	return fitnessFcn(g, fitnessPar);
}

double RealGen::getMeanFitness() {
	double meanF = 0.0;
	for(int i=0; i<Np; i++) {
		meanF += population[i].fitness;
	}
	return meanF / (double)Np;
}

RealGenotype RealGen::getBestChromosome() {
	RealGenotype best;
	best = population[iminFitness];
	best.bound(LB, UB);
	return best;
}

double RealGen::getMinFitness() {
	return minFitness;
}

double RealGen::diversity() {  // TODO
	double I = 0.0;
	// Compute the centroid
	for(size_t j=0; j<Nx; j++) {
		double ci = 0.0;
		for(int i=0; i<Np; i++) {
			ci += population[i].gene[j];
		}
		ci /= Np;
		for(int i=0; i<Np; i++) {
			double dx = population[i].gene[j] - ci;
			I += dx*dx;
		}
	}
	return I;
}

void RealGen::evalMinFitness(){
	minFitness = population[0].fitness;
	iminFitness = 0;
	for(int i=0; i<Np; i++) {
		if(population[i].fitness < minFitness) {
			minFitness = population[i].fitness;
			iminFitness = i;
		}
	}
}

void RealGen::evalMaxFitness(){
	maxFitness = population[0].fitness;
	imaxFitness = 0;
	for(int i=0; i<Np; i++) {
		if(population[i].fitness > imaxFitness) {
			imaxFitness = population[i].fitness;
			imaxFitness = i;
		}
	}
}

string RealGen::populationToString() {
	std::ostringstream os;
	RealGenotype x_scaled;
	os << "============== Generation: " << generation << " ===================" << endl;
	for(int i=0; i<Np; i++) {
		x_scaled = population[i];
		x_scaled.bound(LB, UB);
		os << "[" << (i+1) << "] : "<< x_scaled.toString() << " -> Fitness " << x_scaled.fitness << endl;
	}
	return os.str();
}

void RealGen::evolve() {
	RealGenotype offspring(Nx);

	int index1, index2;
	size_t k=0;

	if(options.selection.type == ROULETTE_WHEEL_SELECTION) {
		sumFitnessRoulette();
	}

	if(options.selection.sorting) {
		while(k< options.selection.elitismFactor*Np) {
			newPopulation[k] = population[k];
			++k;
		}
	} else {
		// Keep only the best one
		newPopulation[k] = population[iminFitness];
		++k;
	}

	while(k < Np) {
		// Selection
		switch(options.selection.type) {
			case ROULETTE_WHEEL_SELECTION:
				rouletteWheelSelection(index1, index2);
			break;
			case TOURNMENT_SELECTION:
				tournmentSelection(options.selection.tournmentP, index1, index2);
			break;
		}

		// Crossover
		crossoverUniform(index1, index2, offspring);
		// Mutation
		switch(options.mutation.type) {
			case UNIFORM_MUTATION:
				uniformMutate(offspring, options.mutation.uniformPerc);
			break;
			case GAUSSIAN_MUTATION:
				gaussianLocalMutate(offspring);
			break;
		}

		offspring.fitness  = evalFitness(offspring);
		newPopulation[k] = offspring;
		++k;
	}

	if(options.selection.sorting) {
		partial_sort(newPopulation.begin(), newPopulation.begin()+int(options.selection.elitismFactor*Np), newPopulation.end());
	}

	if(options.mutation.type == GAUSSIAN_MUTATION) {
		for(int i=0; i<Nx; i++) {
			sigma[i] = options.mutation.gaussianScale*(1.0 - options.mutation.gaussianShrink*((float)generation/(float)maxGenerations))*0.1;
		}
	}

	evalMinFitness();
	evalMaxFitness();
	meanFitness = getMeanFitness();
	newPopulation.swap(population);
	generation++;
}

// ===================================== Init function =============================
void RealGen::initRandom() {
	generation=0;
	for(int i=0; i<Np; i++) {
		population[i].uniformRandom();
		population[i].fitness = evalFitness(population[i]);
	}
	if(options.selection.sorting) {
		sort(population.begin(), population.end());
	}

	// evaluate statistics
	evalMinFitness();
	evalMaxFitness();
	meanFitness = getMeanFitness();
}

void RealGen::evalPopulationFitness() {
	generation=0;
	for(int i=0; i<Np; i++) {
		population[i].fitness = evalFitness(population[i]);
	}
	if(options.selection.sorting) {
		partial_sort(population.begin(), population.begin()+int(options.selection.elitismFactor*Np), population.end());
	}
}

// ================= Selection =================================
void RealGen::rouletteWheelSelection(int &index1, int &index2) {
	rouletteWheel(index1, sumFitnessR*stat.uniformRand());
	rouletteWheel(index2, sumFitnessR*stat.uniformRand());
	if(index1 == index2) {
		if(index1 != Np-1)
			index2 = index1 + 1;
		else
			index2 = index1 - 1;
	}
}

double RealGen::sumFitnessRoulette() {
	double s=0.0;
	for(int i=0; i<Np; i++) {
		s += population[i].fitness;
	}
	sumFitnessR = Np*maxFitness-s;
}

void RealGen::rouletteWheel(int &index, float stop) {
	float sumP = 0.0;
	index = 0;
	for(int i=0; i<Np; i++) {
		sumP += (maxFitness-population[i].fitness);
		if(sumP > stop) {
			index = i;
			break;
		}
	}
}

void RealGen::tournmentSelection(int p, int &index1, int &index2) {
	tournmentSelect(p, index1);
	tournmentSelect(p, index2);
	if(index1 == index2) {
		if(index1 != Np-1)
			index2 = index1 + 1;
		else
			index2 = index1 - 1;
	}
}

void RealGen::tournmentSelect(int p, int &iMin) {
	iMin = 0;
	double fMin = population[0].fitness;
	for(int i=0; i<p; i++) {
		tourIndex[i] = stat.uniformIndex(Np);
	}
	for(int i=0; i<p; i++) {
		double f=population[tourIndex[i]].fitness;
		if(f < fMin) {
			fMin = f;
			iMin = tourIndex[i];
		}
	}
}
//==================================== Crossover ==================
void RealGen::crossoverUniform(int index1, int index2, RealGenotype &c) {
	for(size_t i=0; i<Nx; i++) {
		if(stat.uniformRand()<0.5) {
			c.gene[i] = population[index1].gene[i];
		} else {
			c.gene[i] = population[index2].gene[i];
		}
	}
}

void RealGen::crossoverFixed(int index1, int index2, RealGenotype &c, int n) {
	for(size_t i=0; i<n; i++) {
		c.gene[i] = population[index1].gene[i];
	}
	for(size_t i=n; i<Nx; i++) {
		c.gene[i] = population[index2].gene[i];
	}
}
//===================================== Mutation ======================
void RealGen::uniformMutate(RealGenotype &g, float perc) {
	for (size_t i=0; i<Nx; i++) {
		if(stat.uniformRand() < options.mutation.mutationRate) {
			g.uniformLocalRandom(i, perc);
		}
	}
}

void RealGen::gaussianLocalMutate(RealGenotype &g) {
	for (size_t i=0; i<Nx; i++) {
		if(stat.uniformRand() < options.mutation.mutationRate) {
			g.gaussianLocalRandom(i, sigma[i]);
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Also need to set aura::Window title<commit_after><|endoftext|>


<commit_before>// Copyright 2015-2016 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <QGuiApplication>
#include <QQuickView>
#include <QDir>
#include <QQmlEngine>
#include <QSurfaceFormat>

int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
    if (QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR > 6)
    {
        // Workaround for Qt versions greater than 5.6
        // Force to OpenGL ES 3
        QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
        fmt.setVersion(3, 0);
        QSurfaceFormat::setDefaultFormat(fmt);
    }
#endif

    QGuiApplication app(argc, argv);

#ifdef Q_OS_WIN
    // Force usage of OpenGL ES through ANGLE on Windows
    QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif

    // Intialize application view
    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);

    // Add the import Path
    view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));

    // Set the source
    view.setSource(QUrl("qrc:/Samples/DisplayInformation/GraphicsOverlay_DictionaryRenderer_3D/GraphicsOverlay_DictionaryRenderer_3D.qml"));

    view.show();

    return app.exec();
}
<commit_msg>fix GraphicsOverlay_DictRend_3D source path<commit_after>// Copyright 2015-2016 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <QGuiApplication>
#include <QQuickView>
#include <QDir>
#include <QQmlEngine>
#include <QSurfaceFormat>

int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
    if (QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR > 6)
    {
        // Workaround for Qt versions greater than 5.6
        // Force to OpenGL ES 3
        QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
        fmt.setVersion(3, 0);
        QSurfaceFormat::setDefaultFormat(fmt);
    }
#endif

    QGuiApplication app(argc, argv);

#ifdef Q_OS_WIN
    // Force usage of OpenGL ES through ANGLE on Windows
    QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif

    // Intialize application view
    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);

    // Add the import Path
    view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));

    // Set the source
    view.setSource(QUrl("qrc:/Samples/Display Information/GraphicsOverlay_DictionaryRenderer_3D/GraphicsOverlay_DictionaryRenderer_3D.qml"));

    view.show();

    return app.exec();
}
<|endoftext|>


<commit_before>#include "LongestCommonSubsequence.hpp"
#include <cassert>

#define TEST_MAX 1024

struct Test {
    int a[MAX];
    int b[MAX];
    int n;
    int result;
} test_cases[] = {
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 1, 3, 5, 7, 9, 11, 13, 15, 17 },
        10, 5
    },
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },
        10, 5
    },
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
        10, 1
    },
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 1, 2, 8, 7, 4, 3, 4, 3, 2, 1 },
        10, 4
    },
};

int main()
{
    int count = sizeof(test_cases) / sizeof(Test);
    for (int i = 0; i < count; i++) {
        Test & t = test_cases[i];
        int r = LongestCommonSubsequence(t.a, t.b, t.n);
        assert(r == t.result);
    }

    return 0;
}
<commit_msg>test LongestCommonSubsequence<commit_after>#include "LongestCommonSubsequence.hpp"
#include <cassert>
#include <iostream>
using namespace std;

#define TEST_MAX 1024

struct Test {
    int a[MAX];
    int b[MAX];
    int n;
    int result;
} test_cases[] = {
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 1, 3, 5, 7, 9, 11, 13, 15, 17 },
        10, 5
    },
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },
        10, 5
    },
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
        10, 1
    },
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        { 0, 1, 2, 8, 7, 4, 3, 4, 3, 2, 1 },
        10, 4
    },
    {
        {0, 1, 1, 5, 4, 9, 7, 31, -13, 34, 21, 17},
        {0, 5, 6, 11, 4, 9, 0, 34, 21, -13, 17, 3},
        11, 6
    },
    {
        { 0, 12, 142, -5, 14, 15, 45, 42, 61, 41, 0, 42, 42, -5, 14, 215, 45, -42, 1, 31 },
        { 0, 42, 42, -5, 14, 215, 45, -42, 1, 31, 0, 12, 142, -5, 14, 15, 45, 42, 61, 41 },
        19, 9
    },
};

int main()
{
    int count = sizeof(test_cases) / sizeof(Test);
    for (int i = 0; i < count; i++) {
        Test & t = test_cases[i];
        int r = LongestCommonSubsequence(t.a, t.b, t.n);
        cout << i << "," << r << endl;
        assert(r == t.result);
    }

    return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

 Program:   Medical Imaging & Interaction Toolkit
 Language:  C++
 Date:      $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
 Version:   $Revision: 21975 $

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>

// Qmitk
#include "QmitkFiberBundleDeveloperView.h"
#include <QmitkStdMultiWidget.h>

// Qt

// VTK
#include <vtkPointSource.h>

const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{

}

// Destructor
QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView()
{

}

void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent )
{
  // build up qt view, unless already done in QtDesigner, etc.
  if ( !m_Controls )
  {
    // create GUI widgets from the Qt Designer's .ui file
    m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls;
    m_Controls->setupUi( parent );

    connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) );

  }

  //  Checkpoint for fiber ORIENTATION
  if ( m_DirectionRadios.empty() )
  {
    m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom);
    m_DirectionRadios.insert(1, m_Controls->radioButton_directionX);
    m_DirectionRadios.insert(2, m_Controls->radioButton_directionY);
    m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ);
  }

}

void QmitkFiberBundleDeveloperView::DoGenerateFibers()
{

  // GET SELECTED FIBER DIRECTION
  QString fibDirection; //stores the object_name of selected radiobutton
  QVector<QRadioButton*>::const_iterator i;
  for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
  {
    QRadioButton* rdbtn = *i;
    if (rdbtn->isChecked())
      fibDirection = rdbtn->objectName();
  }

  vtkSmartPointer<vtkPolyData> FiberPD; // FiberPD stores the generated PolyData
  if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
    //    build polydata with random lines and fibers
   FiberPD = GenerateVtkFibersRandom();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) {
    //    build polydata with XDirection fibers
    FiberPD = GenerateVtkFibersDirectionX();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) {
    //    build polydata with YDirection fibers
    FiberPD = GenerateVtkFibersDirectionY();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) {
    //    build polydata with ZDirection fibers
    FiberPD = GenerateVtkFibersDirectionZ();

  }

}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom()
{
  vtkSmartPointer<vtkPolyData> PDRandom = vtkSmartPointer<vtkPolyData>::New();
  vtkSmartPointer<vtkPointSource> randomPoints = vtkSmartPointer<vtkPointSource>::New();
  randomPoints->SetCenter(0.0, 0.0, 0.0);
  randomPoints->SetNumberOfPoints(m_Controls->boxFiberNumbers->value() * m_Controls->boxPointsPerFiber->value());
  randomPoints->SetRadius(m_Controls->boxPointsPerFiber->value());
  randomPoints->Update();

  // Set vtkPolyLines
  // iterate through points
  for (int i=0; i<randomPoints->GetNumberOfPoints(); ++i)
  {

  }

  return PDRandom;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX()
{
  vtkSmartPointer<vtkPolyData> PDX = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDX;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY()
{
  vtkSmartPointer<vtkPolyData> PDY = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDY;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ()
{
  vtkSmartPointer<vtkPolyData> PDZ = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDZ;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
  m_MultiWidget = &stdMultiWidget;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable()
{
  m_MultiWidget = NULL;
}

/* OnSelectionChanged is registered to SelectionService, therefore no need to
 implement SelectionService Listener explicitly */

void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{

}

void QmitkFiberBundleDeveloperView::Activated()
{

  MITK_INFO << "FB OPerations ACTIVATED()";

}

<commit_msg>interim commit<commit_after>/*=========================================================================

 Program:   Medical Imaging & Interaction Toolkit
 Language:  C++
 Date:      $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
 Version:   $Revision: 21975 $

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>

// Qmitk
#include "QmitkFiberBundleDeveloperView.h"
#include <QmitkStdMultiWidget.h>

// Qt

// VTK
#include <vtkPointSource.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>

const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{

}

// Destructor
QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView()
{

}

void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent )
{
  // build up qt view, unless already done in QtDesigner, etc.
  if ( !m_Controls )
  {
    // create GUI widgets from the Qt Designer's .ui file
    m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls;
    m_Controls->setupUi( parent );

    connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) );

  }

  //  Checkpoint for fiber ORIENTATION
  if ( m_DirectionRadios.empty() )
  {
    m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom);
    m_DirectionRadios.insert(1, m_Controls->radioButton_directionX);
    m_DirectionRadios.insert(2, m_Controls->radioButton_directionY);
    m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ);
  }

}

void QmitkFiberBundleDeveloperView::DoGenerateFibers()
{

  // GET SELECTED FIBER DIRECTION
  QString fibDirection; //stores the object_name of selected radiobutton
  QVector<QRadioButton*>::const_iterator i;
  for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
  {
    QRadioButton* rdbtn = *i;
    if (rdbtn->isChecked())
      fibDirection = rdbtn->objectName();
  }

  vtkSmartPointer<vtkPolyData> FiberPD; // FiberPD stores the generated PolyData
  if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
    //    build polydata with random lines and fibers
   FiberPD = GenerateVtkFibersRandom();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) {
    //    build polydata with XDirection fibers
    FiberPD = GenerateVtkFibersDirectionX();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) {
    //    build polydata with YDirection fibers
    FiberPD = GenerateVtkFibersDirectionY();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) {
    //    build polydata with ZDirection fibers
    FiberPD = GenerateVtkFibersDirectionZ();

  }

}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom()
{

  int numOfFibers = m_Controls->boxFiberNumbers->value();
  int pntsPrFiber = m_Controls->boxPointsPerFiber->value();
  int numOfPoints = numOfFibers * pntsPrFiber;

  vtkSmartPointer<vtkPolyData> PDRandom = vtkSmartPointer<vtkPolyData>::New();
  vtkSmartPointer<vtkPointSource> randomPoints = vtkSmartPointer<vtkPointSource>::New();
  randomPoints->SetCenter(0.0, 0.0, 0.0);
  randomPoints->SetNumberOfPoints(numOfPoints);
  randomPoints->SetRadius(pntsPrFiber);
  randomPoints->Update();

  // Set vtkPolyLines
  //create new cell
  // iterate through points
  int lineId = 0;
  for (int i=0; i<numOfPoints; i+=pntsPrFiber) // e.g. i eqals 0, 50, 100, etc.
  {
    if (i%m_Controls->boxFiberNumbers->value() == 0)
    {
      MITK_INFO << "====== Start New LINE: =======" << ++lineId;
      vtkSmartPointer<vtkPolyLine> newFiber = vtkSmartPointer<vtkPolyLine>::New();

      //fill the fiber with points

    } else {
      MITK_INFO << "LOGIC ERROR IN CREATING FIBERS...Check Values in QmitkFiberBundleDeveloperView.cpp";
    }

  }

  return PDRandom;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX()
{
  vtkSmartPointer<vtkPolyData> PDX = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDX;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY()
{
  vtkSmartPointer<vtkPolyData> PDY = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDY;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ()
{
  vtkSmartPointer<vtkPolyData> PDZ = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDZ;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
  m_MultiWidget = &stdMultiWidget;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable()
{
  m_MultiWidget = NULL;
}

/* OnSelectionChanged is registered to SelectionService, therefore no need to
 implement SelectionService Listener explicitly */

void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{

}

void QmitkFiberBundleDeveloperView::Activated()
{

  MITK_INFO << "FB OPerations ACTIVATED()";

}

<|endoftext|>


<commit_before>/*
	File: qltconverters.hpp

	class QltConverters - содержит набор статических методов для преобразования
	типов контейнеров данных.

*/

#include <QStringList>
#include <QString>

class QltConverters
{

public:

  // Преобразует числовые контейнеры (такие как: QVector<double>, QVector<int>, QList<double>, QList<int>,
  // std::vector<double>,std::vector<int> и т.д.) в QStringList.
  template <typename TContainer>
  static QStringList toQStringList(TContainer inContainer)
  {
    QStringList outContainer;

    for (int index=0; index < inContainer.size(); ++index)
      outContainer.append(QString::number(inContainer.at(index)));

    return outContainer;
  };

};

<commit_msg>minor fix, comparison between signed and unsigned integer<commit_after>/*
	File: qltconverters.hpp

	class QltConverters - содержит набор статических методов для преобразования
	типов контейнеров данных.

*/

#include <QStringList>
#include <QString>

class QltConverters
{

public:

  // Преобразует числовые контейнеры (такие как: QVector<double>, QVector<int>, QList<double>, QList<int>,
  // std::vector<double>,std::vector<int> и т.д.) в QStringList.
  template <typename TContainer>
  static QStringList toQStringList(TContainer inContainer)
  {
    QStringList outContainer;

    for (size_t index=0; index < inContainer.size(); ++index)
      outContainer.append(QString::number(inContainer.at(index)));

    return outContainer;
  };

};

<|endoftext|>


<commit_before>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>

#include <boost/tokenizer.hpp>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

void RPCExecutor::request(const QString &command)
{
    // Parse shell-like command line into separate arguments
    boost::escaped_list_separator<char> els('\\',' ','\"');
    std::string strCommand = command.toStdString();
    boost::tokenizer<boost::escaped_list_separator<char> > tok(strCommand, els);

    std::string strMethod;
    std::vector<std::string> strParams;
    int n = 0;
    for(boost::tokenizer<boost::escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg,++n)
    {
        if(n == 0) // First parameter is the command
            strMethod = *beg;
        else
            strParams.push_back(*beg);
    }

    try {
        std::string strPrint;
        json_spirit::Value result = tableRPC.execute(strMethod, RPCConvertValues(strMethod, strParams));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef WIN32
    // Show Debug logfile label and Open button only for Windows
    ui->labelDebugLogfile->setVisible(false);
    ui->openDebugLogfileButton->setVisible(false);
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
    connect(ui->openDebugLogfileButton, SIGNAL(clicked()), this, SLOT(on_openDebugLogfileButton_clicked()));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(obj == ui->lineEdit)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *key = static_cast<QKeyEvent*>(event);
            switch(key->key())
            {
            case Qt::Key_Up: browseHistory(-1); return true;
            case Qt::Key_Down: browseHistory(1); return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime().toString());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, tr("Welcome to the Bitcoin RPC console.
"
                          "Use up and down arrows to navigate history, and Ctrl-L to clear screen.
"
                          "Type help for an overview of available commands."), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count)
{
    ui->numberOfBlocks->setText(QString::number(count));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}
<commit_msg>RPC console: don't crash on invalid input exception<commit_after>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>

#include <boost/tokenizer.hpp>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

void RPCExecutor::request(const QString &command)
{
    // Parse shell-like command line into separate arguments
    std::string strMethod;
    std::vector<std::string> strParams;
    try {
        boost::escaped_list_separator<char> els('\\',' ','\"');
        std::string strCommand = command.toStdString();
        boost::tokenizer<boost::escaped_list_separator<char> > tok(strCommand, els);

        int n = 0;
        for(boost::tokenizer<boost::escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg,++n)
        {
            if(n == 0) // First parameter is the command
                strMethod = *beg;
            else
                strParams.push_back(*beg);
        }
    }
    catch(boost::escaped_list_error &e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error"));
        return;
    }

    try {
        std::string strPrint;
        json_spirit::Value result = tableRPC.execute(strMethod, RPCConvertValues(strMethod, strParams));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef WIN32
    // Show Debug logfile label and Open button only for Windows
    ui->labelDebugLogfile->setVisible(false);
    ui->openDebugLogfileButton->setVisible(false);
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
    connect(ui->openDebugLogfileButton, SIGNAL(clicked()), this, SLOT(on_openDebugLogfileButton_clicked()));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(obj == ui->lineEdit)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *key = static_cast<QKeyEvent*>(event);
            switch(key->key())
            {
            case Qt::Key_Up: browseHistory(-1); return true;
            case Qt::Key_Down: browseHistory(1); return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime().toString());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, tr("Welcome to the Bitcoin RPC console.
"
                          "Use up and down arrows to navigate history, and Ctrl-L to clear screen.
"
                          "Type help for an overview of available commands."), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count)
{
    ui->numberOfBlocks->setText(QString::number(count));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}
<|endoftext|>


<commit_before>/*
 * Shared memory for sharing data between worker processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "shm.hxx"
#include "system/Error.hxx"
#include "util/RefCount.hxx"

#include <inline/poison.h>
#include <daemon/log.h>

#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/intrusive/set.hpp>

#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

struct shm {
    RefCount ref;

    const size_t page_size;
    const unsigned num_pages;

    /** this lock protects the linked list */
    boost::interprocess::interprocess_mutex mutex;

    struct Page
        : boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
        unsigned num_pages;
        uint8_t *data;

        bool operator<(const Page &other) const {
            return data < other.data;
        }
    };

    typedef boost::intrusive::set<Page,
                                  boost::intrusive::constant_time_size<false>> PageList;

    PageList available;
    Page pages[1];

    shm(size_t _page_size, unsigned _num_pages)
        :page_size(_page_size), num_pages(_num_pages) {
        ref.Init();

        pages[0].num_pages = num_pages;
        pages[0].data = GetData();
        available.push_front(pages[0]);
    }

    static unsigned CalcHeaderPages(size_t page_size, unsigned num_pages) {
        size_t header_size = sizeof(struct shm) +
            (num_pages - 1) * sizeof(Page);
        return (header_size + page_size - 1) / page_size;
    }

    unsigned CalcHeaderPages() const {
        return CalcHeaderPages(page_size, num_pages);
    }

    uint8_t *At(size_t offset) {
        return (uint8_t *)this + offset;
    }

    const uint8_t *At(size_t offset) const {
        return (const uint8_t *)this + offset;
    }

    uint8_t *GetData() {
        return At(page_size * CalcHeaderPages());
    }

    const uint8_t *GetData() const {
        return At(page_size * CalcHeaderPages());
    }

    unsigned PageNumber(const void *p) const {
        ptrdiff_t difference = (const uint8_t *)p - GetData();
        unsigned page_number = difference / page_size;
        assert(difference % page_size == 0);

        assert(page_number < num_pages);

        return page_number;
    }

    Page *FindAvailable(unsigned want_pages);
    Page *SplitPage(Page *page, unsigned want_pages);

    /**
     * Merge this page with its adjacent pages if possible, to create
     * bigger "available" areas.
     */
    void Merge(Page *page);

    void *Allocate(unsigned want_pages);
    void Free(const void *p);
};

struct shm *
shm_new(size_t page_size, unsigned num_pages)
{
    assert(page_size >= sizeof(size_t));
    assert(num_pages > 0);

    const unsigned header_pages = shm::CalcHeaderPages(page_size, num_pages);
    void *p = mmap(nullptr, page_size * (header_pages + num_pages),
                   PROT_READ|PROT_WRITE,
                   MAP_ANONYMOUS|MAP_SHARED,
                   -1, 0);
    if (p == (void *)-1)
        throw MakeErrno("mmap() failed");

    return ::new(p) struct shm(page_size, num_pages);
}

void
shm_ref(struct shm *shm)
{
    assert(shm != nullptr);

    shm->ref.Get();
}

void
shm_close(struct shm *shm)
{
    unsigned header_pages;
    int ret;

    assert(shm != nullptr);

    if (shm->ref.Put())
        shm->~shm();

    header_pages = shm->CalcHeaderPages();
    ret = munmap(shm, shm->page_size * (header_pages + shm->num_pages));
    if (ret < 0)
        daemon_log(1, "munmap() failed: %s\n", strerror(errno));
}

size_t
shm_page_size(const struct shm *shm)
{
    return shm->page_size;
}

shm::Page *
shm::FindAvailable(unsigned want_pages)
{
    for (auto &page : available)
        if (page.num_pages >= want_pages)
            return &page;

    return nullptr;
}

shm::Page *
shm::SplitPage(Page *page, unsigned want_pages)
{
    assert(page->num_pages > want_pages);

    page->num_pages -= want_pages;

    page[page->num_pages].data = page->data + page_size * page->num_pages;
    page += page->num_pages;
    page->num_pages = want_pages;

    return page;
}

void *
shm::Allocate(unsigned want_pages)
{
    assert(want_pages > 0);

    boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(mutex);

    Page *page = FindAvailable(want_pages);
    if (page == nullptr)
        return nullptr;

    assert(available.iterator_to(*page) == available.begin() ||
           &*std::prev(available.iterator_to(*page)) < page);
    assert(std::next(available.iterator_to(*page)) == available.end() ||
           &*std::next(available.iterator_to(*page)) > page);

    assert(page->num_pages >= want_pages);

    if (page->num_pages == want_pages) {
        available.erase(available.iterator_to(*page));

        lock.unlock();

        poison_undefined(page->data, page_size * want_pages);
        return page->data;
    } else {
        page = SplitPage(page, want_pages);

        lock.unlock();

        poison_undefined(page->data, page_size * want_pages);
        return page->data;
    }
}

void *
shm_alloc(struct shm *shm, unsigned want_pages)
{
    return shm->Allocate(want_pages);
}

/** merge this page with its adjacent pages if possible, to create
    bigger "available" areas */
void
shm::Merge(Page *page)
{
    unsigned page_number = PageNumber(page->data);

    /* merge with previous page? */

    assert(available.iterator_to(*page) == available.begin() ||
           &*std::prev(available.iterator_to(*page)) < page);

    auto i = available.iterator_to(*page);

    if (i != available.begin()) {
        Page &previous = *std::prev(i);
        if (PageNumber(previous.data) + previous.num_pages == page_number) {
            previous.num_pages += page->num_pages;
            available.erase(i);

            page = &previous;
            page_number = PageNumber(page->data);
            i = available.iterator_to(*page);
        }
    }

    /* merge with next page? */

    assert(std::next(available.iterator_to(*page)) == available.end() ||
           &*std::next(available.iterator_to(*page)) > page);

    if (i != std::prev(available.end())) {
        Page &next = *std::next(i);

        if (page_number + page->num_pages == PageNumber(next.data)) {
            page->num_pages += next.num_pages;
            available.erase(available.iterator_to(next));
        }
    }
}

void
shm::Free(const void *p)
{
    unsigned page_number = PageNumber(p);
    Page *page = &pages[page_number];

    poison_noaccess(page->data, page_size * page->num_pages);

    boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(mutex);

    available.insert(*page);

    Merge(page);
}

void
shm_free(struct shm *shm, const void *p)
{
    shm->Free(p);
}
<commit_msg>shm/shm: use "this" in operator<<commit_after>/*
 * Shared memory for sharing data between worker processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "shm.hxx"
#include "system/Error.hxx"
#include "util/RefCount.hxx"

#include <inline/poison.h>
#include <daemon/log.h>

#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/intrusive/set.hpp>

#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

struct shm {
    RefCount ref;

    const size_t page_size;
    const unsigned num_pages;

    /** this lock protects the linked list */
    boost::interprocess::interprocess_mutex mutex;

    struct Page
        : boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
        unsigned num_pages;
        uint8_t *data;

        bool operator<(const Page &other) const {
            return this < &other;
        }
    };

    typedef boost::intrusive::set<Page,
                                  boost::intrusive::constant_time_size<false>> PageList;

    PageList available;
    Page pages[1];

    shm(size_t _page_size, unsigned _num_pages)
        :page_size(_page_size), num_pages(_num_pages) {
        ref.Init();

        pages[0].num_pages = num_pages;
        pages[0].data = GetData();
        available.push_front(pages[0]);
    }

    static unsigned CalcHeaderPages(size_t page_size, unsigned num_pages) {
        size_t header_size = sizeof(struct shm) +
            (num_pages - 1) * sizeof(Page);
        return (header_size + page_size - 1) / page_size;
    }

    unsigned CalcHeaderPages() const {
        return CalcHeaderPages(page_size, num_pages);
    }

    uint8_t *At(size_t offset) {
        return (uint8_t *)this + offset;
    }

    const uint8_t *At(size_t offset) const {
        return (const uint8_t *)this + offset;
    }

    uint8_t *GetData() {
        return At(page_size * CalcHeaderPages());
    }

    const uint8_t *GetData() const {
        return At(page_size * CalcHeaderPages());
    }

    unsigned PageNumber(const void *p) const {
        ptrdiff_t difference = (const uint8_t *)p - GetData();
        unsigned page_number = difference / page_size;
        assert(difference % page_size == 0);

        assert(page_number < num_pages);

        return page_number;
    }

    Page *FindAvailable(unsigned want_pages);
    Page *SplitPage(Page *page, unsigned want_pages);

    /**
     * Merge this page with its adjacent pages if possible, to create
     * bigger "available" areas.
     */
    void Merge(Page *page);

    void *Allocate(unsigned want_pages);
    void Free(const void *p);
};

struct shm *
shm_new(size_t page_size, unsigned num_pages)
{
    assert(page_size >= sizeof(size_t));
    assert(num_pages > 0);

    const unsigned header_pages = shm::CalcHeaderPages(page_size, num_pages);
    void *p = mmap(nullptr, page_size * (header_pages + num_pages),
                   PROT_READ|PROT_WRITE,
                   MAP_ANONYMOUS|MAP_SHARED,
                   -1, 0);
    if (p == (void *)-1)
        throw MakeErrno("mmap() failed");

    return ::new(p) struct shm(page_size, num_pages);
}

void
shm_ref(struct shm *shm)
{
    assert(shm != nullptr);

    shm->ref.Get();
}

void
shm_close(struct shm *shm)
{
    unsigned header_pages;
    int ret;

    assert(shm != nullptr);

    if (shm->ref.Put())
        shm->~shm();

    header_pages = shm->CalcHeaderPages();
    ret = munmap(shm, shm->page_size * (header_pages + shm->num_pages));
    if (ret < 0)
        daemon_log(1, "munmap() failed: %s\n", strerror(errno));
}

size_t
shm_page_size(const struct shm *shm)
{
    return shm->page_size;
}

shm::Page *
shm::FindAvailable(unsigned want_pages)
{
    for (auto &page : available)
        if (page.num_pages >= want_pages)
            return &page;

    return nullptr;
}

shm::Page *
shm::SplitPage(Page *page, unsigned want_pages)
{
    assert(page->num_pages > want_pages);

    page->num_pages -= want_pages;

    page[page->num_pages].data = page->data + page_size * page->num_pages;
    page += page->num_pages;
    page->num_pages = want_pages;

    return page;
}

void *
shm::Allocate(unsigned want_pages)
{
    assert(want_pages > 0);

    boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(mutex);

    Page *page = FindAvailable(want_pages);
    if (page == nullptr)
        return nullptr;

    assert(available.iterator_to(*page) == available.begin() ||
           &*std::prev(available.iterator_to(*page)) < page);
    assert(std::next(available.iterator_to(*page)) == available.end() ||
           &*std::next(available.iterator_to(*page)) > page);

    assert(page->num_pages >= want_pages);

    if (page->num_pages == want_pages) {
        available.erase(available.iterator_to(*page));

        lock.unlock();

        poison_undefined(page->data, page_size * want_pages);
        return page->data;
    } else {
        page = SplitPage(page, want_pages);

        lock.unlock();

        poison_undefined(page->data, page_size * want_pages);
        return page->data;
    }
}

void *
shm_alloc(struct shm *shm, unsigned want_pages)
{
    return shm->Allocate(want_pages);
}

/** merge this page with its adjacent pages if possible, to create
    bigger "available" areas */
void
shm::Merge(Page *page)
{
    unsigned page_number = PageNumber(page->data);

    /* merge with previous page? */

    assert(available.iterator_to(*page) == available.begin() ||
           &*std::prev(available.iterator_to(*page)) < page);

    auto i = available.iterator_to(*page);

    if (i != available.begin()) {
        Page &previous = *std::prev(i);
        if (PageNumber(previous.data) + previous.num_pages == page_number) {
            previous.num_pages += page->num_pages;
            available.erase(i);

            page = &previous;
            page_number = PageNumber(page->data);
            i = available.iterator_to(*page);
        }
    }

    /* merge with next page? */

    assert(std::next(available.iterator_to(*page)) == available.end() ||
           &*std::next(available.iterator_to(*page)) > page);

    if (i != std::prev(available.end())) {
        Page &next = *std::next(i);

        if (page_number + page->num_pages == PageNumber(next.data)) {
            page->num_pages += next.num_pages;
            available.erase(available.iterator_to(next));
        }
    }
}

void
shm::Free(const void *p)
{
    unsigned page_number = PageNumber(p);
    Page *page = &pages[page_number];

    poison_noaccess(page->data, page_size * page->num_pages);

    boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(mutex);

    available.insert(*page);

    Merge(page);
}

void
shm_free(struct shm *shm, const void *p)
{
    shm->Free(p);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

/**
 * @file
 * Defines host-dependent types:
 * Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
 */

#ifndef __HOST_HH__
#define __HOST_HH__

#include <inttypes.h>
#include <limits>

/** uint64_t constant */
#define ULL(N)          ((uint64_t)N##ULL)
/** int64_t constant */
#define LL(N)           ((int64_t)N##LL)

/** Statistics counter type.  Not much excuse for not using a 64-bit
 * integer here, but if you're desperate and only run short
 * simulations you could make this 32 bits.
 */
typedef int64_t Counter;

/**
 * Clock cycle count type.
 * @note using an unsigned breaks the cache.
 */
typedef int64_t Tick;

const Tick MaxTick = std::numeric_limits<Tick>::max();

/**
 * Address type
 * This will probably be moved somewhere else in the near future.
 * This should be at least as big as the biggest address width in use
 * in the system, which will probably be 64 bits.
 */
typedef uint64_t Addr;

const Addr MaxAddr = (Addr)-1;

#endif // __HOST_H__
<commit_msg>eventq: I'm sick of the warning about MaxTick being unused.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

/**
 * @file
 * Defines host-dependent types:
 * Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
 */

#ifndef __HOST_HH__
#define __HOST_HH__

#include <inttypes.h>

/** uint64_t constant */
#define ULL(N)          ((uint64_t)N##ULL)
/** int64_t constant */
#define LL(N)           ((int64_t)N##LL)

/** Statistics counter type.  Not much excuse for not using a 64-bit
 * integer here, but if you're desperate and only run short
 * simulations you could make this 32 bits.
 */
typedef int64_t Counter;

/**
 * Clock cycle count type.
 * @note using an unsigned breaks the cache.
 */
typedef int64_t Tick;

const Tick MaxTick = LL(0x7fffffffffffffff);

/**
 * Address type
 * This will probably be moved somewhere else in the near future.
 * This should be at least as big as the biggest address width in use
 * in the system, which will probably be 64 bits.
 */
typedef uint64_t Addr;

const Addr MaxAddr = (Addr)-1;

#endif // __HOST_H__
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/win/dxgi_texture_staging.h"

#include <comdef.h>
#include <unknwn.h>
#include <DXGI.h>
#include <DXGI1_2.h>

#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/logging.h"
#include "webrtc/system_wrappers/include/metrics.h"

using Microsoft::WRL::ComPtr;

namespace webrtc {

DxgiTextureStaging::DxgiTextureStaging(const D3dDevice& device)
    : device_(device) {}

DxgiTextureStaging::~DxgiTextureStaging() = default;

bool DxgiTextureStaging::InitializeStage(ID3D11Texture2D* texture) {
  RTC_DCHECK(texture);
  D3D11_TEXTURE2D_DESC desc = {0};
  texture->GetDesc(&desc);

  desc.ArraySize = 1;
  desc.BindFlags = 0;
  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  desc.MipLevels = 1;
  desc.MiscFlags = 0;
  desc.SampleDesc.Count = 1;
  desc.SampleDesc.Quality = 0;
  desc.Usage = D3D11_USAGE_STAGING;
  if (stage_) {
    AssertStageAndSurfaceAreSameObject();
    D3D11_TEXTURE2D_DESC current_desc;
    stage_->GetDesc(&current_desc);
    const bool recreate_needed = (
        memcmp(&desc, &current_desc, sizeof(D3D11_TEXTURE2D_DESC)) != 0);
    RTC_HISTOGRAM_BOOLEAN("WebRTC.DesktopCapture.StagingTextureRecreate",
                          recreate_needed);
    if (!recreate_needed) {
      return true;
    }

    // The descriptions are not consistent, we need to create a new
    // ID3D11Texture2D instance.
    stage_.Reset();
    surface_.Reset();
  } else {
    RTC_DCHECK(!surface_);
  }

  _com_error error = device_.d3d_device()->CreateTexture2D(
      &desc, nullptr, stage_.GetAddressOf());
  if (error.Error() != S_OK || !stage_) {
    LOG(LS_ERROR) << "Failed to create a new ID3D11Texture2D as stage, error "
                  << error.ErrorMessage() << ", code " << error.Error();
    return false;
  }

  error = stage_.As(&surface_);
  if (error.Error() != S_OK || !surface_) {
    LOG(LS_ERROR) << "Failed to convert ID3D11Texture2D to IDXGISurface, error "
                  << error.ErrorMessage() << ", code " << error.Error();
    return false;
  }

  return true;
}

void DxgiTextureStaging::AssertStageAndSurfaceAreSameObject() {
  ComPtr<IUnknown> left;
  ComPtr<IUnknown> right;
  bool left_result = SUCCEEDED(stage_.As(&left));
  bool right_result = SUCCEEDED(surface_.As(&right));
  RTC_DCHECK(left_result);
  RTC_DCHECK(right_result);
  RTC_DCHECK(left.Get() == right.Get());
}

bool DxgiTextureStaging::CopyFromTexture(
    const DXGI_OUTDUPL_FRAME_INFO& frame_info,
    ID3D11Texture2D* texture) {
  RTC_DCHECK(texture && frame_info.AccumulatedFrames > 0);

  // AcquireNextFrame returns a CPU inaccessible IDXGIResource, so we need to
  // copy it to a CPU accessible staging ID3D11Texture2D.
  if (!InitializeStage(texture)) {
    return false;
  }

  device_.context()->CopyResource(static_cast<ID3D11Resource*>(stage_.Get()),
                                  static_cast<ID3D11Resource*>(texture));

  *rect() = {0};
  _com_error error = surface_->Map(rect(), DXGI_MAP_READ);
  if (error.Error() != S_OK) {
    *rect() = {0};
    LOG(LS_ERROR) << "Failed to map the IDXGISurface to a bitmap, error "
                  << error.ErrorMessage() << ", code " << error.Error();
    return false;
  }

  return true;
}

bool DxgiTextureStaging::DoRelease() {
  _com_error error = surface_->Unmap();
  if (error.Error() != S_OK) {
    stage_.Reset();
    surface_.Reset();
  }
  // If using staging mode, we only need to recreate ID3D11Texture2D instance.
  // This will happen during next CopyFrom call. So this function always returns
  // true.
  return true;
}

}  // namespace webrtc
<commit_msg>Revert "Track recreation of DxgiTextureStaging"<commit_after>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/win/dxgi_texture_staging.h"

#include <comdef.h>
#include <unknwn.h>
#include <DXGI.h>
#include <DXGI1_2.h>

#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/logging.h"

using Microsoft::WRL::ComPtr;

namespace webrtc {

DxgiTextureStaging::DxgiTextureStaging(const D3dDevice& device)
    : device_(device) {}

DxgiTextureStaging::~DxgiTextureStaging() = default;

bool DxgiTextureStaging::InitializeStage(ID3D11Texture2D* texture) {
  RTC_DCHECK(texture);
  D3D11_TEXTURE2D_DESC desc = {0};
  texture->GetDesc(&desc);

  desc.ArraySize = 1;
  desc.BindFlags = 0;
  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  desc.MipLevels = 1;
  desc.MiscFlags = 0;
  desc.SampleDesc.Count = 1;
  desc.SampleDesc.Quality = 0;
  desc.Usage = D3D11_USAGE_STAGING;
  if (stage_) {
    AssertStageAndSurfaceAreSameObject();
    D3D11_TEXTURE2D_DESC current_desc;
    stage_->GetDesc(&current_desc);
    if (memcmp(&desc, &current_desc, sizeof(D3D11_TEXTURE2D_DESC)) == 0) {
      return true;
    }

    // The descriptions are not consistent, we need to create a new
    // ID3D11Texture2D instance.
    stage_.Reset();
    surface_.Reset();
  } else {
    RTC_DCHECK(!surface_);
  }

  _com_error error = device_.d3d_device()->CreateTexture2D(
      &desc, nullptr, stage_.GetAddressOf());
  if (error.Error() != S_OK || !stage_) {
    LOG(LS_ERROR) << "Failed to create a new ID3D11Texture2D as stage, error "
                  << error.ErrorMessage() << ", code " << error.Error();
    return false;
  }

  error = stage_.As(&surface_);
  if (error.Error() != S_OK || !surface_) {
    LOG(LS_ERROR) << "Failed to convert ID3D11Texture2D to IDXGISurface, error "
                  << error.ErrorMessage() << ", code " << error.Error();
    return false;
  }

  return true;
}

void DxgiTextureStaging::AssertStageAndSurfaceAreSameObject() {
  ComPtr<IUnknown> left;
  ComPtr<IUnknown> right;
  bool left_result = SUCCEEDED(stage_.As(&left));
  bool right_result = SUCCEEDED(surface_.As(&right));
  RTC_DCHECK(left_result);
  RTC_DCHECK(right_result);
  RTC_DCHECK(left.Get() == right.Get());
}

bool DxgiTextureStaging::CopyFromTexture(
    const DXGI_OUTDUPL_FRAME_INFO& frame_info,
    ID3D11Texture2D* texture) {
  RTC_DCHECK(texture && frame_info.AccumulatedFrames > 0);

  // AcquireNextFrame returns a CPU inaccessible IDXGIResource, so we need to
  // copy it to a CPU accessible staging ID3D11Texture2D.
  if (!InitializeStage(texture)) {
    return false;
  }

  device_.context()->CopyResource(static_cast<ID3D11Resource*>(stage_.Get()),
                                  static_cast<ID3D11Resource*>(texture));

  *rect() = {0};
  _com_error error = surface_->Map(rect(), DXGI_MAP_READ);
  if (error.Error() != S_OK) {
    *rect() = {0};
    LOG(LS_ERROR) << "Failed to map the IDXGISurface to a bitmap, error "
                  << error.ErrorMessage() << ", code " << error.Error();
    return false;
  }

  return true;
}

bool DxgiTextureStaging::DoRelease() {
  _com_error error = surface_->Unmap();
  if (error.Error() != S_OK) {
    stage_.Reset();
    surface_.Reset();
  }
  // If using staging mode, we only need to recreate ID3D11Texture2D instance.
  // This will happen during next CopyFrom call. So this function always returns
  // true.
  return true;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// simplistic sentence-making
//
// 2011-10-06 GONG Chen <chen.sst@gmail.com>
//
#include <algorithm>
#include <functional>
#include <rime/candidate.h>
#include <rime/config.h>
#include <rime/dict/vocabulary.h>
#include <rime/gear/grammar.h>
#include <rime/gear/poet.h>

namespace rime {

inline static Grammar* create_grammar(Config* config) {
  if (auto* grammar = Grammar::Require("grammar")) {
    return grammar->Create(config);
  }
  return nullptr;
}

Poet::Poet(const Language* language, Config* config, Compare compare)
    : language_(language),
      grammar_(create_grammar(config)),
      compare_(compare) {}

Poet::~Poet() {}

bool Poet::LeftAssociateCompare(const Sentence& one, const Sentence& other) {
  return one.weight() < other.weight() || (  // left associate if even
      one.weight() == other.weight() && (
          one.size() > other.size() || (  // less components is more favorable
              one.size() == other.size() &&
              std::lexicographical_compare(one.syllable_lengths().begin(),
                                           one.syllable_lengths().end(),
                                           other.syllable_lengths().begin(),
                                           other.syllable_lengths().end()))));
}

an<Sentence> Poet::MakeSentence(const WordGraph& graph,
                                size_t total_length,
                                const string& preceding_text) {
  // TODO: save more intermediate sentence candidates
  map<int, an<Sentence>> sentences;
  sentences[0] = New<Sentence>(language_);
  // dynamic programming
  for (const auto& w : graph) {
    size_t start_pos = w.first;
    DLOG(INFO) << "start pos: " << start_pos;
    if (sentences.find(start_pos) == sentences.end())
      continue;
    for (const auto& x : w.second) {
      size_t end_pos = x.first;
      if (start_pos == 0 && end_pos == total_length)
        continue;  // exclude single words from the result
      DLOG(INFO) << "end pos: " << end_pos;
      bool is_rear = end_pos == total_length;
      const DictEntryList& entries(x.second);
      for (const auto& entry : entries) {
        auto new_sentence = New<Sentence>(*sentences[start_pos]);
        new_sentence->Extend(
            *entry, end_pos, is_rear, preceding_text, grammar_.get());
        if (sentences.find(end_pos) == sentences.end() ||
            compare_(*sentences[end_pos], *new_sentence)) {
          DLOG(INFO) << "updated sentences " << end_pos << ") with "
                     << new_sentence->text() << " weight: "
                     << new_sentence->weight();
          sentences[end_pos] = std::move(new_sentence);
        }
      }
    }
  }
  if (sentences.find(total_length) == sentences.end())
    return nullptr;
  else
    return sentences[total_length];
}

}  // namespace rime
<commit_msg>feat(poet): find best sentence candidates<commit_after>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// simplistic sentence-making
//
// 2011-10-06 GONG Chen <chen.sst@gmail.com>
//
#include <algorithm>
#include <functional>
#include <rime/candidate.h>
#include <rime/config.h>
#include <rime/dict/vocabulary.h>
#include <rime/gear/grammar.h>
#include <rime/gear/poet.h>

namespace rime {

inline static Grammar* create_grammar(Config* config) {
  if (auto* grammar = Grammar::Require("grammar")) {
    return grammar->Create(config);
  }
  return nullptr;
}

Poet::Poet(const Language* language, Config* config, Compare compare)
    : language_(language),
      grammar_(create_grammar(config)),
      compare_(compare) {}

Poet::~Poet() {}

bool Poet::LeftAssociateCompare(const Sentence& one, const Sentence& other) {
  return one.weight() < other.weight() || (  // left associate if even
      one.weight() == other.weight() && (
          one.size() > other.size() || (  // less components is more favorable
              one.size() == other.size() &&
              std::lexicographical_compare(one.syllable_lengths().begin(),
                                           one.syllable_lengths().end(),
                                           other.syllable_lengths().begin(),
                                           other.syllable_lengths().end()))));
}

// keep the best sentence candidate per last phrase
using SentenceCandidates = hash_map<string, of<Sentence>>;

static vector<of<Sentence>> top_candidates(const SentenceCandidates& candidates,
                                           size_t n,
                                           Poet::Compare& compare) {
  vector<of<Sentence>> top;
  top.reserve(n + 1);
  for (const auto& candidate : candidates) {
    auto pos = std::upper_bound(
        top.begin(), top.end(), candidate.second,
        [&](const an<Sentence>& a, const an<Sentence>& b) {
          return !compare(*a, *b);  // desc
        });
    if (pos - top.begin() >= n) continue;
    top.insert(pos, candidate.second);
    if (top.size() > n) top.pop_back();
  }
  return top;
}

an<Sentence> find_best_sentence(const SentenceCandidates& candidates,
                                Poet::Compare& compare) {
  an<Sentence> best = nullptr;
  for (const auto& candidate : candidates) {
    if (!best || compare(*best, *candidate.second)) {
      best = candidate.second;
    }
  }
  return best;
}

constexpr int kMaxSentenceCandidates = 7;

an<Sentence> Poet::MakeSentence(const WordGraph& graph,
                                size_t total_length,
                                const string& preceding_text) {
  map<int, SentenceCandidates> sentences;
  sentences[0].emplace("", New<Sentence>(language_));
  for (const auto& w : graph) {
    size_t start_pos = w.first;
    if (sentences.find(start_pos) == sentences.end())
      continue;
    DLOG(INFO) << "start pos: " << start_pos;
    auto top = top_candidates(
        sentences[start_pos], kMaxSentenceCandidates, compare_);
    for (const auto& candidate : top) {
      for (const auto& x : w.second) {
        size_t end_pos = x.first;
        if (start_pos == 0 && end_pos == total_length)
          continue;  // exclude single words from the result
        DLOG(INFO) << "end pos: " << end_pos;
        bool is_rear = end_pos == total_length;
        auto& target(sentences[end_pos]);
        const DictEntryList& entries(x.second);
        for (const auto& entry : entries) {
          auto new_sentence = New<Sentence>(*candidate);
          new_sentence->Extend(
              *entry, end_pos, is_rear, preceding_text, grammar_.get());
          const auto& key = new_sentence->components().back().text;
          auto& best_sentence = target[key];
          if (!best_sentence || compare_(*best_sentence, *new_sentence)) {
            DLOG(INFO) << "updated sentences " << end_pos << ") with "
                       << new_sentence->text() << " weight: "
                       << new_sentence->weight();
            best_sentence = std::move(new_sentence);
          }
        }
      }
    }
  }
  if (sentences.find(total_length) == sentences.end())
    return nullptr;
  else
    return find_best_sentence(sentences[total_length], compare_);
}

}  // namespace rime
<|endoftext|>


<commit_before>#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#define MAX_BUF 512
#define println(X) cout << X << "\n"

#define demo_int(X) printf( #X " -> %d\n", (X) );
#define demo_string(X) printf( #X " -> %s\n", (X) );
#define demo_float(X) printf( #X " -> %f\n", (X) );
#define demo(X) demo_int(X)

int main(int argc, char *argv[]) {
    if(argc != 2) {
        printf("Usage: %s <input>\n", argv[0]);
        exit(1);
    }

}
<commit_msg>Compilable template<commit_after>#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#define MAX_BUF 512
#define println(X) std::cout << X << std::endl

#define demo_int(X) printf( #X " -> %d\n", (X) );
#define demo_string(X) printf( #X " -> %s\n", (X) );
#define demo_float(X) printf( #X " -> %f\n", (X) );
#define demo(X) demo_int(X)

int main(int argc, char *argv[]) {
    if(argc != 2) {
        printf("Usage: %s <input>\n", argv[0]);
        exit(1);
    }

}
<|endoftext|>


<commit_before>/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    ex.cpp

Abstract:

    <abstract>

Author:

    Leonardo de Moura (leonardo) 2011-04-28

Revision History:

--*/
#include<iostream>
#include"z3_exception.h"

class ex {
public:
    virtual ~ex() {}
    virtual char const * msg() const = 0;
};

class ex1 : public ex {
    char const * m_msg;
public:
    ex1(char const * m):m_msg(m) {}
    virtual char const * msg() const { return m_msg; }
};

class ex2 : public ex {
    std::string m_msg;
public:
    ex2(char const * m):m_msg(m) {}
    virtual char const * msg() const { return m_msg.c_str(); }
};

static void th() {
    throw ex2("testing exception");
}

static void tst1() {
    try {
        th();
    }
    catch (ex & e) {
        std::cerr << e.msg() << "\n";
    }
}

static void tst2() {
    try {
        throw default_exception("Format %d %s", 12, "twelve");
    }
    catch (z3_exception& ex) {
        std::cerr << ex.msg() << "\n";
    }
}

void tst_ex() {
    tst1();
    tst2();
}
<commit_msg>fix unit test for default exception<commit_after>/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    ex.cpp

Abstract:

    <abstract>

Author:

    Leonardo de Moura (leonardo) 2011-04-28

Revision History:

--*/
#include<iostream>
#include"z3_exception.h"

class ex {
public:
    virtual ~ex() {}
    virtual char const * msg() const = 0;
};

class ex1 : public ex {
    char const * m_msg;
public:
    ex1(char const * m):m_msg(m) {}
    virtual char const * msg() const { return m_msg; }
};

class ex2 : public ex {
    std::string m_msg;
public:
    ex2(char const * m):m_msg(m) {}
    virtual char const * msg() const { return m_msg.c_str(); }
};

static void th() {
    throw ex2("testing exception");
}

static void tst1() {
    try {
        th();
    }
    catch (ex & e) {
        std::cerr << e.msg() << "\n";
    }
}

static void tst2() {
    try {
        throw default_exception(default_exception::fmt(), "Format %d %s", 12, "twelve");
    }
    catch (z3_exception& ex) {
        std::cerr << ex.msg() << "\n";
    }
}

void tst_ex() {
    tst1();
    tst2();
}
<|endoftext|>