21 #if defined(DEBUG_AST) 40 #if defined(DEBUG_AST) 47 #define DEBUG_STATE(_v_) std::cout <<_v_<<std::endl 49 inline void printAST(
void*) {}
50 #define DEBUG_STATE(_v_) 53 struct EvaluatorInfo {
54 std::shared_ptr<reco::formula::EvaluatorBase> evaluator;
55 std::shared_ptr<reco::formula::EvaluatorBase> top;
57 unsigned int maxNumVariables=0;
58 unsigned int maxNumParameters=0;
61 class ExpressionElementFinderBase {
63 virtual bool checkStart(
char)
const = 0;
65 virtual EvaluatorInfo createEvaluator(std::string::const_iterator, std::string::const_iterator)
const = 0;
67 virtual ~ExpressionElementFinderBase() =
default;
70 std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin, std::string::const_iterator iEnd) {
79 for(
auto it = iBegin+1; it != iEnd; ++it) {
83 }
else if (*it ==
')') {
90 return iBegin +
index;
93 class ConstantFinder :
public ExpressionElementFinderBase {
94 bool checkStart(
char iSymbol)
const final {
95 if( iSymbol ==
'-' or iSymbol ==
'.' or std::isdigit(iSymbol) ) {
101 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final {
106 double value = stod(s, &endIndex);
108 info.nextParseIndex = endIndex;
109 info.evaluator = std::make_shared<reco::formula::ConstantEvaluator>(
value);
110 info.top = info.evaluator;
111 }
catch ( std::invalid_argument
const& ) {}
119 class ParameterFinder :
public ExpressionElementFinderBase {
120 bool checkStart(
char iSymbol)
const final {
121 if( iSymbol ==
'[') {
127 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final {
135 info.nextParseIndex = 1;
139 unsigned long value = stoul(s, &endIndex);
141 if( iBegin+endIndex+1 == iEnd
or *(iBegin+1+endIndex) !=
']' ) {
146 info.nextParseIndex = endIndex+2;
147 info.maxNumParameters = value+1;
148 info.evaluator = std::make_shared<reco::formula::ParameterEvaluator>(
value);
149 info.top = info.evaluator;
150 }
catch ( std::invalid_argument
const& ) {}
157 class VariableFinder :
public ExpressionElementFinderBase {
158 bool checkStart(
char iSymbol)
const final {
159 if( iSymbol ==
'x' or iSymbol ==
'y' or iSymbol ==
'z' or iSymbol ==
't' ) {
165 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final {
170 unsigned int index = 4;
184 info.nextParseIndex = 1;
185 info.maxNumVariables = index+1;
186 info.evaluator = std::make_shared<reco::formula::VariableEvaluator>(
index);
187 info.top = info.evaluator;
192 class ExpressionFinder;
194 class FunctionFinder :
public ExpressionElementFinderBase {
196 FunctionFinder(ExpressionFinder
const* iEF):
197 m_expressionFinder(iEF) {};
199 bool checkStart(
char iSymbol)
const final {
200 return std::isalpha(iSymbol);
203 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const final;
206 ExpressionFinder
const* m_expressionFinder;
210 EvaluatorInfo createBinaryOperatorEvaluator( ExpressionFinder
const&,
211 std::string::const_iterator iBegin,
212 std::string::const_iterator iEnd) ;
214 class ExpressionFinder {
218 m_elements.reserve(4);
219 m_elements.emplace_back(
new FunctionFinder{
this});
220 m_elements.emplace_back(
new ConstantFinder{});
221 m_elements.emplace_back(
new ParameterFinder{});
222 m_elements.emplace_back(
new VariableFinder{});
225 bool checkStart(
char iChar)
const {
226 if (
'(' == iChar
or '-' == iChar
or '+' ==iChar) {
229 for(
auto const& e : m_elements) {
230 if (e->checkStart(iChar) ) {
237 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase> iPreviousBinary)
const {
238 EvaluatorInfo leftEvaluatorInfo ;
240 if( iBegin == iEnd) {
241 return leftEvaluatorInfo;
244 if (*iBegin ==
'+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
245 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd, iPreviousBinary);
248 leftEvaluatorInfo.nextParseIndex +=1;
249 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
250 return leftEvaluatorInfo;
254 else if (*iBegin ==
'-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
255 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd,iPreviousBinary);
258 leftEvaluatorInfo.nextParseIndex +=1;
259 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
260 return leftEvaluatorInfo;
262 leftEvaluatorInfo.evaluator = std::make_shared<reco::formula::UnaryMinusEvaluator>(
std::move(leftEvaluatorInfo.top));
263 leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
266 else if( *iBegin ==
'(') {
267 auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
268 if(iBegin== endParenthesis) {
269 return leftEvaluatorInfo;
271 leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis,std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
272 ++leftEvaluatorInfo.nextParseIndex;
273 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
274 return leftEvaluatorInfo;
277 ++leftEvaluatorInfo.nextParseIndex;
278 leftEvaluatorInfo.top->setPrecedenceToParenthesis();
280 printAST(leftEvaluatorInfo.top.get());
281 leftEvaluatorInfo.evaluator = leftEvaluatorInfo.top;
284 int maxParseDistance = 0;
285 for(
auto const& e: m_elements) {
286 if(e->checkStart(*iBegin) ) {
287 leftEvaluatorInfo = e->createEvaluator(iBegin,iEnd);
288 if(leftEvaluatorInfo.evaluator !=
nullptr) {
291 if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
292 maxParseDistance = leftEvaluatorInfo.nextParseIndex;
296 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
298 leftEvaluatorInfo.nextParseIndex = maxParseDistance;
299 return leftEvaluatorInfo;
303 if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
304 if (iPreviousBinary) {
305 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
306 leftEvaluatorInfo.top = iPreviousBinary;
309 printAST(leftEvaluatorInfo.evaluator.get());
310 return leftEvaluatorInfo;
314 auto fullExpression = createBinaryOperatorEvaluator(*
this, iBegin+leftEvaluatorInfo.nextParseIndex, iEnd);
315 fullExpression.nextParseIndex +=leftEvaluatorInfo.nextParseIndex;
316 fullExpression.maxNumVariables =
std::max(leftEvaluatorInfo.maxNumVariables, fullExpression.maxNumVariables);
317 fullExpression.maxNumParameters =
std::max(leftEvaluatorInfo.maxNumParameters, fullExpression.maxNumParameters);
318 if (iBegin + fullExpression.nextParseIndex != iEnd) {
320 fullExpression.evaluator.reset();
323 if(fullExpression.evaluator ==
nullptr) {
325 return fullExpression;
329 printAST(fullExpression.evaluator.get());
331 auto topNode = fullExpression.top;
333 if (iPreviousBinary) {
334 if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
336 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.evaluator);
337 binaryEval->setLeftEvaluator(iPreviousBinary);
339 binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
340 if(iPreviousBinary->precedence()<topNode->precedence() ) {
342 topNode = iPreviousBinary;
343 iPreviousBinary->setRightEvaluator(fullExpression.top);
349 std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
352 if(parentBinary->lhs() == binaryEval
or parentBinary->lhs()->precedence() > iPreviousBinary->precedence()) {
354 iPreviousBinary->setRightEvaluator(toSwap);
358 assert(parentBinary !=
nullptr);
360 }
while(iPreviousBinary->rhs() ==
nullptr);
364 binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
367 printAST(binaryEval);
369 printAST(topNode.get());
370 fullExpression.top = topNode;
371 return fullExpression;
375 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
379 template<
typename Op>
380 EvaluatorInfo createBinaryOperatorEvaluatorT(
int iSymbolLength,
382 ExpressionFinder
const& iEF,
383 std::string::const_iterator iBegin,
384 std::string::const_iterator iEnd) {
385 auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op> >(iPrec);
386 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd,op);
387 evalInfo.nextParseIndex += iSymbolLength;
389 if(evalInfo.evaluator.get() ==
nullptr) {
393 evalInfo.evaluator = op;
398 double operator()(
double iLHS,
double iRHS)
const {
405 createBinaryOperatorEvaluator( ExpressionFinder
const& iEF,
406 std::string::const_iterator iBegin,
407 std::string::const_iterator iEnd) {
408 EvaluatorInfo evalInfo;
414 return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
421 else if(*iBegin ==
'-') {
422 return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
428 else if(*iBegin ==
'*') {
429 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
435 else if(*iBegin ==
'/') {
436 return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
443 else if(*iBegin ==
'^') {
444 return createBinaryOperatorEvaluatorT<power>(1,
450 else if (*iBegin ==
'<' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
451 return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
458 else if (*iBegin ==
'>' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
459 return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
466 else if (*iBegin ==
'<' ) {
467 return createBinaryOperatorEvaluatorT<std::less<double>>(1,
474 else if (*iBegin ==
'>' ) {
475 return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
482 else if (*iBegin ==
'=' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
483 return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
490 else if (*iBegin ==
'!' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
491 return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
502 template<
typename Op>
504 checkForSingleArgFunction(std::string::const_iterator iBegin,
505 std::string::const_iterator iEnd,
506 ExpressionFinder
const* iExpressionFinder,
510 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
513 auto pos = iName.find(&(*iBegin), 0,iName.size());
515 if(std::string::npos ==
pos or *(iBegin+iName.size()) !=
'(') {
519 info.nextParseIndex = iName.size()+1;
521 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
522 if(iBegin+iName.size() == itEndParen) {
526 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen,
527 std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
528 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
529 if(argEvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
533 ++info.nextParseIndex;
535 info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(
std::move(argEvaluatorInfo.top),
537 info.top = info.evaluator;
541 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
542 std::string::const_iterator iEnd ) {
544 std::string::const_iterator it = iBegin;
545 for(; it != iEnd; ++it) {
548 }
else if(*it ==
')') {
551 else if( *it ==
',' and level == 0 ) {
560 template<
typename Op>
562 checkForTwoArgsFunction(std::string::const_iterator iBegin,
563 std::string::const_iterator iEnd,
564 ExpressionFinder
const* iExpressionFinder,
568 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
571 auto pos = iName.find(&(*iBegin), 0,iName.size());
573 if(std::string::npos ==
pos or *(iBegin+iName.size()) !=
'(') {
577 info.nextParseIndex = iName.size()+1;
579 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
580 if(iBegin+iName.size() == itEndParen) {
584 auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
586 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
587 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
588 if(arg1EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex != itComma-iBegin ) {
592 ++info.nextParseIndex;
594 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
595 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
597 if(arg2EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
601 ++info.nextParseIndex;
603 info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(
std::move(arg1EvaluatorInfo.top),
606 info.top = info.evaluator;
613 double const kLog10Inv = 1./
std::log(10.);
623 const std::string k_TMath__Landau(
"TMath::Landau");
631 FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
634 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
635 k_erf, [](
double iArg)->
double {
return std::erf(iArg); } );
636 if(info.evaluator.get() !=
nullptr) {
640 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
641 k_TMath__Erf, [](
double iArg)->
double {
return std::erf(iArg); } );
642 if(info.evaluator.get() !=
nullptr) {
646 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
647 k_TMath__Landau, [](
double iArg)->
double {
return TMath::Landau(iArg); } );
648 if(info.evaluator.get() !=
nullptr) {
652 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
653 k_log, [](
double iArg)->
double {
return std::log(iArg); } );
654 if(info.evaluator.get() !=
nullptr) {
658 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
659 k_TMath__Log, [](
double iArg)->
double {
return std::log(iArg); } );
660 if(info.evaluator.get() !=
nullptr) {
664 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
665 k_log10, [](
double iArg)->
double {
return std::log(iArg)*kLog10Inv; } );
666 if(info.evaluator.get() !=
nullptr) {
670 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
671 k_exp, [](
double iArg)->
double {
return std::exp(iArg); } );
672 if(info.evaluator.get() !=
nullptr) {
676 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
677 k_sqrt, [](
double iArg)->
double {
return std::sqrt(iArg); } );
678 if(info.evaluator.get() !=
nullptr) {
682 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
683 k_TMath__Sqrt, [](
double iArg)->
double {
return std::sqrt(iArg); } );
684 if(info.evaluator.get() !=
nullptr) {
688 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
689 k_abs, [](
double iArg)->
double {
return std::abs(iArg); } );
690 if(info.evaluator.get() !=
nullptr) {
694 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
695 k_TMath__Abs, [](
double iArg)->
double {
return std::abs(iArg); } );
696 if(info.evaluator.get() !=
nullptr) {
700 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
701 k_pow, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
702 if(info.evaluator.get() !=
nullptr) {
706 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
707 k_TMath__Power, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
708 if(info.evaluator.get() !=
nullptr) {
712 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
713 k_max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
714 if(info.evaluator.get() !=
nullptr) {
718 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
719 k_min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
720 if(info.evaluator.get() !=
nullptr) {
724 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
725 k_TMath__Max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
726 if(info.evaluator.get() !=
nullptr) {
730 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
731 k_TMath__Min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
732 if(info.evaluator.get() !=
nullptr) {
739 ExpressionFinder
const s_expressionFinder;
757 formula.reserve(iFormula.size());
758 std::copy_if(iFormula.begin(), iFormula.end(), std::back_inserter(formula), [](
const char iC) {
return iC !=
' '; } );
760 auto info = s_expressionFinder.createEvaluator(formula.begin(), formula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
762 if(info.nextParseIndex != static_cast<int>(formula.size())
or info.top.get() ==
nullptr) {
764 if(formula.size() != iFormula.size()) {
773 throw cms::Exception(
"FormulaEvaluatorParseError")<<
"While parsing '"<<iFormula<<
"' could not parse beyond '"<<
std::string(iFormula.begin(),iFormula.begin()+
lastIndex) <<
"'";
777 printAST(info.top.get());
780 m_nVariables = info.maxNumVariables;
781 m_nParameters = info.maxNumParameters;
790 return m_evaluator->evaluate(iVariables, iParameters);
795 throw cms::Exception(
"WrongNumVariables")<<
"FormulaEvaluator expected at least "<<m_nVariables<<
" but was passed only "<<iSize;
799 throw cms::Exception(
"WrongNumParameters")<<
"FormulaEvaluator expected at least "<<m_nParameters<<
" but was passed only "<<iSize;
802 std::vector<std::string>
804 return m_evaluator->abstractSyntaxTree();
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
Abs< T >::type abs(const T &t)
static std::atomic< unsigned int > lastIndex
Power< A, B >::type pow(const A &a, const B &b)