33#include <unordered_map>
35using std::map, std::pair, std::make_pair, std::list, std::max, std::string;
38#pragma optimize("",off)
45std::string doubleToString(
double val)
48 ss << std::setprecision(std::numeric_limits<double>::max_digits10) << val;
52bool areMatching(
char opening,
char closing)
54 return (opening ==
'(' && closing ==
')') || (opening ==
'{' && closing ==
'}') ||
55 (opening ==
'[' && closing ==
']') || (opening ==
'\"' && closing ==
'\"');
58bool isBalanced(
const TString &s)
63 if (s[
c] ==
'[' || s[
c] ==
'{' || s[
c] ==
'(') {
65 }
else if (s[
c] ==
']' || s[
c] ==
'}' || s[
c] ==
')') {
66 if (i.empty() || !areMatching(i.top(), s[
c])) {
67 Error(
"TFormula",
"Found unbalanced char '%c' (expected closing of '%c') at index %d of '%s'", s[
c], i.top(),
c,
72 }
else if (s[
c] ==
'\"') {
75 else if (areMatching(i.top(), s[
c]))
83 Error(
"TFormula",
"String '%s' with %zu unbalanced chars.", s.
Data(), i.size());
94std::string vectorizedArgType()
96#ifdef R__HAS_STD_EXPERIMENTAL_SIMD
97 auto n = ROOT::Double_v::size();
98 return "std::experimental::resize_simd_t<" + std::to_string(
n) +
", ROOT::Double_v>";
101 return "ROOT::Double_v";
329static std::unordered_map<std::string, void *>
gClingFunctions = std::unordered_map<std::string, void * >();
336 for (
int i = 0; i < nobjects; ++i) {
337 if (fromv5[i] && target[i]) {
338 TFormula fnew(fromv5[i]->GetName(), fromv5[i]->GetExpFormula());
354 const static std::set<char> ops {
'+',
'^',
'-',
'/',
'*',
'<',
'>',
'|',
'&',
'!',
'=',
'?',
'%'};
355 return ops.end() != ops.find(
c);
362 char brackets[] = {
')',
'(',
'{',
'}'};
363 Int_t bracketsLen =
sizeof(brackets)/
sizeof(
char);
364 for(
Int_t i = 0; i < bracketsLen; ++i)
386 if ( (formula[i] ==
'e' || formula[i] ==
'E') && (i > 0 && i < formula.
Length()-1) ) {
388 if ( (isdigit(formula[i-1]) || formula[i-1] ==
'.') && ( isdigit(formula[i+1]) || formula[i+1] ==
'+' || formula[i+1] ==
'-' ) )
398 if ( (formula[i] ==
'x' || formula[i] ==
'X') && (i > 0 && i < formula.
Length()-1) && formula[i-1] ==
'0') {
399 if (isdigit(formula[i+1]) )
401 static char hex_values[12] = {
'a',
'A',
'b',
'B',
'c',
'C',
'd',
'D',
'e',
'E',
'f',
'F'};
402 for (
int jjj = 0; jjj < 12; ++jjj) {
403 if (formula[i+1] == hex_values[jjj])
420 Bool_t foundOpenParenthesis =
false;
421 if (pos == 0 || pos == formula.
Length()-1)
return false;
422 for (
int i = pos-1; i >=0; i--) {
423 if (formula[i] ==
']' )
return false;
424 if (formula[i] ==
'[' ) {
425 foundOpenParenthesis =
true;
429 if (!foundOpenParenthesis )
return false;
432 for (
int i = pos+1; i < formula.
Length(); i++) {
433 if (formula[i] ==
']' )
return true;
446 TRegexp numericPattern(
"p?[0-9]+");
449 int patternStart = numericPattern.
Index(
a, &len);
450 bool aNumeric = (patternStart == 0 && len ==
a.Length());
452 patternStart = numericPattern.
Index(
b, &len);
453 bool bNumeric = (patternStart == 0 && len ==
b.Length());
455 if (aNumeric && !bNumeric)
457 else if (!aNumeric && bNumeric)
459 else if (!aNumeric && !bNumeric)
462 int aInt = (
a[0] ==
'p') ?
TString(
a(1,
a.Length())).
Atoi() :
a.Atoi();
463 int bInt = (
b[0] ==
'p') ?
TString(
b(1,
b.Length())).
Atoi() :
b.Atoi();
474 for (
int i = 0; i < formula.
Length(); i++) {
477 if (isalpha(formula[i]) || formula[i] ==
'{' || formula[i] ==
'[') {
481 || (formula[i] ==
'{' && formula[j] ==
'}'));
489 if (substitutions.find(
name) != substitutions.end()) {
491 i += substitutions[
name].Length() + 2 - 1;
493 }
else if (isalpha(formula[i])) {
496 i +=
name.Length() - 1;
522 if (strlen(
name)!=1)
return false;
523 for (
auto const & specialName : {
"x",
"y",
"z",
"t"}){
524 if (strcmp(
name,specialName)==0)
return true;
537 gROOT->GetListOfFunctions()->Remove(
this);
542 for (
int i = 0; i < nLinParts; ++i)
delete fLinearParts[i];
558#ifndef R__HAS_STD_EXPERIMENTAL_SIMD
574 if (addToGlobList &&
gROOT) {
579 gROOT->GetListOfFunctions()->Remove(old);
581 Error(
"TFormula",
"The name %s is reserved as a TFormula variable name.\n",
name);
583 gROOT->GetListOfFunctions()->Add(
this);
608 for (
int i = 0; i < npar; ++i) {
612 assert (
fNpar == npar);
622 if (addToGlobList &&
gROOT) {
627 gROOT->GetListOfFunctions()->Remove(old);
629 Error(
"TFormula",
"The name %s is reserved as a TFormula variable name.\n",
name);
631 gROOT->GetListOfFunctions()->Add(
this);
636 Error(
"TFormula",
"Syntax error in building the lambda expression %s", formula );
643 formula.TFormula::Copy(*
this);
649 gROOT->GetListOfFunctions()->Remove(old);
652 Error(
"TFormula",
"The name %s is reserved as a TFormula variable name.\n",formula.
GetName());
654 gROOT->GetListOfFunctions()->Add(
this);
665 rhs.TFormula::Copy(*
this);
672 std::string lambdaExpression = formula;
696 TString lineExpr =
TString::Format(
"std::function<double(double*,double*)> %s = %s ;",lambdaName.
Data(), lambdaExpression.c_str() );
723 if (formula.
IsNull() )
return -1;
735 return (
ret) ? 0 : 1;
745 return (
ret) ? 0 : 1;
774 for (
int i = 0; i < nLinParts; ++i)
delete fnew.
fLinearParts[i];
781 for (
int i = 0; i < nLinParts; ++i) {
785 linearOld->
Copy(*linearNew);
810 Error(
"TFormula",
"Syntax error in building the lambda expression %s",
fFormula.Data() );
856 for (
int i = 0; i < nLinParts; ++i)
delete fLinearParts[i];
863static std::unique_ptr<TMethodCall>
865 bool IsVectorized,
bool AddCladArrayRef =
false) {
866 std::unique_ptr<TMethodCall>
867 Method = std::make_unique<TMethodCall>();
869 TString prototypeArguments =
"";
870 if (HasVariables || HasParameters) {
872 prototypeArguments.
Append(vectorizedArgType() +
" const*");
874 prototypeArguments.
Append(
"Double_t const*");
876 auto AddDoublePtrParam = [&prototypeArguments]() {
877 prototypeArguments.
Append(
",");
878 prototypeArguments.
Append(
"Double_t*");
884 if (AddCladArrayRef) {
885 prototypeArguments.
Append(
",");
886 prototypeArguments.
Append(
"Double_t*");
891 Method->InitWithPrototype(FuncName, prototypeArguments);
892 if (!Method->IsValid()) {
893 Error(
"prepareMethod",
894 "Can't compile function %s prototype with arguments %s", FuncName,
895 prototypeArguments.
Data());
903 if (!method)
return nullptr;
906 if (!
gCling->CallFunc_IsValid(callfunc)) {
907 Error(
"prepareFuncPtr",
"Callfunc retuned from Cling is not valid");
912 =
gCling->CallFunc_IFacePtr(callfunc).fGeneric;
914 Error(
"prepareFuncPtr",
"Compiled function pointer is null");
950 TString triggerAutoparsing =
"namespace ROOT_TFormula_triggerAutoParse {\n"; triggerAutoparsing +=
fClingInput +
"\n}";
951 gCling->ProcessLine(triggerAutoparsing);
969 const TString defvars[] = {
"x",
"y",
"z",
"t"};
970 const pair<TString, Double_t> defconsts[] = {{
"pi",
TMath::Pi()},
988 const std::pair<TString, TString> funShortcuts[] = {
989 {
"sign",
"TMath::Sign"}, {
"binomial",
"TMath::Binomial"}, {
"sq",
"TMath::Sq"}};
991 std::vector<TString> defvars2(10);
992 for (
int i = 0; i < 9; ++i)
995 for (
const auto &var : defvars) {
996 int pos =
fVars.size();
1009 for (
auto con : defconsts) {
1010 fConsts[con.first] = con.second;
1012 for (
auto fun : funShortcuts) {
1040 Bool_t defaultVariable =
false;
1042 Int_t openingBracketPos = formula.
Index(
'(', polPos);
1043 Bool_t defaultCounter = openingBracketPos ==
kNPOS;
1044 Bool_t defaultDegree =
true;
1045 Int_t degree = 1, counter = 0;
1047 std::vector<TString> paramNames;
1050 Bool_t isNewFormat =
false;
1051 if (!defaultCounter) {
1052 TString args = formula(openingBracketPos + 1, formula.
Index(
')', polPos) - openingBracketPos - 1);
1055 sdegree = formula(polPos + 3, openingBracketPos - polPos - 3);
1058 degree = sdegree.
Atoi();
1060 std::vector<TString> tokens;
1061 std::stringstream ss(args.
Data());
1063 while (std::getline(ss, token,
',')) {
1064 tokens.push_back(
TString(token));
1067 if (!tokens.empty()) {
1068 variable = tokens[0];
1072 if (tokens.size() > 1) {
1073 TString counterStr = tokens[1];
1076 counter = counterStr.
Atoi();
1081 for (
size_t i = 1; i < tokens.size(); i++) {
1085 paramStr = paramStr(1, paramStr.
Length() - 2);
1086 paramNames.push_back(paramStr);
1101 if (!defaultCounter) {
1102 sdegree = formula(polPos + 3, openingBracketPos - polPos - 3);
1104 defaultCounter =
true;
1106 if (!defaultCounter) {
1107 degree = sdegree.
Atoi();
1108 counter =
TString(formula(openingBracketPos + 1, formula.
Index(
')', polPos) - openingBracketPos)).
Atoi();
1110 Int_t temp = polPos + 3;
1111 while (temp < formula.
Length() && isdigit(formula[temp])) {
1112 defaultDegree =
false;
1115 degree =
TString(formula(polPos + 3, temp - polPos - 3)).
Atoi();
1118 if (polPos - 1 < 0 || !
IsFunctionNameChar(formula[polPos - 1]) || formula[polPos - 1] ==
':') {
1120 defaultVariable =
true;
1122 Int_t tmp = polPos - 1;
1126 variable = formula(tmp + 1, polPos - (tmp + 1));
1132 if (isNewFormat && !paramNames.empty()) {
1133 for (
Int_t i = 0; i <= degree && i < static_cast<Int_t>(paramNames.size()); i++) {
1136 }
else if (i == 1) {
1144 for (
Int_t i = 1; i <= degree; i++) {
1154 replacement.
Insert(0,
'(');
1161 pattern = formula(polPos, formula.
Index(
')', polPos) - polPos + 1);
1162 }
else if (defaultCounter && !defaultDegree) {
1164 }
else if (defaultCounter && defaultDegree) {
1167 pattern =
TString::Format(
"%spol%d(%d)", (defaultVariable ?
"" : variable.
Data()), degree, counter);
1171 Error(
"HandlePolN",
"Error handling polynomial function - expression is %s - trying to replace %s with %s ",
1176 if (formula == pattern) {
1182 polPos = formula.
Index(
"pol");
1208 map< pair<TString,Int_t> ,pair<TString,TString> > functions;
1211 map<TString,Int_t> functionsNumbers;
1212 functionsNumbers[
"gaus"] = 100;
1213 functionsNumbers[
"bigaus"] = 102;
1214 functionsNumbers[
"landau"] = 400;
1215 functionsNumbers[
"expo"] = 200;
1216 functionsNumbers[
"crystalball"] = 500;
1229 formula.
ReplaceAll(
"xylandaun",
"landaun[x,y]");
1230 formula.
ReplaceAll(
"xylandau",
"landau[x,y]");
1232 const char * defaultVariableNames[] = {
"x",
"y",
"z"};
1234 for (map<pair<TString, Int_t>, pair<TString, TString>>::iterator it = functions.begin(); it != functions.end();
1237 TString funName = it->first.first;
1238 Int_t funDim = it->first.second;
1248 Int_t iposBefore = funPos - 1;
1251 if (iposBefore >= 0) {
1252 assert(iposBefore < formula.
Length());
1257 funPos = formula.
Index(funName, lastFunPos);
1262 Bool_t isNormalized =
false;
1263 if (lastFunPos < formula.
Length()) {
1265 isNormalized = (formula[lastFunPos] ==
'n');
1268 if (lastFunPos < formula.
Length()) {
1269 char c = formula[lastFunPos];
1272 if (isalnum(
c) || (!
IsOperator(
c) &&
c !=
'(' &&
c !=
')' &&
c !=
'[' &&
c !=
']')) {
1274 funPos = formula.
Index(funName, lastFunPos);
1283 std::vector<TString> variables;
1286 Bool_t defaultVariables =
false;
1289 Int_t openingBracketPos = funPos + funName.
Length() + (isNormalized ? 1 : 0);
1291 if (openingBracketPos >= formula.
Length() || formula[openingBracketPos] !=
'[') {
1293 variables.resize(dim);
1294 for (
Int_t idim = 0; idim < dim; ++idim)
1295 variables[idim] = defaultVariableNames[idim];
1296 defaultVariables =
true;
1299 closingBracketPos = formula.
Index(
']', openingBracketPos);
1300 varList = formula(openingBracketPos + 1, closingBracketPos - openingBracketPos - 1);
1302 variables.resize(dim);
1307 varName.
Append(varList[i]);
1309 if (varList[i] ==
',') {
1310 variables[Nvar] = varName;
1317 variables[Nvar] = varName;
1322 if (dim != funDim) {
1323 pair<TString, Int_t> key = make_pair(funName, dim);
1324 if (functions.find(key) == functions.end()) {
1325 Error(
"PreProcessFormula",
"Dimension of function %s is detected to be of dimension %d and is not "
1326 "compatible with existing pre-defined function which has dim %d",
1327 funName.
Data(), dim, funDim);
1331 funPos = formula.
Index(funName, lastFunPos);
1336 Int_t openingParenthesisPos = (closingBracketPos ==
kNPOS) ? openingBracketPos : closingBracketPos + 1;
1337 bool defaultCounter = (openingParenthesisPos > formula.
Length() || formula[openingParenthesisPos] !=
'(');
1342 if (defaultCounter) {
1348 TRegexp counterPattern(
"([0-9]+)");
1350 if (counterPattern.
Index(formula, &len, openingParenthesisPos) == -1) {
1351 funPos = formula.
Index(funName, funPos + 1);
1355 TString(formula(openingParenthesisPos + 1, formula.
Index(
')', funPos) - openingParenthesisPos - 1))
1361 TString body = (isNormalized ? it->second.second : it->second.first);
1362 if (isNormalized && body ==
"") {
1363 Error(
"PreprocessFormula",
"%d dimension function %s has no normalized form.", it->first.second,
1367 for (
int i = 0; i < body.
Length(); ++i) {
1368 if (body[i] ==
'{') {
1372 TString variable = variables[num];
1376 i += variable.
Length() - 1;
1377 }
else if (body[i] ==
'[') {
1380 while (tmp < body.
Length() && body[tmp] !=
']') {
1387 body.
Replace(i + 1, tmp - 1 - i, replacement, replacement.
Length());
1388 i += replacement.
Length() + 1;
1392 if (defaultCounter && defaultVariables) {
1395 if (!defaultCounter && defaultVariables) {
1396 pattern =
TString::Format(
"%s%s(%d)", funName.
Data(), (isNormalized ?
"n" :
""), counter);
1398 if (defaultCounter && !defaultVariables) {
1401 if (!defaultCounter && !defaultVariables) {
1409 fNumber = functionsNumbers[funName] + 10 * (dim - 1);
1416 funPos = formula.
Index(funName);
1426 TRegexp rangePattern(
"\\[[0-9]+\\.\\.[0-9]+\\]");
1429 while ((matchIdx = rangePattern.
Index(formula, &len, matchIdx)) != -1) {
1430 int startIdx = matchIdx + 1;
1431 int endIdx = formula.
Index(
"..", startIdx) + 2;
1435 if (endCnt <= startCnt)
1436 Error(
"HandleParamRanges",
"End parameter (%d) <= start parameter (%d) in parameter range", endCnt, startCnt);
1439 for (
int cnt = startCnt; cnt < endCnt; cnt++)
1444 formula.
Replace(matchIdx, formula.
Index(
"]", matchIdx) + 1 - matchIdx, newString);
1446 matchIdx += newString.
Length();
1460 std::map<std::pair<TString, Int_t>, std::pair<TString, TString>> parFunctions;
1468 if (formula[i] ==
'[') {
1469 while (i < formula.
Length() && formula[i] !=
']')
1474 if (i < formula.
Length() && formula[i] ==
'\"') {
1477 while (i < formula.
Length() && formula[i] !=
'\"');
1491 if (i < formula.
Length() && isalpha(formula[i]) && !
IsOperator(formula[i])) {
1504 std::vector<int> argSeparators;
1505 argSeparators.push_back(j);
1507 for (k = j + 1; depth >= 1 && k < formula.
Length(); k++) {
1508 if (formula[k] ==
',' && depth == 1) {
1510 argSeparators.push_back(k);
1511 }
else if (formula[k] ==
'(')
1513 else if (formula[k] ==
')')
1516 argSeparators.push_back(k - 1);
1522 obj =
gROOT->GetListOfFunctions()->FindObject(
name);
1527 TF1 *
f1 =
dynamic_cast<TF1 *
>(obj);
1529 f =
f1->GetFormula();
1535 bool nameRecognized = (
f !=
nullptr);
1542 ndim =
f->GetNdim();
1543 npar =
f->GetNpar();
1544 replacementFormula =
f->GetExpFormula();
1548 for (
const auto &keyval : parFunctions) {
1550 const pair<TString, Int_t> &name_ndim = keyval.first;
1552 const pair<TString, TString> &formulaPair = keyval.second;
1555 if (
name == name_ndim.first)
1556 replacementFormula = formulaPair.first;
1557 else if (
name == name_ndim.first +
"n" && formulaPair.second !=
"")
1558 replacementFormula = formulaPair.second;
1563 ndim = name_ndim.second;
1568 while ((idx = replacementFormula.
Index(
'[', idx)) !=
kNPOS) {
1569 npar = max(npar, 1 +
TString(replacementFormula(idx + 1, replacementFormula.
Length())).
Atoi());
1570 idx = replacementFormula.
Index(
']', idx);
1572 Error(
"HandleFunctionArguments",
"Square brackets not matching in formula %s",
1573 (
const char *)replacementFormula);
1580 if (nArguments == ndim + npar || nArguments == npar || nArguments == ndim) {
1581 nameRecognized =
true;
1586 if (nameRecognized && ndim > 4)
1587 Error(
"HandleFunctionArguments",
"Number of dimensions %d greater than 4. Cannot parse formula.", ndim);
1590 if (nameRecognized && j < formula.
Length() && formula[j] ==
'(') {
1595 map<TString, TString> argSubstitutions;
1597 const char *defaultVariableNames[] = {
"x",
"y",
"z",
"t"};
1600 bool canReplace =
false;
1601 if (nArguments == ndim + npar) {
1603 for (
int argNr = 0; argNr < nArguments; argNr++) {
1607 TString(formula(argSeparators[argNr] + 1, argSeparators[argNr + 1] - argSeparators[argNr] - 1));
1614 argSubstitutions[oldName] = newName;
1617 argSubstitutions[defaultVariableNames[argNr]] = newName;
1620 int parNr = argNr - ndim;
1623 argSubstitutions[oldName] = newName;
1626 if (
f && oldName == newName)
1632 }
else if (nArguments == npar) {
1637 bool varsImplicit =
true;
1638 for (
int argNr = 0; argNr < nArguments && varsImplicit; argNr++) {
1639 int openIdx = argSeparators[argNr] + 1;
1640 int closeIdx = argSeparators[argNr + 1] - 1;
1643 if (formula[openIdx] !=
'[' || formula[closeIdx] !=
']' || closeIdx <= openIdx + 1)
1644 varsImplicit =
false;
1647 for (
int idx = openIdx + 1; idx < closeIdx && varsImplicit; idx++)
1649 varsImplicit =
false;
1652 Warning(
"HandleFunctionArguments",
1653 "Argument %d is not a parameter. Cannot assume variables are implicit.", argNr);
1660 for (
int dim = 0; dim < ndim; dim++) {
1661 argSubstitutions[
TString::Format(
"{V%d}", dim)] = defaultVariableNames[dim];
1665 for (
int argNr = 0; argNr < nArguments; argNr++) {
1669 TString(formula(argSeparators[argNr] + 1, argSeparators[argNr + 1] - argSeparators[argNr] - 1));
1673 argSubstitutions[oldName] = newName;
1676 if (
f && oldName == newName)
1683 if (!canReplace && nArguments == ndim) {
1687 for (
int argNr = 0; argNr < nArguments; argNr++) {
1690 TString(formula(argSeparators[argNr] + 1, argSeparators[argNr + 1] - argSeparators[argNr] - 1));
1694 argSubstitutions[oldName] = newName;
1697 argSubstitutions[defaultVariableNames[argNr]] = newName;
1702 for (
int parNr = 0; parNr < npar; parNr++)
1716 formula.
Replace(i, k - i, replacementFormula);
1717 i += replacementFormula.
Length() - 1;
1720 Warning(
"HandleFunctionArguments",
"Unable to make replacement. Number of parameters doesn't work : "
1721 "%d arguments, %d dimensions, %d parameters",
1722 nArguments, ndim, npar);
1745 Int_t temp = caretPos;
1748 if (formula[temp] ==
')') {
1751 while (depth != 0 && temp > 0) {
1752 if (formula[temp] ==
')')
1754 if (formula[temp] ==
'(')
1769 assert(temp + 1 >= 0);
1770 Int_t leftPos = temp + 1;
1771 left = formula(leftPos, caretPos - leftPos);
1777 if (temp >= formula.
Length()) {
1778 Error(
"HandleExponentiation",
"Invalid position of operator ^");
1781 if (formula[temp] ==
'(') {
1784 while (depth != 0 && temp < formula.
Length()) {
1785 if (formula[temp] ==
')')
1787 if (formula[temp] ==
'(')
1794 if (formula[temp] ==
'-' || formula[temp] ==
'+')
1800 while (temp < formula.
Length() && ((depth > 0) || !
IsOperator(formula[temp]))) {
1806 if (temp < formula.
Length() && formula[temp] ==
'(')
1808 if (temp < formula.
Length() && formula[temp] ==
')') {
1816 right = formula(caretPos + 1, (temp - 1) - caretPos);
1831 caretPos = formula.
Last(
'^');
1841 if(formula.
Length() == 0)
return;
1843 if(terms.size() <= 1)
return;
1847 int delimeterPos = 0;
1848 for(std::size_t iTerm = 0; iTerm < terms.size(); ++iTerm) {
1849 if (iTerm < terms.size() - 1) {
1851 delimeterPos += terms[iTerm].size() + iTerm;
1854 expandedFormula += terms[iTerm];
1855 expandedFormula += formula(delimeterPos, formula.
Length() - delimeterPos);
1860 auto termName = std::string(
"__linear") + std::to_string(iTerm+1);
1862 std::stringstream ss;
1863 ss <<
"([" << iTerm <<
"]*(" << terms[iTerm] <<
"))";
1864 expandedFormula += ss.str();
1865 if(iTerm < terms.size() - 1) expandedFormula +=
"+";
1867 formula = expandedFormula;
1905 if (!isBalanced(formula)) {
1955 if (formula[i] ==
'[') {
1959 while (i < formula.
Length() && formula[i] !=
']') {
1960 param.
Append(formula[i++]);
1965 int paramIndex = -1;
1967 paramIndex = param.
Atoi();
1971 for (
int idx = 0; idx <= paramIndex; ++idx) {
1991 formula.
Replace(tmp, i - tmp, replacement, replacement.
Length());
1995 int deltai = replacement.
Length() - (i-tmp);
2001 if (formula[i] ==
'\"') {
2005 }
while (i < formula.
Length() && formula[i] !=
'\"');
2023 if (isalpha(formula[i]) &&
2031 if (formula[i] ==
':' && ((i + 1) < formula.
Length())) {
2032 if (formula[i + 1] ==
':') {
2041 name.Append(formula[i++]);
2044 if (formula[i] ==
'(') {
2046 if (i < formula.
Length() && formula[i] ==
')') {
2053 while (depth != 0 && i < formula.
Length()) {
2054 switch (formula[i]) {
2055 case '(': depth++;
break;
2056 case ')': depth--;
break;
2064 body.
Append(formula[i++]);
2069 formula.
Replace(i - originalBodyLen, originalBodyLen, body, body.
Length());
2070 i += body.
Length() - originalBodyLen;
2083 obj =
gROOT->GetListOfFunctions()->FindObject(
name);
2088 TF1 *
f1 =
dynamic_cast<TF1 *
>(obj);
2090 f =
f1->GetFormula();
2098 TString replacementFormula =
f->GetExpFormula();
2111 std::vector<TString> newNames;
2114 newNames.resize(
f->GetNpar());
2116 for (
int jpar =
f->GetNpar() - 1; jpar >= 0; --jpar) {
2124 replacementFormula.
ReplaceAll(oldName, newName);
2125 newNames[jpar] = newName;
2127 newNames[jpar] =
f->GetParName(jpar);
2135 for (
int jpar = 0; jpar <
f->GetNpar(); ++jpar) {
2136 if (nparOffset > 0) {
2138 assert((
int)newNames.size() ==
f->GetNpar());
2145 replacementFormula.
Insert(0,
'(');
2146 replacementFormula.
Insert(replacementFormula.
Length(),
')');
2149 i += replacementFormula.
Length() -
name.Length();
2193 for (list<TFormulaFunction>::iterator funcsIt =
fFuncs.begin(); funcsIt !=
fFuncs.end(); ++funcsIt) {
2210 while (index !=
kNPOS) {
2214 if ((index > 0) && (isalpha(formula[index - 1]) || formula[index - 1] ==
':')) {
2215 index = formula.
Index(shortcut, i2);
2218 if (i2 < formula.
Length() && formula[i2] !=
'(') {
2219 index = formula.
Index(shortcut, i2);
2224 Ssiz_t inext = index + full.Length();
2225 index = formula.
Index(shortcut, inext);
2232#ifdef TFORMULA_CHECK_FUNCTIONS
2238 size_t index =
name.rfind(
"::");
2239 assert(index != std::string::npos);
2247 TIter next(methodList);
2249 while ((p = (
TMethod *)next())) {
2250 if (strcmp(p->
GetName(), functionName.
Data()) == 0 &&
2265 if (
f && fun.
GetNargs() <=
f->GetNargs() && fun.
GetNargs() >=
f->GetNargs() -
f->GetNargsOpt()) {
2273 Info(
"TFormula",
"Could not find %s function with %d argument(s)", fun.
GetName(), fun.
GetNargs());
2296 map<TString, TFormulaVariable>::iterator varsIt =
fVars.find(fun.
GetName());
2297 if (varsIt !=
fVars.end()) {
2300 Double_t value = (*varsIt).second.fValue;
2306 int varDim = (*varsIt).second.fArrayPos;
2307 if (varDim >=
fNdim) {
2312 if (
v.second.fArrayPos < varDim && !
v.second.fFound) {
2314 v.second.fFound =
true;
2335 int digit = sdigit.
Atoi();
2336 if (digit >=
fNdim) {
2339 for (
int j = 0; j <
fNdim; ++j) {
2343 fVars[vname].fFound =
true;
2358 if (paramsIt !=
fParams.end()) {
2375 map<TString, Double_t>::iterator constIt =
fConsts.find(fun.
GetName());
2376 if (constIt !=
fConsts.end()) {
2378 formula.
ReplaceAll(pattern, doubleToString(constIt->second));
2394 if (!hasParameters) {
2408 if (inputIntoCling) {
2411 std::string inputFormula(formula.
Data());
2415 std::string inputFormulaVecFlag = inputFormula;
2417 inputFormulaVecFlag +=
" (vectorized)";
2422 TString argumentsPrototype =
TString::Format(
"%s%s%s", ( (hasVariables || hasParameters) ? (argType +
" const *x").Data() :
""),
2423 (hasParameters ?
"," :
""), (hasParameters ?
"Double_t *p" :
""));
2440 inputIntoCling =
false;
2450 argumentsPrototype.
Data(), inputFormula.c_str());
2469 if (inputIntoCling) {
2495 for (list<TFormulaFunction>::iterator it =
fFuncs.begin(); it !=
fFuncs.end(); ++it) {
2497 if (!it->fFound && !it->IsFuncCall()) {
2499 if (it->GetNargs() == 0)
2500 Error(
"ProcessFormula",
"\"%s\" has not been matched in the formula expression", it->GetName());
2502 Error(
"ProcessFormula",
"Could not find %s function with %d argument(s)", it->GetName(), it->GetNargs());
2513 auto itvar =
fVars.begin();
2516 if (!itvar->second.fFound) {
2518 itvar =
fVars.erase(itvar);
2521 }
while (itvar !=
fVars.end());
2532 make_pair(make_pair(
"gaus", 1), make_pair(
"[0]*exp(-0.5*(({V0}-[1])/[2])*(({V0}-[1])/[2]))",
2533 "[0]*exp(-0.5*(({V0}-[1])/[2])*(({V0}-[1])/[2]))/(sqrt(2*pi)*[2])")));
2534 functions.insert(make_pair(make_pair(
"landau", 1), make_pair(
"[0]*TMath::Landau({V0},[1],[2],false)",
2535 "[0]*TMath::Landau({V0},[1],[2],true)")));
2536 functions.insert(make_pair(make_pair(
"expo", 1), make_pair(
"exp([0]+[1]*{V0})",
"")));
2538 make_pair(make_pair(
"crystalball", 1), make_pair(
"[0]*ROOT::Math::crystalball_function({V0},[3],[4],[2],[1])",
2539 "[0]*ROOT::Math::crystalball_pdf({V0},[3],[4],[2],[1])")));
2541 make_pair(make_pair(
"breitwigner", 1), make_pair(
"[0]*ROOT::Math::breitwigner_pdf({V0},[2],[1])",
2542 "[0]*ROOT::Math::breitwigner_pdf({V0},[2],[4],[1])")));
2544 functions.insert(make_pair(make_pair(
"cheb0", 1), make_pair(
"ROOT::Math::Chebyshev0({V0},[0])",
"")));
2545 functions.insert(make_pair(make_pair(
"cheb1", 1), make_pair(
"ROOT::Math::Chebyshev1({V0},[0],[1])",
"")));
2546 functions.insert(make_pair(make_pair(
"cheb2", 1), make_pair(
"ROOT::Math::Chebyshev2({V0},[0],[1],[2])",
"")));
2547 functions.insert(make_pair(make_pair(
"cheb3", 1), make_pair(
"ROOT::Math::Chebyshev3({V0},[0],[1],[2],[3])",
"")));
2549 make_pair(make_pair(
"cheb4", 1), make_pair(
"ROOT::Math::Chebyshev4({V0},[0],[1],[2],[3],[4])",
"")));
2551 make_pair(make_pair(
"cheb5", 1), make_pair(
"ROOT::Math::Chebyshev5({V0},[0],[1],[2],[3],[4],[5])",
"")));
2553 make_pair(make_pair(
"cheb6", 1), make_pair(
"ROOT::Math::Chebyshev6({V0},[0],[1],[2],[3],[4],[5],[6])",
"")));
2555 make_pair(make_pair(
"cheb7", 1), make_pair(
"ROOT::Math::Chebyshev7({V0},[0],[1],[2],[3],[4],[5],[6],[7])",
"")));
2556 functions.insert(make_pair(make_pair(
"cheb8", 1),
2557 make_pair(
"ROOT::Math::Chebyshev8({V0},[0],[1],[2],[3],[4],[5],[6],[7],[8])",
"")));
2558 functions.insert(make_pair(make_pair(
"cheb9", 1),
2559 make_pair(
"ROOT::Math::Chebyshev9({V0},[0],[1],[2],[3],[4],[5],[6],[7],[8],[9])",
"")));
2561 make_pair(make_pair(
"cheb10", 1),
2562 make_pair(
"ROOT::Math::Chebyshev10({V0},[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10])",
"")));
2565 make_pair(make_pair(
"gaus", 2), make_pair(
"[0]*exp(-0.5*(({V0}-[1])/[2])^2 - 0.5*(({V1}-[3])/[4])^2)",
"")));
2567 make_pair(make_pair(
"landau", 2),
2568 make_pair(
"[0]*TMath::Landau({V0},[1],[2],false)*TMath::Landau({V1},[3],[4],false)",
"TMath::Landau({V0},[0],[1],true)*TMath::Landau({V1},[2],[3],true)")));
2570 make_pair(make_pair(
"expo", 2),
2571 make_pair(
"exp([0]+[1]*{V0}+[2]*{V1})",
"")));
2574 make_pair(make_pair(
"gaus", 3), make_pair(
"[0]*exp(-0.5*(({V0}-[1])/[2])^2 - 0.5*(({V1}-[3])/[4])^2 - 0.5*(({V2}-[5])/[6])^2)",
"")));
2577 make_pair(make_pair(
"bigaus", 2), make_pair(
"[0]*ROOT::Math::bigaussian_pdf({V0},{V1},[2],[4],[5],[1],[3])",
2578 "[0]*ROOT::Math::bigaussian_pdf({V0},{V1},[2],[4],[5],[1],[3])")));
2670 if (i < 0 || i >=
n ) {
2671 Error(
"GetLinearPart",
"Formula %s has only %d linear parts - requested %d",
GetName(),
n,i);
2717 Bool_t anyNewVar =
false;
2720 const TString &vname = vars[i];
2730 Int_t multiplier = 2;
2731 if (
fFuncs.size() > 100) {
2744 if (anyNewVar && !
fFormula.IsNull()) {
2756 Error(
"SetName",
"The name \'%s\' is reserved as a TFormula variable name.\n"
2757 "\tThis function will not be renamed.",
2762 auto listOfFunctions =
gROOT->GetListOfFunctions();
2763 TObject* thisAsFunctionInList =
nullptr;
2765 if (listOfFunctions){
2766 thisAsFunctionInList = listOfFunctions->
FindObject(
this);
2767 if (thisAsFunctionInList) listOfFunctions->Remove(thisAsFunctionInList);
2770 if (thisAsFunctionInList) listOfFunctions->Add(thisAsFunctionInList);
2788 fVars[
v.first].fValue =
v.second;
2791 Error(
"SetVariables",
"Variable %s is not defined.",
v.first.Data());
2802 if (
fVars.end() == nameIt) {
2803 Error(
"GetVariable",
"Variable %s is not defined.",
name);
2806 return nameIt->second.fValue;
2815 if (
fVars.end() == nameIt) {
2816 Error(
"GetVarNumber",
"Variable %s is not defined.",
name);
2819 return nameIt->second.fArrayPos;
2827 if (ivar < 0 || ivar >=
fNdim)
return "";
2830 for (
auto &
v :
fVars) {
2831 if (
v.second.fArrayPos == ivar)
return v.first;
2833 Error(
"GetVarName",
"Variable with index %d not found !!",ivar);
2844 Error(
"SetVariable",
"Variable %s is not defined.",
name.Data());
2892 auto previous = (
ret.first);
2894 pos = previous->second + 1;
2902 Warning(
"inserting parameter %s at pos %d when vector size is %d \n",
name.Data(), pos,
2912 for (
auto it =
ret.first; it !=
fParams.end(); ++it) {
2922 if (processFormula) {
2950 Error(
"GetParameter",
"Parameter %s is not defined.",
name);
2965 Error(
"GetParameter",
"wrong index used - use GetParameter(name)");
2974 if (ipar < 0 || ipar >=
fNpar)
return "";
2978 if (p.second == ipar)
return p.first.Data();
2980 Error(
"GetParName",
"Parameter with index %d not found !!",ipar);
3013 Error(
"SetParameter",
"Parameter %s is not defined.",
name.Data());
3020 for (map<TString, TFormulaVariable>::iterator it =
fParams.begin(); it !=
fParams.end(); ++it) {
3021 if (!it->second.fFound) {
3042 pair<TString, Double_t> p = params[i];
3044 Error(
"SetParameters",
"Parameter %s is not defined", p.first.Data());
3047 fParams[p.first].fValue = p.second;
3048 fParams[p.first].fFound =
true;
3052 for (map<TString, TFormulaVariable>::iterator it =
fParams.begin(); it !=
fParams.end(); ++it) {
3053 if (!it->second.fFound) {
3095 if (param < 0 || param >=
fNpar)
return;
3106 if (ipar < 0 || ipar >
fNpar) {
3107 Error(
"SetParName",
"Wrong Parameter index %d ",ipar);
3113 if (it.second == ipar) {
3121 Error(
"SetParName",
"Parameter %d is not existing.",ipar);
3134 if (!formula.
IsNull() ) {
3136 for(list<TFormulaFunction>::iterator it =
fFuncs.begin(); it !=
fFuncs.end(); ++it)
3138 if (oldName == it->GetName()) {
3145 Error(
"SetParName",
"Parameter %s is not defined.", oldName.
Data());
3161#ifdef R__HAS_STD_EXPERIMENTAL_SIMD
3163 Info(
"SetVectorized",
"Cannot vectorized a function of zero dimension");
3168 Error(
"SetVectorized",
"Cannot set vectorized to %d -- Formula is missing", vectorized);
3185 Warning(
"SetVectorized",
"Cannot set vectorized -- try building with C++20 on Linux");
3195#ifdef R__HAS_STD_EXPERIMENTAL_SIMD
3198 ROOT::Double_v
ret = DoEvalVec(
nullptr, params);
3206 Info(
"EvalPar",
"Function is vectorized - converting Double_t into ROOT::Double_v and back");
3209 const int maxDim = 4;
3210 std::array<ROOT::Double_v, maxDim> xvec;
3211 for (
int i = 0; i <
fNdim; i++)
3214 ROOT::Double_v ans = DoEvalVec(xvec.data(), params);
3218 std::vector<ROOT::Double_v> xvec(
fNdim);
3219 for (
int i = 0; i <
fNdim; i++)
3222 ROOT::Double_v ans = DoEvalVec(xvec.data(), params);
3228 Error(
"EvalPar",
"Formula is vectorized (even though vectorizaton is not supported!)");
3236 return gInterpreter->GetFunction(
nullptr, Name.c_str());
3240#ifdef ROOT_SUPPORT_CLAD
3241 if (!IsCladRuntimeIncluded) {
3242 IsCladRuntimeIncluded =
true;
3243 gInterpreter->Declare(
"#include <Math/CladDerivator.h>\n#pragma clad OFF");
3246 IsCladRuntimeIncluded =
false;
3252 std::string &GenerationInput) {
3253 std::string ReqFuncName = FuncName +
"_req";
3255 GenerationInput = std::string(
"#pragma cling optimize(2)\n") +
3256 "#pragma clad ON\n" +
3257 "void " + ReqFuncName +
"() {\n" +
3258 CladStatement +
"\n " +
3267 Bool_t hasParameters = (Npar > 0);
3268 Bool_t hasVariables = (Ndim > 0);
3269 std::unique_ptr<TMethodCall>
3270 method =
prepareMethod(hasParameters, hasVariables, FuncName.c_str(),
3292 (*FuncPtr)(
nullptr, 2, args,
nullptr);
3303 (*FuncPtr)(
nullptr, 3, args,
nullptr);
3325 std::string GradientCall
3326 (
"clad::gradient(" + std::string(
fClingName.Data()) +
", \"p\");");
3346 Error(
"GradientPar",
"Could not initialize the formula!");
3351 Error(
"GradientPar",
"Could not generate a gradient for the formula %s!",
3356 if ((
int)result.size() <
fNpar) {
3358 "The size of gradient result is %zu but %d is required. Resizing.",
3359 result.size(),
fNpar);
3360 result.resize(
fNpar);
3392 std::string indexes = (
fNpar - 1 == 0) ?
"0" : std::string(
"0:")
3393 + std::to_string(
fNpar - 1);
3394 std::string HessianCall
3395 (
"clad::hessian(" + std::string(
fClingName.Data()) +
", \"p["
3396 + indexes +
"]\" );");
3412 Error(
"HessianPar",
"Could not initialize the formula!");
3417 Error(
"HessianPar",
"Could not generate a hessian for the formula %s!",
3422 if ((
int)result.size() <
fNpar) {
3424 "The size of hessian result is %zu but %d is required. Resizing.",
3438#ifdef R__HAS_STD_EXPERIMENTAL_SIMD
3445ROOT::Double_v TFormula::EvalParVec(
const ROOT::Double_v *
x,
const Double_t *params)
const
3448 return DoEvalVec(
x, params);
3451 return DoEval(
nullptr, params);
3456 Info(
"EvalPar",
"Function is not vectorized - converting ROOT::Double_v into Double_t and back");
3458 const int vecSize = ROOT::Double_v::size();
3459 std::vector<Double_t> xscalars(vecSize*
fNdim);
3461 for (
int i = 0; i < vecSize; i++)
3462 for (
int j = 0; j <
fNdim; j++)
3463 xscalars[i *
fNdim + j] =
x[j][i];
3465 ROOT::Double_v answers(0.);
3466 for (
int i = 0; i < vecSize; i++)
3467 answers[i] =
DoEval(&xscalars[i *
fNdim], params);
3483 Error(
"Eval",
"Formula is invalid and not ready to execute ");
3484 for (
auto it =
fFuncs.begin(); it !=
fFuncs.end(); ++it) {
3487 printf(
"%s is unknown.\n", fun.
GetName());
3499 auto thisFormula =
const_cast<TFormula*
>(
this);
3500 thisFormula->ReInitializeEvalMethod();
3503 Error(
"DoEval",
"Formula has error and it is not properly initialized ");
3509 std::function<
double(
double *,
double *)> & fptr = * ( (std::function<
double(
double *,
double *)> *)
fLambdaPtr);
3512 double *
v =
const_cast<double*
>(
x);
3513 double * p = (params) ?
const_cast<double*
>(params) :
const_cast<double*
>(
fClingParameters.data());
3520 double * vars = (
x) ?
const_cast<double*
>(
x) :
const_cast<double*
>(
fClingVariables.data());
3523 (*fFuncPtr)(
nullptr, 1, args, &result);
3525 double *pars = (params) ?
const_cast<double *
>(params) :
const_cast<double *
>(
fClingParameters.data());
3527 (*fFuncPtr)(
nullptr, 2, args, &result);
3534#ifdef R__HAS_STD_EXPERIMENTAL_SIMD
3535ROOT::Double_v TFormula::DoEvalVec(
const ROOT::Double_v *
x,
const double *params)
const
3538 Error(
"Eval",
"Formula is invalid and not ready to execute ");
3539 for (
auto it =
fFuncs.begin(); it !=
fFuncs.end(); ++it) {
3542 printf(
"%s is unknown.\n", fun.
GetName());
3554 auto thisFormula =
const_cast<TFormula*
>(
this);
3555 thisFormula->ReInitializeEvalMethod();
3558 Error(
"DoEval",
"Formula has error and it is not properly initialized ");
3564 ROOT::Double_v result = 0;
3567 ROOT::Double_v *vars =
const_cast<ROOT::Double_v *
>(
x);
3570 (*fFuncPtr)(0, 1, args, &result);
3572 double *pars = (params) ?
const_cast<double *
>(params) :
const_cast<double *
>(
fClingParameters.data());
3574 (*fFuncPtr)(0, 2, args, &result);
3590 Info(
"ReInitializeEvalMethod",
"compile now lambda expression function using Cling");
3597 if (!
fLazyInitialization)
Warning(
"ReInitializeEvalMethod",
"Formula is NOT properly initialized - try calling again TFormula::PrepareEvalMethod");
3656 std::size_t found = clingFunc.find(
"return");
3657 std::size_t found2 = clingFunc.rfind(
';');
3658 if (found == std::string::npos || found2 == std::string::npos) {
3659 Error(
"GetExpFormula",
"Invalid Cling expression - return default formula expression");
3664 if (!opt.
Contains(
"P"))
return clingFormula;
3667 while (i < clingFormula.
Length()-2 ) {
3669 if (clingFormula[i] ==
'p' && clingFormula[i+1] ==
'[' && isdigit(clingFormula[i+2]) ) {
3671 while ( j < clingFormula.
Length() && isdigit(clingFormula[j]) ) { j++;}
3672 if ( j >= clingFormula.
Length() || clingFormula[j] !=
']') {
3673 Error(
"GetExpFormula",
"Parameters not found - invalid expression - return default cling formula");
3674 return clingFormula;
3676 TString parNumbName = clingFormula(i+2,j-i-2);
3677 int parNumber = parNumbName.
Atoi();
3678 assert(parNumber <
fNpar);
3679 std::stringstream ss;
3680 std::string replacement = doubleToString(
GetParameter(parNumber));
3681 clingFormula.
Replace(i,j-i+1, replacement);
3682 i += replacement.size();
3686 return clingFormula;
3692 while (i < expFormula.
Length()-2 ) {
3694 if (expFormula[i] ==
'[') {
3696 while ( j < expFormula.
Length() && expFormula[j] !=
']' ) { j++;}
3697 if ( j >= expFormula.
Length() || expFormula[j] !=
']') {
3698 Error(
"GetExpFormula",
"Parameter names not found - invalid expression - return default formula");
3701 TString parName = expFormula(i+1,j-i-1);
3702 std::stringstream ss;
3703 std::string replacement = doubleToString(
GetParameter(parName));
3704 expFormula.
Replace(i,j-i+1, replacement);
3705 i += replacement.size();
3711 Warning(
"GetExpFormula",
"Invalid option - return default formula expression");
3716 std::unique_ptr<TInterpreterValue>
v =
gInterpreter->MakeInterpreterValue();
3717 std::string s(
"(void (&)(Double_t const *, Double_t *, Double_t *)) ");
3720 return v->ToString();
3724 std::unique_ptr<TInterpreterValue>
v =
gInterpreter->MakeInterpreterValue();
3726 return v->ToString();
3735 printf(
" Formula expression: \n");
3736 printf(
"\t%s \n",
fFormula.Data() );
3744 printf(
"List of Variables: \n");
3746 for (
int ivar = 0; ivar <
fNdim ; ++ivar) {
3751 printf(
"List of Parameters: \n");
3756 for (
int ipar = 0; ipar <
fNpar ; ++ipar) {
3760 printf(
"Expression passed to Cling:\n");
3763 printf(
"Generated Gradient:\n");
3768 printf(
"Generated Hessian:\n");
3775 Warning(
"Print",
"Formula is not ready to execute. Missing parameters/variables");
3776 for (list<TFormulaFunction>::const_iterator it =
fFuncs.begin(); it !=
fFuncs.end(); ++it) {
3779 printf(
"%s is unknown.\n", fun.
GetName());
3802 if (
b.IsReading() ) {
3819 Error(
"Streamer",
"Old formula read from file is NOT valid");
3872 if (
fNpar != (
int) parValues.size() ) {
3873 Error(
"Streamer",
"number of parameters computed (%d) is not same as the stored parameters (%d)",
fNpar,
int(parValues.size()) );
3876 if (
v > 11 &&
fNdim != ndim) {
3877 Error(
"Streamer",
"number of dimension computed (%d) is not same as the stored value (%d)",
fNdim, ndim );
3892 assert(
fNpar == (
int) parValues.size() );
3895 if (
fParams.size() != paramMap.size() ) {
3896 Warning(
"Streamer",
"number of parameters list found (%zu) is not same as the stored one (%zu) - use re-created list",
fParams.size(),paramMap.size()) ;
3912 gROOT->GetListOfFunctions()->Add(
this);
3915 Error(
"Streamer",
"Formula read from file is NOT ready to execute");
3923 Error(
"Streamer",
"Reading version %d is not supported",
v);
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int).
short Version_t
Class version identifier (short).
int Ssiz_t
String size (currently int).
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int).
bool Bool_t
Boolean (0=false, 1=true) (bool).
double Double_t
Double 8 bytes.
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
const char Option_t
Option string (const char).
Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.", GetName(), objname)
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
void GetParameters(TFitEditor::FuncParams_t &pars, TF1 *func)
Stores the parameters of the given function into pars.
externTInterpreter * gCling
externTVirtualMutex * gROOTMutex
#define R__LOCKGUARD(mutex)
Buffer base class used for serializing objects.
TClass instances represent classes, structs and namespaces in the ROOT type system.
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
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.
Global functions class (global functions are obtained from CINT).
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Int_t GetNargs() const
Number of function arguments.
Method or function calling interface.
CallFunc_t * GetCallFunc() const
Each ROOT class (see TClass) has a linked list of methods.
void Copy(TObject &named) const override
Copy this to obj.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
virtual void SetName(const char *name)
Set the name of the TNamed.
Mother of all ROOT objects.
Bool_t TestBit(UInt_t f) const
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
TObject()
TObject constructor.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Regular expression class.
Ssiz_t Index(const TString &str, Ssiz_t *len, Ssiz_t start=0) const
Find the first occurrence of the regexp in string and return the position, or -1 if there is no match...
TString & Insert(Ssiz_t pos, const char *s)
Int_t Atoi() const
Return integer value of string.
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
const char * Data() const
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
TString & ReplaceAll(const TString &s1, const TString &s2)
Ssiz_t Last(char c) const
Find last occurrence of a character c.
void ToUpper()
Change string to upper case.
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
TString & Append(const char *cs)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
constexpr Double_t G()
Gravitational constant in: .
constexpr Double_t C()
Velocity of light in .
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Double_t QuietNaN()
Returns a quiet NaN as defined by IEEE 754.
Double_t Floor(Double_t x)
Rounds x downward, returning the largest integral value that is not greater than x.
constexpr Double_t K()
Boltzmann's constant in : .
constexpr Double_t Sqrt2()
constexpr Double_t E()
Base of natural log: .
constexpr Double_t Sigma()
Stefan-Boltzmann constant in : .
constexpr Double_t H()
Planck's constant in : .
constexpr Double_t LogE()
Base-10 log of e (to convert ln to log).
constexpr Double_t Ln10()
Natural log of 10 (to convert log to ln).
constexpr Double_t EulerGamma()
Euler-Mascheroni Constant.
constexpr Double_t R()
Universal gas constant ( ) in
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Double_t Infinity()
Returns an infinity as defined by the IEEE standard.
void(* Generic_t)(void *, int, void **, void *)