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;
50 virtual ~ExpressionElementFinderBase() =
default;
53 std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin, std::string::const_iterator iEnd) {
62 for(
auto it = iBegin+1; it != iEnd; ++it) {
66 }
else if (*it ==
')') {
73 return iBegin +
index;
76 class ConstantFinder :
public ExpressionElementFinderBase {
77 bool checkStart(
char iSymbol)
const final {
78 if( iSymbol ==
'-' or iSymbol ==
'.' or std::isdigit(iSymbol) ) {
84 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final {
89 double value = stod(
s, &endIndex);
91 info.nextParseIndex = endIndex;
92 info.evaluator = std::make_shared<reco::formula::ConstantEvaluator>(
value);
93 info.top = info.evaluator;
94 }
catch ( std::invalid_argument ) {}
102 class ParameterFinder :
public ExpressionElementFinderBase {
103 bool checkStart(
char iSymbol)
const final {
104 if( iSymbol ==
'[') {
110 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final {
118 info.nextParseIndex = 1;
122 unsigned long value = stoul(
s, &endIndex);
124 if( iBegin+endIndex+1 == iEnd
or *(iBegin+1+endIndex) !=
']' ) {
129 info.nextParseIndex = endIndex+2;
130 info.maxNumParameters = value+1;
131 info.evaluator = std::make_shared<reco::formula::ParameterEvaluator>(
value);
132 info.top = info.evaluator;
133 }
catch ( std::invalid_argument ) {}
140 class VariableFinder :
public ExpressionElementFinderBase {
141 bool checkStart(
char iSymbol)
const final {
142 if( iSymbol ==
'x' or iSymbol ==
'y' or iSymbol ==
'z' or iSymbol ==
't' ) {
148 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final {
153 unsigned int index = 4;
167 info.nextParseIndex = 1;
168 info.maxNumVariables = index+1;
169 info.evaluator = std::make_shared<reco::formula::VariableEvaluator>(
index);
170 info.top = info.evaluator;
175 class ExpressionFinder;
177 class FunctionFinder :
public ExpressionElementFinderBase {
179 FunctionFinder(ExpressionFinder
const* iEF):
180 m_expressionFinder(iEF) {};
182 bool checkStart(
char iSymbol)
const final {
183 return std::isalpha(iSymbol);
186 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final;
189 ExpressionFinder
const* m_expressionFinder;
193 EvaluatorInfo createBinaryOperatorEvaluator( ExpressionFinder
const&,
194 std::string::const_iterator iBegin,
195 std::string::const_iterator iEnd) ;
197 class ExpressionFinder {
201 m_elements.reserve(4);
202 m_elements.emplace_back(
new FunctionFinder{
this});
203 m_elements.emplace_back(
new ConstantFinder{});
204 m_elements.emplace_back(
new ParameterFinder{});
205 m_elements.emplace_back(
new VariableFinder{});
208 bool checkStart(
char iChar)
const {
209 if (
'(' == iChar
or '-' == iChar
or '+' ==iChar) {
212 for(
auto const&
e : m_elements) {
213 if (
e->checkStart(iChar) ) {
220 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase> iPreviousBinary)
const {
221 EvaluatorInfo leftEvaluatorInfo ;
222 if( iBegin == iEnd) {
223 return leftEvaluatorInfo;
226 if (*iBegin ==
'+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
227 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd, iPreviousBinary);
230 leftEvaluatorInfo.nextParseIndex +=1;
231 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
232 return leftEvaluatorInfo;
236 else if (*iBegin ==
'-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
237 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd,iPreviousBinary);
240 leftEvaluatorInfo.nextParseIndex +=1;
241 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
242 return leftEvaluatorInfo;
244 leftEvaluatorInfo.evaluator = std::make_shared<reco::formula::UnaryMinusEvaluator>(
std::move(leftEvaluatorInfo.top));
245 leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
248 else if( *iBegin ==
'(') {
249 auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
250 if(iBegin== endParenthesis) {
251 return leftEvaluatorInfo;
253 leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis,std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
254 ++leftEvaluatorInfo.nextParseIndex;
255 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
256 return leftEvaluatorInfo;
259 ++leftEvaluatorInfo.nextParseIndex;
260 leftEvaluatorInfo.top->setPrecedenceToParenthesis();
263 int maxParseDistance = 0;
264 for(
auto const&
e: m_elements) {
265 if(
e->checkStart(*iBegin) ) {
266 leftEvaluatorInfo =
e->createEvaluator(iBegin,iEnd);
267 if(leftEvaluatorInfo.evaluator !=
nullptr) {
270 if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
271 maxParseDistance = leftEvaluatorInfo.nextParseIndex;
275 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
277 leftEvaluatorInfo.nextParseIndex = maxParseDistance;
278 return leftEvaluatorInfo;
282 if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
283 if (iPreviousBinary) {
284 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
285 leftEvaluatorInfo.top = iPreviousBinary;
287 return leftEvaluatorInfo;
291 auto fullExpression = createBinaryOperatorEvaluator(*
this, iBegin+leftEvaluatorInfo.nextParseIndex, iEnd);
292 fullExpression.nextParseIndex +=leftEvaluatorInfo.nextParseIndex;
293 fullExpression.maxNumVariables =
std::max(leftEvaluatorInfo.maxNumVariables, fullExpression.maxNumVariables);
294 fullExpression.maxNumParameters =
std::max(leftEvaluatorInfo.maxNumParameters, fullExpression.maxNumParameters);
295 if (iBegin + fullExpression.nextParseIndex != iEnd) {
297 fullExpression.evaluator.reset();
301 auto topNode = fullExpression.top;
303 if (iPreviousBinary) {
304 if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
306 binaryEval->setLeftEvaluator(iPreviousBinary);
308 binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
309 if(iPreviousBinary->precedence()<topNode->precedence() ) {
310 topNode = iPreviousBinary;
311 iPreviousBinary->setRightEvaluator(fullExpression.top);
313 std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
316 iPreviousBinary->setRightEvaluator(toSwap);
320 binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
322 fullExpression.top = topNode;
323 return fullExpression;
327 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
331 template<
typename Op>
332 EvaluatorInfo createBinaryOperatorEvaluatorT(
int iSymbolLength,
334 ExpressionFinder
const& iEF,
335 std::string::const_iterator iBegin,
336 std::string::const_iterator iEnd) {
337 auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op> >(iPrec);
338 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd,op);
339 evalInfo.nextParseIndex += iSymbolLength;
341 if(evalInfo.evaluator.get() ==
nullptr) {
345 evalInfo.evaluator = op;
350 double operator()(
double iLHS,
double iRHS)
const {
357 createBinaryOperatorEvaluator( ExpressionFinder
const& iEF,
358 std::string::const_iterator iBegin,
359 std::string::const_iterator iEnd) {
360 EvaluatorInfo evalInfo;
366 return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
373 else if(*iBegin ==
'-') {
374 return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
380 else if(*iBegin ==
'*') {
381 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
387 else if(*iBegin ==
'/') {
388 return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
395 else if(*iBegin ==
'^') {
396 return createBinaryOperatorEvaluatorT<power>(1,
402 else if (*iBegin ==
'<' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
403 return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
410 else if (*iBegin ==
'>' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
411 return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
418 else if (*iBegin ==
'<' ) {
419 return createBinaryOperatorEvaluatorT<std::less<double>>(1,
426 else if (*iBegin ==
'>' ) {
427 return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
434 else if (*iBegin ==
'=' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
435 return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
442 else if (*iBegin ==
'!' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
443 return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
454 template<
typename Op>
456 checkForSingleArgFunction(std::string::const_iterator iBegin,
457 std::string::const_iterator iEnd,
458 ExpressionFinder
const* iExpressionFinder,
462 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
465 auto pos = iName.find(&(*iBegin), 0,iName.size());
467 if(std::string::npos ==
pos or *(iBegin+iName.size()) !=
'(') {
471 info.nextParseIndex = iName.size()+1;
473 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
474 if(iBegin+iName.size() == itEndParen) {
478 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen,
479 std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
480 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
481 if(argEvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
485 ++info.nextParseIndex;
487 info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(
std::move(argEvaluatorInfo.top),
489 info.top = info.evaluator;
493 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
494 std::string::const_iterator iEnd ) {
496 std::string::const_iterator it = iBegin;
497 for(; it != iEnd; ++it) {
500 }
else if(*it ==
')') {
503 else if( *it ==
',' and level == 0 ) {
512 template<
typename Op>
514 checkForTwoArgsFunction(std::string::const_iterator iBegin,
515 std::string::const_iterator iEnd,
516 ExpressionFinder
const* iExpressionFinder,
520 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
523 auto pos = iName.find(&(*iBegin), 0,iName.size());
525 if(std::string::npos ==
pos or *(iBegin+iName.size()) !=
'(') {
529 info.nextParseIndex = iName.size()+1;
531 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
532 if(iBegin+iName.size() == itEndParen) {
536 auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
538 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
539 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
540 if(arg1EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex != itComma-iBegin ) {
544 ++info.nextParseIndex;
546 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
547 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
549 if(arg2EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
553 ++info.nextParseIndex;
555 info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(
std::move(arg1EvaluatorInfo.top),
558 info.top = info.evaluator;
565 double const kLog10Inv = 1./
std::log(10.);
575 const std::string k_TMath__Landau(
"TMath::Landau");
579 FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
582 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
583 k_erf, [](
double iArg)->
double {
return std::erf(iArg); } );
584 if(info.evaluator.get() !=
nullptr) {
588 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
589 k_TMath__Erf, [](
double iArg)->
double {
return std::erf(iArg); } );
590 if(info.evaluator.get() !=
nullptr) {
594 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
595 k_TMath__Landau, [](
double iArg)->
double {
return TMath::Landau(iArg); } );
596 if(info.evaluator.get() !=
nullptr) {
600 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
601 k_log, [](
double iArg)->
double {
return std::log(iArg); } );
602 if(info.evaluator.get() !=
nullptr) {
606 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
607 k_TMath__Log, [](
double iArg)->
double {
return std::log(iArg); } );
608 if(info.evaluator.get() !=
nullptr) {
612 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
613 k_log10, [](
double iArg)->
double {
return std::log(iArg)*kLog10Inv; } );
614 if(info.evaluator.get() !=
nullptr) {
618 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
619 k_exp, [](
double iArg)->
double {
return std::exp(iArg); } );
620 if(info.evaluator.get() !=
nullptr) {
624 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
625 k_pow, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
626 if(info.evaluator.get() !=
nullptr) {
630 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
631 k_TMath__Power, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
632 if(info.evaluator.get() !=
nullptr) {
636 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
637 k_max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
638 if(info.evaluator.get() !=
nullptr) {
642 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
643 k_min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
644 if(info.evaluator.get() !=
nullptr) {
648 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
649 k_TMath__Max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
650 if(info.evaluator.get() !=
nullptr) {
654 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
655 k_TMath__Min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
656 if(info.evaluator.get() !=
nullptr) {
663 ExpressionFinder
const s_expressionFinder;
679 auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
681 if(info.nextParseIndex != static_cast<int>(iFormula.size())
or info.top.get() ==
nullptr) {
682 throw cms::Exception(
"FormulaEvaluatorParseError")<<
"While parsing '"<<iFormula<<
"' could not parse beyond '"<<
std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<
"'";
685 m_nVariables = info.maxNumVariables;
686 m_nParameters = info.maxNumParameters;
695 return m_evaluator->evaluate(iVariables, iParameters);
700 throw cms::Exception(
"WrongNumVariables")<<
"FormulaEvaluator expected at least "<<m_nVariables<<
" but was passed only "<<iSize;
704 throw cms::Exception(
"WrongNumParameters")<<
"FormulaEvaluator expected at least "<<m_nParameters<<
" but was passed only "<<iSize;
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::EventID const &, edm::Timestamp const & > 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)