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