#ifndef ALIREFARRAY_H
#define ALIREFARRAY_H
#include "TObject.h"
class AliRefArray : public TObject {
public:
AliRefArray();
AliRefArray(UInt_t nelem, UInt_t depth=0);
AliRefArray(const AliRefArray& src);
AliRefArray& operator=(const AliRefArray& src);
virtual ~AliRefArray();
UInt_t GetNElems() const {return fNElems;}
void Expand(UInt_t size=0);
Bool_t IsReferred(UInt_t from, UInt_t to) const;
Bool_t HasReference(UInt_t from) const {return (from>=fNElems||!fElems[from]) ? kFALSE:kTRUE;}
void AddReference(UInt_t from, UInt_t to);
void AddReferences(UInt_t from, UInt_t* refs, UInt_t nref);
UInt_t GetReferences(UInt_t from, UInt_t* refs, UInt_t maxRef) const;
Int_t GetReference(UInt_t from, UInt_t which) const;
void Reset();
void Print(Option_t* opt="") const;
void Compactify();
protected:
void ExpandReferences(Int_t addSize);
protected:
UInt_t fNElems;
UInt_t fRefSize;
Int_t* fElems;
UInt_t* fRefInd;
UInt_t* fRefBuff;
ClassDef(AliRefArray,1)
};
inline Bool_t AliRefArray::IsReferred(UInt_t from, UInt_t to) const
{
Int_t ref;
if (from>=fNElems || !(ref=fElems[from])) return kFALSE;
if (ref<0) {return (ref+int(to))==-1;}
to++;
do { if (fRefBuff[ref]==to) return kTRUE; } while((ref=fRefInd[ref]));
return kFALSE;
}
inline UInt_t AliRefArray::GetReferences(UInt_t from, UInt_t* refs, UInt_t maxRef) const
{
Int_t ref;
UInt_t nrefs=0;
if (from>=fNElems || !(ref=fElems[from])) return 0;
if (ref<0) {refs[0] = -(1+ref); return 1;}
do { refs[nrefs++]=fRefBuff[ref]-1; } while((ref=(int)fRefInd[ref]) && nrefs<maxRef);
return nrefs;
}
inline Int_t AliRefArray::GetReference(UInt_t from, UInt_t which) const
{
Int_t ref;
if (from>=fNElems || !(ref=fElems[from])) return -1;
if (ref<0) return which ? -1 : -(1+ref);
int ref1 = ref;
while(which && (ref1=(int)fRefInd[ref])) {ref=ref1;which--;}
return which ? -1 : (Int_t) fRefBuff[ref]-1;
}
inline void AliRefArray::AddReference(UInt_t from, UInt_t to)
{
if (from>=fNElems) Expand(from+1);
int &ref0 = fElems[from];
if (!ref0) {ref0 = -(++to); return;}
int chk = ref0>0 ? 1:2;
if (!fRefInd || int(fRefInd[0])>(int(fRefSize)-chk)) ExpandReferences( fRefSize );
UInt_t &freeSlot = fRefInd[0];
Int_t ref = fElems[from];
if (ref<0) { fRefInd[freeSlot]=0; fRefBuff[freeSlot] = -ref; ref = fElems[from] = freeSlot++; }
while(fRefInd[ref]) ref=fRefInd[ref];
fRefBuff[freeSlot] = ++to;
fRefInd[ref] = freeSlot++;
}
inline void AliRefArray::Compactify()
{
if (fRefInd && fRefSize>fRefInd[0]) fRefSize = fRefInd[0];
}
#endif