#include "TROOT.h"
#include "TTreeFormula.h"
#include "TTree.h"
#include "TBranch.h"
#include "TBranchObject.h"
#include "TFunction.h"
#include "TClonesArray.h"
#include "TLeafC.h"
#include "TLeafObject.h"
#include "TDataMember.h"
#include "TMethodCall.h"
#include "TCutG.h"
#include "TRandom.h"
#include "TInterpreter.h"
#include "TDataType.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include "TBranchElement.h"
#include "TLeafElement.h"
#include "TArrayI.h"
#include "TAxis.h"
#include "TError.h"
#include "TVirtualCollectionProxy.h"
#include "TString.h"
#include "TTimeStamp.h"
#include "TMath.h"
#include "TVirtualRefProxy.h"
#include "TTreeFormulaManager.h"
#include "TFormLeafInfo.h"
#include "TMethod.h"
#include "TBaseClass.h"
#include "TFormLeafInfoReference.h"
#include "TEntryList.h"
#include <stdio.h>
#include <math.h>
#ifdef R__SOLARIS
#include <typeinfo>
#endif
#include <algorithm>
const Int_t kMaxLen     = 512;
R__EXTERN TTree *gTree;
ClassImp(TTreeFormula)
inline static void R__LoadBranch(TBranch* br, Long64_t entry, Bool_t quickLoad)
{
   if (!quickLoad || (br->GetReadEntry() != entry)) {
      br->GetEntry(entry);
   }
}
class TDimensionInfo : public TObject {
public:
   Int_t fCode;  
   Int_t fOper;  
   Int_t fSize;
   TFormLeafInfoMultiVarDim* fMultiDim;
   TDimensionInfo(Int_t code, Int_t oper, Int_t size, TFormLeafInfoMultiVarDim* multiDim)
      : fCode(code), fOper(oper), fSize(size), fMultiDim(multiDim) {};
   ~TDimensionInfo() {};
};
TTreeFormula::TTreeFormula(): TFormula(), fQuickLoad(kFALSE), fNeedLoading(kTRUE),
   fDidBooleanOptimization(kFALSE), fDimensionSetup(0)
{
   
   fTree       = 0;
   fLookupType = 0;
   fNindex     = 0;
   fNcodes     = 0;
   fAxis       = 0;
   fHasCast    = 0;
   fManager    = 0;
   Int_t j,k;
   for (j=0; j<kMAXCODES; j++) {
      fNdimensions[j] = 0;
      fCodes[j] = 0;
      fNdata[j] = 1;
      fHasMultipleVarDim[j] = kFALSE;
      for (k = 0; k<kMAXFORMDIM; k++) {
         fIndexes[j][k] = -1;
         fCumulSizes[j][k] = 1;
         fVarIndexes[j][k] = 0;
      }
   }
}
TTreeFormula::TTreeFormula(const char *name,const char *expression, TTree *tree)
   :TFormula(), fTree(tree), fQuickLoad(kFALSE), fNeedLoading(kTRUE),
    fDidBooleanOptimization(kFALSE), fDimensionSetup(0)
{
   
   Init(name,expression);
}
TTreeFormula::TTreeFormula(const char *name,const char *expression, TTree *tree,
                           const std::vector<std::string>& aliases)
   :TFormula(), fTree(tree), fQuickLoad(kFALSE), fNeedLoading(kTRUE),
    fDidBooleanOptimization(kFALSE), fDimensionSetup(0), fAliasesUsed(aliases)
{
   
   Init(name,expression);
}
void TTreeFormula::Init(const char*name, const char* expression)
{
   
   TDirectory *const savedir=gDirectory;
   fNindex       = kMAXFOUND;
   fLookupType   = new Int_t[fNindex];
   fNcodes       = 0;
   fMultiplicity = 0;
   fAxis         = 0;
   fHasCast      = 0;
   Int_t i,j,k;
   fManager      = new TTreeFormulaManager;
   fManager->Add(this);
   for (j=0; j<kMAXCODES; j++) {
      fNdimensions[j] = 0;
      fLookupType[j] = kDirect;
      fCodes[j] = 0;
      fNdata[j] = 1;
      fHasMultipleVarDim[j] = kFALSE;
      for (k = 0; k<kMAXFORMDIM; k++) {
         fIndexes[j][k] = -1;
         fCumulSizes[j][k] = 1;
         fVarIndexes[j][k] = 0;
      }
   }
   fDimensionSetup = new TList;
   if (Compile(expression)) {
      fTree = 0; fNdim = 0; 
      if(savedir) savedir->cd();
      return; 
   }
   if (fNcodes >= kMAXFOUND) {
      Warning("TTreeFormula","Too many items in expression:%s",expression);
      fNcodes = kMAXFOUND;
   }
   SetName(name);
   for (i=0;i<fNoper;i++) {
      if (GetAction(i)==kDefinedString) {
         Int_t string_code = GetActionParam(i);
         TLeaf *leafc = (TLeaf*)fLeaves.UncheckedAt(string_code);
         if (!leafc) continue;
         
         
         
         
         
         
         
         
         
         if (fNcodes == 1) {
            
            
            
            SetBit(kIsCharacter);
         }
         continue;
      }
   }
   if (fNoper==1 && GetAction(0)==kAliasString) {
      TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
      R__ASSERT(subform);
      if (subform->TestBit(kIsCharacter)) SetBit(kIsCharacter);
   } else if (fNoper==2 && GetAction(0)==kAlternateString) {
      TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
      R__ASSERT(subform);
      if (subform->TestBit(kIsCharacter)) SetBit(kIsCharacter);
   }
   fManager->Sync();
   
   Int_t k0,k1;
   for(k0 = 0; k0 < fNcodes; k0++) {
      for(k1 = 0; k1 < fNdimensions[k0]; k1++ ) {
         
         if ( fIndexes[k0][k1]>=0 && fFixedSizes[k0][k1]>=0
              && fIndexes[k0][k1]>=fFixedSizes[k0][k1]) {
            Error("TTreeFormula",
                  "Index %d for dimension #%d in %s is too high (max is %d)",
                  fIndexes[k0][k1],k1+1, expression,fFixedSizes[k0][k1]-1);
            fTree = 0; fNdim = 0; 
            if(savedir) savedir->cd();
            return;
         }
      }
   }
   
   for(k=0; k<fNcodes; k++) {
      TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(k);
      TBranch *branch = 0;
      if (leaf) {
         branch = leaf->GetBranch();
         if (fBranches.FindObject(branch)) branch = 0;
      }
      fBranches.AddAtAndExpand(branch,k);
   }
   
   if (IsInteger(kFALSE)) SetBit(kIsInteger);
   if(savedir) savedir->cd();
}
TTreeFormula::~TTreeFormula()
{
   if (fManager) {
      fManager->Remove(this);
      if (fManager->fFormulas.GetLast()<0) {
         delete fManager;
         fManager = 0;
      }
   }
   fLeafNames.Delete();
   fDataMembers.Delete();
   
   TList temp;
   TIter next(&fMethods);
   TObject *obj;
   while ((obj=next())) {
      if (obj->InheritsFrom("TCutG") || obj->InheritsFrom("TEntryList")) temp.Add(obj);
   }
   TIter next2(&temp);
   while ((obj=next2())) {
      fMethods.Remove(obj);
   }
   fMethods.Delete();
   fAliases.Delete();
   if (fLookupType) delete [] fLookupType;
   for (int j=0; j<fNcodes; j++) {
      for (int k = 0; k<fNdimensions[j]; k++) {
         if (fVarIndexes[j][k]) delete fVarIndexes[j][k];
         fVarIndexes[j][k] = 0;
      }
   }
   if (fDimensionSetup) {
      fDimensionSetup->Delete();
      delete fDimensionSetup;
   }
}
void TTreeFormula::DefineDimensions(Int_t code, Int_t size,
                                    TFormLeafInfoMultiVarDim * info,
                                    Int_t& virt_dim) {
   
   if (info) {
      fManager->EnableMultiVarDims();
      
         info->fVirtDim = virt_dim;
         fManager->AddVarDims(virt_dim); 
      
   }
   Int_t vsize = 0;
   if (fIndexes[code][fNdimensions[code]]==-2) {
      TTreeFormula *indexvar = fVarIndexes[code][fNdimensions[code]];
      
      Int_t index_multiplicity = indexvar->GetMultiplicity();
      switch (index_multiplicity) {
         case -1:
         case  0:
         case  2:
            vsize = indexvar->GetNdata();
            break;
         case  1:
            vsize = -1;
            break;
      };
   } else vsize = size;
   fCumulSizes[code][fNdimensions[code]] = size;
   if ( fIndexes[code][fNdimensions[code]] < 0 ) {
      fManager->UpdateUsedSize(virt_dim, vsize);
   }
   fNdimensions[code] ++;
}
Int_t TTreeFormula::RegisterDimensions(const char *info, Int_t code)
{
   
   
   const char * current;
   Int_t size, scanindex, vardim;
   current = info;
   vardim = 0;
   
   
   
   
   if (current[0] != '[') current--;
   while (current) {
      current++;
      scanindex = sscanf(current,"%d",&size);
      
      
      if (scanindex==0) size = -1;
      vardim += RegisterDimensions(code, size);
      if (fNdimensions[code] >= kMAXFORMDIM) {
         
         break;
      }
      current = (char*)strstr( current, "[" );
   }
   return vardim;
}
Int_t TTreeFormula::RegisterDimensions(Int_t code, Int_t size, TFormLeafInfoMultiVarDim * multidim) {
   
   TDimensionInfo * info = new TDimensionInfo(code,fNoper,size,multidim);
   fDimensionSetup->Add(info);
   fCumulSizes[code][fNdimensions[code]] = size;
   fNdimensions[code] ++;
   return (size==-1) ? 1 : 0;
}
Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo,
                                       TFormLeafInfo *maininfo,
                                       Bool_t useCollectionObject) {
   
   Int_t ndim, size, current, vardim;
   vardim = 0;
   const TStreamerElement * elem = leafinfo->fElement;
   TClass* c = elem ? elem->GetClassPointer() : 0;
   TFormLeafInfoMultiVarDim * multi = dynamic_cast<TFormLeafInfoMultiVarDim * >(leafinfo);
   if (multi) {
      
      fManager->EnableMultiVarDims();
      multi->fDim = fNdimensions[code];
      return RegisterDimensions(code, -1, multi);
   }
   if (elem->IsA() == TStreamerBasicPointer::Class()) {
      if (elem->GetArrayDim()>0) {
         ndim = elem->GetArrayDim();
         size = elem->GetMaxIndex(0);
         vardim += RegisterDimensions(code, -1);
      } else {
         ndim = 1;
         size = -1;
      }
      TStreamerBasicPointer *array = (TStreamerBasicPointer*)elem;
      TClass *cl = leafinfo->fClass;
      Int_t offset;
      TStreamerElement* counter = ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(array->GetCountName(),offset);
      if (maininfo==0 || maininfo==leafinfo || 1) {
         leafinfo->fCounter = new TFormLeafInfo(cl,offset,counter);
      } else {
         leafinfo->fCounter = maininfo->DeepCopy();
         TFormLeafInfo *current = leafinfo->fCounter;
         while(current->fNext && current->fNext->fNext) current=current->fNext;
         delete current->fNext;
         current->fNext = new TFormLeafInfo(cl,offset,counter);
      }
   } else if (!useCollectionObject && elem->GetClassPointer() == TClonesArray::Class() ) {
      ndim = 1;
      size = -1;
      TClass * clonesClass = TClonesArray::Class();
      Int_t c_offset;
      TStreamerElement *counter = ((TStreamerInfo*)clonesClass->GetStreamerInfo())->GetStreamerElement("fLast",c_offset);
      leafinfo->fCounter = new TFormLeafInfo(clonesClass,c_offset,counter);
   } else if (!useCollectionObject && elem->GetClassPointer() && elem->GetClassPointer()->GetCollectionProxy() ) {
      if ( typeid(*leafinfo) == typeid(TFormLeafInfoCollection) ) {
         ndim = 1;
         size = -1;
      } else {
         R__ASSERT( fHasMultipleVarDim[code] );
         ndim = 1;
         size = 1;
      }
   } else if ( c && c->GetReferenceProxy() && c->GetReferenceProxy()->HasCounter() ) {
      ndim = 1;
      size = -1;
   } else if (elem->GetArrayDim()>0) {
      ndim = elem->GetArrayDim();
      size = elem->GetMaxIndex(0);
   } else if ( elem->GetNewType()== TStreamerInfo::kCharStar) {
      
      
      
      
      
      ndim = 1;
      size = 1; 
   } else return 0;
   current = 0;
   do {
      vardim += RegisterDimensions(code, size);
      if (fNdimensions[code] >= kMAXFORMDIM) {
         
         break;
      }
      current++;
      size = elem->GetMaxIndex(current);
   } while (current<ndim);
   return vardim;
}
Int_t TTreeFormula::RegisterDimensions(Int_t code, TBranchElement *branch) {
   
   TBranchElement * leafcount2 = branch->GetBranchCount2();
   if (leafcount2) {
      
      TBranchElement *leafcount = dynamic_cast<TBranchElement*>(branch->GetBranchCount());
      R__ASSERT(leafcount); 
      fManager->EnableMultiVarDims();
      TFormLeafInfoMultiVarDim * info = new TFormLeafInfoMultiVarDimDirect();
      fDataMembers.AddAtAndExpand(info, code);
      fHasMultipleVarDim[code] = kTRUE;
      info->fCounter = new TFormLeafInfoDirect(leafcount);
      info->fCounter2 = new TFormLeafInfoDirect(leafcount2);
      info->fDim = fNdimensions[code];
      
      
      
      
      return RegisterDimensions(code, -1, info);
   }
   return 0;
}
Int_t TTreeFormula::RegisterDimensions(Int_t code, TLeaf *leaf) {
   
   Int_t numberOfVarDim = 0;
   
   
   
   const char *tname = leaf->GetTitle();
   char *leaf_dim = (char*)strstr( tname, "[" );
   const char *bname = leaf->GetBranch()->GetName();
   char *branch_dim = (char*)strstr(bname,"[");
   if (branch_dim) branch_dim++; 
   if (leaf_dim) {
      leaf_dim++; 
      if (!branch_dim || strncmp(branch_dim,leaf_dim,strlen(branch_dim))) {
         
         numberOfVarDim += RegisterDimensions( leaf_dim, code);
      } else if (branch_dim && strncmp(branch_dim,leaf_dim,strlen(branch_dim))==0
                 && strlen(leaf_dim)>strlen(branch_dim)
                 && (leaf_dim+strlen(branch_dim))[0]=='[') {
         
         numberOfVarDim += RegisterDimensions( leaf_dim+strlen(branch_dim)+1, code);
      }
   }
   if (branch_dim) {
      
      numberOfVarDim += RegisterDimensions( branch_dim, code);
   }
   if (leaf->IsA() == TLeafElement::Class()) {
      TBranchElement* branch = (TBranchElement*) leaf->GetBranch();
      if (branch->GetBranchCount2()) {
         if (!branch->GetBranchCount()) {
            Warning("DefinedVariable",
                    "Noticed an incorrect in-memory TBranchElement object (%s).\nIt has a BranchCount2 but no BranchCount!\nThe result might be incorrect!",
                    branch->GetName());
            return numberOfVarDim;
         }
         
         if (fLookupType[code] == kDataMember)
            Warning("DefinedVariable",
                    "Already in kDataMember mode when handling multiple variable dimensions");
         fLookupType[code] = kDataMember;
         
         numberOfVarDim += RegisterDimensions( code, branch);
      }
   }
   return numberOfVarDim;
}
Int_t TTreeFormula::DefineAlternate(const char *expression)
{
   
   
   
   
   
   
   static const char *altfunc = "Alt$(";
   if (   strncmp(expression,altfunc,strlen(altfunc))==0
       && expression[strlen(expression)-1]==')' ) {
      TString full = expression;
      TString part1;
      TString part2;
      int paran = 0;
      int instr = 0;
      int brack = 0;
      for(unsigned int i=strlen(altfunc);i<strlen(expression);++i) {
         switch (expression[i]) {
            case '(': paran++; break;
            case ')': paran--; break;
            case '"': instr = instr ? 0 : 1; break;
            case '[': brack++; break;
            case ']': brack--; break;
         };
         if (expression[i]==',' && paran==0 && instr==0 && brack==0) {
            part1 = full( strlen(altfunc), i-strlen(altfunc) );
            part2 = full( i+1, full.Length() -1 - (i+1) );
            break; 
         }
      }
      if (part1.Length() && part2.Length()) {
         TTreeFormula *primary = new TTreeFormula("primary",part1,fTree);
         TTreeFormula *alternate = new TTreeFormula("alternate",part2,fTree);
         if (alternate->GetManager()->GetMultiplicity() != 0 ) {
            Error("DefinedVariable","The 2nd arguments in %s can not be an array (%s,%d)!",
                  expression,alternate->GetTitle(),
                  alternate->GetManager()->GetMultiplicity());
            return -1;
         }
         
         short isstring = 0;
         if (primary->IsString()) {
            if (!alternate->IsString()) {
               Error("DefinedVariable",
                     "The 2nd arguments in %s has to return the same type as the 1st argument (string)!",
                     expression);
               return -1;
            }
            isstring = 1;
         } else if (alternate->IsString()) {
            Error("DefinedVariable",
                  "The 2nd arguments in %s has to return the same type as the 1st argument (numerical type)!",
                  expression);
            return -1;
         }
         fAliases.AddAtAndExpand(primary,fNoper);
         fExpr[fNoper] = "";
         SetAction(fNoper, (Int_t)kAlternate + isstring, 0 );
         ++fNoper;
         fAliases.AddAtAndExpand(alternate,fNoper);
         return (Int_t)kAlias + isstring;
      }
   }
   return 0;
}
Int_t TTreeFormula::ParseWithLeaf(TLeaf* leaf, const char* subExpression, Bool_t final, UInt_t paran_level, TObjArray& castqueue, Bool_t useLeafCollectionObject, const char* fullExpression)
{
   
   
   
   
   
   
   Int_t action = 0;
   Int_t numberOfVarDim = 0;
   char *current;
   char  scratch[kMaxLen]; scratch[0] = '\0';
   char     work[kMaxLen];    work[0] = '\0';
   const char *right = subExpression;
   TString name = fullExpression;
   TBranch *branch = leaf ? leaf->GetBranch() : 0;
   Long64_t readentry = fTree->GetTree()->GetReadEntry();
   if (readentry==-1) readentry=0;
   Bool_t useLeafReferenceObject = false;
   Int_t code = fNcodes-1;
   
   if (leaf && leaf->IsA()==TLeafElement::Class()) {
      TBranchElement *br = ((TBranchElement*)branch);
      if ( br->GetInfo() == 0 ) {
         Error("DefinedVariable","Missing StreamerInfo for %s.  We will be unable to read!",
               name.Data());
         return -2;
      }
      TBranchElement *mom = (TBranchElement*)br->GetMother();
      if (mom!=br) {
         if (mom->GetInfo()==0) {
            Error("DefinedVariable","Missing StreamerInfo for %s."
                  "  We will be unable to read!",
                  mom->GetName());
            return -2;
         }
         if ((mom->GetType()) < 0 && !mom->GetAddress()) {
            Error("DefinedVariable", "Address not set when the type of the branch is negative for for %s.  We will be unable to read!", mom->GetName());
            return -2;
         }
      }
   }
   
   
   
   
   TTree *realtree = fTree->GetTree();
   const char* alias = 0;
   if (leaf) {
      if (realtree) alias = realtree->GetFriendAlias(leaf->GetBranch()->GetTree());
      if (!alias && realtree!=fTree) {
         
         alias = fTree->GetFriendAlias(leaf->GetBranch()->GetTree());
      }
   }
   if (alias) sprintf(scratch,"%s.%s",alias,leaf->GetName());
   else if (leaf) strcpy(scratch,leaf->GetName());
   TTree *tleaf = realtree;
   if (leaf) {
      TTree *tleaf = leaf->GetBranch()->GetTree();
      fCodes[code] = tleaf->GetListOfLeaves()->IndexOf(leaf);
      TNamed *named = new TNamed(scratch,leaf->GetBranch()->GetName());
      fLeafNames.AddAtAndExpand(named,code);
      fLeaves.AddAtAndExpand(leaf,code);
   }
   
   
   if (tleaf != realtree && tleaf->GetTreeIndex()) {
      
      if (fMultiplicity == 0) fMultiplicity = 1;
   }
   
   
   TClass * cl = 0;
   TFormLeafInfo *maininfo = 0;
   TFormLeafInfo *previnfo = 0;
   Bool_t unwindCollection = kFALSE;
   if (leaf==0) {
      TNamed *names = (TNamed*)fLeafNames.UncheckedAt(code);
      fLeafNames.AddAt(0,code);
      TTree *what = (TTree*)fLeaves.UncheckedAt(code);
      fLeaves.AddAt(0,code);
      cl = what ? what->IsA() : TTree::Class();
      maininfo = new TFormLeafInfoTTree(fTree,names->GetName(),what);
      previnfo = maininfo;
      delete names;
   } else if (leaf->InheritsFrom("TLeafObject") ) {
      TBranchObject *bobj = (TBranchObject*)leaf->GetBranch();
      cl = TClass::GetClass(bobj->GetClassName());
   } else if (leaf->InheritsFrom("TLeafElement")) {
      TBranchElement *branchEl = (TBranchElement *)leaf->GetBranch();
      branchEl->SetupAddresses();
      TStreamerInfo *info = branchEl->GetInfo();
      TStreamerElement *element = 0;
      Int_t type = branchEl->GetStreamerType();
      switch(type) {
         case TStreamerInfo::kBase:
         case TStreamerInfo::kObject:
         case TStreamerInfo::kTString:
         case TStreamerInfo::kTNamed:
         case TStreamerInfo::kTObject:
         case TStreamerInfo::kAny:
         case TStreamerInfo::kAnyP:
         case TStreamerInfo::kAnyp:
         case TStreamerInfo::kSTL:
         case TStreamerInfo::kSTLp:
         case TStreamerInfo::kObjectp:
         case TStreamerInfo::kObjectP: {
            element = (TStreamerElement *)info->GetElems()[branchEl->GetID()];
            if (element) cl = element->GetClassPointer();
         }
         break;
         case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kAny:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP:
         case TStreamerInfo::kOffsetL + TStreamerInfo::kObject:  {
            element = (TStreamerElement *)info->GetElems()[branchEl->GetID()];
            if (element){
               cl = element->GetClassPointer();
            }
         }
         break;
         case -1: {
            cl = info->GetClass();
         }
         break;
      }
      
      
      if (cl && branchEl->GetBranchCount()) {
         if (branchEl->GetType()==31) {
            
            if (!element) {
               Warning("DefineVariable",
                       "Missing TStreamerElement in object in TClonesArray section");
               return -2;
            }
            TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE);
            
            
            
            
            
            maininfo = clonesinfo;
            
            Int_t offset;
            info->GetStreamerElement(element->GetName(),offset);
            if (type == TStreamerInfo::kObjectp ||
                  type == TStreamerInfo::kObjectP ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP ||
                  type == TStreamerInfo::kSTLp ||
                  type == TStreamerInfo::kAnyp ||
                  type == TStreamerInfo::kAnyP ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) {
               previnfo = new TFormLeafInfoPointer(cl,offset+branchEl->GetOffset(),element);
            } else {
               previnfo = new TFormLeafInfo(cl,offset+branchEl->GetOffset(),element);
            }
            maininfo->fNext = previnfo;
            unwindCollection = kTRUE;
         } else if (branchEl->GetType()==41) {
            
            if (!element) {
               Warning("DefineVariable","Missing TStreamerElement in object in Collection section");
               return -2;
            }
            
            TBranchElement *count = branchEl->GetBranchCount();
            TFormLeafInfo* collectioninfo;
            if ( count->GetID() >= 0 ) {
               TStreamerElement *collectionElement =
                  (TStreamerElement *)count->GetInfo()->GetElems()[count->GetID()];
               TClass *collectionCl = collectionElement->GetClassPointer();
               collectioninfo =
                  new TFormLeafInfoCollection(collectionCl, 0, collectionElement, kTRUE);
            } else {
               TClass *collectionCl = TClass::GetClass(count->GetClassName());
               collectioninfo =
                  new TFormLeafInfoCollection(collectionCl, 0, collectionCl, kTRUE);
            }
            
            
            
            
            
            maininfo = collectioninfo;
            
            Int_t offset;
            info->GetStreamerElement(element->GetName(),offset);
            if (type == TStreamerInfo::kObjectp ||
                  type == TStreamerInfo::kObjectP ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP ||
                  type == TStreamerInfo::kSTLp ||
                  type == TStreamerInfo::kAnyp ||
                  type == TStreamerInfo::kAnyP ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp ||
                  type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) {
               previnfo = new TFormLeafInfoPointer(cl,offset+branchEl->GetOffset(),element);
            } else {
               previnfo = new TFormLeafInfo(cl,offset+branchEl->GetOffset(),element);
            }
            maininfo->fNext = previnfo;
            unwindCollection = kTRUE;
         }
      } else if ( branchEl->GetType()==3) {
         TFormLeafInfo* clonesinfo;
         if (useLeafCollectionObject) {
            clonesinfo = new TFormLeafInfoCollectionObject(cl);
         } else {
            clonesinfo = new TFormLeafInfoClones(cl, 0, kTRUE);
            
            numberOfVarDim += RegisterDimensions(code,clonesinfo,maininfo,useLeafCollectionObject);
         }
         maininfo = clonesinfo;
         previnfo = maininfo;
      } else if (!useLeafCollectionObject && branchEl->GetType()==4) {
         TFormLeafInfo* collectioninfo;
         if (useLeafCollectionObject) {
            collectioninfo = new TFormLeafInfoCollectionObject(cl);
         } else {
            collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
            
            numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,useLeafCollectionObject);
         }
         maininfo = collectioninfo;
         previnfo = maininfo;
      } else if (branchEl->GetStreamerType()==-1 && cl && cl->GetCollectionProxy()) {
         if (useLeafCollectionObject) {
            TFormLeafInfo *collectioninfo = new TFormLeafInfoCollectionObject(cl);
            maininfo = collectioninfo;
            previnfo = collectioninfo;
         } else {
            TFormLeafInfo *collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
            
            numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
            maininfo = collectioninfo;
            previnfo = collectioninfo;
            if (cl->GetCollectionProxy()->GetValueClass()!=0 &&
                cl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=0) {
               TFormLeafInfo *multi = new TFormLeafInfoMultiVarDimCollection(cl,0,
                     cl->GetCollectionProxy()->GetValueClass(),collectioninfo);
               fHasMultipleVarDim[code] = kTRUE;
               numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
               previnfo->fNext = multi;
               cl = cl->GetCollectionProxy()->GetValueClass();
               multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
               previnfo = multi->fNext;
            }
            if (cl->GetCollectionProxy()->GetValueClass()==0 &&
                cl->GetCollectionProxy()->GetType()>0) {
               previnfo->fNext =
                        new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType());
               previnfo = previnfo->fNext;
            } else {
               
            }
         }
      } else if (strlen(right)==0 && cl && element && final) {
         TClass *elemCl = element->GetClassPointer();
         if (!useLeafCollectionObject
             && elemCl && elemCl->GetCollectionProxy()
             && elemCl->GetCollectionProxy()->GetValueClass()
             && elemCl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()) {
            TFormLeafInfo *collectioninfo =
               new TFormLeafInfoCollection(cl, 0, elemCl);
            
            numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
            maininfo = collectioninfo;
            previnfo = collectioninfo;
            TFormLeafInfo *multi =
               new TFormLeafInfoMultiVarDimCollection(elemCl, 0,
                                                      elemCl->GetCollectionProxy()->GetValueClass(),
                                                      collectioninfo);
            fHasMultipleVarDim[code] = kTRUE;
            numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
            previnfo->fNext = multi;
            cl = elemCl->GetCollectionProxy()->GetValueClass();
            multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
            previnfo = multi->fNext;
            if (cl->GetCollectionProxy()->GetValueClass()==0 &&
                cl->GetCollectionProxy()->GetType()>0) {
               previnfo->fNext =
                  new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType());
               previnfo = previnfo->fNext;
            }
         } else if (!useLeafCollectionObject
               && elemCl && elemCl->GetCollectionProxy()
               && elemCl->GetCollectionProxy()->GetValueClass()==0
               && elemCl->GetCollectionProxy()->GetType()>0) {
            
            
            
            
            TFormLeafInfo* collectioninfo =
               new TFormLeafInfoCollection(cl, 0, elemCl);
            
            numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
            collectioninfo->fNext =
               new TFormLeafInfoNumerical(elemCl->GetCollectionProxy()->GetType());
            maininfo = collectioninfo;
            previnfo = maininfo->fNext;
         } else if (!element->IsaPointer()) {
            maininfo = new TFormLeafInfoDirect(branchEl);
            previnfo = maininfo;
         }
      }
      else if ( cl && cl->GetReferenceProxy() )  {
         if ( useLeafCollectionObject || fullExpression[0] == '@' || fullExpression[strlen(scratch)] == '@' ) {
            useLeafReferenceObject = true;
         }
         else  {
            if ( !maininfo )  {
               maininfo = previnfo = new TFormLeafInfoReference(cl, element, 0);
               numberOfVarDim += RegisterDimensions(code,maininfo,maininfo,kFALSE);
            }
            cl = 0;
            for(int i=0; i<leaf->GetBranch()->GetEntries()-readentry; ++i)  {
               R__LoadBranch(leaf->GetBranch(), readentry+i, fQuickLoad);
               cl = ((TFormLeafInfoReference*)maininfo)->GetValueClass(leaf);
               if ( cl ) break;
            }
            if ( !cl )  {
               Error("DefinedVariable","Failed to access class type of reference target (%s)",element->GetName());
               return -1;
            }
         }
      }
   }
   
   if (leaf) numberOfVarDim += RegisterDimensions(code,leaf);
   if (cl) {
      if (unwindCollection) {
         
         
         R__ASSERT(numberOfVarDim==1 && maininfo);
         if (!useLeafCollectionObject && cl && cl->GetCollectionProxy()) {
            TFormLeafInfo *multi =
               new TFormLeafInfoMultiVarDimCollection(cl, 0, cl, maininfo);
            fHasMultipleVarDim[code] = kTRUE;
            numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
            previnfo->fNext = multi;
            multi->fNext =  new TFormLeafInfoCollection(cl, 0, cl, false);
            previnfo = multi->fNext;
            if (cl->GetCollectionProxy()->GetValueClass()==0 &&
                cl->GetCollectionProxy()->GetType()>0) {
               previnfo->fNext =
                  new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType());
               previnfo = previnfo->fNext;
            }
         } else if (!useLeafCollectionObject && cl == TClonesArray::Class()) {
            TFormLeafInfo *multi =
               new TFormLeafInfoMultiVarDimClones(cl, 0, cl, maininfo);
            fHasMultipleVarDim[code] = kTRUE;
            numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
            previnfo->fNext = multi;
            multi->fNext =  new TFormLeafInfoClones(cl, 0, false);
            previnfo = multi->fNext;
         }
      }
      Int_t offset;
      Int_t nchname = strlen(right);
      TFormLeafInfo *leafinfo = 0;
      TStreamerElement* element = 0;
      
      
      
      
      
      
      
      TClass * casted = (TClass*) castqueue.At(paran_level+1);
      if (casted && cl != TClonesArray::Class()) {
         if ( ! casted->InheritsFrom(cl) ) {
            Error("DefinedVariable","%s does not inherit from %s.  Casting not possible!",
                  casted->GetName(),cl->GetName());
            return -2;
         }
         leafinfo = new TFormLeafInfoCast(cl,casted);
         fHasCast = kTRUE;
         if (maininfo==0) {
            maininfo = leafinfo;
         }
         if (previnfo==0) {
            previnfo = leafinfo;
         } else {
            previnfo->fNext = leafinfo;
            previnfo = leafinfo;
         }
         leafinfo = 0;
         cl = casted;
         castqueue.AddAt(0,paran_level);
      }
      Int_t i;
      Bool_t prevUseCollectionObject = useLeafCollectionObject;
      Bool_t useCollectionObject = useLeafCollectionObject;
      Bool_t useReferenceObject = useLeafReferenceObject;
      Bool_t prevUseReferenceObject = useLeafReferenceObject;
      for (i=0, current = &(work[0]); i<=nchname;i++ ) {
         
         if (right[i] == '(') {
            
            do {
               *current++ = right[i++];
            } while(right[i]!=')' && right[i]);
            *current++ = right[i];
            *current='\0';
            char *params = strchr(work,'(');
            if (params) {
               *params = 0; params++;
            } else params = (char *) ")";
            if (cl==0) {
               Error("DefinedVariable","Can not call '%s' with a class",work);
               return -1;
            }
            if (cl->GetClassInfo()==0 && !cl->GetCollectionProxy()) {
               Error("DefinedVariable","Class probably unavailable:%s",cl->GetName());
               return -2;
            }
            if (!useCollectionObject && cl == TClonesArray::Class()) {
               
               
               
               TBranch *branch = leaf->GetBranch();
               R__LoadBranch(branch,readentry,fQuickLoad);
               TClonesArray * clones;
               if (previnfo) clones = (TClonesArray*)previnfo->GetLocalValuePointer(leaf,0);
               else {
                  Bool_t top = (branch==((TBranchElement*)branch)->GetMother()
                                 || !leaf->IsOnTerminalBranch());
                  TClass *mother_cl;
                  if (leaf->IsA()==TLeafObject::Class()) {
                     
                     mother_cl = cl;
                  } else {
                     mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
                  }
                  TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0, top);
                  
                  numberOfVarDim += RegisterDimensions(code,clonesinfo,maininfo,kFALSE);
                  previnfo = clonesinfo;
                  maininfo = clonesinfo;
                  clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0);
               }
               TClass * inside_cl = clones->GetClass();
               if (1 || inside_cl) cl = inside_cl;
            }
            else if (!useCollectionObject && cl && cl->GetCollectionProxy() ) {
               
               
               
               if (previnfo==0) {
                  Bool_t top = (branch==((TBranchElement*)branch)->GetMother()
                                 || !leaf->IsOnTerminalBranch());
                  TClass *mother_cl;
                  if (leaf->IsA()==TLeafObject::Class()) {
                     
                     mother_cl = cl;
                  } else {
                     mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
                  }
                  TFormLeafInfo* collectioninfo =
                     new TFormLeafInfoCollection(mother_cl, 0,cl,top);
                  
                  numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
                  previnfo = collectioninfo;
                  maininfo = collectioninfo;
               }
               TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass();
               if (inside_cl) cl = inside_cl;
               else if (cl->GetCollectionProxy()->GetType()>0) {
                  Warning("DefinedVariable","Can not call method on content of %s in %s\n",
                           cl->GetName(),name.Data());
                  return -2;
               }
            }
            TMethodCall *method  = 0;
            if (cl==0) {
               Error("DefinedVariable",
                     "Could not discover the TClass corresponding to (%s)!",
                     right);
               return -2;
            } else if (cl==TClonesArray::Class() && strcmp(work,"size")==0) {
               method = new TMethodCall(cl, "GetEntriesFast", "");
            } else if (cl->GetCollectionProxy() && strcmp(work,"size")==0) {
               if (maininfo==0) {
                  TFormLeafInfo* collectioninfo=0;
                  if (useLeafCollectionObject) {
                     Bool_t top = (branch==((TBranchElement*)branch)->GetMother()
                                 || !leaf->IsOnTerminalBranch());
                     collectioninfo = new TFormLeafInfoCollectionObject(cl,top);
                  }
                  maininfo=previnfo=collectioninfo;
               }
               leafinfo = new TFormLeafInfoCollectionSize(cl);
               cl = 0;
            } else {
               if (cl->GetClassInfo()==0) {
                  Error("DefinedVariable",
                        "Can not call method %s on class without dictionary (%s)!",
                        right,cl->GetName());
                  return -2;
               }
               method = new TMethodCall(cl, work, params);
            }
            if (method) {
               if (!method->GetMethod()) {
                  Error("DefinedVariable","Unknown method:%s in %s",right,cl->GetName());
                  return -1;
               }
               switch(method->ReturnType()) {
                  case TMethodCall::kLong:
                     leafinfo = new TFormLeafInfoMethod(cl,method);
                     cl = 0;
                     break;
                  case TMethodCall::kDouble:
                     leafinfo = new TFormLeafInfoMethod(cl,method);
                     cl = 0;
                     break;
                  case TMethodCall::kString:
                     leafinfo = new TFormLeafInfoMethod(cl,method);
                     
                     numberOfVarDim += RegisterDimensions(code,1); 
                     cl = 0;
                     break;
                  case TMethodCall::kOther:
                     {
                        TString return_type =
                          gInterpreter->TypeName(method->GetMethod()->GetReturnTypeName());
                        leafinfo = new TFormLeafInfoMethod(cl,method);
                        cl = (return_type == "void") ? 0 : TClass::GetClass(return_type.Data());
                     }
                     break;
                  default:
                     Error("DefineVariable","Method %s from %s has an impossible return type %d",
                        work,cl->GetName(),method->ReturnType());
                     return -2;
               }
            }
            if (maininfo==0) {
               maininfo = leafinfo;
            }
            if (previnfo==0) {
               previnfo = leafinfo;
            } else {
               previnfo->fNext = leafinfo;
               previnfo = leafinfo;
            }
            leafinfo = 0;
            current = &(work[0]);
            *current = 0;
            prevUseCollectionObject = kFALSE;
            prevUseReferenceObject = kFALSE;
            useCollectionObject = kFALSE;
            if (cl && cl->GetCollectionProxy()) {
               if (numberOfVarDim>1) {
                  Warning("DefinedVariable","TTreeFormula support only 2 level of variables size collections.  Assuming '@' notation for the collection %s.",
                     cl->GetName());
                  leafinfo = new TFormLeafInfo(cl,0,0);
                  useCollectionObject = kTRUE;
               } else if (numberOfVarDim==0) {
                  R__ASSERT(maininfo);
                  leafinfo = new TFormLeafInfoCollection(cl,0,cl);
                  numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
               } else if (numberOfVarDim==1) {
                  R__ASSERT(maininfo);
                  leafinfo =
                     new TFormLeafInfoMultiVarDimCollection(cl,0,
                     (TStreamerElement*)0,maininfo);
                  previnfo->fNext = leafinfo;
                  previnfo = leafinfo;
                  leafinfo = new TFormLeafInfoCollection(cl,0,cl);
                  fHasMultipleVarDim[code] = kTRUE;
                  numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
               }
               previnfo->fNext = leafinfo;
               previnfo = leafinfo;
               leafinfo = 0;
            }
            continue;
         } else if (right[i] == ')') {
            
            
            TClass * casted = (TClass*) ((int(--paran_level)>=0) ? castqueue.At(paran_level) : 0);
            if (casted) {
               leafinfo = new TFormLeafInfoCast(cl,casted);
               fHasCast = kTRUE;
               if (maininfo==0) {
                  maininfo = leafinfo;
               }
               if (previnfo==0) {
                  previnfo = leafinfo;
               } else {
                  previnfo->fNext = leafinfo;
                  previnfo = leafinfo;
               }
               leafinfo = 0;
               current = &(work[0]);
               *current = 0;
               cl = casted;
               continue;
            }
         } else if (i > 0 && (right[i] == '.' || right[i] == '[' || right[i] == '\0') ) {
            
            
            Bool_t needClass = kTRUE;
            *current = '\0';
            
            if (strlen(work)==0) continue;
            prevUseCollectionObject = useCollectionObject;
            prevUseReferenceObject = useReferenceObject;
            if (work[0]=='@') {
               useReferenceObject = kTRUE;
               useCollectionObject = kTRUE;
               Int_t l = 0;
               for(l=0;work[l+1]!=0;++l) work[l] = work[l+1];
               work[l] = '\0';
            } else if (work[strlen(work)-1]=='@') {
               useReferenceObject = kTRUE;
               useCollectionObject = kTRUE;
               work[strlen(work)-1] = '\0';
            } else {
               useReferenceObject = kFALSE;
               useCollectionObject = kFALSE;
            }
            Bool_t mustderef = kFALSE;
            if ( !prevUseReferenceObject && cl && cl->GetReferenceProxy() )  {
               R__LoadBranch(leaf->GetBranch(), readentry, fQuickLoad);
               if ( !maininfo )  {
                  maininfo = previnfo = new TFormLeafInfoReference(cl, element, offset);
                  if ( cl->GetReferenceProxy()->HasCounter() )  {
                     numberOfVarDim += RegisterDimensions(code,-1);
                  }
                  prevUseReferenceObject = kFALSE;
               }
               needClass = kFALSE;
               mustderef = kTRUE;
            }
            else if (!prevUseCollectionObject && cl == TClonesArray::Class()) {
               
               
               
               TBranch *branch = leaf->GetBranch();
               R__LoadBranch(branch,readentry,fQuickLoad);
               TClonesArray * clones;
               if (maininfo) {
                  clones = (TClonesArray*)maininfo->GetValuePointer(leaf,0);
               } else {
                  
                  
                  TClass *mother_cl;
                  if (leaf->IsA()==TLeafObject::Class()) {
                     
                     mother_cl = cl;
                  } else {
                     mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
                  }
                  TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0);
                  
                  numberOfVarDim += RegisterDimensions(code,clonesinfo,maininfo,kFALSE);
                  mustderef = kTRUE;
                  previnfo = clonesinfo;
                  maininfo = clonesinfo;
                  if (branch->GetListOfBranches()->GetLast()>=0) {
                     if (branch->IsA() != TBranchElement::Class()) {
                        Error("DefinedVariable","Unimplemented usage of ClonesArray");
                        return -2;
                     }
                     
                     clones = (TClonesArray*)((TBranchElement*)branch)->GetObject();
                  } else
                     clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0);
               }
               
               if (clones==0) {
                  Warning("DefinedVariable",
                          "TClonesArray object was not retrievable for %s!",
                          name.Data());
                  return -1;
               }
               TClass * inside_cl = clones->GetClass();
               if (1 || inside_cl) cl = inside_cl;
               
               if (0 && strlen(work)==0) {
                  
                  
                  
               }
            } else if (!prevUseCollectionObject && cl && cl->GetCollectionProxy() ) {
               
               
               
               TBranch *branch = leaf->GetBranch();
               R__LoadBranch(branch,readentry,fQuickLoad);
               if (maininfo==0) {
                  
                  
                  TClass *mother_cl;
                  if (leaf->IsA()==TLeafObject::Class()) {
                     
                     mother_cl = cl;
                  } else {
                     mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
                  }
                  TFormLeafInfo* collectioninfo =
                     new TFormLeafInfoCollection(mother_cl, 0, cl);
                  
                  numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
                  mustderef = kTRUE;
                  previnfo = collectioninfo;
                  maininfo = collectioninfo;
               } 
               
               TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass();
               if (!inside_cl && cl->GetCollectionProxy()->GetType() > 0) {
                  Warning("DefinedVariable","No data member in content of %s in %s\n",
                           cl->GetName(),name.Data());
               }
               if (1 || inside_cl) cl = inside_cl;
               
            }
            if (!cl) {
               Warning("DefinedVariable","Missing class for %s!",name.Data());
            } else {
               element = ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(work,offset);
            }
            if (!element && !prevUseCollectionObject) {
               
               
               TIter next( cl->GetStreamerInfo()->GetElements() );
               TStreamerElement * curelem;
               while ((curelem = (TStreamerElement*)next())) {
                  if (curelem->GetClassPointer() ==  TClonesArray::Class()) {
                     Int_t clones_offset;
                     ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(curelem->GetName(),clones_offset);
                     TFormLeafInfo* clonesinfo =
                        new TFormLeafInfo(cl, clones_offset, curelem);
                     TClonesArray * clones;
                     R__LoadBranch(leaf->GetBranch(),readentry,fQuickLoad);
                     if (previnfo) {
                        previnfo->fNext = clonesinfo;
                        clones = (TClonesArray*)maininfo->GetValuePointer(leaf,0);
                        previnfo->fNext = 0;
                     } else {
                        clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0);
                     }
                     TClass *sub_cl = clones->GetClass();
                     if (sub_cl) element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(work,offset);
                     delete clonesinfo;
                     if (element) {
                        leafinfo = new TFormLeafInfoClones(cl,clones_offset,curelem);
                        numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
                        if (maininfo==0) maininfo = leafinfo;
                        if (previnfo==0) previnfo = leafinfo;
                        else {
                           previnfo->fNext = leafinfo;
                           previnfo = leafinfo;
                        }
                        leafinfo = 0;
                        cl = sub_cl;
                        break;
                     }
                  } else if (curelem->GetClassPointer() && curelem->GetClassPointer()->GetCollectionProxy()) {
                     Int_t coll_offset;
                     ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(curelem->GetName(),coll_offset);
                     TClass *sub_cl =
                        curelem->GetClassPointer()->GetCollectionProxy()->GetValueClass();
                     if (sub_cl) {
                        element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(work,offset);
                     }
                     if (element) {
                        if (numberOfVarDim>1) {
                           Warning("DefinedVariable","TTreeFormula support only 2 level of variables size collections.  Assuming '@' notation for the collection %s.",
                                   curelem->GetName());
                           leafinfo = new TFormLeafInfo(cl,coll_offset,curelem);
                           useCollectionObject = kTRUE;
                        } else if (numberOfVarDim==1) {
                           R__ASSERT(maininfo);
                           leafinfo =
                              new TFormLeafInfoMultiVarDimCollection(cl,coll_offset,
                                                                     curelem,maininfo);
                           fHasMultipleVarDim[code] = kTRUE;
                           leafinfo->fNext = new TFormLeafInfoCollection(cl,coll_offset,curelem);
                           numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
                        } else {
                           leafinfo = new TFormLeafInfoCollection(cl,coll_offset,curelem);
                           numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
                        }
                        if (maininfo==0) maininfo = leafinfo;
                        if (previnfo==0) previnfo = leafinfo;
                        else {
                           previnfo->fNext = leafinfo;
                           previnfo = leafinfo;
                        }
                        if (leafinfo->fNext) {
                           previnfo = leafinfo->fNext;
                        }
                        leafinfo = 0;
                        cl = sub_cl;
                        break;
                     }
                  }
               }
            }
            if (element) {
               Int_t type = element->GetNewType();
               if (type<60 && type!=0) {
                  
                  if (numberOfVarDim>=1 && type>40) {
                     
                     leafinfo = new TFormLeafInfoMultiVarDim(cl,offset,element,maininfo);
                     fHasMultipleVarDim[code] = kTRUE;
                  } else {
                     if (leafinfo && type<=40 ) {
                        leafinfo->AddOffset(offset,element);
                     } else {
                        leafinfo = new TFormLeafInfo(cl,offset,element);
                     }
                  }
               } else {
                  Bool_t object = kFALSE;
                  Bool_t pointer = kFALSE;
                  Bool_t objarr = kFALSE;
                  switch(type) {
                     case TStreamerInfo::kObjectp:
                     case TStreamerInfo::kObjectP:
                     case TStreamerInfo::kSTLp:
                     case TStreamerInfo::kAnyp:
                     case TStreamerInfo::kAnyP:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP:
                        pointer = kTRUE;
                        break;
                     case TStreamerInfo::kBase:
                     case TStreamerInfo::kAny :
                     case TStreamerInfo::kSTL:
                     case TStreamerInfo::kObject:
                     case TStreamerInfo::kTString:
                     case TStreamerInfo::kTNamed:
                     case TStreamerInfo::kTObject:
                        object = kTRUE;
                        break;
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kAny:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL:
                     case TStreamerInfo::kOffsetL + TStreamerInfo::kObject:
                        objarr = kTRUE;
                        break;
                     case TStreamerInfo::kStreamer:
                     case TStreamerInfo::kStreamLoop:
                        
                        Error("DefinedVariable",
                              "%s is a datamember of %s BUT is not yet of a supported type (%d)",
                              right,cl->GetName(),type);
                        return -2;
                     default:
                        
                        Error("DefinedVariable",
                              "%s is a datamember of %s BUT is not of a unknown type (%d)",
                              right,cl->GetName(),type);
                        return -2;
                  }
                  if (object && !useCollectionObject &&
                      ( element->GetClassPointer() ==  TClonesArray::Class()
                        || element->GetClassPointer()->GetCollectionProxy() ) )
                  {
                     object = kFALSE;
                  }
                  if (object && leafinfo) {
                     leafinfo->AddOffset(offset,element);
                  } else if (objarr) {
                     
                     leafinfo = new TFormLeafInfo(cl,offset,element);
                     mustderef = kTRUE;
                  } else {
                     if (!useCollectionObject && element->GetClassPointer() ==  TClonesArray::Class()) {
                        leafinfo = new TFormLeafInfoClones(cl,offset,element);
                        mustderef = kTRUE;
                     } else if (!useCollectionObject &&  element->GetClassPointer()
                                && element->GetClassPointer()->GetCollectionProxy()) {
                        mustderef = kTRUE;
                        if (numberOfVarDim>1) {
                           Warning("DefinedVariable","TTreeFormula support only 2 level of variables size collections.  Assuming '@' notation for the collection %s.",
                                   element->GetName());
                           leafinfo = new TFormLeafInfo(cl,offset,element);
                           useCollectionObject = kTRUE;
                        } else if (numberOfVarDim==1) {
                           R__ASSERT(maininfo);
                           leafinfo =
                              new TFormLeafInfoMultiVarDimCollection(cl,offset,element,maininfo);
                           fHasMultipleVarDim[code] = kTRUE;
                           
                           
                           
                           
                           
                           
                           
                           
                           leafinfo->fNext =  new TFormLeafInfoCollection(cl, offset, element);
                           if (element->GetClassPointer()->GetCollectionProxy()->GetValueClass()==0) {
                              TFormLeafInfo *info = new TFormLeafInfoNumerical(
                                 element->GetClassPointer()->GetCollectionProxy()->GetType());
                              if (leafinfo->fNext) leafinfo->fNext->fNext = info;
                              else leafinfo->fNext = info;
                           }
                        } else {
                           leafinfo =  new TFormLeafInfoCollection(cl, offset, element);
                           TClass *elemCl = element->GetClassPointer();
                           TClass *valueCl = elemCl->GetCollectionProxy()->GetValueClass();
                           if (!maininfo) maininfo = leafinfo;
                           if (valueCl!=0 && valueCl->GetCollectionProxy()!=0) {
                              numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
                              if (previnfo==0) previnfo = leafinfo;
                              else {
                                 previnfo->fNext = leafinfo;
                                 previnfo = leafinfo;
                              }
                              leafinfo = new TFormLeafInfoMultiVarDimCollection(elemCl,0,
                                 elemCl->GetCollectionProxy()->GetValueClass(),maininfo);
                              
                              fHasMultipleVarDim[code] = kTRUE;
                              
                              leafinfo->fNext =  new TFormLeafInfoCollection(elemCl,0,
                                 valueCl);
                              elemCl = valueCl;
                           }
                           if (elemCl->GetCollectionProxy() &&
                               elemCl->GetCollectionProxy()->GetValueClass()==0) {
                              TFormLeafInfo *info = new TFormLeafInfoNumerical(
                                 elemCl->GetCollectionProxy()->GetType());
                              if (leafinfo->fNext) leafinfo->fNext->fNext = info;
                              else leafinfo->fNext = info;
                           }
                        }
                     } else if ( (object || pointer) && !useReferenceObject && element->GetClassPointer()->GetReferenceProxy() ) {
                        TClass* c = element->GetClassPointer();
                        R__LoadBranch(leaf->GetBranch(),readentry,fQuickLoad);
                        if ( object )  {
                           leafinfo = new TFormLeafInfoReference(c, element, offset);
                        }
                        else  {
                           leafinfo = new TFormLeafInfoPointer(cl,offset,element);
                           leafinfo->fNext = new TFormLeafInfoReference(c, element, 0);
                        }
                        
                        
                        
                        prevUseReferenceObject = kFALSE;
                        needClass = kFALSE;
                        mustderef = kTRUE;
                     } else if (pointer) {
                        
                        leafinfo = new TFormLeafInfoPointer(cl,offset,element);
                        mustderef = kTRUE;
                     } else {
                        
                        R__ASSERT(object);
                        leafinfo = new TFormLeafInfo(cl,offset,element);
                     }
                  }
               }
            } else {
               Error("DefinedVariable","%s is not a datamember of %s",work,cl->GetName());
               return -1;
            }
            numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,useCollectionObject); 
            if (maininfo==0) {
               maininfo = leafinfo;
            }
            if (previnfo==0) {
               previnfo = leafinfo;
            } else if (previnfo!=leafinfo) {
               previnfo->fNext = leafinfo;
               previnfo = leafinfo;
            }
            while (previnfo->fNext) previnfo = previnfo->fNext;
            if ( right[i] != '\0' )  {
               if ( !needClass && mustderef )   {
                  maininfo->SetBranch(leaf->GetBranch());
                  char *ptr = (char*)maininfo->GetValuePointer(leaf,0);
                  TFormLeafInfoReference* refInfo = 0;
                  if ( !maininfo->IsReference() )  {
                     for( TFormLeafInfo* inf = maininfo->fNext; inf; inf = inf->fNext )  {
                        if ( inf->IsReference() )  {
                           refInfo = (TFormLeafInfoReference*)inf;
                        }
                     }
                  }
                  else {
                     refInfo = (TFormLeafInfoReference*)maininfo;
                  }
                  if ( refInfo )  {
                     cl = refInfo->GetValueClass(ptr);
                     if ( !cl )  {
                        Error("DefinedVariable","Failed to access class type of reference target (%s)",element->GetName());
                        return -1;
                     }
                     element = ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(work,offset);
                  }
                  else  {
                     Error("DefinedVariable","Failed to access class type of reference target (%s)",element->GetName());
                     return -1;
                  }
               }
               else if ( needClass )  {
                  cl = element->GetClassPointer();
               }
            }
            if (mustderef) leafinfo = 0;
            current = &(work[0]);
            *current = 0;
            R__ASSERT(right[i] != '[');  
         } else
            *current++ = right[i];
      }
      if (maininfo) {
         fDataMembers.AddAtAndExpand(maininfo,code);
         if (leaf) fLookupType[code] = kDataMember;
         else fLookupType[code] = kTreeMember;
      }
   }
   if (strlen(work)!=0) {
      
      return -1;
   }
   static TClassRef stdStringClass = TClass::GetClass("string");
   TClass *objClass = EvalClass(code);
   if (IsLeafString(code) || objClass == TString::Class() || objClass == stdStringClass) {
      if ( SwitchToFormLeafInfo(code) ) {
         TFormLeafInfo *last = (TFormLeafInfo*)fDataMembers.At(code);
         
         if (!last) return action;
         while (last->fNext) { last = last->fNext; }
         const char *funcname = 0;
         if (objClass == TString::Class()) {
            funcname = "Data";
         } else if (objClass == stdStringClass) {
            funcname = "c_str";
         }
         if (funcname) {
            TMethodCall *method = new TMethodCall(objClass, funcname, "");
            last->fNext = new TFormLeafInfoMethod(objClass,method);
         }
      }
      return kDefinedString;
   }
   if (objClass) {
      TMethodCall *method = new TMethodCall(objClass, "AsDouble", "");
      if (method->IsValid()
         && (method->ReturnType() == TMethodCall::kLong || method->ReturnType() == TMethodCall::kDouble)
         && SwitchToFormLeafInfo(code) ) {
         TFormLeafInfo *last = (TFormLeafInfo*)fDataMembers.At(code);
         
         if (!last) return action;
         while (last->fNext) { last = last->fNext; }
         last->fNext = new TFormLeafInfoMethod(objClass,method);
         return kDefinedVariable;
      }
      delete method;
      method = new TMethodCall(objClass, "AsString", "");
      if (method->IsValid()
          && method->ReturnType() == TMethodCall::kString
          && SwitchToFormLeafInfo(code) ) {
         TFormLeafInfo *last = (TFormLeafInfo*)fDataMembers.At(code);
         
         if (!last) return action;
         while (last->fNext) { last = last->fNext; }
         last->fNext = new TFormLeafInfoMethod(objClass,method);
         return kDefinedString;
      }
      if (method->IsValid()
          && method->ReturnType() == TMethodCall::kOther) {
         TClass *rcl = 0;
         TFunction *f = method->GetMethod();
         if (f) rcl = TClass::GetClass(gInterpreter->TypeName(f->GetReturnTypeName()));
         if ((rcl == TString::Class() || rcl == stdStringClass)
             && SwitchToFormLeafInfo(code) ) {
            TFormLeafInfo *last = (TFormLeafInfo*)fDataMembers.At(code);
            
            if (!last) return action;
            while (last->fNext) { last = last->fNext; }
            last->fNext = new TFormLeafInfoMethod(objClass,method);
            last = last->fNext;
            objClass = rcl;
            const char *funcname = 0;
            if (objClass == TString::Class()) {
               funcname = "Data";
            } else if (objClass == stdStringClass) {
               funcname = "c_str";
            }
            if (funcname) {
               method = new TMethodCall(objClass, funcname, "");
               last->fNext = new TFormLeafInfoMethod(objClass,method);
            }
            return kDefinedString;
         }
      }
      delete method;
   }
   return action;
}
Int_t TTreeFormula::FindLeafForExpression(const char* expression, TLeaf*& leaf, TString& leftover, Bool_t& final, UInt_t& paran_level, TObjArray& castqueue, std::vector<std::string>& aliasUsed, Bool_t& useLeafCollectionObject, const char* fullExpression)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   Long64_t readentry = fTree->GetTree()->GetReadEntry();
   if (readentry==-1) readentry=0;
   const char *cname = expression;
   char    first[kMaxLen];  first[0] = '\0';
   char   second[kMaxLen]; second[0] = '\0';
   char    right[kMaxLen];  right[0] = '\0';
   char     work[kMaxLen];   work[0] = '\0';
   char     left[kMaxLen];   left[0] = '\0';
   char  scratch[kMaxLen];
   char scratch2[kMaxLen];
   std::string currentname;
   Int_t previousdot = 0;
   char *current;
   TLeaf *tmp_leaf=0;
   TBranch *branch=0, *tmp_branch=0;
   Int_t nchname = strlen(cname);
   Int_t i;
   Bool_t foundAtSign = kFALSE;
   for (i=0, current = &(work[0]); i<=nchname && !final;i++ ) {
      
      *current++ = cname[i];
      if (cname[i] == '(') {
         ++paran_level;
         if (current==work+1) {
            
            
            current--;
         }
         continue;
         
         
         
         
         
         
         
      }
      if (cname[i] == ')') {
         if (paran_level==0) {
            Error("DefinedVariable","Unmatched paranthesis in %s",fullExpression);
            return -1;
         }
         
         *(--current) = 0;
         paran_level--;
         TString cast_name = gInterpreter->TypeName(work);
         TClass *cast_cl = TClass::GetClass(cast_name);
         if (cast_cl) {
            
            castqueue.AddAtAndExpand(cast_cl,paran_level);
            current = &(work[0]);
            *current = 0;
            
            continue;
         } else if (gROOT->GetType(cast_name)) {
            
            current = &(work[0]);
            *current = 0;
            Warning("DefinedVariable",
               "Casting to primary types like \"%s\" is not supported yet",cast_name.Data());
            continue;
         }
         *(current++)=')';
         *current='\0';
         char *params = strchr(work,'(');
         if (params) {
            *params = 0; params++;
            if (branch && !leaf) {
               
               
               if (BranchHasMethod(0, branch, work, params, readentry)) {
                  
               }
            }
            
            
            TIter next(fTree->GetIteratorOnAllLeaves());
            TLeaf* leafcur = 0;
            while (!leaf && (leafcur = (TLeaf*) next())) {
               if (leafcur) {
                  TBranch* br = leafcur->GetBranch();
                  Bool_t yes = BranchHasMethod(leafcur, br, work, params, readentry);
                  if (yes) {
                     leaf = leafcur;
                     
                  }
               } else {
                  Fatal("FindLeafForExpression", "Tree has no leaves!");
               }
            }
            if (!leaf) {
               
               if (strlen(left) && left[strlen(left)-1]=='.') left[strlen(left)-1]=0;
               const char *aliasValue = fTree->GetAlias(left);
               if (aliasValue && strcspn(aliasValue,"+*/-%&!=<>|")==strlen(aliasValue)) {
                  
                  
                  if (find(aliasUsed.begin(),
                     aliasUsed.end(),
                     left) != aliasUsed.end()) {
                        Error("DefinedVariable",
                           "The substitution of the branch alias \"%s\" by \"%s\" in \"%s\" failed\n"\
                           "\tbecause \"%s\" is used [recursively] in its own definition!",
                           left,aliasValue,fullExpression,left);
                        return -3;
                  }
                  aliasUsed.push_back(left);
                  TString newExpression = aliasValue;
                  newExpression += (cname+strlen(left));
                  Int_t res = FindLeafForExpression(newExpression, leaf, leftover, final, paran_level,
                     castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
                  if (res<0) {
                     Error("DefinedVariable",
                        "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
                     return -3;
                  }
                  return res;
               }
               
               
               return -1;
            }
            
            
            
            
            
            
            
            strcpy(right,work);
            strcat(right,"(");
            strcat(right,params);
            final = kTRUE;
            
            current = &(work[0]);
            *current = 0;
            break;
         }
      }
      if (cname[i] == '.' || cname[i] == '\0' || cname[i] == ')') {
         
         
         *current = '\0';
         Int_t len = strlen(work);
         if (work[0]=='@') {
            foundAtSign = kTRUE;
            Int_t l = 0;
            for(l=0;work[l+1]!=0;++l) work[l] = work[l+1];
            work[l] = '\0';
            --current;
         } else if (len>=2 && work[len-2]=='@') {
            foundAtSign = kTRUE;
            work[len-2] = cname[i];
            work[len-1] = '\0';
            --current;
         } else {
            foundAtSign = kFALSE;
         }
         if (left[0]==0) strcpy(left,work);
         if (!leaf && !branch) {
            
            strcpy(first,work);
            std::string treename(first);
            if (treename.size() && treename[treename.size()-1]=='.') {
               treename.erase(treename.size()-1);
            }
            if (treename== "This"  ) {
               
               TNamed *named = new TNamed(fTree->GetName(),fTree->GetName());
               fLeafNames.AddAtAndExpand(named,fNcodes);
               fLeaves.AddAtAndExpand(fTree,fNcodes);
               if (cname[i]) leftover = &(cname[i+1]);
               return 2;
            }
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            branch = fTree->FindBranch(first);
            leaf = fTree->FindLeaf(first);
            
            
            if (cname[i]) first[strlen(first)-1]='\0';
            if (!branch) branch = fTree->FindBranch(first);
            if (!leaf) leaf = fTree->FindLeaf(first);
            TClass* cl = 0;
            if ( branch && branch->InheritsFrom(TBranchElement::Class()) ) {
               int offset=0;
               TBranchElement* bElt = (TBranchElement*)branch;
               TStreamerInfo* info  = bElt->GetInfo();
               TStreamerElement* element = info ? info->GetStreamerElement(first,offset) : 0;
               if (element) cl = element->GetClassPointer();
               if ( cl && !cl->GetReferenceProxy() ) cl = 0;
            }
            if ( cl )  {  
               final = kTRUE;
               useLeafCollectionObject = foundAtSign;
               
               current = &(work[0]);
               *current = 0;
            }
            else if (branch && (foundAtSign || cname[i] != 0)  ) {
               
               
               
               if (leaf==0) {
                  
                  
                  if (branch->InheritsFrom(TBranchElement::Class()) ) {
                     Int_t type = ((TBranchElement*)branch)->GetType();
                     if ( type == 3 || type ==4) {
                        
                        leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
                        if (foundAtSign) {
                           useLeafCollectionObject = foundAtSign;
                           foundAtSign = kFALSE;
                           current = &(work[0]);
                           *current = 0;
                           ++i;
                           break;
                        }
                     }
                  }
               }
               
               useLeafCollectionObject = foundAtSign;
               foundAtSign = kFALSE;
               current = &(work[0]);
               *current = 0;
            } else if (leaf || branch) {
               if (leaf && branch) {
                  
                  
                  
                  
                  
               }
               if (leaf && leaf->IsOnTerminalBranch()) {
                  
                  
                  final = kTRUE;
               }
               
               current = &(work[0]);
               *current = 0;
            } else {
               
               
               TLeaf *leafcur = GetLeafWithDatamember(first,work,readentry);
               if (leafcur) {
                  leaf = leafcur;
                  branch = leaf->GetBranch();
                  if (leaf->IsOnTerminalBranch()) {
                     final = kTRUE;
                     strcpy(right,first);
                     
                     if (foundAtSign) strcat(right,"@");
                     if (cname[i]=='.') strcat(right,".");
                     
                     current = &(work[0]);
                     *current = 0;
                  };
               } else if (cname[i] == '.') {
                  
                  
                  
                  
                  TBranch *branchcur;
                  TIter next( fTree->GetListOfBranches() );
                  while(!branch && (branchcur=(TBranch*)next()) ) {
                     branch = branchcur->FindBranch(first);
                  }
                  if (branch) {
                     
                     current = &(work[0]);
                     *current = 0;
                  }
               }
            }
         } else {  
            if (final) {
               Error("DefinedVariable", "Unexpected control flow!");
               return -1;
            }
            
            
            if (cname[i]) work[strlen(work)-1] = '\0';
            sprintf(scratch,"%s.%s",first,work);
            sprintf(scratch2,"%s.%s.%s",first,second,work);
            if (previousdot) {
               currentname = &(work[previousdot+1]);
            }
            
            
            if (branch) {
               tmp_leaf = branch->FindLeaf(work);
               if (!tmp_leaf)  tmp_leaf = branch->FindLeaf(scratch);
               if (!tmp_leaf)  tmp_leaf = branch->FindLeaf(scratch2);
               if (!tmp_leaf)  tmp_leaf = branch->FindLeaf(currentname.c_str());
            }
            if (tmp_leaf && tmp_leaf->IsOnTerminalBranch() ) {
               
               
               final = kTRUE;
            }
            if (branch) {
               tmp_branch = branch->FindBranch(work);
               if (!tmp_branch) tmp_branch = branch->FindBranch(scratch);
               if (!tmp_branch) tmp_branch = branch->FindBranch(scratch2);
               if (!tmp_branch) tmp_branch = branch->FindBranch(currentname.c_str());
            }
            if (tmp_branch) {
               branch=tmp_branch;
               
               if (!final) {
                  tmp_leaf = branch->FindLeaf(work);
                  if (!tmp_leaf)  tmp_leaf = branch->FindLeaf(scratch);
                  if (!tmp_leaf)  tmp_leaf = branch->FindLeaf(scratch2);
                  if (!tmp_leaf)  tmp_leaf = branch->FindLeaf(currentname.c_str());
                  if (tmp_leaf && tmp_leaf->IsOnTerminalBranch() ) {
                     
                     
                     final = kTRUE;
                     leaf = tmp_leaf;
                  }
               }
            }
            if (tmp_leaf) {
               
               if (second[0]) strcat(second,".");
               strcat(second,work);
               leaf = tmp_leaf;
               useLeafCollectionObject = foundAtSign;
               foundAtSign = kFALSE;
               
               current = &(work[0]);
               *current = 0;
            } else {
               
               if (strlen(work)) {
                  if (foundAtSign) {
                     Int_t where = strlen(work);
                     work[where] = '@';
                     work[where+1] = cname[i];
                     ++current;
                     previousdot = where+1;
                  } else {
                     previousdot = strlen(work);
                     work[strlen(work)] = cname[i];
                  }
               } else --current;
            }
         }
      }
   }
   
   if (strlen(work)) {
      strcat(right,work);
   }
   if (i<nchname) {
      if (strlen(right) && right[strlen(right)-1]!='.' && cname[i]!='.') {
         
         
         
         strcat(right,".");
      }
      strcat(right,&cname[i]);
   }
   if (!final && branch) {
      if (!leaf) {
         leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(0);
         if (!leaf) return -1;
      }
      final = leaf->IsOnTerminalBranch();
   }
   if (leaf && leaf->InheritsFrom("TLeafObject") ) {
      if (strlen(right)==0) strcpy(right,work);
   }
   if (leaf==0 && left[0]!=0) {
      if (left[strlen(left)-1]=='.') left[strlen(left)-1]=0;
      
      const char *aliasValue = fTree->GetAlias(left);
      if (aliasValue && strcspn(aliasValue,"+*/-%&!=<>|")==strlen(aliasValue)) {
         
         
         if (find(aliasUsed.begin(),
                  aliasUsed.end(),
                  left) != aliasUsed.end()) {
            Error("DefinedVariable",
                  "The substitution of the branch alias \"%s\" by \"%s\" in \"%s\" failed\n"\
                  "\tbecause \"%s\" is used [recursively] in its own definition!",
                  left,aliasValue,fullExpression,left);
            return -3;
         }
         aliasUsed.push_back(left);
         TString newExpression = aliasValue;
         newExpression += (cname+strlen(left));
         Int_t res = FindLeafForExpression(newExpression, leaf, leftover, final, paran_level,
                                           castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
         if (res<0) {
            Error("DefinedVariable",
                  "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
            return -3;
         }
         return res;
      }
   }
   leftover = right;
   return 0;
}
Int_t TTreeFormula::DefinedVariable(TString &name, Int_t &action)
{
   action = kDefinedVariable;
   if (!fTree) return -1;
   fNpar = 0;
   if (name.Length() > kMaxLen) return -1;
   Int_t i,k;
   if (name == "Entry$") {
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kIndexOfEntry;
      return code;
   }
   if (name == "LocalEntry$") {
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kIndexOfLocalEntry;
      return code;
   }
   if (name == "Entries$") {
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kEntries;
      return code;
   }
   if (name == "Iteration$") {
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kIteration;
      return code;
   }
   if (name == "Length$") {
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kLength;
      return code;
   }
   static const char *lenfunc = "Length$(";
   if (strncmp(name.Data(),"Length$(",strlen(lenfunc))==0
       && name[name.Length()-1]==')') {
      TString subform = name.Data()+strlen(lenfunc);
      subform.Remove( subform.Length() - 1 );
      TTreeFormula *lengthForm = new TTreeFormula("lengthForm",subform,fTree);
      fAliases.AddAtAndExpand(lengthForm,fNoper);
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kLengthFunc;
      return code;
   }
   static const char *sumfunc = "Sum$(";
   if (strncmp(name.Data(),"Sum$(",strlen(sumfunc))==0
       && name[name.Length()-1]==')') {
      TString subform = name.Data()+strlen(sumfunc);
      subform.Remove( subform.Length() - 1 );
      TTreeFormula *sumForm = new TTreeFormula("sumForm",subform,fTree);
      fAliases.AddAtAndExpand(sumForm,fNoper);
      Int_t code = fNcodes++;
      fCodes[code] = 0;
      fLookupType[code] = kSum;
      return code;
   }
   
   Int_t res = DefineAlternate(name.Data());
   if (res!=0) {
      
      if (res<0) return res;
      action = res;
      return 0;
   }
   
   char    cname[kMaxLen];  strcpy(cname,name.Data());
   char     dims[kMaxLen];   dims[0] = '\0';
   Bool_t final = kFALSE;
   UInt_t paran_level = 0;
   TObjArray castqueue;
   
   Int_t cnamelen = strlen(cname);
   for(i=0,k=0; i<cnamelen; ++i, ++k) {
      if (cname[i] == '[') {
         int bracket = i;
         int bracket_level = 1;
         int j;
         for (j=++i; j<cnamelen && (bracket_level>0 || cname[j]=='['); j++, i++) {
            if (cname[j]=='[') bracket_level++;
            else if (cname[j]==']') bracket_level--;
         }
         if (bracket_level != 0) {
            
            return -1;
         }
         strncat(dims,&cname[bracket],j-bracket);
         
      }
      if (i!=k) cname[k] = cname[i];
   }
   cname[k]='\0';
   Bool_t useLeafCollectionObject = kFALSE;
   TString leftover;
   TLeaf *leaf = 0;
   {
      std::vector<std::string> aliasSofar = fAliasesUsed;
      res = FindLeafForExpression(cname, leaf, leftover, final, paran_level, castqueue, aliasSofar, useLeafCollectionObject, name);
   }
   if (res<0) return res;
   if (!leaf && res!=2) {
      
      const char *aliasValue = fTree->GetAlias(cname);
      if (aliasValue) {
         
         
         if (find(fAliasesUsed.begin(),
                  fAliasesUsed.end(),
                  cname) != fAliasesUsed.end()) {
            Error("DefinedVariable",
                  "The substitution of the alias \"%s\" by \"%s\" failed\n"\
                  "\tbecause \"%s\" is recursively used in its own definition!",
                  cname,aliasValue,cname);
            return -3;
         }
         std::vector<std::string> aliasSofar = fAliasesUsed;
         aliasSofar.push_back( cname );
         
         TTreeFormula *subform = new TTreeFormula(cname,aliasValue,fTree,aliasSofar); 
         if (subform->GetNdim()==0) {
            Error("DefinedVariable",
                  "The substitution of the alias \"%s\" by \"%s\" failed.",cname,aliasValue);
            return -3;
         }
         fManager->Add(subform);
         fAliases.AddAtAndExpand(subform,fNoper);
         if (subform->IsString()) {
            action = kAliasString;
            return 0;
         } else {
            action = kAlias;
            return 0;
         }
      }
   }
   if (leaf || res==2) {
      if (leaf && leaf->GetBranch() && leaf->GetBranch()->TestBit(kDoNotProcess)) {
         Error("DefinedVariable","the branch \"%s\" has to be enabled to be used",leaf->GetBranch()->GetName());
         return -2;
      }
      Int_t code = fNcodes++;
      
      
      if (dims[0]) {
         char *current = &( dims[0] );
         Int_t dim = 0;
         char varindex[kMaxLen];
         Int_t index;
         Int_t scanindex ;
         while (current) {
            current++;
            if (current[0] == ']') {
               fIndexes[code][dim] = -1; 
            } else {
               scanindex = sscanf(current,"%d",&index);
               if (scanindex) {
                  fIndexes[code][dim] = index;
               } else {
                  fIndexes[code][dim] = -2; 
                  strcpy(varindex,current);
                  char *end = varindex;
                  for(char bracket_level = 0;*end!=0;end++) {
                     if (*end=='[') bracket_level++;
                     if (bracket_level==0 && *end==']') break;
                     if (*end==']') bracket_level--;
                  }
                  if (end != 0) {
                     *end = '\0';
                     fVarIndexes[code][dim] = new TTreeFormula("index_var",
                                                               varindex,
                                                                  fTree);
                     current += strlen(varindex)+1; 
                  }
               }
            }
            dim ++;
            if (dim >= kMAXFORMDIM) {
               
               break;
            }
            current = (char*)strstr( current, "[" );
         }
      }
      
      
      Int_t res = ParseWithLeaf(leaf,leftover,final,paran_level,castqueue,useLeafCollectionObject,name);
      if (res<0) return res;
      if (res>0) action = res;
      return code;
   }
   TCutG *gcut = (TCutG*)gROOT->GetListOfSpecials()->FindObject(name.Data());
   if (gcut) {
      if (gcut->GetObjectX()) {
         if(!gcut->GetObjectX()->InheritsFrom(TTreeFormula::Class())) {
            delete gcut->GetObjectX(); gcut->SetObjectX(0);
         }
      }
      if (gcut->GetObjectY()) {
         if(!gcut->GetObjectY()->InheritsFrom(TTreeFormula::Class())) {
            delete gcut->GetObjectY(); gcut->SetObjectY(0);
         }
      }
      Int_t code = fNcodes;
      if (strlen(gcut->GetVarX()) && strlen(gcut->GetVarY()) ) {
         TTreeFormula *fx = new TTreeFormula("f_x",gcut->GetVarX(),fTree);
         gcut->SetObjectX(fx);
         TTreeFormula *fy = new TTreeFormula("f_y",gcut->GetVarY(),fTree);
         gcut->SetObjectY(fy);
         fCodes[code] = -2;
      } else if (strlen(gcut->GetVarX())) {
         
         
         Double_t min = 0;
         Double_t max = 0;
         Int_t n = gcut->GetN();
         Double_t *x = gcut->GetX();
         min = max = x[0];
         for(Int_t i2 = 1; i2<n; i2++) {
            if (x[i2] < min) min = x[i2];
            if (x[i2] > max) max = x[i2];
         }
         TString formula = "(";
         formula += min;
         formula += "<=";
         formula += gcut->GetVarX();
         formula += " && ";
         formula += gcut->GetVarX();
         formula += "<=";
         formula += max;
         formula += ")";
         TTreeFormula *fx = new TTreeFormula("f_x",formula.Data(),fTree);
         gcut->SetObjectX(fx);
         fCodes[code] = -1;
      } else {
         Error("DefinedVariable","Found a TCutG without leaf information (%s)",
               gcut->GetName());
         return -1;
      }
      fMethods.AddAtAndExpand(gcut,code);
      fNcodes++;
      fLookupType[code] = -1;
      return code;
   }
   
   TEntryList *elist = (TEntryList*)gDirectory->Get(name.Data());
   if (elist) {
      Int_t code = fNcodes;
      fCodes[code] = 0;
      fMethods.AddAtAndExpand(elist, code);
      fNcodes++;
      fLookupType[code] = kEntryList;
      return code;
   }
   return -1;
}
TLeaf* TTreeFormula::GetLeafWithDatamember(const char* topchoice, const char* nextchoice, Long64_t readentry) const
{
   
   
   TClass * cl = 0;
   TIter next (fTree->GetIteratorOnAllLeaves());
   TFormLeafInfo* clonesinfo = 0;
   TLeaf *leafcur;
   while ((leafcur = (TLeaf*)next())) {
      
      
      
      cl = 0;
      if (leafcur->InheritsFrom("TLeafObject") &&
          leafcur->GetBranch()->GetListOfBranches()->Last()==0) {
         TLeafObject *lobj = (TLeafObject*)leafcur;
         cl = lobj->GetClass();
      } else if (leafcur->InheritsFrom("TLeafElement") && leafcur->IsOnTerminalBranch()) {
         TLeafElement * lElem = (TLeafElement*) leafcur;
         if (lElem->IsOnTerminalBranch()) {
            TBranchElement *branchEl = (TBranchElement *)leafcur->GetBranch();
            Int_t type = branchEl->GetStreamerType();
            if (type==-1) {
               cl =  branchEl->GetInfo()->GetClass();
            } else if (type>60 || type==0) {
               
               
               
               TStreamerElement* element = (TStreamerElement*)
                  branchEl->GetInfo()->GetElems()[branchEl->GetID()];
               if (element) cl = element->GetClassPointer();
               else cl = 0;
            }
         }
      }
      if (clonesinfo) { delete clonesinfo; clonesinfo = 0; }
      if (cl ==  TClonesArray::Class()) {
         
         
         
         R__LoadBranch(leafcur->GetBranch(),readentry,fQuickLoad);
         TClonesArray * clones;
         TBranch *branch = leafcur->GetBranch();
         if  (   branch->IsA()==TBranchElement::Class()
                 && ((TBranchElement*)branch)->GetType()==31) {
            
            
            
            continue;
         } else {
            Bool_t toplevel = (branch == branch->GetMother());
            clonesinfo = new TFormLeafInfoClones(cl, 0, toplevel);
            clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leafcur,0);
         }
         if (clones) cl = clones->GetClass();
      } else if (cl && cl->GetCollectionProxy()) {
         
         
         
         TBranch *branch = leafcur->GetBranch();
         if  (   branch->IsA()==TBranchElement::Class()
                 && ((TBranchElement*)branch)->GetType()==41) {
            
            
            
            continue;
         } else {
            clonesinfo = new TFormLeafInfoCollection(cl, 0);
         }
         cl = cl->GetCollectionProxy()->GetValueClass();
      }
      if (cl) {
         
         
         Int_t offset;
         TStreamerInfo* info =  (TStreamerInfo*)cl->GetStreamerInfo();
         TStreamerElement* element = info?info->GetStreamerElement(topchoice,offset):0;
         if (!element) {
            TIter next( cl->GetStreamerInfo()->GetElements() );
            TStreamerElement * curelem;
            while ((curelem = (TStreamerElement*)next())) {
               if (curelem->GetClassPointer() ==  TClonesArray::Class()) {
                  
                  
                  
                  
                  TBranch *branch = leafcur->GetBranch();
                  TFormLeafInfo *leafinfo = 0;
                  if (clonesinfo) {
                     leafinfo = clonesinfo;
                  } else if (branch->IsA()==TBranchElement::Class()
                             && ((TBranchElement*)branch)->GetType()==31) {
                     
                     TBranchElement *branchEl = (TBranchElement*)branch;
                     TStreamerInfo *info = branchEl->GetInfo();
                     TClass * mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
                     TStreamerElement *element =
                        (TStreamerElement *)info->GetElems()[branchEl->GetID()];
                     leafinfo = new TFormLeafInfoClones(mother_cl, 0, element, kTRUE);
                  }
                  Int_t clones_offset;
                  ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(curelem->GetName(),clones_offset);
                  TFormLeafInfo* sub_clonesinfo = new TFormLeafInfo(cl, clones_offset, curelem);
                  if (leafinfo)
                     if (leafinfo->fNext) leafinfo->fNext->fNext = sub_clonesinfo;
                     else leafinfo->fNext = sub_clonesinfo;
                  else leafinfo = sub_clonesinfo;
                  R__LoadBranch(branch,readentry,fQuickLoad);
                  TClonesArray * clones = (TClonesArray*)leafinfo->GetValuePointer(leafcur,0);
                  delete leafinfo; clonesinfo = 0;
                  
                  
                  
                  
                  if (!clones) continue;
                  TClass *sub_cl = clones->GetClass();
                  
                  element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(nextchoice,offset);
                  if (element) break;
               } 
               else if (curelem->GetClassPointer() && curelem->GetClassPointer()->GetCollectionProxy()) {
                  TClass *sub_cl = curelem->GetClassPointer()->GetCollectionProxy()->GetValueClass();
                  while(sub_cl && sub_cl->GetCollectionProxy())
                     sub_cl = sub_cl->GetCollectionProxy()->GetValueClass();
                  
                  if (sub_cl) element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(nextchoice,offset);
                  if (element) break;
               }
            } 
         }
         if (element) break;
         else cl = 0;
      }
   }
   delete clonesinfo;
   if (cl) {
      return leafcur;
   } else {
      return 0;
   }
}
Bool_t TTreeFormula::BranchHasMethod(TLeaf* leafcur, TBranch* branch, const char* method, const char* params, Long64_t readentry) const
{
   
   
   TClass *cl = 0;
   TLeafObject* lobj = 0;
   
   
   
   
   
   if (branch->TestBit(kDoNotProcess)) {
      return kFALSE;
   }
   
   if (branch->InheritsFrom(TBranchObject::Class())) {
      lobj = (TLeafObject*) branch->GetListOfLeaves()->At(0);
      cl = lobj->GetClass();
   } else if (branch->InheritsFrom(TBranchElement::Class())) {
      TBranchElement* branchEl = (TBranchElement*) branch;
      Int_t type = branchEl->GetStreamerType();
      if (type == -1) {
         cl = branchEl->GetInfo()->GetClass();
      } else if (type > 60) {
         
         
         
         TStreamerElement* element = (TStreamerElement*) branchEl->GetInfo()->GetElems()[branchEl->GetID()];
         if (element) {
            cl = element->GetClassPointer();
         } else {
            cl = 0;
         }
         if ((cl == TClonesArray::Class()) && (branchEl->GetType() == 31)) {
            
            
            
            cl = 0;
         }
         
      }
   }
   if (cl == TClonesArray::Class()) {
      
      
      
      
      TClonesArray* clones = 0;
      R__LoadBranch(branch, readentry, fQuickLoad);
      if (branch->InheritsFrom(TBranchObject::Class())) {
         clones = (TClonesArray*) lobj->GetObject();
      } else if (branch->InheritsFrom(TBranchElement::Class())) {
         
         
         
         TBranchElement* bc = (TBranchElement*) branch;
         if (bc == bc->GetMother()) {
            
            
            clones = (TClonesArray*) bc->GetObject();
         } else if (!leafcur || !leafcur->IsOnTerminalBranch()) {
            TStreamerElement* element = (TStreamerElement*) bc->GetInfo()->GetElems()[bc->GetID()];
            if (element->IsaPointer()) {
               clones = *((TClonesArray**) bc->GetAddress());
               
            } else {
               
               clones = (TClonesArray*) bc->GetObject();
            }
         }
         if (!clones) {
            R__LoadBranch(bc, readentry, fQuickLoad);
            TClass* mother_cl;
            mother_cl = bc->GetInfo()->GetClass();
            TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0);
            
            clones = (TClonesArray*) clonesinfo->GetLocalValuePointer(leafcur, 0);
            
            delete clonesinfo;
         }
      }
      cl = clones->GetClass();
   } else if (cl && cl->GetCollectionProxy()) {
      cl = cl->GetCollectionProxy()->GetValueClass();
   }
   if (cl) {
      if (cl->GetClassInfo()) {
         if (cl->GetMethodAllAny(method)) {
            
            
            
            
            TMethodCall* methodcall = new TMethodCall(cl, method, params);
            if (methodcall->GetMethod()) {
               
               
               return kTRUE;
            }
            delete methodcall;
         }
      }
   }
   cl = 0;
   return kFALSE;
}
Int_t TTreeFormula::GetRealInstance(Int_t instance, Int_t codeindex) {
      
      
      
      
      
      Int_t real_instance = 0;
      Int_t virt_dim;
      Bool_t check = kFALSE;
      if (codeindex<0) {
         codeindex = 0;
         check = kTRUE;
      }
      Int_t max_dim = fNdimensions[codeindex];
      if ( max_dim ) {
         virt_dim = 0;
         max_dim--;
         if (!fManager->fMultiVarDim) {
            if (fIndexes[codeindex][0]>=0) {
               real_instance = fIndexes[codeindex][0] * fCumulSizes[codeindex][1];
            } else {
               Int_t local_index;
               local_index = ( instance / fManager->fCumulUsedSizes[virt_dim+1]);
               if (fIndexes[codeindex][0]==-2) {
                  
                  if (check) {
                     Int_t index_real_instance = fVarIndexes[codeindex][0]->GetRealInstance(local_index,-1);
                     if (index_real_instance > fVarIndexes[codeindex][0]->fNdata[0]) {
                        
                        return fNdata[0]+1;
                     }
                  }
                  if (fDidBooleanOptimization && local_index!=0) {
                     
                     fVarIndexes[codeindex][0]->LoadBranches();
                  }
                  local_index = (Int_t)fVarIndexes[codeindex][0]->EvalInstance(local_index);
               }
               real_instance = local_index * fCumulSizes[codeindex][1];
               virt_dim ++;
            }
         } else {
            
            
            
            
            
            
            
            TFormLeafInfo * info = 0;
            if (fHasMultipleVarDim[codeindex]) {
               info = (TFormLeafInfo *)(fDataMembers.At(codeindex));
               
            }
            Int_t local_index;
            switch (fIndexes[codeindex][0]) {
            case -2:
               if (fDidBooleanOptimization && instance!=0) {
                  
                  fVarIndexes[codeindex][0]->LoadBranches();
               }
               local_index = (Int_t)fVarIndexes[codeindex][0]->EvalInstance(instance);
               if (local_index<0) {
                  Error("EvalInstance","Index %s is out of bound (%d) in formula %s",
                        fVarIndexes[codeindex][0]->GetTitle(),
                        local_index,
                        GetTitle());
                  local_index = 0;
               }
               break;
            case -1: {
                  local_index = 0;
                  Int_t virt_accum = 0;
                  Int_t maxloop = fManager->fCumulUsedVarDims->GetSize();
                  do {
                     virt_accum += fManager->fCumulUsedVarDims->GetArray()[local_index];
                     local_index++;
                  } while( instance >= virt_accum && local_index<maxloop);
                  if (local_index==maxloop && (instance >= virt_accum)) {
                     local_index--;
                     instance = fNdata[0]+1; 
                     if (check) return fNdata[0]+1;
                  } else {
                     local_index--;
                     if (fManager->fCumulUsedVarDims->At(local_index)) {
                        instance -= (virt_accum - fManager->fCumulUsedVarDims->At(local_index));
                     } else {
                        instance = fNdata[0]+1; 
                        if (check) return fNdata[0]+1;
                     }
                  }
                  virt_dim ++;
               }
               break;
            default:
               local_index = fIndexes[codeindex][0];
            }
            
            
            if (fManager->fVarDims[kMAXFORMDIM]) {
               fManager->fCumulUsedSizes[kMAXFORMDIM] = fManager->fVarDims[kMAXFORMDIM]->At(local_index);
            } else {
               fManager->fCumulUsedSizes[kMAXFORMDIM] = fManager->fUsedSizes[kMAXFORMDIM];
            }
            for(Int_t d = kMAXFORMDIM-1; d>0; d--) {
               if (fManager->fVarDims[d]) {
                  fManager->fCumulUsedSizes[d] = fManager->fCumulUsedSizes[d+1] * fManager->fVarDims[d]->At(local_index);
               } else {
                  fManager->fCumulUsedSizes[d] = fManager->fCumulUsedSizes[d+1] * fManager->fUsedSizes[d];
               }
            }
            if (info) {
               
               
               info->SetPrimaryIndex(local_index);
               real_instance = 0;
               
               Int_t vdim = info->GetVarDim();
               Int_t isize = info->GetSize(local_index);
               if (fIndexes[codeindex][vdim]>isize) {
                  
                  return fNdata[0]+1;
               }
               fCumulSizes[codeindex][vdim] =  isize*fCumulSizes[codeindex][vdim+1];
               for(Int_t k=vdim -1; k>0; --k) {
                  fCumulSizes[codeindex][k] = fCumulSizes[codeindex][k+1]*fFixedSizes[codeindex][k];
               }
            } else {
               real_instance = local_index * fCumulSizes[codeindex][1];
            }
         }
         if (max_dim>0) {
            for (Int_t dim = 1; dim < max_dim; dim++) {
               if (fIndexes[codeindex][dim]>=0) {
                  real_instance += fIndexes[codeindex][dim] * fCumulSizes[codeindex][dim+1];
               } else {
                  Int_t local_index;
                  if (virt_dim && fManager->fCumulUsedSizes[virt_dim]>1) {
                     local_index = ( ( instance % fManager->fCumulUsedSizes[virt_dim] )
                                     / fManager->fCumulUsedSizes[virt_dim+1]);
                  } else {
                     local_index = ( instance / fManager->fCumulUsedSizes[virt_dim+1]);
                  }
                  if (fIndexes[codeindex][dim]==-2) {
                     
                     if (fDidBooleanOptimization && local_index!=0) {
                        
                        fVarIndexes[codeindex][dim]->LoadBranches();
                     }
                     local_index = (Int_t)fVarIndexes[codeindex][dim]->EvalInstance(local_index);
                     if (local_index<0 ||
                         local_index>=(fCumulSizes[codeindex][dim]/fCumulSizes[codeindex][dim+1])) {
                        Error("EvalInstance","Index %s is out of bound (%d/%d) in formula %s",
                              fVarIndexes[codeindex][dim]->GetTitle(),
                              local_index,
                              (fCumulSizes[codeindex][dim]/fCumulSizes[codeindex][dim+1]),
                              GetTitle());
                        local_index = (fCumulSizes[codeindex][dim]/fCumulSizes[codeindex][dim+1])-1;
                     }
                  }
                  real_instance += local_index * fCumulSizes[codeindex][dim+1];
                  virt_dim ++;
               }
            }
            if (fIndexes[codeindex][max_dim]>=0) {
               real_instance += fIndexes[codeindex][max_dim];
            } else {
               Int_t local_index;
               if (virt_dim && fManager->fCumulUsedSizes[virt_dim]>1) {
                  local_index = instance % fManager->fCumulUsedSizes[virt_dim];
               } else {
                  local_index = instance;
               }
               if (fIndexes[codeindex][max_dim]==-2) {
                  if (fDidBooleanOptimization && local_index!=0) {
                     
                     fVarIndexes[codeindex][max_dim]->LoadBranches();
                  }
                  local_index = (Int_t)fVarIndexes[codeindex][max_dim]->EvalInstance(local_index);
                  if (local_index<0 ||
                         local_index>=fCumulSizes[codeindex][max_dim]) {
                     Error("EvalInstance","Index %s is of out bound (%d/%d) in formula %s",
                           fVarIndexes[codeindex][max_dim]->GetTitle(),
                           local_index,
                           fCumulSizes[codeindex][max_dim],
                           GetTitle());
                     local_index = fCumulSizes[codeindex][max_dim]-1;
                  }
               }
               real_instance += local_index;
            }
         } 
      } 
      return real_instance;
}
TClass* TTreeFormula::EvalClass() const
{
   if (fNoper != 1 || fNcodes <=0 ) return 0;
   return EvalClass(0);
}
TClass* TTreeFormula::EvalClass(Int_t oper) const
{
   TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(oper);
   switch(fLookupType[oper]) {
      case kDirect: {
         if (leaf->IsA()==TLeafObject::Class()) {
            return ((TLeafObject*)leaf)->GetClass();
         } else if ( leaf->IsA()==TLeafElement::Class()) {
            TBranchElement * branch = (TBranchElement*)((TLeafElement*)leaf)->GetBranch();
            TStreamerInfo * info = branch->GetInfo();
            Int_t id = branch->GetID();
            if (id>=0) {
               if (info==0 || info->GetElems()==0) {
                  
                  return 0;
               }
               TStreamerElement* elem = (TStreamerElement*)info->GetElems()[id];
               if (elem==0) {
                  
                  return 0;
               } else {
                  return TClass::GetClass( elem->GetTypeName() );
               }
            } else return TClass::GetClass( branch->GetClassName() );
         } else {
            return 0;
         }
      }
      case kMethod: return 0; 
      case kTreeMember:
      case kDataMember: {
         TObject *obj = fDataMembers.UncheckedAt(oper);
         if (!obj) return 0;
         return ((TFormLeafInfo*)obj)->GetClass();
      }
      default: return 0;
   }
}
void* TTreeFormula::EvalObject(int instance)
{
   if (fNoper != 1 || fNcodes <=0 ) return 0;
   switch (fLookupType[0]) {
      case kIndexOfEntry:
      case kIndexOfLocalEntry:
      case kEntries:
      case kLength:
      case kLengthFunc:
      case kIteration:
      case kEntryList:
         return 0;
   }
   TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
   Int_t real_instance = GetRealInstance(instance,0);
   if (instance==0 || fNeedLoading) {
      fNeedLoading = kFALSE;
      R__LoadBranch(leaf->GetBranch(),
                    leaf->GetBranch()->GetTree()->GetReadEntry(),
                    fQuickLoad);
   }
   else if (real_instance>fNdata[0]) return 0;
   if (fAxis) {
      return 0;
   }
   switch(fLookupType[0]) {
      case kDirect: {
         if (real_instance) {
            Warning("EvalObject","Not yet implement for kDirect and arrays (for %s).\nPlease contact the developers",GetName());
         }
         return leaf->GetValuePointer();
      }
      case kMethod: return GetValuePointerFromMethod(0,leaf);
      case kTreeMember:
      case kDataMember: return ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->GetValuePointer(leaf,real_instance);
      default: return 0;
   }
}
const char* TTreeFormula::EvalStringInstance(Int_t instance)
{
   
   const Int_t kMAXSTRINGFOUND = 10;
   const char *stringStack[kMAXSTRINGFOUND];
   if (fNoper==1 && fNcodes>0 && IsString()) {
      TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
      Int_t real_instance = GetRealInstance(instance,0);
      if (instance==0 || fNeedLoading) {
         fNeedLoading = kFALSE;
         TBranch *branch = leaf->GetBranch();
         R__LoadBranch(branch,branch->GetTree()->GetReadEntry(),fQuickLoad);
      } else if (real_instance>fNdata[0]) return 0;
      if (fLookupType[0]==kDirect) {
         return (char*)leaf->GetValuePointer();
      } else {
         return  (char*)GetLeafInfo(0)->GetValuePointer(leaf,instance);
      }
   }
   EvalInstance(instance,stringStack);
   return stringStack[0];
}
#define TT_EVAL_INIT                                                                            \
   TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);                                                \
                                                                                                \
   const Int_t real_instance = GetRealInstance(instance,0);                                     \
                                                                                                \
   if (instance==0) fNeedLoading = kTRUE;                                                       \
   if (real_instance>fNdata[0]) return 0;                                                       \
                                                                                                \
                           \
                                                                                                \
   if (fNeedLoading) {                                                                          \
      fNeedLoading = kFALSE;                                                                    \
      TBranch *br = leaf->GetBranch();                                                          \
      Long64_t tentry = br->GetTree()->GetReadEntry();                                          \
      R__LoadBranch(br,tentry,fQuickLoad);                                                      \
   }                                                                                            \
                                                                                                \
   if (fAxis) {                                                                                 \
      char * label;                                                                             \
              \
      if (fLookupType[0]==kDirect) {                                                            \
         label = (char*)leaf->GetValuePointer();                                                \
      } else {                                                                                  \
         label = (char*)GetLeafInfo(0)->GetValuePointer(leaf,instance);                         \
      }                                                                                         \
      Int_t bin = fAxis->FindBin(label);                                                        \
      return bin-0.5;                                                                           \
   }
