29 #pragma optimize("",off)
32 static Int_t gMAXOP=1000,gMAXPAR=1000,gMAXCONST=1000;
33 const Int_t gMAXSTRINGFOUND = 10;
34 const UInt_t kOptimizationError = BIT(19);
36 ClassImp(ROOT::v5::TFormula);
134 TFormula::TFormula(): TNamed()
155 fOptimal = (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalParOld;
161 TFormula::TFormula(
const char *name,
const char *expression) :
162 TNamed(name,expression)
183 fOptimal = (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalParOld;
185 if (!expression || !*expression) {
186 Error(
"TFormula",
"expression may not be 0 or have 0 length");
192 nch = strlen(expression);
193 char *expr =
new char[nch+1];
195 for (i=0;i<nch;i++) {
196 if (expression[i] ==
' ')
continue;
197 if (i > 0 && (expression[i] ==
'*') && (expression[i-1] ==
'*')) {
201 expr[j] = expression[i]; j++;
204 Bool_t gausNorm = kFALSE;
205 Bool_t landauNorm = kFALSE;
206 Bool_t linear = kFALSE;
209 TString chaine = expr;
211 if (chaine.Contains(
"++"))
214 if (chaine.Contains(
"gausn")) {
216 TString tmp = chaine;
217 tmp.ReplaceAll(
"gausn",
"");
218 tmp.ReplaceAll(
"landaun",
"");
219 if ( tmp.Contains(
"gaus") )
220 Warning(
"TFormula",
"Cannot use both gaus and gausn - gaus will be treated as gausn");
221 if ( tmp.Contains(
"landau") )
222 Warning(
"TFormula",
"Cannot use both gausn and landau - landau will be treated as landaun");
225 if (chaine.Contains(
"landaun")) {
227 TString tmp = chaine;
228 tmp.ReplaceAll(
"landaun",
"");
229 tmp.ReplaceAll(
"gausn",
"");
230 if ( tmp.Contains(
"gaus") ) {
231 Warning(
"TFormula",
"Cannot use both gaus and landaun - gaus will be treated as gausn");
233 if ( tmp.Contains(
"landau") )
234 Warning(
"TFormula",
"Cannot use both landau and landaun - landau will be treated as landaun");
238 chaine.ReplaceAll(
"gausn",
"gaus");
240 chaine.ReplaceAll(
"landaun",
"landau");
242 SetTitle(chaine.Data());
246 if (linear) SetBit(kLinear);
248 if (Compile())
return;
250 if (gausNorm) SetBit(kNormalized);
251 if (landauNorm) SetBit(kNormalized);
256 if (strcmp(name,
"x")==0 || strcmp(name,
"y")==0 ||
257 strcmp(name,
"z")==0 || strcmp(name,
"t")==0 )
259 Error(
"TFormula",
"The name \'%s\' is reserved as a TFormula variable name.\n"
260 "\tThis function will not be registered in the list of functions",name);
262 R__LOCKGUARD(gROOTMutex);
263 TFormula *old = (TFormula*)gROOT->GetListOfFunctions()->FindObject(name);
265 gROOT->GetListOfFunctions()->Remove(old);
267 gROOT->GetListOfFunctions()->Add(
this);
274 TFormula::TFormula(
const TFormula &formula) : TNamed()
293 fOptimal = (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalParOld;
295 ((TFormula&)formula).TFormula::Copy(*
this);
301 TFormula& TFormula::operator=(
const TFormula &rhs)
312 TFormula::~TFormula()
315 R__LOCKGUARD(gROOTMutex);
316 gROOT->GetListOfFunctions()->Remove(
this);
345 Bool_t TFormula::AnalyzeFunction(TString &chaine, Int_t &err, Int_t offset)
352 Ssiz_t argStart = chaine.First(
'(');
353 if (argStart<0)
return false;
355 TString functionName = chaine(0,argStart);
359 Ssiz_t scopeEnd = functionName.Last(
':');
361 if (scopeEnd>0 && functionName[scopeEnd-1]==
':') {
362 spaceName = functionName(0,scopeEnd-1);
363 functionName.Remove(0,scopeEnd+1);
368 if (chaine[chaine.Length()-1] !=
')') {
369 Error(
"AnalyzeFunction",
"We thought we had a function but we dont (in %s)\n",chaine.Data());
372 TString args = chaine(argStart+1,chaine.Length()-2-argStart);
374 argArr.SetOwner(kTRUE);
377 Bool_t inString =
false;
382 for(i=0; i<args.Length(); i++) {
383 if (args[i]==
'"') inString = !inString;
384 if (inString)
continue;
386 Bool_t foundArg =
false;
389 case '(': paran++;
break;
390 case ')': paran--;
break;
391 case '[': brack++;
break;
392 case ']': brack--;
break;
394 case ',':
if (paran==0 && brack==0) { foundArg =
true; }
break;
396 if ((i+1)==args.Length()) {
397 foundArg =
true; i++;
400 TString arg = args(prevComma,i-prevComma);
407 argArr.Add(
new TObjString(arg));
420 TClass *ns = (spaceName.Length()) ? TClass::GetClass(spaceName) : 0;
421 ClassInfo_t *cinfo = 0;
423 cinfo = ns->GetClassInfo();
425 cinfo = gInterpreter->ClassInfo_Factory();
430 static TypeInfo_t *
const doubletype { gInterpreter->TypeInfo_Factory(
"double") };
432 std::vector<TypeInfo_t*> proto(nargs,doubletype);
434 CallFunc_t *callfunc = gInterpreter->CallFunc_Factory();
436 gInterpreter->CallFunc_SetFuncProto(callfunc,cinfo,functionName,proto,
false,&func_offset,ROOT::kConversionMatch);
438 TMethodCall *method =
new TMethodCall(ns,callfunc,func_offset);
440 if (!ns) gInterpreter->ClassInfo_Delete(cinfo);
441 gInterpreter->CallFunc_Delete(callfunc);
443 if (method->IsValid()) {
444 if (method->ReturnType() == TMethodCall::kOther) {
457 while ( (objstr=(TObjString*)next()) ) {
458 Analyze(objstr->String(),err,offset);
461 fFunctions.Add(method);
462 fExpr[fNoper] = method->GetMethod()->GetPrototype();
463 SetAction(fNoper, kFunctionCall, fFunctions.GetLast()*1000 + nargs);
474 TString cbase(chaine);
475 Int_t args_paran = cbase.First(
"(");
480 ROOT::v5::TFormulaPrimitive *prim = ROOT::v5::TFormulaPrimitive::FindFormula(cbase, args_paran>0 ? cbase.Data() + args_paran + 1 : (
const char*)0);
481 if (prim && (!IsA()->GetBaseClass(
"TTreeFormula"))) {
486 while ( (objstr=(TObjString*)next()) ) {
487 Analyze(objstr->String(),err,offset);
if (err)
return kFALSE;
489 if (nargs!=prim->fNArguments) {
490 Error(
"Compile",
"%s requires %d arguments",
491 prim->GetName(), prim->fNArguments);
494 fExpr[fNoper] = prim->GetName();
495 if (prim->fType==10){
496 SetAction(fNoper, kFD1);
498 if (prim->fType==110){
499 SetAction(fNoper, kFD2);
501 if (prim->fType==1110){
502 SetAction(fNoper, kFD3);
504 if (prim->fType==-1){
505 SetAction(fNoper, kFDM);
506 if (fNpar<prim->fNParameters) fNpar+=prim->fNParameters;
711 void TFormula::Analyze(
const char *schain, Int_t &err, Int_t offset)
715 Int_t valeur,find,n,i,j,k,lchain,nomb,virgule,inter,nest;
716 valeur=find=n=i=j=k=lchain=nomb=virgule=inter=nest = 0;
717 Int_t compt,compt2,compt3,compt4;
722 TString s,chaine_error,chaine1ST;
723 TString s1,s2,s3,ctemp;
725 TString chaine = schain;
726 const TFormula *oldformula;
727 Int_t modulo,plus,puiss10,puiss10bis,moins,multi,divi,puiss,et,ou,petit,grand,egal,diff,peteg,grdeg,etx,oux,rshift,lshift,tercond,terelse;
729 TString slash(
"/"), escapedSlash(
"\\/");
732 Int_t actionCode,actionParam;
736 lchain = chaine.Length();
739 lchain = chaine.Length();
740 while (parenthese && lchain>0 && err==0){
744 lchain = chaine.Length();
745 if (lchain==0) err=4;
747 for (i=1; i<=lchain; ++i) {
748 if (chaine(i-1,1) ==
"\"") inString = !inString;
750 if (chaine(i-1,1) ==
"[") compt2++;
751 if (chaine(i-1,1) ==
"]") compt2--;
752 if (chaine(i-1,1) ==
"(") compt++;
753 if (chaine(i-1,1) ==
")") compt--;
755 if (compt < 0) err = 40;
756 if (compt2< 0) err = 42;
757 if (compt==0 && (i!=lchain || lchain==1)) parenthese = kFALSE;
760 if (compt > 0) err = 41;
761 if (compt2> 0) err = 43;
762 if (parenthese) chaine = chaine(1,lchain-2);
766 if (lchain==0) err=4;
767 modulo=plus=moins=multi=divi=puiss=et=ou=petit=grand=egal=diff=peteg=grdeg=etx=oux=rshift=lshift=tercond=terelse=0;
772 compt = compt2 = compt3 = compt4 = 0;puiss10=0;puiss10bis = 0;
775 Bool_t isdecimal = 1;
777 for (i=1;i<=lchain; i++) {
779 puiss10=puiss10bis=0;
782 isdecimal = isdecimal && (strchr(
"0123456789.",t)!=0);
784 if ( chaine[i-2] ==
'e' || chaine[i-2] ==
'E' ) puiss10 = 1;
785 }
else if ( strchr(
"+-/[]()&|><=!*/%^\\",t) ) {
790 if (chaine[j-2] ==
'e' || chaine[j-2] ==
'E') {
791 Bool_t isrightdecimal = 1;
793 for(k=j-3; k>=0 && isrightdecimal; --k) {
795 isrightdecimal = isrightdecimal && (strchr(
"0123456789.",t)!=0);
796 if (!isrightdecimal) {
797 if (strchr(
"+-/[]()&|><=!*/%^\\",t)!=0) {
802 if (k<0 && isrightdecimal) puiss10bis = 1;
805 if (puiss10 && (i<=lchain)) {
807 puiss10 = (strchr(
"0123456789.",t)!=0);
809 if (puiss10bis && (j<=lchain)) {
811 puiss10bis = (strchr(
"0123456789.",t)!=0);
814 if (chaine(i-1,1) ==
"\"") inString = !inString;
815 if (inString)
continue;
816 if (chaine(i-1,1) ==
"[") compt2++;
817 if (chaine(i-1,1) ==
"]") compt2--;
818 if (chaine(i-1,1) ==
"(") compt++;
819 if (chaine(i-1,1) ==
")") compt--;
820 if (chaine(j-1,1) ==
"[") compt3++;
821 if (chaine(j-1,1) ==
"]") compt3--;
822 if (chaine(j-1,1) ==
"(") compt4++;
823 if (chaine(j-1,1) ==
")") compt4--;
824 if (chaine(i-1,2)==
"&&" && !inString && compt==0 && compt2==0 && et==0) {et=i;puiss=0;}
825 if (chaine(i-1,2)==
"||" && compt==0 && compt2==0 && ou==0) {puiss10=0; ou=i;}
826 if (chaine(i-1,1)==
"&" && compt==0 && compt2==0 && etx==0) {etx=i;puiss=0;}
827 if (chaine(i-1,1)==
"|" && compt==0 && compt2==0 && oux==0) {puiss10=0; oux=i;}
828 if (chaine(i-1,2)==
">>" && compt==0 && compt2==0 && rshift==0) {puiss10=0; rshift=i;}
829 if (chaine(i-1,1)==
">" && compt==0 && compt2==0 && rshift==0 && grand==0)
830 {puiss10=0; grand=i;}
831 if (chaine(i-1,2)==
"<<" && compt==0 && compt2==0 && lshift==0) {puiss10=0; lshift=i;}
832 if (chaine(i-1,1)==
"<" && compt==0 && compt2==0 && lshift==0 && petit==0)
836 for(
int ip = i,depth=0; ip < lchain; ++ip) {
840 if (isalnum(c) || c==
'_' || c==
',')
continue;
841 if (c==
':' && chaine(ip+1)==
':') { ++ip;
continue; }
842 if (c==
'<') { ++depth;
continue; }
844 if (depth) { --depth;
continue; }
860 if ((chaine(i-1,2)==
"<=" || chaine(i-1,2)==
"=<") && compt==0 && compt2==0
861 && peteg==0) {peteg=i; puiss10=0; petit=0;}
862 if ((chaine(i-1,2)==
"=>" || chaine(i-1,2)==
">=") && compt==0 && compt2==0
863 && grdeg==0) {puiss10=0; grdeg=i; grand=0;}
864 if (chaine(i-1,2) ==
"==" && compt == 0 && compt2 == 0 && egal == 0) {puiss10=0; egal=i;}
865 if (chaine(i-1,2) ==
"!=" && compt == 0 && compt2 == 0 && diff == 0) {puiss10=0; diff=i;}
866 if (i>1 && chaine(i-1,1) ==
"+" && compt == 0 && compt2 == 0 && puiss10==0) plus=i;
867 if (chaine(j-1,1) ==
"-" && chaine(j-2,1) !=
"*" && chaine(j-2,1) !=
"/"
868 && chaine(j-2,1)!=
"^" && compt3==0 && compt4==0 && moins==0 && puiss10bis==0) moins=j;
869 if (chaine(i-1,1)==
"%" && compt==0 && compt2==0 && modulo==0) {puiss10=0; modulo=i;}
870 if (chaine(i-1,1)==
"*" && compt==0 && compt2==0 && multi==0) {puiss10=0; multi=i;}
871 if (chaine(j-1,1)==
"/" && chaine(j-2,1)!=
"\\"
872 && compt4==0 && compt3==0 && divi==0)
876 if (chaine(j-1)==
'^' && compt4==0 && compt3==0 && puiss==0) {puiss10=0; puiss=j;}
877 if (chaine(i-1)==
'?' && compt == 0 && compt2 == 0 && tercond == 0) {puiss10=0; tercond=i;}
878 if (chaine(i-1)==
':' && tercond && compt == 0 && compt2 == 0 && terelse == 0) {
879 if (i>2 && chaine(i-2)!=
':' && chaine(i)!=
':') {
880 puiss10=0; terelse=i;
890 if (tercond && terelse) {
891 if (tercond == 1 || terelse == lchain || tercond == (terelse-1) ) {
896 ctemp = chaine(0,tercond-1);
897 Analyze(ctemp.Data(),err,offset);
if (err)
return;
899 fExpr[fNoper] =
"?: condition jump";
900 actionCode = kJumpIf;
902 SetAction(fNoper,actionCode, actionParam);
903 Int_t optloc = fNoper++;
906 ctemp = chaine(tercond,terelse-tercond-1);
907 Analyze(ctemp.Data(),err,offset);
if (err)
return;
908 actionParam = fNoper;
909 SetAction(optloc, actionCode, actionParam);
911 fExpr[fNoper] =
"?: else jump";
915 SetAction(fNoper,actionCode, actionParam);
919 ctemp = chaine(terelse,lchain-terelse);
920 Analyze(ctemp.Data(),err,offset);
if (err)
return;
922 actionParam = fNoper - 1;
923 SetAction(optloc, actionCode, actionParam);
925 if (IsString(optloc-1) != IsString(fNoper-1)) {
930 }
else if (ou != 0) {
931 if (ou==1 || ou==lchain-1) {
936 ctemp = chaine(0,ou-1);
937 Analyze(ctemp.Data(),err,offset);
if (err)
return;
939 fExpr[fNoper] =
"|| checkpoint";
940 actionCode = kBoolOptimize;
942 SetAction(fNoper,actionCode, actionParam);
943 Int_t optloc = fNoper++;
945 ctemp = chaine(ou+1,lchain-ou-1);
946 Analyze(ctemp.Data(),err,offset);
if (err)
return;
947 fExpr[fNoper] =
"||";
949 SetAction(fNoper,actionCode, 0);
951 SetAction( optloc, GetAction(optloc), GetActionParam(optloc) + (fNoper-optloc) * 10);
953 if (!CheckOperands(optloc-1,fNoper-1,err))
return;
956 if (et==1 || et==lchain-1) {
961 ctemp = chaine(0,et-1);
962 Analyze(ctemp.Data(),err,offset);
if (err)
return;
964 fExpr[fNoper] =
"&& checkpoint";
965 actionCode = kBoolOptimize;
967 SetAction(fNoper,actionCode,actionParam);
969 Int_t optloc = fNoper++;
971 ctemp = chaine(et+1,lchain-et-1);
972 Analyze(ctemp.Data(),err,offset);
if (err)
return;
973 fExpr[fNoper] =
"&&";
975 SetAction(fNoper,actionCode,0);
977 SetAction(optloc, GetAction(optloc), GetActionParam(optloc) + (fNoper-optloc) * 10);
979 if (!CheckOperands(optloc-1,fNoper-1,err))
return;
982 if (oux==1 || oux==lchain) {
987 ctemp = chaine(0,oux-1);
988 Analyze(ctemp.Data(),err,offset);
if (err)
return;
989 UInt_t leftopr = fNoper-1;
990 ctemp = chaine(oux,lchain-oux);
991 Analyze(ctemp.Data(),err,offset);
if (err)
return;
994 SetAction(fNoper,actionCode,actionParam);
996 if (!CheckOperands(leftopr,fNoper-1,err))
return;
999 if (etx==1 || etx==lchain) {
1004 ctemp = chaine(0,etx-1);
1005 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1006 UInt_t leftopr = fNoper-1;
1007 ctemp = chaine(etx,lchain-etx);
1008 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1009 fExpr[fNoper] =
"&";
1010 actionCode = kBitAnd;
1011 SetAction(fNoper,actionCode,actionParam);
1013 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1015 }
else if (petit != 0) {
1016 if (petit==1 || petit==lchain) {
1021 ctemp = chaine(0,petit-1);
1022 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1023 UInt_t leftopr = fNoper-1;
1024 ctemp = chaine(petit,lchain-petit);
1025 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1026 fExpr[fNoper] =
"<";
1028 SetAction(fNoper,actionCode,actionParam);
1030 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1032 }
else if (grand != 0) {
1033 if (grand==1 || grand==lchain) {
1038 ctemp = chaine(0,grand-1);
1039 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1040 UInt_t leftopr = fNoper-1;
1041 ctemp = chaine(grand,lchain-grand);
1042 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1043 fExpr[fNoper] =
">";
1044 actionCode = kGreater;
1045 SetAction(fNoper,actionCode,actionParam);
1047 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1049 }
else if (peteg != 0) {
1050 if (peteg==1 || peteg==lchain-1) {
1055 ctemp = chaine(0,peteg-1);
1056 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1057 ctemp = chaine(peteg+1,lchain-peteg-1);
1058 UInt_t leftopr = fNoper-1;
1059 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1060 fExpr[fNoper] =
"<=";
1061 actionCode = kLessThan;
1062 SetAction(fNoper,actionCode,actionParam);
1064 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1066 }
else if (grdeg != 0) {
1067 if (grdeg==1 || grdeg==lchain-1) {
1072 ctemp = chaine(0,grdeg-1);
1073 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1074 UInt_t leftopr = fNoper-1;
1075 ctemp = chaine(grdeg+1,lchain-grdeg-1);
1076 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1077 fExpr[fNoper] =
">=";
1078 actionCode = kGreaterThan;
1079 SetAction(fNoper,actionCode,actionParam);
1081 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1083 }
else if (egal != 0) {
1084 if (egal==1 || egal==lchain-1) {
1089 ctemp = chaine(0,egal-1);
1090 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1091 Int_t optloc = fNoper-1;
1093 ctemp = chaine(egal+1,lchain-egal-1);
1094 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1095 fExpr[fNoper] =
"==";
1096 actionCode = kEqual;
1098 Bool_t isstring = IsString(fNoper-1);
1099 if (IsString(optloc) != isstring) {
1101 chaine_error =
"==";
1102 }
else if (isstring) {
1103 actionCode = kStringEqual;
1105 SetAction(fNoper,actionCode,actionParam);
1108 }
else if (diff != 0) {
1109 if (diff==1 || diff==lchain-1) {
1111 chaine_error =
"!=";
1114 ctemp = chaine(0,diff-1);
1115 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1116 Int_t optloc = fNoper-1;
1118 ctemp = chaine(diff+1,lchain-diff-1);
1119 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1120 fExpr[fNoper] =
"!=";
1121 actionCode = kNotEqual;
1123 Bool_t isstring = IsString(fNoper-1);
1124 if (IsString(optloc) != isstring) {
1126 chaine_error =
"!=";
1127 }
else if (isstring) {
1128 actionCode = kStringNotEqual;
1130 SetAction(fNoper,actionCode,actionParam);
1133 }
else if (plus != 0) {
1139 ctemp = chaine(0,plus-1);
1140 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1141 UInt_t leftopr = fNoper-1;
1142 ctemp = chaine(plus,lchain-plus);
1143 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1144 fExpr[fNoper] =
"+";
1146 SetAction(fNoper,actionCode,actionParam);
1148 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1153 ctemp = chaine(moins,lchain-moins);
1154 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1155 fExpr[fNoper] =
"-";
1156 actionCode = kSignInv;
1157 SetAction(fNoper,actionCode,actionParam);
1159 if (!CheckOperands(fNoper-1,err))
return;
1161 if (moins == lchain) {
1165 ctemp = chaine(0,moins-1);
1166 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1167 UInt_t leftopr = fNoper-1;
1168 ctemp = chaine(moins,lchain-moins);
1169 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1170 fExpr[fNoper] =
"-";
1171 actionCode = kSubstract;
1172 SetAction(fNoper,actionCode,actionParam);
1174 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1177 }
else if (modulo != 0) {
1178 if (modulo == 1 || modulo == lchain) {
1182 ctemp = chaine(0,modulo-1);
1183 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1184 UInt_t leftopr = fNoper-1;
1185 ctemp = chaine(modulo,lchain-modulo);
1186 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1187 fExpr[fNoper] =
"%";
1188 actionCode = kModulo;
1189 SetAction(fNoper,actionCode,actionParam);
1191 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1193 }
else if (rshift != 0) {
1194 if (rshift == 1 || rshift == lchain) {
1198 ctemp = chaine(0,rshift-1);
1199 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1200 UInt_t leftopr = fNoper-1;
1201 ctemp = chaine(rshift+1,lchain-rshift-1);
1202 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1203 fExpr[fNoper] =
">>";
1204 actionCode = kRightShift;
1205 SetAction(fNoper,actionCode,actionParam);
1207 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1209 }
else if (lshift != 0) {
1210 if (lshift == 1 || lshift == lchain) {
1214 ctemp = chaine(0,lshift-1);
1215 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1216 UInt_t leftopr = fNoper-1;
1217 ctemp = chaine(lshift+1,lchain-lshift-1);
1218 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1219 fExpr[fNoper] =
">>";
1220 actionCode = kLeftShift;
1221 SetAction(fNoper,actionCode,actionParam);
1223 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1227 if (multi == 1 || multi == lchain) {
1232 ctemp = chaine(0,multi-1);
1233 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1234 UInt_t leftopr = fNoper-1;
1235 ctemp = chaine(multi,lchain-multi);
1236 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1237 fExpr[fNoper] =
"*";
1238 actionCode = kMultiply;
1239 SetAction(fNoper,actionCode,actionParam);
1241 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1245 if (divi == 1 || divi == lchain) {
1250 ctemp = chaine(0,divi-1);
1251 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1252 UInt_t leftopr = fNoper-1;
1253 ctemp = chaine(divi,lchain-divi);
1254 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1255 fExpr[fNoper] =
"/";
1256 actionCode = kDivide;
1257 SetAction(fNoper,actionCode,actionParam);
1259 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1263 if (puiss == 1 || puiss == lchain) {
1265 chaine_error =
"**";
1268 if (chaine(lchain-2,2) ==
"^2") {
1269 ctemp =
"sq(" + chaine(0,lchain-2) +
")";
1270 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1272 ctemp = chaine(0,puiss-1);
1273 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1274 UInt_t leftopr = fNoper-1;
1275 ctemp = chaine(puiss,lchain-puiss);
1276 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1277 fExpr[fNoper] =
"^";
1279 SetAction(fNoper,actionCode,actionParam);
1281 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1290 Bool_t hasDot = kFALSE;
1291 Bool_t isHexa = kFALSE;
1292 Bool_t hasExpo= kFALSE;
1293 if ((chaine(0,2)==
"0x")||(chaine(0,2)==
"0X")) isHexa=kTRUE;
1294 for (j=0; j<chaine.Length() && err==0; j++) {
1297 if (j>0 && (chaine(j,1)==
"e" || chaine(j,2)==
"e+" || chaine(j,2)==
"e-" || chaine(j,1)==
"E" || chaine(j,2)==
"E+" || chaine(j,2)==
"E-")) {
1300 chaine_error=chaine;
1307 if (chaine(j,2)==
"e+" || chaine(j,2)==
"e-" || chaine(j,2)==
"E+" || chaine(j,2)==
"E-") j++;
1310 if (chaine(j,1) ==
"." && !hasDot) hasDot = kTRUE;
1315 if (!strchr(
"0123456789",t) && (chaine(j,1)!=
"+" || j!=0)) {
1317 chaine_error=chaine;
1323 if (!strchr(
"0123456789abcdefABCDEF",t) && (j>1)) {
1325 chaine_error=chaine;
1329 if (fNconst >= gMAXCONST) err = 27;
1331 if (!isHexa) {
if (sscanf((
const char*)chaine,
"%lg",&vafConst) > 0) err = 0;
else err =1;}
1332 else {
if (sscanf((
const char*)chaine,
"%lx",&vafConst2) > 0) err = 0;
else err=1;
1333 vafConst = (Double_t) vafConst2;}
1334 fExpr[fNoper] = chaine;
1336 for (j=0;j<fNconst;j++) {
1337 if (vafConst == fConst[j] ) k= j;
1339 if ( k < 0) { k = fNconst; fNconst++; fConst[k] = vafConst; }
1340 actionCode = kConstant;
1342 SetAction(fNoper,actionCode,actionParam);
1353 R__LOCKGUARD(gROOTMutex);
1354 oldformula = (
const TFormula*)gROOT->GetListOfFunctions()->FindObject((
const char*)chaine);
1356 if (oldformula && strcmp(schain,oldformula->GetTitle())) {
1357 Int_t nprior = fNpar;
1358 Analyze(oldformula->GetExpFormula(),err,fNpar);
1360 if (oldformula->IsNormalized()) SetBit(kNormalized);
1365 Int_t npold = oldformula->GetNpar();
1367 for (Int_t ipar=0;ipar<npold;ipar++) {
1368 fParams[ipar+fNpar-npold] = oldformula->GetParameter(ipar);
1379 ctemp.ReplaceAll(escapedSlash, slash);
1381 k = DefinedVariable(ctemp,action);
1387 chaine_error = ctemp;
1388 }
else if ( k >= 0 ) {
1389 fExpr[fNoper] = ctemp;
1390 actionCode = action;
1392 SetAction(fNoper,actionCode,actionParam);
1393 if (action==kDefinedString) fNstring++;
1394 else if (k <kMAXFOUND && !fAlreadyFound.TestBitNumber(k)) {
1395 fAlreadyFound.SetBitNumber(k);
1399 }
else if (chaine(0,1) ==
"!") {
1400 ctemp = chaine(1,lchain-1);
1401 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1402 fExpr[fNoper] =
"!";
1404 SetAction(fNoper,actionCode,actionParam);
1406 if (!CheckOperands(fNoper-1,err))
return;
1407 }
else if (chaine(0,1)==
"\"" && chaine(chaine.Length()-1,1)==
"\"") {
1409 fExpr[fNoper] = chaine(1,chaine.Length()-2);
1410 actionCode = kStringConst;
1411 SetAction(fNoper,actionCode,actionParam);
1413 }
else if (chaine(0,4) ==
"cos(") {
1414 ctemp = chaine(3,lchain-3);
1415 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1416 fExpr[fNoper] =
"cos";
1418 SetAction(fNoper,actionCode,actionParam);
1420 if (!CheckOperands(fNoper-1,err))
return;
1421 }
else if (chaine(0,4) ==
"sin(") {
1422 ctemp = chaine(3,lchain-3);
1423 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1424 fExpr[fNoper] =
"sin";
1426 SetAction(fNoper,actionCode,actionParam);
1428 if (!CheckOperands(fNoper-1,err))
return;
1429 }
else if (chaine(0,4) ==
"tan(") {
1430 ctemp = chaine(3,lchain-3);
1431 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1432 fExpr[fNoper] =
"tan";
1434 SetAction(fNoper,actionCode,actionParam);
1436 if (!CheckOperands(fNoper-1,err))
return;
1437 }
else if (chaine(0,5) ==
"acos(") {
1438 ctemp = chaine(4,lchain-4);
1439 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1440 fExpr[fNoper] =
"acos";
1442 SetAction(fNoper,actionCode,actionParam);
1444 if (!CheckOperands(fNoper-1,err))
return;
1445 }
else if (chaine(0,5) ==
"asin(") {
1446 ctemp = chaine(4,lchain-4);
1447 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1448 fExpr[fNoper] =
"asin";
1450 SetAction(fNoper,actionCode,actionParam);
1452 if (!CheckOperands(fNoper-1,err))
return;
1453 }
else if (chaine(0,5) ==
"atan(") {
1454 ctemp = chaine(4,lchain-4);
1455 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1456 fExpr[fNoper] =
"atan";
1458 SetAction(fNoper,actionCode,actionParam);
1460 if (!CheckOperands(fNoper-1,err))
return;
1461 }
else if (chaine(0,5) ==
"cosh(") {
1462 ctemp = chaine(4,lchain-4);
1463 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1464 fExpr[fNoper] =
"cosh";
1466 SetAction(fNoper,actionCode,actionParam);
1468 if (!CheckOperands(fNoper-1,err))
return;
1469 }
else if (chaine(0,5) ==
"sinh(") {
1470 ctemp = chaine(4,lchain-4);
1471 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1472 fExpr[fNoper] =
"sinh";
1474 SetAction(fNoper,actionCode,actionParam);
1476 if (!CheckOperands(fNoper-1,err))
return;
1477 }
else if (chaine(0,5) ==
"tanh(") {
1478 ctemp = chaine(4,lchain-4);
1479 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1480 fExpr[fNoper] =
"tanh";
1482 SetAction(fNoper,actionCode,actionParam);
1484 if (!CheckOperands(fNoper-1,err))
return;
1485 }
else if (chaine(0,6) ==
"acosh(") {
1486 ctemp = chaine(5,lchain-5);
1487 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1488 fExpr[fNoper] =
"acosh";
1489 actionCode = kacosh;
1490 SetAction(fNoper,actionCode,actionParam);
1492 if (!CheckOperands(fNoper-1,err))
return;
1493 }
else if (chaine(0,6) ==
"asinh(") {
1494 ctemp = chaine(5,lchain-5);
1495 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1496 fExpr[fNoper] =
"asinh";
1497 actionCode = kasinh;
1498 SetAction(fNoper,actionCode,actionParam);
1500 if (!CheckOperands(fNoper-1,err))
return;
1501 }
else if (chaine(0,6) ==
"atanh(") {
1502 ctemp = chaine(5,lchain-5);
1503 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1504 fExpr[fNoper] =
"atanh";
1505 actionCode = katanh;
1506 SetAction(fNoper,actionCode,actionParam);
1508 if (!CheckOperands(fNoper-1,err))
return;
1509 }
else if (chaine(0,3) ==
"sq(") {
1510 ctemp = chaine(2,lchain-2);
1511 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1512 fExpr[fNoper] =
"sq";
1514 SetAction(fNoper,actionCode,actionParam);
1516 if (!CheckOperands(fNoper-1,err))
return;
1517 }
else if (chaine(0,4) ==
"log(") {
1518 ctemp = chaine(3,lchain-3);
1519 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1520 fExpr[fNoper] =
"log";
1522 SetAction(fNoper,actionCode,actionParam);
1524 if (!CheckOperands(fNoper-1,err))
return;
1525 }
else if (chaine(0,6) ==
"log10(") {
1526 ctemp = chaine(5,lchain-5);
1527 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1528 fExpr[fNoper] =
"log10";
1529 actionCode = klog10;
1530 SetAction(fNoper,actionCode,actionParam);
1532 if (!CheckOperands(fNoper-1,err))
return;
1533 }
else if (chaine(0,4) ==
"exp(") {
1534 ctemp = chaine(3,lchain-3);
1535 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1536 fExpr[fNoper] =
"exp";
1538 SetAction(fNoper,actionCode,actionParam);
1540 if (!CheckOperands(fNoper-1,err))
return;
1541 }
else if (chaine(0,4) ==
"abs(") {
1542 ctemp = chaine(3,lchain-3);
1543 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1544 fExpr[fNoper] =
"abs";
1546 SetAction(fNoper,actionCode,actionParam);
1548 if (!CheckOperands(fNoper-1,err))
return;
1549 }
else if (chaine(0,5) ==
"sign(") {
1550 ctemp = chaine(4,lchain-4);
1551 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1552 fExpr[fNoper] =
"sign";
1554 SetAction(fNoper,actionCode,actionParam);
1556 if (!CheckOperands(fNoper-1,err))
return;
1557 }
else if (chaine(0,4) ==
"int(") {
1558 ctemp = chaine(3,lchain-3);
1559 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1560 fExpr[fNoper] =
"int";
1562 SetAction(fNoper,actionCode,actionParam);
1564 if (!CheckOperands(fNoper-1,err))
return;
1565 }
else if (chaine ==
"rndm" || chaine(0,5) ==
"rndm(") {
1566 fExpr[fNoper] =
"rndm";
1568 SetAction(fNoper,actionCode,actionParam);
1570 }
else if (chaine(0,5) ==
"sqrt(") {
1571 ctemp = chaine(4,lchain-4);
1572 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1573 fExpr[fNoper] =
"sqrt";
1575 SetAction(fNoper,actionCode,actionParam);
1577 if (!CheckOperands(fNoper-1,err))
return;
1581 }
else if ( chaine ==
"expo" || chaine(0,5)==
"expo("
1582 || (lchain==5 && chaine(1,4)==
"expo")
1583 || (lchain==6 && chaine(2,4)==
"expo")
1584 || chaine(1,5)==
"expo(" || chaine(2,5)==
"expo(" ) {
1586 if (chaine(1,4) ==
"expo") {
1590 if (fNdim < 1) fNdim = 1; }
1591 else if (ctemp==
"y") {
1593 if (fNdim < 2) fNdim = 2; }
1594 else if (ctemp==
"z") {
1596 if (fNdim < 3) fNdim = 3; }
1597 else if (ctemp==
"t") {
1599 if (fNdim < 4) fNdim = 4; }
1602 chaine_error=chaine1ST;
1604 chaine=chaine(1,lchain-1);
1605 lchain=chaine.Length();
1607 if (chaine(2,4) ==
"expo") {
1608 if (chaine(0,2) !=
"xy") {
1610 chaine_error=chaine1ST;
1614 if (fNdim < 2) fNdim = 2;
1615 chaine=chaine(2,lchain-2);
1616 lchain=chaine.Length();
1620 if (fNpar>=gMAXPAR) err=7;
1622 fExpr[fNoper] = chaine1ST;
1623 actionCode = kexpo + inter2;
1624 actionParam = offset;
1625 SetAction(fNoper,actionCode,actionParam);
1626 if (inter2 == 5+offset && fNpar < 3+offset) fNpar = 3+offset;
1627 if (fNpar < 2+offset) fNpar = 2+offset;
1628 if (fNpar>=gMAXPAR) err=7;
1631 if (fNdim < 1) fNdim = 1;
1632 if (fNpar == 2) SetNumber(200);
1635 }
else if (chaine(4,1) ==
"(") {
1636 ctemp = chaine(5,lchain-6);
1637 fExpr[fNoper] = chaine1ST;
1638 for (j=0; j<ctemp.Length(); j++) {
1640 if (strchr(
"0123456789",t)==0 && (ctemp(j,1)!=
"+" || j!=0)) {
1642 chaine_error=chaine1ST;
1646 sscanf(ctemp.Data(),
"%d",&inter);
1649 actionCode = kexpo + inter2;
1650 actionParam = inter;
1651 SetAction(fNoper,actionCode,actionParam);
1652 if (inter2 == 5) inter++;
1653 if (inter+2>fNpar) fNpar = inter+2;
1654 if (fNpar>=gMAXPAR) err=7;
1656 if (fNpar == 2) SetNumber(200);
1661 chaine_error=chaine;
1666 }
else if (chaine==
"gaus"
1667 || (lchain==5 && chaine(1,4)==
"gaus")
1668 || (lchain==6 && chaine(2,4)==
"gaus")
1669 || chaine(0,5)==
"gaus(" || chaine(1,5)==
"gaus(" || chaine(2,5)==
"gaus(") {
1671 if (chaine(1,4) ==
"gaus") {
1675 if (fNdim < 1) fNdim = 1; }
1676 else if (ctemp==
"y") {
1678 if (fNdim < 2) fNdim = 2; }
1679 else if (ctemp==
"z") {
1681 if (fNdim < 3) fNdim = 3; }
1682 else if (ctemp==
"t") {
1684 if (fNdim < 4) fNdim = 4; }
1687 chaine_error=chaine1ST;
1689 chaine=chaine(1,lchain-1);
1690 lchain=chaine.Length();
1692 if (chaine(2,4) ==
"gaus") {
1693 if (chaine(0,2) !=
"xy") {
1695 chaine_error=chaine1ST;
1699 if (fNdim < 2) fNdim = 2;
1700 chaine=chaine(2,lchain-2);
1701 lchain=chaine.Length();
1705 if (lchain == 4 && err==0) {
1706 if (fNpar>=gMAXPAR) err=7;
1708 fExpr[fNoper] = chaine1ST;
1709 actionCode = kgaus + inter2;
1710 actionParam = offset;
1711 SetAction(fNoper,actionCode,actionParam);
1712 if (inter2 == 5+offset && fNpar < 5+offset) fNpar = 5+offset;
1713 if (3+offset>fNpar) fNpar = 3+offset;
1714 if (fNpar>=gMAXPAR) err=7;
1717 if (fNdim < 1) fNdim = 1;
1718 if (fNpar == 3) SetNumber(100);
1721 }
else if (chaine(4,1) ==
"(" && err==0) {
1722 ctemp = chaine(5,lchain-6);
1723 fExpr[fNoper] = chaine1ST;
1724 for (j=0; j<ctemp.Length(); j++) {
1726 if (strchr(
"0123456789",t)==0 && (ctemp(j,1)!=
"+" || j!=0)) {
1728 chaine_error=chaine1ST;
1732 sscanf(ctemp.Data(),
"%d",&inter);
1735 actionCode = kgaus + inter2;
1736 actionParam = inter;
1737 SetAction(fNoper,actionCode,actionParam);
1738 if (inter2 == 5) inter += 2;
1739 if (inter+3>fNpar) fNpar = inter+3;
1740 if (fNpar>=gMAXPAR) err=7;
1742 if(fNpar == 3) SetNumber(100);
1745 }
else if (err==0) {
1747 chaine_error=chaine1ST;
1752 }
else if (chaine==
"landau" || (lchain==7 && chaine(1,6)==
"landau")
1753 || (lchain==8 && chaine(2,6)==
"landau")
1754 || chaine(0,7)==
"landau(" || chaine(1,7)==
"landau(" || chaine(2,7)==
"landau(") {
1756 if (chaine(1,6) ==
"landau") {
1760 if (fNdim < 1) fNdim = 1; }
1761 else if (ctemp==
"y") {
1763 if (fNdim < 2) fNdim = 2; }
1764 else if (ctemp==
"z") {
1766 if (fNdim < 3) fNdim = 3; }
1767 else if (ctemp==
"t") {
1769 if (fNdim < 4) fNdim = 4; }
1772 chaine_error=chaine1ST;
1774 chaine=chaine(1,lchain-1);
1775 lchain=chaine.Length();
1777 if (chaine(2,6) ==
"landau") {
1778 if (chaine(0,2) !=
"xy") {
1780 chaine_error=chaine1ST;
1784 if (fNdim < 2) fNdim = 2;
1785 chaine=chaine(2,lchain-2);
1786 lchain=chaine.Length();
1790 if (lchain == 6 && err==0) {
1791 if (fNpar>=gMAXPAR) err=7;
1793 fExpr[fNoper] = chaine1ST;
1794 actionCode = klandau + inter2;
1795 actionParam = offset;
1796 SetAction(fNoper,actionCode,actionParam);
1797 if (inter2 == 5+offset && fNpar < 5+offset) fNpar = 5+offset;
1798 if (3+offset>fNpar) fNpar = 3+offset;
1799 if (fNpar>=gMAXPAR) err=7;
1802 if (fNdim < 1) fNdim = 1;
1803 if (fNpar == 3) SetNumber(400);
1806 }
else if (chaine(6,1) ==
"(" && err==0) {
1807 ctemp = chaine(7,lchain-8);
1808 fExpr[fNoper] = chaine1ST;
1809 for (j=0; j<ctemp.Length(); j++) {
1811 if (strchr(
"0123456789",t)==0 && (ctemp(j,1)!=
"+" || j!=0)) {
1813 chaine_error=chaine1ST;
1817 sscanf(ctemp.Data(),
"%d",&inter);
1820 actionCode = klandau + inter2;
1821 actionParam = inter;
1822 SetAction(fNoper,actionCode,actionParam);
1823 if (inter2 == 5) inter += 2;
1824 if (inter+3>fNpar) fNpar = inter+3;
1825 if (fNpar>=gMAXPAR) err=7;
1827 if (fNpar == 3) SetNumber(400);
1830 }
else if (err==0) {
1832 chaine_error=chaine1ST;
1837 }
else if (chaine(0,3) ==
"pol" || chaine(1,3) ==
"pol") {
1839 if (chaine(1,3) ==
"pol") {
1843 if (fNdim < 1) fNdim = 1; }
1844 else if (ctemp==
"y") {
1846 if (fNdim < 2) fNdim = 2; }
1847 else if (ctemp==
"z") {
1849 if (fNdim < 3) fNdim = 3; }
1850 else if (ctemp==
"t") {
1852 if (fNdim < 4) fNdim = 4; }
1855 chaine_error=chaine1ST;
1857 chaine=chaine(1,lchain-1);
1858 lchain=chaine.Length();
1860 if (chaine(lchain-1,1) ==
")") {
1862 for (j=3;j<lchain;j++)
if (chaine(j,1)==
"(" && nomb == 0) nomb = j;
1863 if (nomb == 3) err = 23;
1864 if (nomb == 0) err = 40;
1865 ctemp = chaine(nomb+1,lchain-nomb-2);
1866 for (j=0; j<ctemp.Length(); j++) {
1868 if (strchr(
"0123456789",t)==0 && (ctemp(j,1)!=
"+" || j!=0)) {
1870 chaine_error=chaine1ST;
1874 sscanf(ctemp.Data(),
"%d",&inter);
1875 if (inter < 0) err = 20;
1884 ctemp = chaine(3,nomb-3);
1885 if (sscanf(ctemp.Data(),
"%d",&n) > 0) {
1886 if (n < 0 ) err = 24;
1887 if (n >= 20) err = 25;
1891 fExpr[fNoper] = chaine1ST;
1892 actionCode = kpol+(inter2-1);
1893 actionParam = n*100+inter+2;
1894 SetAction(fNoper,actionCode,actionParam);
1895 if (inter+n+1>=fNpar) fNpar = inter + n + 2;
1896 if (fNpar>=gMAXPAR) err=7;
1899 if (fNdim < 1) fNdim = 1;
1906 }
else if (chaine(0,4) ==
"pow(") {
1907 compt = 4; nomb = 0; virgule = 0; nest=0;
1908 while(compt != lchain) {
1910 if (chaine(compt-1,1) ==
"(") nest++;
1911 else if (chaine(compt-1,1) ==
")") nest--;
1912 else if (chaine(compt-1,1) ==
"," && nest==0) {
1914 if (nomb == 1 && virgule == 0) virgule = compt;
1917 if (nomb != 1) err = 22;
1919 ctemp = chaine(4,virgule-5);
1920 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1921 UInt_t leftopr = fNoper-1;
1922 ctemp = chaine(virgule,lchain-virgule-1);
1923 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1924 fExpr[fNoper] =
"^";
1926 SetAction(fNoper,actionCode,actionParam);
1928 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1930 }
else if (chaine(0,7) ==
"strstr(") {
1931 compt = 7; nomb = 0; virgule = 0; nest=0;
1933 while(compt != lchain) {
1935 if (chaine(compt-1,1) ==
"\"") {
1936 inString = !inString;
1937 }
else if (!inString) {
1938 if (chaine(compt-1,1) ==
"(") nest++;
1939 else if (chaine(compt-1,1) ==
")") nest--;
1940 else if (chaine(compt-1,1) ==
"," && nest==0) {
1942 if (nomb == 1 && virgule == 0) virgule = compt;
1946 if (nomb != 1) err = 28;
1948 ctemp = chaine(7,virgule-8);
1949 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1950 Int_t optloc = fNoper-1;
1952 ctemp = chaine(virgule,lchain-virgule-1);
1953 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1954 fExpr[fNoper] =
"strstr";
1955 actionCode = kstrstr;
1956 SetAction(fNoper,actionCode,actionParam);
1959 if ( !IsString(optloc) || !IsString(fNoper-2) ) {
1961 chaine_error =
"strstr";
1964 }
else if (chaine(0,4) ==
"min(") {
1965 compt = 4; nomb = 0; virgule = 0; nest=0;
1966 while(compt != lchain) {
1968 if (chaine(compt-1,1) ==
"(") nest++;
1969 else if (chaine(compt-1,1) ==
")") nest--;
1970 else if (chaine(compt-1,1) ==
"," && nest==0) {
1972 if (nomb == 1 && virgule == 0) virgule = compt;
1980 ctemp = chaine(4,virgule-5);
1981 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1982 UInt_t leftopr = fNoper-1;
1983 ctemp = chaine(virgule,lchain-virgule-1);
1984 Analyze(ctemp.Data(),err,offset);
if (err)
return;
1985 fExpr[fNoper] =
"min";
1987 SetAction(fNoper,actionCode,actionParam);
1989 if (!CheckOperands(leftopr,fNoper-1,err))
return;
1991 }
else if (chaine(0,4) ==
"max(") {
1992 compt = 4; nomb = 0; virgule = 0; nest=0;
1993 while(compt != lchain) {
1995 if (chaine(compt-1,1) ==
"(") nest++;
1996 else if (chaine(compt-1,1) ==
")") nest--;
1997 else if (chaine(compt-1,1) ==
"," && nest==0) {
1999 if (nomb == 1 && virgule == 0) virgule = compt;
2007 ctemp = chaine(4,virgule-5);
2008 Analyze(ctemp.Data(),err,offset);
if (err)
return;
2009 UInt_t leftopr = fNoper-1;
2010 ctemp = chaine(virgule,lchain-virgule-1);
2011 Analyze(ctemp.Data(),err,offset);
if (err)
return;
2012 fExpr[fNoper] =
"max";
2014 SetAction(fNoper,actionCode,actionParam);
2016 if (!CheckOperands(leftopr,fNoper-1,err))
return;
2019 }
else if (chaine(0,6) ==
"atan2(") {
2020 compt = 6; nomb = 0; virgule = 0; nest=0;
2021 while(compt != lchain) {
2023 if (chaine(compt-1,1) ==
"(") nest++;
2024 else if (chaine(compt-1,1) ==
")") nest--;
2025 else if (chaine(compt-1,1) ==
"," && nest==0) {
2027 if (nomb == 1 && virgule == 0) virgule = compt;
2030 if (nomb != 1) err = 21;
2032 ctemp = chaine(6,virgule-7);
2033 Analyze(ctemp.Data(),err,offset);
if (err)
return;
2034 UInt_t leftopr = fNoper-1;
2035 ctemp = chaine(virgule,lchain-virgule-1);
2036 Analyze(ctemp.Data(),err,offset);
if (err)
return;
2037 fExpr[fNoper] =
"atan2";
2038 actionCode = katan2;
2039 SetAction(fNoper,actionCode,actionParam);
2041 if (!CheckOperands(leftopr,fNoper-1,err))
return;
2043 }
else if (chaine(0,5) ==
"fmod(") {
2044 compt = 5; nomb = 0; virgule = 0; nest=0;
2045 while(compt != lchain) {
2047 if (chaine(compt-1,1) ==
"(") nest++;
2048 else if (chaine(compt-1,1) ==
")") nest--;
2049 else if (chaine(compt-1,1) ==
"," && nest==0) {
2051 if (nomb == 1 && virgule == 0) virgule = compt;
2059 ctemp = chaine(5,virgule-6);
2060 Analyze(ctemp.Data(),err,offset);
if (err)
return;
2061 UInt_t leftopr = fNoper-1;
2062 ctemp = chaine(virgule,lchain-virgule-1);
2063 Analyze(ctemp.Data(),err,offset);
if (err)
return;
2064 fExpr[fNoper] =
"fmod";
2066 SetAction(fNoper,actionCode,actionParam);
2068 if (!CheckOperands(leftopr,fNoper-1,err))
return;
2070 }
else if (AnalyzeFunction(chaine,err,offset) || err) {
2072 chaine_error = chaine;
2078 }
else if (chaine(0,1) ==
"[" && chaine(lchain-1,1) ==
"]") {
2079 fExpr[fNoper] = chaine;
2081 ctemp = chaine(1,lchain-2);
2082 for (j=0; j<ctemp.Length(); j++) {
2084 if (strchr(
"0123456789",t)==0 && (ctemp(j,1)!=
"+" || j!=0)) {
2086 chaine_error=chaine1ST;
2090 sscanf(ctemp.Data(),
"%d",&valeur);
2091 actionCode = kParameter;
2092 actionParam = offset + valeur;
2093 SetAction(fNoper-1, actionCode, actionParam);
2094 fExpr[fNoper-1] =
"[";
2095 fExpr[fNoper-1] = (fExpr[fNoper-1] + (
long int)(valeur+offset)) +
"]";
2097 }
else if (chaine ==
"pi") {
2098 fExpr[fNoper] =
"pi";
2100 SetAction(fNoper,actionCode,actionParam);
2117 if (fNoper>=gMAXOP) err=6;
2124 chaine_error =
"\""+chaine_error+
"\"";
2126 case 2 : er =
" Invalid Floating Point Operation";
break;
2127 case 4 : er =
" Empty String";
break;
2128 case 5 : er =
" Invalid Syntax " + chaine_error;
break;
2129 case 6 : er =
" Too many operators !";
break;
2130 case 7 : er =
" Too many parameters !";
break;
2131 case 10 : er =
" z specified but not x and y";
break;
2132 case 11 : er =
" z and y specified but not x";
break;
2133 case 12 : er =
" y specified but not x";
break;
2134 case 13 : er =
" z and x specified but not y";
break;
2135 case 20 : er =
" Non integer value for parameter number : " + chaine_error;
break;
2136 case 21 : er =
" ATAN2 requires two arguments";
break;
2137 case 22 : er =
" POW requires two arguments";
break;
2138 case 23 : er =
" Degree of polynomial not specified";
break;
2139 case 24 : er =
" Degree of polynomial must be positive";
break;
2140 case 25 : er =
" Degree of polynomial must be less than 20";
break;
2141 case 26 : er =
" Unknown name : " + chaine_error;
break;
2142 case 27 : er =
" Too many constants in expression";
break;
2143 case 28 : er =
" strstr requires two arguments";
break;
2144 case 29 : er =
" TFormula can only call interpreted and compiled functions that return a numerical type: " + chaine_error;
break;
2145 case 30 : er =
" Bad numerical expression : " + chaine_error;
break;
2146 case 31 : er =
" Part of the Variable " + chaine_error; er +=
" exists but some of it is not accessible or useable";
break;
2147 case 40 : er =
" '(' is expected";
break;
2148 case 41 : er =
" ')' is expected";
break;
2149 case 42 : er =
" '[' is expected";
break;
2150 case 43 : er =
" ']' is expected";
break;
2151 case 44 : er =
" The function '" + chaine(0,err_hint) +
"' requires two arguments.";
break;
2152 case 45 : er =
"The operator " + chaine_error +
" requires a numerical operand.";
break;
2153 case 46 : er =
"Both operands of the operator " + chaine_error +
" have to be either numbers or strings.";
break;
2154 case 47 : er = chaine_error +
" requires 2 string arguments";
break;
2156 Error(
"Compile",
"%s", er.Data());
2166 Bool_t TFormula::CheckOperands(Int_t oper, Int_t &err)
2168 if ( IsString(oper-1) && !StringToNumber(oper-1) ) {
2169 Error(
"Compile",
"\"%s\" requires a numerical operand.",fExpr[oper].Data());
2180 Bool_t TFormula::CheckOperands(Int_t leftoper, Int_t oper, Int_t &err)
2182 if ( IsString(oper-1) || IsString(leftoper) ) {
2183 if (IsString(oper-1) && StringToNumber(oper-1)) {
2186 if (IsString(leftoper) && StringToNumber(leftoper)) {
2189 Error(
"Compile",
"\"%s\" requires two numerical operands.",fExpr[oper].Data());
2200 Bool_t TFormula::StringToNumber(Int_t )
2211 void TFormula::Clear(Option_t * )
2221 void TFormula::ClearFormula(Option_t * )
2231 if (fExpr) {
delete [] fExpr; fExpr = 0;}
2232 if (fNames) {
delete [] fNames; fNames = 0;}
2233 if (fOper) {
delete [] fOper; fOper = 0;}
2234 if (fConst) {
delete [] fConst; fConst = 0;}
2235 if (fParams) {
delete [] fParams; fParams = 0;}
2236 fFunctions.Delete();
2237 fLinearParts.Delete();
2240 if (fPredefined) {
delete [] fPredefined; fPredefined = 0;}
2241 if (fOperOffset) {
delete [] fOperOffset; fOperOffset = 0;}
2242 if (fExprOptimized) {
delete [] fExprOptimized; fExprOptimized = 0;}
2243 if (fOperOptimized) {
delete [] fOperOptimized; fOperOptimized = 0;}
2251 inline static void ResizeArrayIfAllocated(T*& oldArray,
int newSize){
2254 if (!oldArray || newSize <=0)
return;
2256 T* newArray =
new T[newSize];
2257 std::copy(oldArray, oldArray+newSize, newArray);
2259 oldArray = newArray;
2290 Int_t TFormula::Compile(
const char *expression)
2292 Int_t i,j,lc,valeur,err;
2298 if (strlen(expression)) SetTitle(expression);
2300 TString chaine = GetTitle();
2302 if (chaine.Contains(
";")) {
2303 char *sctemp =
new char[chaine.Length()+1];
2304 strlcpy(sctemp,chaine.Data(),chaine.Length()+1);
2305 char *semicol = (
char*)strstr(sctemp,
";");
2306 if (semicol) *semicol = 0;
2312 if (TestBit(kLinear)){
2313 ProcessLinear(chaine);
2317 fExpr =
new TString[gMAXOP];
2318 fConst =
new Double_t[gMAXCONST];
2319 fParams =
new Double_t[gMAXPAR];
2320 fNames =
new TString[gMAXPAR];
2321 fOper =
new Int_t[gMAXOP];
2322 for (i=0; i<gMAXPAR; i++) {
2326 for (i=0; i<gMAXOP; i++) {
2330 for (i=0; i<gMAXCONST; i++)
2334 Bool_t inString =
false;
2335 for (i=1; i<=chaine.Length(); i++) {
2336 lc =chaine.Length();
2337 if (chaine(i-1,1) ==
"\"") inString = !inString;
2338 if (inString)
continue;
2339 if (chaine(i-1,2) ==
"**") {
2340 chaine = chaine(0,i-1) +
"^" + chaine(i+1,lc-i-1);
2342 }
else if (chaine(i-1,2) ==
"++") {
2343 chaine = chaine(0,i) + chaine(i+1,lc-i-1);
2345 }
else if (chaine(i-1,2) ==
"+-" || chaine(i-1,2) ==
"-+") {
2346 chaine = chaine(0,i-1) +
"-" + chaine(i+1,lc-i-1);
2348 }
else if (chaine(i-1,2) ==
"--") {
2349 chaine = chaine(0,i-1) +
"+" + chaine(i+1,lc-i-1);
2351 }
else if (chaine(i-1,2) ==
"->") {
2352 chaine = chaine(0,i-1) +
"." + chaine(i+1,lc-i-1);
2354 }
else if (chaine(i-1,1) ==
"[") {
2355 for (j=1;j<=chaine.Length()-i;j++) {
2356 if (chaine(j+i-1,1) ==
"]" || j+i > chaine.Length())
break;
2358 ctemp = chaine(i,j-1);
2360 sscanf(ctemp.Data(),
"%d",&valeur);
2361 if (valeur >= fNpar) fNpar = valeur+1;
2362 }
else if (chaine(i-1,1) ==
" ") {
2363 chaine = chaine(0,i-1)+chaine(i,lc-i);
2368 Analyze((
const char*)chaine,err);
2372 delete [] fParams; fParams = 0;
2373 delete [] fNames; fNames = 0;
2378 if (fNdim <= 0) fNdim = 1;
2379 if (chaine.Length() > 4)
2381 if ( GetNumber() != 400 &&
2382 GetNumber() != 410 &&
2383 GetNumber() != 110 )
2385 else if ( GetNumber() == 110 && chaine.Length() > 6 )
2387 else if ( GetNumber() == 410 && chaine.Length() > 8 )
2391 if (GetNumber() == 100) {
2392 SetParName(0,
"Constant");
2393 SetParName(1,
"Mean");
2394 SetParName(2,
"Sigma");
2397 if (GetNumber() == 110){
2398 SetParName(0,
"Constant");
2399 SetParName(1,
"MeanX");
2400 SetParName(2,
"SigmaX");
2401 SetParName(3,
"MeanY");
2402 SetParName(4,
"SigmaY");
2405 if (GetNumber() == 200) {
2406 SetParName(0,
"Constant");
2407 SetParName(1,
"Slope");
2410 if (GetNumber() == 300+fNpar) {
2411 for (i=0;i<fNpar;i++) SetParName(i,Form(
"p%d",i));
2414 if (GetNumber() == 400) {
2415 SetParName(0,
"Constant");
2416 SetParName(1,
"MPV");
2417 SetParName(2,
"Sigma");
2420 if (GetNumber() == 410) {
2421 SetParName(0,
"Constant");
2422 SetParName(1,
"MPVX");
2423 SetParName(2,
"SigmaX");
2424 SetParName(3,
"MPVY");
2425 SetParName(4,
"SigmaY");
2437 ResizeArrayIfAllocated(fExpr, fNoper);
2438 ResizeArrayIfAllocated(fConst, fNconst);
2439 ResizeArrayIfAllocated(fParams, fNpar);
2440 ResizeArrayIfAllocated(fNames, fNpar);
2441 ResizeArrayIfAllocated(fOper, fNoper);
2445 if (err) { fNdim = 0;
return 1; }
2449 if (!IsA()->GetBaseClass(
"TTreeFormula")) {
2459 void TFormula::Copy(TObject &obj)
const
2462 ((TFormula&)obj).ClearFormula();
2464 ((TFormula&)obj).fNdim = fNdim;
2465 ((TFormula&)obj).fNpar = fNpar;
2466 ((TFormula&)obj).fNoper = fNoper;
2467 ((TFormula&)obj).fNconst = fNconst;
2468 ((TFormula&)obj).fNumber = fNumber;
2469 ((TFormula&)obj).fNval = fNval;
2470 ((TFormula&)obj).fExpr = 0;
2471 ((TFormula&)obj).fConst = 0;
2472 ((TFormula&)obj).fParams = 0;
2473 ((TFormula&)obj).fNames = 0;
2474 if (fExpr && fNoper) {
2475 ((TFormula&)obj).fExpr =
new TString[fNoper];
2476 for (i=0;i<fNoper;i++) ((TFormula&)obj).fExpr[i] = fExpr[i];
2478 if (fOper && fNoper) {
2479 ((TFormula&)obj).fOper =
new Int_t[fNoper];
2480 for (i=0;i<fNoper;i++) ((TFormula&)obj).fOper[i] = fOper[i];
2482 if (fConst && fNconst) {
2483 ((TFormula&)obj).fConst =
new Double_t[fNconst];
2484 for (i=0;i<fNconst;i++) ((TFormula&)obj).fConst[i] = fConst[i];
2486 if (fParams && fNpar) {
2487 ((TFormula&)obj).fParams =
new Double_t[fNpar];
2488 for (i=0;i<fNpar;i++) ((TFormula&)obj).fParams[i] = fParams[i];
2490 if (fNames && fNpar) {
2491 ((TFormula&)obj).fNames =
new TString[fNpar];
2492 for (i=0;i<fNpar;i++) ((TFormula&)obj).fNames[i] = fNames[i];
2495 TIter next(&fFunctions);
2497 while ( (fobj = next()) ) {
2498 ((TFormula&)obj).fFunctions.Add( fobj->Clone() );
2505 if(fExprOptimized) {
2506 ((TFormula&)obj).fExprOptimized =
new TString[fNoper];
2507 for (i=0;i<fNoper;i++) ((TFormula&)obj).fExprOptimized[i] = fExprOptimized[i];
2509 if (fOperOptimized) {
2510 ((TFormula&)obj).fOperOptimized =
new Int_t[fNoper];
2511 for (i=0;i<fNoper;i++) ((TFormula&)obj).fOperOptimized[i] = fOperOptimized[i];
2514 ((TFormula&)obj).fPredefined =
new ROOT::v5::TFormulaPrimitive*[fNoper];
2515 for (i=0;i<fNoper;i++) {((TFormula&)obj).fPredefined[i] = fPredefined[i];}
2518 ((TFormula&)obj).fOperOffset =
new TOperOffset[fNoper];
2519 for (i=0;i<fNoper;i++) {((TFormula&)obj).fOperOffset[i] = fOperOffset[i];}
2522 ((TFormula&)obj).fNOperOptimized = fNOperOptimized;
2523 ((TFormula&)obj).fOptimal = fOptimal;
2553 char *TFormula::DefinedString(Int_t)
2584 Double_t TFormula::DefinedValue(Int_t)
2619 Int_t TFormula::DefinedVariable(TString &chaine,Int_t &action)
2622 if (chaine ==
"x") {
2623 if (fNdim < 1) fNdim = 1;
2625 }
else if (chaine ==
"y") {
2626 if (fNdim < 2) fNdim = 2;
2628 }
else if (chaine ==
"z") {
2629 if (fNdim < 3) fNdim = 3;
2631 }
else if (chaine ==
"t") {
2632 if (fNdim < 4) fNdim = 4;
2638 if (chaine.Data()[0]==
'x'){
2639 if (chaine.Data()[1]==
'[' && chaine.Data()[3]==
']'){
2640 const char ch0 =
'0';
2641 Int_t dim = chaine.Data()[2]-ch0;
2642 if (dim<0)
return -1;
2643 if (dim>9)
return -1;
2644 if (fNdim<=dim) fNdim = dim+1;
2647 if (chaine.Data()[1]==
'[' && chaine.Data()[4]==
']'){
2648 const char ch0 =
'0';
2649 Int_t dim = (chaine.Data()[2]-ch0)*10+(chaine.Data()[3]-ch0);
2650 if (dim<0)
return -1;
2651 if (dim>99)
return -1;
2652 if (fNdim<=dim) fNdim = dim+1;
2666 Double_t TFormula::Eval(Double_t x, Double_t y, Double_t z, Double_t t)
const
2673 return ((TFormula*)
this)->EvalPar(xx);
2685 Double_t TFormula::EvalParOld(
const Double_t *x,
const Double_t *uparams)
2689 Double_t tab[kMAXFOUND];
2690 const char *stringStack[gMAXSTRINGFOUND] = {0};
2691 Double_t param_calc[kMAXFOUND];
2692 char *string_calc[gMAXSTRINGFOUND] = {0};
2693 Int_t precalculated = 0;
2694 Int_t precalculated_str = 0;
2698 params =
const_cast<Double_t*
>(uparams);
2705 for (i=0; i<fNoper; ++i) {
2707 const int oper = fOper[i];
2708 const int opcode = oper >> kTFOperShift;
2712 case kParameter : { pos++; tab[pos-1] = params[ oper & kTFOperMask ];
continue; }
2713 case kConstant : { pos++; tab[pos-1] = fConst[ oper & kTFOperMask ];
continue; }
2714 case kVariable : { pos++; tab[pos-1] = x[ oper & kTFOperMask ];
continue; }
2715 case kStringConst: { strpos++; stringStack[strpos-1] = (
char*)fExpr[i].Data(); pos++; tab[pos-1] = 0;
continue; }
2717 case kAdd : pos--; tab[pos-1] += tab[pos];
continue;
2718 case kSubstract : pos--; tab[pos-1] -= tab[pos];
continue;
2719 case kMultiply : pos--; tab[pos-1] *= tab[pos];
continue;
2720 case kDivide : pos--;
if (tab[pos] == 0) tab[pos-1] = 0;
2721 else tab[pos-1] /= tab[pos];
2723 case kModulo : {pos--;
2724 Long64_t int1((Long64_t)tab[pos-1]);
2725 Long64_t int2((Long64_t)tab[pos]);
2726 tab[pos-1] = Double_t(int1%int2);
2729 case kcos : tab[pos-1] = TMath::Cos(tab[pos-1]);
continue;
2730 case ksin : tab[pos-1] = TMath::Sin(tab[pos-1]);
continue;
2731 case ktan :
if (TMath::Cos(tab[pos-1]) == 0) {tab[pos-1] = 0;}
2732 else tab[pos-1] = TMath::Tan(tab[pos-1]);
2734 case kacos :
if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
2735 else tab[pos-1] = TMath::ACos(tab[pos-1]);
2737 case kasin :
if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
2738 else tab[pos-1] = TMath::ASin(tab[pos-1]);
2740 case katan : tab[pos-1] = TMath::ATan(tab[pos-1]);
continue;
2741 case kcosh : tab[pos-1] = TMath::CosH(tab[pos-1]);
continue;
2742 case ksinh : tab[pos-1] = TMath::SinH(tab[pos-1]);
continue;
2743 case ktanh :
if (TMath::CosH(tab[pos-1]) == 0) {tab[pos-1] = 0;}
2744 else tab[pos-1] = TMath::TanH(tab[pos-1]);
2746 case kacosh:
if (tab[pos-1] < 1) {tab[pos-1] = 0;}
2747 else tab[pos-1] = TMath::ACosH(tab[pos-1]);
2749 case kasinh: tab[pos-1] = TMath::ASinH(tab[pos-1]);
continue;
2750 case katanh:
if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
2751 else tab[pos-1] = TMath::ATanH(tab[pos-1]);
2753 case katan2: pos--; tab[pos-1] = TMath::ATan2(tab[pos-1],tab[pos]);
continue;
2755 case kfmod : pos--; tab[pos-1] = fmod(tab[pos-1],tab[pos]);
continue;
2756 case kpow : pos--; tab[pos-1] = TMath::Power(tab[pos-1],tab[pos]);
continue;
2757 case ksq : tab[pos-1] = tab[pos-1]*tab[pos-1];
continue;
2758 case ksqrt : tab[pos-1] = TMath::Sqrt(TMath::Abs(tab[pos-1]));
continue;
2760 case kstrstr : strpos -= 2; pos-=2; pos++;
2761 if (strstr(stringStack[strpos],stringStack[strpos+1])) tab[pos-1]=1;
2765 case kmin : pos--; tab[pos-1] = TMath::Min(tab[pos-1],tab[pos]);
continue;
2766 case kmax : pos--; tab[pos-1] = TMath::Max(tab[pos-1],tab[pos]);
continue;
2768 case klog :
if (tab[pos-1] > 0) tab[pos-1] = TMath::Log(tab[pos-1]);
2769 else {tab[pos-1] = 0;}
2771 case kexp : { Double_t dexp = tab[pos-1];
2772 if (dexp < -700) {tab[pos-1] = 0;
continue;}
2773 if (dexp > 700) {tab[pos-1] = TMath::Exp(700);
continue;}
2774 tab[pos-1] = TMath::Exp(dexp);
continue; }
2775 case klog10:
if (tab[pos-1] > 0) tab[pos-1] = TMath::Log10(tab[pos-1]);
2776 else {tab[pos-1] = 0;}
2779 case kpi : pos++; tab[pos-1] = TMath::ACos(-1);
continue;
2781 case kabs : tab[pos-1] = TMath::Abs(tab[pos-1]);
continue;
2782 case ksign :
if (tab[pos-1] < 0) tab[pos-1] = -1;
else tab[pos-1] = 1;
continue;
2783 case kint : tab[pos-1] = Double_t(Int_t(tab[pos-1]));
continue;
2785 case kSignInv: tab[pos-1] = -1 * tab[pos-1];
continue;
2787 case krndm : pos++; tab[pos-1] = gRandom->Rndm();
continue;
2789 case kAnd : pos--;
if (tab[pos-1]!=0 && tab[pos]!=0) tab[pos-1]=1;
2792 case kOr : pos--;
if (tab[pos-1]!=0 || tab[pos]!=0) tab[pos-1]=1;
2795 case kEqual: pos--;
if (tab[pos-1] == tab[pos]) tab[pos-1]=1;
2798 case kNotEqual : pos--;
if (tab[pos-1] != tab[pos]) tab[pos-1]=1;
2801 case kLess : pos--;
if (tab[pos-1] < tab[pos]) tab[pos-1]=1;
2804 case kGreater : pos--;
if (tab[pos-1] > tab[pos]) tab[pos-1]=1;
2808 case kLessThan: pos--;
if (tab[pos-1]<=tab[pos]) tab[pos-1]=1;
2811 case kGreaterThan: pos--;
if (tab[pos-1]>=tab[pos]) tab[pos-1]=1;
2814 case kNot :
if (tab[pos-1]!=0) tab[pos-1] = 0;
else tab[pos-1] = 1;
2817 case kStringEqual : strpos -= 2; pos -=2 ; pos++;
2818 if (!strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
2821 case kStringNotEqual: strpos -= 2; pos -= 2; pos++;
2822 if (strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
2826 case kBitAnd : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) & ((Int_t) tab[pos]);
continue;
2827 case kBitOr : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) | ((Int_t) tab[pos]);
continue;
2828 case kLeftShift : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) <<((Int_t) tab[pos]);
continue;
2829 case kRightShift: pos--; tab[pos-1]= ((Int_t) tab[pos-1]) >>((Int_t) tab[pos]);
continue;
2831 case kJump : i = (oper & kTFOperMask);
continue;
2832 case kJumpIf : pos--;
if (!tab[pos]) i = (oper & kTFOperMask);
continue;
2834 case kBoolOptimize: {
2837 int param = (oper & kTFOperMask);
2838 Bool_t skip = kFALSE;
2839 int op = param % 10;
2841 if (op == 1 && (!tab[pos-1]) ) {
2850 }
else if (op == 2 && tab[pos-1] ) {
2862 int toskip = param / 10;
2872 #define R__EXPO(var) \
2874 pos++; int param = (oper & kTFOperMask); \
2875 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[var]); \
2879 case kxexpo: R__EXPO(0);
2880 case kyexpo: R__EXPO(1);
2881 case kzexpo: R__EXPO(2);
2882 case kxyexpo:{ pos++;
int param = (oper & kTFOperMask);
2883 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[0]+params[param+2]*x[1]);
2886 #define R__GAUS(var) \
2888 pos++; int param = (oper & kTFOperMask); \
2889 tab[pos-1] = params[param]*TMath::Gaus(x[var],params[param+1],params[param+2],IsNormalized()); \
2894 case kxgaus: R__GAUS(0);
2895 case kygaus: R__GAUS(1);
2896 case kzgaus: R__GAUS(2);
2897 case kxygaus: {pos++;
int param = (oper & kTFOperMask);
2898 Double_t intermede1;
2899 if (params[param+2] == 0) {
2902 intermede1=Double_t((x[0]-params[param+1])/params[param+2]);
2904 Double_t intermede2;
2905 if (params[param+4] == 0) {
2908 intermede2=Double_t((x[1]-params[param+3])/params[param+4]);
2910 tab[pos-1] = params[param]*TMath::Exp(-0.5*(intermede1*intermede1+intermede2*intermede2));
2913 #define R__LANDAU(var) \
2915 pos++; const int param = (oper & kTFOperMask); \
2916 tab[pos-1] = params[param]*TMath::Landau(x[var],params[param+1],params[param+2],IsNormalized()); \
2920 case kxlandau: R__LANDAU(0);
2921 case kylandau: R__LANDAU(1);
2922 case kzlandau: R__LANDAU(2);
2923 case kxylandau: { pos++;
int param = oper&0x7fffff ;
2924 Double_t intermede1=TMath::Landau(x[0], params[param+1], params[param+2],IsNormalized());
2925 Double_t intermede2=TMath::Landau(x[1], params[param+3], params[param+4],IsNormalized());
2926 tab[pos-1] = params[param]*intermede1*intermede2;
2930 #define R__POLY(var) \
2932 pos++; int param = (oper & kTFOperMask); \
2933 tab[pos-1] = 0; Double_t intermede = 1; \
2934 Int_t inter = param/100; \
2935 Int_t int1= param-inter*100-1; \
2936 for (j=0 ;j<inter+1;j++) { \
2937 tab[pos-1] += intermede*params[j+int1]; \
2938 intermede *= x[var]; \
2943 case kxpol: R__POLY(0);
2944 case kypol: R__POLY(1);
2945 case kzpol: R__POLY(2);
2947 case kDefinedVariable : {
2948 if (!precalculated) {
2950 for(j=0;j<fNval;j++) param_calc[j]=DefinedValue(j);
2952 pos++; tab[pos-1] = param_calc[(oper & kTFOperMask)];
2956 case kDefinedString : {
2957 int param = (oper & kTFOperMask);
2958 if (!precalculated_str) {
2959 precalculated_str=1;
2960 for (j=0;j<fNstring;j++) string_calc[j]=DefinedString(j);
2962 strpos++; stringStack[strpos-1] = string_calc[param];
2963 pos++; tab[pos-1] = 0;
2967 case kFunctionCall: {
2970 int param = (oper & kTFOperMask);
2971 int fno = param / 1000;
2972 int nargs = param % 1000;
2975 TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
2978 method->ResetParam();
2980 UInt_t argloc = pos-nargs;
2981 for(j=0;j<nargs;j++,argloc++,pos--) {
2982 method->SetParam(tab[argloc]);
2987 method->Execute(ret);
2993 if (!TestBit(kOptimizationError)) {
2994 SetBit(kOptimizationError);
2995 Warning(
"EvalParOld",
"Found an unsupported opcode (%d)",oper >> kTFOperShift);
2998 Double_t result0 = tab[0];
3020 TString TFormula::GetExpFormula(Option_t *option)
const
3023 TString* tab=
new TString[fNoper];
3024 Bool_t* ismulti=
new Bool_t[fNoper];
3030 Int_t ternaryend = -1;
3031 for(Int_t i=0;i<fNoper;i++){
3032 optype = GetAction(i);
3034 if (ternaryend==i) {
3036 if(ismulti[spos-1]){
3037 tab[spos-2]=tab[spos-2]+
"("+tab[spos-1]+
")";
3039 tab[spos-2]=tab[spos-2]+tab[spos-1];
3047 if (optype==kBoolOptimize) {
3052 if (optype==kSignInv) {
3053 tab[spos-1]=
"-("+tab[spos-1]+
")";
3059 if (kexpo<=optype && optype<=kzpol) {
3061 ismulti[spos]=kFALSE;
3067 if ((optype<=151 && optype>=140 && optype!=145) || (optype == 40)) {
3069 ismulti[spos]=kFALSE;
3075 if(((optype>0 && optype<6) || optype==20 ||
3076 (((optype>59 && optype<69) || (optype >75 && optype<82)) && spos>=2))) {
3078 if(ismulti[spos-2]){
3079 tab[spos-2]=
"("+tab[spos-2]+
")";
3081 if(ismulti[spos-1]){
3082 tab[spos-2]+=fExpr[i]+(
"("+tab[spos-1]+
")");
3084 tab[spos-2]+=fExpr[i]+tab[spos-1];
3086 ismulti[spos-2]=kTRUE;
3091 if (optype==kJumpIf) {
3092 if(ismulti[spos-1]){
3093 tab[spos-1]=
"("+tab[spos-1]+
")?";
3095 tab[spos-1]=tab[spos-1]+
"?";
3099 if (optype==kJump) {
3100 if(ismulti[spos-1]){
3101 tab[spos-2]=tab[spos-2]+
"("+tab[spos-1]+
"):";
3103 tab[spos-2]=tab[spos-2]+tab[spos-1]+
":";
3105 ternaryend = GetActionParam(i) + 1;
3112 TString funcname = fExpr[i];
3113 if((optype>9 && optype<16) ||
3114 (optype>20 && optype<23) ||
3115 (optype>29 && optype<34) ||
3116 (optype>40 && optype<44) ||
3117 (optype>69 && optype<76) ||
3123 if((optype>15 && optype<20) ||
3124 (optype>22 && optype<26)) {
3129 int param = (fOper[i] & kTFOperMask);
3131 int nargs = param % 1000;
3136 for(j=0, depth=0;j<funcname.Length();++j) {
3137 switch (funcname[j]) {
3144 funcname.Remove(0,j+1);
3145 j = funcname.Length();
3150 Ssiz_t ind = funcname.First(
'(');
3151 funcname.Remove(ind);
3154 Error(
"GetExpFormula",
"Internal error, number of argument found is %d",-offset);
3155 }
else if (offset == 0) {
3156 tab[spos]=funcname+
"()";
3157 ismulti[spos]=kFALSE;
3160 }
else if (offset<=0 && (spos+offset>=0)) {
3161 tab[spos+offset]=funcname+(
"("+tab[spos+offset]);
3162 for (j=offset+1; j<0; j++){
3163 tab[spos+offset]+=
","+tab[spos+j];
3165 tab[spos+offset]+=
")";
3166 ismulti[spos+offset]=kFALSE;
3171 if (ternaryend==fNoper) {
3173 if(ismulti[spos-1]){
3174 tab[spos-2]=tab[spos-2]+
"("+tab[spos-1]+
")";
3176 tab[spos-2]=tab[spos-2]+tab[spos-1];
3182 if (spos > 0) ret = tab[spos-1];
3187 TString opt = option;
3189 if (opt.Contains(
"p")) {
3192 for (j=0;j<fNpar;j++) {
3193 snprintf(pb,
sizeof(pb),
"[%d]",j);
3194 snprintf(pbv,100,
"%g",fParams[j]);
3195 ret.ReplaceAll(pb,pbv);
3197 ret.ReplaceAll(
"--",
"+");
3198 ret.ReplaceAll(
"+-",
"-");
3210 const TObject* TFormula::GetLinearPart(Int_t i)
3212 if (!fLinearParts.IsEmpty())
3213 return fLinearParts.UncheckedAt(i);
3220 Double_t TFormula::GetParameter(Int_t ipar)
const
3222 if (ipar <0 || ipar >= fNpar)
return 0;
3223 return fParams[ipar];
3229 Double_t TFormula::GetParameter(
const char *parName)
const
3231 const Double_t kNaN = 1e-300;
3232 Int_t index = GetParNumber(parName);
3234 Error(
"TFormula",
"Parameter %s not found", parName);
3237 return GetParameter(index);
3243 const char *TFormula::GetParName(Int_t ipar)
const
3245 if (ipar <0 || ipar >= fNpar)
return "";
3246 if (fNames[ipar].Length() > 0)
return (
const char*)fNames[ipar];
3247 return Form(
"p%d",ipar);
3253 Int_t TFormula::GetParNumber(
const char *parName)
const
3258 for (Int_t i=0; i<fNpar; i++) {
3259 if (!strcmp(GetParName(i),parName))
return i;
3267 Bool_t TFormula::IsString(Int_t oper)
const
3269 return GetAction(oper) == kStringConst;
3275 void TFormula::Print(Option_t *)
const
3278 Printf(
" %20s : %s Ndim= %d, Npar= %d, Noper= %d",GetName(),GetTitle(), fNdim,fNpar,fNoper);
3279 for (i=0;i<fNoper;i++) {
3280 Printf(
" fExpr[%d] = %s action = %d action param = %d ",
3281 i,(
const char*)fExpr[i],GetAction(i),GetActionParam(i));
3285 if (fNOperOptimized>0){
3286 Printf(
"Optimized expression");
3287 for (i=0;i<fNOperOptimized;i++) {
3288 Printf(
" fExpr[%d] = %s\t\t action = %d action param = %d ",
3289 i,(
const char*)fExprOptimized[i],GetActionOptimized(i),GetActionParamOptimized(i));
3293 if (!fNames)
return;
3294 if (!fParams)
return;
3295 for (i=0;i<fNpar;i++) {
3296 Printf(
" Par%3d %20s = %g",i,GetParName(i),fParams[i]);
3304 void TFormula::ProcessLinear(TString &formula)
3306 TString formula2(formula);
3309 Int_t nf, offset, replsize;
3311 pch= (
char*)strstr(formula.Data(),
"++");
3313 formula.Insert(0,
"[0]*(");
3314 pch= (
char*)strstr(formula.Data(),
"++");
3319 snprintf(repl,20,
")+[%d]*(", nf);
3320 offset = pch-formula.Data();
3321 if (nf<10) replsize = 7;
3322 else if (nf<100) replsize = 8;
3324 formula.Replace(pch-formula.Data(), 2, repl, replsize);
3325 pch = (
char*)strstr(formula.Data()+offset,
"++");
3328 formula.Append(
')', 1);
3331 formula2=formula2(4, formula2.Length()-4);
3332 pch= (
char*)strchr(formula2.Data(),
'[');
3333 snprintf(repl,20,
"++");
3336 offset = pch-formula2.Data()-1;
3337 if (nf<10) replsize = 5;
3339 formula2.Replace(pch-formula2.Data()-1, replsize, repl, 2);
3340 pch = (
char*)strchr(formula2.Data()+offset,
'[');
3345 fLinearParts.Expand(nf);
3347 TString replaceformula;
3348 formula2 = formula2.ReplaceAll(
"++", 2,
"|", 1);
3349 TObjArray *oa = formula2.Tokenize(
"|");
3350 TString replaceformula_name;
3351 for (Int_t i=0; i<nf; i++) {
3352 replaceformula = ((TObjString *)oa->UncheckedAt(i))->GetString();
3353 replaceformula_name =
"f_linear_";
3354 replaceformula_name.Append(replaceformula);
3355 TFormula *f =
new TFormula(replaceformula_name.Data(), replaceformula.Data());
3357 Error(
"TFormula",
"f_linear not allocated");
3361 R__LOCKGUARD(gROOTMutex);
3362 gROOT->GetListOfFunctions()->Remove(f);
3364 f->SetBit(kNotGlobal, 1);
3365 fLinearParts.Add(f);
3373 void TFormula::SetParameter(
const char *name, Double_t value)
3375 Int_t ipar = GetParNumber(name);
3376 if (ipar <0 || ipar >= fNpar)
return;
3377 fParams[ipar] = value;
3384 void TFormula::SetParameter(Int_t ipar, Double_t value)
3386 if (ipar <0 || ipar >= fNpar)
return;
3387 fParams[ipar] = value;
3395 void TFormula::SetParameters(
const Double_t *params)
3397 for (Int_t i=0; i<fNpar;i++) {
3398 fParams[i] = params[i];
3410 void TFormula::SetParameters(Double_t p0,Double_t p1,Double_t p2,Double_t p3,Double_t p4
3411 ,Double_t p5,Double_t p6,Double_t p7,Double_t p8,Double_t p9,Double_t p10)
3413 if (fNpar > 0) fParams[0] = p0;
3414 if (fNpar > 1) fParams[1] = p1;
3415 if (fNpar > 2) fParams[2] = p2;
3416 if (fNpar > 3) fParams[3] = p3;
3417 if (fNpar > 4) fParams[4] = p4;
3418 if (fNpar > 5) fParams[5] = p5;
3419 if (fNpar > 6) fParams[6] = p6;
3420 if (fNpar > 7) fParams[7] = p7;
3421 if (fNpar > 8) fParams[8] = p8;
3422 if (fNpar > 9) fParams[9] = p9;
3423 if (fNpar >10) fParams[10]= p10;
3430 void TFormula::SetParName(Int_t ipar,
const char *name)
3432 if (ipar <0 || ipar >= fNpar)
return;
3433 fNames[ipar] = name;
3439 void TFormula::SetParNames(
const char*name0,
const char*name1,
const char*name2,
const char*name3,
const char*name4,
3440 const char*name5,
const char*name6,
const char*name7,
const char*name8,
const char*name9,
const char*name10)
3442 if (fNpar > 0) fNames[0] = name0;
3443 if (fNpar > 1) fNames[1] = name1;
3444 if (fNpar > 2) fNames[2] = name2;
3445 if (fNpar > 3) fNames[3] = name3;
3446 if (fNpar > 4) fNames[4] = name4;
3447 if (fNpar > 5) fNames[5] = name5;
3448 if (fNpar > 6) fNames[6] = name6;
3449 if (fNpar > 7) fNames[7] = name7;
3450 if (fNpar > 8) fNames[8] = name8;
3451 if (fNpar > 9) fNames[9] = name9;
3452 if (fNpar >10) fNames[10]= name10;
3458 void TFormula::Streamer(TBuffer &b,
const TClass *onfile_class)
3460 if (b.IsReading()) {
3462 Version_t v = b.ReadVersion(&R__s, &R__c);
3464 Error(
"Streamer",
"version 6 is not supported");
3467 Streamer(b, v, R__s, R__c, onfile_class);
3470 b.WriteClassBuffer(TFormula::Class(),
this);
3477 void TFormula::Streamer(TBuffer &b)
3479 if (b.IsReading()) {
3481 Version_t v = b.ReadVersion(&R__s, &R__c);
3483 Error(
"Streamer",
"version 6 is not supported");
3486 Streamer(b, v, R__s, R__c,
nullptr);
3489 b.WriteClassBuffer(TFormula::Class(),
this);
3496 void TFormula::Streamer(TBuffer &b, Int_t v, UInt_t R__s, UInt_t R__c,
const TClass *onfile_class)
3501 b.ReadClassBuffer(TFormula::Class(),
this, v, R__s, R__c, onfile_class);
3502 if (!TestBit(kNotGlobal)) {
3503 R__LOCKGUARD(gROOTMutex);
3504 gROOT->GetListOfFunctions()->Add(
this);
3508 if (fFunctions.GetLast()>=0) {
3511 Double_t *param = fParams;
3512 TString *names = fNames;
3517 Error(
"Streamer",
"error compiling formula");
3520 for (Int_t i = 0; i<npar && i<fNpar; ++i) fParams[i] = param[i];
3532 TNamed::Streamer(b);
3535 if (v > 1) b >> fNval;
3536 if (v > 2) b >> fNstring;
3537 fNpar = b.ReadArray(fParams);
3538 fOper =
new Int_t[gMAXOP];
3539 fNoper = b.ReadArray(fOper);
3540 fNconst = b.ReadArray(fConst);
3542 fExpr =
new TString[fNoper];
3545 fNames =
new TString[fNpar];
3548 for (i=0;i<fNoper;i++) fExpr[i].Streamer(b);
3549 for (i=0;i<fNpar;i++) fNames[i].Streamer(b);
3551 R__LOCKGUARD(gROOTMutex);
3552 if (gROOT->GetListOfFunctions()->FindObject(GetName()))
return;
3553 gROOT->GetListOfFunctions()->Add(
this);
3555 b.CheckByteCount(R__s, R__c, TFormula::IsA());
3562 void TFormula::Convert(UInt_t )
3570 kOldxylandau = 4500,
3571 kOldConstants = 50000,
3572 kOldStrings = 80000,
3573 kOldVariable = 100000,
3574 kOldTreeString = 105000,
3575 kOldFormulaVar = 110000,
3576 kOldBoolOptimize = 120000,
3577 kOldFunctionCall = 200000
3581 for (i=0,j=0; i<fNoper; ++i,++j) {
3582 Int_t action = fOper[i];
3583 Int_t newActionCode = 0;
3584 Int_t newActionParam = 0;
3589 newActionCode = kSignInv;
3591 Float_t aresult = 99.99;
3592 sscanf((
const char*)fExpr[i],
"%g",&aresult);
3593 R__ASSERT((aresult+1)<0.001);
3599 for (
int z=i; z<fNoper; ++z) {
3600 fExpr[z-1] = fExpr[z];
3603 }
else if ( action < 100 ) {
3606 newActionCode = action;
3608 }
else if (action >= kOldFunctionCall) {
3611 newActionCode = kFunctionCall;
3612 newActionParam = action-kOldFunctionCall;
3614 }
else if (action >= kOldBoolOptimize) {
3617 newActionCode = kBoolOptimize;
3618 newActionParam = action-kOldBoolOptimize;
3620 }
else if (action >= kOldFormulaVar) {
3623 newActionCode = kVariable;
3624 newActionParam = action-kOldFormulaVar;
3626 }
else if (action >= kOldTreeString) {
3629 newActionCode = kDefinedString;
3630 newActionParam = action-kOldTreeString;
3632 }
else if (action >= kOldVariable) {
3635 newActionCode = kDefinedVariable;
3636 newActionParam = action-kOldVariable;
3638 }
else if (action == kOldStrings) {
3641 newActionCode = kStringConst;
3643 }
else if (action >= kOldConstants) {
3646 newActionCode = kConstant;
3647 newActionParam = action-kOldConstants;
3649 }
else if (action > 10000 && action < kOldConstants) {
3652 int var = action/10000;
3653 newActionCode = kpol + (var-1);
3654 newActionParam = action - var*10000;
3656 }
else if (action >= 4600) {
3658 Error(
"Convert",
"Unsupported value %d",action);
3660 }
else if (action > kOldxylandau) {
3663 newActionCode = kxylandau;
3664 newActionParam = action - (kOldxylandau+1);
3666 }
else if (action > kOldlandau) {
3669 newActionCode = klandau;
3670 int var = action/100-40;
3671 if (var) newActionCode += var;
3672 newActionParam = action - var*100 - (kOldlandau+1);
3674 }
else if (action > 2500 && action < 2600) {
3677 newActionCode = kxygaus;
3678 newActionParam = action-2501;
3680 }
else if (action > 2000 && action < 2500) {
3683 newActionCode = kgaus;
3684 int var = action/100-20;
3685 if (var) newActionCode += var;
3686 newActionParam = action - var*100 - (kOldgaus+1);
3688 }
else if (action > 1500 && action < 1600) {
3691 newActionCode = kxyexpo;
3692 newActionParam = action-1501;
3694 }
else if (action > 1000 && action < 1500) {
3697 newActionCode = kexpo;
3698 int var = action/100-10;
3699 if (var) newActionCode += var;
3700 newActionParam = action - var*100 - (kOldexpo+1);
3702 }
else if (action > 100 && action < 200) {
3705 newActionCode = kParameter;
3706 newActionParam = action - 101;
3709 SetAction( j, newActionCode, newActionParam );
3726 TOperOffset::TOperOffset()
3744 void TFormula::MakePrimitive(
const char *expr, Int_t pos)
3746 TString cbase(expr);
3747 cbase.ReplaceAll(
"Double_t ",
"");
3748 int paran = cbase.First(
"(");
3755 if (cbase==
"<") cbase=
"XlY";
3756 if (cbase==
"<=") cbase=
"XleY";
3757 if (cbase==
">") cbase=
"XgY";
3758 if (cbase==
">=") cbase=
"XgeY";
3759 if (cbase==
"==" && GetActionOptimized(pos)!=kStringEqual) cbase=
"XeY";
3760 if (cbase==
"!=" && GetActionOptimized(pos)!=kStringNotEqual) cbase=
"XneY";
3762 ROOT::v5::TFormulaPrimitive *prim = ROOT::v5::TFormulaPrimitive::FindFormula(cbase ,paran>0 ? cbase.Data() + paran + 1 : (
const char*)0);
3764 fPredefined[pos] = prim;
3765 if (prim->fType==10) {
3766 SetActionOptimized(pos, kFD1);
3768 if (prim->fType==110) {
3769 SetActionOptimized(pos, kFD2);
3771 if (prim->fType==1110) {
3772 SetActionOptimized(pos, kFD3);
3774 if (prim->fType==-1) {
3775 SetActionOptimized(pos, kFDM);
3777 if (prim->fType==0){
3778 SetActionOptimized(pos,kConstant,fNconst);
3779 fConst[fNconst] = prim->Eval(0);
3816 void TFormula::Optimize()
3824 if (fPredefined) {
delete [] fPredefined; fPredefined = 0;}
3825 if (fOperOffset) {
delete [] fOperOffset; fOperOffset = 0;}
3826 if (fExprOptimized) {
delete [] fExprOptimized; fExprOptimized = 0;}
3827 if (fOperOptimized) {
delete [] fOperOptimized; fOperOptimized = 0;}
3829 fExprOptimized =
new TString[fNoper];
3830 fOperOptimized =
new Int_t[fNoper];
3831 fPredefined =
new ROOT::v5::TFormulaPrimitive*[fNoper];
3832 fOperOffset =
new TOperOffset[fNoper];
3833 for (i=0; i<fNoper; i++) {
3834 fExprOptimized[i] = fExpr[i] ;
3835 fOperOptimized[i] = fOper[i];
3842 for (i=0;i<fNoper;i++){
3843 if (fExprOptimized[i].Data()) {
3844 MakePrimitive(fExprOptimized[i].Data(), i);
3848 Int_t maxfound = fNoper+1;
3849 Int_t *offset =
new Int_t[maxfound*16];
3850 Int_t *optimized =
new Int_t[maxfound];
3853 ROOT::v5::TFormulaPrimitive* primitive[10];
3854 primitive[0] = ROOT::v5::TFormulaPrimitive::FindFormula(
"PlusXY");
3855 primitive[1] = ROOT::v5::TFormulaPrimitive::FindFormula(
"MinusXY");
3856 primitive[2] = ROOT::v5::TFormulaPrimitive::FindFormula(
"MultXY");
3857 primitive[3] = ROOT::v5::TFormulaPrimitive::FindFormula(
"DivXY");
3858 primitive[4] = ROOT::v5::TFormulaPrimitive::FindFormula(
"XpYpZ");
3859 primitive[5] = ROOT::v5::TFormulaPrimitive::FindFormula(
"XxYxZ");
3860 primitive[6] = ROOT::v5::TFormulaPrimitive::FindFormula(
"XxYpZ");
3861 primitive[7] = ROOT::v5::TFormulaPrimitive::FindFormula(
"XpYxZ");
3862 primitive[8] = ROOT::v5::TFormulaPrimitive::FindFormula(
"Pow2");
3863 primitive[9] = ROOT::v5::TFormulaPrimitive::FindFormula(
"Pow3");
3867 for (i=0;i<fNoper;i++) optimized[i]=0;
3869 for (i=0;i<fNoper;i++){
3870 Int_t actionparam = GetActionParamOptimized(i);
3871 Int_t action = GetActionOptimized(i);
3873 if (action==kBoolOptimize){
3877 fOperOffset[i].fType1 = actionparam/10;
3878 fOperOffset[i].fOffset0 = actionparam%10;
3879 fOperOffset[i].fToJump = i+fOperOffset[i].fType1;
3882 if (action==kJump || action==kJumpIf) {
3884 fOperOffset[i].fType1 = action;
3885 fOperOffset[i].fToJump = actionparam;
3888 if (action==kConstant&&i<fNoper-2){
3892 if (GetActionOptimized(i+1)==kConstant && GetActionOptimized(i+2)==kFDM){
3896 fOperOffset[i].fType0=actionparam;
3897 fOperOffset[i].fOffset0=GetActionParamOptimized(i-1);
3898 Int_t offset2 = int(fConst[fOperOffset[i].fOffset0]+0.4);
3899 fOperOffset[i].fOffset0=offset2;
3900 Int_t nparmax = offset2+fPredefined[i]->fNParameters;
3908 case kVariable : {action=kData; fOperOffset[i].fType0=0;
break;}
3909 case kParameter: {action=kData; fOperOffset[i].fType0=1;
break;}
3910 case kConstant : {action=kData; fOperOffset[i].fType0=2;
break;}
3913 fOperOffset[i].fOffset0 = GetActionParamOptimized(i);
3914 SetActionOptimized(i,action, actionparam);
3918 fNOperOptimized = fNoper;
3920 for (i=0; i<fNoper; ++i)
3923 if (!(GetActionOptimized(i)== kData))
continue;
3924 offset[0] = fOperOffset[i].fType0;
3925 offset[1] = fOperOptimized[i] & kTFOperMask;
3927 if ((i+1) >= fNoper)
continue;
3929 if (GetActionOptimized(i+1)==kFD1){
3932 fOperOffset[i].fType0 = offset[0];
3933 fOperOffset[i].fOffset0 = offset[1];
3934 SetActionOptimized(i ,kUnary);
3937 if (GetActionOptimized(i+1)==kAdd){
3940 fOperOffset[i].fType0 = offset[0];
3941 fOperOffset[i].fOffset0 = offset[1];
3942 SetActionOptimized(i ,kPlusD);
3945 if (GetActionOptimized(i+1)==kMultiply){
3948 fOperOffset[i].fType0 = offset[0];
3949 fOperOffset[i].fOffset0 = offset[1];
3950 SetActionOptimized(i,kMultD);
3954 if ((i+2) >= fNoper)
continue;
3958 if (!(GetActionOptimized(i+1)== kData))
continue;
3959 offset[2] = fOperOffset[i+1].fType0;
3960 offset[3] = fOperOptimized[i+1] & kTFOperMask;
3962 if (GetActionOptimized(i+2)==kFD2 || GetActionOptimized(i+2)==kAdd ||GetActionOptimized(i+2)==kSubstract||
3963 GetActionOptimized(i+2)==kMultiply || GetActionOptimized(i+2)==kDivide){
3969 fOperOffset[i].fType0 = offset[0];
3970 fOperOffset[i].fOffset0 = offset[1];
3971 fOperOffset[i].fType1 = offset[2];
3972 fOperOffset[i].fOffset1 = offset[3];
3973 fOperOffset[i].fType2 = GetActionOptimized(i);
3974 if (GetActionOptimized(i)==kAdd) {fPredefined[i] = primitive[0];}
3975 if (GetActionOptimized(i)==kSubstract) {fPredefined[i] = primitive[1];}
3976 if (GetActionOptimized(i)==kMultiply) {
3977 fPredefined[i]=primitive[2];
3978 if (offset[0]==offset[2]&&offset[1]==offset[3]) {
3979 fPredefined[i] = primitive[8];
3980 SetActionOptimized(i,kUnary);
3984 if (GetActionOptimized(i)==kDivide) {
3985 fPredefined[i] = primitive[3];
3987 SetActionOptimized(i,kBinary);
3991 if ((i+3) >= fNoper)
continue;
3996 if (!(GetActionOptimized(i+2)== kData))
continue;
3997 offset[4] = fOperOffset[i+2].fType0;
3998 offset[5] = fOperOptimized[i+2] & kTFOperMask;
4000 if (GetActionOptimized(i+3)==kFD3|| ( (GetActionOptimized(i+3)==kAdd||GetActionOptimized(i+3)==kMultiply) &&
4001 (GetActionOptimized(i+4)==kAdd||GetActionOptimized(i+4)==kMultiply) ) ){
4007 fOperOffset[i].fType0 = offset[0];
4008 fOperOffset[i].fOffset0 = offset[1];
4009 fOperOffset[i].fType1 = offset[2];
4010 fOperOffset[i].fOffset1 = offset[3];
4011 fOperOffset[i].fType2 = offset[4];
4012 fOperOffset[i].fOffset2 = offset[5];
4014 fOperOffset[i].fOldAction = GetActionOptimized(i);
4015 if (GetActionOptimized(i)==kFD3) {
4016 SetActionOptimized(i,kThree);
4020 Int_t action2=kThree;
4021 if (GetActionOptimized(i)==kAdd&&GetActionOptimized(i+1)==kAdd) action=4;
4022 if (GetActionOptimized(i)==kMultiply&&GetActionOptimized(i+1)==kMultiply) {
4024 if (offset[0]==offset[2]&&offset[1]==offset[3]&&offset[0]==offset[4]&&offset[1]==offset[5]){
4025 fPredefined[i]=primitive[9];
4030 if (GetActionOptimized(i)==kAdd&&GetActionOptimized(i+1)==kMultiply) action=6;
4031 if (GetActionOptimized(i)==kMultiply&&GetActionOptimized(i+1)==kAdd) action=7;
4035 fOperOffset[i].fType0 = offset[0];
4036 fOperOffset[i].fOffset0 = offset[1];
4037 fOperOffset[i].fType1 = offset[2];
4038 fOperOffset[i].fOffset1 = offset[3];
4039 fOperOffset[i].fType2 = offset[4];
4040 fOperOffset[i].fOffset2 = offset[5];
4041 fPredefined[i]=primitive[action];
4042 SetActionOptimized(i,action2);
4050 Int_t *map0 =
new Int_t[maxfound];
4051 Int_t *map1 =
new Int_t[maxfound];
4052 for (i=0;i<fNoper;i++){
4055 fOperOptimized[operO] = fOperOptimized[i];
4056 fPredefined[operO] = fPredefined[i];
4057 fOperOffset[operO] = fOperOffset[i];
4058 expr += fExprOptimized[i];
4059 if (optimized[i]==0){
4060 fExprOptimized[operO] = expr;
4070 for (i=0; i<fNOperOptimized; i++){
4071 Int_t optaction = GetActionOptimized(i);
4072 if (optaction==kBoolOptimize){
4073 Int_t oldpos = fOperOffset[i].fToJump;
4074 Int_t newpos = oldpos==fNoper ? fNOperOptimized : map0[oldpos];
4075 fOperOffset[i].fToJump = newpos;
4076 Int_t actionop = GetActionParamOptimized(i) % 10;
4078 case 1: SetActionOptimized(i,kBoolOptimizeAnd,newpos);
break;
4079 case 2: SetActionOptimized(i,kBoolOptimizeOr,newpos);
break;
4081 }
else if (optaction==kJump || optaction==kJumpIf) {
4082 Int_t oldpos = fOperOffset[i].fToJump;
4083 Int_t newpos = oldpos==fNoper ? fNOperOptimized : map0[oldpos];
4084 fOperOffset[i].fToJump = newpos;
4085 SetActionOptimized(i,optaction,newpos);
4090 fNOperOptimized = operO;
4092 fOptimal= (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalParFast;
4093 if (fNOperOptimized==1) {
4094 switch(GetActionOptimized(0)){
4095 case kData : {fOptimal= (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive0;
break;}
4096 case kUnary : {fOptimal= (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive1;
break;}
4097 case kBinary : {fOptimal= (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive2;
break;}
4098 case kThree : {fOptimal= (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive3;
break;}
4099 case kFDM : {fOptimal= (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive4;
break;}
4106 delete [] optimized;
4112 Double_t TFormula::EvalPrimitive(
const Double_t *x,
const Double_t *params)
4114 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
4115 Double_t result = pdata[fOperOffset->fType0][fOperOffset->fOffset0];
4116 switch((fOperOptimized[0] >> kTFOperShift)) {
4117 case kData :
return result;
4118 case kUnary :
return (fPredefined[0]->fFunc10)(pdata[fOperOffset->fType0][fOperOffset->fOffset0]);
4119 case kBinary :
return (fPredefined[0]->fFunc110)(result,
4120 pdata[fOperOffset->fType1][fOperOffset->fOffset1]);
4122 case kThree :
return (fPredefined[0]->fFunc1110)(result, pdata[fOperOffset->fType1][fOperOffset->fOffset1],
4123 pdata[fOperOffset->fType2][fOperOffset->fOffset2]);
4124 case kFDM :
return (fPredefined[0]->fFuncG)((Double_t*)&x[fOperOffset->fType0],
4125 (Double_t*)¶ms[fOperOffset->fOffset0]);
4133 Double_t TFormula::EvalPrimitive0(
const Double_t *x,
const Double_t *params)
4135 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
4136 return pdata[fOperOffset->fType0][fOperOffset->fOffset0];
4142 Double_t TFormula::EvalPrimitive1(
const Double_t *x,
const Double_t *params)
4144 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
4145 return (fPredefined[0]->fFunc10)(pdata[fOperOffset->fType0][fOperOffset->fOffset0]);
4151 Double_t TFormula::EvalPrimitive2(
const Double_t *x,
const Double_t *params)
4153 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
4154 return (fPredefined[0]->fFunc110)(pdata[fOperOffset->fType0][fOperOffset->fOffset0],
4155 pdata[fOperOffset->fType1][fOperOffset->fOffset1]);
4161 Double_t TFormula::EvalPrimitive3(
const Double_t *x,
const Double_t *params)
4163 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
4164 return (fPredefined[0]->fFunc1110)(pdata[fOperOffset->fType0][fOperOffset->fOffset0], pdata[fOperOffset->fType1][fOperOffset->fOffset1],
4165 pdata[fOperOffset->fType2][fOperOffset->fOffset2]);
4171 Double_t TFormula::EvalPrimitive4(
const Double_t *x,
const Double_t *params)
4173 const Double_t *par = (params!=0)?params:fParams;
4174 return (fPredefined[0]->fFuncG)((Double_t*)&x[fOperOffset->fType0],
4175 (Double_t*)&par[fOperOffset->fOffset0]);
4187 Double_t TFormula::EvalParFast(
const Double_t *x,
const Double_t *uparams)
4189 const Double_t *pdata[3] = {x,(uparams!=0)?uparams:fParams, fConst};
4192 Double_t tab[kMAXFOUND] = {0};
4193 const char *stringStack[gMAXSTRINGFOUND] = {0};
4194 Double_t param_calc[kMAXFOUND];
4195 char *string_calc[gMAXSTRINGFOUND] = {0};
4196 Int_t precalculated = 0;
4197 Int_t precalculated_str = 0;
4203 params =
const_cast<Double_t*
>(uparams);
4214 for (i=0; i<fNOperOptimized; ++i) {
4216 const int oper = fOperOptimized[i];
4217 const int opcode = oper >> kTFOperShift;
4220 case kData : tab[pos] = pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0]; pos++;
continue;
4221 case kPlusD : tab[pos-1]+= pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0];
continue;
4222 case kMultD : tab[pos-1]*= pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0];
continue;
4223 case kAdd : pos--; tab[pos-1] += tab[pos];
continue;
4224 case kSubstract : pos--; tab[pos-1] -= tab[pos];
continue;
4225 case kMultiply : pos--; tab[pos-1] *= tab[pos];
continue;
4226 case kDivide : pos--;
if (tab[pos] == 0) tab[pos-1] = 0;
4227 else tab[pos-1] /= tab[pos];
4229 case kUnary : tab[pos] = (fPredefined[i]->fFunc10)(pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0]); pos++;
continue;
4230 case kBinary : tab[pos] = (fPredefined[i]->fFunc110)(pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0],
4231 pdata[fOperOffset[i].fType1][fOperOffset[i].fOffset1]);pos++;
continue;
4233 case kThree : tab[pos] = (fPredefined[i]->fFunc1110)(pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0],
4234 pdata[fOperOffset[i].fType1][fOperOffset[i].fOffset1],
4235 pdata[fOperOffset[i].fType2][fOperOffset[i].fOffset2]); pos++;
continue;
4237 case kFDM : tab[pos] = (fPredefined[i]->fFuncG)(&x[fOperOffset[i].fType0],¶ms[fOperOffset[i].fOffset0]); pos++;
continue;
4238 case kFD1 : tab[pos-1] =(fPredefined[i]->fFunc10)(tab[pos-1]);
continue;
4239 case kFD2 : pos--; tab[pos-1] = (fPredefined[i]->fFunc110)(tab[pos-1],tab[pos]);
continue;
4240 case kFD3 : pos-=2; tab[pos-1] = (fPredefined[i]->fFunc1110)(tab[pos-1],tab[pos],tab[pos+1]);
continue;
4244 case kBoolOptimizeAnd: {
4245 if (!tab[pos-1]) i=fOperOffset[i].fToJump;
4248 case kBoolOptimizeOr: {
4249 if (tab[pos-1]) i=fOperOffset[i].fToJump;
4252 case kAnd : pos--; tab[pos-1] = (bool)tab[pos];
continue;
4253 case kOr : pos--; tab[pos-1] = (bool)tab[pos];
continue;
4257 case kabs :
if (tab[pos-1]<0) tab[pos-1]=-tab[pos-1];
continue;
4258 case ksign :
if (tab[pos-1] < 0) tab[pos-1] = -1;
else tab[pos-1] = 1;
continue;
4259 case kint : tab[pos-1] = Double_t(Int_t(tab[pos-1]));
continue;
4260 case kpow : pos--; tab[pos-1] = TMath::Power(tab[pos-1],tab[pos]);
continue;
4262 case kModulo : {pos--;
4263 Long64_t int1((Long64_t)tab[pos-1]);
4264 Long64_t int2((Long64_t)tab[pos]);
4265 tab[pos-1] = Double_t(int1%int2);
4269 case kStringConst: { strpos++; stringStack[strpos-1] = (
char*)fExprOptimized[i].Data(); pos++; tab[pos-1] = 0;
continue; }
4270 case kfmod : pos--; tab[pos-1] = fmod(tab[pos-1],tab[pos]);
continue;
4272 case kstrstr : strpos -= 2; pos-=2; pos++;
4273 if (strstr(stringStack[strpos],stringStack[strpos+1])) tab[pos-1]=1;
4276 case kpi : pos++; tab[pos-1] = TMath::ACos(-1);
continue;
4279 case kSignInv: tab[pos-1] = -1 * tab[pos-1];
continue;
4281 case krndm : pos++; tab[pos-1] = gRandom->Rndm();
continue;
4284 case kEqual: pos--;
if (tab[pos-1] == tab[pos]) tab[pos-1]=1;
4287 case kNotEqual : pos--;
if (tab[pos-1] != tab[pos]) tab[pos-1]=1;
4290 case kNot :
if (tab[pos-1]!=0) tab[pos-1] = 0;
else tab[pos-1] = 1;
4293 case kStringEqual : strpos -= 2; pos -=2 ; pos++;
4294 if (!strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
4297 case kStringNotEqual: strpos -= 2; pos -= 2; pos++;
4298 if (strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
4302 case kBitAnd : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) & ((Int_t) tab[pos]);
continue;
4303 case kBitOr : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) | ((Int_t) tab[pos]);
continue;
4304 case kLeftShift : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) <<((Int_t) tab[pos]);
continue;
4305 case kRightShift: pos--; tab[pos-1]= ((Int_t) tab[pos-1]) >>((Int_t) tab[pos]);
continue;
4307 case kJump : i = (oper & kTFOperMask);
continue;
4308 case kJumpIf : pos--;
if (!tab[pos]) i = (oper & kTFOperMask);
continue;
4310 case kBoolOptimize: {
4313 int param = (oper & kTFOperMask);
4314 int op = param % 10;
4316 if (op == 1 && (!tab[pos-1]) ) {
4325 }
else if (op == 2 && tab[pos-1] ) {
4342 #define R__EXPO(var) \
4344 pos++; int param = (oper & kTFOperMask); \
4345 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[var]); \
4349 case kxexpo: R__EXPO(0);
4350 case kyexpo: R__EXPO(1);
4351 case kzexpo: R__EXPO(2);
4352 case kxyexpo:{ pos++;
int param = (oper & kTFOperMask);
4353 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[0]+params[param+2]*x[1]);
4358 #define R__GAUS(var) \
4360 pos++; int param = (oper & kTFOperMask); \
4361 tab[pos-1] = params[param]*TMath::Gaus(x[var],params[param+1], \
4362 params[param+2],IsNormalized()); \
4367 case kxgaus: R__GAUS(0);
4368 case kygaus: R__GAUS(1);
4369 case kzgaus: R__GAUS(2);
4370 case kxygaus: { pos++;
int param = (oper & kTFOperMask);
4371 Double_t intermede1;
4372 if (params[param+2] == 0) {
4375 intermede1=Double_t((x[0]-params[param+1])/params[param+2]);
4377 Double_t intermede2;
4378 if (params[param+4] == 0) {
4381 intermede2=Double_t((x[1]-params[param+3])/params[param+4]);
4383 tab[pos-1] = params[param]*TMath::Exp(-0.5*(intermede1*intermede1+intermede2*intermede2));
4386 #define R__LANDAU(var) \
4388 pos++; const int param = (oper & kTFOperMask); \
4389 tab[pos-1] = params[param]*TMath::Landau(x[var],params[param+1],params[param+2],IsNormalized()); \
4393 case kxlandau: R__LANDAU(0);
4394 case kylandau: R__LANDAU(1);
4395 case kzlandau: R__LANDAU(2);
4396 case kxylandau: { pos++;
int param = oper&0x7fffff ;
4397 Double_t intermede1=TMath::Landau(x[0], params[param+1], params[param+2],IsNormalized());
4398 Double_t intermede2=TMath::Landau(x[1], params[param+3], params[param+4],IsNormalized());
4399 tab[pos-1] = params[param]*intermede1*intermede2;
4403 #define R__POLY(var) \
4405 pos++; int param = (oper & kTFOperMask); \
4406 tab[pos-1] = 0; Double_t intermede = 1; \
4407 Int_t inter = param/100; \
4408 Int_t int1= param-inter*100-1; \
4409 for (j=0 ;j<inter+1;j++) { \
4410 tab[pos-1] += intermede*params[j+int1]; \
4411 intermede *= x[var]; \
4416 case kxpol: R__POLY(0);
4417 case kypol: R__POLY(1);
4418 case kzpol: R__POLY(2);
4420 case kDefinedVariable : {
4421 if (!precalculated) {
4423 for(j=0;j<fNval;j++) param_calc[j]=DefinedValue(j);
4425 pos++; tab[pos-1] = param_calc[(oper & kTFOperMask)];
4429 case kDefinedString : {
4430 int param = (oper & kTFOperMask);
4431 if (!precalculated_str) {
4432 precalculated_str=1;
4433 for (j=0;j<fNstring;j++) string_calc[j]=DefinedString(j);
4435 strpos++; stringStack[strpos-1] = string_calc[param];
4436 pos++; tab[pos-1] = 0;
4440 case kFunctionCall: {
4443 int param = (oper & kTFOperMask);
4444 int fno = param / 1000;
4445 int nargs = param % 1000;
4448 TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
4451 method->ResetParam();
4453 UInt_t argloc = pos-nargs;
4454 for(j=0;j<nargs;j++,argloc++,pos--) {
4455 method->SetParam(tab[argloc]);
4460 method->Execute(ret);
4466 if (!TestBit(kOptimizationError)) {
4467 SetBit(kOptimizationError);
4468 Warning(
"EvalParFast",
"Found an unsupported optmized opcode (%d)",oper >> kTFOperShift);
4471 Double_t result0 = tab[0];
4479 Int_t TFormula::PreCompile()
4481 TString str = fTitle;
4482 if (str.Length()<3)
return 1;
4483 if (str[str.Length()-1]!=
'+'&&str[str.Length()-2]!=
'+')
return 1;
4484 str[str.Length()-2]=0;
4485 TString funName(
"preformula_");
4487 if (ROOT::v5::TFormulaPrimitive::FindFormula(funName))
return 0;
4489 fileName.Form(
"/tmp/%s.C",funName.Data());
4492 hf = fopen(fileName.Data(),
"w");
4494 Error(
"PreCompile",
"Unable to open the file %s for writing.",fileName.Data());
4497 fprintf(hf,
"/////////////////////////////////////////////////////////////////////////\n");
4498 fprintf(hf,
"// This code has been automatically generated \n");
4500 fprintf(hf,
"Double_t %s(Double_t *x, Double_t *p){",funName.Data());
4501 fprintf(hf,
"return (%s);\n}",str.Data());
4525 void TFormula::SetMaxima(Int_t maxop, Int_t maxpar, Int_t maxconst)
4527 gMAXOP = TMath::Max(10,maxop);
4528 gMAXPAR = TMath::Max(10,maxpar);
4529 gMAXCONST = TMath::Max(10,maxconst);
4538 void TFormula::GetMaxima(Int_t& maxop, Int_t& maxpar, Int_t& maxconst)
4542 maxconst = gMAXCONST;