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 ) {}
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 ) {}
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 ;
239 if( iBegin == iEnd) {
240 return leftEvaluatorInfo;
243 if (*iBegin ==
'+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
244 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd, iPreviousBinary);
247 leftEvaluatorInfo.nextParseIndex +=1;
248 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
249 return leftEvaluatorInfo;
253 else if (*iBegin ==
'-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
254 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd,iPreviousBinary);
257 leftEvaluatorInfo.nextParseIndex +=1;
258 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
259 return leftEvaluatorInfo;
261 leftEvaluatorInfo.evaluator = std::make_shared<reco::formula::UnaryMinusEvaluator>(
std::move(leftEvaluatorInfo.top));
262 leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
265 else if( *iBegin ==
'(') {
266 auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
267 if(iBegin== endParenthesis) {
268 return leftEvaluatorInfo;
270 leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis,std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
271 ++leftEvaluatorInfo.nextParseIndex;
272 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
273 return leftEvaluatorInfo;
276 ++leftEvaluatorInfo.nextParseIndex;
277 leftEvaluatorInfo.top->setPrecedenceToParenthesis();
279 printAST(leftEvaluatorInfo.top.get());
280 leftEvaluatorInfo.evaluator = leftEvaluatorInfo.top;
283 int maxParseDistance = 0;
284 for(
auto const& e: m_elements) {
285 if(e->checkStart(*iBegin) ) {
286 leftEvaluatorInfo = e->createEvaluator(iBegin,iEnd);
287 if(leftEvaluatorInfo.evaluator !=
nullptr) {
290 if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
291 maxParseDistance = leftEvaluatorInfo.nextParseIndex;
295 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
297 leftEvaluatorInfo.nextParseIndex = maxParseDistance;
298 return leftEvaluatorInfo;
302 if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
303 if (iPreviousBinary) {
304 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
305 leftEvaluatorInfo.top = iPreviousBinary;
308 printAST(leftEvaluatorInfo.evaluator.get());
309 return leftEvaluatorInfo;
313 auto fullExpression = createBinaryOperatorEvaluator(*
this, iBegin+leftEvaluatorInfo.nextParseIndex, iEnd);
314 fullExpression.nextParseIndex +=leftEvaluatorInfo.nextParseIndex;
315 fullExpression.maxNumVariables =
std::max(leftEvaluatorInfo.maxNumVariables, fullExpression.maxNumVariables);
316 fullExpression.maxNumParameters =
std::max(leftEvaluatorInfo.maxNumParameters, fullExpression.maxNumParameters);
317 if (iBegin + fullExpression.nextParseIndex != iEnd) {
319 fullExpression.evaluator.reset();
322 if(fullExpression.evaluator ==
nullptr) {
324 return fullExpression;
327 printAST(fullExpression.evaluator.get());
329 auto topNode = fullExpression.top;
331 if (iPreviousBinary) {
332 if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
334 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.evaluator);
335 binaryEval->setLeftEvaluator(iPreviousBinary);
337 binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
338 if(iPreviousBinary->precedence()<topNode->precedence() ) {
340 topNode = iPreviousBinary;
341 iPreviousBinary->setRightEvaluator(fullExpression.top);
344 std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
347 iPreviousBinary->setRightEvaluator(toSwap);
351 binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
354 printAST(binaryEval);
355 fullExpression.top = topNode;
356 return fullExpression;
360 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
364 template<
typename Op>
365 EvaluatorInfo createBinaryOperatorEvaluatorT(
int iSymbolLength,
367 ExpressionFinder
const& iEF,
368 std::string::const_iterator iBegin,
369 std::string::const_iterator iEnd) {
370 auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op> >(iPrec);
371 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd,op);
372 evalInfo.nextParseIndex += iSymbolLength;
374 if(evalInfo.evaluator.get() ==
nullptr) {
378 evalInfo.evaluator = op;
383 double operator()(
double iLHS,
double iRHS)
const {
390 createBinaryOperatorEvaluator( ExpressionFinder
const& iEF,
391 std::string::const_iterator iBegin,
392 std::string::const_iterator iEnd) {
393 EvaluatorInfo evalInfo;
399 return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
406 else if(*iBegin ==
'-') {
407 return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
413 else if(*iBegin ==
'*') {
414 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
420 else if(*iBegin ==
'/') {
421 return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
428 else if(*iBegin ==
'^') {
429 return createBinaryOperatorEvaluatorT<power>(1,
435 else if (*iBegin ==
'<' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
436 return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
443 else if (*iBegin ==
'>' and iBegin+1 != iEnd and *(iBegin+1) ==
'=') {
444 return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
451 else if (*iBegin ==
'<' ) {
452 return createBinaryOperatorEvaluatorT<std::less<double>>(1,
459 else if (*iBegin ==
'>' ) {
460 return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
467 else if (*iBegin ==
'=' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
468 return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
475 else if (*iBegin ==
'!' and iBegin+1 != iEnd and *(iBegin+1) ==
'=' ) {
476 return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
487 template<
typename Op>
489 checkForSingleArgFunction(std::string::const_iterator iBegin,
490 std::string::const_iterator iEnd,
491 ExpressionFinder
const* iExpressionFinder,
495 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
498 auto pos = iName.find(&(*iBegin), 0,iName.size());
500 if(std::string::npos ==
pos or *(iBegin+iName.size()) !=
'(') {
504 info.nextParseIndex = iName.size()+1;
506 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
507 if(iBegin+iName.size() == itEndParen) {
511 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen,
512 std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
513 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
514 if(argEvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
518 ++info.nextParseIndex;
520 info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(
std::move(argEvaluatorInfo.top),
522 info.top = info.evaluator;
526 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
527 std::string::const_iterator iEnd ) {
529 std::string::const_iterator it = iBegin;
530 for(; it != iEnd; ++it) {
533 }
else if(*it ==
')') {
536 else if( *it ==
',' and level == 0 ) {
545 template<
typename Op>
547 checkForTwoArgsFunction(std::string::const_iterator iBegin,
548 std::string::const_iterator iEnd,
549 ExpressionFinder
const* iExpressionFinder,
553 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
556 auto pos = iName.find(&(*iBegin), 0,iName.size());
558 if(std::string::npos ==
pos or *(iBegin+iName.size()) !=
'(') {
562 info.nextParseIndex = iName.size()+1;
564 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
565 if(iBegin+iName.size() == itEndParen) {
569 auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
571 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
572 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
573 if(arg1EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex != itComma-iBegin ) {
577 ++info.nextParseIndex;
579 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
580 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
582 if(arg2EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
586 ++info.nextParseIndex;
588 info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(
std::move(arg1EvaluatorInfo.top),
591 info.top = info.evaluator;
598 double const kLog10Inv = 1./
std::log(10.);
608 const std::string k_TMath__Landau(
"TMath::Landau");
616 FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
619 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
620 k_erf, [](
double iArg)->
double {
return std::erf(iArg); } );
621 if(info.evaluator.get() !=
nullptr) {
625 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
626 k_TMath__Erf, [](
double iArg)->
double {
return std::erf(iArg); } );
627 if(info.evaluator.get() !=
nullptr) {
631 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
632 k_TMath__Landau, [](
double iArg)->
double {
return TMath::Landau(iArg); } );
633 if(info.evaluator.get() !=
nullptr) {
637 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
638 k_log, [](
double iArg)->
double {
return std::log(iArg); } );
639 if(info.evaluator.get() !=
nullptr) {
643 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
644 k_TMath__Log, [](
double iArg)->
double {
return std::log(iArg); } );
645 if(info.evaluator.get() !=
nullptr) {
649 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
650 k_log10, [](
double iArg)->
double {
return std::log(iArg)*kLog10Inv; } );
651 if(info.evaluator.get() !=
nullptr) {
655 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
656 k_exp, [](
double iArg)->
double {
return std::exp(iArg); } );
657 if(info.evaluator.get() !=
nullptr) {
661 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
662 k_sqrt, [](
double iArg)->
double {
return std::sqrt(iArg); } );
663 if(info.evaluator.get() !=
nullptr) {
667 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
668 k_TMath__Sqrt, [](
double iArg)->
double {
return std::sqrt(iArg); } );
669 if(info.evaluator.get() !=
nullptr) {
673 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
674 k_abs, [](
double iArg)->
double {
return std::abs(iArg); } );
675 if(info.evaluator.get() !=
nullptr) {
679 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
680 k_TMath__Abs, [](
double iArg)->
double {
return std::abs(iArg); } );
681 if(info.evaluator.get() !=
nullptr) {
685 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
686 k_pow, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
687 if(info.evaluator.get() !=
nullptr) {
691 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
692 k_TMath__Power, [](
double iArg1,
double iArg2)->
double {
return std::pow(iArg1,iArg2); } );
693 if(info.evaluator.get() !=
nullptr) {
697 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
698 k_max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
699 if(info.evaluator.get() !=
nullptr) {
703 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
704 k_min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
705 if(info.evaluator.get() !=
nullptr) {
709 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
710 k_TMath__Max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
711 if(info.evaluator.get() !=
nullptr) {
715 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
716 k_TMath__Min, [](
double iArg1,
double iArg2)->
double {
return std::min(iArg1,iArg2); } );
717 if(info.evaluator.get() !=
nullptr) {
724 ExpressionFinder
const s_expressionFinder;
740 auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
742 if(
info.nextParseIndex != static_cast<int>(iFormula.size())
or info.top.get() ==
nullptr) {
743 throw cms::Exception(
"FormulaEvaluatorParseError")<<
"While parsing '"<<iFormula<<
"' could not parse beyond '"<<
std::string(iFormula.begin(),iFormula.begin()+
info.nextParseIndex) <<
"'";
746 m_nVariables =
info.maxNumVariables;
747 m_nParameters =
info.maxNumParameters;
756 return m_evaluator->evaluate(iVariables, iParameters);
761 throw cms::Exception(
"WrongNumVariables")<<
"FormulaEvaluator expected at least "<<m_nVariables<<
" but was passed only "<<iSize;
765 throw cms::Exception(
"WrongNumParameters")<<
"FormulaEvaluator expected at least "<<m_nParameters<<
" but was passed only "<<iSize;
768 std::vector<std::string>
770 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)
Power< A, B >::type pow(const A &a, const B &b)