<commit_before>#include "DataLikelihood.h"
#include "multichoose.h"
#include "multipermute.h"

// log probability of a given matching of true and observed alleles
// true alleles are the 'real' alleles
// observed alleles are whet we observe
// a mismatch between these two sets implies an error, which is scored accordingly here
long double likelihoodGivenTrueAlleles(vector<Allele*>& observedAlleles, vector<Allele*>& trueAlleles) {
    long double prob = 0;
    vector<Allele*>::iterator o = observedAlleles.begin();
    vector<Allele*>::iterator t = trueAlleles.begin();
    for ( ; o != observedAlleles.end() && t != trueAlleles.end(); ++o, ++t)
    {
        Allele& observedAllele = **o;
        Allele& trueAllele = **t;
        if (observedAllele == trueAllele) {
            prob += log(1 - exp(observedAllele.lnquality));
        } else {
            prob += observedAllele.lnquality;
        }
    }
    return prob;
}

/*
  'Exact' data likelihood, sum of sampling probability * joint Q score for the
  observed alleles over all possible underlying 'true allele' combinations."""
*/
long double
probObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype) {

    //cout << endl << endl << "genotype: "  << genotype << endl;
    int observationCount = observedAlleles.size();
    vector<long double> alleleProbs = genotype.alleleProbabilities();
    vector<long double> probs;
    vector<Allele> uniqueAlleles = genotype.uniqueAlleles();
    vector<vector<Allele*> > combos = multichoose_ptr(observationCount, uniqueAlleles);
    for (vector<vector<Allele*> >::iterator combo = combos.begin(); combo != combos.end(); ++combo) {
        //cout << endl << "combo: " << *combo << endl;
        vector<vector<Allele*> > trueAllelePermutations = multipermute(*combo);
        for (vector<vector<Allele*> >::iterator perm = trueAllelePermutations.begin(); perm != trueAllelePermutations.end(); ++perm) {
            vector<Allele*>& trueAlleles = *perm;
            //cout << "permu: " << *perm << endl;
            map<string, int> trueAlleleCounts = countAllelesString(trueAlleles);
            long double lnTrueAllelePermutationsCount = log(trueAllelePermutations.size());
            vector<int> observationCounts; // counts of 'observations' of true alleles, ordered according to the genotype's internal ordering
            for (Genotype::const_iterator g = genotype.begin(); g != genotype.end(); ++g) {
                map<string, int>::const_iterator count = trueAlleleCounts.find(g->first.currentBase);
                if (count != trueAlleleCounts.end()) {
                    observationCounts.push_back(count->second);
                } else {
                    observationCounts.push_back(0);
                }
            }
            //cout << "multinomial: " << exp(multinomialln(alleleProbs, observationCounts)) << endl;
            //cout << "likelihood: " << exp(likelihoodGivenTrueAlleles(observedAlleles, trueAlleles)) << endl;
            probs.push_back(multinomialln(alleleProbs, observationCounts)
                    + likelihoodGivenTrueAlleles(observedAlleles, trueAlleles)
                    - lnTrueAllelePermutationsCount);
        }
    }
    //cout << "l = " << logsumexp(probs) << endl;
    return logsumexp(probs);
}

/*
long double
badApproxProbObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype
        ) {

    int observationCount = observedAlleles.size();
    vector<long double> alleleProbs = genotype.alleleProbabilities();
    vector<int> observationCounts = genotype.alleleCountsInObservations(observedAlleles);

    long double probInAllWrong = 0; //
    long double probOutAreAllErrors = 0; //
    for (vector<Allele*>::iterator obs = observedAlleles.begin(); obs != observedAlleles.end(); ++obs) {
        Allele& observation = **obs;
        if (genotype.containsAllele(observation)) {
            probInAllWrong += observation.lnquality;
        } else {
            probOutAreAllErrors += observation.lnquality;
        }
    }

    if (sum(observationCounts) == 0) {
        return probOutAreAllErrors;
    } else {
        long double someInCorrect = log(1 - exp(probInAllWrong));
        return someInCorrect + (probOutAreAllErrors != 0 ? log(1 - exp(probOutAreAllErrors)) : 0) + log(dirichletMaximumLikelihoodRatio(alleleProbs, observationCounts));
    }

}
*/

// p(out are wrong) * p(in are correct) * (multinomial(in | genotype))
// sum(Q)           * sum(1 - Q)        *          ...
long double
approxProbObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype
        ) {

    int observationCount = observedAlleles.size();
    vector<long double> alleleProbs = genotype.alleleProbabilities();
    vector<int> observationCounts = genotype.alleleCountsInObservations(observedAlleles);

    long double probInAllCorrect = 0; //
    long double probOutAllWrong  = 0; //
    for (vector<Allele*>::iterator obs = observedAlleles.begin(); obs != observedAlleles.end(); ++obs) {
        Allele& observation = **obs;
        if (genotype.containsAllele(observation)) {
            probInAllCorrect += log(1 - exp(observation.lnquality));
        } else {
            probOutAllWrong += observation.lnquality;
        }
    }

    if (sum(observationCounts) == 0) {
        return probOutAllWrong;
    } else {
        return probInAllCorrect + probOutAllWrong + multinomialln(alleleProbs, observationCounts);
    }

}

long double
bamBayesApproxProbObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype,
        long double dependenceFactor
        ) {

    int observationCount = observedAlleles.size();

    long double sumQout = 0;
    int countOut = 0;

    for (vector<Allele*>::iterator obs = observedAlleles.begin(); obs != observedAlleles.end(); ++obs) {
        Allele& observation = **obs;
        if (!genotype.containsAllele(observation)) {
            sumQout += observation.lnquality;
            ++countOut;
        }
    }

    if (countOut > 1) {
        sumQout *= (1 + (countOut - 1) * dependenceFactor) / countOut;
        //cerr << "dependencefactor," << observedAlleles.front()->sampleID << "," << IUPAC2GenotypeStr(IUPAC(genotype)) << "," << (1 + (countOut - 1) * dependenceFactor) / countOut << endl;
    }

    long double lnprob = sumQout - countOut * log(3);

    if (!genotype.homozygous()) {
        long double lnBinomialfactor = observationCount * log(0.5);
        //cerr << "lnprob," << observedAlleles.front()->sampleID << "," << IUPAC2GenotypeStr(IUPAC(genotype)) << "," << lnprob + lnBinomialfactor << endl;
        return lnprob + lnBinomialfactor;
    } else {
        //cerr << "lnprob," << observedAlleles.front()->sampleID << "," << IUPAC2GenotypeStr(IUPAC(genotype)) << "," << lnprob << endl;
        return lnprob;
    }

}

vector<pair<Genotype*, long double> >
exactProbObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes) {
    vector<pair<Genotype*, long double> > results;
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        results.push_back(make_pair(&*g, probObservedAllelesGivenGenotype(observedAlleles, *g)));
    }
    return results;
}

vector<pair<Genotype*, long double> >
approxProbObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes) {
    vector<pair<Genotype*, long double> > results;
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        results.push_back(make_pair(&*g, approxProbObservedAllelesGivenGenotype(observedAlleles, *g)));
    }
    return results;
}

// uses caching to reduce computation while generating the exact correct result

vector<pair<Genotype*, long double> >
probObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes) {
    vector<pair<Genotype*, long double> > results;
    // cache the results on the basis of number of alleles in the genotype as a fraction of the genotype
    map<pair<int, int>, long double> cachedProbsGivenAllelesInGenotype;
    bool allSame = (countAlleles(observedAlleles).size() == 1);
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        long double prob;
        Genotype& genotype = *g;
        if (allSame) {
            pair<int, int> alleleRatio = make_pair(0, genotype.uniqueAlleles().size());
            //alleleRatio(observedAlleles, genotype);
            for (Genotype::iterator a = genotype.begin(); a != genotype.end(); ++a) {
                if (a->first == *(observedAlleles.front()))
                    alleleRatio.first += 1;
            }
            map<pair<int, int>, long double>::iterator c = cachedProbsGivenAllelesInGenotype.find(alleleRatio);
            if (c != cachedProbsGivenAllelesInGenotype.end()) {
                prob = c->second;
            } else {
                prob = approxProbObservedAllelesGivenGenotype(observedAlleles, genotype);
                cachedProbsGivenAllelesInGenotype[alleleRatio] = prob;
            }
            results.push_back(make_pair(&genotype, prob));
        } else {
            results.push_back(make_pair(&genotype, approxProbObservedAllelesGivenGenotype(observedAlleles, genotype)));
        }
    }
    return results;
}

// bambayes style data likelihoods
vector<pair<Genotype*, long double> >
bamBayesProbObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes,
        long double dependenceFactor) {
    vector<pair<Genotype*, long double> > results;
    // cache the results on the basis of number of alleles in the genotype as a fraction of the genotype
    map<pair<int, int>, long double> cachedProbsGivenAllelesInGenotype;
    bool allSame = (countAlleles(observedAlleles).size() == 1);
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        long double prob;
        Genotype& genotype = *g;
        if (allSame) {
            pair<int, int> alleleRatio = make_pair(0, genotype.uniqueAlleles().size());
            //alleleRatio(observedAlleles, genotype);
            for (Genotype::iterator a = genotype.begin(); a != genotype.end(); ++a) {
                if (a->first == *(observedAlleles.front()))
                    alleleRatio.first += 1;
            }
            map<pair<int, int>, long double>::iterator c = cachedProbsGivenAllelesInGenotype.find(alleleRatio);
            if (c != cachedProbsGivenAllelesInGenotype.end()) {
                prob = c->second;
            } else {
                prob = bamBayesApproxProbObservedAllelesGivenGenotype(observedAlleles, genotype, dependenceFactor);
                cachedProbsGivenAllelesInGenotype[alleleRatio] = prob;
            }
            results.push_back(make_pair(&genotype, prob));
        } else {
            results.push_back(make_pair(&genotype, bamBayesApproxProbObservedAllelesGivenGenotype(observedAlleles, genotype, dependenceFactor)));
        }
    }
    return results;
}
<commit_msg>changed default data likelihood calculations<commit_after>#include "DataLikelihood.h"
#include "multichoose.h"
#include "multipermute.h"

