CMS 3D CMS Logo

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