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.evaluator->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.evaluator);
319 if (topNode->precedence() > binaryEval->precedence()) {
320 topNode = fullExpression.evaluator;
323 fullExpression.top = topNode;
324 return fullExpression;
328 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
332 template<
typename Op>
333 EvaluatorInfo createBinaryOperatorEvaluatorT(
int iSymbolLength,
335 ExpressionFinder
const& iEF,
336 std::string::const_iterator iBegin,
337 std::string::const_iterator iEnd) {
338 auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op> >(iPrec);
339 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd,op);
340 evalInfo.nextParseIndex += iSymbolLength;
342 if(evalInfo.evaluator.get() ==
nullptr) {
346 evalInfo.evaluator = op;
351 double operator()(
double iLHS,
double iRHS)
const {
358 createBinaryOperatorEvaluator( ExpressionFinder
const& iEF,
359 std::string::const_iterator iBegin,
360 std::string::const_iterator iEnd) {
361 EvaluatorInfo evalInfo;
367 return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
374 else if(*iBegin ==
'-') {
375 return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
381 else if(*iBegin ==
'*') {
382 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
388 else if(*iBegin ==
'/') {
389 return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
396 else if(*iBegin ==
'^') {
397 return createBinaryOperatorEvaluatorT<power>(1,
403 else if (*iBegin ==
'<' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
404 return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
411 else if (*iBegin ==
'>' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
412 return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
419 else if (*iBegin ==
'<' ) {
420 return createBinaryOperatorEvaluatorT<std::less<double>>(1,
427 else if (*iBegin ==
'>' ) {
428 return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
435 else if (*iBegin ==
'=' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
436 return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
443 else if (*iBegin ==
'!' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
444 return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
455 template<
typename Op>
457 checkForSingleArgFunction(std::string::const_iterator iBegin,
458 std::string::const_iterator iEnd,
459 ExpressionFinder
const* iExpressionFinder,
463 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
466 auto pos = iName.find(&(*iBegin), 0,iName.size());
468 if(std::string::npos == pos
or *(iBegin+iName.size()) !=
'(') {
472 info.nextParseIndex = iName.size()+1;
474 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
475 if(iBegin+iName.size() == itEndParen) {
479 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen,
480 std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
481 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
482 if(argEvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
486 ++info.nextParseIndex;
488 info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(
std::move(argEvaluatorInfo.top),
490 info.top = info.evaluator;
494 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
495 std::string::const_iterator iEnd ) {
497 std::string::const_iterator it = iBegin;
498 for(; it != iEnd; ++it) {
501 }
else if(*it ==
')') {
504 else if( *it ==
',' and level == 0 ) {
513 template<
typename Op>
515 checkForTwoArgsFunction(std::string::const_iterator iBegin,
516 std::string::const_iterator iEnd,
517 ExpressionFinder
const* iExpressionFinder,
521 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
524 auto pos = iName.find(&(*iBegin), 0,iName.size());
526 if(std::string::npos == pos
or *(iBegin+iName.size()) !=
'(') {
530 info.nextParseIndex = iName.size()+1;
532 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
533 if(iBegin+iName.size() == itEndParen) {
537 auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
539 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
540 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
541 if(arg1EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex != itComma-iBegin ) {
545 ++info.nextParseIndex;
547 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
548 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
550 if(arg2EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
554 ++info.nextParseIndex;
556 info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(
std::move(arg1EvaluatorInfo.top),
559 info.top = info.evaluator;
565 static const std::string k_TMath__Log(
"TMath::Log");
566 double const kLog10Inv = 1./
std::log(10.);
569 static const std::string k_TMath__Power(
"TMath::Power");
572 static const std::string k_TMath__Max(
"TMath::Max");
573 static const std::string k_TMath__Min(
"TMath::Min");
574 static const std::string k_TMath__Erf(
"TMath::Erf");
576 static const std::string k_TMath__Landau(
"TMath::Landau");
580 FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
583 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
584 k_erf, [](
double iArg)->
double {
return std::erf(iArg); } );
585 if(info.evaluator.get() !=
nullptr) {
589 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
590 k_TMath__Erf, [](
double iArg)->
double {
return std::erf(iArg); } );
591 if(info.evaluator.get() !=
nullptr) {
595 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
596 k_TMath__Landau, [](
double iArg)->
double {
return TMath::Landau(iArg); } );
597 if(info.evaluator.get() !=
nullptr) {
601 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
602 k_log, [](
double iArg)->
double {
return std::log(iArg); } );
603 if(info.evaluator.get() !=
nullptr) {
607 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
608 k_TMath__Log, [](
double iArg)->
double {
return std::log(iArg); } );
609 if(info.evaluator.get() !=
nullptr) {
613 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
614 k_log10, [](
double iArg)->
double {
return std::log(iArg)*kLog10Inv; } );
615 if(info.evaluator.get() !=
nullptr) {
619 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
620 k_exp, [](
double iArg)->
double {
return std::exp(iArg); } );
621 if(info.evaluator.get() !=
nullptr) {
625 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
626 k_pow, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
627 if(info.evaluator.get() !=
nullptr) {
631 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
632 k_TMath__Power, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
633 if(info.evaluator.get() !=
nullptr) {
637 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
638 k_max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
639 if(info.evaluator.get() !=
nullptr) {
643 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
644 k_min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
645 if(info.evaluator.get() !=
nullptr) {
649 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
650 k_TMath__Max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
651 if(info.evaluator.get() !=
nullptr) {
655 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
656 k_TMath__Min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
657 if(info.evaluator.get() !=
nullptr) {
664 static ExpressionFinder
const s_expressionFinder;
680 auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
682 if(info.nextParseIndex != static_cast<int>(iFormula.size())
or info.top.get() ==
nullptr) {
683 throw cms::Exception(
"FormulaEvaluatorParseError")<<
"While parsing '"<<iFormula<<
"' could not parse beyond '"<<
std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<
"'";
696 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)