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 
582 
583  EvaluatorInfo
584  FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const {
585  EvaluatorInfo info;
586 
587  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
588  k_erf, [](double iArg)->double { return std::erf(iArg); } );
589  if(info.evaluator.get() != nullptr) {
590  return info;
591  }
592 
593  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
594  k_TMath__Erf, [](double iArg)->double { return std::erf(iArg); } );
595  if(info.evaluator.get() != nullptr) {
596  return info;
597  }
598 
599  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
600  k_TMath__Landau, [](double iArg)->double { return TMath::Landau(iArg); } );
601  if(info.evaluator.get() != nullptr) {
602  return info;
603  }
604 
605  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
606  k_log, [](double iArg)->double { return std::log(iArg); } );
607  if(info.evaluator.get() != nullptr) {
608  return info;
609  }
610 
611  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
612  k_TMath__Log, [](double iArg)->double { return std::log(iArg); } );
613  if(info.evaluator.get() != nullptr) {
614  return info;
615  }
616 
617  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
618  k_log10, [](double iArg)->double { return std::log(iArg)*kLog10Inv; } );
619  if(info.evaluator.get() != nullptr) {
620  return info;
621  }
622 
623  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
624  k_exp, [](double iArg)->double { return std::exp(iArg); } );
625  if(info.evaluator.get() != nullptr) {
626  return info;
627  }
628 
629  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
630  k_pow, [](double iArg1, double iArg2)->double { return std::pow(iArg1,iArg2); } );
631  if(info.evaluator.get() != nullptr) {
632  return info;
633  }
634 
635  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
636  k_TMath__Power, [](double iArg1, double iArg2)->double { return std::pow(iArg1,iArg2); } );
637  if(info.evaluator.get() != nullptr) {
638  return info;
639  }
640 
641  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
642  k_max, [](double iArg1, double iArg2)->double { return std::max(iArg1,iArg2); } );
643  if(info.evaluator.get() != nullptr) {
644  return info;
645  }
646 
647  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
648  k_min, [](double iArg1, double iArg2)->double { return std::min(iArg1,iArg2); } );
649  if(info.evaluator.get() != nullptr) {
650  return info;
651  }
652 
653  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
654  k_TMath__Max, [](double iArg1, double iArg2)->double { return std::max(iArg1,iArg2); } );
655  if(info.evaluator.get() != nullptr) {
656  return info;
657  }
658 
659  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
660  k_TMath__Min, [](double iArg1, double iArg2)->double { return std::min(iArg1,iArg2); } );
661  if(info.evaluator.get() != nullptr) {
662  return info;
663  }
664 
665  return info;
666  };
667 
668  ExpressionFinder const s_expressionFinder;
669 
670 }
671 //
672 // constants, enums and typedefs
673 //
674 
675 //
676 // static data member definitions
677 //
678 
679 //
680 // constructors and destructor
681 //
683 {
684  auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
685 
686  if(info.nextParseIndex != static_cast<int>(iFormula.size()) or info.top.get() == nullptr) {
687  throw cms::Exception("FormulaEvaluatorParseError")<<"While parsing '"<<iFormula<<"' could not parse beyond '"<<std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<"'";
688  }
689  m_evaluator = std::move(info.top);
690  m_nVariables = info.maxNumVariables;
691  m_nParameters = info.maxNumParameters;
692 }
693 
694 //
695 // const member functions
696 //
697 double
698 FormulaEvaluator::evaluate(double const* iVariables, double const* iParameters) const
699 {
700  return m_evaluator->evaluate(iVariables, iParameters);
701 }
702 
703 void
705  throw cms::Exception("WrongNumVariables")<<"FormulaEvaluator expected at least "<<m_nVariables<<" but was passed only "<<iSize;
706 }
707 void
709  throw cms::Exception("WrongNumParameters")<<"FormulaEvaluator expected at least "<<m_nParameters<<" but was passed only "<<iSize;
710 }
static const TGPicture * info(bool iBackgroundIsBlack)
void setRightEvaluator(std::shared_ptr< EvaluatorBase > iOther)
void swapLeftEvaluator(std::shared_ptr< EvaluatorBase > &iNew)
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
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