36 struct EvaluatorInfo {
37 std::shared_ptr<reco::formula::EvaluatorBase> evaluator;
38 std::shared_ptr<reco::formula::EvaluatorBase> top;
40 unsigned int maxNumVariables=0;
41 unsigned int maxNumParameters=0;
44 class ExpressionElementFinderBase {
46 virtual bool checkStart(
char)
const = 0;
48 virtual EvaluatorInfo createEvaluator(std::string::const_iterator, std::string::const_iterator)
const = 0;
51 std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin, std::string::const_iterator iEnd) {
60 for(
auto it = iBegin+1; it != iEnd; ++it) {
64 }
else if (*it ==
')') {
71 return iBegin +
index;
74 class ConstantFinder :
public ExpressionElementFinderBase {
75 virtual bool checkStart(
char iSymbol)
const override final {
76 if( iSymbol ==
'-' or iSymbol ==
'.' or std::isdigit(iSymbol) ) {
82 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final {
87 double value = stod(
s, &endIndex);
89 info.nextParseIndex = endIndex;
90 info.evaluator = std::make_shared<reco::formula::ConstantEvaluator>(
value);
91 info.top = info.evaluator;
92 }
catch ( std::invalid_argument ) {}
100 class ParameterFinder :
public ExpressionElementFinderBase {
101 virtual bool checkStart(
char iSymbol)
const override final {
102 if( iSymbol ==
'[') {
108 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final {
116 info.nextParseIndex = 1;
120 unsigned long value = stoul(
s, &endIndex);
122 if( iBegin+endIndex+1 == iEnd
or *(iBegin+1+endIndex) !=
']' ) {
127 info.nextParseIndex = endIndex+2;
128 info.maxNumParameters = value+1;
129 info.evaluator = std::make_shared<reco::formula::ParameterEvaluator>(
value);
130 info.top = info.evaluator;
131 }
catch ( std::invalid_argument ) {}
138 class VariableFinder :
public ExpressionElementFinderBase {
139 virtual bool checkStart(
char iSymbol)
const override final {
140 if( iSymbol ==
'x' or iSymbol ==
'y' or iSymbol ==
'z' or iSymbol ==
't' ) {
146 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final {
151 unsigned int index = 4;
165 info.nextParseIndex = 1;
166 info.maxNumVariables = index+1;
167 info.evaluator = std::make_shared<reco::formula::VariableEvaluator>(
index);
168 info.top = info.evaluator;
173 class ExpressionFinder;
175 class FunctionFinder :
public ExpressionElementFinderBase {
177 FunctionFinder(ExpressionFinder
const* iEF):
178 m_expressionFinder(iEF) {};
180 virtual bool checkStart(
char iSymbol)
const override final {
181 return std::isalpha(iSymbol);
184 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final;
187 ExpressionFinder
const* m_expressionFinder;
191 EvaluatorInfo createBinaryOperatorEvaluator( ExpressionFinder
const&,
192 std::string::const_iterator iBegin,
193 std::string::const_iterator iEnd) ;
195 class ExpressionFinder {
199 m_elements.reserve(4);
200 m_elements.emplace_back(
new FunctionFinder{
this});
201 m_elements.emplace_back(
new ConstantFinder{});
202 m_elements.emplace_back(
new ParameterFinder{});
203 m_elements.emplace_back(
new VariableFinder{});
206 bool checkStart(
char iChar)
const {
207 if (
'(' == iChar
or '-' == iChar
or '+' ==iChar) {
210 for(
auto const&
e : m_elements) {
211 if (
e->checkStart(iChar) ) {
218 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase> iPreviousBinary)
const {
219 EvaluatorInfo leftEvaluatorInfo ;
220 if( iBegin == iEnd) {
221 return leftEvaluatorInfo;
224 if (*iBegin ==
'+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
225 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd, iPreviousBinary);
228 leftEvaluatorInfo.nextParseIndex +=1;
229 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
230 return leftEvaluatorInfo;
234 else if (*iBegin ==
'-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
235 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd,iPreviousBinary);
238 leftEvaluatorInfo.nextParseIndex +=1;
239 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
240 return leftEvaluatorInfo;
242 leftEvaluatorInfo.evaluator = std::make_shared<reco::formula::UnaryMinusEvaluator>(
std::move(leftEvaluatorInfo.top));
243 leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
246 else if( *iBegin ==
'(') {
247 auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
248 if(iBegin== endParenthesis) {
249 return leftEvaluatorInfo;
251 leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis,std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
252 ++leftEvaluatorInfo.nextParseIndex;
253 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
254 return leftEvaluatorInfo;
257 ++leftEvaluatorInfo.nextParseIndex;
258 leftEvaluatorInfo.top->setPrecedenceToParenthesis();
261 int maxParseDistance = 0;
262 for(
auto const&
e: m_elements) {
263 if(
e->checkStart(*iBegin) ) {
264 leftEvaluatorInfo =
e->createEvaluator(iBegin,iEnd);
265 if(leftEvaluatorInfo.evaluator !=
nullptr) {
268 if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
269 maxParseDistance = leftEvaluatorInfo.nextParseIndex;
273 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
275 leftEvaluatorInfo.nextParseIndex = maxParseDistance;
276 return leftEvaluatorInfo;
280 if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
281 if (iPreviousBinary) {
282 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
283 leftEvaluatorInfo.top = iPreviousBinary;
285 return leftEvaluatorInfo;
289 auto fullExpression = createBinaryOperatorEvaluator(*
this, iBegin+leftEvaluatorInfo.nextParseIndex, iEnd);
290 fullExpression.nextParseIndex +=leftEvaluatorInfo.nextParseIndex;
291 fullExpression.maxNumVariables =
std::max(leftEvaluatorInfo.maxNumVariables, fullExpression.maxNumVariables);
292 fullExpression.maxNumParameters =
std::max(leftEvaluatorInfo.maxNumParameters, fullExpression.maxNumParameters);
293 if (iBegin + fullExpression.nextParseIndex != iEnd) {
295 fullExpression.evaluator.reset();
299 auto topNode = fullExpression.top;
301 if (iPreviousBinary) {
302 if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
304 binaryEval->setLeftEvaluator(iPreviousBinary);
306 binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
307 if(iPreviousBinary->precedence()<topNode->precedence() ) {
308 topNode = iPreviousBinary;
309 iPreviousBinary->setRightEvaluator(fullExpression.top);
311 std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
314 iPreviousBinary->setRightEvaluator(toSwap);
318 binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
320 fullExpression.top = topNode;
321 return fullExpression;
325 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
329 template<
typename Op>
330 EvaluatorInfo createBinaryOperatorEvaluatorT(
int iSymbolLength,
332 ExpressionFinder
const& iEF,
333 std::string::const_iterator iBegin,
334 std::string::const_iterator iEnd) {
335 auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op> >(iPrec);
336 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd,op);
337 evalInfo.nextParseIndex += iSymbolLength;
339 if(evalInfo.evaluator.get() ==
nullptr) {
343 evalInfo.evaluator = op;
348 double operator()(
double iLHS,
double iRHS)
const {
355 createBinaryOperatorEvaluator( ExpressionFinder
const& iEF,
356 std::string::const_iterator iBegin,
357 std::string::const_iterator iEnd) {
358 EvaluatorInfo evalInfo;
364 return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
371 else if(*iBegin ==
'-') {
372 return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
378 else if(*iBegin ==
'*') {
379 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
385 else if(*iBegin ==
'/') {
386 return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
393 else if(*iBegin ==
'^') {
394 return createBinaryOperatorEvaluatorT<power>(1,
400 else if (*iBegin ==
'<' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
401 return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
408 else if (*iBegin ==
'>' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
409 return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
416 else if (*iBegin ==
'<' ) {
417 return createBinaryOperatorEvaluatorT<std::less<double>>(1,
424 else if (*iBegin ==
'>' ) {
425 return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
432 else if (*iBegin ==
'=' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
433 return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
440 else if (*iBegin ==
'!' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
441 return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
452 template<
typename Op>
454 checkForSingleArgFunction(std::string::const_iterator iBegin,
455 std::string::const_iterator iEnd,
456 ExpressionFinder
const* iExpressionFinder,
460 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
463 auto pos = iName.find(&(*iBegin), 0,iName.size());
465 if(std::string::npos == pos
or *(iBegin+iName.size()) !=
'(') {
469 info.nextParseIndex = iName.size()+1;
471 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
472 if(iBegin+iName.size() == itEndParen) {
476 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen,
477 std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
478 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
479 if(argEvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
483 ++info.nextParseIndex;
485 info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(
std::move(argEvaluatorInfo.top),
487 info.top = info.evaluator;
491 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
492 std::string::const_iterator iEnd ) {
494 std::string::const_iterator it = iBegin;
495 for(; it != iEnd; ++it) {
498 }
else if(*it ==
')') {
501 else if( *it ==
',' and level == 0 ) {
510 template<
typename Op>
512 checkForTwoArgsFunction(std::string::const_iterator iBegin,
513 std::string::const_iterator iEnd,
514 ExpressionFinder
const* iExpressionFinder,
518 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
521 auto pos = iName.find(&(*iBegin), 0,iName.size());
523 if(std::string::npos == pos
or *(iBegin+iName.size()) !=
'(') {
527 info.nextParseIndex = iName.size()+1;
529 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
530 if(iBegin+iName.size() == itEndParen) {
534 auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
536 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
537 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
538 if(arg1EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex != itComma-iBegin ) {
542 ++info.nextParseIndex;
544 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
545 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
547 if(arg2EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
551 ++info.nextParseIndex;
553 info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(
std::move(arg1EvaluatorInfo.top),
556 info.top = info.evaluator;
562 static const std::string k_TMath__Log(
"TMath::Log");
563 double const kLog10Inv = 1./
std::log(10.);
566 static const std::string k_TMath__Power(
"TMath::Power");
569 static const std::string k_TMath__Max(
"TMath::Max");
570 static const std::string k_TMath__Min(
"TMath::Min");
571 static const std::string k_TMath__Erf(
"TMath::Erf");
573 static const std::string k_TMath__Landau(
"TMath::Landau");
577 FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
580 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
581 k_erf, [](
double iArg)->
double {
return std::erf(iArg); } );
582 if(info.evaluator.get() !=
nullptr) {
586 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
587 k_TMath__Erf, [](
double iArg)->
double {
return std::erf(iArg); } );
588 if(info.evaluator.get() !=
nullptr) {
592 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
593 k_TMath__Landau, [](
double iArg)->
double {
return TMath::Landau(iArg); } );
594 if(info.evaluator.get() !=
nullptr) {
598 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
599 k_log, [](
double iArg)->
double {
return std::log(iArg); } );
600 if(info.evaluator.get() !=
nullptr) {
604 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
605 k_TMath__Log, [](
double iArg)->
double {
return std::log(iArg); } );
606 if(info.evaluator.get() !=
nullptr) {
610 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
611 k_log10, [](
double iArg)->
double {
return std::log(iArg)*kLog10Inv; } );
612 if(info.evaluator.get() !=
nullptr) {
616 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
617 k_exp, [](
double iArg)->
double {
return std::exp(iArg); } );
618 if(info.evaluator.get() !=
nullptr) {
622 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
623 k_pow, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
624 if(info.evaluator.get() !=
nullptr) {
628 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
629 k_TMath__Power, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
630 if(info.evaluator.get() !=
nullptr) {
634 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
635 k_max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
636 if(info.evaluator.get() !=
nullptr) {
640 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
641 k_min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
642 if(info.evaluator.get() !=
nullptr) {
646 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
647 k_TMath__Max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
648 if(info.evaluator.get() !=
nullptr) {
652 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
653 k_TMath__Min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
654 if(info.evaluator.get() !=
nullptr) {
661 static ExpressionFinder
const s_expressionFinder;
677 auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
679 if(info.nextParseIndex != static_cast<int>(iFormula.size())
or info.top.get() ==
nullptr) {
680 throw cms::Exception(
"FormulaEvaluatorParseError")<<
"While parsing '"<<iFormula<<
"' could not parse beyond '"<<
std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<
"'";
693 return m_evaluator->evaluate(iVariables, iParameters);
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Power< A, B >::type pow(const A &a, const B &b)