35 struct EvaluatorInfo {
36 std::unique_ptr<reco::formula::EvaluatorBase> evaluator;
38 unsigned int maxNumVariables=0;
39 unsigned int maxNumParameters=0;
42 class ExpressionElementFinderBase {
44 virtual bool checkStart(
char)
const = 0;
46 virtual EvaluatorInfo createEvaluator(std::string::const_iterator, std::string::const_iterator)
const = 0;
49 std::string::const_iterator findMatchingParenthesis(std::string::const_iterator iBegin, std::string::const_iterator iEnd) {
58 for(
auto it = iBegin+1; it != iEnd; ++it) {
62 }
else if (*it ==
')') {
69 return iBegin +
index;
72 class ConstantFinder :
public ExpressionElementFinderBase {
73 virtual bool checkStart(
char iSymbol)
const override final {
74 if( iSymbol ==
'-' or iSymbol ==
'.' or std::isdigit(iSymbol) ) {
80 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final {
85 double value = stod(
s, &endIndex);
87 info.nextParseIndex = endIndex;
89 }
catch ( std::invalid_argument ) {}
97 class ParameterFinder :
public ExpressionElementFinderBase {
98 virtual bool checkStart(
char iSymbol)
const override final {
105 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final {
113 info.nextParseIndex = 1;
117 unsigned long value = stoul(
s, &endIndex);
119 if( iBegin+endIndex+1 == iEnd
or *(iBegin+1+endIndex) !=
']' ) {
124 info.nextParseIndex = endIndex+2;
125 info.maxNumParameters =
value;
127 }
catch ( std::invalid_argument ) {}
134 class VariableFinder :
public ExpressionElementFinderBase {
135 virtual bool checkStart(
char iSymbol)
const override final {
136 if( iSymbol ==
'x' or iSymbol ==
'y' or iSymbol ==
'z' or iSymbol ==
't' ) {
142 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final {
147 unsigned int index = 4;
161 info.nextParseIndex = 1;
162 info.maxNumVariables = index+1;
168 class ExpressionFinder;
170 class FunctionFinder :
public ExpressionElementFinderBase {
172 FunctionFinder(ExpressionFinder
const* iEF):
173 m_expressionFinder(iEF) {};
175 virtual bool checkStart(
char iSymbol)
const override final {
176 return std::isalpha(iSymbol);
179 virtual EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const override final;
182 ExpressionFinder
const* m_expressionFinder;
186 EvaluatorInfo createBinaryOperatorEvaluator( ExpressionFinder
const&,
187 std::unique_ptr<reco::formula::EvaluatorBase> iLHS,
188 std::string::const_iterator iBegin,
189 std::string::const_iterator iEnd) ;
191 class ExpressionFinder {
195 m_elements.reserve(4);
196 m_elements.emplace_back(
new FunctionFinder{
this});
197 m_elements.emplace_back(
new ConstantFinder{});
198 m_elements.emplace_back(
new ParameterFinder{});
199 m_elements.emplace_back(
new VariableFinder{});
202 bool checkStart(
char iChar)
const {
203 if (
'(' == iChar
or '-' == iChar
or '+' ==iChar) {
206 for(
auto const&
e : m_elements) {
207 if (
e->checkStart(iChar) ) {
214 EvaluatorInfo createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
215 EvaluatorInfo leftEvaluatorInfo ;
216 if( iBegin == iEnd) {
217 return leftEvaluatorInfo;
220 if (*iBegin ==
'+' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
221 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd);
224 leftEvaluatorInfo.nextParseIndex +=1;
225 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
226 return leftEvaluatorInfo;
228 if( leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
229 return leftEvaluatorInfo;
233 else if (*iBegin ==
'-' and iEnd -iBegin > 1 and not std::isdigit( *(iBegin+1) ) ) {
234 leftEvaluatorInfo = createEvaluator(iBegin+1, iEnd);
237 leftEvaluatorInfo.nextParseIndex +=1;
238 if(
nullptr == leftEvaluatorInfo.evaluator.get() ) {
239 return leftEvaluatorInfo;
242 if( leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
243 return leftEvaluatorInfo;
247 else if( *iBegin ==
'(') {
248 auto endParenthesis = findMatchingParenthesis(iBegin,iEnd);
249 if(iBegin== endParenthesis) {
250 return leftEvaluatorInfo;
252 leftEvaluatorInfo = createEvaluator(iBegin+1,endParenthesis);
253 ++leftEvaluatorInfo.nextParseIndex;
254 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
255 return leftEvaluatorInfo;
258 ++leftEvaluatorInfo.nextParseIndex;
259 leftEvaluatorInfo.evaluator->setPrecidenceToParenthesis();
260 if( iBegin+leftEvaluatorInfo.nextParseIndex == iEnd) {
261 return leftEvaluatorInfo;
265 int maxParseDistance = 0;
266 for(
auto const&
e: m_elements) {
267 if(
e->checkStart(*iBegin) ) {
268 leftEvaluatorInfo =
e->createEvaluator(iBegin,iEnd);
269 if(leftEvaluatorInfo.evaluator !=
nullptr) {
272 if (leftEvaluatorInfo.nextParseIndex > maxParseDistance) {
273 maxParseDistance = leftEvaluatorInfo.nextParseIndex;
277 if(leftEvaluatorInfo.evaluator.get() ==
nullptr) {
279 leftEvaluatorInfo.nextParseIndex = maxParseDistance;
280 return leftEvaluatorInfo;
284 if(leftEvaluatorInfo.nextParseIndex == iEnd-iBegin) {
285 return leftEvaluatorInfo;
289 auto fullExpression = createBinaryOperatorEvaluator(*
this,
std::move(leftEvaluatorInfo.evaluator), iBegin+leftEvaluatorInfo.nextParseIndex, iEnd);
290 fullExpression.nextParseIndex +=leftEvaluatorInfo.nextParseIndex;
291 fullExpression.maxNumVariables =
std::max(leftEvaluatorInfo.maxNumVariables, fullExpression.maxNumVariables);
292 fullExpression.maxNumParameters =
std::max(leftEvaluatorInfo.maxNumParameters, fullExpression.maxNumParameters);
293 if (iBegin + fullExpression.nextParseIndex != iEnd) {
295 fullExpression.evaluator.release();
297 return fullExpression;
301 std::vector<std::unique_ptr<ExpressionElementFinderBase>> m_elements;
305 template<
typename Op>
306 EvaluatorInfo createBinaryOperatorEvaluatorT(
int iSymbolLength,
308 ExpressionFinder
const& iEF,
309 std::unique_ptr<reco::formula::EvaluatorBase> iLHS,
310 std::string::const_iterator iBegin,
311 std::string::const_iterator iEnd) {
312 EvaluatorInfo evalInfo = iEF.createEvaluator(iBegin+iSymbolLength,iEnd);
313 evalInfo.nextParseIndex += iSymbolLength;
315 if(evalInfo.evaluator.get() ==
nullptr) {
319 if( static_cast<unsigned int>(iPrec) >= evalInfo.evaluator->precidence() ) {
322 std::unique_ptr<reco::formula::EvaluatorBase>
temp;
323 b->swapLeftEvaluator(temp);
325 b->swapLeftEvaluator(op);
329 evalInfo.evaluator.swap(op);
335 double operator()(
double iLHS,
double iRHS)
const {
342 createBinaryOperatorEvaluator( ExpressionFinder
const& iEF,
343 std::unique_ptr<reco::formula::EvaluatorBase> iLHS,
344 std::string::const_iterator iBegin,
345 std::string::const_iterator iEnd) {
346 EvaluatorInfo evalInfo;
352 return createBinaryOperatorEvaluatorT<std::plus<double>>(1,
360 else if(*iBegin ==
'-') {
361 return createBinaryOperatorEvaluatorT<std::minus<double>>(1,
368 else if(*iBegin ==
'*') {
369 return createBinaryOperatorEvaluatorT<std::multiplies<double>>(1,
376 else if(*iBegin ==
'/') {
377 return createBinaryOperatorEvaluatorT<std::divides<double>>(1,
385 else if(*iBegin ==
'^') {
386 return createBinaryOperatorEvaluatorT<power>(1,
398 template<
typename Op>
400 checkForSingleArgFunction(std::string::const_iterator iBegin,
401 std::string::const_iterator iEnd,
402 ExpressionFinder
const* iExpressionFinder,
406 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
409 auto pos = iName.find(&(*iBegin), 0,iName.size());
411 if(std::string::npos == pos
or *(iBegin+iName.size()) !=
'(') {
415 info.nextParseIndex = iName.size()+1;
417 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
418 if(iBegin+iName.size() == itEndParen) {
422 auto argEvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itEndParen);
423 info.nextParseIndex += argEvaluatorInfo.nextParseIndex;
424 if(argEvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
428 ++info.nextParseIndex;
435 std::string::const_iterator findCommaNotInParenthesis(std::string::const_iterator iBegin,
436 std::string::const_iterator iEnd ) {
438 std::string::const_iterator it = iBegin;
439 for(; it != iEnd; ++it) {
442 }
else if(*it ==
')') {
445 else if( *it ==
',' and level == 0 ) {
454 template<
typename Op>
456 checkForTwoArgsFunction(std::string::const_iterator iBegin,
457 std::string::const_iterator iEnd,
458 ExpressionFinder
const* iExpressionFinder,
462 if(iName.size()+2 >
static_cast<unsigned int>(iEnd-iBegin) ) {
465 auto pos = iName.find(&(*iBegin), 0,iName.size());
467 if(std::string::npos == pos
or *(iBegin+iName.size()) !=
'(') {
471 info.nextParseIndex = iName.size()+1;
473 auto itEndParen = findMatchingParenthesis(iBegin+iName.size(),iEnd);
474 if(iBegin+iName.size() == itEndParen) {
478 auto itComma = findCommaNotInParenthesis(iBegin+iName.size()+1, itEndParen);
480 auto arg1EvaluatorInfo = iExpressionFinder->createEvaluator(iBegin+iName.size()+1, itComma);
481 info.nextParseIndex += arg1EvaluatorInfo.nextParseIndex;
482 if(arg1EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex != itComma-iBegin ) {
486 ++info.nextParseIndex;
488 auto arg2EvaluatorInfo = iExpressionFinder->createEvaluator(itComma+1, itEndParen);
489 info.nextParseIndex += arg2EvaluatorInfo.nextParseIndex;
491 if(arg2EvaluatorInfo.evaluator.get() ==
nullptr or info.nextParseIndex+1 != 1+itEndParen - iBegin) {
495 ++info.nextParseIndex;
505 static const std::string k_TMath__Log(
"TMath::Log");
506 double const kLog10Inv = 1./
std::log(10.);
512 FunctionFinder::createEvaluator(std::string::const_iterator iBegin, std::string::const_iterator iEnd)
const {
515 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
516 k_log, [](
double iArg)->
double {
return std::log(iArg); } );
517 if(info.evaluator.get() !=
nullptr) {
521 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
522 k_TMath__Log, [](
double iArg)->
double {
return std::log(iArg); } );
523 if(info.evaluator.get() !=
nullptr) {
527 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
528 k_log10, [](
double iArg)->
double {
return std::log(iArg)*kLog10Inv; } );
529 if(info.evaluator.get() !=
nullptr) {
533 info = checkForSingleArgFunction(iBegin, iEnd, m_expressionFinder,
534 k_exp, [](
double iArg)->
double {
return std::exp(iArg); } );
535 if(info.evaluator.get() !=
nullptr) {
539 info = checkForTwoArgsFunction(iBegin, iEnd, m_expressionFinder,
540 k_max, [](
double iArg1,
double iArg2)->
double {
return std::max(iArg1,iArg2); } );
541 if(info.evaluator.get() !=
nullptr) {
548 static ExpressionFinder
const s_expressionFinder;
564 auto info = s_expressionFinder.createEvaluator(iFormula.begin(), iFormula.end());
566 if(info.nextParseIndex != static_cast<int>(iFormula.size())
or info.evaluator.get() ==
nullptr) {
567 throw cms::Exception(
"FormulaEvaluatorParseError")<<
"While parsing '"<<iFormula<<
"' could not parse beyond '"<<
std::string(iFormula.begin(),iFormula.begin()+info.nextParseIndex) <<
"'";
580 return m_evaluator->evaluate(iVariables, iParameters);
585 throw cms::Exception(
"WrongNumVariables")<<
"FormulaEvaluator expected at least "<<
m_nVariables<<
" but was passed only "<<iSize;
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
Power< A, B >::type pow(const A &a, const B &b)