// log probability of a given matching of true and observed alleles
// true alleles are the 'real' alleles
// observed alleles are whet we observe
// a mismatch between these two sets implies an error, which is scored accordingly here
long double likelihoodGivenTrueAlleles(vector<Allele*>& observedAlleles, vector<Allele*>& trueAlleles) {
    long double prob = 0;
    vector<Allele*>::iterator o = observedAlleles.begin();
    vector<Allele*>::iterator t = trueAlleles.begin();
    for ( ; o != observedAlleles.end() && t != trueAlleles.end(); ++o, ++t)
    {
        Allele& observedAllele = **o;
        Allele& trueAllele = **t;
        if (observedAllele == trueAllele) {
            prob += log(1 - exp(observedAllele.lnquality));
        } else {
            prob += observedAllele.lnquality;
        }
    }
    return prob;
}

/*
  'Exact' data likelihood, sum of sampling probability * joint Q score for the
  observed alleles over all possible underlying 'true allele' combinations."""
*/
long double
probObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype) {

    //cout << endl << endl << "genotype: "  << genotype << endl;
    int observationCount = observedAlleles.size();
    vector<long double> alleleProbs = genotype.alleleProbabilities();
    vector<long double> probs;
    vector<Allele> uniqueAlleles = genotype.uniqueAlleles();
    vector<vector<Allele*> > combos = multichoose_ptr(observationCount, uniqueAlleles);
    for (vector<vector<Allele*> >::iterator combo = combos.begin(); combo != combos.end(); ++combo) {
        //cout << endl << "combo: " << *combo << endl;
        vector<vector<Allele*> > trueAllelePermutations = multipermute(*combo);
        for (vector<vector<Allele*> >::iterator perm = trueAllelePermutations.begin(); perm != trueAllelePermutations.end(); ++perm) {
            vector<Allele*>& trueAlleles = *perm;
            //cout << "permu: " << *perm << endl;
            map<string, int> trueAlleleCounts = countAllelesString(trueAlleles);
            long double lnTrueAllelePermutationsCount = log(trueAllelePermutations.size());
            vector<int> observationCounts; // counts of 'observations' of true alleles, ordered according to the genotype's internal ordering
            for (Genotype::const_iterator g = genotype.begin(); g != genotype.end(); ++g) {
                map<string, int>::const_iterator count = trueAlleleCounts.find(g->first.currentBase);
                if (count != trueAlleleCounts.end()) {
                    observationCounts.push_back(count->second);
                } else {
                    observationCounts.push_back(0);
                }
            }
            //cout << "multinomial: " << exp(multinomialln(alleleProbs, observationCounts)) << endl;
            //cout << "likelihood: " << exp(likelihoodGivenTrueAlleles(observedAlleles, trueAlleles)) << endl;
            probs.push_back(multinomialln(alleleProbs, observationCounts)
                    + likelihoodGivenTrueAlleles(observedAlleles, trueAlleles)
                    - lnTrueAllelePermutationsCount);
        }
    }
    //cout << "l = " << logsumexp(probs) << endl;
    return logsumexp(probs);
}

// p(out are wrong) * p(in are correct) * (multinomial(in | genotype))
// sum(Q)           * sum(1 - Q)        *          ...
/*
long double
approxProbObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype
        ) {

    int observationCount = observedAlleles.size();
    vector<long double> alleleProbs = genotype.alleleProbabilities();
    vector<int> observationCounts = genotype.alleleCountsInObservations(observedAlleles);

    long double probInAllCorrect = 0; //
    long double probOutAllWrong  = 0; //
    for (vector<Allele*>::iterator obs = observedAlleles.begin(); obs != observedAlleles.end(); ++obs) {
        Allele& observation = **obs;
        if (genotype.containsAllele(observation)) {
            probInAllCorrect += log(1 - exp(observation.lnquality));
        } else {
            probOutAllWrong += observation.lnquality;
        }
    }

    if (sum(observationCounts) == 0) {
        return probOutAllWrong;
    } else {
        return probInAllCorrect + probOutAllWrong + multinomialln(alleleProbs, observationCounts);
    }

}
*/

long double
approxProbObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype
        ) {

    int observationCount = observedAlleles.size();
    vector<long double> alleleProbs = genotype.alleleProbabilities();
    vector<int> observationCounts = genotype.alleleCountsInObservations(observedAlleles);

    long double probInAllCorrect = 0; //
    long double probOutAllWrong  = 0; //
    for (vector<Allele*>::iterator obs = observedAlleles.begin(); obs != observedAlleles.end(); ++obs) {
        Allele& observation = **obs;
        if (!genotype.containsAllele(observation)) {
            probOutAllWrong += observation.lnquality;
        }
    }

    if (sum(observationCounts) == 0) {
        return probOutAllWrong;
    } else {
        return probOutAllWrong + multinomialln(alleleProbs, observationCounts);
    }

}

long double
bamBayesApproxProbObservedAllelesGivenGenotype(
        vector<Allele*>& observedAlleles,
        Genotype& genotype,
        long double dependenceFactor
        ) {

    int observationCount = observedAlleles.size();

    long double sumQout = 0;
    int countOut = 0;

    for (vector<Allele*>::iterator obs = observedAlleles.begin(); obs != observedAlleles.end(); ++obs) {
        Allele& observation = **obs;
        if (!genotype.containsAllele(observation)) {
            sumQout += observation.lnquality;
            ++countOut;
        }
    }

    if (countOut > 1) {
        sumQout *= (1 + (countOut - 1) * dependenceFactor) / countOut;
        //cerr << "dependencefactor," << observedAlleles.front()->sampleID << "," << IUPAC2GenotypeStr(IUPAC(genotype)) << "," << (1 + (countOut - 1) * dependenceFactor) / countOut << endl;
    }

    long double lnprob = sumQout - countOut * log(3);

    if (!genotype.homozygous()) {
        long double lnBinomialfactor = observationCount * log(0.5);
        //cerr << "lnprob," << observedAlleles.front()->sampleID << "," << IUPAC2GenotypeStr(IUPAC(genotype)) << "," << lnprob + lnBinomialfactor << endl;
        return lnprob + lnBinomialfactor;
    } else {
        //cerr << "lnprob," << observedAlleles.front()->sampleID << "," << IUPAC2GenotypeStr(IUPAC(genotype)) << "," << lnprob << endl;
        return lnprob;
    }

}

vector<pair<Genotype*, long double> >
exactProbObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes) {
    vector<pair<Genotype*, long double> > results;
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        results.push_back(make_pair(&*g, probObservedAllelesGivenGenotype(observedAlleles, *g)));
    }
    return results;
}

vector<pair<Genotype*, long double> >
approxProbObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes) {
    vector<pair<Genotype*, long double> > results;
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        results.push_back(make_pair(&*g, approxProbObservedAllelesGivenGenotype(observedAlleles, *g)));
    }
    return results;
}

// uses caching to reduce computation while generating the exact correct result

vector<pair<Genotype*, long double> >
probObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes) {
    vector<pair<Genotype*, long double> > results;
    // cache the results on the basis of number of alleles in the genotype as a fraction of the genotype
    map<pair<int, int>, long double> cachedProbsGivenAllelesInGenotype;
    bool allSame = (countAlleles(observedAlleles).size() == 1);
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        long double prob;
        Genotype& genotype = *g;
        if (allSame) {
            pair<int, int> alleleRatio = make_pair(0, genotype.uniqueAlleles().size());
            //alleleRatio(observedAlleles, genotype);
            for (Genotype::iterator a = genotype.begin(); a != genotype.end(); ++a) {
                if (a->first == *(observedAlleles.front()))
                    alleleRatio.first += 1;
            }
            map<pair<int, int>, long double>::iterator c = cachedProbsGivenAllelesInGenotype.find(alleleRatio);
            if (c != cachedProbsGivenAllelesInGenotype.end()) {
                prob = c->second;
            } else {
                prob = approxProbObservedAllelesGivenGenotype(observedAlleles, genotype);
                cachedProbsGivenAllelesInGenotype[alleleRatio] = prob;
            }
            results.push_back(make_pair(&genotype, prob));
        } else {
            results.push_back(make_pair(&genotype, approxProbObservedAllelesGivenGenotype(observedAlleles, genotype)));
        }
    }
    return results;
}

// bambayes style data likelihoods
vector<pair<Genotype*, long double> >
bamBayesProbObservedAllelesGivenGenotypes(
        vector<Allele*>& observedAlleles,
        vector<Genotype>& genotypes,
        long double dependenceFactor) {
    vector<pair<Genotype*, long double> > results;
    // cache the results on the basis of number of alleles in the genotype as a fraction of the genotype
    map<pair<int, int>, long double> cachedProbsGivenAllelesInGenotype;
    bool allSame = (countAlleles(observedAlleles).size() == 1);
    for (vector<Genotype>::iterator g = genotypes.begin(); g != genotypes.end(); ++g) {
        long double prob;
        Genotype& genotype = *g;
        if (allSame) {
            pair<int, int> alleleRatio = make_pair(0, genotype.uniqueAlleles().size());
            //alleleRatio(observedAlleles, genotype);
            for (Genotype::iterator a = genotype.begin(); a != genotype.end(); ++a) {
                if (a->first == *(observedAlleles.front()))
                    alleleRatio.first += 1;
            }
            map<pair<int, int>, long double>::iterator c = cachedProbsGivenAllelesInGenotype.find(alleleRatio);
            if (c != cachedProbsGivenAllelesInGenotype.end()) {
                prob = c->second;
            } else {
                prob = bamBayesApproxProbObservedAllelesGivenGenotype(observedAlleles, genotype, dependenceFactor);
                cachedProbsGivenAllelesInGenotype[alleleRatio] = prob;
            }
            results.push_back(make_pair(&genotype, prob));
        } else {
            results.push_back(make_pair(&genotype, bamBayesApproxProbObservedAllelesGivenGenotype(observedAlleles, genotype, dependenceFactor)));
        }
    }
    return results;
}
<|endoftext|>