#define TREE_EVAL_INIT                                                                          \
   const Int_t real_instance = GetRealInstance(instance,0);                                     \
                                                                                                \
   if (real_instance>fNdata[0]) return 0;                                                       \
                                                                                                \
   if (fAxis) {                                                                                 \
      char * label;                                                                             \
              \
      label = (char*)GetLeafInfo(0)->GetValuePointer((TLeaf*)0x0,instance);                     \
      Int_t bin = fAxis->FindBin(label);                                                        \
      return bin-0.5;                                                                           \
   }
#define TT_EVAL_INIT_LOOP                                                                       \
   TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(code);                                             \
                                                                                                \
                                 \
   const Int_t real_instance = GetRealInstance(instance,code);                                  \
                                                                                                \
   if (willLoad) {                                                                              \
      TBranch *branch = (TBranch*)fBranches.UncheckedAt(code);                                  \
      if (branch) {                                                                             \
         Long64_t treeEntry = branch->GetTree()->GetReadEntry();                                \
         R__LoadBranch(branch,treeEntry,fQuickLoad);                                            \
      } else if (fDidBooleanOptimization) {                                                     \
         branch = leaf->GetBranch();                                                            \
         Long64_t treeEntry = branch->GetTree()->GetReadEntry();                                \
         if (branch->GetReadEntry() != treeEntry) branch->GetEntry( treeEntry );                \
      }                                                                                         \
   } else {                                                                                     \
                                       \
      if (fDidBooleanOptimization) {                                                            \
         TBranch *br = leaf->GetBranch();                                                       \
         Long64_t treeEntry = br->GetTree()->GetReadEntry();                                    \
         if (br->GetReadEntry() != treeEntry) br->GetEntry( treeEntry );                        \
      }                                                                                         \
   }                                                                                            \
   if (real_instance>fNdata[code]) return 0;
