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 // user include files
22 #include "formulaEvaluatorBase.h"
31 
32 using namespace reco;
33 
34 namespace {
35  //Formula Parser Code
36  struct EvaluatorInfo {
37  std::shared_ptr<reco::formula::EvaluatorBase> evaluator;
38  std::shared_ptr<reco::formula::EvaluatorBase> top;
39  int nextParseIndex=0;
40  unsigned int maxNumVariables=0;
41  unsigned int maxNumParameters=0;
42  };
43 
44  class ExpressionElementFinderBase {
45  public:
46  virtual bool checkStart(char) const = 0;
47 
48  virtual EvaluatorInfo createEvaluator(std::string::const_iterator, std::string::const_iterator) const = 0;
49 
50  virtual ~ExpressionElementFinderBase() = default;
51  };
52 
53  std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin, std::string::const_iterator iEnd) {
54  if (iBegin == iEnd) {
55  return iBegin;
56  }
57  if( *iBegin != '(') {
58  return iBegin;
59  }
60  int level = 1;
61  size_t index = 0;
62  for( auto it = iBegin+1; it != iEnd; ++it) {
63  ++index;
64  if (*it == '(') {
65  ++level;
66  } else if (*it == ')') {
67  --level;
68  if (level == 0) {
69  break;
70  }
71  }
72  }
73  return iBegin + index;
74  }
75 
76  class ConstantFinder : public ExpressionElementFinderBase {
77  bool checkStart(char iSymbol) const final {
78  if( iSymbol == '-' or iSymbol == '.' or std::isdigit(iSymbol) ) {
79  return true;
80  }
81  return false;
82  }
83 
84  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
85  EvaluatorInfo info;
86  try {
87  size_t endIndex=0;
88  std::string s(iBegin,iEnd);
89  double value = stod(s, &endIndex);
90 
91  info.nextParseIndex = endIndex;
92  info.evaluator = std::make_shared<reco::formula::ConstantEvaluator>(value);
93  info.top = info.evaluator;
94  } catch ( std::invalid_argument ) {}
95 
96  return info;
97 
98  }
99  };
100 
101 
102  class ParameterFinder : public ExpressionElementFinderBase {
103  bool checkStart(char iSymbol) const final {
104  if( iSymbol == '[') {
105  return true;
106  }
107  return false;
108  }
109 
110  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
111  EvaluatorInfo info;
112  if(iEnd == iBegin) {
113  return info;
114  }
115  if(*iBegin != '[') {
116  return info;
117  }
118  info.nextParseIndex = 1;
119  try {
120  size_t endIndex=0;
121  std::string s(iBegin+1,iEnd);
122  unsigned long value = stoul(s, &endIndex);
123 
124  if( iBegin+endIndex+1 == iEnd or *(iBegin+1+endIndex) != ']' ) {
125  return info;
126  }
127 
128 
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 ) {}
134 
135  return info;
136 
137  }
138  };
139 
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' ) {
143  return true;
144  }
145  return false;
146  }
147 
148  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
149  EvaluatorInfo info;
150  if(iBegin == iEnd) {
151  return info;
152  }
153  unsigned int index = 4;
154  switch (*iBegin) {
155  case 'x':
156  { index = 0; break;}
157  case 'y':
158  { index = 1; break;}
159  case 'z':
160  { index = 2; break;}
161  case 't':
162  {index = 3; break;}
163  }
164  if(index == 4) {
165  return info;
166  }
167  info.nextParseIndex = 1;
168  info.maxNumVariables = index+1;
169  info.evaluator = std::make_shared<reco::formula::VariableEvaluator>(index);
170  info.top = info.evaluator;
171  return info;
172  }
173  };
174 
175  class ExpressionFinder;
176 
177  class FunctionFinder : public ExpressionElementFinderBase {
178  public:
179  FunctionFinder(ExpressionFinder const* iEF):
180  m_expressionFinder(iEF) {};
181 
182  bool checkStart(char iSymbol) const final {
183  return std::isalpha(iSymbol);
184  }
185 
186  EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final;
187 
188  private:
189  ExpressionFinder const* m_expressionFinder;
190  };
191 
192 
193  EvaluatorInfo createBinaryOperatorEvaluator( ExpressionFinder const&,
194  std::string::const_iterator iBegin,
195  std::string::const_iterator iEnd) ;
196 
197  class ExpressionFinder {
198 
199  public:
200  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{});
206  }
207 
208  bool checkStart(char iChar) const {
209  if ( '(' == iChar or '-' == iChar or '+' ==iChar) {
210  return true;
211  }
212  for( auto const& e : m_elements) {
213  if (e->checkStart(iChar) ) {
214  return true;
215  }
216  }
217  return false;
218  }
219 
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;
224  }
225  //Start with '+'
226  if (*iBegin == '+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
227  leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd, iPreviousBinary);
228 
229  //have to account for the '+' we skipped over
230  leftEvaluatorInfo.nextParseIndex +=1;
231  if( nullptr == leftEvaluatorInfo.evaluator.get() ) {
232  return leftEvaluatorInfo;
233  }
234  }
235  //Start with '-'
236  else if (*iBegin == '-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
237  leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd,iPreviousBinary);
238 
239  //have to account for the '+' we skipped over
240  leftEvaluatorInfo.nextParseIndex +=1;
241  if( nullptr == leftEvaluatorInfo.evaluator.get() ) {
242  return leftEvaluatorInfo;
243  }
244  leftEvaluatorInfo.evaluator = std::make_shared<reco::formula::UnaryMinusEvaluator>( std::move(leftEvaluatorInfo.top));
245  leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
246  }
247  //Start with '('
248  else if( *iBegin == '(') {
249  auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
250  if(iBegin== endParenthesis) {
251  return leftEvaluatorInfo;
252  }
253  leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis,std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
254  ++leftEvaluatorInfo.nextParseIndex;
255  if(leftEvaluatorInfo.evaluator.get() == nullptr) {
256  return leftEvaluatorInfo;
257  }
258  //need to account for closing parenthesis
259  ++leftEvaluatorInfo.nextParseIndex;
260  leftEvaluatorInfo.top->setPrecedenceToParenthesis();
261  } else {
262  //Does not start with a '('
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) {
268  break;
269  }
270  if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
271  maxParseDistance = leftEvaluatorInfo.nextParseIndex;
272  }
273  }
274  }
275  if(leftEvaluatorInfo.evaluator.get() == nullptr) {
276  //failed to parse
277  leftEvaluatorInfo.nextParseIndex = maxParseDistance;
278  return leftEvaluatorInfo;
279  }
280  }
281  //did we evaluate the full expression?
282  if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
283  if (iPreviousBinary) {
284  iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
285  leftEvaluatorInfo.top = iPreviousBinary;
286  }
287  return leftEvaluatorInfo;
288  }
289 
290  //see if this is a binary expression
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) {
296  //did not parse the full expression
297  fullExpression.evaluator.reset();
298  }
299 
300  if(fullExpression.evaluator == nullptr) {
301  //we had a parsing problem
302  return fullExpression;
303  }
304 
305  //Now to handle precedence
306  auto topNode = fullExpression.top;
307  auto binaryEval = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(fullExpression.evaluator.get());
308  if (iPreviousBinary) {
309  if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
310  iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.evaluator);
311  binaryEval->setLeftEvaluator(iPreviousBinary);
312  } else {
313  binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
314  if(iPreviousBinary->precedence()<topNode->precedence() ) {
315  topNode = iPreviousBinary;
316  iPreviousBinary->setRightEvaluator(fullExpression.top);
317  }else {
318  std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
319  auto topBinary = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(topNode.get());
320  topBinary->swapLeftEvaluator(toSwap);
321  iPreviousBinary->setRightEvaluator(toSwap);
322  }
323  }
324  } else {
325  binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
326  }
327  fullExpression.top = topNode;
328  return fullExpression;
329  }
330 
331  private:
332  std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
333 
334  };
335 
336  template<typename Op>
337  EvaluatorInfo createBinaryOperatorEvaluatorT(int iSymbolLength,
339  ExpressionFinder const& iEF,
340  std::string::const_iterator iBegin,
341  std::string::const_iterator iEnd) {
342  auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op> >(iPrec);
343  EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd,op);
344  evalInfo.nextParseIndex += iSymbolLength;
345 
346  if(evalInfo.evaluator.get() == nullptr) {
347  return evalInfo;
348  }
349 
350  evalInfo.evaluator = op;
351  return evalInfo;
352  }
353 
354  struct power {
355  double operator()(double iLHS, double iRHS) const {
356  return std::pow(iLHS,iRHS);
357  }
358  };
359 
360 
361  EvaluatorInfo
362  createBinaryOperatorEvaluator( ExpressionFinder const& iEF,
363  std::string::const_iterator iBegin,
364  std::string::const_iterator iEnd) {
365  EvaluatorInfo evalInfo;
366  if(iBegin == iEnd) {
367  return evalInfo;
368  }
369 
370  if(*iBegin == '+') {
371  return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
373  iEF,
374  iBegin,
375  iEnd);
376  }
377 
378  else if(*iBegin == '-') {
379  return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
381  iEF,
382  iBegin,
383  iEnd);
384  }
385  else if(*iBegin == '*') {
386  return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
388  iEF,
389  iBegin,
390  iEnd);
391  }
392  else if(*iBegin == '/') {
393  return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
395  iEF,
396  iBegin,
397  iEnd);
398  }
399 
400  else if(*iBegin == '^') {
401  return createBinaryOperatorEvaluatorT<power>(1,
403  iEF,
404  iBegin,
405  iEnd);
406  }
407  else if (*iBegin =='<' and iBegin+1 != iEnd and *(iBegin+1) == '=') {
408  return createBinaryOperatorEvaluatorT<std::less_equal<double>>(2,
410  iEF,
411  iBegin,
412  iEnd);
413 
414  }
415  else if (*iBegin =='>' and iBegin+1 != iEnd and *(iBegin+1) == '=') {
416  return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(2,
418  iEF,
419  iBegin,
420  iEnd);
421 
422  }
423  else if (*iBegin =='<' ) {
424  return createBinaryOperatorEvaluatorT<std::less<double>>(1,
426  iEF,
427  iBegin,
428  iEnd);
429 
430  }
431  else if (*iBegin =='>' ) {
432  return createBinaryOperatorEvaluatorT<std::greater<double>>(1,
434  iEF,
435  iBegin,
436  iEnd);
437 
438  }
439  else if (*iBegin =='=' and iBegin+1 != iEnd and *(iBegin+1) == '=' ) {
440  return createBinaryOperatorEvaluatorT<std::equal_to<double>>(2,
442  iEF,
443  iBegin,
444  iEnd);
445 
446  }
447  else if (*iBegin =='!' and iBegin+1 != iEnd and *(iBegin+1) == '=' ) {
448  return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(2,
450  iEF,
451  iBegin,
452  iEnd);
453 
454  }
455  return evalInfo;
456  }
457 
458 
459  template<typename Op>
460  EvaluatorInfo
461  checkForSingleArgFunction(std::string::const_iterator iBegin,
462  std::string::const_iterator iEnd,
463  ExpressionFinder const* iExpressionFinder,
464  const std::string& iName,
465  Op op) {
466  EvaluatorInfo info;
467  if(iName.size()+2 > static_cast<unsigned int>(iEnd-iBegin) ) {
468  return info;
469  }
470  auto pos = iName.find(&(*iBegin), 0,iName.size());
471 
472  if(std::string::npos == pos or *(iBegin+iName.size()) != '(') {
473  return info;
474  }
475 
476  info.nextParseIndex = iName.size()+1;
477 
478  auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
479  if(iBegin+iName.size() == itEndParen) {
480  return info;
481  }
482 
483  auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen,
484  std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
485  info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
486  if(argEvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
487  return info;
488  }
489  //account for closing parenthesis
490  ++info.nextParseIndex;
491 
492  info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(std::move(argEvaluatorInfo.top),
493  op);
494  info.top = info.evaluator;
495  return info;
496  }
497 
498  std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
499  std::string::const_iterator iEnd ) {
500  int level = 0;
501  std::string::const_iterator it = iBegin;
502  for(; it != iEnd; ++it) {
503  if (*it == '(') {
504  ++level;
505  } else if(*it == ')') {
506  --level;
507  }
508  else if( *it ==',' and level == 0 ) {
509  return it;
510  }
511  }
512 
513  return it;
514  }
515 
516 
517  template<typename Op>
518  EvaluatorInfo
519  checkForTwoArgsFunction(std::string::const_iterator iBegin,
520  std::string::const_iterator iEnd,
521  ExpressionFinder const* iExpressionFinder,
522  const std::string& iName,
523  Op op) {
524  EvaluatorInfo info;
525  if(iName.size()+2 > static_cast<unsigned int>(iEnd-iBegin) ) {
526  return info;
527  }
528  auto pos = iName.find(&(*iBegin), 0,iName.size());
529 
530  if(std::string::npos == pos or *(iBegin+iName.size()) != '(') {
531  return info;
532  }
533 
534  info.nextParseIndex = iName.size()+1;
535 
536  auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
537  if(iBegin+iName.size() == itEndParen) {
538  return info;
539  }
540 
541  auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
542 
543  auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
544  info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
545  if(arg1EvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex != itComma-iBegin ) {
546  return info;
547  }
548  //account for commas
549  ++info.nextParseIndex;
550 
551  auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
552  info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
553 
554  if(arg2EvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
555  return info;
556  }
557  //account for closing parenthesis
558  ++info.nextParseIndex;
559 
560  info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(std::move(arg1EvaluatorInfo.top),
561  std::move(arg2EvaluatorInfo.top),
562  op);
563  info.top = info.evaluator;
564  return info;
565  }
566 
567  const std::string k_log("log");
568  const std::string k_log10("log10");
569  const std::string k_TMath__Log("TMath::Log");
570  double const kLog10Inv = 1./std::log(10.);
571  const std::string k_exp("exp");
572  const std::string k_pow("pow");
573  const std::string k_TMath__Power("TMath::Power");
574  const std::string k_max("max");
575  const std::string k_min("min");
576  const std::string k_TMath__Max("TMath::Max");
577  const std::string k_TMath__Min("TMath::Min");
578  const std::string k_TMath__Erf("TMath::Erf");
579  const std::string k_erf("erf");
580  const std::string k_TMath__Landau("TMath::Landau");
581  const std::string k_sqrt("sqrt");
582  const std::string k_TMath__Sqrt("TMath::Sqrt");
583  const std::string k_abs("abs");
584  const std::string k_TMath__Abs("TMath::Abs");
585 
586 
587  EvaluatorInfo
588  FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const {
589  EvaluatorInfo info;
590 
591  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
592  k_erf, [](double iArg)->double { return std::erf(iArg); } );
593  if(info.evaluator.get() != nullptr) {
594  return info;
595  }
596 
597  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
598  k_TMath__Erf, [](double iArg)->double { return std::erf(iArg); } );
599  if(info.evaluator.get() != nullptr) {
600  return info;
601  }
602 
603  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
604  k_TMath__Landau, [](double iArg)->double { return TMath::Landau(iArg); } );
605  if(info.evaluator.get() != nullptr) {
606  return info;
607  }
608 
609  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
610  k_log, [](double iArg)->double { return std::log(iArg); } );
611  if(info.evaluator.get() != nullptr) {
612  return info;
613  }
614 
615  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
616  k_TMath__Log, [](double iArg)->double { return std::log(iArg); } );
617  if(info.evaluator.get() != nullptr) {
618  return info;
619  }
620 
621  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
622  k_log10, [](double iArg)->double { return std::log(iArg)*kLog10Inv; } );
623  if(info.evaluator.get() != nullptr) {
624  return info;
625  }
626 
627  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
628  k_exp, [](double iArg)->double { return std::exp(iArg); } );
629  if(info.evaluator.get() != nullptr) {
630  return info;
631  }
632 
633  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
634  k_sqrt, [](double iArg)->double { return std::sqrt(iArg); } );
635  if(info.evaluator.get() != nullptr) {
636  return info;
637  }
638 
639  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
640  k_TMath__Sqrt, [](double iArg)->double { return std::sqrt(iArg); } );
641  if(info.evaluator.get() != nullptr) {
642  return info;
643  }
644 
645  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
646  k_abs, [](double iArg)->double { return std::abs(iArg); } );
647  if(info.evaluator.get() != nullptr) {
648  return info;
649  }
650 
651  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
652  k_TMath__Abs, [](double iArg)->double { return std::abs(iArg); } );
653  if(info.evaluator.get() != nullptr) {
654  return info;
655  }
656 
657  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
658  k_pow, [](double iArg1, double iArg2)->double { return std::pow(iArg1,iArg2); } );
659  if(info.evaluator.get() != nullptr) {
660  return info;
661  }
662 
663  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
664  k_TMath__Power, [](double iArg1, double iArg2)->double { return std::pow(iArg1,iArg2); } );
665  if(info.evaluator.get() != nullptr) {
666  return info;
667  }
668 
669  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
670  k_max, [](double iArg1, double iArg2)->double { return std::max(iArg1,iArg2); } );
671  if(info.evaluator.get() != nullptr) {
672  return info;
673  }
674 
675  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
676  k_min, [](double iArg1, double iArg2)->double { return std::min(iArg1,iArg2); } );
677  if(info.evaluator.get() != nullptr) {
678  return info;
679  }
680 
681  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
682  k_TMath__Max, [](double iArg1, double iArg2)->double { return std::max(iArg1,iArg2); } );
683  if(info.evaluator.get() != nullptr) {
684  return info;
685  }
686 
687  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
688  k_TMath__Min, [](double iArg1, double iArg2)->double { return std::min(iArg1,iArg2); } );
689  if(info.evaluator.get() != nullptr) {
690  return info;
691  }
692 
693  return info;
694  };
695 
696  ExpressionFinder const s_expressionFinder;
697 
698 }
699 //
700 // constants, enums and typedefs
701 //
702 
703 //
704 // static data member definitions
705 //
706 
707 //
708 // constructors and destructor
709 //
711 {
712  auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
713 
714  if(info.nextParseIndex != static_cast<int>(iFormula.size()) or info.top.get() == nullptr) {
715  throw cms::Exception("FormulaEvaluatorParseError")<<"While parsing '"<<iFormula<<"' could not parse beyond '"<<std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<"'";
716  }
717  m_evaluator = std::move(info.top);
718  m_nVariables = info.maxNumVariables;
719  m_nParameters = info.maxNumParameters;
720 }
721 
722 //
723 // const member functions
724 //
725 double
726 FormulaEvaluator::evaluate(double const* iVariables, double const* iParameters) const
727 {
728  return m_evaluator->evaluate(iVariables, iParameters);
729 }
730 
731 void
733  throw cms::Exception("WrongNumVariables")<<"FormulaEvaluator expected at least "<<m_nVariables<<" but was passed only "<<iSize;
734 }
735 void
737  throw cms::Exception("WrongNumParameters")<<"FormulaEvaluator expected at least "<<m_nParameters<<" but was passed only "<<iSize;
738 }
static const TGPicture * info(bool iBackgroundIsBlack)
void setRightEvaluator(std::shared_ptr< EvaluatorBase > iOther)
void swapLeftEvaluator(std::shared_ptr< EvaluatorBase > &iNew)
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)
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