<commit_before>#include "codeConverterBase.h"

#include <qrkernel/settingsManager.h>

using namespace generatorBase::converters;
using namespace qReal;

CodeConverterBase::CodeConverterBase(QString const &pathToTemplates
		, interpreterBase::robotModel::RobotModelInterface const &robotModel
		, QMap<interpreterBase::robotModel::PortInfo, interpreterBase::robotModel::DeviceInfo> const &devices
		, simple::Binding::ConverterInterface const *inputPortConverter
		, simple::Binding::ConverterInterface const *functionInvocationsConverter)
	: TemplateParametrizedConverter(pathToTemplates)
	, mRobotModel(robotModel)
	, mDevices(devices)
	, mInputConverter(inputPortConverter)
	, mFunctionInvocationsConverter(functionInvocationsConverter)
{
}

CodeConverterBase::~CodeConverterBase()
{
	delete mInputConverter;
	delete mFunctionInvocationsConverter;
}

QString CodeConverterBase::convert(QString const &data) const
{
	return replaceFunctionInvocations(replaceSystemVariables(data)).trimmed();
}

QString CodeConverterBase::replaceSystemVariables(QString const &expression) const
{
	QString result = expression;

	for (interpreterBase::robotModel::PortInfo const &port : mRobotModel.availablePorts()) {
		QString const variable = port.reservedVariable();
		if (!variable.isEmpty()) {
			result.replace(variable, deviceExpression(port));
		}
	}

	result.replace("Time", timelineExpression());
	return result;
}

QString CodeConverterBase::replaceFunctionInvocations(QString const &expression) const
{
	QString result = expression;

	QString const randomTemplate = mFunctionInvocationsConverter->convert("random");

	QRegExp const randomFunctionInvocationRegEx("random\\((.*)\\)");
	int pos = randomFunctionInvocationRegEx.indexIn(result, 0);
	while (pos != -1) {
		QString const param = randomFunctionInvocationRegEx.cap(1);
		QString randomInvocation = randomTemplate;
		randomInvocation.replace("@@UPPER_BOUND@@", param);
		result.replace(randomFunctionInvocationRegEx, randomInvocation);
		pos += randomFunctionInvocationRegEx.matchedLength();
		pos = randomFunctionInvocationRegEx.indexIn(result, pos);
	}

	return result;
}

QString CodeConverterBase::deviceExpression(interpreterBase::robotModel::PortInfo const &port) const
{
	if (mDevices[port].isNull()) {
		return QString();
	}

	QString const templatePath = QString("sensors/%1.t").arg(mDevices[port].name());

	// Converter must take a string like "1" or "2" (and etc) and return correct value
	return readTemplate(templatePath).replace("@@PORT@@", mInputConverter->convert(port.name()));
}

QString CodeConverterBase::timelineExpression() const
{
	/// @todo: generate timestamps code in nxt c when required
	return readTemplate("whatTime.t");
}
<commit_msg>Fixed timer variable generation<commit_after>#include "codeConverterBase.h"

#include <qrkernel/settingsManager.h>

using namespace generatorBase::converters;
using namespace qReal;

CodeConverterBase::CodeConverterBase(QString const &pathToTemplates
		, interpreterBase::robotModel::RobotModelInterface const &robotModel
		, QMap<interpreterBase::robotModel::PortInfo, interpreterBase::robotModel::DeviceInfo> const &devices
		, simple::Binding::ConverterInterface const *inputPortConverter
		, simple::Binding::ConverterInterface const *functionInvocationsConverter)
	: TemplateParametrizedConverter(pathToTemplates)
	, mRobotModel(robotModel)
	, mDevices(devices)
	, mInputConverter(inputPortConverter)
	, mFunctionInvocationsConverter(functionInvocationsConverter)
{
}

CodeConverterBase::~CodeConverterBase()
{
	delete mInputConverter;
	delete mFunctionInvocationsConverter;
}

QString CodeConverterBase::convert(QString const &data) const
{
	return replaceFunctionInvocations(replaceSystemVariables(data)).trimmed();
}

QString CodeConverterBase::replaceSystemVariables(QString const &expression) const
{
	QString result = expression;

	for (interpreterBase::robotModel::PortInfo const &port : mRobotModel.availablePorts()) {
		QString const variable = port.reservedVariable();
		if (!variable.isEmpty()) {
			result.replace(variable, deviceExpression(port));
		}
	}

	result.replace("time", timelineExpression());
	return result;
}

QString CodeConverterBase::replaceFunctionInvocations(QString const &expression) const
{
	QString result = expression;

	QString const randomTemplate = mFunctionInvocationsConverter->convert("random");

	QRegExp const randomFunctionInvocationRegEx("random\\((.*)\\)");
	int pos = randomFunctionInvocationRegEx.indexIn(result, 0);
	while (pos != -1) {
		QString const param = randomFunctionInvocationRegEx.cap(1);
		QString randomInvocation = randomTemplate;
		randomInvocation.replace("@@UPPER_BOUND@@", param);
		result.replace(randomFunctionInvocationRegEx, randomInvocation);
		pos += randomFunctionInvocationRegEx.matchedLength();
		pos = randomFunctionInvocationRegEx.indexIn(result, pos);
	}

	return result;
}

QString CodeConverterBase::deviceExpression(interpreterBase::robotModel::PortInfo const &port) const
{
	if (mDevices[port].isNull()) {
		return QString();
	}

	QString const templatePath = QString("sensors/%1.t").arg(mDevices[port].name());

	// Converter must take a string like "1" or "2" (and etc) and return correct value
	return readTemplate(templatePath).replace("@@PORT@@", mInputConverter->convert(port.name()));
}

QString CodeConverterBase::timelineExpression() const
{
	/// @todo: generate timestamps code in nxt c when required
	return readTemplate("whatTime.t");
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_SYMBOLIZER_UTILS_HPP
#define MAPNIK_SYMBOLIZER_UTILS_HPP

// mapnik
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/path_expression.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/color.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/transform_processor.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/xml_tree.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/evaluate_global_attributes.hpp>
#include <mapnik/parse_transform.hpp>
#include <mapnik/util/variant.hpp>

namespace mapnik {

template <typename Symbolizer>
struct symbolizer_traits
{
    static char const* name() { return "Unknown";}
};

template<>
struct symbolizer_traits<point_symbolizer>
{
    static char const* name() { return "PointSymbolizer";}
};

template<>
struct symbolizer_traits<line_symbolizer>
{
    static char const* name() { return "LineSymbolizer";}
};

template<>
struct symbolizer_traits<polygon_symbolizer>
{
    static char const* name() { return "PolygonSymbolizer";}
};

template<>
struct symbolizer_traits<text_symbolizer>
{
    static char const* name() { return "TextSymbolizer";}
};

template<>
struct symbolizer_traits<line_pattern_symbolizer>
{
    static char const* name() { return "LinePatternSymbolizer";}
};

template<>
struct symbolizer_traits<polygon_pattern_symbolizer>
{
    static char const* name() { return "PolygonPatternSymbolizer";}
};

template<>
struct symbolizer_traits<markers_symbolizer>
{
    static char const* name() { return "MarkersSymbolizer";}
};

template<>
struct symbolizer_traits<shield_symbolizer>
{
    static char const* name() { return "ShieldSymbolizer";}
};

template<>
struct symbolizer_traits<raster_symbolizer>
{
    static char const* name() { return "RasterSymbolizer";}
};

template<>
struct symbolizer_traits<building_symbolizer>
{
    static char const* name() { return "BuildingSymbolizer";}
};

template<>
struct symbolizer_traits<group_symbolizer>
{
    static char const* name() { return "GroupSymbolizer";}
};

template<>
struct symbolizer_traits<debug_symbolizer>
{
    static char const* name() { return "DebugSymbolizer";}
};

// symbolizer name impl
namespace detail {

struct symbolizer_name_impl : public util::static_visitor<std::string>
{
public:
    template <typename Symbolizer>
    std::string operator () (Symbolizer const&) const
    {
        return symbolizer_traits<Symbolizer>::name();
    }
};
}

inline std::string symbolizer_name(symbolizer const& sym)
{
    std::string type = util::apply_visitor( detail::symbolizer_name_impl(), sym);
    return type;
}

template <typename Meta>
class symbolizer_property_value_string : public util::static_visitor<std::string>
{
public:
    symbolizer_property_value_string (Meta const& meta)
        : meta_(meta) {}

    std::string operator() ( mapnik::enumeration_wrapper const& e) const
    {
        std::stringstream ss;
        auto const& convert_fun_ptr(std::get<2>(meta_));
        if ( convert_fun_ptr )
        {
            ss << convert_fun_ptr(e);
        }
        return ss.str();
    }

    std::string operator () ( path_expression_ptr const& expr) const
    {
        std::ostringstream ss;
        if (expr)
        {
            ss << '\"' << path_processor::to_string(*expr) << '\"';
        }
        return ss.str();
    }

    std::string operator () (text_placements_ptr const& expr) const
    {
        return std::string("\"<fixme-text-placement-ptr>\"");
    }

    std::string operator () (raster_colorizer_ptr const& expr) const
    {
        return std::string("\"<fixme-raster-colorizer-ptr>\"");
    }

    std::string operator () (transform_type const& expr) const
    {
        std::ostringstream ss;
        if (expr)
        {
            ss << '\"' << transform_processor_type::to_string(*expr) << '\"';
        }
        return ss.str();
    }

    std::string operator () (expression_ptr const& expr) const
    {
        std::ostringstream ss;
        if (expr)
        {
            ss << '\"' << "FIXME" /*mapnik::to_expression_string(*expr)*/ <<  '\"';
        }
        return ss.str();
    }

    std::string operator () (color const& c) const
    {
        std::ostringstream ss;
        ss << '\"' << c << '\"';
        return ss.str();
    }

    std::string operator () (dash_array const& dash) const
    {
        std::ostringstream ss;
        for (std::size_t i = 0; i < dash.size(); ++i)
        {
            ss << dash[i].first << ", " << dash[i].second;
            if ( i + 1 < dash.size() ) ss << ',';
        }
        return ss.str();
    }

    template <typename T>
    std::string operator () ( T const& val ) const
    {
        std::ostringstream ss;
        ss << val;
        return ss.str();
    }

private:
    Meta const& meta_;
};

struct symbolizer_to_json : public util::static_visitor<std::string>
{
    using result_type = std::string;

    template <typename T>
    auto operator() (T const& sym) const -> result_type
    {
        std::stringstream ss;
        ss << "{\"type\":\"" << mapnik::symbolizer_traits<T>::name() << "\",";
        ss << "\"properties\":{";
        bool first = true;
        for (auto const& prop : sym.properties)
        {
            auto const& meta = mapnik::get_meta(prop.first);
            if (first) first = false;
            else ss << ",";
            ss << "\"" <<  std::get<0>(meta) << "\":";
            ss << util::apply_visitor(symbolizer_property_value_string<property_meta_type>(meta),prop.second);
        }
        ss << "}}";
        return ss.str();
    }
};

namespace {

template <typename Symbolizer, typename T>
struct set_property_impl
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        std::cerr << "do nothing" << std::endl;
    }
};

template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_color> >
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        put(sym, key, mapnik::parse_color(val));
    }
};

