// @(#)root/treeplayer:$Name: $:$Id: TTreeFormulaManager.cxx,v 1.2 2002/04/04 17:28:52 rdm Exp $
// Author: Philippe Canal 20/03/02
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers and al. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#include "TTreeFormulaManager.h"
#include "TArrayI.h"
#include "TError.h"
#include "TLeafElement.h"
ClassImp(TTreeFormulaManager)
//________________________________________________________________________________
//
// A TreeFormulaManager is used to coordinate one or more TTreeFormula objecs
//
// In particular it makes sure that the dimensions and size of all the formulas
// is properly coordinated.
//
//______________________________________________________________________________
TTreeFormulaManager::TTreeFormulaManager() : TObject()
{
//*-*-*-*-*-*-*-*-*-*-*Tree FormulaManger default constructor*-*-*-*-*-*-*-*-*-*
//*-* ======================================
fMultiplicity = 0;
fMultiVarDim = kFALSE;
fNeedSync = kFALSE;
for(Int_t i=0; i<kMAXFORMDIM+1; i++) {
fVarDims[i] = 0;
fCumulUsedSizes[i] = 1;
fUsedSizes[i] = 1;
fVirtUsedSizes[i] = 1;
}
fCumulUsedVarDims = 0;
}
//______________________________________________________________________________
TTreeFormulaManager::~TTreeFormulaManager()
{
//*-*-*-*-*-*-*-*-*-*-*Tree FormulaManager default destructor*-*-*-*-*-*-*-*-*-*
//*-* ======================================
for (int l = 0; l<kMAXFORMDIM; l++) {
if (fVarDims[l]) delete fVarDims[l];
fVarDims[l] = 0;
}
if (fCumulUsedVarDims) delete fCumulUsedVarDims;
}
//______________________________________________________________________________
void TTreeFormulaManager::Remove(TTreeFormula* adding)
{
// Remove a formula from this manager
fFormulas.Remove(adding);
}
//______________________________________________________________________________
void TTreeFormulaManager::Add(TTreeFormula* adding)
{
// Add a new formula to the list of formulas managed
// The manager of the formula will be changed and the old one will be deleted
// if it is empty.
TTreeFormulaManager * old = adding->fManager;
if (old) {
if (old==this) {
if (fFormulas.FindObject(adding)) return;
} else {
old->fFormulas.Remove(adding);
if (old->fFormulas.GetLast()==-1) delete adding->fManager;
}
}
fFormulas.Add(adding);
adding->fManager = this;
fNeedSync = kTRUE;
}
//______________________________________________________________________________
void TTreeFormulaManager::AddVarDims(Int_t virt_dim)
{
// Add a variable dimension
if (!fVarDims[virt_dim]) fVarDims[virt_dim] = new TArrayI;
}
//______________________________________________________________________________
void TTreeFormulaManager::CancelDimension(Int_t virt_dim)
{
// Cancel a dimension. This is usually called when an out-of-bounds index
// is used.
fCumulUsedSizes[virt_dim] = 0;
}
//______________________________________________________________________________
void TTreeFormulaManager::EnableMultiVarDims()
{
fMultiVarDim = kTRUE;
if (!fCumulUsedVarDims) fCumulUsedVarDims = new TArrayI;
}
//______________________________________________________________________________
Int_t TTreeFormulaManager::GetNdata()
{
//*-*-*-*-*-*-*-*Return number of available instances in the formulas*-*-*-*-*-*
//*-* ====================================================
//
Int_t k;
// new version of GetNData:
// Possible problem: we only allow one variable dimension so far.
if (fMultiplicity==0) return fNdata;
if (fMultiplicity==2) return fNdata; // CumulUsedSizes[0];
// We have at least one leaf with a variable size:
// Reset the registers.
for(k=0; k<=kMAXFORMDIM; k++) {
fUsedSizes[k] = TMath::Abs(fVirtUsedSizes[k]);
if (fVarDims[k]) {
for(Int_t i0=0;i0<fVarDims[k]->GetSize();i0++) {
fVarDims[k]->AddAt(0,i0);
}
}
}
TTreeFormula* current = 0;
Int_t size = fFormulas.GetLast()+1;
for(Int_t i=0; i<size; i++) {
current = (TTreeFormula*)fFormulas.UncheckedAt(i);
if (current->fMultiplicity!=1 && !current->fHasCast) continue;
if (!current->LoadCurrentDim() ) { fNdata = 0; return 0; }
}
if (fMultiplicity==-1) { fNdata = 1; return fCumulUsedSizes[0]; }
Int_t overall = 1;
if (!fMultiVarDim) {
for (k = kMAXFORMDIM; (k >= 0) ; k--) {
if (fUsedSizes[k]>=0) {
overall *= fUsedSizes[k];
fCumulUsedSizes[k] = overall;
} else {
Error("GetNdata","a dimension is still negative!");
}
}
} else {
overall = 0; // Since we work with additions in this section
if (fUsedSizes[0]>fCumulUsedVarDims->GetSize()) fCumulUsedVarDims->Set(fUsedSizes[0]);
for(Int_t i = 0; i < fUsedSizes[0]; i++) {
Int_t local_overall = 1;
for (k = kMAXFORMDIM; (k > 0) ; k--) {
if (fVarDims[k]) {
Int_t index = fVarDims[k]->At(i);
if (fUsedSizes[k]==1 || (index!=1 && index<fUsedSizes[k]))
local_overall *= index;
else local_overall *= fUsedSizes[k];
} else {
local_overall *= fUsedSizes[k];
}
}
// a negative value indicates that this value of the primary index
// will lead to an invalid index; So we skip it.
if (fCumulUsedVarDims->At(i)<0) fCumulUsedVarDims->AddAt(0,i);
else {
fCumulUsedVarDims->AddAt(local_overall,i);
overall += local_overall;
}
}
}
fNdata = overall;
return overall;
}
//______________________________________________________________________________
Bool_t TTreeFormulaManager::Sync() {
if (!fNeedSync) return true;
TTreeFormula* current = 0;
Bool_t hasCast = kFALSE;
fMultiplicity = 0;
// We do not use an intermediary variable because ResetDimensions
// might add more formulas (TCutG).
for(Int_t i=0; i<fFormulas.GetLast()+1; i++) {
current = (TTreeFormula*)fFormulas.UncheckedAt(i);
hasCast |= current->fHasCast;
// We probably need to reset the formula's dimension
current->ResetDimensions();
switch (current->GetMultiplicity()) {
case 0:
// nothing to do
break;
case 1:
fMultiplicity = 1;
break;
case 2:
if (fMultiplicity!=1) fMultiplicity = 2;
break;
default:
Error("Sync","Unexpected case!");
}
} // end of for each formulas
// For now we keep fCumulUsedSizes sign aware.
// This will be reset properly (if needed) by GetNdata.
fCumulUsedSizes[kMAXFORMDIM] = fUsedSizes[kMAXFORMDIM];
for (Int_t k = kMAXFORMDIM; (k > 0) ; k--) {
if (fUsedSizes[k-1]>=0) {
fCumulUsedSizes[k-1] = fUsedSizes[k-1] * fCumulUsedSizes[k];
} else {
fCumulUsedSizes[k-1] = - TMath::Abs(fCumulUsedSizes[k]);
}
}
// Now that we know the virtual dimension we know if a loop over EvalInstance
// is needed or not.
if (fCumulUsedSizes[0]==1 && fMultiplicity!=0) {
// Case where even though we have an array. We know that they will always
// only be one element.
fMultiplicity -= 2;
} else if (fCumulUsedSizes[0]<0 && fMultiplicity==2) {
// Case of a fixed length array that have one of its indices given
// by a variable.
fMultiplicity = 1;
} else if (fMultiplicity==0 && hasCast) {
fMultiplicity = -1;
}
switch(fMultiplicity) {
case 0: fNdata = 1; break;
case 2: fNdata = fCumulUsedSizes[0]; break;
default: fNdata = 0;
}
fNeedSync = kFALSE;
return true;
}
//______________________________________________________________________________
void TTreeFormulaManager::UpdateFormulaLeaves()
{
// this function could be called TTreePlayer::UpdateFormulaLeaves, itself
// called by TChain::LoadTree when a new Tree is loaded.
// Because Trees in a TChain may have a different list of leaves, one
// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
// A safer alternative would be to recompile the whole thing .... However
// currently compile HAS TO be called from the constructor!
Int_t size = fFormulas.GetLast()+1;
for(Int_t i=0; i<size; i++) {
TTreeFormula *current = (TTreeFormula*)fFormulas.UncheckedAt(i);
current->UpdateFormulaLeaves();
}
}
//______________________________________________________________________________
void TTreeFormulaManager::UpdateUsedSize(Int_t &virt_dim, Int_t vsize) {
if (vsize<0)
fVirtUsedSizes[virt_dim] = -1 * TMath::Abs(fVirtUsedSizes[virt_dim]);
else
if ( TMath::Abs(fVirtUsedSizes[virt_dim])==1
|| (vsize < TMath::Abs(fVirtUsedSizes[virt_dim]) ) ) {
// Absolute values represent the min of all real dimensions
// that are known. The fact that it is negatif indicates
// that one of the leaf has a variable size for this
// dimensions.
if (fVirtUsedSizes[virt_dim] < 0) {
fVirtUsedSizes[virt_dim] = -1 * vsize;
} else {
fVirtUsedSizes[virt_dim] = vsize;
}
}
fUsedSizes[virt_dim] = fVirtUsedSizes[virt_dim];
virt_dim++;
}
ROOT page - Class index - Top of the page
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.