TEntryListBlock.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TEntryListBlock.cxx 35363 2010-09-17 12:33:37Z brun $
00002 // Author: Anna Kreshuk 27/10/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //______________________________________________________________________________
00013 /* Begin_Html
00014 <center><h2>TEntryListBlock: Used by TEntryList to store the entry numbers</h2></center>
00015  There are 2 ways to represent entry numbers in a TEntryListBlock:
00016 <ol>
00017  <li> as bits, where passing entry numbers are assigned 1, not passing - 0
00018  <li> as a simple array of entry numbers
00019 <ul>
00020 <li> storing the numbers of entries that pass
00021 <li> storing the numbers of entries that don't pass
00022 </ul>
00023  </ol>
00024  In both cases, a UShort_t* is used. The second option is better in case
00025  less than 1/16 or more than 15/16 of entries pass the selection, and the representation can be
00026  changed by calling OptimizeStorage() function. 
00027  When the block is being filled, it's always stored as bits, and the OptimizeStorage()
00028  function is called by TEntryList when it starts filling the next block. If
00029  Enter() or Remove() is called after OptimizeStorage(), representation is 
00030  again changed to 1). 
00031 End_Html
00032 Begin_Macro(source)
00033 entrylistblock_figure1.C
00034 End_Macro
00035 
00036 Begin_Html
00037  <h4>Operations on blocks (see also function comments)</h4>
00038 <ul>
00039  <li> <b>Merge</b>() - adds all entries from one block to the other. If the first block 
00040              uses array representation, it's changed to bits representation only
00041              if the total number of passing entries is still less than kBlockSize
00042  <li> <b>GetEntry(n)</b> - returns n-th non-zero entry.
00043  <li> <b>Next</b>()      - return next non-zero entry. In case of representation 1), Next()
00044                  is faster than GetEntry()
00045 </ul>
00046 End_Html */
00047 
00048 
00049 #include "TEntryListBlock.h"
00050 #include "TString.h"
00051 
00052 ClassImp(TEntryListBlock)
00053 
00054 //______________________________________________________________________________
00055 TEntryListBlock::TEntryListBlock()
00056 {
00057    //default c-tor
00058 
00059    fIndices = 0;
00060    fN = kBlockSize;
00061    fNPassed = 0;
00062    fType = -1;
00063    fPassing = 1;
00064    fCurrent = 0;
00065    fLastIndexReturned = -1;
00066    fLastIndexQueried = -1;
00067 }
00068 
00069 //______________________________________________________________________________
00070 TEntryListBlock::TEntryListBlock(const TEntryListBlock &eblock) : TObject(eblock)
00071 {
00072    //copy c-tor
00073 
00074    Int_t i;
00075    fN = eblock.fN;
00076    if (eblock.fIndices){
00077       fIndices = new UShort_t[fN];
00078       for (i=0; i<fN; i++)
00079          fIndices[i] = eblock.fIndices[i];
00080    } else {
00081       fIndices = 0;
00082    }
00083    fNPassed = eblock.fNPassed;
00084    fType = eblock.fType;
00085    fPassing = eblock.fPassing;
00086    fCurrent = eblock.fCurrent;
00087    fLastIndexReturned = -1;
00088    fLastIndexQueried = -1;
00089 }
00090 
00091 
00092 //______________________________________________________________________________
00093 TEntryListBlock::~TEntryListBlock()
00094 {
00095    //destructor
00096 
00097    if (fIndices)
00098       delete [] fIndices;
00099    fIndices = 0;
00100 }
00101 
00102 //______________________________________________________________________________
00103 Bool_t TEntryListBlock::Enter(Int_t entry)
00104 {
00105    //If the block has already been optimized and the entries
00106    //are stored as a list and not as bits, trying to enter a new entry
00107    //will make the block switch to bits representation
00108 
00109    if (entry > kBlockSize*16) {
00110       Error("Enter", "illegal entry value!");
00111       return 0;
00112    }
00113    if (!fIndices){
00114       fIndices = new UShort_t[kBlockSize] ;
00115       for (Int_t i=0; i<kBlockSize; i++)
00116          fIndices[i] = 0;
00117       fType = 0; //start in bits
00118    }
00119    if (fType==0){
00120       //bits
00121       Int_t i = entry>>4;
00122       Int_t j = entry & 15;
00123       if ((fIndices[i] & (1<<j))==0){
00124          fIndices[i] |= 1<<j;
00125          fNPassed++;
00126          return 1;
00127       } else {
00128          return 0;
00129       }
00130    }
00131    //list
00132    //change to bits
00133    UShort_t *bits = new UShort_t[kBlockSize];
00134    Transform(1, bits);
00135    Enter(entry);
00136    return 0;
00137 }
00138 
00139 //______________________________________________________________________________
00140 Bool_t TEntryListBlock::Remove(Int_t entry)
00141 {
00142 //Remove entry #entry
00143 //If the block has already been optimized and the entries
00144 //are stored as a list and not as bits, trying to remove a new entry
00145 //will make the block switch to bits representation
00146 
00147    if (entry > kBlockSize*16) {
00148       Error("Remove", "Illegal entry value!\n");
00149       return 0;
00150    }
00151    if (fType==0){
00152       Int_t i = entry>>4;
00153       Int_t j = entry & 15;
00154       if ((fIndices[i] & (1<<j))!=0){
00155          fIndices[i] &= (0xFFFF^(1<<j));
00156          fNPassed--;
00157          return 1;
00158       } else { 
00159          return 0;
00160       }
00161    }
00162    //list
00163    //change to bits
00164    UShort_t *bits = new UShort_t[kBlockSize];
00165    Transform(1, bits);
00166    return Remove(entry);
00167    //return 0;
00168 }
00169 //______________________________________________________________________________
00170 Int_t TEntryListBlock::Contains(Int_t entry)
00171 {
00172 //true if the block contains entry #entry
00173 
00174    if (entry > kBlockSize*16) {
00175       Error("Contains", "Illegal entry value!\n");
00176       return 0;
00177    }
00178    if (!fIndices && fPassing)
00179       return 0;
00180    if (fType==0 && fIndices){
00181       //bits
00182       Int_t i = entry>>4;
00183       Int_t j = entry & 15;
00184       Bool_t result = (fIndices[i] & (1<<j))!=0;
00185       return result;
00186    }
00187    //list
00188    if (entry < fCurrent) fCurrent = 0;
00189    if (fPassing && fIndices){
00190       for (Int_t i = fCurrent; i<fNPassed; i++){
00191          if (fIndices[i]==entry){
00192             fCurrent = i;
00193             return kTRUE;
00194          }
00195       }
00196    } else {
00197       if (!fIndices || fNPassed==0){
00198          //all entries pass
00199          return kTRUE;
00200       } 
00201       if (entry > fIndices[fNPassed-1])
00202          return kTRUE;
00203       for (Int_t i= fCurrent; i<fNPassed; i++){
00204          if (fIndices[i]==entry){
00205             fCurrent = i;
00206             return kFALSE;
00207          } 
00208          if (fIndices[i]>entry){
00209             fCurrent = i;
00210             return kTRUE;
00211          }
00212       }
00213    }
00214    return 0;
00215 }
00216 
00217 //______________________________________________________________________________
00218 Int_t TEntryListBlock::Merge(TEntryListBlock *block)
00219 {
00220    //Merge with the other block
00221    //Returns the resulting number of entries in the block
00222 
00223    Int_t i, j;
00224    if (block->GetNPassed() == 0) return GetNPassed();
00225    if (GetNPassed() == 0){
00226       //this block is empty
00227       fN = block->fN;
00228       fIndices = new UShort_t[fN];
00229       for (i=0; i<fN; i++)
00230          fIndices[i] = block->fIndices[i];
00231       fNPassed = block->fNPassed;
00232       fType = block->fType;
00233       fPassing = block->fPassing;
00234       fCurrent = block->fCurrent;
00235       fLastIndexReturned = -1;
00236       fLastIndexQueried = -1;
00237       return fNPassed;
00238    }
00239    if (fType==0){
00240       //stored as bits
00241       if (block->fType == 0){
00242          for (i=0; i<kBlockSize*16; i++){
00243             if (block->Contains(i))
00244                Enter(i);
00245          }
00246       } else {
00247          if (block->fPassing){
00248             //the other block stores entries that pass
00249             for (i=0; i<block->fNPassed; i++){
00250                Enter(block->fIndices[i]);
00251             }
00252          } else {
00253             //the other block stores entries that don't pass
00254             if (block->fNPassed==0){
00255                for (i=0; i<kBlockSize*16; i++){
00256                   Enter(i);
00257                }
00258             }
00259             for (j=0; j<block->fIndices[0]; j++)
00260                Enter(j);
00261             for (i=0; i<block->fNPassed-1; i++){
00262                for (j=block->fIndices[i]+1; j<block->fIndices[i+1]; j++){
00263                   Enter(j);
00264                }
00265             }
00266             for (j=block->fIndices[block->fNPassed-1]+1; j<kBlockSize*16; j++)
00267                Enter(j);
00268          }
00269       }
00270    } else {
00271       //stored as a list
00272       if (GetNPassed() + block->GetNPassed() > kBlockSize){
00273          //change to bits
00274          UShort_t *bits = new UShort_t[kBlockSize];
00275          Transform(1, bits);
00276          Merge(block);
00277       } else {
00278          //this is only possible if fPassing=1 in both blocks
00279          if (block->fType==1){
00280             //second block stored as a list
00281             //make a bigger list
00282             Int_t en = block->fNPassed;
00283             Int_t newsize = fNPassed + en;
00284             UShort_t *newlist = new UShort_t[newsize];
00285             UShort_t *elst = block->fIndices;
00286             Int_t newpos, elpos;
00287             newpos = elpos = 0;
00288             for (i=0; i<fNPassed; i++) {
00289                while (elpos < en && fIndices[i] > elst[elpos]) {
00290                   newlist[newpos] = elst[elpos];
00291                   newpos++;
00292                   elpos++;
00293                }
00294                if (fIndices[i] == elst[elpos]) elpos++;
00295                newlist[newpos] = fIndices[i];
00296                newpos++;
00297             }
00298             while (elpos < en) {
00299                newlist[newpos] = elst[elpos];
00300                newpos++;
00301                elpos++;
00302             }
00303             delete [] fIndices;
00304             fIndices = newlist;
00305             fNPassed = newpos;
00306             fN = fNPassed;
00307          } else {
00308             //second block is stored as bits
00309 
00310             Int_t en = block->fNPassed;
00311             Int_t newsize = fNPassed + en;
00312             UShort_t *newlist = new UShort_t[newsize];
00313             Int_t newpos, current;
00314             newpos = current = 0;
00315             for (i=0; i<kBlockSize*16; i++){
00316                if (!block->Contains(i)) continue;
00317                while(current < fNPassed && fIndices[current]<i){
00318                   newlist[newpos] = fIndices[current];
00319                   current++;
00320                   newpos++;
00321                }
00322                if (fIndices[current]==i) current++;
00323                newlist[newpos] = i;
00324                newpos++;
00325             }
00326             while(current<fNPassed){
00327                newlist[newpos] = fIndices[current];
00328                newpos++;
00329                current++;
00330             }
00331             delete [] fIndices;
00332             fIndices = newlist;
00333             fNPassed = newpos;
00334             fN = fNPassed;
00335          }
00336       }
00337    }
00338    fLastIndexQueried = -1;
00339    fLastIndexReturned = -1;
00340    OptimizeStorage();
00341    return GetNPassed();
00342 }
00343 
00344 //______________________________________________________________________________
00345 Int_t TEntryListBlock::GetNPassed()
00346 {
00347 //Returns the number of entries, passing the selection.
00348 //In case, when the block stores entries that pass (fPassing=1) returns fNPassed
00349 
00350    if (fPassing)
00351       return fNPassed;
00352    else
00353       return kBlockSize*16-fNPassed;
00354 }
00355 
00356 //______________________________________________________________________________
00357 Int_t TEntryListBlock::GetEntry(Int_t entry)
00358 {
00359 //Return entry #entry
00360 //See also Next()
00361 
00362    if (entry > kBlockSize*16) return -1;
00363    if (entry > GetNPassed()) return -1;
00364    if (entry == fLastIndexQueried+1) return Next();
00365    else {
00366       Int_t i=0; Int_t j=0; Int_t entries_found=0;
00367       if (fType==0){
00368          if ((fIndices[i] & (1<<j))!=0)
00369             entries_found++;
00370          while (entries_found<entry+1){
00371             if (j==15){i++; j=0;}
00372             else j++;
00373             if ((fIndices[i] & (1<<j))!=0)
00374                entries_found++;
00375          }
00376          fLastIndexQueried = entry;
00377          fLastIndexReturned = i*16+j;
00378          return fLastIndexReturned;
00379       }
00380       if (fType==1){
00381          if (fPassing){
00382             fLastIndexQueried = entry;
00383             fLastIndexReturned = fIndices[entry];
00384             return fIndices[entry];
00385          } else {
00386             fLastIndexQueried = entry;
00387             if (!fIndices || fNPassed==0){
00388                //all entries pass
00389                fLastIndexReturned = entry;
00390                return fLastIndexReturned;
00391             } 
00392             for (i=0; i<fIndices[0]; i++){               
00393                entries_found++;
00394                if (entries_found==entry+1){
00395                   fLastIndexReturned = i;
00396                   return fLastIndexReturned;
00397                }
00398             }
00399             for (i=0; i<fNPassed-1; i++){
00400                for (j=fIndices[i]+1; j<fIndices[i+1]; j++){
00401                   entries_found++;
00402                   if (entries_found==entry+1){
00403                      fLastIndexReturned = j;
00404                      return fLastIndexReturned;
00405                   }
00406                }
00407             }
00408             for (j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
00409                entries_found++;
00410                if (entries_found==entry+1){
00411                   fLastIndexReturned = j;
00412                   return fLastIndexReturned;
00413                }
00414             }
00415          }   
00416       }
00417       return -1;
00418    }
00419 }
00420 
00421 //______________________________________________________________________________
00422 Int_t TEntryListBlock::Next()
00423 {
00424 //Return the next non-zero entry
00425 //Faster than GetEntry() function
00426 
00427    if (fLastIndexQueried==GetNPassed()-1){
00428       fLastIndexQueried=-1;
00429       fLastIndexReturned = -1;
00430       return -1;
00431    }
00432 
00433    if (fType==0) {
00434       //bits
00435       Int_t i=0;
00436       Int_t j=0;
00437       fLastIndexReturned++;
00438       i = fLastIndexReturned>>4;
00439       j = fLastIndexReturned & 15;
00440       Bool_t result=(fIndices[i] & (1<<j))!=0;
00441       while (result==0){
00442          if (j==15) {j=0; i++;}
00443          else j++;
00444          result = (fIndices[i] & (1<<j))!=0;
00445       }
00446       fLastIndexReturned = i*16+j;
00447       fLastIndexQueried++;
00448       return fLastIndexReturned;
00449 
00450    } 
00451    if (fType==1) {
00452       fLastIndexQueried++;
00453       if (fPassing){
00454          fLastIndexReturned = fIndices[fLastIndexQueried];
00455          return fIndices[fLastIndexQueried];
00456       } else {
00457          fLastIndexReturned++;
00458          while (!Contains(fLastIndexReturned)){
00459             fLastIndexReturned++;
00460             }
00461          return fLastIndexReturned;
00462       }
00463       
00464    }
00465    return -1;
00466 }
00467 
00468 //______________________________________________________________________________
00469 void TEntryListBlock::Print(const Option_t *option) const
00470 {
00471    //Print the entries in this block
00472 
00473    TString opt = option;
00474    opt.ToUpper();
00475    if (opt.Contains("A")) PrintWithShift(0);
00476 }
00477 
00478 //______________________________________________________________________________
00479 void TEntryListBlock::PrintWithShift(Int_t shift) const
00480 {
00481    //print the indices of this block + shift (used from TEntryList::Print()) to 
00482    //print the corrent values
00483 
00484    Int_t i;
00485    if (fType==0){
00486       Int_t ibit, ibite;
00487       Bool_t result;
00488       for (i=0; i<kBlockSize*16; i++){
00489          ibite = i>>4;
00490          ibit = i & 15;
00491          result = (fIndices[ibite] & (1<<ibit))!=0;
00492          if (result)
00493             printf("%d\n", i+shift);
00494       }
00495    } else {
00496       if (fPassing){
00497          for (i=0; i<fNPassed; i++){
00498             printf("%d\n", fIndices[i]+shift);
00499          }
00500       } else {
00501          if (fNPassed==0){
00502             for (i=0; i<kBlockSize*16; i++)
00503                printf("%d\n", i+shift);
00504             return;
00505          }
00506          for (i=0; i<fIndices[0]; i++){
00507             printf("%d\n", i+shift);
00508          }
00509          for (i=0; i<fNPassed-1; i++){
00510             for (Int_t j=fIndices[i]+1; j<fIndices[i+1]; j++){
00511                printf("%d\n", j+shift);
00512             }
00513          }
00514          for (Int_t j=fIndices[fNPassed-1]+1; j<kBlockSize*16; j++){
00515             printf("%d\n", j+shift);
00516          }
00517       }
00518    }
00519 }
00520 
00521 
00522 //______________________________________________________________________________
00523 void TEntryListBlock::OptimizeStorage()
00524 {
00525    //if there are < kBlockSize or >kBlockSize*15 entries, change to an array representation
00526 
00527    if (fType!=0) return;
00528    if (fNPassed > kBlockSize*15)
00529       fPassing = 0;
00530    if (fNPassed<kBlockSize || !fPassing){
00531       //less than 4000 entries passing, makes sense to change from bits to list
00532       UShort_t *indexnew = new UShort_t[fNPassed];
00533       Transform(0, indexnew);
00534    }
00535 }
00536 
00537 
00538 //______________________________________________________________________________
00539 void TEntryListBlock::Transform(Bool_t dir, UShort_t *indexnew)
00540 {
00541    //Transform the existing fIndices
00542    //dir=0 - transform from bits to a list
00543    //dir=1 - tranform from a list to bits
00544 
00545    Int_t i=0;
00546    Int_t ilist = 0;
00547    Int_t ibite, ibit;
00548    if (!dir) {
00549          for (i=0; i<kBlockSize*16; i++){
00550             ibite = i >> 4;
00551             ibit = i & 15;
00552             Bool_t result = (fIndices[ibite] & (1<<ibit))!=0;
00553             if (result && fPassing){
00554                //fill with the entries that pass
00555                indexnew[ilist] = i;
00556                ilist++;
00557             }
00558             else if (!result && !fPassing){
00559                //fill with the entries that don't pass
00560                indexnew[ilist] = i;
00561                ilist++;
00562             }
00563          }
00564       if (fIndices)
00565          delete [] fIndices;
00566       fIndices = indexnew;
00567       fType = 1;
00568       if (!fPassing)
00569          fNPassed = kBlockSize*16-fNPassed;
00570       fN = fNPassed;
00571       return;
00572    }
00573 
00574 
00575    if (fPassing){
00576       for (i=0; i<kBlockSize; i++)
00577          indexnew[i] = 0;
00578       for (i=0; i<fNPassed; i++){
00579          ibite = fIndices[i]>>4;
00580          ibit = fIndices[i] & 15;
00581          indexnew[ibite] |= 1<<ibit;
00582       }
00583    } else {
00584       for (i=0; i<kBlockSize; i++)
00585          indexnew[i] = 65535;
00586       for (i=0; i<fNPassed; i++){
00587          ibite = fIndices[i]>>4;
00588          ibit = fIndices[i] & 15;
00589          indexnew[ibite] ^= 1<<ibit;
00590       }
00591       fNPassed = kBlockSize*16-fNPassed;
00592    } 
00593    if (fIndices)
00594       delete [] fIndices;
00595    fIndices = indexnew;
00596    fType = 0;
00597    fN = kBlockSize;
00598    fPassing = 1;
00599    return;
00600 }

Generated on Tue Jul 5 15:34:02 2011 for ROOT_528-00b_version by  doxygen 1.5.1