template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_double> >
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        std::cerr << " expects double" << std::endl;
    }
};

template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_bool> >
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        std::cerr << " expects bool" << std::endl;
    }
};

}

template <typename Symbolizer, typename T>
inline void set_property(Symbolizer & sym, mapnik::keys key, T const& val)
{
    switch (std::get<3>(get_meta(key)))
    {
    case property_types::target_bool:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_bool> >::apply(sym,key,val);
        break;
    case property_types::target_integer:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_integer> >::apply(sym,key,val);
        break;
    case property_types::target_double:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_double> >::apply(sym,key,val);
        break;
    case property_types::target_color:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_color> >::apply(sym,key,val);
        break;
    default:
        break;
    }
}

template <typename Symbolizer, typename T>
inline void set_property_from_value(Symbolizer & sym, mapnik::keys key, T const& val)
{
    switch (std::get<3>(get_meta(key)))
    {
    case property_types::target_bool:
        put(sym, key, val.to_bool());
        break;
    case property_types::target_integer:
        put(sym, key, val.to_int());
        break;
    case property_types::target_double:
        put(sym, key, val.to_double());
        break;
    case property_types::target_color:
        put(sym, key, mapnik::parse_color(val.to_string()));
        break;
    default:
        break;
    }
}

namespace detail {
// helpers
template <typename Symbolizer, typename T, bool is_enum = false>
struct set_symbolizer_property_impl
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const& node)
    {
        using value_type = T;
        try
        {
            boost::optional<value_type> val = node.get_opt_attr<value_type>(name);
            if (val) put(sym, key, *val);
        }
        catch (config_error const& ex)
        {
            // try parsing as an expression
            boost::optional<expression_ptr> val = node.get_opt_attr<expression_ptr>(name);
            if (val)
            {
                // first try pre-evaluate expressions which don't have dynamic properties
                auto result = pre_evaluate_expression<mapnik::value>(*val);
                if (std::get<1>(result))
                {
                    set_property_from_value(sym, key,std::get<0>(result));
                }
                else
                {
                    // expression_ptr
                    put(sym, key, *val);
                }
            }
            else
            {
                ex.append_context(std::string("set_symbolizer_property '") + name + "'", node);
                throw;
            }
        }
    }
};

template <typename Symbolizer>
struct set_symbolizer_property_impl<Symbolizer,transform_type,false>
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const & node)
    {
        boost::optional<std::string> transform = node.get_opt_attr<std::string>(name);
        if (transform) put(sym, key, mapnik::parse_transform(*transform));
    }
};

template <typename Symbolizer>
struct set_symbolizer_property_impl<Symbolizer,dash_array,false>
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const & node)
    {
        boost::optional<std::string> str = node.get_opt_attr<std::string>(name);
        if (str)
        {
            std::vector<double> buf;
            dash_array dash;
            if (util::parse_dasharray((*str).begin(),(*str).end(),buf) && util::add_dashes(buf,dash))
            {
                put(sym,key,dash);
            }
            else
            {
                boost::optional<expression_ptr> val = node.get_opt_attr<expression_ptr>(name);
                if (val)
                {
                    // first try pre-evaluate expressions which don't have dynamic properties
                    auto result = pre_evaluate_expression<mapnik::value>(*val);
                    if (std::get<1>(result))
                    {
                        set_property_from_value(sym, key,std::get<0>(result));
                    }
                    else
                    {
                        // expression_ptr
                        put(sym, key, *val);
                    }
                }
                else
                {
                    throw config_error(std::string("Failed to parse dasharray ") +
                                       "'. Expected a " +
                                       "list of floats or 'none' but got '" + (*str) + "'");
                }
            }
        }
    }
};

template <typename Symbolizer, typename T>
struct set_symbolizer_property_impl<Symbolizer, T, true>
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const & node)
    {
        using value_type = T;
        try
        {
            boost::optional<std::string> enum_str = node.get_opt_attr<std::string>(name);
            if (enum_str)
            {
                boost::optional<T> enum_val = detail::enum_traits<T>::from_string(*enum_str);
                if (enum_val)
                {
                    put(sym, key, *enum_val);
                }
                else
                {
                    boost::optional<expression_ptr> val = node.get_opt_attr<expression_ptr>(name);
                    if (val)
                    {
                        // first try pre-evaluating expression
                        auto result = pre_evaluate_expression<value>(*val);
                        if (std::get<1>(result))
                        {
                            boost::optional<T> enum_val = detail::enum_traits<T>::from_string(std::get<0>(result).to_string());
                            if (enum_val)
                            {
                                put(sym, key, *enum_val);
                            }
                            else
                            {
                                // can't evaluate
                                throw config_error("failed to parse symbolizer property: '" + name + "'");
                            }
                        }
                        else
                        {
                            // put expression_ptr
                            put(sym, key, *val);
                        }
                    }
                    else
                    {
                        throw config_error("failed to parse symbolizer property: '" + name + "'");
                    }
                }
            }
        }
        catch (config_error const& ex)
        {
            ex.append_context(std::string("set_symbolizer_property '") + name + "'", node);
            throw;
        }
    }
};

} // namespace detail

template <typename Symbolizer, typename T>
bool set_symbolizer_property(Symbolizer & sym, keys key, xml_node const& node)
{
    std::string const& name = std::get<0>(get_meta(key));
    if (node.has_attribute(name)) {
        detail::set_symbolizer_property_impl<Symbolizer,T, std::is_enum<T>::value>::apply(sym,key,name,node);
    }
}

}

#endif // MAPNIK_SYMBOLIZER_UTILS_HPP
<commit_msg>fix return type<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_SYMBOLIZER_UTILS_HPP
#define MAPNIK_SYMBOLIZER_UTILS_HPP

// mapnik
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/path_expression.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/color.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/transform_processor.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/xml_tree.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/evaluate_global_attributes.hpp>
#include <mapnik/parse_transform.hpp>
#include <mapnik/util/variant.hpp>

namespace mapnik {

template <typename Symbolizer>
struct symbolizer_traits
{
    static char const* name() { return "Unknown";}
};

template<>
struct symbolizer_traits<point_symbolizer>
{
    static char const* name() { return "PointSymbolizer";}
};

template<>
struct symbolizer_traits<line_symbolizer>
{
    static char const* name() { return "LineSymbolizer";}
};

template<>
struct symbolizer_traits<polygon_symbolizer>
{
    static char const* name() { return "PolygonSymbolizer";}
};

template<>
struct symbolizer_traits<text_symbolizer>
{
    static char const* name() { return "TextSymbolizer";}
};

template<>
struct symbolizer_traits<line_pattern_symbolizer>
{
    static char const* name() { return "LinePatternSymbolizer";}
};

template<>
struct symbolizer_traits<polygon_pattern_symbolizer>
{
    static char const* name() { return "PolygonPatternSymbolizer";}
};

template<>
struct symbolizer_traits<markers_symbolizer>
{
    static char const* name() { return "MarkersSymbolizer";}
};

template<>
struct symbolizer_traits<shield_symbolizer>
{
    static char const* name() { return "ShieldSymbolizer";}
};

template<>
struct symbolizer_traits<raster_symbolizer>
{
    static char const* name() { return "RasterSymbolizer";}
};

template<>
struct symbolizer_traits<building_symbolizer>
{
    static char const* name() { return "BuildingSymbolizer";}
};

template<>
struct symbolizer_traits<group_symbolizer>
{
    static char const* name() { return "GroupSymbolizer";}
};

template<>
struct symbolizer_traits<debug_symbolizer>
{
    static char const* name() { return "DebugSymbolizer";}
};

// symbolizer name impl
namespace detail {

struct symbolizer_name_impl : public util::static_visitor<std::string>
{
public:
    template <typename Symbolizer>
    std::string operator () (Symbolizer const&) const
    {
        return symbolizer_traits<Symbolizer>::name();
    }
};
}

inline std::string symbolizer_name(symbolizer const& sym)
{
    std::string type = util::apply_visitor( detail::symbolizer_name_impl(), sym);
    return type;
}

template <typename Meta>
class symbolizer_property_value_string : public util::static_visitor<std::string>
{
public:
    symbolizer_property_value_string (Meta const& meta)
        : meta_(meta) {}

    std::string operator() ( mapnik::enumeration_wrapper const& e) const
    {
        std::stringstream ss;
        auto const& convert_fun_ptr(std::get<2>(meta_));
        if ( convert_fun_ptr )
        {
            ss << convert_fun_ptr(e);
        }
        return ss.str();
    }

