00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <math.h>
00013
00014 #include "Riostream.h"
00015 #include "TROOT.h"
00016 #include "TClass.h"
00017 #include "TFormula.h"
00018 #include "TMath.h"
00019 #include "TRandom.h"
00020 #include "TFunction.h"
00021 #include "TMethodCall.h"
00022 #include "TObjString.h"
00023 #include "TError.h"
00024 #include "TFormulaPrimitive.h"
00025
00026 #ifdef WIN32
00027 #pragma optimize("",off)
00028 #endif
00029
00030 static Int_t gMAXOP=1000,gMAXPAR=1000,gMAXCONST=1000;
00031 const Int_t gMAXSTRINGFOUND = 10;
00032 const UInt_t kOptimizationError = BIT(19);
00033
00034 ClassImp(TFormula)
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 TFormula::TFormula(): TNamed()
00128 {
00129
00130
00131
00132 fNdim = 0;
00133 fNpar = 0;
00134 fNoper = 0;
00135 fNconst = 0;
00136 fNumber = 0;
00137 fExpr = 0;
00138 fOper = 0;
00139 fConst = 0;
00140 fParams = 0;
00141 fNstring= 0;
00142 fNames = 0;
00143 fNval = 0;
00144
00145
00146 fNOperOptimized = 0;
00147 fExprOptimized = 0;
00148 fOperOptimized = 0;
00149 fOperOffset = 0;
00150 fPredefined = 0;
00151 fOptimal = (TFormulaPrimitive::TFuncG)&TFormula::EvalParOld;
00152 }
00153
00154
00155 TFormula::TFormula(const char *name,const char *expression) :
00156 TNamed(name,expression)
00157 {
00158
00159
00160
00161 fNdim = 0;
00162 fNpar = 0;
00163 fNoper = 0;
00164 fNconst = 0;
00165 fNumber = 0;
00166 fExpr = 0;
00167 fOper = 0;
00168 fConst = 0;
00169 fParams = 0;
00170 fNstring= 0;
00171 fNames = 0;
00172 fNval = 0;
00173
00174
00175 fNOperOptimized = 0;
00176 fExprOptimized = 0;
00177 fOperOptimized = 0;
00178 fOperOffset = 0;
00179 fPredefined = 0;
00180 fOptimal = (TFormulaPrimitive::TFuncG)&TFormula::EvalParOld;
00181
00182 if (!expression || !*expression) {
00183 Error("TFormula", "expression may not be 0 or have 0 length");
00184 return;
00185 }
00186
00187
00188 Int_t i,j,nch;
00189 nch = strlen(expression);
00190 char *expr = new char[nch+1];
00191 j = 0;
00192 for (i=0;i<nch;i++) {
00193 if (expression[i] == ' ') continue;
00194 if (i > 0 && (expression[i] == '*') && (expression[i-1] == '*')) {
00195 expr[j-1] = '^';
00196 continue;
00197 }
00198 expr[j] = expression[i]; j++;
00199 }
00200 expr[j] = 0;
00201 Bool_t gausNorm = kFALSE;
00202 Bool_t landauNorm = kFALSE;
00203 Bool_t linear = kFALSE;
00204
00205 if (j) {
00206 TString chaine = expr;
00207
00208 if (chaine.Contains("++"))
00209 linear = kTRUE;
00210
00211 if (chaine.Contains("gausn")) {
00212 gausNorm = kTRUE;
00213 chaine.ReplaceAll("gausn","gaus");
00214 }
00215
00216 if (chaine.Contains("landaun")) {
00217 landauNorm = kTRUE;
00218 chaine.ReplaceAll("landaun","landau");
00219 }
00220 SetTitle(chaine.Data());
00221 }
00222 delete [] expr;
00223
00224 if (linear) SetBit(kLinear);
00225
00226 if (Compile()) return;
00227
00228 if (gausNorm) SetBit(kNormalized);
00229 if (landauNorm) SetBit(kNormalized);
00230
00231
00232
00233 TFormula *old = (TFormula*)gROOT->GetListOfFunctions()->FindObject(name);
00234 if (old) {
00235 gROOT->GetListOfFunctions()->Remove(old);
00236 }
00237 if (strcmp(name,"x")==0 || strcmp(name,"y")==0 ||
00238 strcmp(name,"z")==0 || strcmp(name,"t")==0 )
00239 {
00240 Error("TFormula","The name \'%s\' is reserved as a TFormula variable name.\n"
00241 "\tThis function will not be registered in the list of functions",name);
00242 } else {
00243 gROOT->GetListOfFunctions()->Add(this);
00244 }
00245 }
00246
00247
00248 TFormula::TFormula(const TFormula &formula) : TNamed()
00249 {
00250
00251
00252 fNdim = 0;
00253 fNpar = 0;
00254 fNoper = 0;
00255 fNconst = 0;
00256 fNumber = 0;
00257 fExpr = 0;
00258 fOper = 0;
00259 fConst = 0;
00260 fParams = 0;
00261 fNstring= 0;
00262 fNames = 0;
00263 fNval = 0;
00264 fNOperOptimized = 0;
00265 fPredefined = 0;
00266 fOperOffset = 0;
00267 fExprOptimized = 0;
00268 fOperOptimized = 0;
00269
00270 ((TFormula&)formula).TFormula::Copy(*this);
00271 }
00272
00273
00274 TFormula& TFormula::operator=(const TFormula &rhs)
00275 {
00276
00277
00278 if (this != &rhs) {
00279 rhs.Copy(*this);
00280 }
00281 return *this;
00282 }
00283
00284
00285 TFormula::~TFormula()
00286 {
00287
00288
00289
00290 if (gROOT) gROOT->GetListOfFunctions()->Remove(this);
00291
00292 ClearFormula();
00293 }
00294
00295
00296 Bool_t TFormula::AnalyzeFunction(TString &chaine, Int_t &err, Int_t offset)
00297 {
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 int i,j;
00319
00320
00321
00322
00323 Ssiz_t argStart = chaine.First('(');
00324 if (argStart<0) return false;
00325
00326 TString functionName = chaine(0,argStart);
00327
00328
00329
00330 Ssiz_t scopeEnd = functionName.Last(':');
00331 TString spaceName;
00332 if (scopeEnd>0 && functionName[scopeEnd-1]==':') {
00333 spaceName = functionName(0,scopeEnd-1);
00334 functionName.Remove(0,scopeEnd+1);
00335 }
00336
00337
00338
00339 if (chaine[chaine.Length()-1] != ')') {
00340 Error("AnalyzeFunction","We thought we had a function but we dont (in %s)\n",chaine.Data());
00341 }
00342
00343 TString args = chaine(argStart+1,chaine.Length()-2-argStart);
00344 TObjArray argArr;
00345 argArr.SetOwner(kTRUE);
00346
00347
00348 Bool_t inString = false;
00349 int paran = 0;
00350 int brack = 0;
00351 int prevComma = 0;
00352 int nargs = 0;
00353 for(i=0; i<args.Length(); i++) {
00354 if (args[i]=='"') inString = !inString;
00355 if (inString) continue;
00356
00357 Bool_t foundArg = false;
00358 switch(args[i]) {
00359
00360 case '(': paran++; break;
00361 case ')': paran--; break;
00362 case '[': brack++; break;
00363 case ']': brack--; break;
00364
00365 case ',': if (paran==0 && brack==0) { foundArg = true; } break;
00366 }
00367 if ((i+1)==args.Length()) {
00368 foundArg = true; i++;
00369 }
00370 if (foundArg) {
00371 TString arg = args(prevComma,i-prevComma);
00372
00373
00374
00375
00376
00377
00378 argArr.Add(new TObjString(arg));
00379 nargs++;
00380
00381 prevComma = i+1;
00382 };
00383 }
00384
00385 if (nargs>999) {
00386 err = 7;
00387 return false;
00388 }
00389
00390
00391
00392
00393
00394 TString proto;
00395 for(j=0; j<nargs; j++) {
00396 proto += "0.0,";
00397 }
00398 if (nargs) proto.Remove(proto.Length()-1);
00399
00400
00401 TClass *ns = (spaceName.Length()) ? TClass::GetClass(spaceName) : 0;
00402 TMethodCall *method = new TMethodCall();
00403 if (ns) {
00404 method->Init(ns,functionName,proto);
00405 } else {
00406 method->Init(functionName,proto);
00407 }
00408
00409 if (method->IsValid()) {
00410 if (method->ReturnType() == TMethodCall::kOther) {
00411
00412
00413
00414
00415
00416 err=29;
00417
00418 } else {
00419
00420
00421 TIter next(&argArr);
00422 TObjString *objstr;
00423 while ( (objstr=(TObjString*)next()) ) {
00424 Analyze(objstr->String(),err,offset);
00425 }
00426
00427 fFunctions.Add(method);
00428 fExpr[fNoper] = method->GetMethod()->GetPrototype();
00429 SetAction(fNoper, kFunctionCall, fFunctions.GetLast()*1000 + nargs);
00430 fNoper++;
00431 return true;
00432 }
00433 }
00434
00435 delete method;
00436
00437
00438
00439
00440 TString cbase(chaine);
00441 Int_t args_paran = cbase.First("(");
00442 if (args_paran>0){
00443 cbase[args_paran]=0;
00444 }
00445
00446 TFormulaPrimitive *prim = TFormulaPrimitive::FindFormula(cbase, args_paran>0 ? cbase.Data() + args_paran + 1 : (const char*)0);
00447 if (prim && (!IsA()->GetBaseClass("TTreeFormula"))) {
00448
00449
00450 TIter next(&argArr);
00451 TObjString *objstr;
00452 while ( (objstr=(TObjString*)next()) ) {
00453 Analyze(objstr->String(),err,offset); if (err) return kFALSE;
00454 }
00455 if (nargs!=prim->fNArguments) {
00456 Error("Compile", "%s requires %d arguments",
00457 prim->GetName(), prim->fNArguments);
00458 return kFALSE;
00459 }
00460 fExpr[fNoper] = prim->GetName();
00461 if (prim->fType==10){
00462 SetAction(fNoper, kFD1);
00463 }
00464 if (prim->fType==110){
00465 SetAction(fNoper, kFD2);
00466 }
00467 if (prim->fType==1110){
00468 SetAction(fNoper, kFD3);
00469 }
00470 if (prim->fType==-1){
00471 SetAction(fNoper, kFDM);
00472 if (fNpar<prim->fNParameters) fNpar+=prim->fNParameters;
00473 }
00474
00475 fNoper++;
00476 return kTRUE;
00477 }
00478
00479 return kFALSE;
00480 }
00481
00482
00483
00484 void TFormula::Analyze(const char *schain, Int_t &err, Int_t offset)
00485 {
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 Int_t valeur,find,n,i,j,k,lchain,nomb,virgule,inter,nest;
00675 Int_t compt,compt2,compt3,compt4;
00676 Bool_t inString;
00677 Double_t vafConst;
00678 ULong_t vafConst2;
00679 Bool_t parenthese;
00680 TString s,chaine_error,chaine1ST;
00681 TString s1,s2,s3,ctemp;
00682
00683 TString chaine = schain;
00684 TFormula *oldformula;
00685 Int_t modulo,plus,puiss10,puiss10bis,moins,multi,divi,puiss,et,ou,petit,grand,egal,diff,peteg,grdeg,etx,oux,rshift,lshift,tercond,terelse;
00686 char t;
00687 TString slash("/"), escapedSlash("\\/");
00688 Int_t inter2 = 0;
00689 SetNumber(0);
00690 Int_t actionCode,actionParam;
00691 Int_t err_hint = 0;
00692
00693
00694
00695 lchain = chaine.Length();
00696
00697 parenthese = kTRUE;
00698 lchain = chaine.Length();
00699 while (parenthese && lchain>0 && err==0){
00700 compt = 0;
00701 compt2 = 0;
00702 inString = false;
00703 lchain = chaine.Length();
00704 if (lchain==0) err=4;
00705 else {
00706 for (i=1; i<=lchain; ++i) {
00707 if (chaine(i-1,1) == "\"") inString = !inString;
00708 if (!inString) {
00709 if (chaine(i-1,1) == "[") compt2++;
00710 if (chaine(i-1,1) == "]") compt2--;
00711 if (chaine(i-1,1) == "(") compt++;
00712 if (chaine(i-1,1) == ")") compt--;
00713 }
00714 if (compt < 0) err = 40;
00715 if (compt2< 0) err = 42;
00716 if (compt==0 && (i!=lchain || lchain==1)) parenthese = kFALSE;
00717
00718 }
00719 if (compt > 0) err = 41;
00720 if (compt2> 0) err = 43;
00721 if (parenthese) chaine = chaine(1,lchain-2);
00722 }
00723 }
00724
00725 if (lchain==0) err=4;
00726 modulo=plus=moins=multi=divi=puiss=et=ou=petit=grand=egal=diff=peteg=grdeg=etx=oux=rshift=lshift=tercond=terelse=0;
00727
00728
00729
00730
00731 if (err==0) {
00732 compt = compt2 = compt3 = compt4 = 0;puiss10=0;puiss10bis = 0;
00733 inString = false;
00734 j = lchain;
00735 Bool_t isdecimal = 1;
00736
00737 for (i=1;i<=lchain; i++) {
00738
00739 puiss10=puiss10bis=0;
00740 if (i>2) {
00741 t = chaine[i-3];
00742 isdecimal = isdecimal && (strchr("0123456789.",t)!=0);
00743 if (isdecimal) {
00744 if ( chaine[i-2] == 'e' || chaine[i-2] == 'E' ) puiss10 = 1;
00745 } else if ( strchr("+-/[]()&|><=!*/%^\\",t) ) {
00746 isdecimal = 1;
00747 }
00748 }
00749 if (j>2) {
00750 if (chaine[j-2] == 'e' || chaine[j-2] == 'E') {
00751 Bool_t isrightdecimal = 1;
00752
00753 for(k=j-3; k>=0 && isrightdecimal; --k) {
00754 t = chaine[k];
00755 isrightdecimal = isrightdecimal && (strchr("0123456789.",t)!=0);
00756 if (!isrightdecimal) {
00757 if (strchr("+-/[]()&|><=!*/%^\\",t)!=0) {
00758 puiss10bis = 1;
00759 }
00760 }
00761 }
00762 if (k<0 && isrightdecimal) puiss10bis = 1;
00763 }
00764 }
00765 if (puiss10 && (i<=lchain)) {
00766 t = chaine[i];
00767 puiss10 = (strchr("0123456789.",t)!=0);
00768 }
00769 if (puiss10bis && (j<=lchain)) {
00770 t = chaine[j];
00771 puiss10bis = (strchr("0123456789.",t)!=0);
00772 }
00773
00774 if (chaine(i-1,1) == "\"") inString = !inString;
00775 if (inString) continue;
00776 if (chaine(i-1,1) == "[") compt2++;
00777 if (chaine(i-1,1) == "]") compt2--;
00778 if (chaine(i-1,1) == "(") compt++;
00779 if (chaine(i-1,1) == ")") compt--;
00780 if (chaine(j-1,1) == "[") compt3++;
00781 if (chaine(j-1,1) == "]") compt3--;
00782 if (chaine(j-1,1) == "(") compt4++;
00783 if (chaine(j-1,1) == ")") compt4--;
00784 if (chaine(i-1,2)=="&&" && !inString && compt==0 && compt2==0 && et==0) {et=i;puiss=0;}
00785 if (chaine(i-1,2)=="||" && compt==0 && compt2==0 && ou==0) {puiss10=0; ou=i;}
00786 if (chaine(i-1,1)=="&" && compt==0 && compt2==0 && etx==0) {etx=i;puiss=0;}
00787 if (chaine(i-1,1)=="|" && compt==0 && compt2==0 && oux==0) {puiss10=0; oux=i;}
00788 if (chaine(i-1,2)==">>" && compt==0 && compt2==0 && rshift==0) {puiss10=0; rshift=i;}
00789 if (chaine(i-1,1)==">" && compt==0 && compt2==0 && rshift==0 && grand==0)
00790 {puiss10=0; grand=i;}
00791 if (chaine(i-1,2)=="<<" && compt==0 && compt2==0 && lshift==0) {puiss10=0; lshift=i;}
00792 if (chaine(i-1,1)=="<" && compt==0 && compt2==0 && lshift==0 && petit==0)
00793 {puiss10=0; petit=i;
00794
00795
00796 for(int ip = i,depth=0; ip < lchain; ++ip) {
00797 char c = chaine(ip);
00798
00799
00800 if (isalnum(c) || c=='_' || c==',') continue;
00801 if (c==':' && chaine(ip+1)==':') { ++ip; continue; }
00802 if (c=='<') { ++depth; continue; }
00803 if (c=='>') {
00804 if (depth) { --depth; continue; }
00805 else {
00806
00807 petit = 0;
00808 i = ip+1;
00809 break;
00810 }
00811 }
00812
00813 break;
00814 }
00815 if (petit==0) {
00816
00817 continue;
00818 }
00819 }
00820 if ((chaine(i-1,2)=="<=" || chaine(i-1,2)=="=<") && compt==0 && compt2==0
00821 && peteg==0) {peteg=i; puiss10=0; petit=0;}
00822 if ((chaine(i-1,2)=="=>" || chaine(i-1,2)==">=") && compt==0 && compt2==0
00823 && grdeg==0) {puiss10=0; grdeg=i; grand=0;}
00824 if (chaine(i-1,2) == "==" && compt == 0 && compt2 == 0 && egal == 0) {puiss10=0; egal=i;}
00825 if (chaine(i-1,2) == "!=" && compt == 0 && compt2 == 0 && diff == 0) {puiss10=0; diff=i;}
00826 if (i>1 && chaine(i-1,1) == "+" && compt == 0 && compt2 == 0 && puiss10==0) plus=i;
00827 if (chaine(j-1,1) == "-" && chaine(j-2,1) != "*" && chaine(j-2,1) != "/"
00828 && chaine(j-2,1)!="^" && compt3==0 && compt4==0 && moins==0 && puiss10bis==0) moins=j;
00829 if (chaine(i-1,1)=="%" && compt==0 && compt2==0 && modulo==0) {puiss10=0; modulo=i;}
00830 if (chaine(i-1,1)=="*" && compt==0 && compt2==0 && multi==0) {puiss10=0; multi=i;}
00831 if (chaine(j-1,1)=="/" && chaine(j-2,1)!="\\"
00832 && compt4==0 && compt3==0 && divi==0)
00833 {
00834 puiss10=0; divi=j;
00835 }
00836 if (chaine(j-1)=='^' && compt4==0 && compt3==0 && puiss==0) {puiss10=0; puiss=j;}
00837 if (chaine(i-1)=='?' && compt == 0 && compt2 == 0 && tercond == 0) {puiss10=0; tercond=i;}
00838 if (chaine(i-1)==':' && tercond && compt == 0 && compt2 == 0 && terelse == 0) {
00839 if (i>2 && chaine(i-2)!=':' && chaine(i)!=':') {
00840 puiss10=0; terelse=i;
00841 }
00842 }
00843
00844 j--;
00845 }
00846
00847
00848
00849
00850 enum { kIsCharacter = BIT(12) };
00851 actionParam = 0;
00852 if (tercond && terelse) {
00853 if (tercond == 1 || terelse == lchain || tercond == (terelse-1) ) {
00854 err = 5;
00855 chaine_error = "?:";
00856 } else {
00857
00858 ctemp = chaine(0,tercond-1);
00859 Analyze(ctemp.Data(),err,offset); if (err) return;
00860
00861 fExpr[fNoper] = "?: condition jump";
00862 actionCode = kJumpIf;
00863 actionParam = 0;
00864 SetAction(fNoper,actionCode, actionParam);
00865 Int_t optloc = fNoper++;
00866
00867
00868 ctemp = chaine(tercond,terelse-tercond-1);
00869 Analyze(ctemp.Data(),err,offset); if (err) return;
00870 actionParam = fNoper;
00871 SetAction(optloc, actionCode, actionParam);
00872
00873 fExpr[fNoper] = "?: else jump";
00874 actionCode = kJump;
00875 actionParam = 0;
00876
00877 SetAction(fNoper,actionCode, actionParam);
00878 optloc = fNoper++;
00879
00880
00881 ctemp = chaine(terelse,lchain-terelse);
00882 Analyze(ctemp.Data(),err,offset); if (err) return;
00883
00884 actionParam = fNoper - 1;
00885 SetAction(optloc, actionCode, actionParam);
00886
00887 if (IsString(optloc-1) != IsString(fNoper-1)) {
00888 err = 45;
00889 chaine_error = "?:";
00890 }
00891 }
00892 } else if (ou != 0) {
00893 if (ou==1 || ou==lchain-1) {
00894 err=5;
00895 chaine_error="||";
00896 }
00897 else {
00898 ctemp = chaine(0,ou-1);
00899 Analyze(ctemp.Data(),err,offset); if (err) return;
00900
00901 fExpr[fNoper] = "|| checkpoint";
00902 actionCode = kBoolOptimize;
00903 actionParam = 2;
00904 SetAction(fNoper,actionCode, actionParam);
00905 Int_t optloc = fNoper++;
00906
00907 ctemp = chaine(ou+1,lchain-ou-1);
00908 Analyze(ctemp.Data(),err,offset); if (err) return;
00909 fExpr[fNoper] = "||";
00910 actionCode = kOr;
00911 SetAction(fNoper,actionCode, 0);
00912
00913 SetAction( optloc, GetAction(optloc), GetActionParam(optloc) + (fNoper-optloc) * 10);
00914 fNoper++;
00915 if (!CheckOperands(optloc-1,fNoper-1,err)) return;
00916 }
00917 } else if (et!=0) {
00918 if (et==1 || et==lchain-1) {
00919 err=5;
00920 chaine_error="&&";
00921 }
00922 else {
00923 ctemp = chaine(0,et-1);
00924 Analyze(ctemp.Data(),err,offset); if (err) return;
00925
00926 fExpr[fNoper] = "&& checkpoint";
00927 actionCode = kBoolOptimize;
00928 actionParam = 1;
00929 SetAction(fNoper,actionCode,actionParam);
00930
00931 Int_t optloc = fNoper++;
00932
00933 ctemp = chaine(et+1,lchain-et-1);
00934 Analyze(ctemp.Data(),err,offset); if (err) return;
00935 fExpr[fNoper] = "&&";
00936 actionCode = kAnd;
00937 SetAction(fNoper,actionCode,0);
00938
00939 SetAction(optloc, GetAction(optloc), GetActionParam(optloc) + (fNoper-optloc) * 10);
00940 fNoper++;
00941 if (!CheckOperands(optloc-1,fNoper-1,err)) return;
00942 }
00943 } else if (oux!=0) {
00944 if (oux==1 || oux==lchain) {
00945 err=5;
00946 chaine_error="|";
00947 }
00948 else {
00949 ctemp = chaine(0,oux-1);
00950 Analyze(ctemp.Data(),err,offset); if (err) return;
00951 UInt_t leftopr = fNoper-1;
00952 ctemp = chaine(oux,lchain-oux);
00953 Analyze(ctemp.Data(),err,offset); if (err) return;
00954 fExpr[fNoper] = "|";
00955 actionCode = kBitOr;
00956 SetAction(fNoper,actionCode,actionParam);
00957 fNoper++;
00958 if (!CheckOperands(leftopr,fNoper-1,err)) return;
00959 }
00960 } else if (etx!=0) {
00961 if (etx==1 || etx==lchain) {
00962 err=5;
00963 chaine_error="&";
00964 }
00965 else {
00966 ctemp = chaine(0,etx-1);
00967 Analyze(ctemp.Data(),err,offset); if (err) return;
00968 UInt_t leftopr = fNoper-1;
00969 ctemp = chaine(etx,lchain-etx);
00970 Analyze(ctemp.Data(),err,offset); if (err) return;
00971 fExpr[fNoper] = "&";
00972 actionCode = kBitAnd;
00973 SetAction(fNoper,actionCode,actionParam);
00974 fNoper++;
00975 if (!CheckOperands(leftopr,fNoper-1,err)) return;
00976 }
00977 } else if (petit != 0) {
00978 if (petit==1 || petit==lchain) {
00979 err=5;
00980 chaine_error="<";
00981 }
00982 else {
00983 ctemp = chaine(0,petit-1);
00984 Analyze(ctemp.Data(),err,offset); if (err) return;
00985 UInt_t leftopr = fNoper-1;
00986 ctemp = chaine(petit,lchain-petit);
00987 Analyze(ctemp.Data(),err,offset); if (err) return;
00988 fExpr[fNoper] = "<";
00989 actionCode = kLess;
00990 SetAction(fNoper,actionCode,actionParam);
00991 fNoper++;
00992 if (!CheckOperands(leftopr,fNoper-1,err)) return;
00993 }
00994 } else if (grand != 0) {
00995 if (grand==1 || grand==lchain) {
00996 err=5;
00997 chaine_error=">";
00998 }
00999 else {
01000 ctemp = chaine(0,grand-1);
01001 Analyze(ctemp.Data(),err,offset); if (err) return;
01002 UInt_t leftopr = fNoper-1;
01003 ctemp = chaine(grand,lchain-grand);
01004 Analyze(ctemp.Data(),err,offset); if (err) return;
01005 fExpr[fNoper] = ">";
01006 actionCode = kGreater;
01007 SetAction(fNoper,actionCode,actionParam);
01008 fNoper++;
01009 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01010 }
01011 } else if (peteg != 0) {
01012 if (peteg==1 || peteg==lchain-1) {
01013 err=5;
01014 chaine_error="<=";
01015 }
01016 else {
01017 ctemp = chaine(0,peteg-1);
01018 Analyze(ctemp.Data(),err,offset); if (err) return;
01019 ctemp = chaine(peteg+1,lchain-peteg-1);
01020 UInt_t leftopr = fNoper-1;
01021 Analyze(ctemp.Data(),err,offset); if (err) return;
01022 fExpr[fNoper] = "<=";
01023 actionCode = kLessThan;
01024 SetAction(fNoper,actionCode,actionParam);
01025 fNoper++;
01026 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01027 }
01028 } else if (grdeg != 0) {
01029 if (grdeg==1 || grdeg==lchain-1) {
01030 err=5;
01031 chaine_error="=>";
01032 }
01033 else {
01034 ctemp = chaine(0,grdeg-1);
01035 Analyze(ctemp.Data(),err,offset); if (err) return;
01036 UInt_t leftopr = fNoper-1;
01037 ctemp = chaine(grdeg+1,lchain-grdeg-1);
01038 Analyze(ctemp.Data(),err,offset); if (err) return;
01039 fExpr[fNoper] = ">=";
01040 actionCode = kGreaterThan;
01041 SetAction(fNoper,actionCode,actionParam);
01042 fNoper++;
01043 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01044 }
01045 } else if (egal != 0) {
01046 if (egal==1 || egal==lchain-1) {
01047 err=5;
01048 chaine_error="==";
01049 }
01050 else {
01051 ctemp = chaine(0,egal-1);
01052 Analyze(ctemp.Data(),err,offset); if (err) return;
01053 Int_t optloc = fNoper-1;
01054
01055 ctemp = chaine(egal+1,lchain-egal-1);
01056 Analyze(ctemp.Data(),err,offset); if (err) return;
01057 fExpr[fNoper] = "==";
01058 actionCode = kEqual;
01059
01060 Bool_t isstring = IsString(fNoper-1);
01061 if (IsString(optloc) != isstring) {
01062 err = 45;
01063 chaine_error = "==";
01064 } else if (isstring) {
01065 actionCode = kStringEqual;
01066 SetBit(kIsCharacter);
01067 }
01068 SetAction(fNoper,actionCode,actionParam);
01069 fNoper++;
01070 }
01071 } else if (diff != 0) {
01072 if (diff==1 || diff==lchain-1) {
01073 err=5;
01074 chaine_error = "!=";
01075 }
01076 else {
01077 ctemp = chaine(0,diff-1);
01078 Analyze(ctemp.Data(),err,offset); if (err) return;
01079 Int_t optloc = fNoper-1;
01080
01081 ctemp = chaine(diff+1,lchain-diff-1);
01082 Analyze(ctemp.Data(),err,offset); if (err) return;
01083 fExpr[fNoper] = "!=";
01084 actionCode = kNotEqual;
01085
01086 Bool_t isstring = IsString(fNoper-1);
01087 if (IsString(optloc) != isstring) {
01088 err = 45;
01089 chaine_error = "!=";
01090 } else if (isstring) {
01091 actionCode = kStringNotEqual;
01092 SetBit(kIsCharacter);
01093 }
01094 SetAction(fNoper,actionCode,actionParam);
01095 fNoper++;
01096 }
01097 } else if (plus != 0) {
01098 if (plus==lchain) {
01099 err=5;
01100 chaine_error = "+";
01101 }
01102 else {
01103 ctemp = chaine(0,plus-1);
01104 Analyze(ctemp.Data(),err,offset); if (err) return;
01105 UInt_t leftopr = fNoper-1;
01106 ctemp = chaine(plus,lchain-plus);
01107 Analyze(ctemp.Data(),err,offset); if (err) return;
01108 fExpr[fNoper] = "+";
01109 actionCode = kAdd;
01110 SetAction(fNoper,actionCode,actionParam);
01111 fNoper++;
01112 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01113 }
01114 } else {
01115 if (moins != 0) {
01116 if (moins == 1) {
01117 ctemp = chaine(moins,lchain-moins);
01118 Analyze(ctemp.Data(),err,offset); if (err) return;
01119 fExpr[fNoper] = "-";
01120 actionCode = kSignInv;
01121 SetAction(fNoper,actionCode,actionParam);
01122 ++fNoper;
01123 if (!CheckOperands(fNoper-1,err)) return;
01124 } else {
01125 if (moins == lchain) {
01126 err=5;
01127 chaine_error = "-";
01128 } else {
01129 ctemp = chaine(0,moins-1);
01130 Analyze(ctemp.Data(),err,offset); if (err) return;
01131 UInt_t leftopr = fNoper-1;
01132 ctemp = chaine(moins,lchain-moins);
01133 Analyze(ctemp.Data(),err,offset); if (err) return;
01134 fExpr[fNoper] = "-";
01135 actionCode = kSubstract;
01136 SetAction(fNoper,actionCode,actionParam);
01137 fNoper++;
01138 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01139 }
01140 }
01141 } else if (modulo != 0) {
01142 if (modulo == 1 || modulo == lchain) {
01143 err=5;
01144 chaine_error="%";
01145 } else {
01146 ctemp = chaine(0,modulo-1);
01147 Analyze(ctemp.Data(),err,offset); if (err) return;
01148 UInt_t leftopr = fNoper-1;
01149 ctemp = chaine(modulo,lchain-modulo);
01150 Analyze(ctemp.Data(),err,offset); if (err) return;
01151 fExpr[fNoper] = "%";
01152 actionCode = kModulo;
01153 SetAction(fNoper,actionCode,actionParam);
01154 fNoper++;
01155 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01156 }
01157 } else if (rshift != 0) {
01158 if (rshift == 1 || rshift == lchain) {
01159 err=5;
01160 chaine_error=">>";
01161 } else {
01162 ctemp = chaine(0,rshift-1);
01163 Analyze(ctemp.Data(),err,offset); if (err) return;
01164 UInt_t leftopr = fNoper-1;
01165 ctemp = chaine(rshift+1,lchain-rshift-1);
01166 Analyze(ctemp.Data(),err,offset); if (err) return;
01167 fExpr[fNoper] = ">>";
01168 actionCode = kRightShift;
01169 SetAction(fNoper,actionCode,actionParam);
01170 fNoper++;
01171 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01172 }
01173 } else if (lshift != 0) {
01174 if (lshift == 1 || lshift == lchain) {
01175 err=5;
01176 chaine_error=">>";
01177 } else {
01178 ctemp = chaine(0,lshift-1);
01179 Analyze(ctemp.Data(),err,offset); if (err) return;
01180 UInt_t leftopr = fNoper-1;
01181 ctemp = chaine(lshift+1,lchain-lshift-1);
01182 Analyze(ctemp.Data(),err,offset); if (err) return;
01183 fExpr[fNoper] = ">>";
01184 actionCode = kLeftShift;
01185 SetAction(fNoper,actionCode,actionParam);
01186 fNoper++;
01187 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01188 }
01189 } else {
01190 if (multi != 0) {
01191 if (multi == 1 || multi == lchain) {
01192 err=5;
01193 chaine_error="*";
01194 }
01195 else {
01196 ctemp = chaine(0,multi-1);
01197 Analyze(ctemp.Data(),err,offset); if (err) return;
01198 UInt_t leftopr = fNoper-1;
01199 ctemp = chaine(multi,lchain-multi);
01200 Analyze(ctemp.Data(),err,offset); if (err) return;
01201 fExpr[fNoper] = "*";
01202 actionCode = kMultiply;
01203 SetAction(fNoper,actionCode,actionParam);
01204 fNoper++;
01205 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01206 }
01207 } else {
01208 if (divi != 0) {
01209 if (divi == 1 || divi == lchain) {
01210 err=5;
01211 chaine_error = "/";
01212 }
01213 else {
01214 ctemp = chaine(0,divi-1);
01215 Analyze(ctemp.Data(),err,offset); if (err) return;
01216 UInt_t leftopr = fNoper-1;
01217 ctemp = chaine(divi,lchain-divi);
01218 Analyze(ctemp.Data(),err,offset); if (err) return;
01219 fExpr[fNoper] = "/";
01220 actionCode = kDivide;
01221 SetAction(fNoper,actionCode,actionParam);
01222 fNoper++;
01223 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01224 }
01225 } else {
01226 if (puiss != 0) {
01227 if (puiss == 1 || puiss == lchain) {
01228 err = 5;
01229 chaine_error = "**";
01230 }
01231 else {
01232 if (chaine(lchain-2,2) == "^2") {
01233 ctemp = "sq(" + chaine(0,lchain-2) + ")";
01234 Analyze(ctemp.Data(),err,offset); if (err) return;
01235 } else {
01236 ctemp = chaine(0,puiss-1);
01237 Analyze(ctemp.Data(),err,offset); if (err) return;
01238 UInt_t leftopr = fNoper-1;
01239 ctemp = chaine(puiss,lchain-puiss);
01240 Analyze(ctemp.Data(),err,offset); if (err) return;
01241 fExpr[fNoper] = "^";
01242 actionCode = kpow;
01243 SetAction(fNoper,actionCode,actionParam);
01244 fNoper++;
01245 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01246 }
01247 }
01248 } else {
01249
01250 find=0;
01251
01252
01253 {
01254 Bool_t hasDot = kFALSE;
01255 Bool_t isHexa = kFALSE;
01256 Bool_t hasExpo= kFALSE;
01257 if ((chaine(0,2)=="0x")||(chaine(0,2)=="0X")) isHexa=kTRUE;
01258 for (j=0; j<chaine.Length() && err==0; j++) {
01259 t=chaine[j];
01260 if (!isHexa) {
01261 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-")) {
01262 if (hasExpo) {
01263 err=26;
01264 chaine_error=chaine;
01265 }
01266 hasExpo = kTRUE;
01267
01268
01269
01270 hasDot = kTRUE;
01271 if (chaine(j,2)=="e+" || chaine(j,2)=="e-" || chaine(j,2)=="E+" || chaine(j,2)=="E-") j++;
01272 }
01273 else {
01274 if (chaine(j,1) == "." && !hasDot) hasDot = kTRUE;
01275 else {
01276
01277
01278
01279 if (!strchr("0123456789",t) && (chaine(j,1)!="+" || j!=0)) {
01280 err = 30;
01281 chaine_error=chaine;
01282 }
01283 }
01284 }
01285 }
01286 else {
01287 if (!strchr("0123456789abcdefABCDEF",t) && (j>1)) {
01288 err = 30;
01289 chaine_error=chaine;
01290 }
01291 }
01292 }
01293 if (fNconst >= gMAXCONST) err = 27;
01294 if (!err) {
01295 if (!isHexa) {if (sscanf((const char*)chaine,"%lg",&vafConst) > 0) err = 0; else err =1;}
01296 else {if (sscanf((const char*)chaine,"%lx",&vafConst2) > 0) err = 0; else err=1;
01297 vafConst = (Double_t) vafConst2;}
01298 fExpr[fNoper] = chaine;
01299 k = -1;
01300 for (j=0;j<fNconst;j++) {
01301 if (vafConst == fConst[j] ) k= j;
01302 }
01303 if ( k < 0) { k = fNconst; fNconst++; fConst[k] = vafConst; }
01304 actionCode = kConstant;
01305 actionParam = k;
01306 SetAction(fNoper,actionCode,actionParam);
01307 fNoper++;
01308 }
01309 if (err==30) err=0;
01310 else find = kTRUE;
01311 }
01312
01313
01314
01315 if (find==0) {
01316 oldformula = (TFormula*)gROOT->GetListOfFunctions()->FindObject((const char*)chaine);
01317 if (oldformula && strcmp(schain,oldformula->GetTitle())) {
01318 Int_t nprior = fNpar;
01319 Analyze(oldformula->GetExpFormula(),err,fNpar);
01320
01321 if (err) return;
01322 fNpar = nprior;
01323 find=1;
01324 if (!err) {
01325 Int_t npold = oldformula->GetNpar();
01326 fNpar += npold;
01327 for (Int_t ipar=0;ipar<npold;ipar++) {
01328 fParams[ipar+fNpar-npold] = oldformula->GetParameter(ipar);
01329 }
01330 }
01331 }
01332 }
01333 if (find == 0) {
01334
01335
01336 ctemp = chaine;
01337 ctemp.ReplaceAll(escapedSlash, slash);
01338 Int_t action;
01339 k = DefinedVariable(ctemp,action);
01340 if (k==-3) {
01341
01342 err = 1;
01343 } if (k==-2) {
01344 err = 31;
01345 chaine_error = ctemp;
01346 } else if ( k >= 0 ) {
01347 fExpr[fNoper] = ctemp;
01348 actionCode = action;
01349 actionParam = k;
01350 SetAction(fNoper,actionCode,actionParam);
01351 if (action==kDefinedString) fNstring++;
01352 else if (k <kMAXFOUND && !fAlreadyFound.TestBitNumber(k)) {
01353 fAlreadyFound.SetBitNumber(k);
01354 fNval++;
01355 }
01356 fNoper++;
01357 } else if (chaine(0,1) == "!") {
01358 ctemp = chaine(1,lchain-1);
01359 Analyze(ctemp.Data(),err,offset); if (err) return;
01360 fExpr[fNoper] = "!";
01361 actionCode = kNot;
01362 SetAction(fNoper,actionCode,actionParam);
01363 fNoper++;
01364 if (!CheckOperands(fNoper-1,err)) return;
01365 } else if (chaine(0,1)=="\"" && chaine(chaine.Length()-1,1)=="\"") {
01366
01367 fExpr[fNoper] = chaine(1,chaine.Length()-2);
01368 actionCode = kStringConst;
01369 SetAction(fNoper,actionCode,actionParam);
01370 fNoper++;
01371 } else if (chaine(0,4) == "cos(") {
01372 ctemp = chaine(3,lchain-3);
01373 Analyze(ctemp.Data(),err,offset); if (err) return;
01374 fExpr[fNoper] = "cos";
01375 actionCode = kcos;
01376 SetAction(fNoper,actionCode,actionParam);
01377 fNoper++;
01378 if (!CheckOperands(fNoper-1,err)) return;
01379 } else if (chaine(0,4) == "sin(") {
01380 ctemp = chaine(3,lchain-3);
01381 Analyze(ctemp.Data(),err,offset); if (err) return;
01382 fExpr[fNoper] = "sin";
01383 actionCode = ksin;
01384 SetAction(fNoper,actionCode,actionParam);
01385 fNoper++;
01386 if (!CheckOperands(fNoper-1,err)) return;
01387 } else if (chaine(0,4) == "tan(") {
01388 ctemp = chaine(3,lchain-3);
01389 Analyze(ctemp.Data(),err,offset); if (err) return;
01390 fExpr[fNoper] = "tan";
01391 actionCode = ktan;
01392 SetAction(fNoper,actionCode,actionParam);
01393 fNoper++;
01394 if (!CheckOperands(fNoper-1,err)) return;
01395 } else if (chaine(0,5) == "acos(") {
01396 ctemp = chaine(4,lchain-4);
01397 Analyze(ctemp.Data(),err,offset); if (err) return;
01398 fExpr[fNoper] = "acos";
01399 actionCode = kacos;
01400 SetAction(fNoper,actionCode,actionParam);
01401 fNoper++;
01402 if (!CheckOperands(fNoper-1,err)) return;
01403 } else if (chaine(0,5) == "asin(") {
01404 ctemp = chaine(4,lchain-4);
01405 Analyze(ctemp.Data(),err,offset); if (err) return;
01406 fExpr[fNoper] = "asin";
01407 actionCode = kasin;
01408 SetAction(fNoper,actionCode,actionParam);
01409 fNoper++;
01410 if (!CheckOperands(fNoper-1,err)) return;
01411 } else if (chaine(0,5) == "atan(") {
01412 ctemp = chaine(4,lchain-4);
01413 Analyze(ctemp.Data(),err,offset); if (err) return;
01414 fExpr[fNoper] = "atan";
01415 actionCode = katan;
01416 SetAction(fNoper,actionCode,actionParam);
01417 fNoper++;
01418 if (!CheckOperands(fNoper-1,err)) return;
01419 } else if (chaine(0,5) == "cosh(") {
01420 ctemp = chaine(4,lchain-4);
01421 Analyze(ctemp.Data(),err,offset); if (err) return;
01422 fExpr[fNoper] = "cosh";
01423 actionCode = kcosh;
01424 SetAction(fNoper,actionCode,actionParam);
01425 fNoper++;
01426 if (!CheckOperands(fNoper-1,err)) return;
01427 } else if (chaine(0,5) == "sinh(") {
01428 ctemp = chaine(4,lchain-4);
01429 Analyze(ctemp.Data(),err,offset); if (err) return;
01430 fExpr[fNoper] = "sinh";
01431 actionCode = ksinh;
01432 SetAction(fNoper,actionCode,actionParam);
01433 fNoper++;;
01434 if (!CheckOperands(fNoper-1,err)) return;
01435 } else if (chaine(0,5) == "tanh(") {
01436 ctemp = chaine(4,lchain-4);
01437 Analyze(ctemp.Data(),err,offset); if (err) return;
01438 fExpr[fNoper] = "tanh";
01439 actionCode = ktanh;
01440 SetAction(fNoper,actionCode,actionParam);
01441 fNoper++;;
01442 if (!CheckOperands(fNoper-1,err)) return;
01443 } else if (chaine(0,6) == "acosh(") {
01444 ctemp = chaine(5,lchain-5);
01445 Analyze(ctemp.Data(),err,offset); if (err) return;
01446 fExpr[fNoper] = "acosh";
01447 actionCode = kacosh;
01448 SetAction(fNoper,actionCode,actionParam);
01449 fNoper++;;
01450 if (!CheckOperands(fNoper-1,err)) return;
01451 } else if (chaine(0,6) == "asinh(") {
01452 ctemp = chaine(5,lchain-5);
01453 Analyze(ctemp.Data(),err,offset); if (err) return;
01454 fExpr[fNoper] = "asinh";
01455 actionCode = kasinh;
01456 SetAction(fNoper,actionCode,actionParam);
01457 fNoper++;;
01458 if (!CheckOperands(fNoper-1,err)) return;
01459 } else if (chaine(0,6) == "atanh(") {
01460 ctemp = chaine(5,lchain-5);
01461 Analyze(ctemp.Data(),err,offset); if (err) return;
01462 fExpr[fNoper] = "atanh";
01463 actionCode = katanh;
01464 SetAction(fNoper,actionCode,actionParam);
01465 fNoper++;;
01466 if (!CheckOperands(fNoper-1,err)) return;
01467 } else if (chaine(0,3) == "sq(") {
01468 ctemp = chaine(2,lchain-2);
01469 Analyze(ctemp.Data(),err,offset); if (err) return;
01470 fExpr[fNoper] = "sq";
01471 actionCode = ksq;
01472 SetAction(fNoper,actionCode,actionParam);
01473 fNoper++;;
01474 if (!CheckOperands(fNoper-1,err)) return;
01475 } else if (chaine(0,4) == "log(") {
01476 ctemp = chaine(3,lchain-3);
01477 Analyze(ctemp.Data(),err,offset); if (err) return;
01478 fExpr[fNoper] = "log";
01479 actionCode = klog;
01480 SetAction(fNoper,actionCode,actionParam);
01481 fNoper++;;
01482 if (!CheckOperands(fNoper-1,err)) return;
01483 } else if (chaine(0,6) == "log10(") {
01484 ctemp = chaine(5,lchain-5);
01485 Analyze(ctemp.Data(),err,offset); if (err) return;
01486 fExpr[fNoper] = "log10";
01487 actionCode = klog10;
01488 SetAction(fNoper,actionCode,actionParam);
01489 fNoper++;;
01490 if (!CheckOperands(fNoper-1,err)) return;
01491 } else if (chaine(0,4) == "exp(") {
01492 ctemp = chaine(3,lchain-3);
01493 Analyze(ctemp.Data(),err,offset); if (err) return;
01494 fExpr[fNoper] = "exp";
01495 actionCode = kexp;
01496 SetAction(fNoper,actionCode,actionParam);
01497 fNoper++;;
01498 if (!CheckOperands(fNoper-1,err)) return;
01499 } else if (chaine(0,4) == "abs(") {
01500 ctemp = chaine(3,lchain-3);
01501 Analyze(ctemp.Data(),err,offset); if (err) return;
01502 fExpr[fNoper] = "abs";
01503 actionCode = kabs;
01504 SetAction(fNoper,actionCode,actionParam);
01505 fNoper++;;
01506 if (!CheckOperands(fNoper-1,err)) return;
01507 } else if (chaine(0,5) == "sign(") {
01508 ctemp = chaine(4,lchain-4);
01509 Analyze(ctemp.Data(),err,offset); if (err) return;
01510 fExpr[fNoper] = "sign";
01511 actionCode = ksign;
01512 SetAction(fNoper,actionCode,actionParam);
01513 fNoper++;;
01514 if (!CheckOperands(fNoper-1,err)) return;
01515 } else if (chaine(0,4) == "int(") {
01516 ctemp = chaine(3,lchain-3);
01517 Analyze(ctemp.Data(),err,offset); if (err) return;
01518 fExpr[fNoper] = "int";
01519 actionCode = kint;
01520 SetAction(fNoper,actionCode,actionParam);
01521 fNoper++;;
01522 if (!CheckOperands(fNoper-1,err)) return;
01523 } else if (chaine == "rndm" || chaine(0,5) == "rndm(") {
01524 fExpr[fNoper] = "rndm";
01525 actionCode = krndm;
01526 SetAction(fNoper,actionCode,actionParam);
01527 fNoper++;;
01528 } else if (chaine(0,5) == "sqrt(") {
01529 ctemp = chaine(4,lchain-4);
01530 Analyze(ctemp.Data(),err,offset); if (err) return;
01531 fExpr[fNoper] = "sqrt";
01532 actionCode = ksqrt;
01533 SetAction(fNoper,actionCode,actionParam);
01534 fNoper++;;
01535 if (!CheckOperands(fNoper-1,err)) return;
01536
01537
01538
01539 } else if ( chaine == "expo" || chaine(0,5)=="expo("
01540 || (lchain==5 && chaine(1,4)=="expo")
01541 || (lchain==6 && chaine(2,4)=="expo")
01542 || chaine(1,5)=="expo(" || chaine(2,5)=="expo(" ) {
01543 chaine1ST=chaine;
01544 if (chaine(1,4) == "expo") {
01545 ctemp=chaine(0,1);
01546 if (ctemp=="x") {
01547 inter2=0;
01548 if (fNdim < 1) fNdim = 1; }
01549 else if (ctemp=="y") {
01550 inter2=1;
01551 if (fNdim < 2) fNdim = 2; }
01552 else if (ctemp=="z") {
01553 inter2=2;
01554 if (fNdim < 3) fNdim = 3; }
01555 else if (ctemp=="t") {
01556 inter2=3;
01557 if (fNdim < 4) fNdim = 4; }
01558 else {
01559 err=26;
01560 chaine_error=chaine1ST;
01561 }
01562 chaine=chaine(1,lchain-1);
01563 lchain=chaine.Length();
01564 } else inter2=0;
01565 if (chaine(2,4) == "expo") {
01566 if (chaine(0,2) != "xy") {
01567 err=26;
01568 chaine_error=chaine1ST;
01569 }
01570 else {
01571 inter2=5;
01572 if (fNdim < 2) fNdim = 2;
01573 chaine=chaine(2,lchain-2);
01574 lchain=chaine.Length();
01575 }
01576 }
01577 if (lchain == 4) {
01578 if (fNpar>=gMAXPAR) err=7;
01579 if (!err) {
01580 fExpr[fNoper] = chaine1ST;
01581 actionCode = kexpo + inter2;
01582 actionParam = offset;
01583 SetAction(fNoper,actionCode,actionParam);
01584 if (inter2 == 5+offset && fNpar < 3+offset) fNpar = 3+offset;
01585 if (fNpar < 2+offset) fNpar = 2+offset;
01586 if (fNpar>=gMAXPAR) err=7;
01587 if (!err) {
01588 fNoper++;
01589 if (fNdim < 1) fNdim = 1;
01590 if (fNpar == 2) SetNumber(200);
01591 }
01592 }
01593 } else if (chaine(4,1) == "(") {
01594 ctemp = chaine(5,lchain-6);
01595 fExpr[fNoper] = chaine1ST;
01596 for (j=0; j<ctemp.Length(); j++) {
01597 t=ctemp[j];
01598 if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
01599 err=20;
01600 chaine_error=chaine1ST;
01601 }
01602 }
01603 if (err==0) {
01604 sscanf(ctemp.Data(),"%d",&inter);
01605 if (inter>=0) {
01606 inter += offset;
01607 actionCode = kexpo + inter2;
01608 actionParam = inter;
01609 SetAction(fNoper,actionCode,actionParam);
01610 if (inter2 == 5) inter++;
01611 if (inter+2>fNpar) fNpar = inter+2;
01612 if (fNpar>=gMAXPAR) err=7;
01613 if (!err) fNoper++;
01614 if (fNpar == 2) SetNumber(200);
01615 } else err=20;
01616 } else err = 20;
01617 } else {
01618 err=26;
01619 chaine_error=chaine;
01620 }
01621
01622
01623 } else if (chaine=="gaus"
01624 || (lchain==5 && chaine(1,4)=="gaus")
01625 || (lchain==6 && chaine(2,4)=="gaus")
01626 || chaine(0,5)=="gaus(" || chaine(1,5)=="gaus(" || chaine(2,5)=="gaus(") {
01627 chaine1ST=chaine;
01628 if (chaine(1,4) == "gaus") {
01629 ctemp=chaine(0,1);
01630 if (ctemp=="x") {
01631 inter2=0;
01632 if (fNdim < 1) fNdim = 1; }
01633 else if (ctemp=="y") {
01634 inter2=1;
01635 if (fNdim < 2) fNdim = 2; }
01636 else if (ctemp=="z") {
01637 inter2=2;
01638 if (fNdim < 3) fNdim = 3; }
01639 else if (ctemp=="t") {
01640 inter2=3;
01641 if (fNdim < 4) fNdim = 4; }
01642 else {
01643 err=26;
01644 chaine_error=chaine1ST;
01645 }
01646 chaine=chaine(1,lchain-1);
01647 lchain=chaine.Length();
01648 } else inter2=0;
01649 if (chaine(2,4) == "gaus") {
01650 if (chaine(0,2) != "xy") {
01651 err=26;
01652 chaine_error=chaine1ST;
01653 }
01654 else {
01655 inter2=5;
01656 if (fNdim < 2) fNdim = 2;
01657 chaine=chaine(2,lchain-2);
01658 lchain=chaine.Length();
01659 SetNumber(110);
01660 }
01661 }
01662 if (lchain == 4 && err==0) {
01663 if (fNpar>=gMAXPAR) err=7;
01664 if (!err) {
01665 fExpr[fNoper] = chaine1ST;
01666 actionCode = kgaus + inter2;
01667 actionParam = offset;
01668 SetAction(fNoper,actionCode,actionParam);
01669 if (inter2 == 5+offset && fNpar < 5+offset) fNpar = 5+offset;
01670 if (3+offset>fNpar) fNpar = 3+offset;
01671 if (fNpar>=gMAXPAR) err=7;
01672 if (!err) {
01673 fNoper++;
01674 if (fNdim < 1) fNdim = 1;
01675 if (fNpar == 3) SetNumber(100);
01676 }
01677 }
01678 } else if (chaine(4,1) == "(" && err==0) {
01679 ctemp = chaine(5,lchain-6);
01680 fExpr[fNoper] = chaine1ST;
01681 for (j=0; j<ctemp.Length(); j++) {
01682 t=ctemp[j];
01683 if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
01684 err=20;
01685 chaine_error=chaine1ST;
01686 }
01687 }
01688 if (err==0) {
01689 sscanf(ctemp.Data(),"%d",&inter);
01690 if (inter >= 0) {
01691 inter += offset;
01692 actionCode = kgaus + inter2;
01693 actionParam = inter;
01694 SetAction(fNoper,actionCode,actionParam);
01695 if (inter2 == 5) inter += 2;
01696 if (inter+3>fNpar) fNpar = inter+3;
01697 if (fNpar>=gMAXPAR) err=7;
01698 if (!err) fNoper++;
01699 if(fNpar == 3) SetNumber(100);
01700 } else err = 20;
01701 }
01702 } else if (err==0) {
01703 err=26;
01704 chaine_error=chaine1ST;
01705 }
01706
01707
01708 } else if (chaine=="landau" || (lchain==7 && chaine(1,6)=="landau")
01709 || (lchain==8 && chaine(2,6)=="landau")
01710 || chaine(0,7)=="landau(" || chaine(1,7)=="landau(" || chaine(2,7)=="landau(") {
01711 chaine1ST=chaine;
01712 if (chaine(1,6) == "landau") {
01713 ctemp=chaine(0,1);
01714 if (ctemp=="x") {
01715 inter2=0;
01716 if (fNdim < 1) fNdim = 1; }
01717 else if (ctemp=="y") {
01718 inter2=1;
01719 if (fNdim < 2) fNdim = 2; }
01720 else if (ctemp=="z") {
01721 inter2=2;
01722 if (fNdim < 3) fNdim = 3; }
01723 else if (ctemp=="t") {
01724 inter2=3;
01725 if (fNdim < 4) fNdim = 4; }
01726 else {
01727 err=26;
01728 chaine_error=chaine1ST;
01729 }
01730 chaine=chaine(1,lchain-1);
01731 lchain=chaine.Length();
01732 } else inter2=0;
01733 if (chaine(2,6) == "landau") {
01734 if (chaine(0,2) != "xy") {
01735 err=26;
01736 chaine_error=chaine1ST;
01737 }
01738 else {
01739 inter2=5;
01740 if (fNdim < 2) fNdim = 2;
01741 chaine=chaine(2,lchain-2);
01742 lchain=chaine.Length();
01743 SetNumber(410);
01744 }
01745 }
01746 if (lchain == 6 && err==0) {
01747 if (fNpar>=gMAXPAR) err=7;
01748 if (!err) {
01749 fExpr[fNoper] = chaine1ST;
01750 actionCode = klandau + inter2;
01751 actionParam = offset;
01752 SetAction(fNoper,actionCode,actionParam);
01753 if (inter2 == 5+offset && fNpar < 5+offset) fNpar = 5+offset;
01754 if (3+offset>fNpar) fNpar = 3+offset;
01755 if (fNpar>=gMAXPAR) err=7;
01756 if (!err) {
01757 fNoper++;
01758 if (fNdim < 1) fNdim = 1;
01759 if (fNpar == 3) SetNumber(400);
01760 }
01761 }
01762 } else if (chaine(6,1) == "(" && err==0) {
01763 ctemp = chaine(7,lchain-8);
01764 fExpr[fNoper] = chaine1ST;
01765 for (j=0; j<ctemp.Length(); j++) {
01766 t=ctemp[j];
01767 if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
01768 err=20;
01769 chaine_error=chaine1ST;
01770 }
01771 }
01772 if (err==0) {
01773 sscanf(ctemp.Data(),"%d",&inter);
01774 if (inter >= 0) {
01775 inter += offset;
01776 actionCode = klandau + inter2;
01777 actionParam = inter;
01778 SetAction(fNoper,actionCode,actionParam);
01779 if (inter2 == 5) inter += 2;
01780 if (inter+3>fNpar) fNpar = inter+3;
01781 if (fNpar>=gMAXPAR) err=7;
01782 if (!err) fNoper++;
01783 if (fNpar == 3) SetNumber(400);
01784 } else err = 20;
01785 }
01786 } else if (err==0) {
01787 err=26;
01788 chaine_error=chaine1ST;
01789 }
01790
01791
01792 } else if (chaine(0,3) == "pol" || chaine(1,3) == "pol") {
01793 chaine1ST=chaine;
01794 if (chaine(1,3) == "pol") {
01795 ctemp=chaine(0,1);
01796 if (ctemp=="x") {
01797 inter2=1;
01798 if (fNdim < 1) fNdim = 1; }
01799 else if (ctemp=="y") {
01800 inter2=2;
01801 if (fNdim < 2) fNdim = 2; }
01802 else if (ctemp=="z") {
01803 inter2=3;
01804 if (fNdim < 3) fNdim = 3; }
01805 else if (ctemp=="t") {
01806 inter2=4;
01807 if (fNdim < 4) fNdim = 4; }
01808 else {
01809 err=26;
01810 chaine_error=chaine1ST;
01811 }
01812 chaine=chaine(1,lchain-1);
01813 lchain=chaine.Length();
01814 } else inter2=1;
01815 if (chaine(lchain-1,1) == ")") {
01816 nomb = 0;
01817 for (j=3;j<lchain;j++) if (chaine(j,1)=="(" && nomb == 0) nomb = j;
01818 if (nomb == 3) err = 23;
01819 if (nomb == 0) err = 40;
01820 ctemp = chaine(nomb+1,lchain-nomb-2);
01821 for (j=0; j<ctemp.Length(); j++) {
01822 t=ctemp[j];
01823 if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
01824 err=20;
01825 chaine_error=chaine1ST;
01826 }
01827 }
01828 if (!err) {
01829 sscanf(ctemp.Data(),"%d",&inter);
01830 if (inter < 0) err = 20;
01831 }
01832 }
01833 else {
01834 nomb = lchain;
01835 inter = 0;
01836 }
01837 if (!err) {
01838 inter--;
01839 ctemp = chaine(3,nomb-3);
01840 if (sscanf(ctemp.Data(),"%d",&n) > 0) {
01841 if (n < 0 ) err = 24;
01842 if (n >= 20) err = 25;
01843 } else err = 20;
01844 }
01845 if (!err) {
01846 fExpr[fNoper] = chaine1ST;
01847 actionCode = kpol+(inter2-1);
01848 actionParam = n*100+inter+2;
01849 SetAction(fNoper,actionCode,actionParam);
01850 if (inter+n+1>=fNpar) fNpar = inter + n + 2;
01851 if (fNpar>=gMAXPAR) err=7;
01852 if (!err) {
01853 fNoper++;
01854 if (fNdim < 1) fNdim = 1;
01855 SetNumber(300+n);
01856 }
01857 }
01858
01859
01860 } else if (chaine(0,4) == "pow(") {
01861 compt = 4; nomb = 0; virgule = 0; nest=0;
01862 while(compt != lchain) {
01863 compt++;
01864 if (chaine(compt-1,1) == "(") nest++;
01865 else if (chaine(compt-1,1) == ")") nest--;
01866 else if (chaine(compt-1,1) == "," && nest==0) {
01867 nomb++;
01868 if (nomb == 1 && virgule == 0) virgule = compt;
01869 }
01870 }
01871 if (nomb != 1) err = 22;
01872 else {
01873 ctemp = chaine(4,virgule-5);
01874 Analyze(ctemp.Data(),err,offset); if (err) return;
01875 UInt_t leftopr = fNoper-1;
01876 ctemp = chaine(virgule,lchain-virgule-1);
01877 Analyze(ctemp.Data(),err,offset); if (err) return;
01878 fExpr[fNoper] = "^";
01879 actionCode = kpow;
01880 SetAction(fNoper,actionCode,actionParam);
01881 fNoper++;
01882 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01883 }
01884 } else if (chaine(0,7) == "strstr(") {
01885 compt = 7; nomb = 0; virgule = 0; nest=0;
01886 inString = false;
01887 while(compt != lchain) {
01888 compt++;
01889 if (chaine(compt-1,1) == "\"") {
01890 inString = !inString;
01891 } else if (!inString) {
01892 if (chaine(compt-1,1) == "(") nest++;
01893 else if (chaine(compt-1,1) == ")") nest--;
01894 else if (chaine(compt-1,1) == "," && nest==0) {
01895 nomb++;
01896 if (nomb == 1 && virgule == 0) virgule = compt;
01897 }
01898 }
01899 }
01900 if (nomb != 1) err = 28;
01901 else {
01902 ctemp = chaine(7,virgule-8);
01903 Analyze(ctemp.Data(),err,offset); if (err) return;
01904 Int_t optloc = fNoper-1;
01905
01906 ctemp = chaine(virgule,lchain-virgule-1);
01907 Analyze(ctemp.Data(),err,offset); if (err) return;
01908 fExpr[fNoper] = "strstr";
01909 actionCode = kstrstr;
01910 SetAction(fNoper,actionCode,actionParam);
01911 fNoper++;
01912
01913 if ( !IsString(optloc) || !IsString(fNoper-2) ) {
01914 err = 46;
01915 chaine_error = "strstr";
01916 }
01917 }
01918 } else if (chaine(0,4) == "min(") {
01919 compt = 4; nomb = 0; virgule = 0; nest=0;
01920 while(compt != lchain) {
01921 compt++;
01922 if (chaine(compt-1,1) == "(") nest++;
01923 else if (chaine(compt-1,1) == ")") nest--;
01924 else if (chaine(compt-1,1) == "," && nest==0) {
01925 nomb++;
01926 if (nomb == 1 && virgule == 0) virgule = compt;
01927 }
01928 }
01929 if (nomb != 1) {
01930 err = 44;
01931 err_hint = 3;
01932 }
01933 else {
01934 ctemp = chaine(4,virgule-5);
01935 Analyze(ctemp.Data(),err,offset); if (err) return;
01936 UInt_t leftopr = fNoper-1;
01937 ctemp = chaine(virgule,lchain-virgule-1);
01938 Analyze(ctemp.Data(),err,offset); if (err) return;
01939 fExpr[fNoper] = "min";
01940 actionCode = kmin;
01941 SetAction(fNoper,actionCode,actionParam);
01942 fNoper++;
01943 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01944 }
01945 } else if (chaine(0,4) == "max(") {
01946 compt = 4; nomb = 0; virgule = 0; nest=0;
01947 while(compt != lchain) {
01948 compt++;
01949 if (chaine(compt-1,1) == "(") nest++;
01950 else if (chaine(compt-1,1) == ")") nest--;
01951 else if (chaine(compt-1,1) == "," && nest==0) {
01952 nomb++;
01953 if (nomb == 1 && virgule == 0) virgule = compt;
01954 }
01955 }
01956 if (nomb != 1) {
01957 err = 44;
01958 err_hint = 3;
01959 }
01960 else {
01961 ctemp = chaine(4,virgule-5);
01962 Analyze(ctemp.Data(),err,offset); if (err) return;
01963 UInt_t leftopr = fNoper-1;
01964 ctemp = chaine(virgule,lchain-virgule-1);
01965 Analyze(ctemp.Data(),err,offset); if (err) return;
01966 fExpr[fNoper] = "max";
01967 actionCode = kmax;
01968 SetAction(fNoper,actionCode,actionParam);
01969 fNoper++;
01970 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01971 }
01972
01973 } else if (chaine(0,6) == "atan2(") {
01974 compt = 6; nomb = 0; virgule = 0; nest=0;
01975 while(compt != lchain) {
01976 compt++;
01977 if (chaine(compt-1,1) == "(") nest++;
01978 else if (chaine(compt-1,1) == ")") nest--;
01979 else if (chaine(compt-1,1) == "," && nest==0) {
01980 nomb++;
01981 if (nomb == 1 && virgule == 0) virgule = compt;
01982 }
01983 }
01984 if (nomb != 1) err = 21;
01985 else {
01986 ctemp = chaine(6,virgule-7);
01987 Analyze(ctemp.Data(),err,offset); if (err) return;
01988 UInt_t leftopr = fNoper-1;
01989 ctemp = chaine(virgule,lchain-virgule-1);
01990 Analyze(ctemp.Data(),err,offset); if (err) return;
01991 fExpr[fNoper] = "atan2";
01992 actionCode = katan2;
01993 SetAction(fNoper,actionCode,actionParam);
01994 fNoper++;
01995 if (!CheckOperands(leftopr,fNoper-1,err)) return;
01996 }
01997 } else if (chaine(0,5) == "fmod(") {
01998 compt = 5; nomb = 0; virgule = 0; nest=0;
01999 while(compt != lchain) {
02000 compt++;
02001 if (chaine(compt-1,1) == "(") nest++;
02002 else if (chaine(compt-1,1) == ")") nest--;
02003 else if (chaine(compt-1,1) == "," && nest==0) {
02004 nomb++;
02005 if (nomb == 1 && virgule == 0) virgule = compt;
02006 }
02007 }
02008 if (nomb != 1) {
02009 err = 44;
02010 err_hint = 4;
02011 }
02012 else {
02013 ctemp = chaine(5,virgule-6);
02014 Analyze(ctemp.Data(),err,offset); if (err) return;
02015 UInt_t leftopr = fNoper-1;
02016 ctemp = chaine(virgule,lchain-virgule-1);
02017 Analyze(ctemp.Data(),err,offset); if (err) return;
02018 fExpr[fNoper] = "fmod";
02019 actionCode = kfmod;
02020 SetAction(fNoper,actionCode,actionParam);
02021 fNoper++;
02022 if (!CheckOperands(leftopr,fNoper-1,err)) return;
02023 }
02024 } else if (AnalyzeFunction(chaine,err,offset) || err) {
02025 if (err) {
02026 chaine_error = chaine;
02027 } else {
02028
02029
02030
02031 }
02032 } else if (chaine(0,1) == "[" && chaine(lchain-1,1) == "]") {
02033 fExpr[fNoper] = chaine;
02034 fNoper++;
02035 ctemp = chaine(1,lchain-2);
02036 for (j=0; j<ctemp.Length(); j++) {
02037 t=ctemp[j];
02038 if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
02039 err=20;
02040 chaine_error=chaine1ST;
02041 }
02042 }
02043 if (!err) {
02044 sscanf(ctemp.Data(),"%d",&valeur);
02045 actionCode = kParameter;
02046 actionParam = offset + valeur;
02047 SetAction(fNoper-1, actionCode, actionParam);
02048 fExpr[fNoper-1] = "[";
02049 fExpr[fNoper-1] = (fExpr[fNoper-1] + (long int)(valeur+offset)) + "]";
02050 }
02051 } else if (chaine == "pi") {
02052 fExpr[fNoper] = "pi";
02053 actionCode = kpi;
02054 SetAction(fNoper,actionCode,actionParam);
02055 fNoper++;
02056 }
02057 else {
02058
02059
02060 err = 30;
02061 }
02062 }
02063 }
02064 }
02065 }
02066 }
02067 }
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084 if (fNoper>=gMAXOP) err=6;
02085
02086 }
02087
02088
02089 if (err>1) {
02090 TString er = "";
02091 chaine_error = "\""+chaine_error+"\"";
02092 switch(err) {
02093 case 2 : er = " Invalid Floating Point Operation"; break;
02094 case 4 : er = " Empty String"; break;
02095 case 5 : er = " Invalid Syntax " + chaine_error; break;
02096 case 6 : er = " Too many operators !"; break;
02097 case 7 : er = " Too many parameters !"; break;
02098 case 10 : er = " z specified but not x and y"; break;
02099 case 11 : er = " z and y specified but not x"; break;
02100 case 12 : er = " y specified but not x"; break;
02101 case 13 : er = " z and x specified but not y"; break;
02102 case 20 : er = " Non integer value for parameter number : " + chaine_error; break;
02103 case 21 : er = " ATAN2 requires two arguments"; break;
02104 case 22 : er = " POW requires two arguments"; break;
02105 case 23 : er = " Degree of polynomial not specified"; break;
02106 case 24 : er = " Degree of polynomial must be positive"; break;
02107 case 25 : er = " Degree of polynomial must be less than 20"; break;
02108 case 26 : er = " Unknown name : " + chaine_error; break;
02109 case 27 : er = " Too many constants in expression"; break;
02110 case 28 : er = " strstr requires two arguments"; break;
02111 case 29 : er = " TFormula can only call interpreted and compiled functions that return a numerical type: " + chaine_error; break;
02112 case 30 : er = " Bad numerical expression : " + chaine_error; break;
02113 case 31 : er = " Part of the Variable " + chaine_error; er += " exists but some of it is not accessible or useable"; break;
02114 case 40 : er = " '(' is expected"; break;
02115 case 41 : er = " ')' is expected"; break;
02116 case 42 : er = " '[' is expected"; break;
02117 case 43 : er = " ']' is expected"; break;
02118 case 44 : er = " The function '" + chaine(0,err_hint) + "' requires two arguments."; break;
02119 case 45 : er = "The operator " + chaine_error + " requires a numerical operand."; break;
02120 case 46 : er = "Both operands of the operator " + chaine_error + " have to be either numbers or strings."; break;
02121 case 47 : er = chaine_error + " requires 2 string arguments"; break;
02122 }
02123 Error("Compile", "%s", er.Data());
02124 err=1;
02125 }
02126
02127 }
02128
02129
02130 Bool_t TFormula::CheckOperands(Int_t oper, Int_t &err)
02131 {
02132
02133
02134 if ( IsString(oper-1) && !StringToNumber(oper-1) ) {
02135 Error("Compile","\"%s\" requires a numerical operand.",fExpr[oper].Data());
02136 err = 45;
02137 return kFALSE;
02138 }
02139 return kTRUE;
02140 }
02141
02142
02143 Bool_t TFormula::CheckOperands(Int_t leftoper, Int_t oper, Int_t &err)
02144 {
02145
02146
02147 if ( IsString(oper-1) || IsString(leftoper) ) {
02148 if (IsString(oper-1) && StringToNumber(oper-1)) {
02149 return kTRUE;
02150 }
02151 if (IsString(leftoper) && StringToNumber(leftoper)) {
02152 return kTRUE;
02153 }
02154 Error("Compile","\"%s\" requires two numerical operands.",fExpr[oper].Data());
02155 err = 46;
02156 return kFALSE;
02157 }
02158 return kTRUE;
02159 }
02160
02161
02162 Bool_t TFormula::StringToNumber(Int_t )
02163 {
02164
02165
02166
02167
02168 return kFALSE;
02169 }
02170
02171
02172 void TFormula::Clear(Option_t * )
02173 {
02174
02175
02176
02177
02178
02179
02180 ClearFormula();
02181 }
02182
02183
02184 void TFormula::ClearFormula(Option_t * )
02185 {
02186
02187
02188
02189
02190
02191
02192 fNdim = 0;
02193 fNpar = 0;
02194 fNoper = 0;
02195 fNconst = 0;
02196 fNumber = 0;
02197 fNstring= 0;
02198 fNval = 0;
02199
02200 if (fExpr) { delete [] fExpr; fExpr = 0;}
02201 if (fNames) { delete [] fNames; fNames = 0;}
02202 if (fOper) { delete [] fOper; fOper = 0;}
02203 if (fConst) { delete [] fConst; fConst = 0;}
02204 if (fParams) { delete [] fParams; fParams = 0;}
02205 fFunctions.Delete();
02206 fLinearParts.Delete();
02207
02208
02209 if (fPredefined) { delete [] fPredefined; fPredefined = 0;}
02210 if (fOperOffset) { delete [] fOperOffset; fOperOffset = 0;}
02211 if (fExprOptimized) { delete [] fExprOptimized; fExprOptimized = 0;}
02212 if (fOperOptimized) { delete [] fOperOptimized; fOperOptimized = 0;}
02213
02214
02215
02216 }
02217
02218
02219 Int_t TFormula::Compile(const char *expression)
02220 {
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250 Int_t i,j,lc,valeur,err;
02251 TString ctemp;
02252
02253 ClearFormula();
02254
02255
02256 if (strlen(expression)) SetTitle(expression);
02257
02258 TString chaine = GetTitle();
02259
02260 if (chaine.Contains(";")) {
02261 char *sctemp = new char[chaine.Length()+1];
02262 strlcpy(sctemp,chaine.Data(),chaine.Length()+1);
02263 char *semicol = (char*)strstr(sctemp,";");
02264 if (semicol) *semicol = 0;
02265 chaine = sctemp;
02266 delete [] sctemp;
02267 }
02268
02269
02270
02271 if (TestBit(kLinear)){
02272 ProcessLinear(chaine);
02273 }
02274
02275
02276 fExpr = new TString[gMAXOP];
02277 fConst = new Double_t[gMAXCONST];
02278 fParams = new Double_t[gMAXPAR];
02279 fNames = new TString[gMAXPAR];
02280 fOper = new Int_t[gMAXOP];
02281 for (i=0; i<gMAXPAR; i++) {
02282 fParams[i] = 0;
02283 fNames[i] = "";
02284 }
02285 for (i=0; i<gMAXOP; i++) {
02286 fExpr[i] = "";
02287 fOper[i] = 0;
02288 }
02289 for (i=0; i<gMAXCONST; i++)
02290 fConst[i] = 0;
02291
02292
02293
02294 Bool_t inString = false;
02295 for (i=1; i<=chaine.Length(); i++) {
02296 lc =chaine.Length();
02297 if (chaine(i-1,1) == "\"") inString = !inString;
02298 if (inString) continue;
02299 if (chaine(i-1,2) == "**") {
02300 chaine = chaine(0,i-1) + "^" + chaine(i+1,lc-i-1);
02301 i=0;
02302 } else if (chaine(i-1,2) == "++") {
02303 chaine = chaine(0,i) + chaine(i+1,lc-i-1);
02304 i=0;
02305 } else if (chaine(i-1,2) == "+-" || chaine(i-1,2) == "-+") {
02306 chaine = chaine(0,i-1) + "-" + chaine(i+1,lc-i-1);
02307 i=0;
02308 } else if (chaine(i-1,2) == "--") {
02309 chaine = chaine(0,i-1) + "+" + chaine(i+1,lc-i-1);
02310 i=0;
02311 } else if (chaine(i-1,2) == "->") {
02312 chaine = chaine(0,i-1) + "." + chaine(i+1,lc-i-1);
02313 i=0;
02314 } else if (chaine(i-1,1) == "[") {
02315 for (j=1;j<=chaine.Length()-i;j++) {
02316 if (chaine(j+i-1,1) == "]" || j+i > chaine.Length()) break;
02317 }
02318 ctemp = chaine(i,j-1);
02319 valeur=0;
02320 sscanf(ctemp.Data(),"%d",&valeur);
02321 if (valeur >= fNpar) fNpar = valeur+1;
02322 } else if (chaine(i-1,1) == " ") {
02323 chaine = chaine(0,i-1)+chaine(i,lc-i);
02324 i=0;
02325 }
02326 }
02327 err = 0;
02328 Analyze((const char*)chaine,err);
02329
02330
02331 if (!fNpar) {
02332 delete [] fParams; fParams = 0;
02333 delete [] fNames; fNames = 0;
02334 }
02335
02336
02337 if (!err) {
02338 if (fNdim <= 0) fNdim = 1;
02339 if (chaine.Length() > 4)
02340 {
02341 if ( GetNumber() != 400 &&
02342 GetNumber() != 410 &&
02343 GetNumber() != 110 )
02344 SetNumber(0);
02345 else if ( GetNumber() == 110 && chaine.Length() > 6 )
02346 SetNumber(0);
02347 else if ( GetNumber() == 410 && chaine.Length() > 8 )
02348 SetNumber(0);
02349 }
02350
02351 if (GetNumber() == 100) {
02352 SetParName(0,"Constant");
02353 SetParName(1,"Mean");
02354 SetParName(2,"Sigma");
02355 }
02356
02357 if (GetNumber() == 110){
02358 SetParName(0,"Constant");
02359 SetParName(1,"MeanX");
02360 SetParName(2,"SigmaX");
02361 SetParName(3,"MeanY");
02362 SetParName(4,"SigmaY");
02363 }
02364
02365 if (GetNumber() == 200) {
02366 SetParName(0,"Constant");
02367 SetParName(1,"Slope");
02368 }
02369
02370 if (GetNumber() == 300+fNpar) {
02371 for (i=0;i<fNpar;i++) SetParName(i,Form("p%d",i));
02372 }
02373
02374 if (GetNumber() == 400) {
02375 SetParName(0,"Constant");
02376 SetParName(1,"MPV");
02377 SetParName(2,"Sigma");
02378 }
02379
02380 if (GetNumber() == 410) {
02381 SetParName(0,"Constant");
02382 SetParName(1,"MPVX");
02383 SetParName(2,"SigmaX");
02384 SetParName(3,"MPVY");
02385 SetParName(4,"SigmaY");
02386 }
02387 }
02388
02389 if (err) { fNdim = 0; return 1; }
02390
02391
02392
02393 if (!IsA()->GetBaseClass("TTreeFormula")) {
02394 Optimize();
02395 }
02396
02397 return 0;
02398 }
02399
02400
02401 void TFormula::Copy(TObject &obj) const
02402 {
02403
02404
02405
02406 Int_t i;
02407 ((TFormula&)obj).ClearFormula();
02408 TNamed::Copy(obj);
02409 ((TFormula&)obj).fNdim = fNdim;
02410 ((TFormula&)obj).fNpar = fNpar;
02411 ((TFormula&)obj).fNoper = fNoper;
02412 ((TFormula&)obj).fNconst = fNconst;
02413 ((TFormula&)obj).fNumber = fNumber;
02414 ((TFormula&)obj).fNval = fNval;
02415 ((TFormula&)obj).fExpr = 0;
02416 ((TFormula&)obj).fConst = 0;
02417 ((TFormula&)obj).fParams = 0;
02418 ((TFormula&)obj).fNames = 0;
02419 if (fExpr && fNoper) {
02420 ((TFormula&)obj).fExpr = new TString[fNoper];
02421 for (i=0;i<fNoper;i++) ((TFormula&)obj).fExpr[i] = fExpr[i];
02422 }
02423 if (fOper && fNoper) {
02424 ((TFormula&)obj).fOper = new Int_t[fNoper];
02425 for (i=0;i<fNoper;i++) ((TFormula&)obj).fOper[i] = fOper[i];
02426 }
02427 if (fConst && fNconst) {
02428 ((TFormula&)obj).fConst = new Double_t[fNconst];
02429 for (i=0;i<fNconst;i++) ((TFormula&)obj).fConst[i] = fConst[i];
02430 }
02431 if (fParams && fNpar) {
02432 ((TFormula&)obj).fParams = new Double_t[fNpar];
02433 for (i=0;i<fNpar;i++) ((TFormula&)obj).fParams[i] = fParams[i];
02434 }
02435 if (fNames && fNpar) {
02436 ((TFormula&)obj).fNames = new TString[fNpar];
02437 for (i=0;i<fNpar;i++) ((TFormula&)obj).fNames[i] = fNames[i];
02438 }
02439
02440 TIter next(&fFunctions);
02441 TObject *fobj;
02442 while ( (fobj = next()) ) {
02443 ((TFormula&)obj).fFunctions.Add( fobj->Clone() );
02444 }
02445
02446
02447
02448
02449 if (fNoper) {
02450 if(fExprOptimized) {
02451 ((TFormula&)obj).fExprOptimized = new TString[fNoper];
02452 for (i=0;i<fNoper;i++) ((TFormula&)obj).fExprOptimized[i] = fExprOptimized[i];
02453 }
02454 if (fOperOptimized) {
02455 ((TFormula&)obj).fOperOptimized = new Int_t[fNoper];
02456 for (i=0;i<fNoper;i++) ((TFormula&)obj).fOperOptimized[i] = fOperOptimized[i];
02457 }
02458 if (fPredefined) {
02459 ((TFormula&)obj).fPredefined = new TFormulaPrimitive*[fNoper];
02460 for (i=0;i<fNoper;i++) {((TFormula&)obj).fPredefined[i] = fPredefined[i];}
02461 }
02462 if (fOperOffset) {
02463 ((TFormula&)obj).fOperOffset = new TOperOffset[fNoper];
02464 for (i=0;i<fNoper;i++) {((TFormula&)obj).fOperOffset[i] = fOperOffset[i];}
02465 }
02466 }
02467 ((TFormula&)obj).fNOperOptimized = fNOperOptimized;
02468 ((TFormula&)obj).fOptimal = fOptimal;
02469
02470 }
02471
02472
02473 char *TFormula::DefinedString(Int_t)
02474 {
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498 return 0;
02499 }
02500
02501
02502 Double_t TFormula::DefinedValue(Int_t)
02503 {
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527 return 0;
02528 }
02529
02530
02531 Int_t TFormula::DefinedVariable(TString &chaine,Int_t &action)
02532 {
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561 action = kVariable;
02562 if (chaine == "x") {
02563 if (fNdim < 1) fNdim = 1;
02564 return 0;
02565 } else if (chaine == "y") {
02566 if (fNdim < 2) fNdim = 2;
02567 return 1;
02568 } else if (chaine == "z") {
02569 if (fNdim < 3) fNdim = 3;
02570 return 2;
02571 } else if (chaine == "t") {
02572 if (fNdim < 4) fNdim = 4;
02573 return 3;
02574 }
02575
02576
02577
02578 if (chaine.Data()[0]=='x'){
02579 if (chaine.Data()[1]=='[' && chaine.Data()[3]==']'){
02580 const char ch0 = '0';
02581 Int_t dim = chaine.Data()[2]-ch0;
02582 if (dim<0) return -1;
02583 if (dim>9) return -1;
02584 if (fNdim<=dim) fNdim = dim+1;
02585 return dim;
02586 }
02587 if (chaine.Data()[1]=='[' && chaine.Data()[4]==']'){
02588 const char ch0 = '0';
02589 Int_t dim = (chaine.Data()[2]-ch0)*10+(chaine.Data()[3]-ch0);
02590 if (dim<0) return -1;
02591 if (dim>99) return -1;
02592 if (fNdim<=dim) fNdim = dim+1;
02593 return dim;
02594 }
02595 }
02596 return -1;
02597 }
02598
02599
02600 Double_t TFormula::Eval(Double_t x, Double_t y, Double_t z, Double_t t) const
02601 {
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611 Double_t xx[4];
02612 xx[0] = x;
02613 xx[1] = y;
02614 xx[2] = z;
02615 xx[3] = t;
02616 return ((TFormula*)this)->EvalPar(xx);
02617 }
02618
02619
02620 Double_t TFormula::EvalParOld(const Double_t *x, const Double_t *uparams)
02621 {
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637 Int_t i,j;
02638 Double_t tab[kMAXFOUND];
02639 const char *stringStack[gMAXSTRINGFOUND];
02640 Double_t param_calc[kMAXFOUND];
02641 char *string_calc[gMAXSTRINGFOUND];
02642 Int_t precalculated = 0;
02643 Int_t precalculated_str = 0;
02644 Double_t *params;
02645
02646 if (uparams) {
02647 params = const_cast<Double_t*>(uparams);
02648 } else {
02649 params = fParams;
02650 }
02651 UInt_t pos = 0;
02652 UInt_t strpos = 0;
02653
02654 for (i=0; i<fNoper; ++i) {
02655
02656 const int oper = fOper[i];
02657 const int opcode = oper >> kTFOperShift;
02658
02659 switch(opcode) {
02660
02661 case kParameter : { pos++; tab[pos-1] = params[ oper & kTFOperMask ]; continue; }
02662 case kConstant : { pos++; tab[pos-1] = fConst[ oper & kTFOperMask ]; continue; }
02663 case kVariable : { pos++; tab[pos-1] = x[ oper & kTFOperMask ]; continue; }
02664 case kStringConst: { strpos++; stringStack[strpos-1] = (char*)fExpr[i].Data(); pos++; tab[pos-1] = 0; continue; }
02665
02666 case kAdd : pos--; tab[pos-1] += tab[pos]; continue;
02667 case kSubstract : pos--; tab[pos-1] -= tab[pos]; continue;
02668 case kMultiply : pos--; tab[pos-1] *= tab[pos]; continue;
02669 case kDivide : pos--; if (tab[pos] == 0) tab[pos-1] = 0;
02670 else tab[pos-1] /= tab[pos];
02671 continue;
02672 case kModulo : {pos--;
02673 Long64_t int1((Long64_t)tab[pos-1]);
02674 Long64_t int2((Long64_t)tab[pos]);
02675 tab[pos-1] = Double_t(int1%int2);
02676 continue;}
02677
02678 case kcos : tab[pos-1] = TMath::Cos(tab[pos-1]); continue;
02679 case ksin : tab[pos-1] = TMath::Sin(tab[pos-1]); continue;
02680 case ktan : if (TMath::Cos(tab[pos-1]) == 0) {tab[pos-1] = 0;}
02681 else tab[pos-1] = TMath::Tan(tab[pos-1]);
02682 continue;
02683 case kacos : if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
02684 else tab[pos-1] = TMath::ACos(tab[pos-1]);
02685 continue;
02686 case kasin : if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
02687 else tab[pos-1] = TMath::ASin(tab[pos-1]);
02688 continue;
02689 case katan : tab[pos-1] = TMath::ATan(tab[pos-1]); continue;
02690 case kcosh : tab[pos-1] = TMath::CosH(tab[pos-1]); continue;
02691 case ksinh : tab[pos-1] = TMath::SinH(tab[pos-1]); continue;
02692 case ktanh : if (TMath::CosH(tab[pos-1]) == 0) {tab[pos-1] = 0;}
02693 else tab[pos-1] = TMath::TanH(tab[pos-1]);
02694 continue;
02695 case kacosh: if (tab[pos-1] < 1) {tab[pos-1] = 0;}
02696 else tab[pos-1] = TMath::ACosH(tab[pos-1]);
02697 continue;
02698 case kasinh: tab[pos-1] = TMath::ASinH(tab[pos-1]); continue;
02699 case katanh: if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
02700 else tab[pos-1] = TMath::ATanH(tab[pos-1]); continue;
02701 case katan2: pos--; tab[pos-1] = TMath::ATan2(tab[pos-1],tab[pos]); continue;
02702
02703 case kfmod : pos--; tab[pos-1] = fmod(tab[pos-1],tab[pos]); continue;
02704 case kpow : pos--; tab[pos-1] = TMath::Power(tab[pos-1],tab[pos]); continue;
02705 case ksq : tab[pos-1] = tab[pos-1]*tab[pos-1]; continue;
02706 case ksqrt : tab[pos-1] = TMath::Sqrt(TMath::Abs(tab[pos-1])); continue;
02707
02708 case kstrstr : strpos -= 2; pos-=2; pos++;
02709 if (strstr(stringStack[strpos],stringStack[strpos+1])) tab[pos-1]=1;
02710 else tab[pos-1]=0; continue;
02711
02712 case kmin : pos--; tab[pos-1] = TMath::Min(tab[pos-1],tab[pos]); continue;
02713 case kmax : pos--; tab[pos-1] = TMath::Max(tab[pos-1],tab[pos]); continue;
02714
02715 case klog : if (tab[pos-1] > 0) tab[pos-1] = TMath::Log(tab[pos-1]);
02716 else {tab[pos-1] = 0;}
02717 continue;
02718 case kexp : { Double_t dexp = tab[pos-1];
02719 if (dexp < -700) {tab[pos-1] = 0; continue;}
02720 if (dexp > 700) {tab[pos-1] = TMath::Exp(700); continue;}
02721 tab[pos-1] = TMath::Exp(dexp); continue; }
02722 case klog10: if (tab[pos-1] > 0) tab[pos-1] = TMath::Log10(tab[pos-1]);
02723 else {tab[pos-1] = 0;}
02724 continue;
02725
02726 case kpi : pos++; tab[pos-1] = TMath::ACos(-1); continue;
02727
02728 case kabs : tab[pos-1] = TMath::Abs(tab[pos-1]); continue;
02729 case ksign : if (tab[pos-1] < 0) tab[pos-1] = -1; else tab[pos-1] = 1; continue;
02730 case kint : tab[pos-1] = Double_t(Int_t(tab[pos-1])); continue;
02731
02732 case kSignInv: tab[pos-1] = -1 * tab[pos-1]; continue;
02733
02734 case krndm : pos++; tab[pos-1] = gRandom->Rndm(1); continue;
02735
02736 case kAnd : pos--; if (tab[pos-1]!=0 && tab[pos]!=0) tab[pos-1]=1;
02737 else tab[pos-1]=0; continue;
02738 case kOr : pos--; if (tab[pos-1]!=0 || tab[pos]!=0) tab[pos-1]=1;
02739 else tab[pos-1]=0; continue;
02740 case kEqual: pos--; if (tab[pos-1] == tab[pos]) tab[pos-1]=1;
02741 else tab[pos-1]=0; continue;
02742 case kNotEqual : pos--; if (tab[pos-1] != tab[pos]) tab[pos-1]=1;
02743 else tab[pos-1]=0; continue;
02744 case kLess : pos--; if (tab[pos-1] < tab[pos]) tab[pos-1]=1;
02745 else tab[pos-1]=0; continue;
02746 case kGreater : pos--; if (tab[pos-1] > tab[pos]) tab[pos-1]=1;
02747 else tab[pos-1]=0; continue;
02748
02749 case kLessThan: pos--; if (tab[pos-1]<=tab[pos]) tab[pos-1]=1;
02750 else tab[pos-1]=0; continue;
02751 case kGreaterThan: pos--; if (tab[pos-1]>=tab[pos]) tab[pos-1]=1;
02752 else tab[pos-1]=0; continue;
02753 case kNot : if (tab[pos-1]!=0) tab[pos-1] = 0; else tab[pos-1] = 1; continue;
02754
02755 case kStringEqual : strpos -= 2; pos -=2 ; pos++;
02756 if (!strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
02757 else tab[pos-1]=0; continue;
02758 case kStringNotEqual: strpos -= 2; pos -= 2; pos++;
02759 if (strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
02760 else tab[pos-1]=0; continue;
02761
02762 case kBitAnd : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) & ((Int_t) tab[pos]); continue;
02763 case kBitOr : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) | ((Int_t) tab[pos]); continue;
02764 case kLeftShift : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) <<((Int_t) tab[pos]); continue;
02765 case kRightShift: pos--; tab[pos-1]= ((Int_t) tab[pos-1]) >>((Int_t) tab[pos]); continue;
02766
02767 case kJump : i = (oper & kTFOperMask); continue;
02768 case kJumpIf : pos--; if (!tab[pos]) i = (oper & kTFOperMask); continue;
02769
02770 case kBoolOptimize: {
02771
02772
02773 int param = (oper & kTFOperMask);
02774 Bool_t skip = kFALSE;
02775 int op = param % 10;
02776
02777 if (op == 1 && (!tab[pos-1]) ) {
02778
02779
02780 skip = kTRUE;
02781
02782
02783
02784 tab[pos-1] = 0;
02785
02786 } else if (op == 2 && tab[pos-1] ) {
02787
02788
02789 skip = kTRUE;
02790
02791
02792
02793 tab[pos-1] = 1;
02794
02795 }
02796
02797 if (skip) {
02798 int toskip = param / 10;
02799 i += toskip;
02800 }
02801 continue;
02802 }
02803
02804 }
02805
02806 switch(opcode) {
02807
02808 #define R__EXPO(var) \
02809 { \
02810 pos++; int param = (oper & kTFOperMask); \
02811 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[var]); \
02812 continue; \
02813 }
02814
02815 case kxexpo: R__EXPO(0);
02816 case kyexpo: R__EXPO(1);
02817 case kzexpo: R__EXPO(2);
02818 case kxyexpo:{ pos++; int param = (oper & kTFOperMask);
02819 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[0]+params[param+2]*x[1]);
02820 continue; }
02821
02822 #define R__GAUS(var) \
02823 { \
02824 pos++; int param = (oper & kTFOperMask); \
02825 tab[pos-1] = params[param]*TMath::Gaus(x[var],params[param+1],params[param+2],IsNormalized()); \
02826 continue; \
02827 }
02828
02829
02830 case kxgaus: R__GAUS(0);
02831 case kygaus: R__GAUS(1);
02832 case kzgaus: R__GAUS(2);
02833 case kxygaus: {pos++; int param = (oper & kTFOperMask);
02834 Double_t intermede1;
02835 if (params[param+2] == 0) {
02836 intermede1=1e10;
02837 } else {
02838 intermede1=Double_t((x[0]-params[param+1])/params[param+2]);
02839 }
02840 Double_t intermede2;
02841 if (params[param+4] == 0) {
02842 intermede2=1e10;
02843 } else {
02844 intermede2=Double_t((x[1]-params[param+3])/params[param+4]);
02845 }
02846 tab[pos-1] = params[param]*TMath::Exp(-0.5*(intermede1*intermede1+intermede2*intermede2));
02847 continue; }
02848
02849 #define R__LANDAU(var) \
02850 { \
02851 pos++; const int param = (oper & kTFOperMask); \
02852 tab[pos-1] = params[param]*TMath::Landau(x[var],params[param+1],params[param+2],IsNormalized()); \
02853 continue; \
02854 }
02855
02856 case kxlandau: R__LANDAU(0);
02857 case kylandau: R__LANDAU(1);
02858 case kzlandau: R__LANDAU(2);
02859 case kxylandau: { pos++; int param = oper&0x7fffff ;
02860 Double_t intermede1=TMath::Landau(x[0], params[param+1], params[param+2],IsNormalized());
02861 Double_t intermede2=TMath::Landau(x[1], params[param+3], params[param+4],IsNormalized());
02862 tab[pos-1] = params[param]*intermede1*intermede2;
02863 continue;
02864 }
02865
02866 #define R__POLY(var) \
02867 { \
02868 pos++; int param = (oper & kTFOperMask); \
02869 tab[pos-1] = 0; Double_t intermede = 1; \
02870 Int_t inter = param/100; \
02871 Int_t int1= param-inter*100-1; \
02872 for (j=0 ;j<inter+1;j++) { \
02873 tab[pos-1] += intermede*params[j+int1]; \
02874 intermede *= x[var]; \
02875 } \
02876 continue; \
02877 }
02878
02879 case kxpol: R__POLY(0);
02880 case kypol: R__POLY(1);
02881 case kzpol: R__POLY(2);
02882
02883 case kDefinedVariable : {
02884 if (!precalculated) {
02885 precalculated = 1;
02886 for(j=0;j<fNval;j++) param_calc[j]=DefinedValue(j);
02887 }
02888 pos++; tab[pos-1] = param_calc[(oper & kTFOperMask)];
02889 continue;
02890 }
02891
02892 case kDefinedString : {
02893 int param = (oper & kTFOperMask);
02894 if (!precalculated_str) {
02895 precalculated_str=1;
02896 for (j=0;j<fNstring;j++) string_calc[j]=DefinedString(j);
02897 }
02898 strpos++; stringStack[strpos-1] = string_calc[param];
02899 pos++; tab[pos-1] = 0;
02900 continue;
02901 }
02902
02903 case kFunctionCall: {
02904
02905
02906 int param = (oper & kTFOperMask);
02907 int fno = param / 1000;
02908 int nargs = param % 1000;
02909
02910
02911 TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
02912
02913
02914 TString args;
02915 if (nargs) {
02916 UInt_t argloc = pos-nargs;
02917 for(j=0;j<nargs;j++,argloc++,pos--) {
02918 if (TMath::IsNaN(tab[argloc])) {
02919
02920
02921 args += "(double)(0x8000000000000)";
02922 } else {
02923 args += tab[argloc];
02924 }
02925 args += ',';
02926 }
02927 args.Remove(args.Length()-1);
02928 }
02929 pos++;
02930 Double_t ret;
02931 method->Execute(args,ret);
02932 tab[pos-1] = ret;
02933
02934 continue;
02935 };
02936 }
02937 if (!TestBit(kOptimizationError)) {
02938 SetBit(kOptimizationError);
02939 Warning("EvalParOld","Found an unsupported opcode (%d)",oper >> kTFOperShift);
02940 }
02941 }
02942 Double_t result0 = tab[0];
02943 return result0;
02944
02945 }
02946
02947
02948 TString TFormula::GetExpFormula(Option_t *option) const
02949 {
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968 if (fNoper>0) {
02969 TString* tab=new TString[fNoper];
02970 Bool_t* ismulti=new Bool_t[fNoper];
02971 Int_t spos=0;
02972
02973 ismulti[0]=kFALSE;
02974 Int_t optype;
02975 Int_t j;
02976 Int_t ternaryend = -1;
02977 for(Int_t i=0;i<fNoper;i++){
02978 optype = GetAction(i);
02979
02980 if (ternaryend==i) {
02981
02982 if(ismulti[spos-1]){
02983 tab[spos-2]=tab[spos-2]+"("+tab[spos-1]+")";
02984 } else {
02985 tab[spos-2]=tab[spos-2]+tab[spos-1];
02986 }
02987 spos--;
02988
02989
02990 }
02991
02992
02993 if (optype==kBoolOptimize) {
02994 continue;
02995 }
02996
02997
02998 if (optype==kSignInv) {
02999 tab[spos-1]="-("+tab[spos-1]+")";
03000
03001 continue;
03002 }
03003
03004
03005 if (kexpo<=optype && optype<=kzpol) {
03006 tab[spos]=fExpr[i];
03007 ismulti[spos]=kFALSE;
03008 spos++;
03009 continue;
03010 }
03011
03012
03013 if ((optype<=151 && optype>=140 && optype!=145) || (optype == 40)) {
03014 tab[spos]=fExpr[i];
03015 ismulti[spos]=kFALSE;
03016 spos++;
03017 continue;
03018 }
03019
03020
03021 if(((optype>0 && optype<6) || optype==20 ||
03022 (((optype>59 && optype<69) || (optype >75 && optype<82)) && spos>=2))) {
03023
03024 if(ismulti[spos-2]){
03025 tab[spos-2]="("+tab[spos-2]+")";
03026 }
03027 if(ismulti[spos-1]){
03028 tab[spos-2]+=fExpr[i]+("("+tab[spos-1]+")");
03029 }else{
03030 tab[spos-2]+=fExpr[i]+tab[spos-1];
03031 }
03032 ismulti[spos-2]=kTRUE;
03033 spos--;
03034 continue;
03035 }
03036
03037 if (optype==kJumpIf) {
03038 if(ismulti[spos-1]){
03039 tab[spos-1]="("+tab[spos-1]+")?";
03040 } else {
03041 tab[spos-1]=tab[spos-1]+"?";
03042 }
03043 continue;
03044 }
03045 if (optype==kJump) {
03046 if(ismulti[spos-1]){
03047 tab[spos-2]=tab[spos-2]+"("+tab[spos-1]+"):";
03048 } else {
03049 tab[spos-2]=tab[spos-2]+tab[spos-1]+":";
03050 }
03051 ternaryend = GetActionParam(i) + 1;
03052 spos--;
03053 continue;
03054 }
03055
03056
03057 int offset = 0;
03058 TString funcname = fExpr[i];
03059 if((optype>9 && optype<16) ||
03060 (optype>20 && optype<23) ||
03061 (optype>29 && optype<34) ||
03062 (optype>40 && optype<44) ||
03063 (optype>69 && optype<76) ||
03064 (optype==145)) {
03065
03066 offset = -1;
03067 }
03068
03069 if((optype>15 && optype<20) ||
03070 (optype>22 && optype<26)) {
03071
03072 offset = -2;
03073 }
03074 if(optype==145) {
03075 int param = (fOper[i] & kTFOperMask);
03076
03077 int nargs = param % 1000;
03078 offset = -nargs;
03079
03080
03081 int depth;
03082 for(j=0, depth=0;j<funcname.Length();++j) {
03083 switch (funcname[j]) {
03084 case '<':
03085 ++depth; break;
03086 case '>':
03087 --depth; break;
03088 case ' ':
03089 if (depth==0) {
03090 funcname.Remove(0,j+1);
03091 j = funcname.Length();
03092 break;
03093 }
03094 }
03095 }
03096 Ssiz_t ind = funcname.First('(');
03097 funcname.Remove(ind);
03098 }
03099 if (offset<=0 && (spos+offset>=0)) {
03100 tab[spos+offset]=funcname+("("+tab[spos+offset]);
03101 for (j=offset+1; j<0; j++){
03102 tab[spos+offset]+=","+tab[spos+j];
03103 }
03104 tab[spos+offset]+=")";
03105 ismulti[spos+offset]=kFALSE;
03106 spos+=offset+1;
03107 continue;
03108 }
03109 }
03110 if (ternaryend==fNoper) {
03111
03112 if(ismulti[spos-1]){
03113 tab[spos-2]=tab[spos-2]+"("+tab[spos-1]+")";
03114 } else {
03115 tab[spos-2]=tab[spos-2]+tab[spos-1];
03116 }
03117 spos--;
03118 }
03119
03120 TString ret = "";
03121 if (spos > 0) ret = tab[spos-1];
03122 delete[] tab;
03123 delete[] ismulti;
03124
03125
03126 TString opt = option;
03127 opt.ToLower();
03128 if (opt.Contains("p")) {
03129 char pb[10];
03130 char pbv[100];
03131 for (j=0;j<fNpar;j++) {
03132 snprintf(pb,10,"[%d]",j);
03133 snprintf(pbv,100,"%g",fParams[j]);
03134 ret.ReplaceAll(pb,pbv);
03135 }
03136 ret.ReplaceAll("--","+");
03137 ret.ReplaceAll("+-","-");
03138 }
03139 return ret;
03140 } else{
03141 TString ret="";
03142 return ret;
03143 }
03144 }
03145
03146
03147 const TObject* TFormula::GetLinearPart(Int_t i)
03148 {
03149
03150
03151 if (!fLinearParts.IsEmpty())
03152 return fLinearParts.UncheckedAt(i);
03153 return 0;
03154 }
03155
03156
03157 Double_t TFormula::GetParameter(Int_t ipar) const
03158 {
03159
03160
03161 if (ipar <0 || ipar >= fNpar) return 0;
03162 return fParams[ipar];
03163 }
03164
03165
03166 Double_t TFormula::GetParameter(const char *parName) const
03167 {
03168
03169
03170 const Double_t kNaN = 1e-300;
03171 Int_t index = GetParNumber(parName);
03172 if (index==-1) {
03173 Error("TFormula", "Parameter %s not found", parName);
03174 return kNaN;
03175 }
03176 return GetParameter(index);
03177 }
03178
03179
03180 const char *TFormula::GetParName(Int_t ipar) const
03181 {
03182
03183
03184
03185 if (ipar <0 || ipar >= fNpar) return "";
03186 if (fNames[ipar].Length() > 0) return (const char*)fNames[ipar];
03187 return Form("p%d",ipar);
03188 }
03189
03190
03191 Int_t TFormula::GetParNumber(const char *parName) const
03192 {
03193
03194
03195 if (!parName)
03196 return -1;
03197
03198 for (Int_t i=0; i<fNpar; i++) {
03199 if (!strcmp(GetParName(i),parName)) return i;
03200 }
03201 return -1;
03202 }
03203
03204
03205 Bool_t TFormula::IsString(Int_t oper) const
03206 {
03207
03208
03209
03210 return GetAction(oper) == kStringConst;
03211 }
03212
03213
03214 void TFormula::Print(Option_t *) const
03215 {
03216
03217
03218 Int_t i;
03219 Printf(" %20s : %s Ndim= %d, Npar= %d, Noper= %d",GetName(),GetTitle(), fNdim,fNpar,fNoper);
03220 for (i=0;i<fNoper;i++) {
03221 Printf(" fExpr[%d] = %s action = %d action param = %d ",
03222 i,(const char*)fExpr[i],GetAction(i),GetActionParam(i));
03223 }
03224
03225
03226 if (fNOperOptimized>0){
03227 Printf("Optimized expression");
03228 for (i=0;i<fNOperOptimized;i++) {
03229 Printf(" fExpr[%d] = %s\t\t action = %d action param = %d ",
03230 i,(const char*)fExprOptimized[i],GetActionOptimized(i),GetActionParamOptimized(i));
03231 }
03232 }
03233
03234
03235 if (!fNames) return;
03236 if (!fParams) return;
03237 for (i=0;i<fNpar;i++) {
03238 Printf(" Par%3d %20s = %g",i,GetParName(i),fParams[i]);
03239 }
03240 }
03241
03242
03243 void TFormula::ProcessLinear(TString &formula)
03244 {
03245
03246
03247
03248 TString formula2(formula);
03249 char repl[20];
03250 char *pch;
03251 Int_t nf, offset, replsize;
03252
03253 pch= (char*)strstr(formula.Data(), "++");
03254 if (pch)
03255 formula.Insert(0, "[0]*(");
03256 pch= (char*)strstr(formula.Data(), "++");
03257 if (pch){
03258
03259 nf = 1;
03260 while (pch){
03261 snprintf(repl,20, ")+[%d]*(", nf);
03262 offset = pch-formula.Data();
03263 if (nf<10) replsize = 7;
03264 else if (nf<100) replsize = 8;
03265 else replsize = 9;
03266 formula.Replace(pch-formula.Data(), 2, repl, replsize);
03267 pch = (char*)strstr(formula.Data()+offset, "++");
03268 nf++;
03269 }
03270 formula.Append(')', 1);
03271 } else {
03272
03273 formula2=formula2(4, formula2.Length()-4);
03274 pch= (char*)strchr(formula2.Data(), '[');
03275 snprintf(repl,20, "++");
03276 nf = 1;
03277 while (pch){
03278 offset = pch-formula2.Data()-1;
03279 if (nf<10) replsize = 5;
03280 else replsize = 6;
03281 formula2.Replace(pch-formula2.Data()-1, replsize, repl, 2);
03282 pch = (char*)strchr(formula2.Data()+offset, '[');
03283 nf++;
03284 }
03285 }
03286
03287 fLinearParts.Expand(nf);
03288
03289 TString replaceformula;
03290 formula2 = formula2.ReplaceAll("++", 2, "|", 1);
03291 TObjArray *oa = formula2.Tokenize("|");
03292 for (Int_t i=0; i<nf; i++) {
03293 replaceformula = ((TObjString *)oa->UncheckedAt(i))->GetString();
03294 TFormula *f = new TFormula(replaceformula.Data(), replaceformula.Data());
03295 if (!f) {
03296 Error("TFormula", "f_linear not allocated");
03297 return;
03298 }
03299 gROOT->GetListOfFunctions()->Remove(f);
03300 f->SetBit(kNotGlobal, 1);
03301 fLinearParts.Add(f);
03302 }
03303 oa->Delete();
03304 }
03305
03306
03307 void TFormula::SetParameter(const char *name, Double_t value)
03308 {
03309
03310
03311
03312 Int_t ipar = GetParNumber(name);
03313 if (ipar <0 || ipar >= fNpar) return;
03314 fParams[ipar] = value;
03315 Update();
03316 }
03317
03318
03319 void TFormula::SetParameter(Int_t ipar, Double_t value)
03320 {
03321
03322
03323
03324 if (ipar <0 || ipar >= fNpar) return;
03325 fParams[ipar] = value;
03326 Update();
03327 }
03328
03329
03330 void TFormula::SetParameters(const Double_t *params)
03331 {
03332
03333
03334
03335 for (Int_t i=0; i<fNpar;i++) {
03336 fParams[i] = params[i];
03337 }
03338 Update();
03339 }
03340
03341
03342
03343 void TFormula::SetParameters(Double_t p0,Double_t p1,Double_t p2,Double_t p3,Double_t p4
03344 ,Double_t p5,Double_t p6,Double_t p7,Double_t p8,Double_t p9,Double_t p10)
03345 {
03346
03347
03348
03349
03350
03351
03352 if (fNpar > 0) fParams[0] = p0;
03353 if (fNpar > 1) fParams[1] = p1;
03354 if (fNpar > 2) fParams[2] = p2;
03355 if (fNpar > 3) fParams[3] = p3;
03356 if (fNpar > 4) fParams[4] = p4;
03357 if (fNpar > 5) fParams[5] = p5;
03358 if (fNpar > 6) fParams[6] = p6;
03359 if (fNpar > 7) fParams[7] = p7;
03360 if (fNpar > 8) fParams[8] = p8;
03361 if (fNpar > 9) fParams[9] = p9;
03362 if (fNpar >10) fParams[10]= p10;
03363 Update();
03364 }
03365
03366
03367 void TFormula::SetParName(Int_t ipar, const char *name)
03368 {
03369
03370
03371 if (ipar <0 || ipar >= fNpar) return;
03372 fNames[ipar] = name;
03373 }
03374
03375
03376 void TFormula::SetParNames(const char*name0,const char*name1,const char*name2,const char*name3,const char*name4,
03377 const char*name5,const char*name6,const char*name7,const char*name8,const char*name9,const char*name10)
03378 {
03379
03380
03381
03382 if (fNpar > 0) fNames[0] = name0;
03383 if (fNpar > 1) fNames[1] = name1;
03384 if (fNpar > 2) fNames[2] = name2;
03385 if (fNpar > 3) fNames[3] = name3;
03386 if (fNpar > 4) fNames[4] = name4;
03387 if (fNpar > 5) fNames[5] = name5;
03388 if (fNpar > 6) fNames[6] = name6;
03389 if (fNpar > 7) fNames[7] = name7;
03390 if (fNpar > 8) fNames[8] = name8;
03391 if (fNpar > 9) fNames[9] = name9;
03392 if (fNpar >10) fNames[10]= name10;
03393 }
03394
03395
03396 void TFormula::Streamer(TBuffer &b)
03397 {
03398
03399
03400 if (b.IsReading()) {
03401 UInt_t R__s, R__c;
03402 Version_t v = b.ReadVersion(&R__s, &R__c);
03403 if (v > 3) {
03404
03405 if (v==6) {
03406 Error("Streamer","version 6 is not supported");
03407 return;
03408 }
03409 b.ReadClassBuffer(TFormula::Class(), this, v, R__s, R__c);
03410 if (!TestBit(kNotGlobal)) gROOT->GetListOfFunctions()->Add(this);
03411
03412
03413 if (fFunctions.GetLast()>=0) {
03414
03415
03416 Double_t *param = fParams;
03417 TString *names = fNames;
03418 Int_t npar = fNpar;
03419 fParams = 0;
03420 fNames = 0;
03421 Compile();
03422 for (Int_t i = 0; i<npar && i<fNpar; ++i) fParams[i] = param[i];
03423 delete [] param;
03424 delete [] fNames;
03425 fNames = names;
03426 } else if (v<6) {
03427 Convert(v);
03428 }
03429 Optimize();
03430 return;
03431 }
03432
03433 TNamed::Streamer(b);
03434 b >> fNdim;
03435 b >> fNumber;
03436 if (v > 1) b >> fNval;
03437 if (v > 2) b >> fNstring;
03438 fNpar = b.ReadArray(fParams);
03439 fOper = new Int_t[gMAXOP];
03440 fNoper = b.ReadArray(fOper);
03441 fNconst = b.ReadArray(fConst);
03442 if (fNoper) {
03443 fExpr = new TString[fNoper];
03444 }
03445 if (fNpar) {
03446 fNames = new TString[fNpar];
03447 }
03448 Int_t i;
03449 for (i=0;i<fNoper;i++) fExpr[i].Streamer(b);
03450 for (i=0;i<fNpar;i++) fNames[i].Streamer(b);
03451 if (gROOT->GetListOfFunctions()->FindObject(GetName())) return;
03452 gROOT->GetListOfFunctions()->Add(this);
03453 b.CheckByteCount(R__s, R__c, TFormula::IsA());
03454
03455 Convert(v);
03456
03457
03458 } else {
03459 b.WriteClassBuffer(TFormula::Class(),this);
03460 }
03461 }
03462
03463 void TFormula::Convert(UInt_t )
03464 {
03465
03466
03467 enum {
03468 kOldexpo = 1000,
03469 kOldgaus = 2000,
03470 kOldlandau = 4000,
03471 kOldxylandau = 4500,
03472 kOldConstants = 50000,
03473 kOldStrings = 80000,
03474 kOldVariable = 100000,
03475 kOldTreeString = 105000,
03476 kOldFormulaVar = 110000,
03477 kOldBoolOptimize = 120000,
03478 kOldFunctionCall = 200000
03479 };
03480 int i,j;
03481
03482 for (i=0,j=0; i<fNoper; ++i,++j) {
03483 Int_t action = fOper[i];
03484 Int_t newActionCode = 0;
03485 Int_t newActionParam = 0;
03486
03487 if ( action == 0) {
03488
03489
03490 newActionCode = kSignInv;
03491
03492 Float_t aresult = 99.99;
03493 sscanf((const char*)fExpr[i],"%g",&aresult);
03494 R__ASSERT((aresult+1)<0.001);
03495
03496 ++i;
03497
03498
03499
03500 for (int z=i; z<fNoper; ++z) {
03501 fExpr[z-1] = fExpr[z];
03502 }
03503
03504 } else if ( action < 100 ) {
03505
03506
03507 newActionCode = action;
03508
03509 } else if (action >= kOldFunctionCall) {
03510
03511
03512 newActionCode = kFunctionCall;
03513 newActionParam = action-kOldFunctionCall;
03514
03515 } else if (action >= kOldBoolOptimize) {
03516
03517
03518 newActionCode = kBoolOptimize;
03519 newActionParam = action-kOldBoolOptimize;
03520
03521 } else if (action >= kOldFormulaVar) {
03522
03523
03524 newActionCode = kVariable;
03525 newActionParam = action-kOldFormulaVar;
03526
03527 } else if (action >= kOldTreeString) {
03528
03529
03530 newActionCode = kDefinedString;
03531 newActionParam = action-kOldTreeString;
03532
03533 } else if (action >= kOldVariable) {
03534
03535
03536 newActionCode = kDefinedVariable;
03537 newActionParam = action-kOldVariable;
03538
03539 } else if (action == kOldStrings) {
03540
03541
03542 newActionCode = kStringConst;
03543
03544 } else if (action >= kOldConstants) {
03545
03546
03547 newActionCode = kConstant;
03548 newActionParam = action-kOldConstants;
03549
03550 } else if (action > 10000 && action < kOldConstants) {
03551
03552
03553 int var = action/10000;
03554 newActionCode = kpol + (var-1);
03555 newActionParam = action - var*10000;
03556
03557 } else if (action >= 4600) {
03558
03559 Error("Convert","Unsupported value %d",action);
03560
03561 } else if (action > kOldxylandau) {
03562
03563
03564 newActionCode = kxylandau;
03565 newActionParam = action - (kOldxylandau+1);
03566
03567 } else if (action > kOldlandau) {
03568
03569
03570 newActionCode = klandau;
03571 int var = action/100-40;
03572 if (var) newActionCode += var;
03573 newActionParam = action - var*100 - (kOldlandau+1);
03574
03575 } else if (action > 2500 && action < 2600) {
03576
03577
03578 newActionCode = kxygaus;
03579 newActionParam = action-2501;
03580
03581 } else if (action > 2000 && action < 2500) {
03582
03583
03584 newActionCode = kgaus;
03585 int var = action/100-20;
03586 if (var) newActionCode += var;
03587 newActionParam = action - var*100 - (kOldgaus+1);
03588
03589 } else if (action > 1500 && action < 1600) {
03590
03591
03592 newActionCode = kxyexpo;
03593 newActionParam = action-1501;
03594
03595 } else if (action > 1000 && action < 1500) {
03596
03597
03598 newActionCode = kexpo;
03599 int var = action/100-10;
03600 if (var) newActionCode += var;
03601 newActionParam = action - var*100 - (kOldexpo+1);
03602
03603 } if (action > 100 && action < 200) {
03604
03605
03606 newActionCode = kParameter;
03607 newActionParam = action - 101;
03608 }
03609
03610 SetAction( j, newActionCode, newActionParam );
03611
03612 }
03613 if (i!=j) {
03614 fNoper -= (i-j);
03615 }
03616
03617 }
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628 TOperOffset::TOperOffset()
03629 {
03630
03631
03632
03633
03634
03635
03636
03637 fType0=0;
03638 fType1=0;
03639 fType2=0;
03640 fType3=0;
03641 fOffset0=0;
03642 fOffset1=0;
03643 fOffset2=0;
03644 fOffset3=0;
03645 fOldAction=0;
03646 fToJump=0;
03647 }
03648
03649
03650 void TFormula::MakePrimitive(const char *expr, Int_t pos)
03651 {
03652
03653
03654
03655
03656
03657 TString cbase(expr);
03658 cbase.ReplaceAll("Double_t ","");
03659 int paran = cbase.First("(");
03660 int nargs = 0;
03661 if (paran>0) {
03662 nargs = 1;
03663 cbase[paran]=0;
03664 }
03665
03666 if (cbase=="<") cbase="XlY";
03667 if (cbase=="<=") cbase="XleY";
03668 if (cbase==">") cbase="XgY";
03669 if (cbase==">=") cbase="XgeY";
03670 if (cbase=="==" && GetActionOptimized(pos)!=kStringEqual) cbase="XeY";
03671 if (cbase=="!=" && GetActionOptimized(pos)!=kStringNotEqual) cbase="XneY";
03672
03673 TFormulaPrimitive *prim = TFormulaPrimitive::FindFormula(cbase ,paran>0 ? cbase.Data() + paran + 1 : (const char*)0);
03674 if (prim) {
03675 fPredefined[pos] = prim;
03676 if (prim->fType==10) {
03677 SetActionOptimized(pos, kFD1);
03678 }
03679 if (prim->fType==110) {
03680 SetActionOptimized(pos, kFD2);
03681 }
03682 if (prim->fType==1110) {
03683 SetActionOptimized(pos, kFD3);
03684 }
03685 if (prim->fType==-1) {
03686 SetActionOptimized(pos, kFDM);
03687 }
03688 if (prim->fType==0){
03689 SetActionOptimized(pos,kConstant,fNconst);
03690 fConst[fNconst] = prim->Eval(0);
03691 fNconst++;
03692 }
03693 return;
03694 }
03695 }
03696
03697
03698 void TFormula::Optimize()
03699 {
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731 Int_t i;
03732
03733 if (fPredefined) { delete [] fPredefined; fPredefined = 0;}
03734 if (fOperOffset) { delete [] fOperOffset; fOperOffset = 0;}
03735 if (fExprOptimized) { delete [] fExprOptimized; fExprOptimized = 0;}
03736 if (fOperOptimized) { delete [] fOperOptimized; fOperOptimized = 0;}
03737
03738 fExprOptimized = new TString[fNoper];
03739 fOperOptimized = new Int_t[fNoper];
03740 fPredefined = new TFormulaPrimitive*[fNoper];
03741 fOperOffset = new TOperOffset[fNoper];
03742 for (i=0; i<fNoper; i++) {
03743 fExprOptimized[i] = fExpr[i] ;
03744 fOperOptimized[i] = fOper[i];
03745 fPredefined[i]= 0;
03746 }
03747
03748
03749
03750
03751 for (i=0;i<fNoper;i++){
03752 if (fExprOptimized[i].Data()) {
03753 MakePrimitive(fExprOptimized[i].Data(), i);
03754 }
03755 }
03756
03757 Int_t maxfound = fNoper+1;
03758 Int_t *offset = new Int_t[maxfound*16];
03759 Int_t *optimized = new Int_t[maxfound];
03760
03761
03762 TFormulaPrimitive* primitive[10];
03763 primitive[0] = TFormulaPrimitive::FindFormula("PlusXY");
03764 primitive[1] = TFormulaPrimitive::FindFormula("MinusXY");
03765 primitive[2] = TFormulaPrimitive::FindFormula("MultXY");
03766 primitive[3] = TFormulaPrimitive::FindFormula("DivXY");
03767 primitive[4] = TFormulaPrimitive::FindFormula("XpYpZ");
03768 primitive[5] = TFormulaPrimitive::FindFormula("XxYxZ");
03769 primitive[6] = TFormulaPrimitive::FindFormula("XxYpZ");
03770 primitive[7] = TFormulaPrimitive::FindFormula("XpYxZ");
03771 primitive[8] = TFormulaPrimitive::FindFormula("Pow2");
03772 primitive[9] = TFormulaPrimitive::FindFormula("Pow3");
03773
03774
03775
03776 for (i=0;i<fNoper;i++) optimized[i]=0;
03777
03778 for (i=0;i<fNoper;i++){
03779 Int_t actionparam = GetActionParamOptimized(i);
03780 Int_t action = GetActionOptimized(i);
03781
03782 if (action==kBoolOptimize){
03783
03784
03785
03786 fOperOffset[i].fType1 = actionparam/10;
03787 fOperOffset[i].fOffset0 = actionparam%10;
03788 fOperOffset[i].fToJump = i+fOperOffset[i].fType1;
03789 continue;
03790 }
03791 if (action==kJump || action==kJumpIf) {
03792
03793 fOperOffset[i].fType1 = action;
03794 fOperOffset[i].fToJump = actionparam;
03795 }
03796
03797 if (action==kConstant&&i<fNoper-2){
03798
03799
03800
03801 if (GetActionOptimized(i+1)==kConstant && GetActionOptimized(i+2)==kFDM){
03802 optimized[i]=1;
03803 optimized[i+1]=1;
03804 i+=2;
03805 fOperOffset[i].fType0=actionparam;
03806 fOperOffset[i].fOffset0=GetActionParamOptimized(i-1);
03807 Int_t offset2 = int(fConst[fOperOffset[i].fOffset0]+0.4);
03808 fOperOffset[i].fOffset0=offset2;
03809 Int_t nparmax = offset2+fPredefined[i]->fNParameters;
03810 if (nparmax>fNpar){
03811 fNpar=nparmax;
03812 }
03813 continue;
03814 }
03815 }
03816 switch(action){
03817 case kVariable : {action=kData; fOperOffset[i].fType0=0; break;}
03818 case kParameter: {action=kData; fOperOffset[i].fType0=1; break;}
03819 case kConstant : {action=kData; fOperOffset[i].fType0=2; break;}
03820 }
03821
03822 fOperOffset[i].fOffset0 = GetActionParamOptimized(i);
03823 SetActionOptimized(i,action, actionparam);
03824 }
03825
03826
03827 fNOperOptimized = fNoper;
03828
03829 for (i=0; i<fNoper; ++i)
03830 {
03831
03832 if (!(GetActionOptimized(i)== kData)) continue;
03833 offset[0] = fOperOffset[i].fType0;
03834 offset[1] = fOperOptimized[i] & kTFOperMask;
03835
03836 if ((i+1) >= fNoper) continue;
03837
03838 if (GetActionOptimized(i+1)==kFD1){
03839 optimized[i] = 1;
03840 i++;
03841 fOperOffset[i].fType0 = offset[0];
03842 fOperOffset[i].fOffset0 = offset[1];
03843 SetActionOptimized(i ,kUnary);
03844 continue;
03845 }
03846 if (GetActionOptimized(i+1)==kAdd){
03847 optimized[i] = 1;
03848 i++;
03849 fOperOffset[i].fType0 = offset[0];
03850 fOperOffset[i].fOffset0 = offset[1];
03851 SetActionOptimized(i ,kPlusD);
03852 continue;
03853 }
03854 if (GetActionOptimized(i+1)==kMultiply){
03855 optimized[i] = 1;
03856 i++;
03857 fOperOffset[i].fType0 = offset[0];
03858 fOperOffset[i].fOffset0 = offset[1];
03859 SetActionOptimized(i,kMultD);
03860 continue;
03861 }
03862
03863 if ((i+2) >= fNoper) continue;
03864
03865
03866
03867 if (!(GetActionOptimized(i+1)== kData)) continue;
03868 offset[2] = fOperOffset[i+1].fType0;
03869 offset[3] = fOperOptimized[i+1] & kTFOperMask;
03870
03871 if (GetActionOptimized(i+2)==kFD2 || GetActionOptimized(i+2)==kAdd ||GetActionOptimized(i+2)==kSubstract||
03872 GetActionOptimized(i+2)==kMultiply || GetActionOptimized(i+2)==kDivide){
03873
03874 optimized[i] = 1;
03875 optimized[i+1] = 1;
03876 i+=2;
03877
03878 fOperOffset[i].fType0 = offset[0];
03879 fOperOffset[i].fOffset0 = offset[1];
03880 fOperOffset[i].fType1 = offset[2];
03881 fOperOffset[i].fOffset1 = offset[3];
03882 fOperOffset[i].fType2 = GetActionOptimized(i);
03883 if (GetActionOptimized(i)==kAdd) {fPredefined[i] = primitive[0];}
03884 if (GetActionOptimized(i)==kSubstract) {fPredefined[i] = primitive[1];}
03885 if (GetActionOptimized(i)==kMultiply) {
03886 fPredefined[i]=primitive[2];
03887 if (offset[0]==offset[2]&&offset[1]==offset[3]) {
03888 fPredefined[i] = primitive[8];
03889 SetActionOptimized(i,kUnary);
03890 continue;
03891 }
03892 }
03893 if (GetActionOptimized(i)==kDivide) {
03894 fPredefined[i] = primitive[3];
03895 }
03896 SetActionOptimized(i,kBinary);
03897 continue;
03898 }
03899
03900 if ((i+3) >= fNoper) continue;
03901
03902
03903
03904
03905 if (!(GetActionOptimized(i+2)== kData)) continue;
03906 offset[4] = fOperOffset[i+2].fType0;
03907 offset[5] = fOperOptimized[i+2] & kTFOperMask;
03908
03909 if (GetActionOptimized(i+3)==kFD3|| ( (GetActionOptimized(i+3)==kAdd||GetActionOptimized(i+3)==kMultiply) &&
03910 (GetActionOptimized(i+4)==kAdd||GetActionOptimized(i+4)==kMultiply) ) ){
03911 optimized[i+0] = 1;
03912 optimized[i+1] = 1;
03913 optimized[i+2] = 1;
03914 i+=3;
03915
03916 fOperOffset[i].fType0 = offset[0];
03917 fOperOffset[i].fOffset0 = offset[1];
03918 fOperOffset[i].fType1 = offset[2];
03919 fOperOffset[i].fOffset1 = offset[3];
03920 fOperOffset[i].fType2 = offset[4];
03921 fOperOffset[i].fOffset2 = offset[5];
03922
03923 fOperOffset[i].fOldAction = GetActionOptimized(i);
03924 if (GetActionOptimized(i)==kFD3) {
03925 SetActionOptimized(i,kThree);
03926 continue;
03927 }
03928 Int_t action=0;
03929 Int_t action2=kThree;
03930 if (GetActionOptimized(i)==kAdd&&GetActionOptimized(i+1)==kAdd) action=4;
03931 if (GetActionOptimized(i)==kMultiply&&GetActionOptimized(i+1)==kMultiply) {
03932 action=5;
03933 if (offset[0]==offset[2]&&offset[1]==offset[3]&&offset[0]==offset[4]&&offset[1]==offset[5]){
03934 fPredefined[i]=primitive[9];
03935 action2=kUnary;
03936 action =9;
03937 }
03938 }
03939 if (GetActionOptimized(i)==kAdd&&GetActionOptimized(i+1)==kMultiply) action=6;
03940 if (GetActionOptimized(i)==kMultiply&&GetActionOptimized(i+1)==kAdd) action=7;
03941
03942 optimized[i]=1;
03943 i++;
03944 fOperOffset[i].fType0 = offset[0];
03945 fOperOffset[i].fOffset0 = offset[1];
03946 fOperOffset[i].fType1 = offset[2];
03947 fOperOffset[i].fOffset1 = offset[3];
03948 fOperOffset[i].fType2 = offset[4];
03949 fOperOffset[i].fOffset2 = offset[5];
03950 fPredefined[i]=primitive[action];
03951 SetActionOptimized(i,action2);
03952 continue;
03953 }
03954 }
03955
03956
03957 Int_t operO=0;
03958 TString expr="";
03959 Int_t *map0 = new Int_t[maxfound];
03960 Int_t *map1 = new Int_t[maxfound];
03961 for (i=0;i<fNoper;i++){
03962 map0[i] = operO;
03963 map1[operO] = i;
03964 fOperOptimized[operO] = fOperOptimized[i];
03965 fPredefined[operO] = fPredefined[i];
03966 fOperOffset[operO] = fOperOffset[i];
03967 expr += fExprOptimized[i];
03968 if (optimized[i]==0){
03969 fExprOptimized[operO] = expr;
03970 expr = "";
03971 operO++;
03972 }else{
03973 expr += ",";
03974 }
03975 }
03976
03977
03978
03979 for (i=0; i<fNOperOptimized; i++){
03980 Int_t optaction = GetActionOptimized(i);
03981 if (optaction==kBoolOptimize){
03982 Int_t oldpos = fOperOffset[i].fToJump;
03983 Int_t newpos = oldpos==fNoper ? fNOperOptimized : map0[oldpos];
03984 fOperOffset[i].fToJump = newpos;
03985 Int_t actionop = GetActionParamOptimized(i) % 10;
03986 switch (actionop) {
03987 case 1: SetActionOptimized(i,kBoolOptimizeAnd,newpos); break;
03988 case 2: SetActionOptimized(i,kBoolOptimizeOr,newpos); break;
03989 }
03990 } else if (optaction==kJump || optaction==kJumpIf) {
03991 Int_t oldpos = fOperOffset[i].fToJump;
03992 Int_t newpos = oldpos==fNoper ? fNOperOptimized : map0[oldpos];
03993 fOperOffset[i].fToJump = newpos;
03994 SetActionOptimized(i,optaction,newpos);
03995 }
03996 }
03997
03998
03999 fNOperOptimized = operO;
04000
04001 fOptimal= (TFormulaPrimitive::TFuncG)&TFormula::EvalParFast;
04002 if (fNOperOptimized==1) {
04003 switch(GetActionOptimized(0)){
04004 case kData : {fOptimal= (TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive0; break;}
04005 case kUnary : {fOptimal= (TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive1; break;}
04006 case kBinary : {fOptimal= (TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive2; break;}
04007 case kThree : {fOptimal= (TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive3; break;}
04008 case kFDM : {fOptimal= (TFormulaPrimitive::TFuncG)&TFormula::EvalPrimitive4; break;}
04009 }
04010 }
04011
04012 delete [] map1;
04013 delete [] map0;
04014 delete [] offset;
04015 delete [] optimized;
04016 }
04017
04018
04019 Double_t TFormula::EvalPrimitive(const Double_t *x, const Double_t *params)
04020 {
04021
04022
04023
04024 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
04025 Double_t result = pdata[fOperOffset->fType0][fOperOffset->fOffset0];
04026 switch((fOperOptimized[0] >> kTFOperShift)) {
04027 case kData : return result;
04028 case kUnary : return (fPredefined[0]->fFunc10)(pdata[fOperOffset->fType0][fOperOffset->fOffset0]);
04029 case kBinary :return (fPredefined[0]->fFunc110)(result,
04030 pdata[fOperOffset->fType1][fOperOffset->fOffset1]);
04031
04032 case kThree :return (fPredefined[0]->fFunc1110)(result, pdata[fOperOffset->fType1][fOperOffset->fOffset1],
04033 pdata[fOperOffset->fType2][fOperOffset->fOffset2]);
04034 case kFDM : return (fPredefined[0]->fFuncG)((Double_t*)&x[fOperOffset->fType0],
04035 (Double_t*)¶ms[fOperOffset->fOffset0]);
04036 }
04037 return 0;
04038 }
04039
04040
04041 Double_t TFormula::EvalPrimitive0(const Double_t *x, const Double_t *params)
04042 {
04043
04044
04045
04046 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
04047 return pdata[fOperOffset->fType0][fOperOffset->fOffset0];
04048 }
04049
04050
04051 Double_t TFormula::EvalPrimitive1(const Double_t *x, const Double_t *params)
04052 {
04053
04054
04055
04056 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
04057 return (fPredefined[0]->fFunc10)(pdata[fOperOffset->fType0][fOperOffset->fOffset0]);
04058 }
04059
04060
04061 Double_t TFormula::EvalPrimitive2(const Double_t *x, const Double_t *params)
04062 {
04063
04064
04065
04066 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
04067 return (fPredefined[0]->fFunc110)(pdata[fOperOffset->fType0][fOperOffset->fOffset0],
04068 pdata[fOperOffset->fType1][fOperOffset->fOffset1]);
04069 }
04070
04071
04072 Double_t TFormula::EvalPrimitive3(const Double_t *x, const Double_t *params)
04073 {
04074
04075
04076
04077 const Double_t *pdata[3] = {x,(params!=0)?params:fParams, fConst};
04078 return (fPredefined[0]->fFunc1110)(pdata[fOperOffset->fType0][fOperOffset->fOffset0], pdata[fOperOffset->fType1][fOperOffset->fOffset1],
04079 pdata[fOperOffset->fType2][fOperOffset->fOffset2]);
04080 }
04081
04082
04083 Double_t TFormula::EvalPrimitive4(const Double_t *x, const Double_t *params)
04084 {
04085
04086
04087
04088 const Double_t *par = (params!=0)?params:fParams;
04089 return (fPredefined[0]->fFuncG)((Double_t*)&x[fOperOffset->fType0],
04090 (Double_t*)&par[fOperOffset->fOffset0]);
04091 }
04092
04093
04094
04095 Double_t TFormula::EvalParFast(const Double_t *x, const Double_t *uparams)
04096 {
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111 const Double_t *pdata[3] = {x,(uparams!=0)?uparams:fParams, fConst};
04112
04113 Int_t i,j;
04114 Double_t tab[kMAXFOUND];
04115 const char *stringStack[gMAXSTRINGFOUND];
04116 Double_t param_calc[kMAXFOUND];
04117 char *string_calc[gMAXSTRINGFOUND];
04118 Int_t precalculated = 0;
04119 Int_t precalculated_str = 0;
04120
04121 Double_t *params;
04122
04123 if (uparams) {
04124
04125 params = const_cast<Double_t*>(uparams);
04126 } else {
04127 params = fParams;
04128 }
04129
04130
04131
04132
04133 UInt_t pos = 0;
04134 UInt_t strpos = 0;
04135
04136 for (i=0; i<fNOperOptimized; ++i) {
04137
04138 const int oper = fOperOptimized[i];
04139 const int opcode = oper >> kTFOperShift;
04140
04141 switch(opcode) {
04142 case kData : tab[pos] = pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0]; pos++;continue;
04143 case kPlusD : tab[pos-1]+= pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0]; continue;
04144 case kMultD : tab[pos-1]*= pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0]; continue;
04145 case kAdd : pos--; tab[pos-1] += tab[pos]; continue;
04146 case kSubstract : pos--; tab[pos-1] -= tab[pos]; continue;
04147 case kMultiply : pos--; tab[pos-1] *= tab[pos]; continue;
04148 case kDivide : pos--; if (tab[pos] == 0) tab[pos-1] = 0;
04149 else tab[pos-1] /= tab[pos];
04150 continue;
04151 case kUnary : tab[pos] = (fPredefined[i]->fFunc10)(pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0]); pos++;continue;
04152 case kBinary : tab[pos] = (fPredefined[i]->fFunc110)(pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0],
04153 pdata[fOperOffset[i].fType1][fOperOffset[i].fOffset1]);pos++;continue;
04154
04155 case kThree : tab[pos] = (fPredefined[i]->fFunc1110)(pdata[fOperOffset[i].fType0][fOperOffset[i].fOffset0],
04156 pdata[fOperOffset[i].fType1][fOperOffset[i].fOffset1],
04157 pdata[fOperOffset[i].fType2][fOperOffset[i].fOffset2]); pos++; continue;
04158
04159 case kFDM : tab[pos] = (fPredefined[i]->fFuncG)(&x[fOperOffset[i].fType0],¶ms[fOperOffset[i].fOffset0]); pos++;continue;
04160 case kFD1 : tab[pos-1] =(fPredefined[i]->fFunc10)(tab[pos-1]); continue;
04161 case kFD2 : pos--; tab[pos-1] = (fPredefined[i]->fFunc110)(tab[pos-1],tab[pos]); continue;
04162 case kFD3 : pos-=2; tab[pos-1] = (fPredefined[i]->fFunc1110)(tab[pos-1],tab[pos],tab[pos+1]); continue;
04163 }
04164
04165 switch(opcode) {
04166 case kBoolOptimizeAnd: {
04167 if (!tab[pos-1]) i=fOperOffset[i].fToJump; continue;
04168 }
04169 case kBoolOptimizeOr: {
04170 if (tab[pos-1]) i=fOperOffset[i].fToJump; continue;
04171 }
04172 case kAnd : pos--; tab[pos-1] = (bool)tab[pos]; continue;
04173 case kOr : pos--; tab[pos-1] = (bool)tab[pos]; continue;
04174 }
04175 switch(opcode) {
04176
04177 case kabs : if (tab[pos-1]<0) tab[pos-1]=-tab[pos-1]; continue;
04178 case ksign : if (tab[pos-1] < 0) tab[pos-1] = -1; else tab[pos-1] = 1; continue;
04179 case kint : tab[pos-1] = Double_t(Int_t(tab[pos-1])); continue;
04180 case kpow : pos--; tab[pos-1] = TMath::Power(tab[pos-1],tab[pos]); continue;
04181
04182 case kModulo : {pos--;
04183 Long64_t int1((Long64_t)tab[pos-1]);
04184 Long64_t int2((Long64_t)tab[pos]);
04185 tab[pos-1] = Double_t(int1%int2);
04186 continue;}
04187
04188
04189 case kStringConst: { strpos++; stringStack[strpos-1] = (char*)fExprOptimized[i].Data(); pos++; tab[pos-1] = 0; continue; }
04190 case kfmod : pos--; tab[pos-1] = fmod(tab[pos-1],tab[pos]); continue;
04191
04192 case kstrstr : strpos -= 2; pos-=2; pos++;
04193 if (strstr(stringStack[strpos],stringStack[strpos+1])) tab[pos-1]=1;
04194 else tab[pos-1]=0; continue;
04195 case kpi : pos++; tab[pos-1] = TMath::ACos(-1); continue;
04196
04197
04198 case kSignInv: tab[pos-1] = -1 * tab[pos-1]; continue;
04199
04200 case krndm : pos++; tab[pos-1] = gRandom->Rndm(1); continue;
04201
04202
04203 case kEqual: pos--; if (tab[pos-1] == tab[pos]) tab[pos-1]=1;
04204 else tab[pos-1]=0; continue;
04205 case kNotEqual : pos--; if (tab[pos-1] != tab[pos]) tab[pos-1]=1;
04206 else tab[pos-1]=0; continue;
04207 case kNot : if (tab[pos-1]!=0) tab[pos-1] = 0; else tab[pos-1] = 1; continue;
04208
04209 case kStringEqual : strpos -= 2; pos -=2 ; pos++;
04210 if (!strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
04211 else tab[pos-1]=0; continue;
04212 case kStringNotEqual: strpos -= 2; pos -= 2; pos++;
04213 if (strcmp(stringStack[strpos+1],stringStack[strpos])) tab[pos-1]=1;
04214 else tab[pos-1]=0; continue;
04215
04216 case kBitAnd : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) & ((Int_t) tab[pos]); continue;
04217 case kBitOr : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) | ((Int_t) tab[pos]); continue;
04218 case kLeftShift : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) <<((Int_t) tab[pos]); continue;
04219 case kRightShift: pos--; tab[pos-1]= ((Int_t) tab[pos-1]) >>((Int_t) tab[pos]); continue;
04220
04221 case kJump : i = (oper & kTFOperMask); continue;
04222 case kJumpIf : pos--; if (!tab[pos]) i = (oper & kTFOperMask); continue;
04223
04224 case kBoolOptimize: {
04225
04226
04227 int param = (oper & kTFOperMask);
04228 int op = param % 10;
04229
04230 if (op == 1 && (!tab[pos-1]) ) {
04231
04232
04233 i += param / 10;
04234
04235
04236
04237 tab[pos-1] = 0;
04238
04239 } else if (op == 2 && tab[pos-1] ) {
04240
04241
04242 i += param / 10;
04243
04244
04245
04246 tab[pos-1] = 1;
04247
04248 }
04249
04250 continue;
04251 }
04252
04253 }
04254 switch(opcode) {
04255
04256 #define R__EXPO(var) \
04257 { \
04258 pos++; int param = (oper & kTFOperMask); \
04259 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[var]); \
04260 continue; \
04261 }
04262
04263 case kxexpo: R__EXPO(0);
04264 case kyexpo: R__EXPO(1);
04265 case kzexpo: R__EXPO(2);
04266 case kxyexpo:{ pos++; int param = (oper & kTFOperMask);
04267 tab[pos-1] = TMath::Exp(params[param]+params[param+1]*x[0]+params[param+2]*x[1]);
04268 continue; }
04269 #ifdef R__GAUS
04270 #undef R__GAUS
04271 #endif
04272 #define R__GAUS(var) \
04273 { \
04274 pos++; int param = (oper & kTFOperMask); \
04275 tab[pos-1] = params[param]*TMath::Gaus(x[var],params[param+1], \
04276 params[param+2],IsNormalized()); \
04277 continue; \
04278 }
04279
04280
04281 case kxgaus: R__GAUS(0);
04282 case kygaus: R__GAUS(1);
04283 case kzgaus: R__GAUS(2);
04284 case kxygaus: { pos++; int param = (oper & kTFOperMask);
04285 Double_t intermede1;
04286 if (params[param+2] == 0) {
04287 intermede1=1e10;
04288 } else {
04289 intermede1=Double_t((x[0]-params[param+1])/params[param+2]);
04290 }
04291 Double_t intermede2;
04292 if (params[param+4] == 0) {
04293 intermede2=1e10;
04294 } else {
04295 intermede2=Double_t((x[1]-params[param+3])/params[param+4]);
04296 }
04297 tab[pos-1] = params[param]*TMath::Exp(-0.5*(intermede1*intermede1+intermede2*intermede2));
04298 continue; }
04299
04300 #define R__LANDAU(var) \
04301 { \
04302 pos++; const int param = (oper & kTFOperMask); \
04303 tab[pos-1] = params[param]*TMath::Landau(x[var],params[param+1],params[param+2],IsNormalized()); \
04304 continue; \
04305 }
04306
04307 case kxlandau: R__LANDAU(0);
04308 case kylandau: R__LANDAU(1);
04309 case kzlandau: R__LANDAU(2);
04310 case kxylandau: { pos++; int param = oper&0x7fffff ;
04311 Double_t intermede1=TMath::Landau(x[0], params[param+1], params[param+2],IsNormalized());
04312 Double_t intermede2=TMath::Landau(x[1], params[param+3], params[param+4],IsNormalized());
04313 tab[pos-1] = params[param]*intermede1*intermede2;
04314 continue;
04315 }
04316
04317 #define R__POLY(var) \
04318 { \
04319 pos++; int param = (oper & kTFOperMask); \
04320 tab[pos-1] = 0; Double_t intermede = 1; \
04321 Int_t inter = param/100; \
04322 Int_t int1= param-inter*100-1; \
04323 for (j=0 ;j<inter+1;j++) { \
04324 tab[pos-1] += intermede*params[j+int1]; \
04325 intermede *= x[var]; \
04326 } \
04327 continue; \
04328 }
04329
04330 case kxpol: R__POLY(0);
04331 case kypol: R__POLY(1);
04332 case kzpol: R__POLY(2);
04333
04334 case kDefinedVariable : {
04335 if (!precalculated) {
04336 precalculated = 1;
04337 for(j=0;j<fNval;j++) param_calc[j]=DefinedValue(j);
04338 }
04339 pos++; tab[pos-1] = param_calc[(oper & kTFOperMask)];
04340 continue;
04341 }
04342
04343 case kDefinedString : {
04344 int param = (oper & kTFOperMask);
04345 if (!precalculated_str) {
04346 precalculated_str=1;
04347 for (j=0;j<fNstring;j++) string_calc[j]=DefinedString(j);
04348 }
04349 strpos++; stringStack[strpos-1] = string_calc[param];
04350 pos++; tab[pos-1] = 0;
04351 continue;
04352 }
04353
04354 case kFunctionCall: {
04355
04356
04357 int param = (oper & kTFOperMask);
04358 int fno = param / 1000;
04359 int nargs = param % 1000;
04360
04361
04362 TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
04363
04364
04365 TString args;
04366 if (nargs) {
04367 UInt_t argloc = pos-nargs;
04368 for(j=0;j<nargs;j++,argloc++,pos--) {
04369 if (TMath::IsNaN(tab[argloc])) {
04370
04371
04372 args += "(double)(0x8000000000000)";
04373 } else {
04374 args += tab[argloc];
04375 }
04376 args += ',';
04377 }
04378 args.Remove(args.Length()-1);
04379 }
04380 pos++;
04381 Double_t ret;
04382 method->Execute(args,ret);
04383 tab[pos-1] = ret;
04384
04385 continue;
04386 };
04387 }
04388 if (!TestBit(kOptimizationError)) {
04389 SetBit(kOptimizationError);
04390 Warning("EvalParFast","Found an unsupported optmized opcode (%d)",oper >> kTFOperShift);
04391 }
04392 }
04393 Double_t result0 = tab[0];
04394 return result0;
04395
04396 }
04397
04398
04399
04400 Int_t TFormula::PreCompile()
04401 {
04402
04403
04404
04405 TString str = fTitle;
04406 if (str.Length()<3) return 1;
04407 if (str[str.Length()-1]!='+'&&str[str.Length()-2]!='+') return 1;
04408 str[str.Length()-2]=0;
04409 TString funName("preformula_");
04410 funName += fName;
04411 if (TFormulaPrimitive::FindFormula(funName)) return 0;
04412 TString fileName;
04413 fileName.Form("/tmp/%s.C",funName.Data());
04414
04415 FILE *hf;
04416 hf = fopen(fileName.Data(),"w");
04417 if (hf == 0) {
04418 Error("PreCompile","Unable to open the file %s for writing.",fileName.Data());
04419 return 1;
04420 }
04421 fprintf(hf, "/////////////////////////////////////////////////////////////////////////\n");
04422 fprintf(hf, "// This code has been automatically generated \n");
04423
04424 fprintf(hf, "Double_t %s(Double_t *x, Double_t *p){",funName.Data());
04425 fprintf(hf, "return (%s);\n}",str.Data());
04426
04427
04428
04429 fclose(hf);
04430
04431 return 0;
04432
04433
04434 }
04435
04436
04437
04438 void TFormula::SetMaxima(Int_t maxop, Int_t maxpar, Int_t maxconst)
04439 {
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450 gMAXOP = TMath::Max(10,maxop);
04451 gMAXPAR = TMath::Max(10,maxpar);
04452 gMAXCONST = TMath::Max(10,maxconst);
04453 }