#include "TEntryListBlock.h"
#include "TString.h"
ClassImp(TEntryListBlock)
TEntryListBlock::TEntryListBlock()
{
   
   fIndices = 0;
   fN = kBlockSize;
   fNPassed = 0;
   fType = -1;
   fPassing = 1;
   fCurrent = 0;
   fLastIndexReturned = -1;
   fLastIndexQueried = -1;
}
TEntryListBlock::TEntryListBlock(const TEntryListBlock &eblock) : TObject(eblock)
{
   
   Int_t i;
   fN = eblock.fN;
   if (eblock.fIndices){
      fIndices = new UShort_t[fN];
      for (i=0; i<fN; i++)
         fIndices[i] = eblock.fIndices[i];
   }
   fNPassed = eblock.fNPassed;
   fType = eblock.fType;
   fPassing = eblock.fPassing;
   fCurrent = eblock.fCurrent;
   fLastIndexReturned = -1;
   fLastIndexQueried = -1;
}
TEntryListBlock::~TEntryListBlock()
{
   
   if (fIndices)
      delete [] fIndices;
   fIndices = 0;
}
Bool_t TEntryListBlock::Enter(Int_t entry)
{
   
   
   
   if (entry > kBlockSize*16) {
      Error("Enter", "illegal entry value!");
      return 0;
   }
   if (!fIndices){
      fIndices = new UShort_t[kBlockSize] ;
      for (Int_t i=0; i<kBlockSize; i++)
         fIndices[i] = 0;
      fType = 0; 
   }
   if (fType==0){
      
      Int_t i = entry>>4;
      Int_t j = entry & 15;
      if ((fIndices[i] & (1<<j))==0){
         fIndices[i] |= 1<<j;
         fNPassed++;
         return 1;
      } else {
         return 0;
      }
   }
   
   
   UShort_t *bits = new UShort_t[kBlockSize];
   Transform(1, bits);
   Enter(entry);
   return 0;
}
Bool_t TEntryListBlock::Remove(Int_t entry)
{
   if (entry > kBlockSize*16) {
      Error("Remove", "Illegal entry value!\n");
      return 0;
   }
   if (fType==0){
      Int_t i = entry>>4;
      Int_t j = entry & 15;
      if ((fIndices[i] & (1<<j))!=0){
         fIndices[i] &= (0xFFFF^(1<<j));
         fNPassed--;
         return 1;
      } else { 
         return 0;
      }
   }
   
   
   UShort_t *bits = new UShort_t[kBlockSize];
   Transform(1, bits);
   return Remove(entry);
   
}
Int_t TEntryListBlock::Contains(Int_t entry)
{
   if (entry > kBlockSize*16) {
      Error("Contains", "Illegal entry value!\n");
      return 0;
   }
   if (!fIndices && fPassing)
      return 0;
   if (fType==0){
      
      Int_t i = entry>>4;
      Int_t j = entry & 15;
      Bool_t result = (fIndices[i] & (1<<j))!=0;
      return result;
   }
   
   if (entry < fCurrent) fCurrent = 0;
   if (fPassing){
      for (Int_t i = fCurrent; i<fNPassed; i++){
         if (fIndices[i]==entry){
            fCurrent = i;
            return kTRUE;
         }
      }
   } else {
      if (!fIndices || fNPassed==0){
         
         return kTRUE;
      } 
      if (entry > fIndices[fNPassed-1])
         return kTRUE;
      for (Int_t i= fCurrent; i<fNPassed; i++){
         if (fIndices[i]==entry){
            fCurrent = i;
            return kFALSE;
         } 
         if (fIndices[i]>entry){
            fCurrent = i;
            return kTRUE;
         }
      }
   }
   return 0;
}
Int_t TEntryListBlock::Merge(TEntryListBlock *block)
{
   
   
   Int_t i, j;
   if (block->GetNPassed() == 0) return GetNPassed();
   if (GetNPassed() == 0){
      
      fN = block->fN;
      fIndices = new UShort_t[fN];
      for (Int_t i=0; i<fN; i++)
         fIndices[i] = block->fIndices[i];
      fNPassed = block->fNPassed;
      fType = block->fType;
      fPassing = block->fPassing;
      fCurrent = block->fCurrent;
      fLastIndexReturned = -1;
      fLastIndexQueried = -1;
      return fNPassed;
   }
   if (fType==0){
      
      if (block->fType == 0){
         for (i=0; i<kBlockSize*16; i++){
            if (block->Contains(i))
               Enter(i);
         }
      } else {
         if (block->fPassing){
            
            for (i=0; i<block->fNPassed; i++){
               Enter(block->fIndices[i]);
            }
         } else {
            
            if (block->fNPassed==0){
               for (Int_t i=0; i<kBlockSize*16; i++){
                  Enter(i);
               }
            }
            for (j=0; j<block->fIndices[0]; j++)
               Enter(j);
            for (i=0; i<block->fNPassed-1; i++){
               for (j=block->fIndices[i]+1; j<block->fIndices[i+1]; j++){
                  Enter(j);
               }
            }
            for (j=block->fIndices[block->fNPassed-1]+1; j<kBlockSize*16; j++)
               Enter(j);
         }
      }
   } else {
      
      if (GetNPassed() + block->GetNPassed() > kBlockSize){
         
         UShort_t *bits = new UShort_t[kBlockSize];
         Transform(1, bits);
         Merge(block);
      } else {
         
         if (block->fType==1){
            
            
            Int_t en = block->fNPassed;
            Int_t newsize = fNPassed + en;
            UShort_t *newlist = new UShort_t[newsize];
            UShort_t *elst = block->fIndices;
            Int_t newpos, elpos;
            newpos = elpos = 0;
            for (i=0; i<fNPassed; i++) {
               while (elpos < en && fIndices[i] > elst[elpos]) {
                  newlist[newpos] = elst[elpos];
                  newpos++;
                  elpos++;
               }
               if (fIndices[i] == elst[elpos]) elpos++;
               newlist[newpos] = fIndices[i];
               newpos++;
            }
            while (elpos < en) {
               newlist[newpos] = elst[elpos];
               newpos++;
               elpos++;
            }
            delete [] fIndices;
            fIndices = newlist;
            fNPassed = newpos;
            fN = fNPassed;
         } else {
            
            Int_t en = block->fNPassed;
            Int_t newsize = fNPassed + en;
            UShort_t *newlist = new UShort_t[newsize];
            Int_t newpos, current;
            newpos = current = 0;
            for (i=0; i<kBlockSize*16; i++){
               if (!block->Contains(i)) continue;
               while(current < fNPassed && fIndices[current]<i){
                  newlist[newpos] = fIndices[current];
                  current++;
                  newpos++;
               }
               if (fIndices[current]==i) current++;
               newlist[newpos] = i;
               newpos++;
            }
            while(current<fNPassed){
               newlist[newpos] = fIndices[current];
               newpos++;
               current++;
            }
            delete [] fIndices;
            fIndices = newlist;
            fNPassed = newpos;
            fN = fNPassed;
         }
      }
   }
   fLastIndexQueried = -1;
   fLastIndexReturned = -1;
   OptimizeStorage();
   return GetNPassed();
}
Int_t TEntryListBlock::GetNPassed()
{
   if (fPassing)
      return fNPassed;
   else
      return kBlockSize*16-fNPassed;
}
Int_t TEntryListBlock::GetEntry(Int_t entry)
{
   if (entry > kBlockSize*16) return -1;
   if (entry > GetNPassed()) return -1;
   if (entry == fLastIndexQueried+1) return Next();
   else {
      Int_t i=0; Int_t j=0; Int_t entries_found=0;
      if (fType==0){
         if ((fIndices[i] & (1<<j))!=0)
            entries_found++;
         while (entries_found<entry+1){
            if (j==15){i++; j=0;}
            else j++;
            if ((fIndices[i] & (1<<j))!=0)
               entries_found++;
         }
         fLastIndexQueried = entry;
         fLastIndexReturned = i*16+j;
         return fLastIndexReturned;
      }
      if (fType==1){
         if (fPassing){
            fLastIndexQueried = entry;
            fLastIndexReturned = fIndices[entry];
            return fIndices[entry];
         } else {
            fLastIndexQueried = entry;
            for (i=0; i<fIndices[0]; i++){               
               entries_found++;
               if (entries_found==entry+1){
                  fLastIndexReturned = i;
                  return fLastIndexReturned;
               }
            }
            for (i=0; i<fNPassed-1; i++){
               for (j=fIndices[i]+1; j<fIndices[i+1]; j++){
                  entries_found++;
                  if (entries_found==entry+1){
                     fLastIndexReturned = j;
                     return fLastIndexReturned;
                  }
               }
            }
            for (j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
               entries_found++;
               if (entries_found==entry+1){
                  fLastIndexReturned = j;
                  return fLastIndexReturned;
               }
            }
         }   
      }
      return -1;
   }
}
Int_t TEntryListBlock::Next()
{
   if (fLastIndexQueried==GetNPassed()-1){
      fLastIndexQueried=-1;
      fLastIndexReturned = -1;
      return -1;
   }
   if (fType==0) {
      
      Int_t i=0;
      Int_t j=0;
      fLastIndexReturned++;
      i = fLastIndexReturned>>4;
      j = fLastIndexReturned & 15;
      Bool_t result=(fIndices[i] & (1<<j))!=0;
      while (result==0){
         if (j==15) {j=0; i++;}
         else j++;
         result = (fIndices[i] & (1<<j))!=0;
      }
      fLastIndexReturned = i*16+j;
      fLastIndexQueried++;
      return fLastIndexReturned;
   } 
   if (fType==1) {
      fLastIndexQueried++;
      if (fPassing){
         fLastIndexReturned = fIndices[fLastIndexQueried];
         return fIndices[fLastIndexQueried];
      } else {
         fLastIndexReturned++;
         while (!Contains(fLastIndexReturned)){
            fLastIndexReturned++;
            }
         return fLastIndexReturned;
      }
      
   }
   return -1;
}
void TEntryListBlock::Print(const Option_t *option) const
{
   
   TString opt = option;
   opt.ToUpper();
   if (opt.Contains("A")) PrintWithShift(0);
}
void TEntryListBlock::PrintWithShift(Int_t shift) const
{
   
   
   Int_t i;
   if (fType==0){
      Int_t ibit, ibite;
      Bool_t result;
      for (i=0; i<kBlockSize*16; i++){
         ibite = i>>4;
         ibit = i & 15;
         result = (fIndices[ibite] & (1<<ibit))!=0;
         if (result)
            printf("%d\n", i+shift);
      }
   } else {
      if (fPassing){
         for (i=0; i<fNPassed; i++){
            printf("%d\n", fIndices[i]+shift);
         }
      } else {
         if (fNPassed==0){
            for (Int_t i=0; i<kBlockSize*16; i++)
               printf("%d\n", i+shift);
            return;
         }
         for (Int_t i=0; i<fIndices[0]; i++){
            printf("%d\n", i+shift);
         }
         for (Int_t i=0; i<fNPassed-1; i++){
            for (Int_t j=fIndices[i]+1; j<fIndices[i+1]; j++){
               printf("%d\n", j+shift);
            }
         }
         for (Int_t j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
            printf("%d\n", j+shift);
         }
      }
   }
}
void TEntryListBlock::OptimizeStorage()
{
   
   if (fType!=0) return;
   if (fNPassed > kBlockSize*15)
      fPassing = 0;
   if (fNPassed<kBlockSize || !fPassing){
      
      UShort_t *indexnew = new UShort_t[fNPassed];
      Transform(0, indexnew);
   }
}
void TEntryListBlock::Transform(Bool_t dir, UShort_t *indexnew)
{
   
   
   
   Int_t i=0;
   Int_t ilist = 0;
   Int_t ibite, ibit;
   if (!dir) {
         for (i=0; i<kBlockSize*16; i++){
            ibite = i >> 4;
            ibit = i & 15;
            Bool_t result = (fIndices[ibite] & (1<<ibit))!=0;
            if (result && fPassing){
               
               indexnew[ilist] = i;
               ilist++;
            }
            else if (!result && !fPassing){
               
               indexnew[ilist] = i;
               ilist++;
            }
         }
      if (fIndices)
         delete [] fIndices;
      fIndices = indexnew;
      fType = 1;
      if (!fPassing)
         fNPassed = kBlockSize*16-fNPassed;
      fN = fNPassed;
      return;
   }
   if (fPassing){
      for (i=0; i<kBlockSize; i++)
         indexnew[i] = 0;
      for (i=0; i<fNPassed; i++){
         ibite = fIndices[i]>>4;
         ibit = fIndices[i] & 15;
         indexnew[ibite] |= 1<<ibit;
      }
   } else {
      for (i=0; i<kBlockSize; i++)
         indexnew[i] = 65535;
      for (i=0; i<fNPassed; i++){
         ibite = fIndices[i]>>4;
         ibit = fIndices[i] & 15;
         indexnew[ibite] ^= 1<<ibit;
      }
      fNPassed = kBlockSize*16-fNPassed;
   } 
   if (fIndices)
      delete [] fIndices;
   fIndices = indexnew;
   fType = 0;
   fN = kBlockSize;
   fPassing = 1;
   return;
}
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.