    std::string operator () ( path_expression_ptr const& expr) const
    {
        std::ostringstream ss;
        if (expr)
        {
            ss << '\"' << path_processor::to_string(*expr) << '\"';
        }
        return ss.str();
    }

    std::string operator () (text_placements_ptr const& expr) const
    {
        return std::string("\"<fixme-text-placement-ptr>\"");
    }

    std::string operator () (raster_colorizer_ptr const& expr) const
    {
        return std::string("\"<fixme-raster-colorizer-ptr>\"");
    }

    std::string operator () (transform_type const& expr) const
    {
        std::ostringstream ss;
        if (expr)
        {
            ss << '\"' << transform_processor_type::to_string(*expr) << '\"';
        }
        return ss.str();
    }

    std::string operator () (expression_ptr const& expr) const
    {
        std::ostringstream ss;
        if (expr)
        {
            ss << '\"' << "FIXME" /*mapnik::to_expression_string(*expr)*/ <<  '\"';
        }
        return ss.str();
    }

    std::string operator () (color const& c) const
    {
        std::ostringstream ss;
        ss << '\"' << c << '\"';
        return ss.str();
    }

    std::string operator () (dash_array const& dash) const
    {
        std::ostringstream ss;
        for (std::size_t i = 0; i < dash.size(); ++i)
        {
            ss << dash[i].first << ", " << dash[i].second;
            if ( i + 1 < dash.size() ) ss << ',';
        }
        return ss.str();
    }

    template <typename T>
    std::string operator () ( T const& val ) const
    {
        std::ostringstream ss;
        ss << val;
        return ss.str();
    }

private:
    Meta const& meta_;
};

struct symbolizer_to_json : public util::static_visitor<std::string>
{
    using result_type = std::string;

    template <typename T>
    auto operator() (T const& sym) const -> result_type
    {
        std::stringstream ss;
        ss << "{\"type\":\"" << mapnik::symbolizer_traits<T>::name() << "\",";
        ss << "\"properties\":{";
        bool first = true;
        for (auto const& prop : sym.properties)
        {
            auto const& meta = mapnik::get_meta(prop.first);
            if (first) first = false;
            else ss << ",";
            ss << "\"" <<  std::get<0>(meta) << "\":";
            ss << util::apply_visitor(symbolizer_property_value_string<property_meta_type>(meta),prop.second);
        }
        ss << "}}";
        return ss.str();
    }
};

namespace {

template <typename Symbolizer, typename T>
struct set_property_impl
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        std::cerr << "do nothing" << std::endl;
    }
};

template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_color> >
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        put(sym, key, mapnik::parse_color(val));
    }
};

template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_double> >
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        std::cerr << " expects double" << std::endl;
    }
};

template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_bool> >
{
    static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
    {
        std::cerr << " expects bool" << std::endl;
    }
};

}

template <typename Symbolizer, typename T>
inline void set_property(Symbolizer & sym, mapnik::keys key, T const& val)
{
    switch (std::get<3>(get_meta(key)))
    {
    case property_types::target_bool:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_bool> >::apply(sym,key,val);
        break;
    case property_types::target_integer:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_integer> >::apply(sym,key,val);
        break;
    case property_types::target_double:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_double> >::apply(sym,key,val);
        break;
    case property_types::target_color:
        set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_color> >::apply(sym,key,val);
        break;
    default:
        break;
    }
}

template <typename Symbolizer, typename T>
inline void set_property_from_value(Symbolizer & sym, mapnik::keys key, T const& val)
{
    switch (std::get<3>(get_meta(key)))
    {
    case property_types::target_bool:
        put(sym, key, val.to_bool());
        break;
    case property_types::target_integer:
        put(sym, key, val.to_int());
        break;
    case property_types::target_double:
        put(sym, key, val.to_double());
        break;
    case property_types::target_color:
        put(sym, key, mapnik::parse_color(val.to_string()));
        break;
    default:
        break;
    }
}

namespace detail {
// helpers
template <typename Symbolizer, typename T, bool is_enum = false>
struct set_symbolizer_property_impl
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const& node)
    {
        using value_type = T;
        try
        {
            boost::optional<value_type> val = node.get_opt_attr<value_type>(name);
            if (val) put(sym, key, *val);
        }
        catch (config_error const& ex)
        {
            // try parsing as an expression
            boost::optional<expression_ptr> val = node.get_opt_attr<expression_ptr>(name);
            if (val)
            {
                // first try pre-evaluate expressions which don't have dynamic properties
                auto result = pre_evaluate_expression<mapnik::value>(*val);
                if (std::get<1>(result))
                {
                    set_property_from_value(sym, key,std::get<0>(result));
                }
                else
                {
                    // expression_ptr
                    put(sym, key, *val);
                }
            }
            else
            {
                ex.append_context(std::string("set_symbolizer_property '") + name + "'", node);
                throw;
            }
        }
    }
};

template <typename Symbolizer>
struct set_symbolizer_property_impl<Symbolizer,transform_type,false>
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const & node)
    {
        boost::optional<std::string> transform = node.get_opt_attr<std::string>(name);
        if (transform) put(sym, key, mapnik::parse_transform(*transform));
    }
};

template <typename Symbolizer>
struct set_symbolizer_property_impl<Symbolizer,dash_array,false>
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const & node)
    {
        boost::optional<std::string> str = node.get_opt_attr<std::string>(name);
        if (str)
        {
            std::vector<double> buf;
            dash_array dash;
            if (util::parse_dasharray((*str).begin(),(*str).end(),buf) && util::add_dashes(buf,dash))
            {
                put(sym,key,dash);
            }
            else
            {
                boost::optional<expression_ptr> val = node.get_opt_attr<expression_ptr>(name);
                if (val)
                {
                    // first try pre-evaluate expressions which don't have dynamic properties
                    auto result = pre_evaluate_expression<mapnik::value>(*val);
                    if (std::get<1>(result))
                    {
                        set_property_from_value(sym, key,std::get<0>(result));
                    }
                    else
                    {
                        // expression_ptr
                        put(sym, key, *val);
                    }
                }
                else
                {
                    throw config_error(std::string("Failed to parse dasharray ") +
                                       "'. Expected a " +
                                       "list of floats or 'none' but got '" + (*str) + "'");
                }
            }
        }
    }
};

template <typename Symbolizer, typename T>
struct set_symbolizer_property_impl<Symbolizer, T, true>
{
    static void apply(Symbolizer & sym, keys key, std::string const& name, xml_node const & node)
    {
        using value_type = T;
        try
        {
            boost::optional<std::string> enum_str = node.get_opt_attr<std::string>(name);
            if (enum_str)
            {
                boost::optional<T> enum_val = detail::enum_traits<T>::from_string(*enum_str);
                if (enum_val)
                {
                    put(sym, key, *enum_val);
                }
                else
                {
                    boost::optional<expression_ptr> val = node.get_opt_attr<expression_ptr>(name);
                    if (val)
                    {
                        // first try pre-evaluating expression
                        auto result = pre_evaluate_expression<value>(*val);
                        if (std::get<1>(result))
                        {
                            boost::optional<T> enum_val = detail::enum_traits<T>::from_string(std::get<0>(result).to_string());
                            if (enum_val)
                            {
                                put(sym, key, *enum_val);
                            }
                            else
                            {
                                // can't evaluate
                                throw config_error("failed to parse symbolizer property: '" + name + "'");
                            }
                        }
                        else
                        {
                            // put expression_ptr
                            put(sym, key, *val);
                        }
                    }
                    else
                    {
                        throw config_error("failed to parse symbolizer property: '" + name + "'");
                    }
                }
            }
        }
        catch (config_error const& ex)
        {
            ex.append_context(std::string("set_symbolizer_property '") + name + "'", node);
            throw;
        }
    }
};

} // namespace detail

template <typename Symbolizer, typename T>
void set_symbolizer_property(Symbolizer & sym, keys key, xml_node const& node)
{
    std::string const& name = std::get<0>(get_meta(key));
    if (node.has_attribute(name)) {
        detail::set_symbolizer_property_impl<Symbolizer,T, std::is_enum<T>::value>::apply(sym,key,name,node);
    }
}

}

#endif // MAPNIK_SYMBOLIZER_UTILS_HPP
<|endoftext|>


<commit_before>/*
 * PerfectSensorProcessor.hpp
 *
 *  Created on: Sep 28, 2014
 *      Author: Péter Fankhauser
 *   Institute: ETH Zurich, ANYbotics
 */

#pragma once

#include <elevation_mapping/sensor_processors/SensorProcessorBase.hpp>

namespace elevation_mapping {

/*!
 * Sensor processor for laser range sensors.
 */
class PerfectSensorProcessor : public SensorProcessorBase
{

public:

  /*!
   * Constructor.
   * @param nodeHandle the ROS node handle.
   * @param transformListener the ROS transform listener.
   */
  PerfectSensorProcessor(ros::NodeHandle& nodeHandle, tf::TransformListener& transformListener);

  /*!
   * Destructor.
   */
  virtual ~PerfectSensorProcessor();

private:

  /*!
   * Reads and verifies the parameters.
   * @return true if successful.
   */
  bool readParameters();

  /*!
   * Clean the point cloud. Points below the minimal and above the maximal sensor
   * cutoff value are dropped.
   * @param pointCloud the point cloud to clean.
   * @return true if successful.
   */
  virtual bool cleanPointCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointCloud);

  /*!
   * Computes the elevation map height variances for each point in a point cloud with the
   * sensor model and the robot pose covariance.
   * @param[in] pointCloud the point cloud for which the variances are computed.
   * @param[in] robotPoseCovariance the robot pose covariance matrix.
   * @param[out] variances the elevation map height variances.
   * @return true if successful.
   */
  virtual bool computeVariances(
    const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr pointCloud,
    const Eigen::Matrix<double, 6, 6>& robotPoseCovariance,
    Eigen::VectorXf& variances);
};

} /* namespace elevation_mapping */
<commit_msg>Added missing white spaces<commit_after>/*
 * PerfectSensorProcessor.hpp
 *
 *  Created on: Sep 28, 2014
 *      Author: Péter Fankhauser
 *   Institute: ETH Zurich, ANYbotics
 */

