CMS 3D CMS Logo

FormulaEvaluator.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: CommonTools/Utils
4 // Class : FormulaEvaluator
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Christopher Jones
10 // Created: Thu, 24 Sep 2015 19:07:58 GMT
11 //
12 
13 // system include files
14 #include <cassert>
15 #include <functional>
16 #include <cstdlib>
17 #include <cmath>
18 #include "TMath.h"
19 
20 //#define DEBUG_AST
21 #if defined(DEBUG_AST)
22 #include <iostream>
23 #endif
24 // user include files
26 #include "formulaEvaluatorBase.h"
35 
36 using namespace reco;
37 
38 namespace {
39 
40 #if defined(DEBUG_AST)
41  void printAST(formula::EvaluatorBase* e) {
42  std::cout <<"printAST"<<std::endl;
43  for(auto const& n: e->abstractSyntaxTree()) {
44  std::cout <<n<<std::endl;
45  }
46  }
47 #define DEBUG_STATE(_v_) std::cout <<_v_<<std::endl
48 #else
49  inline void printAST(void*) {}
50 #define DEBUG_STATE(_v_)
51 #endif
52  //Formula Parser Code
53  struct EvaluatorInfo {
54  std::shared_ptr<reco::formula::EvaluatorBase> evaluator;
55  std::shared_ptr<reco::formula::EvaluatorBase> top;
56  int nextParseIndex=0;
57  unsigned int maxNumVariables=0;
58  unsigned int maxNumParameters=0;
59  };
60 
61  class ExpressionElementFinderBase {
62  public:
63  virtual bool checkStart(char) const = 0;
64 
65  virtual EvaluatorInfo createEvaluator(std::string::const_iterator, std::string::const_iterator) const = 0;
66 
67  virtual ~ExpressionElementFinderBase() = default;
68  };
69 
70  std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin, std::string::const_iterator iEnd) {
71  if (iBegin == iEnd) {
72  return iBegin;
73  }
74  if( *iBegin != '(') {
75  return iBegin;
76  }
77  int level = 1;
78  size_t index = 0;
79  for( auto it = iBegin+1; it != iEnd; ++it) {
80  ++index;
81  if (*it == '(') {
82  ++level;
83  } else if (*it == ')') {
84  --level;
85  if (level == 0) {
86  break;
87  }
88  }
89  }
90  return iBegin + index;
91  }
92 
93  class ConstantFinder : public ExpressionElementFinderBase {
94  bool checkStart(char iSymbol) const final {
95  if( iSymbol == '-' or iSymbol == '.' or std::isdigit(iSymbol) ) {
96  return true;
97  }
98  return false;
99  }
100 
101  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
102  EvaluatorInfo info;
103  try {
104  size_t endIndex=0;
105  std::string s(iBegin,iEnd);
106  double value = stod(s, &endIndex);
107 
108  info.nextParseIndex = endIndex;
109  info.evaluator = std::make_shared<reco::formula::ConstantEvaluator>(value);
110  info.top = info.evaluator;
111  } catch ( std::invalid_argument ) {}
112 
113  return info;
114 
115  }
116  };
117 
118 
119  class ParameterFinder : public ExpressionElementFinderBase {
120  bool checkStart(char iSymbol) const final {
121  if( iSymbol == '[') {
122  return true;
123  }
124  return false;
125  }
126 
127  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
128  EvaluatorInfo info;
129  if(iEnd == iBegin) {
130  return info;
131  }
132  if(*iBegin != '[') {
133  return info;
134  }
135  info.nextParseIndex = 1;
136  try {
137  size_t endIndex=0;
138  std::string s(iBegin+1,iEnd);
139  unsigned long value = stoul(s, &endIndex);
140 
141  if( iBegin+endIndex+1 == iEnd or *(iBegin+1+endIndex) != ']' ) {
142  return info;
143  }
144 
145 
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 ) {}
151 
152  return info;
153 
154  }
155  };
156 
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' ) {
160  return true;
161  }
162  return false;
163  }
164 
165  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
166  EvaluatorInfo info;
167  if(iBegin == iEnd) {
168  return info;
169  }
170  unsigned int index = 4;
171  switch (*iBegin) {
172  case 'x':
173  { index = 0; break;}
174  case 'y':
175  { index = 1; break;}
176  case 'z':
177  { index = 2; break;}
178  case 't':
179  {index = 3; break;}
180  }
181  if(index == 4) {
182  return info;
183  }
184  info.nextParseIndex = 1;
185  info.maxNumVariables = index+1;
186  info.evaluator = std::make_shared<reco::formula::VariableEvaluator>(index);
187  info.top = info.evaluator;
188  return info;
189  }
190  };
191 
192  class ExpressionFinder;
193 
194  class FunctionFinder : public ExpressionElementFinderBase {
195  public:
196  FunctionFinder(ExpressionFinder const* iEF):
197  m_expressionFinder(iEF) {};
198 
199  bool checkStart(char iSymbol) const final {
200  return std::isalpha(iSymbol);
201  }
202 
203  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final;
204 
205  private:
206  ExpressionFinder const* m_expressionFinder;
207  };
208 
209 
210  EvaluatorInfo createBinaryOperatorEvaluator( ExpressionFinder const&,
211  std::string::const_iterator iBegin,
212  std::string::const_iterator iEnd) ;
213 
214  class ExpressionFinder {
215 
216  public:
217  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{});
223  }
224 
225  bool checkStart(char iChar) const {
226  if ( '(' == iChar or '-' == iChar or '+' ==iChar) {
227  return true;
228  }
229  for( auto const& e : m_elements) {
230  if (e->checkStart(iChar) ) {
231  return true;
232  }
233  }
234  return false;
235  }
236 
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;
241  }
242  //Start with '+'
243  if (*iBegin == '+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
244  leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd, iPreviousBinary);
245 
246  //have to account for the '+' we skipped over
247  leftEvaluatorInfo.nextParseIndex +=1;
248  if( nullptr == leftEvaluatorInfo.evaluator.get() ) {
249  return leftEvaluatorInfo;
250  }
251  }
252  //Start with '-'
253  else if (*iBegin == '-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
254  leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd,iPreviousBinary);
255 
256  //have to account for the '+' we skipped over
257  leftEvaluatorInfo.nextParseIndex +=1;
258  if( nullptr == leftEvaluatorInfo.evaluator.get() ) {
259  return leftEvaluatorInfo;
260  }
261  leftEvaluatorInfo.evaluator = std::make_shared<reco::formula::UnaryMinusEvaluator>( std::move(leftEvaluatorInfo.top));
262  leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
263  }
264  //Start with '('
265  else if( *iBegin == '(') {
266  auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
267  if(iBegin== endParenthesis) {
268  return leftEvaluatorInfo;
269  }
270  leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis,std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
271  ++leftEvaluatorInfo.nextParseIndex;
272  if(leftEvaluatorInfo.evaluator.get() == nullptr) {
273  return leftEvaluatorInfo;
274  }
275  //need to account for closing parenthesis
276  ++leftEvaluatorInfo.nextParseIndex;
277  leftEvaluatorInfo.top->setPrecedenceToParenthesis();
278  DEBUG_STATE("close parenthesis");
279  printAST(leftEvaluatorInfo.top.get());
280  leftEvaluatorInfo.evaluator = leftEvaluatorInfo.top;
281  } else {
282  //Does not start with a '('
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) {
288  break;
289  }
290  if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
291  maxParseDistance = leftEvaluatorInfo.nextParseIndex;
292  }
293  }
294  }
295  if(leftEvaluatorInfo.evaluator.get() == nullptr) {
296  //failed to parse
297  leftEvaluatorInfo.nextParseIndex = maxParseDistance;
298  return leftEvaluatorInfo;
299  }
300  }
301  //did we evaluate the full expression?
302  if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
303  if (iPreviousBinary) {
304  iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
305  leftEvaluatorInfo.top = iPreviousBinary;
306  }
307  DEBUG_STATE("full expression");
308  printAST(leftEvaluatorInfo.evaluator.get());
309  return leftEvaluatorInfo;
310  }
311 
312  //see if this is a binary expression
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) {
318  //did not parse the full expression
319  fullExpression.evaluator.reset();
320  }
321 
322  if(fullExpression.evaluator == nullptr) {
323  //we had a parsing problem
324  return fullExpression;
325  }
326 
327  printAST(fullExpression.evaluator.get());
328  //Now to handle precedence
329  auto topNode = fullExpression.top;
330  auto binaryEval = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(fullExpression.evaluator.get());
331  if (iPreviousBinary) {
332  if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
333  DEBUG_STATE("prec >=");
334  iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.evaluator);
335  binaryEval->setLeftEvaluator(iPreviousBinary);
336  } else {
337  binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
338  if(iPreviousBinary->precedence()<topNode->precedence() ) {
339  DEBUG_STATE(" swtich topNode");
340  topNode = iPreviousBinary;
341  iPreviousBinary->setRightEvaluator(fullExpression.top);
342  }else {
343  DEBUG_STATE("swapping");
344  std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
345  auto topBinary = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(topNode.get());
346  topBinary->swapLeftEvaluator(toSwap);
347  iPreviousBinary->setRightEvaluator(toSwap);
348  }
349  }
350  } else {
351  binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
352  }
353  DEBUG_STATE("finished binary");
354  printAST(binaryEval);
355  fullExpression.top = topNode;
356  return fullExpression;
357  }
358 
359  private:
360  std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
361 
362  };
363 
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;
373 
374  if(evalInfo.evaluator.get() == nullptr) {
375  return evalInfo;
376  }
377 
378  evalInfo.evaluator = op;
379  return evalInfo;
380  }
381 
382  struct power {
383  double operator()(double iLHS, double iRHS) const {
384  return std::pow(iLHS,iRHS);
385  }
386  };
387 
388 
389  EvaluatorInfo
390  createBinaryOperatorEvaluator( ExpressionFinder const& iEF,
391  std::string::const_iterator iBegin,
392  std::string::const_iterator iEnd) {
393  EvaluatorInfo evalInfo;
394  if(iBegin == iEnd) {
395  return evalInfo;
396  }
397 
398  if(*iBegin == '+') {
399  return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
401  iEF,
402  iBegin,
403  iEnd);
404  }
405 
406  else if(*iBegin == '-') {
407  return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
409  iEF,
410  iBegin,
411  iEnd);
412  }
413  else if(*iBegin == '*') {
414  return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
416  iEF,
417  iBegin,
418  iEnd);
419  }
420  else if(*iBegin == '/') {
421  return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
423  iEF,
424  iBegin,
425  iEnd);
426  }
427 
428  else if(*iBegin == '^') {
429  return createBinaryOperatorEvaluatorT<power>(1,
431  iEF,
432  iBegin,
433  iEnd);
434  }
435  else if (*iBegin =='<' and iBegin+1 != iEnd and *(iBegin+1) == '=') {
436  return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
438  iEF,
439  iBegin,
440  iEnd);
441 
442  }
443  else if (*iBegin =='>' and iBegin+1 != iEnd and *(iBegin+1) == '=') {
444  return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
446  iEF,
447  iBegin,
448  iEnd);
449 
450  }
451  else if (*iBegin =='<' ) {
452  return createBinaryOperatorEvaluatorT<std::less<double>>(1,
454  iEF,
455  iBegin,
456  iEnd);
457 
458  }
459  else if (*iBegin =='>' ) {
460  return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
462  iEF,
463  iBegin,
464  iEnd);
465 
466  }
467  else if (*iBegin =='=' and iBegin+1 != iEnd and *(iBegin+1) == '=' ) {
468  return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
470  iEF,
471  iBegin,
472  iEnd);
473 
474  }
475  else if (*iBegin =='!' and iBegin+1 != iEnd and *(iBegin+1) == '=' ) {
476  return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
478  iEF,
479  iBegin,
480  iEnd);
481 
482  }
483  return evalInfo;
484  }
485 
486 
487  template<typename Op>
488  EvaluatorInfo
489  checkForSingleArgFunction(std::string::const_iterator iBegin,
490  std::string::const_iterator iEnd,
491  ExpressionFinder const* iExpressionFinder,
492  const std::string& iName,
493  Op op) {
494  EvaluatorInfo info;
495  if(iName.size()+2 > static_cast<unsigned int>(iEnd-iBegin) ) {
496  return info;
497  }
498  auto pos = iName.find(&(*iBegin), 0,iName.size());
499 
500  if(std::string::npos == pos or *(iBegin+iName.size()) != '(') {
501  return info;
502  }
503 
504  info.nextParseIndex = iName.size()+1;
505 
506  auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
507  if(iBegin+iName.size() == itEndParen) {
508  return info;
509  }
510 
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) {
515  return info;
516  }
517  //account for closing parenthesis
518  ++info.nextParseIndex;
519 
520  info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(std::move(argEvaluatorInfo.top),
521  op);
522  info.top = info.evaluator;
523  return info;
524  }
525 
526  std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
527  std::string::const_iterator iEnd ) {
528  int level = 0;
529  std::string::const_iterator it = iBegin;
530  for(; it != iEnd; ++it) {
531  if (*it == '(') {
532  ++level;
533  } else if(*it == ')') {
534  --level;
535  }
536  else if( *it ==',' and level == 0 ) {
537  return it;
538  }
539  }
540 
541  return it;
542  }
543 
544 
545  template<typename Op>
546  EvaluatorInfo
547  checkForTwoArgsFunction(std::string::const_iterator iBegin,
548  std::string::const_iterator iEnd,
549  ExpressionFinder const* iExpressionFinder,
550  const std::string& iName,
551  Op op) {
552  EvaluatorInfo info;
553  if(iName.size()+2 > static_cast<unsigned int>(iEnd-iBegin) ) {
554  return info;
555  }
556  auto pos = iName.find(&(*iBegin), 0,iName.size());
557 
558  if(std::string::npos == pos or *(iBegin+iName.size()) != '(') {
559  return info;
560  }
561 
562  info.nextParseIndex = iName.size()+1;
563 
564  auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
565  if(iBegin+iName.size() == itEndParen) {
566  return info;
567  }
568 
569  auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
570 
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 ) {
574  return info;
575  }
576  //account for commas
577  ++info.nextParseIndex;
578 
579  auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
580  info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
581 
582  if(arg2EvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
583  return info;
584  }
585  //account for closing parenthesis
586  ++info.nextParseIndex;
587 
588  info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(std::move(arg1EvaluatorInfo.top),
589  std::move(arg2EvaluatorInfo.top),
590  op);
591  info.top = info.evaluator;
592  return info;
593  }
594 
595  const std::string k_log("log");
596  const std::string k_log10("log10");
597  const std::string k_TMath__Log("TMath::Log");
598  double const kLog10Inv = 1./std::log(10.);
599  const std::string k_exp("exp");
600  const std::string k_pow("pow");
601  const std::string k_TMath__Power("TMath::Power");
602  const std::string k_max("max");
603  const std::string k_min("min");
604  const std::string k_TMath__Max("TMath::Max");
605  const std::string k_TMath__Min("TMath::Min");
606  const std::string k_TMath__Erf("TMath::Erf");
607  const std::string k_erf("erf");
608  const std::string k_TMath__Landau("TMath::Landau");
609  const std::string k_sqrt("sqrt");
610  const std::string k_TMath__Sqrt("TMath::Sqrt");
611  const std::string k_abs("abs");
612  const std::string k_TMath__Abs("TMath::Abs");
613 
614 
615  EvaluatorInfo
616  FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const {
617  EvaluatorInfo info;
618 
619  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
620  k_erf, [](double iArg)->double { return std::erf(iArg); } );
621  if(info.evaluator.get() != nullptr) {
622  return info;
623  }
624 
625  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
626  k_TMath__Erf, [](double iArg)->double { return std::erf(iArg); } );
627  if(info.evaluator.get() != nullptr) {
628  return info;
629  }
630 
631  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
632  k_TMath__Landau, [](double iArg)->double { return TMath::Landau(iArg); } );
633  if(info.evaluator.get() != nullptr) {
634  return info;
635  }
636 
637  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
638  k_log, [](double iArg)->double { return std::log(iArg); } );
639  if(info.evaluator.get() != nullptr) {
640  return info;
641  }
642 
643  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
644  k_TMath__Log, [](double iArg)->double { return std::log(iArg); } );
645  if(info.evaluator.get() != nullptr) {
646  return info;
647  }
648 
649  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
650  k_log10, [](double iArg)->double { return std::log(iArg)*kLog10Inv; } );
651  if(info.evaluator.get() != nullptr) {
652  return info;
653  }
654 
655  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
656  k_exp, [](double iArg)->double { return std::exp(iArg); } );
657  if(info.evaluator.get() != nullptr) {
658  return info;
659  }
660 
661  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
662  k_sqrt, [](double iArg)->double { return std::sqrt(iArg); } );
663  if(info.evaluator.get() != nullptr) {
664  return info;
665  }
666 
667  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
668  k_TMath__Sqrt, [](double iArg)->double { return std::sqrt(iArg); } );
669  if(info.evaluator.get() != nullptr) {
670  return info;
671  }
672 
673  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
674  k_abs, [](double iArg)->double { return std::abs(iArg); } );
675  if(info.evaluator.get() != nullptr) {
676  return info;
677  }
678 
679  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
680  k_TMath__Abs, [](double iArg)->double { return std::abs(iArg); } );
681  if(info.evaluator.get() != nullptr) {
682  return info;
683  }
684 
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) {
688  return info;
689  }
690 
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) {
694  return info;
695  }
696 
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) {
700  return info;
701  }
702 
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) {
706  return info;
707  }
708 
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) {
712  return info;
713  }
714 
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) {
718  return info;
719  }
720 
721  return info;
722  };
723 
724  ExpressionFinder const s_expressionFinder;
725 
726 }
727 //
728 // constants, enums and typedefs
729 //
730 
731 //
732 // static data member definitions
733 //
734 
735 //
736 // constructors and destructor
737 //
739 {
740  auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
741 
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) <<"'";
744  }
745  m_evaluator = std::move(info.top);
746  m_nVariables = info.maxNumVariables;
747  m_nParameters = info.maxNumParameters;
748 }
749 
750 //
751 // const member functions
752 //
753 double
754 FormulaEvaluator::evaluate(double const* iVariables, double const* iParameters) const
755 {
756  return m_evaluator->evaluate(iVariables, iParameters);
757 }
758 
759 void
761  throw cms::Exception("WrongNumVariables")<<"FormulaEvaluator expected at least "<<m_nVariables<<" but was passed only "<<iSize;
762 }
763 void
765  throw cms::Exception("WrongNumParameters")<<"FormulaEvaluator expected at least "<<m_nParameters<<" but was passed only "<<iSize;
766 }
767 
768 std::vector<std::string>
770  return m_evaluator->abstractSyntaxTree();
771 }
static const TGPicture * info(bool iBackgroundIsBlack)
void swapLeftEvaluator(std::shared_ptr< EvaluatorBase > &iNew)
#define DEBUG_STATE(_v_)
virtual std::vector< std::string > abstractSyntaxTree() const =0
T sqrt(T t)
Definition: SSEVec.h:18
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
Definition: Activities.doc:12
double evaluate(V const &iVariables, P const &iParameters) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Definition: value.py:1
T min(T a, T b)
Definition: MathUtil.h:58
void throwWrongNumberOfParameters(size_t) const
FormulaEvaluator(std::string const &iFormula)
std::vector< std::string > abstractSyntaxTree() const
fixed size matrix
void throwWrongNumberOfVariables(size_t) const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
def move(src, dest)
Definition: eostools.py:510