#define TREE_EVAL_INIT_LOOP                                                                     \
                                 \
   const Int_t real_instance = GetRealInstance(instance,code);                                  \
                                                                                                \
   if (real_instance>fNdata[code]) return 0;
namespace {
   Double_t Summing(TTreeFormula *sum) {
      Int_t len = sum->GetNdata();
      Double_t res = 0;
      for (int i=0; i<len; ++i) res += sum->EvalInstance(i);
      return res;
   }
}
Double_t TTreeFormula::EvalInstance(Int_t instance, const char *stringStackArg[])
{
   if (TestBit(kMissingLeaf)) return 0;
   if (fNoper == 1 && fNcodes > 0) {
      switch (fLookupType[0]) {
         case kDirect:     {
            TT_EVAL_INIT;
            Double_t result = leaf->GetValue(real_instance);
            return result;
         }
         case kMethod:     {
            TT_EVAL_INIT;
            ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->SetBranch(leaf->GetBranch());
            return GetValueFromMethod(0,leaf);
         }
         case kDataMember: {
            TT_EVAL_INIT;
            ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->SetBranch(leaf->GetBranch());
            return ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->GetValue(leaf,real_instance);
         }
         case kTreeMember: {
            TREE_EVAL_INIT;
            return ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->GetValue((TLeaf*)0x0,real_instance);
         }
         case kIndexOfEntry: return (Double_t)fTree->GetReadEntry();
         case kIndexOfLocalEntry: return (Double_t)fTree->GetTree()->GetReadEntry();
         case kEntries:      return (Double_t)fTree->GetEntries();
         case kLength:       return fManager->fNdata;
         case kLengthFunc:   return ((TTreeFormula*)fAliases.UncheckedAt(0))->GetNdata();
         case kIteration:    return instance;
         case kSum:          return Summing((TTreeFormula*)fAliases.UncheckedAt(0));
         case kEntryList: {
            TEntryList *elist = (TEntryList*)fMethods.At(0);
            return elist->Contains(fTree->GetTree()->GetReadEntry());
         }
         case -1: break;
      }
      switch (fCodes[0]) {
         case -2: {
            TCutG *gcut = (TCutG*)fMethods.At(0);
            TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
            TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
            Double_t xcut = fx->EvalInstance(instance);
            Double_t ycut = fy->EvalInstance(instance);
            return gcut->IsInside(xcut,ycut);
         }
         case -1: {
            TCutG *gcut = (TCutG*)fMethods.At(0);            TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
            return fx->EvalInstance(instance);
         }
         default: return 0;
      }
   }
   Double_t tab[kMAXFOUND];
   const Int_t kMAXSTRINGFOUND = 10;
   const char *stringStackLocal[kMAXSTRINGFOUND];
   const char **stringStack = stringStackArg?stringStackArg:stringStackLocal;
   const bool willLoad = (instance==0 || fNeedLoading); fNeedLoading = kFALSE;
   if (willLoad) fDidBooleanOptimization = kFALSE;
   Int_t pos  = 0;
   Int_t pos2 = 0;
   for (Int_t i=0; i<fNoper ; ++i) {
      const Int_t oper = GetOper()[i];
      const Int_t newaction = oper >> kTFOperShift;
      if (newaction<kDefinedVariable) {
         
         
         if (newaction==kConstant) { pos++; tab[pos-1] = fConst[(oper & kTFOperMask)]; continue; }
         switch(newaction) {
            case kEnd        : return tab[0];
            case kAdd        : pos--; tab[pos-1] += tab[pos]; continue;
            case kSubstract  : pos--; tab[pos-1] -= tab[pos]; continue;
            case kMultiply   : pos--; tab[pos-1] *= tab[pos]; continue;
            case kDivide     : pos--; if (tab[pos] == 0) tab[pos-1] = 0; 
                                      else               tab[pos-1] /= tab[pos];
                                      continue;
            case kModulo     : {pos--;
                                Long64_t int1((Long64_t)tab[pos-1]);
                                Long64_t int2((Long64_t)tab[pos]);
                                tab[pos-1] = Double_t(int1%int2);
                                continue;}
            case kcos  : tab[pos-1] = TMath::Cos(tab[pos-1]); continue;
            case ksin  : tab[pos-1] = TMath::Sin(tab[pos-1]); continue;
            case ktan  : if (TMath::Cos(tab[pos-1]) == 0) {tab[pos-1] = 0;} 
                         else tab[pos-1] = TMath::Tan(tab[pos-1]);
                         continue;
            case kacos : if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;} 
                         else tab[pos-1] = TMath::ACos(tab[pos-1]);
                         continue;
            case kasin : if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;} 
                         else tab[pos-1] = TMath::ASin(tab[pos-1]);
                         continue;
            case katan : tab[pos-1] = TMath::ATan(tab[pos-1]); continue;
            case kcosh : tab[pos-1] = TMath::CosH(tab[pos-1]); continue;
            case ksinh : tab[pos-1] = TMath::SinH(tab[pos-1]); continue;
            case ktanh : if (TMath::CosH(tab[pos-1]) == 0) {tab[pos-1] = 0;} 
                         else tab[pos-1] = TMath::TanH(tab[pos-1]);
                         continue;
            case kacosh: if (tab[pos-1] < 1) {tab[pos-1] = 0;} 
                         else tab[pos-1] = TMath::ACosH(tab[pos-1]);
                         continue;
            case kasinh: tab[pos-1] = TMath::ASinH(tab[pos-1]); continue;
            case katanh: if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;} 
                     else tab[pos-1] = TMath::ATanH(tab[pos-1]); continue;
            case katan2: pos--; tab[pos-1] = TMath::ATan2(tab[pos-1],tab[pos]); continue;
            case kfmod : pos--; tab[pos-1] = fmod(tab[pos-1],tab[pos]); continue;
            case kpow  : pos--; tab[pos-1] = TMath::Power(tab[pos-1],tab[pos]); continue;
            case ksq   : tab[pos-1] = tab[pos-1]*tab[pos-1]; continue;
            case ksqrt : tab[pos-1] = TMath::Sqrt(TMath::Abs(tab[pos-1])); continue;
            case kstrstr : pos2 -= 2; pos++;if (strstr(stringStack[pos2],stringStack[pos2+1])) tab[pos-1]=1;
                                        else tab[pos-1]=0; continue;
            case kmin : pos--; tab[pos-1] = TMath::Min(tab[pos-1],tab[pos]); continue;
            case kmax : pos--; tab[pos-1] = TMath::Max(tab[pos-1],tab[pos]); continue;
            case klog  : if (tab[pos-1] > 0) tab[pos-1] = TMath::Log(tab[pos-1]);
                         else {tab[pos-1] = 0;} 
                          continue;
            case kexp  : { Double_t dexp = tab[pos-1];
                           if (dexp < -700) {tab[pos-1] = 0; continue;}
                           if (dexp >  700) {tab[pos-1] = TMath::Exp(700); continue;}
                           tab[pos-1] = TMath::Exp(dexp); continue;
                         }
            case klog10: if (tab[pos-1] > 0) tab[pos-1] = TMath::Log10(tab[pos-1]);
                         else {tab[pos-1] = 0;} 
                         continue;
            case kpi   : pos++; tab[pos-1] = TMath::ACos(-1); continue;
            case kabs  : tab[pos-1] = TMath::Abs(tab[pos-1]); continue;
            case ksign : if (tab[pos-1] < 0) tab[pos-1] = -1; else tab[pos-1] = 1; continue;
            case kint  : tab[pos-1] = Double_t(Int_t(tab[pos-1])); continue;
            case kSignInv: tab[pos-1] = -1 * tab[pos-1]; continue;
            case krndm : pos++; tab[pos-1] = gRandom->Rndm(1); continue;
            case kAnd  : pos--; if (tab[pos-1]!=0 && tab[pos]!=0) tab[pos-1]=1;
                                else tab[pos-1]=0; continue;
            case kOr   : pos--; if (tab[pos-1]!=0 || tab[pos]!=0) tab[pos-1]=1;
                                else tab[pos-1]=0; continue;
            case kEqual      : pos--; tab[pos-1] = (tab[pos-1] == tab[pos]) ? 1 : 0; continue;
            case kNotEqual   : pos--; tab[pos-1] = (tab[pos-1] != tab[pos]) ? 1 : 0; continue;
            case kLess       : pos--; tab[pos-1] = (tab[pos-1] <  tab[pos]) ? 1 : 0; continue;
            case kGreater    : pos--; tab[pos-1] = (tab[pos-1] >  tab[pos]) ? 1 : 0; continue;
            case kLessThan   : pos--; tab[pos-1] = (tab[pos-1] <= tab[pos]) ? 1 : 0; continue;
            case kGreaterThan: pos--; tab[pos-1] = (tab[pos-1] >= tab[pos]) ? 1 : 0; continue;
            case kNot        :        tab[pos-1] = (tab[pos-1] !=        0) ? 0 : 1; continue;
            case kStringEqual : pos2 -= 2; pos++; if (!strcmp(stringStack[pos2+1],stringStack[pos2])) tab[pos-1]=1;
                                                  else tab[pos-1]=0; continue;
            case kStringNotEqual: pos2 -= 2; pos++;if (strcmp(stringStack[pos2+1],stringStack[pos2])) tab[pos-1]=1;
                                                   else tab[pos-1]=0; continue;
            case kBitAnd    : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) & ((Int_t) tab[pos]); continue;
            case kBitOr     : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) | ((Int_t) tab[pos]); continue;
            case kLeftShift : pos--; tab[pos-1]= ((Int_t) tab[pos-1]) <<((Int_t) tab[pos]); continue;
            case kRightShift: pos--; tab[pos-1]= ((Int_t) tab[pos-1]) >>((Int_t) tab[pos]); continue;
            case kStringConst: {
               
               pos2++; stringStack[pos2-1] = (char*)fExpr[i].Data();
               continue;
            }
            case kBoolOptimize: {
               
               int param = (oper & kTFOperMask);
               Bool_t skip = kFALSE;
               int op = param % 10; 
               if (op == 1 && (!tab[pos-1]) ) {
                  
                  skip = kTRUE;
                  
                  
                  tab[pos-1] = 0;
               } else if (op == 2 && tab[pos-1] ) {
                  
                  skip = kTRUE;
                  
                  
                  tab[pos-1] = 1;
               }
               if (skip) {
                  int toskip = param / 10;
                  i += toskip;
                  if (willLoad) fDidBooleanOptimization = kTRUE;
              }
               continue;
            }
            case kFunctionCall: {
               
               int param = (oper & kTFOperMask);
               int fno   = param / 1000;
               int nargs = param % 1000;
               
               TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
               
               TString args;
               if (nargs) {
                  UInt_t argloc = pos-nargs;
                  for(Int_t j=0;j<nargs;j++,argloc++,pos--) {
                     if (TMath::IsNaN(tab[argloc])) {
                        
                        
                        args += "(double)(0x8000000000000)";
                     } else {
                        args += tab[argloc];
                     }
                     args += ',';
                  }
                  args.Remove(args.Length()-1);
               }
               pos++;
               Double_t ret;
               method->Execute(args,ret);
               tab[pos-1] = ret; 
               continue;
            }
         }
      } else {
         
         
         if (newaction == kDefinedVariable) {
            const Int_t code = (oper & kTFOperMask);
            const Int_t lookupType = fLookupType[code];
            switch (lookupType) {
               case kIndexOfEntry: tab[pos++] = (Double_t)fTree->GetReadEntry(); continue;
               case kIndexOfLocalEntry: tab[pos++] = (Double_t)fTree->GetTree()->GetReadEntry(); continue;
               case kEntries:      tab[pos++] = (Double_t)fTree->GetEntries(); continue;
               case kLength:       tab[pos++] = fManager->fNdata; continue;
               case kLengthFunc:   tab[pos++] = ((TTreeFormula*)fAliases.UncheckedAt(i))->GetNdata(); continue;
               case kIteration:    tab[pos++] = instance; continue;
               case kSum:          tab[pos++] = Summing((TTreeFormula*)fAliases.UncheckedAt(i)); continue;
               case kDirect:     { TT_EVAL_INIT_LOOP; tab[pos++] = leaf->GetValue(real_instance); continue; }
               case kMethod:     { TT_EVAL_INIT_LOOP; tab[pos++] = GetValueFromMethod(code,leaf); continue; }
               case kDataMember: { TT_EVAL_INIT_LOOP; tab[pos++] = ((TFormLeafInfo*)fDataMembers.UncheckedAt(code))->
                                          GetValue(leaf,real_instance); continue; }
               case kTreeMember: { TREE_EVAL_INIT_LOOP; tab[pos++] = ((TFormLeafInfo*)fDataMembers.UncheckedAt(code))->
                                          GetValue((TLeaf*)0x0,real_instance); continue; }
               case kEntryList: { TEntryList *elist = (TEntryList*)fMethods.At(code);
                  tab[pos++] = elist->Contains(fTree->GetReadEntry());
                  continue;}
               case -1: break;
               default: tab[pos++] = 0; continue;
            }
            switch (fCodes[code]) {
               case -2: {
                  TCutG *gcut = (TCutG*)fMethods.At(code);
                  TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
                  TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
                  Double_t xcut = fx->EvalInstance(instance);
                  Double_t ycut = fy->EvalInstance(instance);
                  tab[pos++] = gcut->IsInside(xcut,ycut);
                  continue;
               }
               case -1: {
                  TCutG *gcut = (TCutG*)fMethods.At(code);
                  TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
                  tab[pos++] = fx->EvalInstance(instance);
                  continue;
               }
               default: {
                  tab[pos++] = 0;
                  continue;
               }
            }
         }
         switch(newaction) {
            
            case kAlias: {
               int aliasN = i;
               TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(aliasN));
               R__ASSERT(subform);
               Double_t param = subform->EvalInstance(instance);
               tab[pos] = param; pos++;
               continue;
            }
            
            case kAliasString: {
               int aliasN = i;
               TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(aliasN));
               R__ASSERT(subform);
               pos2++;
               stringStack[pos2-1] = subform->EvalStringInstance(instance);
               continue;
            }
            
            case kAlternate: {
               int alternateN = i;
               TTreeFormula *primary = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN));
               
               if (instance < primary->GetNdata()) {
                  Double_t param = primary->EvalInstance(instance);
                  ++i; 
                  tab[pos] = param; pos++;
               } else {
                  
                  
                  
               }
               continue;
            }
            case kAlternateString: {
               int alternateN = i;
               TTreeFormula *primary = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN));
               
               if (instance < primary->GetNdata()) {
                  pos2++;
                  stringStack[pos2-1] = primary->EvalStringInstance(instance);
                  ++i; 
               } else {
                  
                  
                  
               }
               continue;
            }
            
            case kDefinedString: {
               Int_t string_code = (oper & kTFOperMask);
               TLeaf *leafc = (TLeaf*)fLeaves.UncheckedAt(string_code);
               
               const Int_t real_instance = GetRealInstance(instance,string_code);
               if (instance==0 || fNeedLoading) {
                  fNeedLoading = kFALSE;
                  TBranch *branch = leafc->GetBranch();
                  Long64_t readentry = branch->GetTree()->GetReadEntry();
                  R__LoadBranch(branch,readentry,fQuickLoad);
               } else {
                  
                  
                  
                  if (fDidBooleanOptimization) {
                     TBranch *br = leafc->GetBranch();
                     Long64_t treeEntry = br->GetTree()->GetReadEntry();
                     R__LoadBranch(br,treeEntry,kTRUE);
                  }
                  if (real_instance>fNdata[string_code]) return 0;
               }
               pos2++;
               if (fLookupType[string_code]==kDirect) {
                  stringStack[pos2-1] = (char*)leafc->GetValuePointer();
               } else {
                  stringStack[pos2-1] = (char*)GetLeafInfo(string_code)->GetValuePointer(leafc,real_instance);
               }
               continue;
            }
         }
      }
      R__ASSERT(i<fNoper);
   }
   Double_t result = tab[0];
   return result;
}
TFormLeafInfo *TTreeFormula::GetLeafInfo(Int_t code) const
{
   return (TFormLeafInfo *)fDataMembers.UncheckedAt(code);
}
TLeaf *TTreeFormula::GetLeaf(Int_t n) const
{
   return (TLeaf*)fLeaves.UncheckedAt(n);
}
TMethodCall *TTreeFormula::GetMethodCall(Int_t code) const
{
   return (TMethodCall *)fMethods.UncheckedAt(code);
}
Int_t TTreeFormula::GetNdata()
{
  return fManager->GetNdata();
}
Double_t TTreeFormula::GetValueFromMethod(Int_t i, TLeaf* leaf) const
{
   
   TMethodCall* m = GetMethodCall(i);
   if (!m) {
      return 0.0;
   }
   void* thisobj = 0;
   if (leaf->InheritsFrom("TLeafObject")) {
      thisobj = ((TLeafObject*) leaf)->GetObject();
   } else {
      TBranchElement* branch = (TBranchElement*) ((TLeafElement*) leaf)->GetBranch();
      Int_t id = branch->GetID();
      
      Int_t offset = 0;
      if (id > -1) {
         TStreamerInfo* info = branch->GetInfo();
         if (info) {
            offset = info->GetOffsets()[id];
         } else {
            Warning("GetValueFromMethod", "No streamer info for branch %s.", branch->GetName());
         }
      }
      if (id < 0) {
         char* address = branch->GetObject();
         thisobj = address;
      } else {
         
         char* address = branch->GetObject();
         if (address) {
            thisobj = *((char**) (address + offset));
         } else {
            
            thisobj = branch->GetObject();
         }
      }
   }
   TMethodCall::EReturnType r = m->ReturnType();
   if (r == TMethodCall::kLong) {
      Long_t l;
      m->Execute(thisobj, l);
      return (Double_t) l;
   }
   if (r == TMethodCall::kDouble) {
      Double_t d;
      m->Execute(thisobj, d);
      return d;
   }
   m->Execute(thisobj);
   return 0;
}
void* TTreeFormula::GetValuePointerFromMethod(Int_t i, TLeaf* leaf) const
{
   
   TMethodCall* m = GetMethodCall(i);
   if (!m) {
      return 0;
   }
   void* thisobj;
   if (leaf->InheritsFrom("TLeafObject")) {
      thisobj = ((TLeafObject*) leaf)->GetObject();
   } else {
      TBranchElement* branch = (TBranchElement*) ((TLeafElement*) leaf)->GetBranch();
      Int_t id = branch->GetID();
      Int_t offset = 0;
      if (id > -1) {
         TStreamerInfo* info = branch->GetInfo();
         if (info) {
            offset = info->GetOffsets()[id];
         } else {
            Warning("GetValuePointerFromMethod", "No streamer info for branch %s.", branch->GetName());
         }
      }
      if (id < 0) {
         char* address = branch->GetObject();
         thisobj = address;
      } else {
         
         char* address = branch->GetObject();
         if (address) {
            thisobj = *((char**) (address + offset));
         } else {
            
            thisobj = branch->GetObject();
         }
      }
   }
   TMethodCall::EReturnType r = m->ReturnType();
   if (r == TMethodCall::kLong) {
      Long_t l;
      m->Execute(thisobj, l);
      return 0;
   }
   if (r == TMethodCall::kDouble) {
      Double_t d;
      m->Execute(thisobj, d);
      return 0;
   }
   if (r == TMethodCall::kOther) {
      char* c;
      m->Execute(thisobj, &c);
      return c;
   }
   m->Execute(thisobj);
   return 0;
}
Bool_t TTreeFormula::IsInteger(Bool_t fast) const
{
   
   
   
   
   if (fast) {
      if (TestBit(kIsInteger)) return kTRUE;
      else                     return kFALSE;
   }
   
   if (fNoper==2 && GetAction(0)==kAlternate) {
      TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
      R__ASSERT(subform);
      return subform->IsInteger(kFALSE);
   }
   if (fNoper > 1) return kFALSE;
   if (GetAction(0)==kAlias) {
      TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
      R__ASSERT(subform);
      return subform->IsInteger(kFALSE);
   }
   if (fLeaves.GetEntries() != 1) {
      switch (fLookupType[0]) {
         case kIndexOfEntry:
         case kIndexOfLocalEntry:
         case kEntries:
         case kLength:
         case kLengthFunc:
         case kIteration:
           return kTRUE;
         case kSum:
         case kEntryList:
         default:
           return kFALSE;
      }
   }
   if (EvalClass()==TBits::Class()) return kTRUE;
   return IsLeafInteger(0);
}
Bool_t TTreeFormula::IsLeafInteger(Int_t code) const
{
   
   
   
   TLeaf *leaf = (TLeaf*)fLeaves.At(code);
   if (!leaf) {
      switch (fLookupType[code]) {
         case kIndexOfEntry:
         case kIndexOfLocalEntry:
         case kEntries:
         case kLength:
         case kLengthFunc:
         case kIteration:
           return kTRUE;
         case kSum:
         case kEntryList:
         default:
           return kFALSE;
      }
   }
   if (fAxis) return kTRUE;
   TFormLeafInfo * info;
   switch (fLookupType[code]) {
      case kMethod:
      case kTreeMember:
      case kDataMember:
         info = GetLeafInfo(code);
         return info->IsInteger();
      case kDirect:
         break;
   }
   if (!strcmp(leaf->GetTypeName(),"Int_t"))    return kTRUE;
   if (!strcmp(leaf->GetTypeName(),"Short_t"))  return kTRUE;
   if (!strcmp(leaf->GetTypeName(),"UInt_t"))   return kTRUE;
   if (!strcmp(leaf->GetTypeName(),"UShort_t")) return kTRUE;
   if (!strcmp(leaf->GetTypeName(),"Bool_t"))   return kTRUE;
   if (!strcmp(leaf->GetTypeName(),"Char_t"))   return kTRUE;
   if (!strcmp(leaf->GetTypeName(),"UChar_t"))  return kTRUE;
   return kFALSE;
}
Bool_t TTreeFormula::IsString() const
{
   
   return TestBit(kIsCharacter) || (fNoper==1 && IsString(0));
}
Bool_t TTreeFormula::IsString(Int_t oper) const
{
   
   
   
   if (TFormula::IsString(oper)) return kTRUE;
   if (GetAction(oper)==kDefinedString) return kTRUE;
   if (GetAction(oper)==kAliasString) return kTRUE;
   if (GetAction(oper)==kAlternateString) return kTRUE;
   return kFALSE;
}
Bool_t  TTreeFormula::IsLeafString(Int_t code) const
{
   
   TLeaf *leaf = (TLeaf*)fLeaves.At(code);
   TFormLeafInfo * info;
   if (fLookupType[code]==kTreeMember) {
      info = GetLeafInfo(code);
      return info->IsString();
   }
   switch(fLookupType[code]) {
      case kDirect:
         if ( !leaf->IsUnsigned() && (leaf->InheritsFrom("TLeafC") || leaf->InheritsFrom("TLeafB") ) ) {
            
            if (leaf->GetLenStatic() > 1) return kTRUE;
            
            
            if (leaf->GetLeafCount()) {
               const char* indexname = leaf->GetLeafCount()->GetName();
               if (indexname[strlen(indexname)-1] == '_' ) {
                  
                  return kFALSE;
               } else {
                  
                  return kTRUE;
               }
               }
         } else if (leaf->InheritsFrom("TLeafElement")) {
            TBranchElement * br = (TBranchElement*)leaf->GetBranch();
            Int_t bid = br->GetID();
            if (bid < 0) return kFALSE;
            if (br->GetInfo()==0 || br->GetInfo()->GetElems()==0) {
               
               
               
               return kFALSE;
            }
            TStreamerElement * elem = (TStreamerElement*) br->GetInfo()->GetElems()[bid];
            if (!elem) {
               
               
               
               return kFALSE;
            }
            if (elem->GetNewType()== TStreamerInfo::kOffsetL +kChar_t) {
               
               if (fIndexes[code][fNdimensions[code]-1] != -1) return kFALSE;
               return kTRUE;
            }
            if ( elem->GetNewType()== TStreamerInfo::kCharStar) {
               
               if (fNdimensions[code] && fIndexes[code][fNdimensions[code]-1] != -1) return kFALSE;
               return kTRUE;
            }
            return kFALSE;
         } else {
            return kFALSE;
         }
      case kMethod:
         
         
         return kFALSE;
      case kDataMember:
         info = GetLeafInfo(code);
         return info->IsString();
      default:
         return kFALSE;
   }
}
char *TTreeFormula::PrintValue(Int_t mode) const
{
   return PrintValue(mode,0);
}
char *TTreeFormula::PrintValue(Int_t mode, Int_t instance, const char *decform) const
{
   const int kMAXLENGTH = 1024;
   static char value[kMAXLENGTH];
   if (mode == -2) {
      for (int i = 0; i < kMAXLENGTH-1; i++)
         value[i] = '*';
      value[kMAXLENGTH-1] = 0;
   } else if (mode == -1)
      sprintf(value, "%s", GetTitle());
   if (fNstring && fNval==0 && fNoper==1) {
      if (mode == 0) {
         const char * val = 0;
         if (fLookupType[0]==kTreeMember) {
            val = (char*)GetLeafInfo(0)->GetValuePointer((TLeaf*)0x0,instance);
         } else {
            TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
            TBranch *branch = leaf->GetBranch();
            Long64_t readentry = branch->GetTree()->GetReadEntry();
            R__LoadBranch(branch,readentry,fQuickLoad);
            if (fLookupType[0]==kDirect) {
               val = (const char*)leaf->GetValuePointer();
            } else {
               val = ((TTreeFormula*)this)->EvalStringInstance(instance);
            }
         }
         if (val) {
            strncpy(value, val, kMAXLENGTH-1);
         } else {
            
         }
         value[kMAXLENGTH-1] = 0;
      }
   } else {
      if (mode == 0) {
         
         
         Int_t real_instance = ((TTreeFormula*)this)->GetRealInstance(instance,-1);
         if (real_instance<fNdata[0]) {
            Ssiz_t len = strlen(decform);
            Bool_t longer  = kFALSE;
            Bool_t shorter = kFALSE;
            char *expo = 0;
            if (len>2) {
               switch (decform[len-2]) {
                  case 'l':
                  case 'L': longer = kTRUE; break;
                  case 'h': shorter = kTRUE; break;
               }
            }
            switch(decform[len-1]) {
               case 'c':
               case 'd':
               case 'i':
               case 'o':
               case 'x':
               case 'X':
               case 'u':
                  {
                     if (shorter) sprintf(value,Form("%%%s",decform),(short)((TTreeFormula*)this)->EvalInstance(instance));
                     else if (longer) sprintf(value,Form("%%%s",decform),(int)((TTreeFormula*)this)->EvalInstance(instance));
                     else sprintf(value,Form("%%%s",decform),(long)((TTreeFormula*)this)->EvalInstance(instance));
                     break;
                  }
               case 'f':
               case 'e':
               case 'E':
               case 'g':
               case 'G':
                  {
                     if (longer) sprintf(value,Form("%%%s",decform),(long double)((TTreeFormula*)this)->EvalInstance(instance));
                     else sprintf(value,Form("%%%s",decform),((TTreeFormula*)this)->EvalInstance(instance));
                     expo = strchr(value,'e');
                     break;
                  }
               default:
                  sprintf(value,Form("%%%sg",decform),((TTreeFormula*)this)->EvalInstance(instance));
                  expo = strchr(value,'e');
            }
            if (expo) {
               
               
               UInt_t len = atoi(decform);
               if (strlen(value)>len) {
                  UInt_t off = strlen(value)-len;
                  char *start = expo - off;
                  UInt_t vlen = strlen(expo);
                  for(UInt_t z=0;z<=vlen;++z) {
                     start[z] = expo[z];
                  }
                  
               }
            }
         } else {
            sprintf(value,Form(" %%%sc",decform),' ');
         }
      }
   }
   return &value[0];
}
void TTreeFormula::ResetLoading()
{
   
   fNeedLoading = kTRUE;
   fDidBooleanOptimization = kFALSE;
}
void TTreeFormula::SetAxis(TAxis *axis)
{
   
   if (!axis) {fAxis = 0; return;}
   if (TestBit(kIsCharacter)) {
      fAxis = axis;
      if (fNoper==1 && GetAction(0)==kAliasString){
         TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
         R__ASSERT(subform);
         subform->SetAxis(axis);
      } else if (fNoper==2 && GetAction(0)==kAlternateString){
         TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
         R__ASSERT(subform);
         subform->SetAxis(axis);
      }
   }
   if (IsInteger()) axis->SetBit(TAxis::kIsInteger);
}
void TTreeFormula::Streamer(TBuffer &R__b)
{
   
   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         R__b.ReadClassBuffer(TTreeFormula::Class(), this, R__v, R__s, R__c);
         return;
      }
      
      TFormula::Streamer(R__b);
      R__b >> fTree;
      R__b >> fNcodes;
      R__b.ReadFastArray(fCodes, fNcodes);
      R__b >> fMultiplicity;
      Int_t instance;
      R__b >> instance; 
      R__b >> fNindex;
      if (fNindex) {
         fLookupType = new Int_t[fNindex];
         R__b.ReadFastArray(fLookupType, fNindex);
      }
      fMethods.Streamer(R__b);
      
   } else {
      R__b.WriteClassBuffer(TTreeFormula::Class(),this);
   }
}
void TTreeFormula::UpdateFormulaLeaves()
{
   
   
   
   
   
   
   char names[512];
   Int_t nleaves = fLeafNames.GetEntriesFast();
   ResetBit( kMissingLeaf );
   for (Int_t i=0;i<nleaves;i++) {
      if (!fTree) break;
      if (!fLeafNames[i]) continue;
      sprintf(names,"%s/%s",fLeafNames[i]->GetTitle(),fLeafNames[i]->GetName());
      TLeaf *leaf = fTree->GetLeaf(names);
      fLeaves[i] = leaf;
      if (fBranches[i] && leaf) fBranches[i]=leaf->GetBranch();
      if (leaf==0) SetBit( kMissingLeaf );
   }
   for (Int_t j=0; j<kMAXCODES; j++) {
      for (Int_t k = 0; k<kMAXFORMDIM; k++) {
         if (fVarIndexes[j][k]) {
            fVarIndexes[j][k]->UpdateFormulaLeaves();
         }
      }
      if (fLookupType[j]==kDataMember || fLookupType[j]==kTreeMember) GetLeafInfo(j)->Update();
      if (j<fNval && fCodes[j]<0) {
         TCutG *gcut = (TCutG*)fMethods.At(j);
         if (gcut) {
           TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
           TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
           if (fx) fx->UpdateFormulaLeaves();
           if (fy) fy->UpdateFormulaLeaves();
         }
      }
   }
   for(Int_t k=0;k<fNoper;k++) {
      const Int_t oper = GetOper()[k];
      switch(oper >> kTFOperShift) {
         case kAlias:
         case kAliasString:
         case kAlternate:
         case kAlternateString:
         {
            TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(k));
            R__ASSERT(subform);
            subform->UpdateFormulaLeaves();
            break;
         }
         case kDefinedVariable:
         {
            Int_t code = GetActionParam(k);
            if (fCodes[code]==0) switch(fLookupType[code]) {
               case kLengthFunc:
               case kSum:
               {
                  TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(k));
                  R__ASSERT(subform);
                  subform->UpdateFormulaLeaves();
                  break;
               }
               default:
                  break;
            }
         }
         default:
            break;
      }
   }
}
void TTreeFormula::ResetDimensions() {
   
   Int_t i,k;
   
   
   
   TIter next(fDimensionSetup);
   Int_t last_code = -1;
   Int_t virt_dim = 0;
   for(TDimensionInfo * info; (info = (TDimensionInfo*)next()); ) {
      if (last_code!=info->fCode) {
         
         
         
         virt_dim = 0;
         last_code = info->fCode;
         fNdimensions[last_code] = 0;
      }
      if (GetAction(info->fOper)==kDefinedString) {
         
         
         TDimensionInfo *nextinfo = (TDimensionInfo*)next();
         while(nextinfo && nextinfo->fCode==info->fCode) {
            DefineDimensions(info->fCode,info->fSize, info->fMultiDim, virt_dim);
            nextinfo = (TDimensionInfo*)next();
         }
         if (!nextinfo) break;
         info = nextinfo;
         virt_dim = 0;
         last_code = info->fCode;
         fNdimensions[last_code] = 0;
         info->fSize = 1; 
      }
      DefineDimensions(info->fCode,info->fSize, info->fMultiDim, virt_dim);
   }
   fMultiplicity = 0;
   for(i=0;i<fNoper;i++) {
      Int_t action = GetAction(i);
      if (action==kAlias || action==kAliasString) {
         TTreeFormula *subform = dynamic_cast<TTreeFormula*>(fAliases.UncheckedAt(i));
         R__ASSERT(subform);
         switch(subform->GetMultiplicity()) {
            case 0: break;
            case 1: fMultiplicity = 1; break;
            case 2: if (fMultiplicity!=1) fMultiplicity = 2; break;
         }
         fManager->Add(subform);
         
         
         continue;
      }
      if (action==kDefinedString) {
      
         
         
         
         
         
         
         
         
         
         
      }
   }
   for (i=0;i<fNcodes;i++) {
      if (fCodes[i] < 0) {
         TCutG *gcut = (TCutG*)fMethods.At(i);
         if (!gcut) continue;
         TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
         TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
         if (fx) {
            switch(fx->GetMultiplicity()) {
               case 0: break;
               case 1: fMultiplicity = 1; break;
               case 2: if (fMultiplicity!=1) fMultiplicity = 2; break;
            }
            fManager->Add(fx);
         }
         if (fy) {
            switch(fy->GetMultiplicity()) {
               case 0: break;
               case 1: fMultiplicity = 1; break;
               case 2: if (fMultiplicity!=1) fMultiplicity = 2; break;
            }
            fManager->Add(fy);
         }
         continue;
      }
      if (fLookupType[i]==kIteration) {
          fMultiplicity = 1;
          continue;
      }
      TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
      if (!leaf) continue;
      
      
      
      
      
      
      if (leaf->GetLeafCount()) {
         
         fMultiplicity = 1;
      } else if (fLookupType[i]==kDataMember) {
         TFormLeafInfo * leafinfo = GetLeafInfo(i);
         TStreamerElement * elem = leafinfo->fElement;
         if (fMultiplicity!=1) {
            if (leafinfo->HasCounter() ) fMultiplicity = 1;
            else if (elem && elem->GetArrayDim()>0) fMultiplicity = 2;
            else if (leaf->GetLenStatic()>1) fMultiplicity = 2;
         }
      } else {
        if (leaf->GetLenStatic()>1 && fMultiplicity!=1) fMultiplicity = 2;
        else {
           
           
           TTree *realtree = fTree->GetTree();
           TTree *tleaf = leaf->GetBranch()->GetTree();
           if (tleaf && tleaf != realtree && tleaf->GetTreeIndex()) {
              
              fMultiplicity = 1;
           }
        }
      }
      Int_t virt_dim = 0;
      for (k = 0; k < fNdimensions[i]; k++) {
         
         
         if ( (fCumulSizes[i][k]>=0) && (fIndexes[i][k] >= fCumulSizes[i][k]) ) {
            
            fManager->CancelDimension(virt_dim); 
         }
         if ( fIndexes[i][k] < 0 ) virt_dim++;
         fFixedSizes[i][k] = fCumulSizes[i][k];
      }
      
      for (k = fNdimensions[i]; (k > 0); k--) {
         
         
         
         fCumulSizes[i][k-1] *= TMath::Abs(fCumulSizes[i][k]);
      }
      
      
      if (fCumulSizes[i][0]>0) fNdata[i] = fCumulSizes[i][0];
      
      
      
   }
}
void TTreeFormula::LoadBranches()
{
   
   Int_t i;
   for (i=0; i<fNoper ; ++i) {
      TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
      if (leaf==0) continue;
      TBranch *br = leaf->GetBranch();
      Long64_t treeEntry = br->GetTree()->GetReadEntry();
      R__LoadBranch(br,treeEntry,kTRUE);
      TTreeFormula *alias = (TTreeFormula*)fAliases.UncheckedAt(i);
      if (alias) alias->LoadBranches();
      Int_t max_dim = fNdimensions[i];
      for (Int_t dim = 0; dim < max_dim; ++dim) {
         if (fVarIndexes[i][dim]) fVarIndexes[i][dim]->LoadBranches();
      }
   }
}
Bool_t TTreeFormula::LoadCurrentDim() {
   
   Int_t size;
   Bool_t outofbounds = kFALSE;
   for (Int_t i=0;i<fNcodes;i++) {
      if (fCodes[i] < 0) continue;
      
      
      
      
      
      
      
      
      
      
      TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
      if (!leaf) continue;
      TTree *realtree = fTree->GetTree();
      TTree *tleaf = leaf->GetBranch()->GetTree();
      if (tleaf && tleaf != realtree && tleaf->GetTreeIndex()) {
         if (tleaf->GetReadEntry()==-1) {
            fNdata[i] = 0;
            outofbounds = kTRUE;
            continue;
         } else {
            fNdata[i] = 1;
         }
      }
      Bool_t hasBranchCount2 = kFALSE;
      if (leaf->GetLeafCount()) {
         TLeaf* leafcount = leaf->GetLeafCount();
         TBranch *branchcount = leafcount->GetBranch();
         TFormLeafInfo * info = 0;
         if (leaf->IsA() == TLeafElement::Class()) {
            
            
            Long64_t readentry = leaf->GetBranch()->GetTree()->GetReadEntry();
            if (readentry==-1) readentry=0;
            if (!branchcount->GetAddress()) {
               R__LoadBranch(branchcount, readentry, fQuickLoad);
            } else {
               
               
               
               branchcount->TBranch::GetEntry(readentry);
               branchcount->ResetReadEntry();
            }
            size = ((TBranchElement*)branchcount)->GetNdata();
            
            
            
            TBranchElement* branch = (TBranchElement*) leaf->GetBranch();
            
            if (fHasMultipleVarDim[i]) {
               info = (TFormLeafInfo* )fDataMembers.At(i);
               if (branch->GetBranchCount2()) R__LoadBranch(branch->GetBranchCount2(),readentry,fQuickLoad);
               else R__LoadBranch(branch,readentry,fQuickLoad);
               
               
               
               info->LoadSizes(branch);
               hasBranchCount2 = kTRUE;
               if (info->GetVirtVarDim()>=0) info->UpdateSizes(fManager->fVarDims[info->GetVirtVarDim()]);
               
               
               Int_t vdim = info->GetVarDim();
               fCumulSizes[i][vdim] =  fCumulSizes[i][vdim+1];
               for(Int_t k=vdim -1; k>=0; k--) {
                  fCumulSizes[i][k] = fCumulSizes[i][k+1]*fFixedSizes[i][k];
               }
               
               
               
               
               
               
               
               
            }
         } else {
            Long64_t readentry = leaf->GetBranch()->GetTree()->GetReadEntry();
            if (readentry==-1) readentry=0;
            R__LoadBranch(branchcount,readentry,fQuickLoad);
            size = leaf->GetLen() / leaf->GetLenStatic();
         }
         if (hasBranchCount2) {
            
            fNdata[i] = fCumulSizes[i][1] * ((TFormLeafInfo *)fDataMembers.At(i))->GetSumOfSizes();
         } else {
            fNdata[i] = size * fCumulSizes[i][1];
         }
         if (fIndexes[i][0]==-1) {
            
            
            if (fManager->fUsedSizes[0]==1 || (size<fManager->fUsedSizes[0]) ) fManager->fUsedSizes[0] = size;
            if (info && fIndexes[i][info->GetVarDim()]>=0) {
               for(Int_t j=0; j<size; j++) {
                  if (fIndexes[i][info->GetVarDim()] >= info->GetSize(j)) {
                     info->SetSize(j,0);
                     if (size>fManager->fCumulUsedVarDims->GetSize()) fManager->fCumulUsedVarDims->Set(size);
                     fManager->fCumulUsedVarDims->AddAt(-1,j);
                  } else if (fIndexes[i][info->GetVarDim()]>=0) {
                     
                     info->SetSize(j,1);
                     if (size>fManager->fCumulUsedVarDims->GetSize()) fManager->fCumulUsedVarDims->Set(size);
                     fManager->fCumulUsedVarDims->AddAt(1,j);
                  }
               }
            }
         } else if (fIndexes[i][0] >= size) {
            
            fManager->fUsedSizes[0] = 0;
            fNdata[i] = 0;
            outofbounds = kTRUE;
         } else if (hasBranchCount2) {
            TFormLeafInfo * info;
            info = (TFormLeafInfo *)fDataMembers.At(i);
            if (fIndexes[i][0]<0
                || fIndexes[i][info->GetVarDim()] >= info->GetSize(fIndexes[i][0])) {
               
               fManager->fUsedSizes[0] = 0;
               fNdata[i] = 0;
               outofbounds = kTRUE;
            }
         }
      } else if (fLookupType[i]==kDataMember) {
         TFormLeafInfo *leafinfo = (TFormLeafInfo*)fDataMembers.UncheckedAt(i);
         if (leafinfo->HasCounter()) {
            TBranch *branch = leaf->GetBranch();
            Long64_t readentry = branch->GetTree()->GetReadEntry();
            if (readentry==-1) readentry=0;
            R__LoadBranch(branch,readentry,fQuickLoad);
            size = (Int_t) leafinfo->GetCounterValue(leaf);
            if (fIndexes[i][0]==-1) {
               
               
               if (fManager->fUsedSizes[0]==1 || (size<fManager->fUsedSizes[0]) ) {
                  fManager->fUsedSizes[0] = size;
               }
            } else if (fIndexes[i][0] >= size) {
               
               fManager->fUsedSizes[0] = 0;
               fNdata[i] = 0;
               outofbounds = kTRUE;
            } else {
               fNdata[i] = size*fCumulSizes[i][1];
            }
            Int_t vdim = leafinfo->GetVarDim();
            if (vdim>=0) {
               
               
               
               
               
               leafinfo->LoadSizes(branch);
               hasBranchCount2 = kTRUE;
               if (fIndexes[i][0]==-1&&fIndexes[i][vdim] >= 0) {
                  for(int z=0; z<size; ++z) {
                     if (fIndexes[i][vdim] >= leafinfo->GetSize(z)) {
                        leafinfo->SetSize(z,0);
                        
                     } else if (fIndexes[i][vdim] >= 0 ) {
                        leafinfo->SetSize(z,1);
                     }
                  }
               }
               leafinfo->UpdateSizes(fManager->fVarDims[vdim]);
               
               
               fCumulSizes[i][vdim] =  fCumulSizes[i][vdim+1];
               for(Int_t k=vdim -1; k>=0; k--) {
                  fCumulSizes[i][k] = fCumulSizes[i][k+1]*fFixedSizes[i][k];
               }
               fNdata[i] = fCumulSizes[i][1] * leafinfo->GetSumOfSizes();
            } else {
               fNdata[i] = size * fCumulSizes[i][1];
            }
         } else if (leafinfo->GetMultiplicity()==-1) {
            TBranch *branch = leaf->GetBranch();
            Long64_t readentry = branch->GetTree()->GetReadEntry();
            if (readentry==-1) readentry=0;
            R__LoadBranch(branch,readentry,fQuickLoad);
            if (leafinfo->GetNdata(leaf)==0) {
               outofbounds = kTRUE;
            }
         }
      }
      
      
      Int_t index;
      TFormLeafInfo * info = 0;
      if (fLookupType[i]!=kDirect) {
         info = (TFormLeafInfo *)fDataMembers.At(i);
      }
      for(Int_t k=0, virt_dim=0; k < fNdimensions[i]; k++) {
         if (fIndexes[i][k]<0) {
            if (fIndexes[i][k]==-2 && fManager->fVirtUsedSizes[virt_dim]<0) {
               
               
               index = fVarIndexes[i][k]->GetNdata();
               if (index==1) {
                  
                  
                  if (fVarIndexes[i][k]->GetManager()->GetMultiplicity()==1) {
                     if (index<fManager->fUsedSizes[virt_dim]) fManager->fUsedSizes[virt_dim] = index;
                  }
               } else if (fManager->fUsedSizes[virt_dim]==-fManager->fVirtUsedSizes[virt_dim] ||
                          index<fManager->fUsedSizes[virt_dim]) {
                  fManager->fUsedSizes[virt_dim] = index;
               }
            } else if (hasBranchCount2 && k==info->GetVarDim()) {
               
               if (fIndexes[i][0]>=0) {
                  index = info->GetSize(fIndexes[i][0]);
                  if (fManager->fUsedSizes[virt_dim]==1 || (index!=1 && index<fManager->fUsedSizes[virt_dim]) )
                     fManager->fUsedSizes[virt_dim] = index;
               }
            }
            virt_dim++;
         } else if (hasBranchCount2 && k==info->GetVarDim()) {
            
            
            
            
            
            
            
         }
      }
   }
   return ! outofbounds;
}
void TTreeFormula::Convert(UInt_t oldversion)
{
   
   enum { kOldAlias           =  100000+10000+1,
          kOldAliasString     = kOldAlias+1,
          kOldAlternate       = kOldAlias+2,
          kOldAlternateString = kOldAliasString+2
   };
   for (int k=0; k<fNoper; k++) {
      
      Int_t action = GetOper()[k];
      switch (action) {
         case kOldAlias:            GetOper()[k] = -kOldAlias; break;
         case kOldAliasString:      GetOper()[k] = -kOldAliasString; break;
         case kOldAlternate:        GetOper()[k] = -kOldAlternate; break;
         case kOldAlternateString:  GetOper()[k] = -kOldAlternateString; break;
      }
   }
   TFormula::Convert(oldversion);
   for (int i=0,offset=0; i<fNoper; i++) {
      Int_t action = GetOper()[i+offset];
      switch (action) {
         case -kOldAlias:            SetAction(i, kAlias, 0); break;
         case -kOldAliasString:      SetAction(i, kAliasString, 0); break;
         case -kOldAlternate:        SetAction(i, kAlternate, 0); break;
         case -kOldAlternateString:  SetAction(i, kAlternateString, 0); break;
      }
   }
}
Bool_t TTreeFormula::SwitchToFormLeafInfo(Int_t code)
{
   
   
   
   
   
   
   
   TFormLeafInfo *last = 0;
   TLeaf *leaf = (TLeaf*)fLeaves.At(code);
   if (!leaf) return kFALSE;
   if (fLookupType[code]==kDirect) {
      if (leaf->InheritsFrom("TLeafElement")) {
         TBranchElement * br = (TBranchElement*)leaf->GetBranch();
         if (br->GetType()==31) {
            
            TStreamerInfo *info = br->GetInfo();
            TClass* cl = info->GetClass();
            TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()];
            TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE);
            Int_t offset;
            info->GetStreamerElement(element->GetName(),offset);
            clonesinfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element);
            last = clonesinfo->fNext;
            fDataMembers.AddAtAndExpand(clonesinfo,code);
            fLookupType[code]=kDataMember;
         } else if (br->GetType()==41) {
            
            TBranchElement *count = br->GetBranchCount();
            TFormLeafInfo* collectioninfo;
            if ( count->GetID() >= 0 ) {
               TStreamerElement *collectionElement =
                  (TStreamerElement *)count->GetInfo()->GetElems()[count->GetID()];
               TClass *collectionCl = collectionElement->GetClassPointer();
               collectioninfo =
                  new TFormLeafInfoCollection(collectionCl, 0, collectionElement, kTRUE);
            } else {
               TClass *collectionCl = TClass::GetClass(count->GetClassName());
               collectioninfo =
                  new TFormLeafInfoCollection(collectionCl, 0, collectionCl, kTRUE);
            }
            TStreamerInfo *info = br->GetInfo();
            TClass* cl = info->GetClass();
            TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()];
            Int_t offset;
            info->GetStreamerElement(element->GetName(),offset);
            collectioninfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element);
            last = collectioninfo->fNext;
            fDataMembers.AddAtAndExpand(collectioninfo,code);
            fLookupType[code]=kDataMember;
         } else {
            last = new TFormLeafInfoDirect(br);
            fDataMembers.AddAtAndExpand(last,code);
            fLookupType[code]=kDataMember;
         }
      } else {
         
         
         
         return kFALSE;
      }
   }
   return kTRUE;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.