#pragma once

#include <elevation_mapping/sensor_processors/SensorProcessorBase.hpp>

namespace elevation_mapping {

/*!
 * Sensor processor for laser range sensors.
 */
class PerfectSensorProcessor : public SensorProcessorBase
{

public:

  /*!
   * Constructor.
   * @param nodeHandle the ROS node handle.
   * @param transformListener the ROS transform listener.
   */
  PerfectSensorProcessor(ros::NodeHandle& nodeHandle, tf::TransformListener& transformListener);

  /*!
   * Destructor.
   */
  virtual ~PerfectSensorProcessor();

private:

  /*!
   * Reads and verifies the parameters.
   * @return true if successful.
   */
  bool readParameters();

  /*!
   * Clean the point cloud. Points below the minimal and above the maximal sensor
   * cutoff value are dropped.
   * @param pointCloud the point cloud to clean.
   * @return true if successful.
   */
  virtual bool cleanPointCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointCloud);

  /*!
   * Computes the elevation map height variances for each point in a point cloud with the
   * sensor model and the robot pose covariance.
   * @param[in] pointCloud the point cloud for which the variances are computed.
   * @param[in] robotPoseCovariance the robot pose covariance matrix.
   * @param[out] variances the elevation map height variances.
   * @return true if successful.
   */
  virtual bool computeVariances(
      const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr pointCloud,
      const Eigen::Matrix<double, 6, 6>& robotPoseCovariance,
      Eigen::VectorXf& variances);
};

} /* namespace elevation_mapping */
<|endoftext|>


<commit_before>#ifndef PICOLIB_SOCKET_IMPL_H_
#define PICOLIB_SOCKET_IMPL_H_

#include <sys/un.h>

namespace Pico {

    namespace Network {

        FUNCTION
        uint16_t _htons(uint16_t port)
        {
            return cpu_to_be16(port);
        }

        template <enum AddressType>
        struct Sockaddr;

        template <>
        struct Sockaddr<IPV4>
        {
            static constexpr int family = AF_INET;
            typedef struct sockaddr_in type;

            FUNCTION
            struct sockaddr_in pack(IpAddress const ip, uint16_t port)
            {
                struct sockaddr_in addr;

                addr.sin_family         = family;
                addr.sin_port           = _htons(port);
                addr.sin_addr.s_addr    = ip.value;

                return addr;
            }
        };

        template <>
        struct Sockaddr<IPV6>
        {
            static constexpr int family = AF_INET6;
            typedef struct sockaddr_in6 type;

            FUNCTION
            struct sockaddr_in6 pack(IpAddress6 const ip, uint16_t port)
            {
                struct sockaddr_in6 addr;

                addr.sin6_flowinfo      = 0;
                addr.sin6_family        = AF_INET6;
                addr.sin6_port          = _htons(port);
                Memory::copy(&addr.sin6_addr.s6_addr, &ip, sizeof(ip));

                return addr;
            }
        };

        template <>
        struct Sockaddr<UNIX>
        {
            static constexpr int family = AF_UNIX;
            typedef struct sockaddr_un type;

            FUNCTION
            struct sockaddr_un pack(UnixAddress const unixaddr)
            {
                struct sockaddr_un addr;

                addr.sun_family = AF_UNIX;
                strcpy(addr.sun_path, unixaddr.path);

                return addr;
            }
        };

        template <>
        struct Sockaddr<UNIX_ABSTRACT>
        {
            static constexpr int family = AF_UNIX;
            typedef struct sockaddr_un type;

            FUNCTION
            struct sockaddr_un pack(UnixAbstractAddress const unixaddr)
            {
                struct sockaddr_un addr;

                addr.sun_family = AF_UNIX;
                addr.sun_path[0] = '\0';
                strcpy(addr.sun_path + 1, unixaddr.path);

                return addr;
            }
        };

        METHOD
        ssize_t SocketIO::in(void *buf, size_t count)
        {
            return Syscall::recv(fd, buf, count, MSG_WAITALL);
        }

        METHOD
        ssize_t SocketIO::out(const void *buf, size_t count)
        {
            // Use write(2) instead of send(2) since it takes 3 arguments instead of 4.
            // This produces slightly smaller code.

            return Syscall::write(fd, buf, count);
        }

        METHOD
        int SocketIO::close()
        {
            return Syscall::close(fd);
        }

        CONSTRUCTOR
        Socket::Socket(int domain, int type, int protocol) : Socket( Syscall::socket(domain, type, protocol) ) {}

        METHOD
        int Socket::get(int level, int optname, void *val, unsigned *len)
        {
            return Syscall::getsockopt(this->file_desc(), level, optname, val, len);
        }

        METHOD
        int Socket::set(int level, int optname, void *val, unsigned len)
        {
            return Syscall::setsockopt(this->file_desc(), level, optname, val, len);
        }

        template <enum AddressType T>
        METHOD
        int Socket::bind(Address<T> addr)
        {
            static_assert(T == UNIX || T == UNIX_ABSTRACT, "This method only supports UNIX address sockets.");

            auto bind_addr = Sockaddr<T>::pack(addr);
            return Syscall::bind(this->file_desc(), reinterpret_cast<struct sockaddr *>(&bind_addr), sizeof(bind_addr));
        }

        template <enum AddressType T>
        METHOD
        int Socket::bind(Address<T> addr, uint16_t port, bool reuse_addr)
        {
            if ( reuse_addr )
            {
                int option = 1;
                set(SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
            }

            auto bind_addr = Sockaddr<T>::pack(addr, port);
            return Syscall::bind(this->file_desc(), reinterpret_cast<struct sockaddr *>(&bind_addr), sizeof(bind_addr));
        }

        template <enum AddressType T>
        METHOD
        int StreamSocket::connect(Address<T> addr)
        {
            static_assert(T == UNIX || T == UNIX_ABSTRACT, "This method only supports UNIX address sockets.");
            auto serv_addr = Sockaddr<T>::pack(addr);

            return Syscall::connect(this->file_desc(), reinterpret_cast<struct sockaddr *>(&serv_addr), sizeof(serv_addr));
        }

        template <enum AddressType T>
        METHOD
        int StreamSocket::connect(Address<T> addr, uint16_t port)
        {
            auto serv_addr = Sockaddr<T>::pack(addr, port);

            return Syscall::connect(this->file_desc(), reinterpret_cast<struct sockaddr *>(&serv_addr), sizeof(serv_addr));
        }

        METHOD
        int StreamSocket::listen(int backlog)
        {
            return Syscall::listen(this->file_desc(), backlog);
        }

        template <bool Fork>
        METHOD
        StreamSocket StreamSocket::accept()
        {
            do {
                int client_fd = Syscall::accept(this->file_desc(), nullptr, 0);
                if ( fork )
                {
                    if ( Syscall::fork() == 0 )
                        return StreamSocket(client_fd);
                    else
                        Syscall::close(client_fd);
                }
                else
                    return StreamSocket(client_fd);

            } while ( fork );
        }
    }
}

#endif
<commit_msg>socket: fix fork bug in accept<commit_after>#ifndef PICOLIB_SOCKET_IMPL_H_
#define PICOLIB_SOCKET_IMPL_H_

#include <sys/un.h>

namespace Pico {

    namespace Network {

        FUNCTION
        uint16_t _htons(uint16_t port)
        {
            return cpu_to_be16(port);
        }

        template <enum AddressType>
        struct Sockaddr;

        template <>
        struct Sockaddr<IPV4>
        {
            static constexpr int family = AF_INET;
            typedef struct sockaddr_in type;

            FUNCTION
            struct sockaddr_in pack(IpAddress const ip, uint16_t port)
            {
                struct sockaddr_in addr;

                addr.sin_family         = family;
                addr.sin_port           = _htons(port);
                addr.sin_addr.s_addr    = ip.value;

                return addr;
            }
        };

        template <>
        struct Sockaddr<IPV6>
        {
            static constexpr int family = AF_INET6;
            typedef struct sockaddr_in6 type;

            FUNCTION
            struct sockaddr_in6 pack(IpAddress6 const ip, uint16_t port)
            {
                struct sockaddr_in6 addr;

                addr.sin6_flowinfo      = 0;
                addr.sin6_family        = AF_INET6;
                addr.sin6_port          = _htons(port);
                Memory::copy(&addr.sin6_addr.s6_addr, &ip, sizeof(ip));

                return addr;
            }
        };

        template <>
        struct Sockaddr<UNIX>
        {
            static constexpr int family = AF_UNIX;
            typedef struct sockaddr_un type;

            FUNCTION
            struct sockaddr_un pack(UnixAddress const unixaddr)
            {
                struct sockaddr_un addr;

                addr.sun_family = AF_UNIX;
                strcpy(addr.sun_path, unixaddr.path);

                return addr;
            }
        };

        template <>
        struct Sockaddr<UNIX_ABSTRACT>
        {
            static constexpr int family = AF_UNIX;
            typedef struct sockaddr_un type;

            FUNCTION
            struct sockaddr_un pack(UnixAbstractAddress const unixaddr)
            {
                struct sockaddr_un addr;

                addr.sun_family = AF_UNIX;
                addr.sun_path[0] = '\0';
                strcpy(addr.sun_path + 1, unixaddr.path);

                return addr;
            }
        };

        METHOD
        ssize_t SocketIO::in(void *buf, size_t count)
        {
            return Syscall::recv(fd, buf, count, MSG_WAITALL);
        }

        METHOD
        ssize_t SocketIO::out(const void *buf, size_t count)
        {
            // Use write(2) instead of send(2) since it takes 3 arguments instead of 4.
            // This produces slightly smaller code.

            return Syscall::write(fd, buf, count);
        }

        METHOD
        int SocketIO::close()
        {
            return Syscall::close(fd);
        }

        CONSTRUCTOR
        Socket::Socket(int domain, int type, int protocol) : Socket( Syscall::socket(domain, type, protocol) ) {}

