File indexing completed on 2024-09-07 04:35:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <cassert>
0015 #include <functional>
0016 #include <cstdlib>
0017 #include <cmath>
0018 #include "TMath.h"
0019
0020
0021 #if defined(DEBUG_AST)
0022 #include <iostream>
0023 #endif
0024
0025 #include "CommonTools/Utils/interface/FormulaEvaluator.h"
0026 #include "formulaEvaluatorBase.h"
0027 #include "formulaUnaryMinusEvaluator.h"
0028 #include "formulaBinaryOperatorEvaluator.h"
0029 #include "formulaConstantEvaluator.h"
0030 #include "formulaVariableEvaluator.h"
0031 #include "formulaParameterEvaluator.h"
0032 #include "formulaFunctionOneArgEvaluator.h"
0033 #include "formulaFunctionTwoArgsEvaluator.h"
0034 #include "FWCore/Utilities/interface/Exception.h"
0035
0036 using namespace reco;
0037
0038 namespace {
0039
0040 #if defined(DEBUG_AST)
0041 void printAST(formula::EvaluatorBase* e) {
0042 std::cout << "printAST" << std::endl;
0043 for (auto const& n : e->abstractSyntaxTree()) {
0044 std::cout << n << std::endl;
0045 }
0046 }
0047 #define DEBUG_STATE(_v_) std::cout << _v_ << std::endl
0048 #else
0049 inline void printAST(void*) {}
0050 #define DEBUG_STATE(_v_)
0051 #endif
0052
0053 struct EvaluatorInfo {
0054 std::shared_ptr<reco::formula::EvaluatorBase> evaluator;
0055 std::shared_ptr<reco::formula::EvaluatorBase> top;
0056 int nextParseIndex = 0;
0057 unsigned int maxNumVariables = 0;
0058 unsigned int maxNumParameters = 0;
0059 };
0060
0061 class ExpressionElementFinderBase {
0062 public:
0063 virtual bool checkStart(char) const = 0;
0064
0065 virtual EvaluatorInfo createEvaluator(std::string::const_iterator, std::string::const_iterator) const = 0;
0066
0067 virtual ~ExpressionElementFinderBase() = default;
0068 };
0069
0070 std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin,
0071 std::string::const_iterator iEnd) {
0072 if (iBegin == iEnd) {
0073 return iBegin;
0074 }
0075 if (*iBegin != '(') {
0076 return iBegin;
0077 }
0078 int level = 1;
0079 size_t index = 0;
0080 for (auto it = iBegin + 1; it != iEnd; ++it) {
0081 ++index;
0082 if (*it == '(') {
0083 ++level;
0084 } else if (*it == ')') {
0085 --level;
0086 if (level == 0) {
0087 break;
0088 }
0089 }
0090 }
0091 return iBegin + index;
0092 }
0093
0094 class ConstantFinder : public ExpressionElementFinderBase {
0095 bool checkStart(char iSymbol) const final {
0096 if (iSymbol == '-' or iSymbol == '.' or std::isdigit(iSymbol)) {
0097 return true;
0098 }
0099 return false;
0100 }
0101
0102 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
0103 EvaluatorInfo info;
0104 try {
0105 size_t endIndex = 0;
0106 std::string s(iBegin, iEnd);
0107 double value = stod(s, &endIndex);
0108
0109 info.nextParseIndex = endIndex;
0110 info.evaluator = std::make_shared<reco::formula::ConstantEvaluator>(value);
0111 info.top = info.evaluator;
0112 } catch (std::invalid_argument const&) {
0113 }
0114
0115 return info;
0116 }
0117 };
0118
0119 class ParameterFinder : public ExpressionElementFinderBase {
0120 bool checkStart(char iSymbol) const final {
0121 if (iSymbol == '[') {
0122 return true;
0123 }
0124 return false;
0125 }
0126
0127 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
0128 EvaluatorInfo info;
0129 if (iEnd == iBegin) {
0130 return info;
0131 }
0132 if (*iBegin != '[') {
0133 return info;
0134 }
0135 info.nextParseIndex = 1;
0136 try {
0137 size_t endIndex = 0;
0138 std::string s(iBegin + 1, iEnd);
0139 unsigned long value = stoul(s, &endIndex);
0140
0141 if (iBegin + endIndex + 1 == iEnd or *(iBegin + 1 + endIndex) != ']') {
0142 return info;
0143 }
0144
0145 info.nextParseIndex = endIndex + 2;
0146 info.maxNumParameters = value + 1;
0147 info.evaluator = std::make_shared<reco::formula::ParameterEvaluator>(value);
0148 info.top = info.evaluator;
0149 } catch (std::invalid_argument const&) {
0150 }
0151
0152 return info;
0153 }
0154 };
0155
0156 class VariableFinder : public ExpressionElementFinderBase {
0157 bool checkStart(char iSymbol) const final {
0158 if (iSymbol == 'x' or iSymbol == 'y' or iSymbol == 'z' or iSymbol == 't') {
0159 return true;
0160 }
0161 return false;
0162 }
0163
0164 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final {
0165 EvaluatorInfo info;
0166 if (iBegin == iEnd) {
0167 return info;
0168 }
0169 unsigned int index = 4;
0170 switch (*iBegin) {
0171 case 'x': {
0172 index = 0;
0173 break;
0174 }
0175 case 'y': {
0176 index = 1;
0177 break;
0178 }
0179 case 'z': {
0180 index = 2;
0181 break;
0182 }
0183 case 't': {
0184 index = 3;
0185 break;
0186 }
0187 }
0188 if (index == 4) {
0189 return info;
0190 }
0191 info.nextParseIndex = 1;
0192 info.maxNumVariables = index + 1;
0193 info.evaluator = std::make_shared<reco::formula::VariableEvaluator>(index);
0194 info.top = info.evaluator;
0195 return info;
0196 }
0197 };
0198
0199 class ExpressionFinder;
0200
0201 class FunctionFinder : public ExpressionElementFinderBase {
0202 public:
0203 FunctionFinder(ExpressionFinder const* iEF) : m_expressionFinder(iEF) {}
0204
0205 bool checkStart(char iSymbol) const final { return std::isalpha(iSymbol); }
0206
0207 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd) const final;
0208
0209 private:
0210 ExpressionFinder const* m_expressionFinder;
0211 };
0212
0213 EvaluatorInfo createBinaryOperatorEvaluator(ExpressionFinder const&,
0214 std::string::const_iterator iBegin,
0215 std::string::const_iterator iEnd);
0216
0217 class ExpressionFinder {
0218 public:
0219 ExpressionFinder() {
0220 m_elements.reserve(4);
0221 m_elements.emplace_back(new FunctionFinder{this});
0222 m_elements.emplace_back(new ConstantFinder{});
0223 m_elements.emplace_back(new ParameterFinder{});
0224 m_elements.emplace_back(new VariableFinder{});
0225 }
0226
0227 bool checkStart(char iChar) const {
0228 if ('(' == iChar or '-' == iChar or '+' == iChar) {
0229 return true;
0230 }
0231 for (auto const& e : m_elements) {
0232 if (e->checkStart(iChar)) {
0233 return true;
0234 }
0235 }
0236 return false;
0237 }
0238
0239 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin,
0240 std::string::const_iterator iEnd,
0241 std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase> iPreviousBinary) const {
0242 EvaluatorInfo leftEvaluatorInfo;
0243
0244 if (iBegin == iEnd) {
0245 return leftEvaluatorInfo;
0246 }
0247
0248 if (*iBegin == '+' and iEnd - iBegin > 1 and not std::isdigit(*(iBegin + 1))) {
0249 leftEvaluatorInfo = createEvaluator(iBegin + 1, iEnd, iPreviousBinary);
0250
0251
0252 leftEvaluatorInfo.nextParseIndex += 1;
0253 if (nullptr == leftEvaluatorInfo.evaluator.get()) {
0254 return leftEvaluatorInfo;
0255 }
0256 }
0257
0258 else if (*iBegin == '-' and iEnd - iBegin > 1 and not std::isdigit(*(iBegin + 1))) {
0259 leftEvaluatorInfo = createEvaluator(iBegin + 1, iEnd, iPreviousBinary);
0260
0261
0262 leftEvaluatorInfo.nextParseIndex += 1;
0263 if (nullptr == leftEvaluatorInfo.evaluator.get()) {
0264 return leftEvaluatorInfo;
0265 }
0266 leftEvaluatorInfo.evaluator =
0267 std::make_shared<reco::formula::UnaryMinusEvaluator>(std::move(leftEvaluatorInfo.top));
0268 leftEvaluatorInfo.top = leftEvaluatorInfo.evaluator;
0269 }
0270
0271 else if (*iBegin == '(') {
0272 auto endParenthesis = findMatchingParenthesis(iBegin, iEnd);
0273 if (iBegin == endParenthesis) {
0274 return leftEvaluatorInfo;
0275 }
0276 leftEvaluatorInfo =
0277 createEvaluator(iBegin + 1, endParenthesis, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
0278 ++leftEvaluatorInfo.nextParseIndex;
0279 if (leftEvaluatorInfo.evaluator.get() == nullptr) {
0280 return leftEvaluatorInfo;
0281 }
0282
0283 ++leftEvaluatorInfo.nextParseIndex;
0284 leftEvaluatorInfo.top->setPrecedenceToParenthesis();
0285 DEBUG_STATE("close parenthesis");
0286 printAST(leftEvaluatorInfo.top.get());
0287 leftEvaluatorInfo.evaluator = leftEvaluatorInfo.top;
0288 } else {
0289
0290 int maxParseDistance = 0;
0291 for (auto const& e : m_elements) {
0292 if (e->checkStart(*iBegin)) {
0293 leftEvaluatorInfo = e->createEvaluator(iBegin, iEnd);
0294 if (leftEvaluatorInfo.evaluator != nullptr) {
0295 break;
0296 }
0297 if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
0298 maxParseDistance = leftEvaluatorInfo.nextParseIndex;
0299 }
0300 }
0301 }
0302 if (leftEvaluatorInfo.evaluator.get() == nullptr) {
0303
0304 leftEvaluatorInfo.nextParseIndex = maxParseDistance;
0305 return leftEvaluatorInfo;
0306 }
0307 }
0308
0309 if (leftEvaluatorInfo.nextParseIndex == iEnd - iBegin) {
0310 if (iPreviousBinary) {
0311 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.top);
0312 leftEvaluatorInfo.top = iPreviousBinary;
0313 }
0314 DEBUG_STATE("full expression");
0315 printAST(leftEvaluatorInfo.evaluator.get());
0316 return leftEvaluatorInfo;
0317 }
0318
0319
0320 auto fullExpression = createBinaryOperatorEvaluator(*this, iBegin + leftEvaluatorInfo.nextParseIndex, iEnd);
0321 fullExpression.nextParseIndex += leftEvaluatorInfo.nextParseIndex;
0322 fullExpression.maxNumVariables = std::max(leftEvaluatorInfo.maxNumVariables, fullExpression.maxNumVariables);
0323 fullExpression.maxNumParameters = std::max(leftEvaluatorInfo.maxNumParameters, fullExpression.maxNumParameters);
0324 if (iBegin + fullExpression.nextParseIndex != iEnd) {
0325
0326 fullExpression.evaluator.reset();
0327 }
0328
0329 if (fullExpression.evaluator == nullptr) {
0330
0331 return fullExpression;
0332 }
0333
0334 DEBUG_STATE("binary before precedence handling");
0335 printAST(fullExpression.evaluator.get());
0336
0337 auto topNode = fullExpression.top;
0338 auto binaryEval = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(fullExpression.evaluator.get());
0339 if (iPreviousBinary) {
0340 if (iPreviousBinary->precedence() >= fullExpression.evaluator->precedence()) {
0341 DEBUG_STATE("prec >=");
0342 iPreviousBinary->setRightEvaluator(leftEvaluatorInfo.evaluator);
0343 binaryEval->setLeftEvaluator(iPreviousBinary);
0344 } else {
0345 binaryEval->setLeftEvaluator(leftEvaluatorInfo.evaluator);
0346 if (iPreviousBinary->precedence() < topNode->precedence()) {
0347 DEBUG_STATE(" switch topNode");
0348 topNode = iPreviousBinary;
0349 iPreviousBinary->setRightEvaluator(fullExpression.top);
0350 } else {
0351 DEBUG_STATE("swapping");
0352
0353
0354
0355 std::shared_ptr<reco::formula::EvaluatorBase> toSwap = iPreviousBinary;
0356 auto parentBinary = dynamic_cast<reco::formula::BinaryOperatorEvaluatorBase*>(topNode.get());
0357 do {
0358 if (parentBinary->lhs() == binaryEval or
0359 parentBinary->lhs()->precedence() > iPreviousBinary->precedence()) {
0360 parentBinary->swapLeftEvaluator(toSwap);
0361 iPreviousBinary->setRightEvaluator(toSwap);
0362 } else {
0363
0364 parentBinary = const_cast<reco::formula::BinaryOperatorEvaluatorBase*>(
0365 dynamic_cast<const reco::formula::BinaryOperatorEvaluatorBase*>(parentBinary->lhs()));
0366 assert(parentBinary != nullptr);
0367 }
0368 } while (iPreviousBinary->rhs() == nullptr);
0369 }
0370 }
0371 } else {
0372 binaryEval->setLeftEvaluator(leftEvaluatorInfo.top);
0373 }
0374 DEBUG_STATE("finished binary");
0375 printAST(binaryEval);
0376 DEBUG_STATE("present top");
0377 printAST(topNode.get());
0378 fullExpression.top = topNode;
0379 return fullExpression;
0380 }
0381
0382 private:
0383 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
0384 };
0385
0386 template <typename Op>
0387 EvaluatorInfo createBinaryOperatorEvaluatorT(int iSymbolLength,
0388 reco::formula::EvaluatorBase::Precedence iPrec,
0389 ExpressionFinder const& iEF,
0390 std::string::const_iterator iBegin,
0391 std::string::const_iterator iEnd) {
0392 auto op = std::make_shared<reco::formula::BinaryOperatorEvaluator<Op>>(iPrec);
0393 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin + iSymbolLength, iEnd, op);
0394 evalInfo.nextParseIndex += iSymbolLength;
0395
0396 if (evalInfo.evaluator.get() == nullptr) {
0397 return evalInfo;
0398 }
0399
0400 evalInfo.evaluator = op;
0401 return evalInfo;
0402 }
0403
0404 struct power {
0405 double operator()(double iLHS, double iRHS) const { return std::pow(iLHS, iRHS); }
0406 };
0407
0408 EvaluatorInfo createBinaryOperatorEvaluator(ExpressionFinder const& iEF,
0409 std::string::const_iterator iBegin,
0410 std::string::const_iterator iEnd) {
0411 EvaluatorInfo evalInfo;
0412 if (iBegin == iEnd) {
0413 return evalInfo;
0414 }
0415
0416 if (*iBegin == '+') {
0417 return createBinaryOperatorEvaluatorT<std::plus<double>>(
0418 1, reco::formula::EvaluatorBase::Precedence::kPlusMinus, iEF, iBegin, iEnd);
0419 }
0420
0421 else if (*iBegin == '-') {
0422 return createBinaryOperatorEvaluatorT<std::minus<double>>(
0423 1, reco::formula::EvaluatorBase::Precedence::kPlusMinus, iEF, iBegin, iEnd);
0424 } else if (*iBegin == '*') {
0425 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(
0426 1, reco::formula::EvaluatorBase::Precedence::kMultDiv, iEF, iBegin, iEnd);
0427 } else if (*iBegin == '/') {
0428 return createBinaryOperatorEvaluatorT<std::divides<double>>(
0429 1, reco::formula::EvaluatorBase::Precedence::kMultDiv, iEF, iBegin, iEnd);
0430 }
0431
0432 else if (*iBegin == '^') {
0433 return createBinaryOperatorEvaluatorT<power>(
0434 1, reco::formula::EvaluatorBase::Precedence::kPower, iEF, iBegin, iEnd);
0435 } else if (*iBegin == '<' and iBegin + 1 != iEnd and *(iBegin + 1) == '=') {
0436 return createBinaryOperatorEvaluatorT<std::less_equal<double>>(
0437 2, reco::formula::EvaluatorBase::Precedence::kComparison, iEF, iBegin, iEnd);
0438
0439 } else if (*iBegin == '>' and iBegin + 1 != iEnd and *(iBegin + 1) == '=') {
0440 return createBinaryOperatorEvaluatorT<std::greater_equal<double>>(
0441 2, reco::formula::EvaluatorBase::Precedence::kComparison, iEF, iBegin, iEnd);
0442
0443 } else if (*iBegin == '<') {
0444 return createBinaryOperatorEvaluatorT<std::less<double>>(
0445 1, reco::formula::EvaluatorBase::Precedence::kComparison, iEF, iBegin, iEnd);
0446
0447 } else if (*iBegin == '>') {
0448 return createBinaryOperatorEvaluatorT<std::greater<double>>(
0449 1, reco::formula::EvaluatorBase::Precedence::kComparison, iEF, iBegin, iEnd);
0450
0451 } else if (*iBegin == '=' and iBegin + 1 != iEnd and *(iBegin + 1) == '=') {
0452 return createBinaryOperatorEvaluatorT<std::equal_to<double>>(
0453 2, reco::formula::EvaluatorBase::Precedence::kIdentity, iEF, iBegin, iEnd);
0454
0455 } else if (*iBegin == '!' and iBegin + 1 != iEnd and *(iBegin + 1) == '=') {
0456 return createBinaryOperatorEvaluatorT<std::not_equal_to<double>>(
0457 2, reco::formula::EvaluatorBase::Precedence::kIdentity, iEF, iBegin, iEnd);
0458 }
0459 return evalInfo;
0460 }
0461
0462 template <typename Op>
0463 EvaluatorInfo checkForSingleArgFunction(std::string::const_iterator iBegin,
0464 std::string::const_iterator iEnd,
0465 ExpressionFinder const* iExpressionFinder,
0466 const std::string& iName,
0467 Op op) {
0468 EvaluatorInfo info;
0469 if (iName.size() + 2 > static_cast<unsigned int>(iEnd - iBegin)) {
0470 return info;
0471 }
0472 auto pos = iName.find(&(*iBegin), 0, iName.size());
0473
0474 if (std::string::npos == pos or *(iBegin + iName.size()) != '(') {
0475 return info;
0476 }
0477
0478 info.nextParseIndex = iName.size() + 1;
0479
0480 auto itEndParen = findMatchingParenthesis(iBegin + iName.size(), iEnd);
0481 if (iBegin + iName.size() == itEndParen) {
0482 return info;
0483 }
0484
0485 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(
0486 iBegin + iName.size() + 1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
0487 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
0488 if (argEvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex + 1 != 1 + itEndParen - iBegin) {
0489 return info;
0490 }
0491
0492 ++info.nextParseIndex;
0493
0494 info.evaluator = std::make_shared<reco::formula::FunctionOneArgEvaluator>(std::move(argEvaluatorInfo.top), op);
0495 info.top = info.evaluator;
0496 return info;
0497 }
0498
0499 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
0500 std::string::const_iterator iEnd) {
0501 int level = 0;
0502 std::string::const_iterator it = iBegin;
0503 for (; it != iEnd; ++it) {
0504 if (*it == '(') {
0505 ++level;
0506 } else if (*it == ')') {
0507 --level;
0508 } else if (*it == ',' and level == 0) {
0509 return it;
0510 }
0511 }
0512
0513 return it;
0514 }
0515
0516 template <typename Op>
0517 EvaluatorInfo checkForTwoArgsFunction(std::string::const_iterator iBegin,
0518 std::string::const_iterator iEnd,
0519 ExpressionFinder const* iExpressionFinder,
0520 const std::string& iName,
0521 Op op) {
0522 EvaluatorInfo info;
0523 if (iName.size() + 2 > static_cast<unsigned int>(iEnd - iBegin)) {
0524 return info;
0525 }
0526 auto pos = iName.find(&(*iBegin), 0, iName.size());
0527
0528 if (std::string::npos == pos or *(iBegin + iName.size()) != '(') {
0529 return info;
0530 }
0531
0532 info.nextParseIndex = iName.size() + 1;
0533
0534 auto itEndParen = findMatchingParenthesis(iBegin + iName.size(), iEnd);
0535 if (iBegin + iName.size() == itEndParen) {
0536 return info;
0537 }
0538
0539 auto itComma = findCommaNotInParenthesis(iBegin + iName.size() + 1, itEndParen);
0540
0541 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(
0542 iBegin + iName.size() + 1, itComma, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
0543 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
0544 if (arg1EvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex != itComma - iBegin) {
0545 return info;
0546 }
0547
0548 ++info.nextParseIndex;
0549
0550 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(
0551 itComma + 1, itEndParen, std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
0552 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
0553
0554 if (arg2EvaluatorInfo.evaluator.get() == nullptr or info.nextParseIndex + 1 != 1 + itEndParen - iBegin) {
0555 return info;
0556 }
0557
0558 ++info.nextParseIndex;
0559
0560 info.evaluator = std::make_shared<reco::formula::FunctionTwoArgsEvaluator>(
0561 std::move(arg1EvaluatorInfo.top), std::move(arg2EvaluatorInfo.top), op);
0562 info.top = info.evaluator;
0563 return info;
0564 }
0565
0566 const std::string k_log("log");
0567 const std::string k_log10("log10");
0568 const std::string k_TMath__Log("TMath::Log");
0569 double const kLog10Inv = 1. / std::log(10.);
0570 const std::string k_exp("exp");
0571 const std::string k_pow("pow");
0572 const std::string k_TMath__Power("TMath::Power");
0573 const std::string k_max("max");
0574 const std::string k_min("min");
0575 const std::string k_TMath__Max("TMath::Max");
0576 const std::string k_TMath__Min("TMath::Min");
0577 const std::string k_TMath__Erf("TMath::Erf");
0578 const std::string k_erf("erf");
0579 const std::string k_TMath__Landau("TMath::Landau");
0580 const std::string k_sqrt("sqrt");
0581 const std::string k_TMath__Sqrt("TMath::Sqrt");
0582 const std::string k_abs("abs");
0583 const std::string k_TMath__Abs("TMath::Abs");
0584 const std::string k_cos("cos");
0585 const std::string k_TMath__Cos("TMath::Cos");
0586 const std::string k_sin("sin");
0587 const std::string k_TMath__Sin("TMath::Sin");
0588 const std::string k_tan("tan");
0589 const std::string k_TMath__Tan("TMath::Tan");
0590 const std::string k_acos("acos");
0591 const std::string k_TMath__ACos("TMath::ACos");
0592 const std::string k_asin("asin");
0593 const std::string k_TMath__ASin("TMath::ASin");
0594 const std::string k_atan("atan");
0595 const std::string k_TMath__ATan("TMath::ATan");
0596 const std::string k_atan2("atan2");
0597 const std::string k_TMath__ATan2("TMath::ATan2");
0598 const std::string k_cosh("cosh");
0599 const std::string k_TMath__CosH("TMath::CosH");
0600 const std::string k_sinh("sinh");
0601 const std::string k_TMath__SinH("TMath::SinH");
0602 const std::string k_tanh("tanh");
0603 const std::string k_TMath__TanH("TMath::TanH");
0604 const std::string k_acosh("acosh");
0605 const std::string k_TMath__ACosH("TMath::ACosH");
0606 const std::string k_asinh("asinh");
0607 const std::string k_TMath__ASinH("TMath::ASinH");
0608 const std::string k_atanh("atanh");
0609 const std::string k_TMath__ATanH("TMath::ATanH");
0610
0611 EvaluatorInfo FunctionFinder::createEvaluator(std::string::const_iterator iBegin,
0612 std::string::const_iterator iEnd) const {
0613 EvaluatorInfo info;
0614
0615 info = checkForSingleArgFunction(
0616 iBegin, iEnd, m_expressionFinder, k_erf, [](double iArg) -> double { return std::erf(iArg); });
0617 if (info.evaluator.get() != nullptr) {
0618 return info;
0619 }
0620
0621 info = checkForSingleArgFunction(
0622 iBegin, iEnd, m_expressionFinder, k_TMath__Erf, [](double iArg) -> double { return std::erf(iArg); });
0623 if (info.evaluator.get() != nullptr) {
0624 return info;
0625 }
0626
0627 info = checkForSingleArgFunction(
0628 iBegin, iEnd, m_expressionFinder, k_TMath__Landau, [](double iArg) -> double { return TMath::Landau(iArg); });
0629 if (info.evaluator.get() != nullptr) {
0630 return info;
0631 }
0632
0633 info = checkForSingleArgFunction(
0634 iBegin, iEnd, m_expressionFinder, k_log, [](double iArg) -> double { return std::log(iArg); });
0635 if (info.evaluator.get() != nullptr) {
0636 return info;
0637 }
0638
0639 info = checkForSingleArgFunction(
0640 iBegin, iEnd, m_expressionFinder, k_TMath__Log, [](double iArg) -> double { return std::log(iArg); });
0641 if (info.evaluator.get() != nullptr) {
0642 return info;
0643 }
0644
0645 info = checkForSingleArgFunction(
0646 iBegin, iEnd, m_expressionFinder, k_log10, [](double iArg) -> double { return std::log(iArg) * kLog10Inv; });
0647 if (info.evaluator.get() != nullptr) {
0648 return info;
0649 }
0650
0651 info = checkForSingleArgFunction(
0652 iBegin, iEnd, m_expressionFinder, k_exp, [](double iArg) -> double { return std::exp(iArg); });
0653 if (info.evaluator.get() != nullptr) {
0654 return info;
0655 }
0656
0657 info = checkForSingleArgFunction(
0658 iBegin, iEnd, m_expressionFinder, k_sqrt, [](double iArg) -> double { return std::sqrt(iArg); });
0659 if (info.evaluator.get() != nullptr) {
0660 return info;
0661 }
0662
0663 info = checkForSingleArgFunction(
0664 iBegin, iEnd, m_expressionFinder, k_TMath__Sqrt, [](double iArg) -> double { return std::sqrt(iArg); });
0665 if (info.evaluator.get() != nullptr) {
0666 return info;
0667 }
0668
0669 info = checkForSingleArgFunction(
0670 iBegin, iEnd, m_expressionFinder, k_abs, [](double iArg) -> double { return std::abs(iArg); });
0671 if (info.evaluator.get() != nullptr) {
0672 return info;
0673 }
0674
0675 info = checkForSingleArgFunction(
0676 iBegin, iEnd, m_expressionFinder, k_TMath__Abs, [](double iArg) -> double { return std::abs(iArg); });
0677 if (info.evaluator.get() != nullptr) {
0678 return info;
0679 }
0680
0681 info = checkForSingleArgFunction(
0682 iBegin, iEnd, m_expressionFinder, k_cos, [](double iArg) -> double { return std::cos(iArg); });
0683 if (info.evaluator.get() != nullptr) {
0684 return info;
0685 }
0686
0687 info = checkForSingleArgFunction(
0688 iBegin, iEnd, m_expressionFinder, k_TMath__Cos, [](double iArg) -> double { return std::cos(iArg); });
0689 if (info.evaluator.get() != nullptr) {
0690 return info;
0691 }
0692
0693 info = checkForSingleArgFunction(
0694 iBegin, iEnd, m_expressionFinder, k_sin, [](double iArg) -> double { return std::sin(iArg); });
0695 if (info.evaluator.get() != nullptr) {
0696 return info;
0697 }
0698
0699 info = checkForSingleArgFunction(
0700 iBegin, iEnd, m_expressionFinder, k_TMath__Sin, [](double iArg) -> double { return std::sin(iArg); });
0701 if (info.evaluator.get() != nullptr) {
0702 return info;
0703 }
0704
0705 info = checkForSingleArgFunction(
0706 iBegin, iEnd, m_expressionFinder, k_tan, [](double iArg) -> double { return std::tan(iArg); });
0707 if (info.evaluator.get() != nullptr) {
0708 return info;
0709 }
0710
0711 info = checkForSingleArgFunction(
0712 iBegin, iEnd, m_expressionFinder, k_TMath__Tan, [](double iArg) -> double { return std::tan(iArg); });
0713 if (info.evaluator.get() != nullptr) {
0714 return info;
0715 }
0716
0717 info = checkForSingleArgFunction(
0718 iBegin, iEnd, m_expressionFinder, k_acos, [](double iArg) -> double { return std::acos(iArg); });
0719 if (info.evaluator.get() != nullptr) {
0720 return info;
0721 }
0722
0723 info = checkForSingleArgFunction(
0724 iBegin, iEnd, m_expressionFinder, k_TMath__ACos, [](double iArg) -> double { return std::acos(iArg); });
0725 if (info.evaluator.get() != nullptr) {
0726 return info;
0727 }
0728
0729 info = checkForSingleArgFunction(
0730 iBegin, iEnd, m_expressionFinder, k_asin, [](double iArg) -> double { return std::asin(iArg); });
0731 if (info.evaluator.get() != nullptr) {
0732 return info;
0733 }
0734
0735 info = checkForSingleArgFunction(
0736 iBegin, iEnd, m_expressionFinder, k_TMath__ASin, [](double iArg) -> double { return std::asin(iArg); });
0737 if (info.evaluator.get() != nullptr) {
0738 return info;
0739 }
0740
0741 info = checkForSingleArgFunction(
0742 iBegin, iEnd, m_expressionFinder, k_atan, [](double iArg) -> double { return std::atan(iArg); });
0743 if (info.evaluator.get() != nullptr) {
0744 return info;
0745 }
0746
0747 info = checkForSingleArgFunction(
0748 iBegin, iEnd, m_expressionFinder, k_TMath__ATan, [](double iArg) -> double { return std::atan(iArg); });
0749 if (info.evaluator.get() != nullptr) {
0750 return info;
0751 }
0752
0753 info = checkForSingleArgFunction(
0754 iBegin, iEnd, m_expressionFinder, k_cosh, [](double iArg) -> double { return std::cosh(iArg); });
0755 if (info.evaluator.get() != nullptr) {
0756 return info;
0757 }
0758
0759 info = checkForSingleArgFunction(
0760 iBegin, iEnd, m_expressionFinder, k_TMath__CosH, [](double iArg) -> double { return std::cosh(iArg); });
0761 if (info.evaluator.get() != nullptr) {
0762 return info;
0763 }
0764
0765 info = checkForSingleArgFunction(
0766 iBegin, iEnd, m_expressionFinder, k_sinh, [](double iArg) -> double { return std::sinh(iArg); });
0767 if (info.evaluator.get() != nullptr) {
0768 return info;
0769 }
0770
0771 info = checkForSingleArgFunction(
0772 iBegin, iEnd, m_expressionFinder, k_TMath__SinH, [](double iArg) -> double { return std::sinh(iArg); });
0773 if (info.evaluator.get() != nullptr) {
0774 return info;
0775 }
0776
0777 info = checkForSingleArgFunction(
0778 iBegin, iEnd, m_expressionFinder, k_tanh, [](double iArg) -> double { return std::tanh(iArg); });
0779 if (info.evaluator.get() != nullptr) {
0780 return info;
0781 }
0782
0783 info = checkForSingleArgFunction(
0784 iBegin, iEnd, m_expressionFinder, k_TMath__TanH, [](double iArg) -> double { return std::tanh(iArg); });
0785 if (info.evaluator.get() != nullptr) {
0786 return info;
0787 }
0788
0789 info = checkForSingleArgFunction(
0790 iBegin, iEnd, m_expressionFinder, k_acosh, [](double iArg) -> double { return std::acosh(iArg); });
0791 if (info.evaluator.get() != nullptr) {
0792 return info;
0793 }
0794
0795 info = checkForSingleArgFunction(
0796 iBegin, iEnd, m_expressionFinder, k_TMath__ACosH, [](double iArg) -> double { return std::acosh(iArg); });
0797 if (info.evaluator.get() != nullptr) {
0798 return info;
0799 }
0800
0801 info = checkForSingleArgFunction(
0802 iBegin, iEnd, m_expressionFinder, k_asinh, [](double iArg) -> double { return std::asinh(iArg); });
0803 if (info.evaluator.get() != nullptr) {
0804 return info;
0805 }
0806
0807 info = checkForSingleArgFunction(
0808 iBegin, iEnd, m_expressionFinder, k_TMath__ASinH, [](double iArg) -> double { return std::asinh(iArg); });
0809 if (info.evaluator.get() != nullptr) {
0810 return info;
0811 }
0812
0813 info = checkForSingleArgFunction(
0814 iBegin, iEnd, m_expressionFinder, k_atanh, [](double iArg) -> double { return std::atanh(iArg); });
0815 if (info.evaluator.get() != nullptr) {
0816 return info;
0817 }
0818
0819 info = checkForSingleArgFunction(
0820 iBegin, iEnd, m_expressionFinder, k_TMath__ATanH, [](double iArg) -> double { return std::atanh(iArg); });
0821 if (info.evaluator.get() != nullptr) {
0822 return info;
0823 }
0824
0825 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder, k_atan2, [](double iArg1, double iArg2) -> double {
0826 return std::atan2(iArg1, iArg2);
0827 });
0828 if (info.evaluator.get() != nullptr) {
0829 return info;
0830 }
0831
0832 info = checkForTwoArgsFunction(
0833 iBegin, iEnd, m_expressionFinder, k_TMath__ATan2, [](double iArg1, double iArg2) -> double {
0834 return std::atan2(iArg1, iArg2);
0835 });
0836 if (info.evaluator.get() != nullptr) {
0837 return info;
0838 }
0839
0840 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder, k_pow, [](double iArg1, double iArg2) -> double {
0841 return std::pow(iArg1, iArg2);
0842 });
0843 if (info.evaluator.get() != nullptr) {
0844 return info;
0845 }
0846
0847 info = checkForTwoArgsFunction(
0848 iBegin, iEnd, m_expressionFinder, k_TMath__Power, [](double iArg1, double iArg2) -> double {
0849 return std::pow(iArg1, iArg2);
0850 });
0851 if (info.evaluator.get() != nullptr) {
0852 return info;
0853 }
0854
0855 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder, k_max, [](double iArg1, double iArg2) -> double {
0856 return std::max(iArg1, iArg2);
0857 });
0858 if (info.evaluator.get() != nullptr) {
0859 return info;
0860 }
0861
0862 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder, k_min, [](double iArg1, double iArg2) -> double {
0863 return std::min(iArg1, iArg2);
0864 });
0865 if (info.evaluator.get() != nullptr) {
0866 return info;
0867 }
0868
0869 info = checkForTwoArgsFunction(
0870 iBegin, iEnd, m_expressionFinder, k_TMath__Max, [](double iArg1, double iArg2) -> double {
0871 return std::max(iArg1, iArg2);
0872 });
0873 if (info.evaluator.get() != nullptr) {
0874 return info;
0875 }
0876
0877 info = checkForTwoArgsFunction(
0878 iBegin, iEnd, m_expressionFinder, k_TMath__Min, [](double iArg1, double iArg2) -> double {
0879 return std::min(iArg1, iArg2);
0880 });
0881 if (info.evaluator.get() != nullptr) {
0882 return info;
0883 }
0884
0885 return info;
0886 };
0887
0888 ExpressionFinder const s_expressionFinder;
0889
0890 }
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902 FormulaEvaluator::FormulaEvaluator(std::string const& iFormula) {
0903
0904 std::string formula;
0905 formula.reserve(iFormula.size());
0906 std::copy_if(iFormula.begin(), iFormula.end(), std::back_inserter(formula), [](const char iC) { return iC != ' '; });
0907
0908 auto info = s_expressionFinder.createEvaluator(
0909 formula.begin(), formula.end(), std::shared_ptr<reco::formula::BinaryOperatorEvaluatorBase>());
0910
0911 if (info.nextParseIndex != static_cast<int>(formula.size()) or info.top.get() == nullptr) {
0912 auto lastIndex = info.nextParseIndex;
0913 if (formula.size() != iFormula.size()) {
0914 lastIndex = 0;
0915 for (decltype(info.nextParseIndex) index = 0; index < info.nextParseIndex; ++index, ++lastIndex) {
0916 while (iFormula[lastIndex] != formula[index]) {
0917 assert(iFormula[lastIndex] == ' ');
0918 ++lastIndex;
0919 }
0920 }
0921 }
0922 throw cms::Exception("FormulaEvaluatorParseError")
0923 << "While parsing '" << iFormula << "' could not parse beyond '"
0924 << std::string(iFormula.begin(), iFormula.begin() + lastIndex) << "'";
0925 }
0926
0927 DEBUG_STATE("DONE parsing");
0928 printAST(info.top.get());
0929
0930 m_evaluator = std::move(info.top);
0931 m_nVariables = info.maxNumVariables;
0932 m_nParameters = info.maxNumParameters;
0933 }
0934
0935
0936
0937
0938 double FormulaEvaluator::evaluate(double const* iVariables, double const* iParameters) const {
0939 return m_evaluator->evaluate(iVariables, iParameters);
0940 }
0941
0942 void FormulaEvaluator::throwWrongNumberOfVariables(size_t iSize) const {
0943 throw cms::Exception("WrongNumVariables")
0944 << "FormulaEvaluator expected at least " << m_nVariables << " but was passed only " << iSize;
0945 }
0946 void FormulaEvaluator::throwWrongNumberOfParameters(size_t iSize) const {
0947 throw cms::Exception("WrongNumParameters")
0948 << "FormulaEvaluator expected at least " << m_nParameters << " but was passed only " << iSize;
0949 }
0950
0951 std::vector<std::string> FormulaEvaluator::abstractSyntaxTree() const { return m_evaluator->abstractSyntaxTree(); }