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  //Now to handle precedence
301  auto topNode = fullExpression.top;
302  auto binaryEval = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(fullExpression.evaluator.get());
303  if (iPreviousBinary) {
304  if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence() ) {
305  iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.evaluator);
306  binaryEval->setLeftEvaluator(iPreviousBinary);
307  } else {
308  binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
309  if(iPreviousBinary->precedence()<topNode->precedence() ) {
310  topNode = iPreviousBinary;
311  iPreviousBinary->setRightEvaluator(fullExpression.top);
312  }else {
313  std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
314  auto topBinary = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(topNode.get());
315  topBinary->swapLeftEvaluator(toSwap);
316  iPreviousBinary->setRightEvaluator(toSwap);
317  }
318  }
319  } else {
320  binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
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.top),
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.top),
556  std::move(arg2EvaluatorInfo.top),
557  op);
558  info.top = info.evaluator;
559  return info;
560  }
561 
562  const std::string k_log("log");
563  const std::string k_log10("log10");
564  const std::string k_TMath__Log("TMath::Log");
565  double const kLog10Inv = 1./std::log(10.);
566  const std::string k_exp("exp");
567  const std::string k_pow("pow");
568  const std::string k_TMath__Power("TMath::Power");
569  const std::string k_max("max");
570  const std::string k_min("min");
571  const std::string k_TMath__Max("TMath::Max");
572  const std::string k_TMath__Min("TMath::Min");
573  const std::string k_TMath__Erf("TMath::Erf");
574  const std::string k_erf("erf");
575  const std::string k_TMath__Landau("TMath::Landau");
576 
577 
578  EvaluatorInfo
579  FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const {
580  EvaluatorInfo info;
581 
582  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
583  k_erf, [](double iArg)->double { return std::erf(iArg); } );
584  if(info.evaluator.get() != nullptr) {
585  return info;
586  }
587 
588  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
589  k_TMath__Erf, [](double iArg)->double { return std::erf(iArg); } );
590  if(info.evaluator.get() != nullptr) {
591  return info;
592  }
593 
594  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
595  k_TMath__Landau, [](double iArg)->double { return TMath::Landau(iArg); } );
596  if(info.evaluator.get() != nullptr) {
597  return info;
598  }
599 
600  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
601  k_log, [](double iArg)->double { return std::log(iArg); } );
602  if(info.evaluator.get() != nullptr) {
603  return info;
604  }
605 
606  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
607  k_TMath__Log, [](double iArg)->double { return std::log(iArg); } );
608  if(info.evaluator.get() != nullptr) {
609  return info;
610  }
611 
612  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
613  k_log10, [](double iArg)->double { return std::log(iArg)*kLog10Inv; } );
614  if(info.evaluator.get() != nullptr) {
615  return info;
616  }
617 
618  info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
619  k_exp, [](double iArg)->double { return std::exp(iArg); } );
620  if(info.evaluator.get() != nullptr) {
621  return info;
622  }
623 
624  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
625  k_pow, [](double iArg1, double iArg2)->double { return std::pow(iArg1,iArg2); } );
626  if(info.evaluator.get() != nullptr) {
627  return info;
628  }
629 
630  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
631  k_TMath__Power, [](double iArg1, double iArg2)->double { return std::pow(iArg1,iArg2); } );
632  if(info.evaluator.get() != nullptr) {
633  return info;
634  }
635 
636  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
637  k_max, [](double iArg1, double iArg2)->double { return std::max(iArg1,iArg2); } );
638  if(info.evaluator.get() != nullptr) {
639  return info;
640  }
641 
642  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
643  k_min, [](double iArg1, double iArg2)->double { return std::min(iArg1,iArg2); } );
644  if(info.evaluator.get() != nullptr) {
645  return info;
646  }
647 
648  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
649  k_TMath__Max, [](double iArg1, double iArg2)->double { return std::max(iArg1,iArg2); } );
650  if(info.evaluator.get() != nullptr) {
651  return info;
652  }
653 
654  info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
655  k_TMath__Min, [](double iArg1, double iArg2)->double { return std::min(iArg1,iArg2); } );
656  if(info.evaluator.get() != nullptr) {
657  return info;
658  }
659 
660  return info;
661  };
662 
663  ExpressionFinder const s_expressionFinder;
664 
665 }
666 //
667 // constants, enums and typedefs
668 //
669 
670 //
671 // static data member definitions
672 //
673 
674 //
675 // constructors and destructor
676 //
678 {
679  auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end(),std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
680 
681  if(info.nextParseIndex != static_cast<int>(iFormula.size()) or info.top.get() == nullptr) {
682  throw cms::Exception("FormulaEvaluatorParseError")<<"While parsing '"<<iFormula<<"' could not parse beyond '"<<std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<"'";
683  }
684  m_evaluator = std::move(info.top);
685  m_nVariables = info.maxNumVariables;
686  m_nParameters = info.maxNumParameters;
687 }
688 
689 //
690 // const member functions
691 //
692 double
693 FormulaEvaluator::evaluate(double const* iVariables, double const* iParameters) const
694 {
695  return m_evaluator->evaluate(iVariables, iParameters);
696 }
697 
698 void
700  throw cms::Exception("WrongNumVariables")<<"FormulaEvaluator expected at least "<<m_nVariables<<" but was passed only "<<iSize;
701 }
702 void
704  throw cms::Exception("WrongNumParameters")<<"FormulaEvaluator expected at least "<<m_nParameters<<" but was passed only "<<iSize;
705 }
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