        METHOD
        int Socket::get(int level, int optname, void *val, unsigned *len)
        {
            return Syscall::getsockopt(this->file_desc(), level, optname, val, len);
        }

        METHOD
        int Socket::set(int level, int optname, void *val, unsigned len)
        {
            return Syscall::setsockopt(this->file_desc(), level, optname, val, len);
        }

        template <enum AddressType T>
        METHOD
        int Socket::bind(Address<T> addr)
        {
            static_assert(T == UNIX || T == UNIX_ABSTRACT, "This method only supports UNIX address sockets.");

            auto bind_addr = Sockaddr<T>::pack(addr);
            return Syscall::bind(this->file_desc(), reinterpret_cast<struct sockaddr *>(&bind_addr), sizeof(bind_addr));
        }

        template <enum AddressType T>
        METHOD
        int Socket::bind(Address<T> addr, uint16_t port, bool reuse_addr)
        {
            if ( reuse_addr )
            {
                int option = 1;
                set(SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
            }

            auto bind_addr = Sockaddr<T>::pack(addr, port);
            return Syscall::bind(this->file_desc(), reinterpret_cast<struct sockaddr *>(&bind_addr), sizeof(bind_addr));
        }

        template <enum AddressType T>
        METHOD
        int StreamSocket::connect(Address<T> addr)
        {
            static_assert(T == UNIX || T == UNIX_ABSTRACT, "This method only supports UNIX address sockets.");
            auto serv_addr = Sockaddr<T>::pack(addr);

            return Syscall::connect(this->file_desc(), reinterpret_cast<struct sockaddr *>(&serv_addr), sizeof(serv_addr));
        }

        template <enum AddressType T>
        METHOD
        int StreamSocket::connect(Address<T> addr, uint16_t port)
        {
            auto serv_addr = Sockaddr<T>::pack(addr, port);

            return Syscall::connect(this->file_desc(), reinterpret_cast<struct sockaddr *>(&serv_addr), sizeof(serv_addr));
        }

        METHOD
        int StreamSocket::listen(int backlog)
        {
            return Syscall::listen(this->file_desc(), backlog);
        }

        template <bool Fork>
        METHOD
        StreamSocket StreamSocket::accept()
        {
            do {
                int client_fd = Syscall::accept(this->file_desc(), nullptr, 0);
                if ( Fork )
                {
                    if ( Syscall::fork() == 0 )
                        return StreamSocket(client_fd);
                    else
                        Syscall::close(client_fd);
                }
                else
                    return StreamSocket(client_fd);

            } while ( Fork );
        }
    }
}

#endif
<|endoftext|>


<commit_before>#ifndef VSMC_UTILITY_CL_MANAGER_HPP
#define VSMC_UTILITY_CL_MANAGER_HPP

#include <vsmc/internal/config.hpp>
#include <vsmc/internal/assert.hpp>
#include <vsmc/internal/defines.hpp>
#include <vsmc/internal/forward.hpp>
#include <vsmc/internal/traits.hpp>
#include <vsmc/utility/cl_wrapper.hpp>

#include <cstddef>
#include <cstdlib>
#include <string>
#include <vector>

namespace vsmc {

struct CLDefault
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_DEFAULT>
        opencl_device_type;
};

/// \brief OpenCL Manager
/// \ingroup Utility
template <typename ID>
class CLManager
{
    public :

    static CLManager<ID> &instance ()
    {
        static CLManager<ID> manager;

        return manager;
    }

    const cl::Platform &platform () const
    {
        return platform_;
    }

    const std::vector<cl::Platform> &platform_vec () const
    {
        return platform_vec_;
    }

    const cl::Context &context () const
    {
        return context_;
    }

    const cl::Device &device () const
    {
        return device_;
    }

    const std::vector<cl::Device> &device_vec () const
    {
        return device_vec_;
    }

    const cl::CommandQueue &command_queue () const
    {
        return command_queue_;
    }

    bool setup () const
    {
        return setup_;
    }

    void setup (cl_device_type dev)
    {
        setup_ = false;
        setup_cl_manager(dev);
    }

    void setup (const cl::Platform &plat, const cl::Context &ctx,
            const cl::Device &dev, const cl::CommandQueue &cmd)
    {
        setup_ = false;
        platform_ = plat;
        cl::Platform::get(&platform_vec_);
        context_ = ctx;
        device_ = dev;
        device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();
        command_queue_ = cmd;
        setup_ = true;
    }

    template<typename CLType>
    cl::Buffer create_buffer (std::size_t num) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);

        if (!num)
            return cl::Buffer();

        return cl::Buffer(context_, CL_MEM_READ_WRITE, sizeof(CLType) * num);
    }

    template<typename CLType, typename InputIter>
    cl::Buffer create_buffer (InputIter first, InputIter last) const
    {
        using std::distance;

        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);

        std::size_t num = static_cast<std::size_t>(
                std::abs(distance(first, last)));

        if (!num)
            return cl::Buffer();

        cl::Buffer buf(create_buffer<CLType>(num));
        write_buffer<CLType>(buf, num, first);

