#include <math.h>
#include "Riostream.h"
#include "TROOT.h"
#include "TClass.h"
#include "TFormula.h"
#include "TMath.h"
#include "TRandom.h"
#include "TFunction.h"
#include "TMethodCall.h"
#include "TObjString.h"
#include "TError.h"
#include "v5/TFormulaPrimitive.h"
#ifdef WIN32
#pragma optimize("",off)
#endif
#include "PFormula.h"
#include <iostream>
using namespace std;
static Int_t  gMAXOP=1000, gMAXPAR=1000, gMAXCONST=1000;
const  Int_t  gMAXSTRINGFOUND = 10;
const  UInt_t kOptimizationError = BIT(19);
PFormula::PFormula() : ROOT::v5::TFormula() {
}
#if 1
PFormula::PFormula(const char *name, const char *expression) : ROOT::v5::TFormula()
{
    
    fNdim   = 0;
    fNpar   = 0;
    fNoper  = 0;
    fNconst = 0;
    fNumber = 0;
    fExpr   = 0;
    
    fConst  = 0;
    fParams = 0;
    fNstring= 0;
    fNames  = 0;
    fNval   = 0;
    
    
    fNOperOptimized = 0;
    fExprOptimized  = 0;
    fOperOptimized  = 0;
    fOperOffset     = 0;
    fPredefined     = 0;
    fOptimal        = (ROOT::v5::TFormulaPrimitive::TFuncG)&TFormula::EvalParOld;
    if (!expression || !*expression) {
	Error("TFormula", "expression may not be 0 or have 0 length");
	return;
    }
    
    Int_t i,j,nch;
    nch = strlen(expression);
    char *expr = new char[nch+1];
    j = 0;
    for (i=0;i<nch;i++) {       
	if (expression[i] == ' ') continue;
	if (i > 0 && (expression[i] == '*') && (expression[i-1] == '*')) {
	    expr[j-1] = '^';
	    continue;
	}
	expr[j] = expression[i]; j++;
    }
    expr[j] = 0;
    Bool_t gausNorm   = kFALSE;
    Bool_t landauNorm = kFALSE;
    Bool_t linear = kFALSE;
    if (j) {
	TString chaine = expr;
	
	if (chaine.Contains("++"))
	    linear = kTRUE;
	
	if (chaine.Contains("gausn")) {
	    gausNorm = kTRUE;
	    chaine.ReplaceAll("gausn","gaus");
	}
	
	if (chaine.Contains("landaun")) {
	    landauNorm = kTRUE;
	    chaine.ReplaceAll("landaun","landau");
	}
	SetTitle(chaine.Data());
    }
    delete [] expr;
    if (linear)    SetBit(kLinear);
    
    chaine = GetTitle();
    
    Int_t lc,valeur;
    TString ctemp;
    
    
    Bool_t inString = false;
    for (i=1; i<=chaine.Length(); i++) {
	lc =chaine.Length();
	if (chaine(i-1,1) == "\"") inString = !inString;
	if (inString) continue;
	if (chaine(i-1,2) == "**") {
	    chaine = chaine(0,i-1) + "^" + chaine(i+1,lc-i-1);
	    i=0;
	} else if (chaine(i-1,2) == "++") {
	    chaine = chaine(0,i) + chaine(i+1,lc-i-1);
	    i=0;
	} else if (chaine(i-1,2) == "+-" || chaine(i-1,2) == "-+") {
	    chaine = chaine(0,i-1) + "-" + chaine(i+1,lc-i-1);
	    i=0;
	} else if (chaine(i-1,2) == "--") {
	    chaine = chaine(0,i-1) + "+" + chaine(i+1,lc-i-1);
	    i=0;
	} else if (chaine(i-1,2) == "->") {
	    chaine = chaine(0,i-1) + "." + chaine(i+1,lc-i-1);
	    i=0;
	} else if (chaine(i-1,1) == "[") {
	    for (j=1;j<=chaine.Length()-i;j++) {
		if (chaine(j+i-1,1) == "]" || j+i > chaine.Length()) break;
	    }
	    ctemp = chaine(i,j-1);
	    valeur=0;
	    sscanf(ctemp.Data(),"%d",&valeur);
	    if (valeur >= fNpar) fNpar = valeur+1;
	} else if (chaine(i-1,1) == " ") {
	    chaine = chaine(0,i-1)+chaine(i,lc-i);
	    i=0;
	}
    }
    
   
    if (Compile()) return;
    if (gausNorm)   SetBit(kNormalized);
    if (landauNorm) SetBit(kNormalized);
    
    TFormula *old = (TFormula*)gROOT->GetListOfFunctions()->FindObject(name);
    if (old) {
	gROOT->GetListOfFunctions()->Remove(old);
    }
    if (strcmp(name,"x")==0 || strcmp(name,"y")==0 ||
	strcmp(name,"z")==0 || strcmp(name,"t")==0 )
	{
	    Error("TFormula","The name \'%s\' is reserved as a TFormula variable name.\n"
		  "\tThis function will not be registered in the list of functions",name);
	} else {
	gROOT->GetListOfFunctions()->Add(this);
    }
}
void PFormula::Analyze(const char *schain, Int_t &err, Int_t offset)
{
    Int_t valeur,find,n,i,j,k,lchain,nomb,virgule,inter,nest;
    Int_t compt,compt2,compt3,compt4;
    Bool_t inString;
    Double_t vafConst;
    ULong_t vafConst2;
    Bool_t parenthese;
    TString s,chaine_error,chaine1ST;
    TString s1,s2,s3,ctemp;
    TString chaine = schain;
    TFormula *oldformula;
    Int_t modulo,plus,puiss10,puiss10bis,moins,multi,divi,puiss,et,ou,petit,grand,egal,diff,peteg,grdeg,etx,oux,rshift,lshift;
    char t;
    TString slash("/"), escapedSlash("\\/");
    Int_t inter2 = 0;
    SetNumber(0);
    Int_t actionCode,actionParam;
    Int_t err_hint = 0;
    
    
    lchain = chaine.Length();
    
    parenthese = kTRUE;
    lchain = chaine.Length();
    while (parenthese && lchain>0 && err==0){
	compt  = 0;
	compt2 = 0;
	inString = false;
	lchain = chaine.Length();
	if (lchain==0) err=4;
	else {
	    for (i=1; i<=lchain; ++i) {
		if (chaine(i-1,1) == "\"") inString = !inString;
		if (!inString) {
		    if (chaine(i-1,1) == "[") compt2++;
		    if (chaine(i-1,1) == "]") compt2--;
		    if (chaine(i-1,1) == "(") compt++;
		    if (chaine(i-1,1) == ")") compt--;
		}
		if (compt < 0) err = 40; 
		if (compt2< 0) err = 42; 
		if (compt==0 && (i!=lchain || lchain==1)) parenthese = kFALSE;
		
	    }
	    if (compt > 0) err = 41; 
	    if (compt2> 0) err = 43; 
	    if (parenthese) chaine = chaine(1,lchain-2);
	}
    } 
    if (lchain==0) err=4; 
    modulo=plus=moins=multi=divi=puiss=et=ou=petit=grand=egal=diff=peteg=grdeg=etx=oux=rshift=lshift=0;
    
    
    if (err==0) {
	compt = compt2 = compt3 = compt4 = 0;puiss10=0;puiss10bis = 0;
	inString = false;
	j = lchain;
	Bool_t isdecimal = 1; 
	for (i=1;i<=lchain; i++) {
	    puiss10=puiss10bis=0;
	    if (i>2) {
		t = chaine[i-3];
		isdecimal = isdecimal && (strchr("0123456789.",t)!=0);
		if (isdecimal) {
		    if ( chaine[i-2] == 'e' ) puiss10 = 1;
		} else if ( strchr("+-/[]()&|><=!*/%^\\",t) ) {
		    isdecimal = 1; 
		}
	    }
	    if (j>2) {
		if (chaine[j-2] == 'e') {
		    Bool_t isrightdecimal = 1;
		    for(k=j-3; k>=0 && isrightdecimal; --k) {
			t = chaine[k];
			isrightdecimal = isrightdecimal && (strchr("0123456789.",t)!=0);
			if (!isrightdecimal) {
			    if (strchr("+-/[]()&|><=!*/%^\\",t)!=0) {
				puiss10bis = 1;
			    }
			}
		    }
		    if (k<0 && isrightdecimal)  puiss10bis = 1;
		}
	    }
	    if (puiss10 && (i<=lchain)) {
		t = chaine[i];
		puiss10 = (strchr("0123456789.",t)!=0);
	    }
	    if (puiss10bis && (j<=lchain)) {
		t = chaine[j];
		puiss10bis = (strchr("0123456789.",t)!=0);
	    }
	    if (chaine(i-1,1) == "\"") inString = !inString;
	    if (inString) continue;
	    if (chaine(i-1,1) == "[") compt2++;
	    if (chaine(i-1,1) == "]") compt2--;
	    if (chaine(i-1,1) == "(") compt++;
	    if (chaine(i-1,1) == ")") compt--;
	    if (chaine(j-1,1) == "[") compt3++;
	    if (chaine(j-1,1) == "]") compt3--;
	    if (chaine(j-1,1) == "(") compt4++;
	    if (chaine(j-1,1) == ")") compt4--;
	    if (chaine(i-1,2)=="&&" && !inString && compt==0 && compt2==0 && et==0) {et=i;puiss=0;}
	    if (chaine(i-1,2)=="||" && compt==0 && compt2==0 && ou==0) {puiss10=0; ou=i;}
	    if (chaine(i-1,1)=="&"  && compt==0 && compt2==0 && etx==0) {etx=i;puiss=0;}
	    if (chaine(i-1,1)=="|"  && compt==0 && compt2==0 && oux==0) {puiss10=0; oux=i;}
	    if (chaine(i-1,2)==">>" && compt==0 && compt2==0 && rshift==0) {puiss10=0; rshift=i;}
	    if (chaine(i-1,1)==">"  && compt==0 && compt2==0 && rshift==0 && grand==0)
		{puiss10=0; grand=i;}
	    if (chaine(i-1,2)=="<<" && compt==0 && compt2==0 && lshift==0) {puiss10=0; lshift=i;}
	    if (chaine(i-1,1)=="<"  && compt==0 && compt2==0 && lshift==0 && petit==0)
		{puiss10=0; petit=i;
		    
		    
		    for(int ip = i,depth=0; ip < lchain; ++ip) {
			char c = chaine(ip);
			
			
			if (isalnum(c) || c=='_' || c==',') continue;
			if (c==':' && chaine(ip+1)==':') { ++ip; continue; }
			if (c=='<') { ++depth; continue; }
			if (c=='>') {
			    if (depth) { --depth; continue; }
			    else {
				
				petit = 0;
				i = ip+1;
				break;
			    }
			}
			
			break;
		    }
		    if (petit==0) {
			
			continue; 
		    }
		}
	    if ((chaine(i-1,2)=="<=" || chaine(i-1,2)=="=<") && compt==0 && compt2==0
		&& peteg==0) {peteg=i; puiss10=0; petit=0;}
	    if ((chaine(i-1,2)=="=>" || chaine(i-1,2)==">=") && compt==0 && compt2==0
		&& grdeg==0) {puiss10=0; grdeg=i; grand=0;}
	    if (chaine(i-1,2) == "==" && compt == 0 && compt2 == 0 && egal == 0) {puiss10=0; egal=i;}
	    if (chaine(i-1,2) == "!=" && compt == 0 && compt2 == 0 && diff == 0) {puiss10=0; diff=i;}
	    if (i>1 && chaine(i-1,1) == "+" && compt == 0 && compt2 == 0 && puiss10==0) plus=i;
	    if (chaine(j-1,1) == "-" && chaine(j-2,1) != "*" && chaine(j-2,1) != "/"
		&& chaine(j-2,1)!="^" && compt3==0 && compt4==0 && moins==0 && puiss10bis==0) moins=j;
	    if (chaine(i-1,1)=="%" && compt==0 && compt2==0 && modulo==0) {puiss10=0; modulo=i;}
	    if (chaine(i-1,1)=="*" && compt==0 && compt2==0 && multi==0)  {puiss10=0; multi=i;}
	    if (chaine(j-1,1)=="/" && chaine(j-2,1)!="\\"
		&& compt4==0 && compt3==0 && divi==0)
		{
		    puiss10=0; divi=j;
		}
	    if (chaine(j-1,1)=="^" && compt4==0 && compt3==0 && puiss==0) {puiss10=0; puiss=j;}
	    j--;
	}
	
	
	actionParam = 0;
	if (ou != 0) {    
	    if (ou==1 || ou==lchain-1) {
		err=5;
		chaine_error="||";
	    }
	    else {
		ctemp = chaine(0,ou-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "|| checkpoint";
		actionCode = kBoolOptimize;
		actionParam = 2;
		SetAction(fNoper,actionCode, actionParam);
		Int_t optloc = fNoper++;
		ctemp = chaine(ou+1,lchain-ou-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "||";
		actionCode = kOr;
		SetAction(fNoper,actionCode, 0);
		SetAction( optloc, GetAction(optloc), GetActionParam(optloc) + (fNoper-optloc) * 10);
		fNoper++;
	    }
	} else if (et!=0) {
	    if (et==1 || et==lchain-1) {
		err=5;
		chaine_error="&&";
	    }
	    else {
		ctemp = chaine(0,et-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "&& checkpoint";
		actionCode = kBoolOptimize;
		actionParam = 1;
		SetAction(fNoper,actionCode,actionParam);
		Int_t optloc = fNoper++;
		ctemp = chaine(et+1,lchain-et-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "&&";
		actionCode = kAnd;
		SetAction(fNoper,actionCode,0);
		SetAction(optloc, GetAction(optloc), GetActionParam(optloc) + (fNoper-optloc) * 10);
		fNoper++;
	    }
	} else if (oux!=0) {
	    if (oux==1 || oux==lchain) {
		err=5;
		chaine_error="|";
	    }
	    else {
		ctemp = chaine(0,oux-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(oux,lchain-oux);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "|";
		actionCode = kBitOr;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (etx!=0) {
	    if (etx==1 || etx==lchain) {
		err=5;
		chaine_error="&";
	    }
	    else {
		ctemp = chaine(0,etx-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(etx,lchain-etx);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "&";
		actionCode = kBitAnd;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (petit != 0) {
	    if (petit==1 || petit==lchain) {
		err=5;
		chaine_error="<";
	    }
	    else {
		ctemp = chaine(0,petit-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(petit,lchain-petit);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "<";
		actionCode = kLess;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (grand != 0) {
	    if (grand==1 || grand==lchain) {
		err=5;
		chaine_error=">";
	    }
	    else {
		ctemp = chaine(0,grand-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(grand,lchain-grand);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = ">";
		actionCode = kGreater;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (peteg != 0) {
	    if (peteg==1 || peteg==lchain-1) {
		err=5;
		chaine_error="<=";
	    }
	    else {
		ctemp = chaine(0,peteg-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(peteg+1,lchain-peteg-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "<=";
		actionCode = kLessThan;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (grdeg != 0) {
	    if (grdeg==1 || grdeg==lchain-1) {
		err=5;
		chaine_error="=>";
	    }
	    else {
		ctemp = chaine(0,grdeg-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(grdeg+1,lchain-grdeg-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = ">=";
		actionCode = kGreaterThan;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (egal != 0) {
	    if (egal==1 || egal==lchain-1) {
		err=5;
		chaine_error="==";
	    }
	    else {
		ctemp = chaine(0,egal-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(egal+1,lchain-egal-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "==";
		actionCode = kEqual;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (diff != 0) {
	    if (diff==1 || diff==lchain-1) {
		err=5;
		chaine_error = "!=";
	    }
	    else {
		ctemp = chaine(0,diff-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(diff+1,lchain-diff-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "!=";
		actionCode = kNotEqual;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else if (plus != 0) {
	    if (plus==lchain) {
		err=5;
		chaine_error = "+";
	    }
	    else {
		ctemp = chaine(0,plus-1);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		ctemp = chaine(plus,lchain-plus);
		Analyze(ctemp.Data(),err,offset); if (err) return;
		fExpr[fNoper] = "+";
		actionCode = kAdd;
		SetAction(fNoper,actionCode,actionParam);
		fNoper++;
	    }
	} else {
	    if (moins != 0) {
		if (moins == 1) {
		    ctemp = chaine(moins,lchain-moins);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    fExpr[fNoper] = "-";
		    actionCode = kSignInv;
		    SetAction(fNoper,actionCode,actionParam);
		    ++fNoper;
		} else {
		    if (moins == lchain) {
			err=5;
			chaine_error = "-";
		    } else {
			ctemp = chaine(0,moins-1);
			Analyze(ctemp.Data(),err,offset); if (err) return;
			ctemp = chaine(moins,lchain-moins);
			Analyze(ctemp.Data(),err,offset); if (err) return;
			fExpr[fNoper] = "-";
			actionCode = kSubstract;
			SetAction(fNoper,actionCode,actionParam);
			fNoper++;
		    }
		}
	    } else if (modulo != 0) {
		if (modulo == 1 || modulo == lchain) {
		    err=5;
		    chaine_error="%";
		} else {
		    ctemp = chaine(0,modulo-1);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    ctemp = chaine(modulo,lchain-modulo);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    fExpr[fNoper] = "%";
		    actionCode = kModulo;
		    SetAction(fNoper,actionCode,actionParam);
		    fNoper++;
		}
	    } else if (rshift != 0) {
		if (rshift == 1 || rshift == lchain) {
		    err=5;
		    chaine_error=">>";
		} else {
		    ctemp = chaine(0,rshift-1);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    ctemp = chaine(rshift+1,lchain-rshift-1);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    fExpr[fNoper] = ">>";
		    actionCode = kRightShift;
		    SetAction(fNoper,actionCode,actionParam);
		    fNoper++;
		}
	    } else if (lshift != 0) {
		if (lshift == 1 || lshift == lchain) {
		    err=5;
		    chaine_error=">>";
		} else {
		    ctemp = chaine(0,lshift-1);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    ctemp = chaine(lshift+1,lchain-lshift-1);
		    Analyze(ctemp.Data(),err,offset); if (err) return;
		    fExpr[fNoper] = ">>";
		    actionCode = kLeftShift;
		    SetAction(fNoper,actionCode,actionParam);
		    fNoper++;
		}
	    } else {
		if (multi != 0) {
		    if (multi == 1 || multi == lchain) {
			err=5;
			chaine_error="*";
		    }
		    else {
			ctemp = chaine(0,multi-1);
			Analyze(ctemp.Data(),err,offset); if (err) return;
			ctemp = chaine(multi,lchain-multi);
			Analyze(ctemp.Data(),err,offset); if (err) return;
			fExpr[fNoper] = "*";
			actionCode = kMultiply;
			SetAction(fNoper,actionCode,actionParam);
			fNoper++;
		    }
		} else {
		    if (divi != 0) {
			if (divi == 1 || divi == lchain) {
			    err=5;
			    chaine_error = "/";
			}
			else {
			    ctemp = chaine(0,divi-1);
			    Analyze(ctemp.Data(),err,offset); if (err) return;
			    ctemp = chaine(divi,lchain-divi);
			    Analyze(ctemp.Data(),err,offset); if (err) return;
			    fExpr[fNoper] = "/";
			    actionCode = kDivide;
			    SetAction(fNoper,actionCode,actionParam);
			    fNoper++;
			}
		    } else {
			if (puiss != 0) {
			    if (puiss == 1 || puiss == lchain) {
				err = 5;
				chaine_error = "**";
			    }
			    else {
				if (chaine(lchain-2,2) == "^2") {
				    ctemp = "sq(" + chaine(0,lchain-2) + ")";
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				} else {
				    ctemp = chaine(0,puiss-1);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    ctemp = chaine(puiss,lchain-puiss);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "^";
				    actionCode = kpow;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				}
			    }
			} else {
			    find=0;
			    
			    {
				Bool_t hasDot = kFALSE;
				Bool_t isHexa = kFALSE;
				Bool_t hasExpo= kFALSE;
				if ((chaine(0,2)=="0x")||(chaine(0,2)=="0X")) isHexa=kTRUE;
				for (j=0; j<chaine.Length() && err==0; j++) {
				    t=chaine[j];
				    if (!isHexa) {
					if (j>0 && (chaine(j,1)=="e" || chaine(j,2)=="e+" || chaine(j,2)=="e-")) {
					    if (hasExpo) {
						err=26;
						chaine_error=chaine;
					    }
					    hasExpo = kTRUE;
					    
					    
					    
					    hasDot = kTRUE;  
					    if (chaine(j,2)=="e+" || chaine(j,2)=="e-") j++;
					}
					else {
					    if (chaine(j,1) == "." && !hasDot) hasDot = kTRUE; 
					    else {
						
						
						
						if (!strchr("0123456789",t) && (chaine(j,1)!="+" || j!=0)) {
						    err = 30;
						    chaine_error=chaine;
						}
					    }
					}
				    }
				    else {
					if (!strchr("0123456789abcdefABCDEF",t) && (j>1)) {
					    err = 30;
					    chaine_error=chaine;
					}
				    }
				}
				if (fNconst >= gMAXCONST) err = 27;
				if (!err) {
				    if (!isHexa) {if (sscanf((const char*)chaine,"%lg",&vafConst) > 0) err = 0; else err =1;}
				    else {if (sscanf((const char*)chaine,"%lx",&vafConst2) > 0) err = 0; else err=1;
					vafConst = (Double_t) vafConst2;}
				    fExpr[fNoper] = chaine;
				    k = -1;
				    for (j=0;j<fNconst;j++) {
					if (vafConst == fConst[j] ) k= j;
				    }
				    if ( k < 0) {  k = fNconst; fNconst++; fConst[k] = vafConst; }
				    actionCode = kConstant;
				    actionParam = k;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				}
				if (err==30) err=0;
				else find = kTRUE;
			    }
			    
			    if (find==0) {
				oldformula = (TFormula*)gROOT->GetListOfFunctions()->FindObject((const char*)chaine);
				if (oldformula && strcmp(schain,oldformula->GetTitle())) {
				    Int_t nprior = fNpar;
				    Analyze(oldformula->GetExpFormula(),err,fNpar); if (err) return; 
				    fNpar = nprior;
				    find=1;
				    if (!err) {
					Int_t npold = oldformula->GetNpar();
					fNpar += npold;
					for (Int_t ipar=0;ipar<npold;ipar++) {
					    fParams[ipar+fNpar-npold] = oldformula->GetParameter(ipar);
					}
				    }
				}
			    }
			    if (find == 0) {
				
				
				ctemp = chaine;
				ctemp.ReplaceAll(escapedSlash, slash);
				Int_t action;
				k = DefinedVariable(ctemp,action);
				if (k==-3) {
				    
				    err = 1;
				} if (k==-2) {
				    err = 31;
				    chaine_error = ctemp;
				} else if ( k >= 0 ) {
				    fExpr[fNoper] = ctemp;
				    actionCode = action;
				    actionParam = k;
				    SetAction(fNoper,actionCode,actionParam);
				    if (action==kDefinedString) fNstring++;
				    else if (k <kMAXFOUND && !fAlreadyFound.TestBitNumber(k)) {
					fAlreadyFound.SetBitNumber(k);
					fNval++;
				    }
				    fNoper++;
				} else if (chaine(0,1) == "!") {
				    ctemp = chaine(1,lchain-1);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "!";
				    actionCode = kNot;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,1)=="\"" && chaine(chaine.Length()-1,1)=="\"") {
				    
				    fExpr[fNoper] = chaine(1,chaine.Length()-2);
				    actionCode = kStringConst;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,4) == "cos(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "cos";
				    actionCode = kcos;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,4) == "sin(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "sin";
				    actionCode = ksin;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,4) == "tan(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "tan";
				    actionCode = ktan;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,5) == "acos(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "acos";
				    actionCode = kacos;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,5) == "asin(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "asin";
				    actionCode = kasin;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,5) == "atan(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "atan";
				    actionCode = katan;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,5) == "cosh(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "cosh";
				    actionCode = kcosh;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				} else if (chaine(0,5) == "sinh(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "sinh";
				    actionCode = ksinh;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,5) == "tanh(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "tanh";
				    actionCode = ktanh;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,6) == "acosh(") {
				    ctemp = chaine(5,lchain-5);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "acosh";
				    actionCode = kacosh;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,6) == "asinh(") {
				    ctemp = chaine(5,lchain-5);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "asinh";
				    actionCode = kasinh;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,6) == "atanh(") {
				    ctemp = chaine(5,lchain-5);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "atanh";
				    actionCode = katanh;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,3) == "sq(") {
				    ctemp = chaine(2,lchain-2);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "sq";
				    actionCode = ksq;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,4) == "log(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "log";
				    actionCode = klog;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,6) == "log10(") {
				    ctemp = chaine(5,lchain-5);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "log10";
				    actionCode = klog10;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,4) == "exp(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "exp";
				    actionCode = kexp;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,4) == "abs(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "abs";
				    actionCode = kabs;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,5) == "sign(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "sign";
				    actionCode = ksign;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,4) == "int(") {
				    ctemp = chaine(3,lchain-3);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "int";
				    actionCode = kint;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine == "rndm" || chaine(0,5) == "rndm(") {
				    fExpr[fNoper] = "rndm";
				    actionCode = krndm;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				} else if (chaine(0,5) == "sqrt(") {
				    ctemp = chaine(4,lchain-4);
				    Analyze(ctemp.Data(),err,offset); if (err) return;
				    fExpr[fNoper] = "sqrt";
				    actionCode = ksqrt;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;;
				    
				    
				} else if ( chaine == "expo" || chaine(0,5)=="expo("
					    || (lchain==5 && chaine(1,4)=="expo")
					    || (lchain==6 && chaine(2,4)=="expo")
					    || chaine(1,5)=="expo(" || chaine(2,5)=="expo(" ) {
				    chaine1ST=chaine;
				    if (chaine(1,4) == "expo") {
					ctemp=chaine(0,1);
					if (ctemp=="x") {
					    inter2=0;
					    if (fNdim < 1) fNdim = 1; }
					else if (ctemp=="y") {
					    inter2=1;
					    if (fNdim < 2) fNdim = 2; }
					else if (ctemp=="z") {
					    inter2=2;
					    if (fNdim < 3) fNdim = 3; }
					else if (ctemp=="t") {
					    inter2=3;
					    if (fNdim < 4) fNdim = 4; }
					else {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					chaine=chaine(1,lchain-1);
					lchain=chaine.Length();
				    } else inter2=0;
				    if (chaine(2,4) == "expo") {
					if (chaine(0,2) != "xy") {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					else {
					    inter2=5;
					    if (fNdim < 2) fNdim = 2;
					    chaine=chaine(2,lchain-2);
					    lchain=chaine.Length();
					}
				    }
				    if (lchain == 4) {
					if (fNpar>=gMAXPAR) err=7; 
					if (!err) {
					    fExpr[fNoper] = chaine1ST;
					    actionCode = kexpo + inter2;
					    actionParam = offset;
					    SetAction(fNoper,actionCode,actionParam);
					    if (inter2 == 5+offset && fNpar < 3+offset) fNpar = 3+offset;
					    if (fNpar < 2+offset) fNpar = 2+offset;
					    if (fNpar>=gMAXPAR) err=7; 
					    if (!err) {
						fNoper++;
						if (fNdim < 1) fNdim = 1;
						if (fNpar == 2) SetNumber(200);
					    }
					}
				    } else if (chaine(4,1) == "(") {
					ctemp = chaine(5,lchain-6);
					fExpr[fNoper] = chaine1ST;
					for (j=0; j<ctemp.Length(); j++) {
					    t=ctemp[j];
					    if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
						err=20;
						chaine_error=chaine1ST;
					    }
					}
					if (err==0) {
					    sscanf(ctemp.Data(),"%d",&inter);
					    if (inter>=0) {
						inter += offset;
						actionCode = kexpo + inter2;
						actionParam = inter;
						SetAction(fNoper,actionCode,actionParam);
						if (inter2 == 5) inter++;
						if (inter+2>fNpar) fNpar = inter+2;
						if (fNpar>=gMAXPAR) err=7; 
						if (!err) fNoper++;
						if (fNpar == 2) SetNumber(200);
					    } else err=20;
					} else err = 20; 
				    } else {
					err=26; 
					chaine_error=chaine;
				    }
				    
				    
				} else if (chaine=="gaus"
					   || (lchain==5 && chaine(1,4)=="gaus")
					   || (lchain==6 && chaine(2,4)=="gaus")
					   || chaine(0,5)=="gaus(" || chaine(1,5)=="gaus(" || chaine(2,5)=="gaus(") {
				    chaine1ST=chaine;
				    if (chaine(1,4) == "gaus") {
					ctemp=chaine(0,1);
					if (ctemp=="x") {
					    inter2=0;
					    if (fNdim < 1) fNdim = 1; }
					else if (ctemp=="y") {
					    inter2=1;
					    if (fNdim < 2) fNdim = 2; }
					else if (ctemp=="z") {
					    inter2=2;
					    if (fNdim < 3) fNdim = 3; }
					else if (ctemp=="t") {
					    inter2=3;
					    if (fNdim < 4) fNdim = 4; }
					else {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					chaine=chaine(1,lchain-1);
					lchain=chaine.Length();
				    } else inter2=0;
				    if (chaine(2,4) == "gaus") {
					if (chaine(0,2) != "xy") {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					else {
					    inter2=5;
					    if (fNdim < 2) fNdim = 2;
					    chaine=chaine(2,lchain-2);
					    lchain=chaine.Length();
					}
				    }
				    if (lchain == 4 && err==0) {
					if (fNpar>=gMAXPAR) err=7; 
					if (!err) {
					    fExpr[fNoper] = chaine1ST;
					    actionCode = kgaus + inter2;
					    actionParam = offset;
					    SetAction(fNoper,actionCode,actionParam);
					    if (inter2 == 5+offset && fNpar < 5+offset) fNpar = 5+offset;
					    if (3+offset>fNpar) fNpar = 3+offset;
					    if (fNpar>=gMAXPAR) err=7; 
					    if (!err) {
						fNoper++;
						if (fNdim < 1) fNdim = 1;
						if (fNpar == 3) SetNumber(100);
					    }
					}
				    } else if (chaine(4,1) == "(" && err==0) {
					ctemp = chaine(5,lchain-6);
					fExpr[fNoper] = chaine1ST;
					for (j=0; j<ctemp.Length(); j++) {
					    t=ctemp[j];
					    if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
						err=20;
						chaine_error=chaine1ST;
					    }
					}
					if (err==0) {
					    sscanf(ctemp.Data(),"%d",&inter);
					    if (inter >= 0) {
						inter += offset;
						actionCode = kgaus + inter2;
						actionParam = inter;
						SetAction(fNoper,actionCode,actionParam);
						if (inter2 == 5) inter += 2;
						if (inter+3>fNpar) fNpar = inter+3;
						if (fNpar>=gMAXPAR) err=7; 
						if (!err) fNoper++;
						if(fNpar == 3) SetNumber(100);
					    } else err = 20; 
					}
				    } else if (err==0) {
					err=26; 
					chaine_error=chaine1ST;
				    }
				    
				    
				} else if (chaine=="landau" || (lchain==7 && chaine(1,6)=="landau")
					   || (lchain==8 && chaine(2,6)=="landau")
					   || chaine(0,7)=="landau(" || chaine(1,7)=="landau(" || chaine(2,7)=="landau(") {
				    chaine1ST=chaine;
				    if (chaine(1,6) == "landau") {
					ctemp=chaine(0,1);
					if (ctemp=="x") {
					    inter2=0;
					    if (fNdim < 1) fNdim = 1; }
					else if (ctemp=="y") {
					    inter2=1;
					    if (fNdim < 2) fNdim = 2; }
					else if (ctemp=="z") {
					    inter2=2;
					    if (fNdim < 3) fNdim = 3; }
					else if (ctemp=="t") {
					    inter2=3;
					    if (fNdim < 4) fNdim = 4; }
					else {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					chaine=chaine(1,lchain-1);
					lchain=chaine.Length();
				    } else inter2=0;
				    if (chaine(2,6) == "landau") {
					if (chaine(0,2) != "xy") {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					else {
					    inter2=5;
					    if (fNdim < 2) fNdim = 2;
					    chaine=chaine(2,lchain-2);
					    lchain=chaine.Length();
					}
				    }
				    if (lchain == 6 && err==0) {
					if (fNpar>=gMAXPAR) err=7; 
					if (!err) {
					    fExpr[fNoper] = chaine1ST;
					    actionCode = klandau + inter2;
					    actionParam = offset;
					    SetAction(fNoper,actionCode,actionParam);
					    if (inter2 == 5+offset && fNpar < 5+offset) fNpar = 5+offset;
					    if (3+offset>fNpar) fNpar = 3+offset;
					    if (fNpar>=gMAXPAR) err=7; 
					    if (!err) {
						fNoper++;
						if (fNdim < 1) fNdim = 1;
						if (fNpar == 3) SetNumber(400);
					    }
					}
				    } else if (chaine(6,1) == "(" && err==0) {
					ctemp = chaine(7,lchain-8);
					fExpr[fNoper] = chaine1ST;
					for (j=0; j<ctemp.Length(); j++) {
					    t=ctemp[j];
					    if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
						err=20;
						chaine_error=chaine1ST;
					    }
					}
					if (err==0) {
					    sscanf(ctemp.Data(),"%d",&inter);
					    if (inter >= 0) {
						inter += offset;
						actionCode = klandau + inter2;
						actionParam = inter;
						SetAction(fNoper,actionCode,actionParam);
						if (inter2 == 5) inter += 2;
						if (inter+3>fNpar) fNpar = inter+3;
						if (fNpar>=gMAXPAR) err=7; 
						if (!err) fNoper++;
						if (fNpar == 3) SetNumber(400);
					    } else err = 20; 
					}
				    } else if (err==0) {
					err=26; 
					chaine_error=chaine1ST;
				    }
				    
				    
				} else if (chaine(0,3) == "pol" || chaine(1,3) == "pol") {
				    chaine1ST=chaine;
				    if (chaine(1,3) == "pol") {
					ctemp=chaine(0,1);
					if (ctemp=="x") {
					    inter2=1;
					    if (fNdim < 1) fNdim = 1; }
					else if (ctemp=="y") {
					    inter2=2;
					    if (fNdim < 2) fNdim = 2; }
					else if (ctemp=="z") {
					    inter2=3;
					    if (fNdim < 3) fNdim = 3; }
					else if (ctemp=="t") {
					    inter2=4;
					    if (fNdim < 4) fNdim = 4; }
					else {
					    err=26; 
					    chaine_error=chaine1ST;
					}
					chaine=chaine(1,lchain-1);
					lchain=chaine.Length();
				    } else inter2=1;
				    if (chaine(lchain-1,1) == ")") {
					nomb = 0;
					for (j=3;j<lchain;j++) if (chaine(j,1)=="(" && nomb == 0) nomb = j;
					if (nomb == 3) err = 23; 
					if (nomb == 0) err = 40; 
					ctemp = chaine(nomb+1,lchain-nomb-2);
					for (j=0; j<ctemp.Length(); j++) {
					    t=ctemp[j];
					    if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
						err=20;
						chaine_error=chaine1ST;
					    }
					}
					if (!err) {
					    sscanf(ctemp.Data(),"%d",&inter);
					    if (inter < 0) err = 20;
					}
				    }
				    else {
					nomb = lchain;
					inter = 0;
				    }
				    if (!err) {
					inter--;
					ctemp = chaine(3,nomb-3);
					if (sscanf(ctemp.Data(),"%d",&n) > 0) {
					    if (n < 0  ) err = 24; 
					    if (n >= 20) err = 25; 
					} else err = 20;
				    }
				    if (!err) {
					fExpr[fNoper] = chaine1ST;
					actionCode = kpol+(inter2-1);
					actionParam = n*100+inter+2;
					SetAction(fNoper,actionCode,actionParam);
					if (inter+n+1>=fNpar) fNpar = inter + n + 2;
					if (fNpar>=gMAXPAR) err=7; 
					if (!err) {
					    fNoper++;
					    if (fNdim < 1) fNdim = 1;
					    SetNumber(300+n);
					}
				    }
				    
				    
				} else if (chaine(0,4) == "pow(") {
				    compt = 4; nomb = 0; virgule = 0; nest=0;
				    while(compt != lchain) {
					compt++;
					if (chaine(compt-1,1) == "(") nest++;
					else if (chaine(compt-1,1) == ")") nest--;
					else if (chaine(compt-1,1) == "," && nest==0) {
					    nomb++;
					    if (nomb == 1 && virgule == 0) virgule = compt;
					}
				    }
				    if (nomb != 1) err = 22; 
				    else {
					ctemp = chaine(4,virgule-5);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					ctemp = chaine(virgule,lchain-virgule-1);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					fExpr[fNoper] = "^";
					actionCode = kpow;
					SetAction(fNoper,actionCode,actionParam);
					fNoper++;
				    }
				} else if (chaine(0,7) == "strstr(") {
				    compt = 7; nomb = 0; virgule = 0; nest=0;
				    inString = false;
				    while(compt != lchain) {
					compt++;
					if (chaine(compt-1,1) == "\"") {
					    inString = !inString;
					}  else if (!inString) {
					    if (chaine(compt-1,1) == "(") nest++;
					    else if (chaine(compt-1,1) == ")") nest--;
					    else if (chaine(compt-1,1) == "," && nest==0) {
						nomb++;
						if (nomb == 1 && virgule == 0) virgule = compt;
					    }
					}
				    }
				    if (nomb != 1) err = 28; 
				    else {
					ctemp = chaine(7,virgule-8);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					ctemp = chaine(virgule,lchain-virgule-1);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					fExpr[fNoper] = "strstr";
					actionCode = kstrstr;
					SetAction(fNoper,actionCode,actionParam);
					fNoper++;
				    }
				} else if (chaine(0,4) == "min(") {
				    compt = 4; nomb = 0; virgule = 0; nest=0;
				    while(compt != lchain) {
					compt++;
					if (chaine(compt-1,1) == "(") nest++;
					else if (chaine(compt-1,1) == ")") nest--;
					else if (chaine(compt-1,1) == "," && nest==0) {
					    nomb++;
					    if (nomb == 1 && virgule == 0) virgule = compt;
					}
				    }
				    if (nomb != 1) {
					err = 44; 
					err_hint = 3;
				    }
				    else {
					ctemp = chaine(4,virgule-5);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					ctemp = chaine(virgule,lchain-virgule-1);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					fExpr[fNoper] = "min";
					actionCode = kmin;
					SetAction(fNoper,actionCode,actionParam);
					fNoper++;
				    }
				} else if (chaine(0,4) == "max(") {
				    compt = 4; nomb = 0; virgule = 0; nest=0;
				    while(compt != lchain) {
					compt++;
					if (chaine(compt-1,1) == "(") nest++;
					else if (chaine(compt-1,1) == ")") nest--;
					else if (chaine(compt-1,1) == "," && nest==0) {
					    nomb++;
					    if (nomb == 1 && virgule == 0) virgule = compt;
					}
				    }
				    if (nomb != 1) {
					err = 44; 
					err_hint = 3;
				    }
				    else {
					ctemp = chaine(4,virgule-5);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					ctemp = chaine(virgule,lchain-virgule-1);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					fExpr[fNoper] = "max";
					actionCode = kmax;
					SetAction(fNoper,actionCode,actionParam);
					fNoper++;
				    }
				} else if (chaine(0,6) == "atan2(") {
				    compt = 6; nomb = 0; virgule = 0; nest=0;
				    while(compt != lchain) {
					compt++;
					if (chaine(compt-1,1) == "(") nest++;
					else if (chaine(compt-1,1) == ")") nest--;
					else if (chaine(compt-1,1) == "," && nest==0) {
					    nomb++;
					    if (nomb == 1 && virgule == 0) virgule = compt;
					}
				    }
				    if (nomb != 1) err = 21;  
				    else {
					ctemp = chaine(6,virgule-7);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					ctemp = chaine(virgule,lchain-virgule-1);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					fExpr[fNoper] = "atan2";
					actionCode = katan2;
					SetAction(fNoper,actionCode,actionParam);
					fNoper++;
				    }
				} else if (chaine(0,5) == "fmod(") {
				    compt = 5; nomb = 0; virgule = 0; nest=0;
				    while(compt != lchain) {
					compt++;
					if (chaine(compt-1,1) == "(") nest++;
					else if (chaine(compt-1,1) == ")") nest--;
					else if (chaine(compt-1,1) == "," && nest==0) {
					    nomb++;
					    if (nomb == 1 && virgule == 0) virgule = compt;
					}
				    }
				    if (nomb != 1) {
					err = 44; 
					err_hint = 4;
				    }
				    else {
					ctemp = chaine(5,virgule-6);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					ctemp = chaine(virgule,lchain-virgule-1);
					Analyze(ctemp.Data(),err,offset); if (err) return;
					fExpr[fNoper] = "fmod";
					actionCode = kfmod;
					SetAction(fNoper,actionCode,actionParam);
					fNoper++;
				    }
				} else if (AnalyzeFunction(chaine,err,offset) || err) { 
				    if (err) {
					chaine_error = chaine;
				    } else {
					
					
					
				    }
				} else if (chaine(0,1) == "[" && chaine(lchain-1,1) == "]") {
				    fExpr[fNoper] = chaine;
				    fNoper++;
				    ctemp = chaine(1,lchain-2);
				    for (j=0; j<ctemp.Length(); j++) {
					t=ctemp[j];
					if (strchr("0123456789",t)==0 && (ctemp(j,1)!="+" || j!=0)) {
					    err=20;
					    chaine_error=chaine1ST; 
					}
				    }
				    if (!err) {
					sscanf(ctemp.Data(),"%d",&valeur);
					actionCode = kParameter;
					actionParam = offset + valeur;
					SetAction(fNoper-1, actionCode, actionParam);
					fExpr[fNoper-1] = "[";
					fExpr[fNoper-1] = (fExpr[fNoper-1] + (long int)(valeur+offset)) + "]";
				    }
				} else if (chaine == "pi") {
				    fExpr[fNoper] = "pi";
				    actionCode = kpi;
				    SetAction(fNoper,actionCode,actionParam);
				    fNoper++;
				}
				else {
				    
				    
				    err = 30;
				}
			    }
			}
		    }
		}
	    }
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	if (fNoper>=gMAXOP) err=6; 
    }
    
    if (err>1) {
	TString er = "";
	error_string =  chaine_error;
	chaine_error = "\""+chaine_error+"\"";
	switch(err) {
	case  2 : er = " Invalid Floating Point Operation"; break;
	case  4 : er = " Empty String"; break;
	case  5 : er = " Invalid Syntax " + chaine_error; break;
	case  6 : er = " Too many operators !"; break;
	case  7 : er = " Too many parameters !"; break;
	case 10 : er = " z specified but not x and y"; break;
	case 11 : er = " z and y specified but not x"; break;
	case 12 : er = " y specified but not x"; break;
	case 13 : er = " z and x specified but not y"; break;
	case 20 : er = " Non integer value for parameter number : " + chaine_error; break;
	case 21 : er = " ATAN2 requires two arguments"; break;
	case 22 : er = " POW requires two arguments"; break;
	case 23 : er = " Degree of polynomial not specified"; break;
	case 24 : er = " Degree of polynomial must be positive"; break;
	case 25 : er = " Degree of polynomial must be less than 20"; break;
	case 26 : er = " Unknown name : " + chaine_error; break;
	case 27 : er = " Too many constants in expression"; break;
	case 28 : er = " strstr requires two arguments"; break;
	case 29 : er = " TFormula can only call interpreted and compiled functions that return a numerical type: " + chaine_error; break;
	    
	case 31 : er = " Part of the Variable " + chaine_error; er += " exists but some of it is not accessible or useable"; break;
	case 40 : er = " '(' is expected"; break;
	case 41 : er = " ')' is expected"; break;
	case 42 : er = " '[' is expected"; break;
	case 43 : er = " ']' is expected"; break;
	case 44 : er = " The function '" + chaine(0,err_hint) + "' requires two arguments."; break;
	}
	if (err != 30)
	    Error("Compile",er.Data());
	
    }
    error_code = err;
}
#else
PFormula::PFormula(const char *name,const char *expression) {
    Error("Compile","ROOT version too old");
}
void PFormula::Analyze(const char *schain, Int_t &err, Int_t offset){
    error_code = 666;
    Error("Compile","ROOT version too old");
    error_string = "ROOT version too old";
}
#endif
ClassImp(PFormula)