12 #if __cplusplus >= 201103L
13 #define ROOT_CPLUSPLUS11 1
28 #include <unordered_map>
42 #pragma optimize("",off)
145 static const
TString gNamePrefix = "TFormula__";
149 static std::unordered_map<std::
string,
void *>
gClingFunctions = std::unordered_map<std::
string,
void * >();
154 char ops[] = {
'+',
'^',
'-',
'/',
'*',
'<',
'>',
'|',
'&',
'!',
'=',
'?'};
155 Int_t opsLen =
sizeof(ops)/
sizeof(
char);
156 for(
Int_t i = 0; i < opsLen; ++i)
164 char brackets[] = {
')',
'(',
'{',
'}'};
165 Int_t bracketsLen =
sizeof(brackets)/
sizeof(
char);
166 for(
Int_t i = 0; i < bracketsLen; ++i)
174 return !IsBracket(c) && !IsOperator(c) && c !=
',' && c !=
' ';
179 return name ==
"x" || name ==
"z" || name ==
"y" || name ==
"t";
186 if ( (formula[i] ==
'e' || formula[i] ==
'E') && (i > 0 && i < formula.
Length()-1) ) {
188 if ( (isdigit(formula[i-1]) || formula[i-1] ==
'.') && ( isdigit(formula[i+1]) || formula[i+1] ==
'+' || formula[i+1] ==
'-' ) )
197 if ( (formula[i] ==
'x' || formula[i] ==
'X') && (i > 0 && i < formula.
Length()-1) && formula[i-1] ==
'0') {
198 if (isdigit(formula[i+1]) )
200 static char hex_values[12] = {
'a',
'A',
'b',
'B',
'c',
'C',
'd',
'D',
'e',
'E',
'f',
'F'};
201 for (
int jjj = 0; jjj < 12; ++jjj) {
202 if (formula[i+1] == hex_values[jjj])
220 if ( a[0] ==
'p' && a.
Length() > 1) {
221 if ( b[0] ==
'p' && b.
Length() > 1) {
225 if (lhs.
IsDigit() && rhs.IsDigit() )
226 return (lhs.
Atoi() < rhs.Atoi() );
233 if ( b[0] ==
'p' && b.
Length() > 1)
251 fReadyToExecute =
false;
252 fClingInitialized =
false;
253 fAllParametersSetted =
false;
265 if (strlen(name)!=1)
return false;
266 for (
auto const & specialName : {
"x",
"y",
"z",
"t"}){
267 if (strcmp(name,specialName)==0)
return true;
280 gROOT->GetListOfFunctions()->Remove(
this);
287 int nLinParts = fLinearParts.size();
289 for (
int i = 0; i < nLinParts; ++i)
delete fLinearParts[i];
304 fReadyToExecute =
false;
305 fClingInitialized =
false;
306 fAllParametersSetted =
false;
313 for(
Int_t i = 0; i < nparams; ++i)
316 DoAddParameter(parName,0,
false);
323 fClingInput(formula),fFormula(formula)
325 fReadyToExecute =
false;
326 fClingInitialized =
false;
334 if (addToGlobList &&
gROOT) {
337 old =
dynamic_cast<TFormula*
> (
gROOT->GetListOfFunctions()->FindObject(name) );
339 gROOT->GetListOfFunctions()->Remove(old);
341 Error(
"TFormula",
"The name %s is reserved as a TFormula variable name.\n",name);
343 gROOT->GetListOfFunctions()->Add(
this);
350 if (!fFormula.IsNull() ) {
351 PreProcessFormula(fFormula);
353 PrepareFormula(fFormula);
359 TFormula::TFormula(
const char *name,
const char *formula,
int ndim,
int npar,
bool addToGlobList) :
361 fClingInput(formula),fFormula(formula)
363 fReadyToExecute =
false;
364 fClingInitialized =
false;
368 for (
int i = 0; i < npar; ++i) {
371 fAllParametersSetted =
true;
374 bool ret = InitLambdaExpression(formula);
380 fReadyToExecute =
true;
382 if (addToGlobList &&
gROOT) {
385 old =
dynamic_cast<TFormula*
> (
gROOT->GetListOfFunctions()->FindObject(name) );
387 gROOT->GetListOfFunctions()->Remove(old);
389 Error(
"TFormula",
"The name %s is reserved as a TFormula variable name.\n",name);
391 gROOT->GetListOfFunctions()->Add(
this);
396 Error(
"TFormula",
"Syntax error in building the lambda expression %s", formula );
403 fReadyToExecute =
false;
404 fClingInitialized =
false;
418 gROOT->GetListOfFunctions()->Remove(old);
421 Error(
"TFormula",
"The name %s is reserved as a TFormula variable name.\n",formula.
GetName());
423 gROOT->GetListOfFunctions()->Add(
this);
426 PreProcessFormula(fFormula);
427 PrepareFormula(fFormula);
444 std::string lambdaExpression = formula;
452 fLambdaPtr = funcit->second;
453 fClingInitialized =
true;
464 TString lineExpr =
TString::Format(
"std::function<double(double*,double*)> %s = %s ;",lambdaName.
Data(), lambdaExpression.c_str() );
467 if (fLambdaPtr !=
nullptr) {
469 gClingFunctions.insert ( std::make_pair ( lambdaExpression, fLambdaPtr) );
470 fClingInitialized =
true;
473 fClingInitialized =
false;
493 if (formula.
IsNull() )
return -1;
496 if (IsValid() && formula == fFormula )
return 0;
499 if (!fFormula.IsNull() )
Clear();
504 bool ret = InitLambdaExpression(fFormula);
505 return (ret) ? 0 : 1;
508 if (fVars.empty() ) FillDefaults();
511 PreProcessFormula(fFormula);
513 bool ret = PrepareFormula(fFormula);
515 return (ret) ? 0 : 1;
524 fnew.fClingParameters = fClingParameters;
525 fnew.fClingVariables = fClingVariables;
527 fnew.fFuncs = fFuncs;
530 fnew.fConsts = fConsts;
531 fnew.fFunctionsShortcuts = fFunctionsShortcuts;
532 fnew.fFormula = fFormula;
540 int nLinParts = fnew.fLinearParts.size();
542 for (
int i = 0; i < nLinParts; ++i)
delete fnew.fLinearParts[i];
543 fnew.fLinearParts.clear();
548 fnew.fLinearParts.reserve(nLinParts);
549 for (
int i = 0; i < nLinParts; ++i) {
553 linearOld->
Copy(*linearNew);
554 fnew.fLinearParts.push_back(linearNew);
561 fnew.fClingInput = fClingInput;
562 fnew.fReadyToExecute = fReadyToExecute;
563 fnew.fClingInitialized = fClingInitialized;
564 fnew.fAllParametersSetted = fAllParametersSetted;
565 fnew.fClingName = fClingName;
568 if (fnew.fMethod)
delete fnew.fMethod;
574 fnew.fFuncPtr = fFuncPtr;
588 if(fMethod) fMethod->Delete();
591 fClingVariables.clear();
592 fClingParameters.clear();
593 fReadyToExecute =
false;
594 fClingInitialized =
false;
595 fAllParametersSetted =
false;
600 fFunctionsShortcuts.clear();
605 for (
int i = 0; i < nLinParts; ++i)
delete fLinearParts[i];
621 Bool_t hasParameters = (fNpar > 0);
622 Bool_t hasVariables = (fNdim > 0);
623 TString prototypeArguments =
"";
626 prototypeArguments.
Append(
"Double_t*");
628 if(hasVariables && hasParameters)
630 prototypeArguments.
Append(
",");
634 prototypeArguments.
Append(
"Double_t*");
637 fMethod->InitWithPrototype(fClingName,prototypeArguments);
638 if(!fMethod->IsValid())
640 Error(
"Eval",
"Can't find %s function prototype with arguments %s",fClingName.Data(),prototypeArguments.
Data());
659 CallFunc_t * callfunc = fMethod->GetCallFunc();
671 if(!fClingInitialized && fReadyToExecute && fClingInput.Length() > 0)
674 fClingInitialized = PrepareEvalMethod();
684 const TString defvars[] = {
"x",
"y",
"z",
"t"};
693 const pair<TString,TString> funShortcuts[] =
694 { {
"sin",
"TMath::Sin" },
695 {
"cos",
"TMath::Cos" }, {
"exp",
"TMath::Exp"}, {
"log",
"TMath::Log"}, {
"log10",
"TMath::Log10"},
696 {
"tan",
"TMath::Tan"}, {
"sinh",
"TMath::SinH"}, {
"cosh",
"TMath::CosH"},
697 {
"tanh",
"TMath::TanH"}, {
"asin",
"TMath::ASin"}, {
"acos",
"TMath::ACos"},
698 {
"atan",
"TMath::ATan"}, {
"atan2",
"TMath::ATan2"}, {
"sqrt",
"TMath::Sqrt"},
699 {
"ceil",
"TMath::Ceil"}, {
"floor",
"TMath::Floor"}, {
"pow",
"TMath::Power"},
700 {
"binomial",
"TMath::Binomial"},{
"abs",
"TMath::Abs"},
701 {
"min",
"TMath::Min"},{
"max",
"TMath::Max"},{
"sign",
"TMath::Sign" },
705 std::vector<TString> defvars2(10);
706 for (
int i = 0; i < 9; ++i)
709 for(
auto var : defvars)
711 int pos = fVars.size();
713 fClingVariables.push_back(0);
724 for(
auto con : defconsts)
726 fConsts[con.first] = con.second;
728 for(
auto fun : funShortcuts)
730 fFunctionsShortcuts[fun.first] = fun.second;
785 while(polPos !=
kNPOS)
788 Bool_t defaultVariable =
false;
790 Int_t openingBracketPos = formula.
Index(
'(',polPos);
791 Bool_t defaultCounter = openingBracketPos ==
kNPOS;
792 Bool_t defaultDegree =
true;
793 Int_t degree,counter;
799 sdegree = formula(polPos + 3,openingBracketPos - polPos - 3);
800 if (!sdegree.
IsDigit() ) defaultCounter =
true;
802 if (!defaultCounter) {
803 degree = sdegree.
Atoi();
804 counter =
TString(formula(openingBracketPos+1,formula.
Index(
')',polPos) - openingBracketPos)).
Atoi();
808 Int_t temp = polPos+3;
809 while(temp < formula.
Length() && isdigit(formula[temp]))
811 defaultDegree =
false;
814 degree =
TString(formula(polPos+3,temp - polPos - 3)).
Atoi();
819 if(polPos - 1 < 0 || !IsFunctionNameChar(formula[polPos-1]) || formula[polPos-1] ==
':' )
822 defaultVariable =
true;
826 Int_t tmp = polPos - 1;
827 while(tmp >= 0 && IsFunctionNameChar(formula[tmp]) && formula[tmp] !=
':')
831 variable = formula(tmp + 1, polPos - (tmp+1));
833 Int_t param = counter + 1;
842 if(defaultCounter && !defaultDegree)
846 else if(defaultCounter && defaultDegree)
852 pattern =
TString::Format(
"%spol%d(%d)",(defaultVariable ?
"" : variable.
Data()),degree,counter);
856 Error(
"HandlePolN",
"Error handling polynomial function - expression is %s - trying to replace %s with %s ", formula.
Data(), pattern.
Data(), replacement.
Data() );
859 if (formula == pattern) {
865 polPos = formula.
Index(
"pol");
887 map< pair<TString,Int_t> ,pair<TString,TString> > functions;
888 functions.insert(make_pair(make_pair(
"gaus",1),make_pair(
"[0]*exp(-0.5*(({V0}-[1])/[2])*(({V0}-[1])/[2]))",
"[0]*exp(-0.5*(({V0}-[1])/[2])*(({V0}-[1])/[2]))/(sqrt(2*pi)*[2])")));
889 functions.insert(make_pair(make_pair(
"landau",1),make_pair(
"[0]*TMath::Landau({V0},[1],[2],false)",
"[0]*TMath::Landau({V0},[1],[2],true)")));
890 functions.insert(make_pair(make_pair(
"expo",1),make_pair(
"exp([0]+[1]*{V0})",
"")));
891 functions.insert(make_pair(make_pair(
"crystalball",1),make_pair(
"[0]*ROOT::Math::crystalball_function({V0},[3],[4],[2],[1])",
"[0]*ROOT::Math::crystalball_pdf({V0},[3],[4],[2],[1])")));
892 functions.insert(make_pair(make_pair(
"breitwigner",1),make_pair(
"[0]*ROOT::Math::breitwigner_pdf({V0},[2],[1])",
"[0]*ROOT::Math::breitwigner_pdf({V0},[2],[4],[1])")));
894 functions.insert(make_pair(make_pair(
"cheb0" ,1),make_pair(
"ROOT::Math::Chebyshev0({V0},[0])",
"")));
895 functions.insert(make_pair(make_pair(
"cheb1" ,1),make_pair(
"ROOT::Math::Chebyshev1({V0},[0],[1])",
"")));
896 functions.insert(make_pair(make_pair(
"cheb2" ,1),make_pair(
"ROOT::Math::Chebyshev2({V0},[0],[1],[2])",
"")));
897 functions.insert(make_pair(make_pair(
"cheb3" ,1),make_pair(
"ROOT::Math::Chebyshev3({V0},[0],[1],[2],[3])",
"")));
898 functions.insert(make_pair(make_pair(
"cheb4" ,1),make_pair(
"ROOT::Math::Chebyshev4({V0},[0],[1],[2],[3],[4])",
"")));
899 functions.insert(make_pair(make_pair(
"cheb5" ,1),make_pair(
"ROOT::Math::Chebyshev5({V0},[0],[1],[2],[3],[4],[5])",
"")));
900 functions.insert(make_pair(make_pair(
"cheb6" ,1),make_pair(
"ROOT::Math::Chebyshev6({V0},[0],[1],[2],[3],[4],[5],[6])",
"")));
901 functions.insert(make_pair(make_pair(
"cheb7" ,1),make_pair(
"ROOT::Math::Chebyshev7({V0},[0],[1],[2],[3],[4],[5],[6],[7])",
"")));
902 functions.insert(make_pair(make_pair(
"cheb8" ,1),make_pair(
"ROOT::Math::Chebyshev8({V0},[0],[1],[2],[3],[4],[5],[6],[7],[8])",
"")));
903 functions.insert(make_pair(make_pair(
"cheb9" ,1),make_pair(
"ROOT::Math::Chebyshev9({V0},[0],[1],[2],[3],[4],[5],[6],[7],[8],[9])",
"")));
904 functions.insert(make_pair(make_pair(
"cheb10",1),make_pair(
"ROOT::Math::Chebyshev10({V0},[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10])",
"")));
906 functions.insert(make_pair(make_pair(
"gaus",2),make_pair(
"[0]*exp(-0.5*(({V0}-[1])/[2])^2 - 0.5*(({V1}-[3])/[4])^2)",
"")));
907 functions.insert(make_pair(make_pair(
"landau",2),make_pair(
"[0]*TMath::Landau({V0},[1],[2],false)*TMath::Landau({V1},[3],[4],false)",
"")));
908 functions.insert(make_pair(make_pair(
"expo",2),make_pair(
"exp([0]+[1]*{V0})",
"exp([0]+[1]*{V0}+[2]*{V1})")));
910 map<TString,Int_t> functionsNumbers;
911 functionsNumbers[
"gaus"] = 100;
912 functionsNumbers[
"landau"] = 400;
913 functionsNumbers[
"expo"] = 200;
914 functionsNumbers[
"crystalball"] = 500;
921 for(map<pair<TString,Int_t>,pair<TString,TString> >::iterator it = functions.begin(); it != functions.end(); ++it)
924 TString funName = it->first.first;
930 while(funPos !=
kNPOS)
937 Int_t iposBefore = funPos - 1;
939 if (iposBefore >= 0) {
941 if (isalpha(formula[iposBefore] ) ) {
947 Bool_t isNormalized =
false;
948 if (lastFunPos < formula.
Length() ) {
950 isNormalized = (formula[lastFunPos] ==
'n');
951 if (isNormalized) lastFunPos += 1;
952 if (lastFunPos < formula.
Length() ) {
954 if (isalnum(formula[lastFunPos] ) )
break;
955 if (formula[lastFunPos] !=
'[' && formula[lastFunPos] !=
'(' && ! IsOperator(formula[lastFunPos] ) ) {
956 funPos = formula.
Index(funName,lastFunPos);
969 Bool_t defaultVariable =
false;
972 Int_t openingBracketPos = funPos + funName.
Length() + (isNormalized ? 1 : 0);
974 if(openingBracketPos > formula.
Length() || formula[openingBracketPos] !=
'[')
977 variables.resize(dim);
979 defaultVariable =
true;
984 closingBracketPos = formula.
Index(
']',openingBracketPos);
985 varList = formula(openingBracketPos+1,closingBracketPos - openingBracketPos - 1);
987 variables.resize(dim);
992 if(IsFunctionNameChar(varList[i]))
994 varName.
Append(varList[i]);
996 if(varList[i] ==
',')
998 variables[Nvar] = varName;
1005 variables[Nvar] = varName;
1009 if(dim != it->first.second)
1011 pair<TString,Int_t> key = make_pair(funName,dim);
1012 if(functions.find(key) == functions.end())
1014 Error(
"PreProcessFormula",
"%d dimension function %s is not defined as parametrized function.",dim,funName.
Data());
1021 Int_t openingParenthesisPos = (closingBracketPos ==
kNPOS) ? openingBracketPos : closingBracketPos + 1;
1022 bool defaultCounter = (openingParenthesisPos > formula.
Length() || formula[openingParenthesisPos] !=
'(');
1033 counter =
TString(formula(openingParenthesisPos+1,formula.
Index(
')',funPos) - openingParenthesisPos -1)).
Atoi();
1037 TString body = (isNormalized ? it->second.second : it->second.first);
1038 if(isNormalized && body ==
"")
1040 Error(
"PreprocessFormula",
"%d dimension function %s has no normalized form.",it->first.second,funName.
Data());
1043 for(
int i = 0 ; i < body.
Length() ; ++i)
1050 TString variable = variables[num];
1054 i += variable.
Length()-1;
1056 else if(body[i] ==
'[')
1060 while(tmp < body.
Length() && body[tmp] !=
']')
1068 body.
Replace(i+1,tmp - 1 - i,replacement,replacement.
Length());
1069 i += replacement.
Length() + 1;
1073 if(defaultCounter && defaultVariable)
1077 (isNormalized ?
"n" :
""));
1079 if(!defaultCounter && defaultVariable)
1083 (isNormalized ?
"n" :
""),
1086 if(defaultCounter && !defaultVariable)
1090 (isNormalized ?
"n":
""),
1093 if(!defaultCounter && !defaultVariable)
1097 (isNormalized ?
"n" :
""),
1105 fNumber = functionsNumbers[funName] + 10*(dim-1);
1110 funPos = formula.
Index(funName);
1124 while(caretPos !=
kNPOS)
1128 Int_t temp = caretPos;
1131 if(formula[temp] ==
')')
1135 while(depth != 0 && temp > 0)
1137 if(formula[temp] ==
')')
1139 if(formula[temp] ==
'(')
1143 if (depth == 0) temp++;
1149 if (temp>=2 && IsScientificNotation(formula, temp-1) ) temp-=3;
1151 while(temp >= 0 && !IsOperator(formula[temp]) && !IsBracket(formula[temp]) );
1154 Int_t leftPos = temp+1;
1155 left = formula(leftPos, caretPos - leftPos);
1161 if (temp >= formula.
Length() ) {
1162 Error(
"HandleExponentiation",
"Invalid position of operator ^");
1165 if(formula[temp] ==
'(')
1169 while(depth != 0 && temp < formula.
Length())
1171 if(formula[temp] ==
')')
1173 if(formula[temp] ==
'(')
1181 if (formula[temp] ==
'-' || formula[temp] ==
'+' ) temp++;
1186 while(temp < formula.
Length() && ( (depth > 0) || !IsOperator(formula[temp]) ) )
1190 if (temp>=2 && IsScientificNotation(formula, temp) ) temp+=2;
1192 if (temp < formula.
Length() && formula[temp] ==
'(') depth++;
1193 if (temp < formula.
Length() && formula[temp] ==
')') {
1201 right = formula(caretPos + 1, (temp - 1) - caretPos );
1209 formula.
Replace(leftPos,pattern.
Length(),replacement,replacement.Length());
1211 caretPos = formula.
Last(
'^');
1220 if (linPos ==
kNPOS )
return;
1226 while(linPos !=
kNPOS)
1234 while(temp >= 0 && formula[temp] !=
'@')
1238 left = formula(temp+1,linPos - (temp +1));
1241 while(temp < formula.
Length() && formula[temp] !=
'@')
1245 TString right = formula(linPos+1,temp - (linPos+1));
1249 Nlinear += (
first) ? 2 : 1;
1259 linPos = formula.
Index(
"@");
1276 HandlePolN(formula);
1277 HandleParametrizedFunctions(formula);
1278 HandleExponentiation(formula);
1280 HandleLinear(formula);
1292 fReadyToExecute =
false;
1293 ExtractFunctors(formula);
1298 fClingInput = formula;
1310 ProcessFormula(fClingInput);
1313 if (
fNumber != 0) SetPredefinedParamNames();
1315 return fReadyToExecute && fClingInitialized;
1337 if(formula[i] ==
'[')
1342 while(formula[i] !=
']' && i < formula.
Length())
1344 param.
Append(formula[i++]);
1351 DoAddParameter(param,0,
false);
1353 formula.
Replace(tmp,i - tmp, replacement,replacement.
Length());
1359 if (formula[i] ==
'\"') {
1363 }
while(formula[i] !=
'\"');
1366 if (IsScientificNotation(formula, i) )
1369 if (IsHexadecimal(formula, i) ) {
1372 while ( !IsOperator(formula[i]) && i < formula.
Length() ) {
1381 if(isalpha(formula[i]) && !IsOperator(formula[i]))
1385 while( IsFunctionNameChar(formula[i]) && i < formula.
Length())
1388 if (formula[i] ==
':' && ( (i+1) < formula.
Length() ) ) {
1389 if ( formula[i+1] ==
':' ) {
1399 name.
Append(formula[i++]);
1402 if(formula[i] ==
'(')
1405 if(formula[i] ==
')')
1413 while(depth != 0 && i < formula.
Length())
1417 case '(': depth++;
break;
1418 case ')': depth--;
break;
1419 case ',':
if(depth == 1) args++;
break;
1423 body.
Append(formula[i++]);
1427 ExtractFunctors(body);
1428 formula.
Replace(i-originalBodyLen,originalBodyLen,body,body.
Length());
1429 i += body.
Length() - originalBodyLen;
1438 TObject *obj =
gROOT->GetListOfFunctions()->FindObject(name);
1442 TF1 *
f1 =
dynamic_cast<TF1*
> (
obj);
1443 if (f1) f = f1->GetFormula();
1446 TString replacementFormula = f->GetExpFormula();
1449 PreProcessFormula(replacementFormula);
1457 std::vector<TString> newNames;
1460 newNames.resize(f->GetNpar() );
1462 for (
int jpar = f->GetNpar()-1; jpar >= 0; --jpar ) {
1469 replacementFormula.
ReplaceAll(oldName,newName);
1470 newNames[jpar] = newName;
1473 newNames[jpar] = f->GetParName(jpar);
1477 ExtractFunctors(replacementFormula);
1481 for (
int jpar = 0; jpar < f->GetNpar(); ++jpar) {
1482 if (nparOffset> 0) {
1484 assert((
int) newNames.size() == f->GetNpar() );
1489 SetParameter(f->GetParName(jpar), f->GetParameter(jpar) );
1492 replacementFormula.
Insert(0,
'(');
1493 replacementFormula.
Insert(replacementFormula.
Length(),
')');
1540 for(list<TFormulaFunction>::iterator funcsIt = fFuncs.begin(); funcsIt != fFuncs.end(); ++funcsIt)
1550 map<TString,TString>::iterator it = fFunctionsShortcuts.find(fun.
GetName());
1551 if(it != fFunctionsShortcuts.end())
1558 while ( index !=
kNPOS) {
1562 if ( (index > 0) && (isalpha( formula[index-1] ) || formula[index-1] ==
':' )) {
1563 index = formula.
Index(shortcut,i2);
1566 if (i2 < formula.
Length() && formula[i2] !=
'(') {
1567 index = formula.
Index(shortcut,i2);
1573 index = formula.
Index(shortcut,inext);
1581 size_t index = name.rfind(
"::");
1582 assert(index != std::string::npos);
1594 if (strcmp(p->
GetName(),functionName.
Data()) == 0 &&
1617 Info(
"TFormula",
"Could not find %s function with %d argument(s)",fun.
GetName(),fun.
GetNargs());
1630 TString replacement = old->GetExpFormula();
1631 PreProcessFormula(replacement);
1632 ExtractFunctors(replacement);
1638 map<TString,TFormulaVariable>::iterator varsIt = fVars.find(fun.
GetName());
1639 if(varsIt!= fVars.end())
1642 TString name = (*varsIt).second.GetName();
1646 AddVariable(name,value);
1647 if(!fVars[name].fFound)
1651 fVars[
name].fFound =
true;
1652 int varDim = (*varsIt).second.fArrayPos;
1653 if (varDim >= fNdim) {
1657 for (
auto &v : fVars) {
1658 if (v.second.fArrayPos < varDim && !v.second.fFound ) {
1659 AddVariable(v.first, v.second.fValue);
1660 v.second.fFound =
true;
1681 int digit = sdigit.
Atoi();
1682 if (digit >= fNdim) {
1685 for (
int j = 0; j <
fNdim; ++j) {
1687 if (fVars.find(vname) == fVars.end() ) {
1689 fVars[vname].fFound =
true;
1690 AddVariable(vname,0.);
1703 auto paramsIt = fParams.find(fun.
GetName());
1704 if(paramsIt != fParams.end())
1725 map<TString,Double_t>::iterator constIt = fConsts.find(fun.
GetName());
1726 if(constIt != fConsts.end())
1743 if(!fReadyToExecute)
1745 fReadyToExecute =
true;
1746 Bool_t hasVariables = (fNdim > 0);
1747 Bool_t hasParameters = (fNpar > 0);
1750 fAllParametersSetted =
true;
1753 if (hasParameters && ! hasVariables) {
1756 hasVariables =
true;
1758 Bool_t hasBoth = hasVariables && hasParameters;
1760 if (inputIntoCling) {
1764 std::string inputFormula = std::string(formula);
1769 TString::Format(
"%s%s%s",(hasVariables ?
"Double_t *x" :
""), (hasBoth ?
"," :
""),
1770 (hasParameters ?
"Double_t *p" :
""));
1774 fClingName = gNamePrefix;
1783 fClingInitialized =
true;
1784 inputIntoCling =
false;
1789 fClingName =
TString::Format(
"%s__id%zu",gNamePrefix.Data(),(
unsigned long) hasher(inputFormula) );
1791 fClingInput =
TString::Format(
"Double_t %s(%s){ return %s ; }", fClingName.Data(),argumentsPrototype.
Data(),inputFormula.c_str());
1803 if(inputIntoCling) {
1804 InputFormulaIntoCling();
1805 if (fClingInitialized) {
1809 gClingFunctions.insert ( std::make_pair ( inputFormula, (
void*) fFuncPtr) );
1814 fAllParametersSetted =
true;
1815 fClingInitialized =
true;
1823 if (!fClingInitialized) {
1824 Bool_t allFunctorsMatched =
true;
1825 for(list<TFormulaFunction>::iterator it = fFuncs.begin(); it != fFuncs.end(); it++)
1829 allFunctorsMatched =
false;
1830 if (it->GetNargs() == 0)
1831 Error(
"ProcessFormula",
"\"%s\" has not been matched in the formula expression",it->GetName() );
1833 Error(
"ProcessFormula",
"Could not find %s function with %d argument(s)",it->GetName(),it->GetNargs());
1836 if (!allFunctorsMatched) {
1838 fReadyToExecute =
false;
1843 if (fClingInitialized && fReadyToExecute) {
1844 auto itvar = fVars.begin();
1847 if ( ! itvar->second.fFound ) {
1849 itvar = fVars.erase(itvar);
1854 while( itvar != fVars.end() );
1924 if (i < 0 || i >= n ) {
1925 Error(
"GetLinearPart",
"Formula %s has only %d linear parts - requested %d",
GetName(),n,i);
1938 if(fVars.find(name) != fVars.end() )
1949 if(var.
fArrayPos >= (
int)fClingVariables.size())
1951 fClingVariables.resize(var.
fArrayPos+1);
1959 fClingVariables.push_back(value);
1960 if (!fFormula.IsNull() ) {
1962 ProcessFormula(fClingInput);
1977 Bool_t anyNewVar =
false;
1978 for(
Int_t i = 0 ; i < size; ++i)
1981 const TString & vname = vars[i];
1991 if(var.
fArrayPos >= (
int)fClingVariables.capacity())
1993 Int_t multiplier = 2;
1994 if(fFuncs.size() > 100)
1998 fClingVariables.reserve(multiplier * fClingVariables.capacity());
2000 fClingVariables.push_back(0.0);
2008 if(anyNewVar && !fFormula.IsNull())
2010 ProcessFormula(fClingInput);
2020 Error(
"SetName",
"The name \'%s\' is reserved as a TFormula variable name.\n"
2021 "\tThis function will not be renamed.",name);
2025 auto listOfFunctions =
gROOT->GetListOfFunctions();
2026 TObject* thisAsFunctionInList =
nullptr;
2028 if (listOfFunctions){
2029 thisAsFunctionInList = listOfFunctions->
FindObject(
this);
2030 if (thisAsFunctionInList) listOfFunctions->Remove(thisAsFunctionInList);
2033 if (thisAsFunctionInList) listOfFunctions->Add(thisAsFunctionInList);
2046 for(
Int_t i = 0; i < size; ++i)
2048 pair<TString,Double_t> v = vars[i];
2049 if(fVars.find(v.first) != fVars.end())
2051 fVars[v.first].fValue = v.second;
2052 fClingVariables[fVars[v.first].fArrayPos] = v.second;
2056 Error(
"SetVariables",
"Variable %s is not defined.",v.first.Data());
2067 if(fVars.find(sname) == fVars.end())
2069 Error(
"GetVariable",
"Variable %s is not defined.",sname.
Data());
2072 return fVars.find(sname)->second.fValue;
2080 if(fVars.find(sname) == fVars.end())
2082 Error(
"GetVarNumber",
"Variable %s is not defined.",sname.
Data());
2085 return fVars.find(sname)->second.fArrayPos;
2094 if (ivar < 0 || ivar >= fNdim)
return "";
2097 for (
auto & v : fVars) {
2098 if (v.second.fArrayPos == ivar)
return v.first;
2100 Error(
"GetVarName",
"Variable with index %d not found !!",ivar);
2110 if(fVars.find(name) == fVars.end())
2112 Error(
"SetVariable",
"Variable %s is not defined.",name.
Data());
2116 fClingVariables[fVars[
name].fArrayPos] =
value;
2130 if(fParams.find(name) != fParams.end() )
2132 int ipos = fParams[
name];
2137 ipos = fParams.size();
2138 fParams[
name] = ipos;
2141 if(ipos >= (
int)fClingParameters.size())
2143 if(ipos >= (
int)fClingParameters.capacity())
2144 fClingParameters.reserve(
TMath::Max(
int(fParams.size()), ipos+1));
2145 fClingParameters.insert(fClingParameters.end(),ipos+1-fClingParameters.size(),0.0);
2147 fClingParameters[ipos] =
value;
2154 int pos = fParams.size();
2156 auto ret = fParams.insert(std::make_pair(name,pos));
2162 if (ret.first == fParams.begin() )
2165 auto previous = (ret.first);
2167 pos = previous->second + 1;
2171 if (pos < (
int)fClingParameters.size() )
2172 fClingParameters.insert(fClingParameters.begin()+pos,
value);
2175 if (pos > (
int)fClingParameters.size() )
2176 Warning(
"inserting parameter %s at pos %d when vector size is %d \n",name.
Data(),pos,(int)fClingParameters.size() );
2178 if(pos >= (
int)fClingParameters.capacity())
2179 fClingParameters.reserve(
TMath::Max(
int(fParams.size()), pos+1));
2180 fClingParameters.insert(fClingParameters.end(),pos+1-fClingParameters.size(),0.0);
2181 fClingParameters[pos] =
value;
2185 for (
auto it = ret.first; it != fParams.end(); ++it ) {
2193 if (processFormula) {
2196 ProcessFormula(fClingInput);
2204 auto it = fParams.find(name);
2205 if(it == fParams.end())
2220 Error(
"GetParameter",
"Parameter %s is not defined.",name);
2233 if(param >=0 && param < (
int) fClingParameters.size())
2234 return fClingParameters[param];
2235 Error(
"GetParameter",
"wrong index used - use GetParameter(name)");
2243 if (ipar < 0 || ipar >= fNpar)
return "";
2246 for (
auto & p : fParams) {
2247 if (p.second == ipar)
return p.first.Data();
2249 Error(
"GetParName",
"Parameter with index %d not found !!",ipar);
2255 if(!fClingParameters.empty())
2256 return const_cast<Double_t*>(&fClingParameters[0]);
2264 if (
Int_t(fClingParameters.size()) > i)
2265 params[i] = fClingParameters[i];
2281 if(fParams.find(name) == fParams.end())
2283 Error(
"SetParameter",
"Parameter %s is not defined.",name.Data());
2287 fParams[
name].fFound =
true;
2288 fClingParameters[fParams[
name].fArrayPos] =
value;
2289 fAllParametersSetted =
true;
2290 for(map<TString,TFormulaVariable>::iterator it = fParams.begin(); it != fParams.end(); it++)
2292 if(!it->second.fFound)
2294 fAllParametersSetted =
false;
2310 for(
Int_t i = 0 ; i < size ; ++i)
2312 pair<TString,Double_t> p = params[i];
2313 if(fParams.find(p.first) == fParams.end())
2315 Error(
"SetParameters",
"Parameter %s is not defined",p.first.Data());
2318 fParams[p.first].fValue = p.second;
2319 fParams[p.first].fFound =
true;
2320 fClingParameters[fParams[p.first].fArrayPos] = p.second;
2322 fAllParametersSetted =
true;
2323 for(map<TString,TFormulaVariable>::iterator it = fParams.begin(); it != fParams.end(); it++)
2325 if(!it->second.fFound)
2327 fAllParametersSetted =
false;
2336 if(!params || size < 0 || size > fNpar)
return;
2338 if (size != (
int) fClingParameters.size() ) {
2339 Warning(
"SetParameters",
"size is not same of cling parameter size %d - %d",size,
int(fClingParameters.size()) );
2340 for(
Int_t i = 0; i < size; ++i)
2347 fAllParametersSetted =
true;
2348 std::copy(params, params+size, fClingParameters.begin() );
2356 DoSetParameters(params,fNpar);
2382 if (param < 0 || param >= fNpar)
return;
2383 assert(
int(fClingParameters.size()) == fNpar);
2384 fClingParameters[param] =
value;
2389 const char *name4,
const char *name5,
const char *name6,
const char *name7,
2390 const char *name8,
const char *name9,
const char *name10)
2407 if (ipar < 0 || ipar > fNpar) {
2408 Error(
"SetParName",
"Wrong Parameter index %d ",ipar);
2413 for (
auto &it : fParams) {
2414 if (it.second == ipar) {
2416 fParams.erase(oldName);
2417 fParams.insert(std::make_pair(name, ipar) );
2422 Error(
"SetParName",
"Parameter %d is not existing.",ipar);
2427 ReplaceParamName(fFormula, oldName, name);
2433 if (!formula.
IsNull() ) {
2435 for(list<TFormulaFunction>::iterator it = fFuncs.begin(); it != fFuncs.end(); ++it)
2437 if(oldName == it->GetName())
2446 Error(
"SetParName",
"Parameter %s is not defined.",oldName.
Data());
2462 return DoEval(x, params);
2469 double xxx[4] = {
x,
y,
z,t};
2477 double xxx[3] = {
x,
y,z};
2485 double xxx[2] = {
x,y};
2506 if(!fReadyToExecute)
2508 Error(
"Eval",
"Formula is invalid and not ready to execute ");
2509 for(
auto it = fFuncs.begin(); it != fFuncs.end(); ++it)
2520 std::function<double(double *, double *)> & fptr = * ( (std::function<double(double *, double *)> *) fLambdaPtr);
2523 double * v =
const_cast<double*
>(
x);
2524 double * p = (params) ? const_cast<double*>(params) :
const_cast<double*
>(fClingParameters.data());
2528 if (!fClingInitialized) {
2529 Error(
"Eval",
"Formula is invalid or not properly initialized - try calling TFormula::Compile");
2531 #ifdef EVAL_IS_NOT_CONST
2533 TString oldClingName = fClingName;
2535 fClingInput.
ReplaceAll(oldClingName, fClingName);
2536 InputFormulaIntoCling();
2542 double * vars = (
x) ? const_cast<double*>(x) :
const_cast<double*
>(fClingVariables.data());
2545 (*fFuncPtr)(0, 1, args, &
result);
2547 double * pars = (params) ? const_cast<double*>(params) :
const_cast<double*
>(fClingParameters.data());
2549 (*fFuncPtr)(0, 2, args, &
result);
2571 if (opt.Contains(
"CLING") ) {
2572 std::string clingFunc = fClingInput.Data();
2575 if (found == std::string::npos || found2 == std::string::npos) {
2576 Error(
"GetExpFormula",
"Invalid Cling expression - return default formula expression");
2579 TString clingFormula = fClingInput(found+7,found2-found-7);
2581 if (!opt.Contains(
"P"))
return clingFormula;
2584 while (i < clingFormula.
Length()-2 ) {
2586 if (clingFormula[i] ==
'p' && clingFormula[i+1] ==
'[' && isdigit(clingFormula[i+2]) ) {
2588 while ( isdigit(clingFormula[j]) ) { j++;}
2589 if (clingFormula[j] !=
']') {
2590 Error(
"GetExpFormula",
"Parameters not found - invalid expression - return default cling formula");
2591 return clingFormula;
2593 TString parNumbName = clingFormula(i+2,j-i-2);
2594 int parNumber = parNumbName.
Atoi();
2595 assert(parNumber < fNpar);
2597 clingFormula.
Replace(i,j-i+1, replacement );
2598 i += replacement.
Length();
2602 return clingFormula;
2604 if (opt.Contains(
"P") ) {
2606 TString expFormula = fFormula;
2608 while (i < expFormula.
Length()-2 ) {
2610 if (expFormula[i] ==
'[') {
2612 while ( expFormula[j] !=
']' ) { j++;}
2613 if (expFormula[j] !=
']') {
2614 Error(
"GetExpFormula",
"Parameter names not found - invalid expression - return default formula");
2617 TString parName = expFormula(i+1,j-i-1);
2619 expFormula.
Replace(i,j-i+1, replacement );
2620 i += replacement.
Length();
2626 Warning(
"GetExpFormula",
"Invalid option - return defult formula expression");
2635 printf(
" Formula expression: \n");
2636 printf(
"\t%s \n",fFormula.Data() );
2642 if (opt.Contains(
"V") ) {
2644 printf(
"List of Variables: \n");
2645 assert(
int(fClingVariables.size()) >= fNdim);
2646 for (
int ivar = 0; ivar <
fNdim ; ++ivar) {
2647 printf(
"Var%4d %20s = %10f \n",ivar,GetVarName(ivar).
Data(), fClingVariables[ivar]);
2651 printf(
"List of Parameters: \n");
2652 if (
int(fClingParameters.size()) < fNpar)
2653 Error(
"Print",
"Number of stored parameters in vector %lu in map %lu is different than fNpar %d",fClingParameters.size(), fParams.size(),
fNpar);
2654 assert(
int(fClingParameters.size()) >= fNpar);
2656 for (
int ipar = 0; ipar <
fNpar ; ++ipar) {
2657 printf(
"Par%4d %20s = %10f \n",ipar,
GetParName(ipar), fClingParameters[ipar] );
2660 printf(
"Expression passed to Cling:\n");
2661 printf(
"\t%s\n",fClingInput.Data() );
2663 if(!fReadyToExecute)
2665 Warning(
"Print",
"Formula is not ready to execute. Missing parameters/variables");
2666 for(list<TFormulaFunction>::const_iterator it = fFuncs.begin(); it != fFuncs.end(); ++it)
2675 if(!fAllParametersSetted)
2701 if (v <= 8 && v > 3 && v != 6) {
2713 if (!fReadyToExecute ) {
2714 Error(
"Streamer",
"Old formula read from file is NOT valid");
2731 if (fFormula.IsNull() )
return;
2735 std::vector<double> parValues = fClingParameters;
2737 fNpar = fParams.size();
2745 fClingParameters.clear();
2750 PreProcessFormula(fFormula);
2754 PrepareFormula(fFormula);
2760 if (fNpar != (
int) parValues.size() ) {
2761 Error(
"Streamer",
"number of parameters computed (%d) is not same as the stored parameters (%d)",fNpar,
int(parValues.size()) );
2767 bool ret = InitLambdaExpression(fFormula);
2769 fReadyToExecute =
true;
2770 fClingInitialized =
true;
2773 assert(fNpar == (
int) parValues.size() );
2774 std::copy( parValues.begin(), parValues.end(), fClingParameters.begin() );
2776 if (fParams.size() != paramMap.size() ) {
2777 Warning(
"Streamer",
"number of parameters list found (%lu) is not same as the stored one (%lu) - use re-created list",fParams.size(),paramMap.size()) ;
2795 gROOT->GetListOfFunctions()->Add(
this);
2797 if (!fReadyToExecute ) {
2798 Error(
"Streamer",
"Formula read from file is NOT ready to execute");
2806 Error(
"Streamer",
"Reading version %d is not supported",v);
virtual const char * GetTitle() const
Returns title of object.
Ssiz_t Last(char c) const
Find last occurrence of a character c.
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
virtual CallFuncIFacePtr_t CallFunc_IFacePtr(CallFunc_t *) const
Double_t Floor(Double_t x)
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
void variables(TString fin="TMVA.root", TString dirName="InputVariables_Id", TString title="TMVA Input Variables", Bool_t isRegression=kFALSE, Bool_t useTMVAStyle=kTRUE)
TString & ReplaceAll(const TString &s1, const TString &s2)
Int_t GetNargs() const
Number of function arguments.
virtual void SetName(const char *name)
Change (i.e.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Buffer base class used for serializing objects.
R__EXTERN TVirtualMutex * gROOTMutex
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
TString & Insert(Ssiz_t pos, const char *s)
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
const char * Data() const
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
The TNamed class is the base class for all named ROOT classes.
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
virtual void Copy(TObject &named) const
Copy this to obj.
Double_t Log10(Double_t x)
virtual Bool_t Declare(const char *code)=0
TString & Append(const char *cs)
std::vector< std::vector< double > > Data
Int_t Atoi() const
Return integer value of string.
Method or function calling interface.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
virtual void Copy(TObject &object) const
Copy this to obj.
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Bool_t TestBit(UInt_t f) const
virtual const char * GetName() const
Returns name of object.
The ROOT global object gROOT contains a list of all defined classes.
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Mother of all ROOT objects.
Global functions class (global functions are obtained from CINT).
void(* Generic_t)(void *, int, void **, void *)
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Short_t Max(Short_t a, Short_t b)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Each ROOT class (see TClass) has a linked list of methods.
R__EXTERN TInterpreter * gCling
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.