        return buf;
    }

    template <typename CLType, typename OutputIter>
    OutputIter read_buffer (const cl::Buffer &buf, std::size_t num,
            OutputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        CLType *temp = read_buffer_pool<CLType>(num);
        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) temp);

        for (std::size_t i = 0; i != num; ++i, ++first)
            *first = temp[i];

        return first;
    }

    template <typename CLType>
    CLType *read_buffer (const cl::Buffer &buf, std::size_t num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) first);

        return first + num;
    }

    template <typename CLType, typename InputIter>
    InputIter write_buffer (const cl::Buffer &buf, std::size_t num,
            InputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        CLType *temp = write_buffer_pool<CLType>(num);
        for (std::size_t i = 0; i != num; ++i, ++first)
            temp[i] = *first;
        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) temp);

        return first;
    }

    template <typename CLType>
    const CLType *write_buffer (const cl::Buffer &buf, std::size_t num,
            const CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) first);

        return first + num;
    }

    template <typename CLType>
    CLType *write_buffer (const cl::Buffer &buf, std::size_t num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) first);

        return first + num;
    }

    template <typename CLType>
    void copy_buffer (const cl::Buffer &src, std::size_t num,
            const cl::Buffer &dst) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(copy_buffer);

        command_queue_.finish();
        command_queue_.enqueueCopyBuffer(src, dst, 0, 0, sizeof(CLType) * num);
        command_queue_.finish();
    }

    cl::Program create_program (const std::string &source) const
    {
        return cl::Program(context_, source);
    }

    void run_kernel (const cl::Kernel &kern,
            std::size_t global_size, std::size_t local_size) const
    {
        command_queue_.finish();
        command_queue_.enqueueNDRangeKernel(kern, cl::NullRange,
                get_global_nd_range(global_size, local_size),
                get_local_nd_range(global_size, local_size));
        command_queue_.finish();
    }

    private :

    cl::Platform platform_;
    std::vector<cl::Platform> platform_vec_;
    cl::Context context_;
    cl::Device device_;
    std::vector<cl::Device> device_vec_;
    cl::CommandQueue command_queue_;

    bool setup_;

    mutable std::size_t read_buffer_pool_bytes_;
    mutable std::size_t write_buffer_pool_bytes_;
    mutable void *read_buffer_pool_;
    mutable void *write_buffer_pool_;

    CLManager () :
        setup_(false), read_buffer_pool_bytes_(0), write_buffer_pool_bytes_(0),
        read_buffer_pool_(VSMC_NULLPTR), write_buffer_pool_(VSMC_NULLPTR)
    {
        cl_device_type dev = OpenCLDeviceTypeTrait<ID>::value ?
            OpenCLDeviceTypeTrait<ID>::type::value :
            CLDefault::opencl_device_type::value;
        setup_cl_manager(dev);
    }

    CLManager (const CLManager<ID> &);
    CLManager<ID> &operator= (const CLManager<ID> &);

    ~CLManager ()
    {
        std::free(read_buffer_pool_);
        std::free(write_buffer_pool_);
    }

    void setup_cl_manager (cl_device_type dev)
    {
        try {
            cl::Platform::get(&platform_vec_);
        } catch (cl::Error) {
            platform_vec_.clear();
        }

        for (std::size_t p = 0; p != platform_vec_.size(); ++p) {
            try {
                platform_ = platform_vec_[p];
                std::string pname;
                platform_.getInfo(CL_PLATFORM_NAME, &pname);
                if (!CheckOpenCLPlatformTrait<ID>::check(pname)) {
                    platform_ = cl::Platform();
                    continue;
                }

                cl_context_properties context_properties[] = {
                    CL_CONTEXT_PLATFORM,
                    (cl_context_properties)(platform_)(), 0
                };
                context_ = cl::Context(dev, context_properties);
                device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();

                bool device_found = false;
                for (std::size_t d = 0; d != device_vec_.size(); ++d) {
                    std::string dname;
                    device_vec_[d].getInfo(CL_DEVICE_NAME, &dname);
                    if (CheckOpenCLDeviceTrait<ID>::check(dname)) {
                        device_ = device_vec_[d];
                        device_found = true;
                        break;
                    }
                }
                if (!device_found) {
                    platform_ = cl::Platform();
                    context_  = cl::Context();
                    device_   = cl::Device();
                    continue;
                }

                command_queue_ = cl::CommandQueue(context_, device_, 0);
                setup_ = true;
                break;
            } catch (cl::Error) {
                platform_      = cl::Platform();
                context_       = cl::Context();
                device_        = cl::Device();
                command_queue_ = cl::CommandQueue();
                device_vec_.clear();
            }
        }
    }

    template <typename CLType>
    CLType *read_buffer_pool (std::size_t num) const
    {
        std::size_t new_bytes = num * sizeof(CLType);
        if (new_bytes > read_buffer_pool_bytes_) {
            std::free(read_buffer_pool_);
            read_buffer_pool_ = std::malloc(new_bytes);
            if (!read_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            read_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(read_buffer_pool_);
    }

    template <typename CLType>
    CLType *write_buffer_pool (std::size_t num) const
    {
        std::size_t new_bytes = num * sizeof(CLType);
        if (new_bytes > write_buffer_pool_bytes_) {
            std::free(write_buffer_pool_);
            write_buffer_pool_ = std::malloc(new_bytes);
            if (!write_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            write_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(write_buffer_pool_);
    }

    cl::NDRange get_global_nd_range (
            std::size_t global_size, std::size_t local_size) const
    {
        return (local_size && global_size % local_size) ?
            cl::NDRange((global_size / local_size + 1) * local_size):
            cl::NDRange(global_size);
    }

    cl::NDRange get_local_nd_range (
            std::size_t global_size, std::size_t local_size) const
    {
        return local_size ? cl::NDRange(local_size) : cl::NullRange;
    }
}; // clss CLManager

} // namespace vsmc

#endif // VSMC_UTILITY_CL_MANAGER_HPP
<commit_msg>gmm cl save counters between kernels<commit_after>#ifndef VSMC_UTILITY_CL_MANAGER_HPP
#define VSMC_UTILITY_CL_MANAGER_HPP

#include <vsmc/internal/config.hpp>
#include <vsmc/internal/assert.hpp>
#include <vsmc/internal/defines.hpp>
#include <vsmc/internal/forward.hpp>
#include <vsmc/internal/traits.hpp>
#include <vsmc/utility/cl_wrapper.hpp>

#include <cstddef>
#include <cstdlib>
#include <string>
#include <vector>

namespace vsmc {

struct CLDefault
{
    typedef cxx11::integral_constant<cl_device_type, CL_DEVICE_TYPE_DEFAULT>
        opencl_device_type;
};

/// \brief OpenCL Manager
/// \ingroup Utility
template <typename ID>
class CLManager
{
    public :

    static CLManager<ID> &instance ()
    {
        static CLManager<ID> manager;

        return manager;
    }

    const cl::Platform &platform () const
    {
        return platform_;
    }

    const std::vector<cl::Platform> &platform_vec () const
    {
        return platform_vec_;
    }

    const cl::Context &context () const
    {
        return context_;
    }

    const cl::Device &device () const
    {
        return device_;
    }

    const std::vector<cl::Device> &device_vec () const
    {
        return device_vec_;
    }

    const cl::CommandQueue &command_queue () const
    {
        return command_queue_;
    }

    bool setup () const
    {
        return setup_;
    }

    bool setup (cl_device_type dev)
    {
        setup_ = false;
        setup_cl_manager(dev);

        return setup_;
    }

    bool setup (const cl::Platform &plat, const cl::Context &ctx,
            const cl::Device &dev, const cl::CommandQueue &cmd)
    {
        setup_ = false;
        platform_ = plat;
        cl::Platform::get(&platform_vec_);
        context_ = ctx;
        device_ = dev;
        device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();
        command_queue_ = cmd;
        setup_ = true;

        return setup_;
    }

    template<typename CLType>
    cl::Buffer create_buffer (std::size_t num) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);

        if (!num)
            return cl::Buffer();

        return cl::Buffer(context_, CL_MEM_READ_WRITE, sizeof(CLType) * num);
    }

    template<typename CLType, typename InputIter>
    cl::Buffer create_buffer (InputIter first, InputIter last) const
    {
        using std::distance;

        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(create_buffer);

        std::size_t num = static_cast<std::size_t>(
                std::abs(distance(first, last)));

        if (!num)
            return cl::Buffer();

        cl::Buffer buf(create_buffer<CLType>(num));
        write_buffer<CLType>(buf, num, first);

        return buf;
    }

    template <typename CLType, typename OutputIter>
    OutputIter read_buffer (const cl::Buffer &buf, std::size_t num,
            OutputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        CLType *temp = read_buffer_pool<CLType>(num);
        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) temp);

        for (std::size_t i = 0; i != num; ++i, ++first)
            *first = temp[i];

        return first;
    }

    template <typename CLType>
    CLType *read_buffer (const cl::Buffer &buf, std::size_t num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(read_buffer);

        command_queue_.finish();
        command_queue_.enqueueReadBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) first);

        return first + num;
    }

    template <typename CLType, typename InputIter>
    InputIter write_buffer (const cl::Buffer &buf, std::size_t num,
            InputIter first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        CLType *temp = write_buffer_pool<CLType>(num);
        for (std::size_t i = 0; i != num; ++i, ++first)
            temp[i] = *first;
        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) temp);

        return first;
    }

    template <typename CLType>
    const CLType *write_buffer (const cl::Buffer &buf, std::size_t num,
            const CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) first);

        return first + num;
    }

    template <typename CLType>
    CLType *write_buffer (const cl::Buffer &buf, std::size_t num,
            CLType *first) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(write_buffer);

        command_queue_.finish();
        command_queue_.enqueueWriteBuffer(buf, CL_TRUE, 0,
                sizeof(CLType) * num, (void *) first);

        return first + num;
    }

    template <typename CLType>
    void copy_buffer (const cl::Buffer &src, std::size_t num,
            const cl::Buffer &dst) const
    {
        VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(copy_buffer);

        command_queue_.finish();
        command_queue_.enqueueCopyBuffer(src, dst, 0, 0, sizeof(CLType) * num);
        command_queue_.finish();
    }

    cl::Program create_program (const std::string &source) const
    {
        return cl::Program(context_, source);
    }

    void run_kernel (const cl::Kernel &kern,
            std::size_t global_size, std::size_t local_size) const
    {
        command_queue_.finish();
        command_queue_.enqueueNDRangeKernel(kern, cl::NullRange,
                get_global_nd_range(global_size, local_size),
                get_local_nd_range(global_size, local_size));
        command_queue_.finish();
    }

    private :

    cl::Platform platform_;
    std::vector<cl::Platform> platform_vec_;
    cl::Context context_;
    cl::Device device_;
    std::vector<cl::Device> device_vec_;
    cl::CommandQueue command_queue_;

    bool setup_;

    mutable std::size_t read_buffer_pool_bytes_;
    mutable std::size_t write_buffer_pool_bytes_;
    mutable void *read_buffer_pool_;
    mutable void *write_buffer_pool_;

    CLManager () :
        setup_(false), read_buffer_pool_bytes_(0), write_buffer_pool_bytes_(0),
        read_buffer_pool_(VSMC_NULLPTR), write_buffer_pool_(VSMC_NULLPTR)
    {
        cl_device_type dev = OpenCLDeviceTypeTrait<ID>::value ?
            OpenCLDeviceTypeTrait<ID>::type::value :
            CLDefault::opencl_device_type::value;
        setup_cl_manager(dev);
    }

    CLManager (const CLManager<ID> &);
    CLManager<ID> &operator= (const CLManager<ID> &);

    ~CLManager ()
    {
        std::free(read_buffer_pool_);
        std::free(write_buffer_pool_);
    }

    void setup_cl_manager (cl_device_type dev)
    {
        try {
            cl::Platform::get(&platform_vec_);
        } catch (cl::Error) {
            platform_vec_.clear();
        }

        for (std::size_t p = 0; p != platform_vec_.size(); ++p) {
            try {
                platform_ = platform_vec_[p];
                std::string pname;
                platform_.getInfo(CL_PLATFORM_NAME, &pname);
                if (!CheckOpenCLPlatformTrait<ID>::check(pname)) {
                    platform_ = cl::Platform();
                    continue;
                }

                cl_context_properties context_properties[] = {
                    CL_CONTEXT_PLATFORM,
                    (cl_context_properties)(platform_)(), 0
                };
                context_ = cl::Context(dev, context_properties);
                device_vec_ = context_.getInfo<CL_CONTEXT_DEVICES>();

                bool device_found = false;
                for (std::size_t d = 0; d != device_vec_.size(); ++d) {
                    std::string dname;
                    device_vec_[d].getInfo(CL_DEVICE_NAME, &dname);
                    if (CheckOpenCLDeviceTrait<ID>::check(dname)) {
                        device_ = device_vec_[d];
                        device_found = true;
                        break;
                    }
                }
                if (!device_found) {
                    platform_ = cl::Platform();
                    context_  = cl::Context();
                    device_   = cl::Device();
                    continue;
                }

                command_queue_ = cl::CommandQueue(context_, device_, 0);
                setup_ = true;
                break;
            } catch (cl::Error) {
                platform_      = cl::Platform();
                context_       = cl::Context();
                device_        = cl::Device();
                command_queue_ = cl::CommandQueue();
                device_vec_.clear();
            }
        }
    }

    template <typename CLType>
    CLType *read_buffer_pool (std::size_t num) const
    {
        std::size_t new_bytes = num * sizeof(CLType);
        if (new_bytes > read_buffer_pool_bytes_) {
            std::free(read_buffer_pool_);
            read_buffer_pool_ = std::malloc(new_bytes);
            if (!read_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            read_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(read_buffer_pool_);
    }

    template <typename CLType>
    CLType *write_buffer_pool (std::size_t num) const
    {
        std::size_t new_bytes = num * sizeof(CLType);
        if (new_bytes > write_buffer_pool_bytes_) {
            std::free(write_buffer_pool_);
            write_buffer_pool_ = std::malloc(new_bytes);
            if (!write_buffer_pool_ && new_bytes)
                throw std::bad_alloc();
            write_buffer_pool_bytes_ = new_bytes;
        }

        return reinterpret_cast<CLType *>(write_buffer_pool_);
    }

    cl::NDRange get_global_nd_range (
            std::size_t global_size, std::size_t local_size) const
    {
        return (local_size && global_size % local_size) ?
            cl::NDRange((global_size / local_size + 1) * local_size):
            cl::NDRange(global_size);
    }

    cl::NDRange get_local_nd_range (
            std::size_t global_size, std::size_t local_size) const
    {
        return local_size ? cl::NDRange(local_size) : cl::NullRange;
    }
}; // clss CLManager

} // namespace vsmc

#endif // VSMC_UTILITY_CL_MANAGER_HPP
<|endoftext|>