TBits.cxx

Go to the documentation of this file.
00001 // @(#)root/cont:$Id: TBits.cxx 29364 2009-07-06 23:58:23Z pcanal $
00002 // Author: Philippe Canal 05/02/2001
00003 //    Feb  5 2001: Creation
00004 //    Feb  6 2001: Changed all int to unsigned int.
00005 
00006 //////////////////////////////////////////////////////////////////////////
00007 //                                                                      //
00008 // TBits                                                                //
00009 //                                                                      //
00010 // Container of bits                                                    //
00011 //                                                                      //
00012 // This class provides a simple container of bits.                      //
00013 // Each bit can be set and tested via the functions SetBitNumber and    //
00014 // TestBitNumber.                                             .         //
00015 // The default value of all bits is kFALSE.                             //
00016 // The size of the container is automatically extended when a bit       //
00017 // number is either set or tested.  To reduce the memory size of the    //
00018 // container use the Compact function, this will discard the memory     //
00019 // occupied by the upper bits that are 0.                               //
00020 //                                                                      //
00021 //////////////////////////////////////////////////////////////////////////
00022 
00023 #include "TBits.h"
00024 #include "string.h"
00025 #include "Riostream.h"
00026 
00027 ClassImp(TBits)
00028 
00029 //______________________________________________________________________________
00030 TBits::TBits(UInt_t nbits) : fNbits(nbits)
00031 {
00032    // TBits constructor.  All bits set to 0
00033 
00034    if (nbits <= 0) nbits = 8;
00035    fNbytes  = ((nbits-1)/8) + 1;
00036    fAllBits = new UChar_t[fNbytes];
00037    // this is redundant only with libNew
00038    memset(fAllBits,0,fNbytes);
00039 }
00040 
00041 //______________________________________________________________________________
00042 TBits::TBits(const TBits &original) : TObject(original), fNbits(original.fNbits),
00043    fNbytes(original.fNbytes)
00044 {
00045    // TBits copy constructor
00046 
00047    fAllBits = new UChar_t[fNbytes];
00048    memcpy(fAllBits,original.fAllBits,fNbytes);
00049 
00050 }
00051 
00052 //______________________________________________________________________________
00053 TBits& TBits::operator=(const TBits& rhs)
00054 {
00055    // TBits assignment operator
00056 
00057    if (this != &rhs) {
00058       TObject::operator=(rhs);
00059       fNbits   = rhs.fNbits;
00060       fNbytes  = rhs.fNbytes;
00061       delete [] fAllBits;
00062       if (fNbytes != 0) {
00063          fAllBits = new UChar_t[fNbytes];
00064          memcpy(fAllBits,rhs.fAllBits,fNbytes);
00065       } else {
00066          fAllBits = 0;
00067       }
00068    }
00069    return *this;
00070 }
00071 
00072 //______________________________________________________________________________
00073 TBits::~TBits()
00074 {
00075    // TBits destructor
00076 
00077    delete [] fAllBits;
00078 }
00079 
00080 //______________________________________________________________________________
00081 void TBits::Clear(Option_t * /*option*/)
00082 {
00083    // Clear the value.
00084 
00085    delete [] fAllBits;
00086    fAllBits = 0;
00087    fNbits   = 0;
00088    fNbytes  = 0;
00089 }
00090 
00091 //______________________________________________________________________________
00092 void TBits::Compact()
00093 {
00094    // Reduce the storage used by the object to a minimun
00095 
00096    if (!fNbits || !fAllBits) return;
00097    UInt_t needed;
00098    for(needed=fNbytes-1;
00099        needed > 0 && fAllBits[needed]==0; ) { needed--; };
00100    needed++;
00101 
00102    if (needed!=fNbytes) {
00103       UChar_t *old_location = fAllBits;
00104       fAllBits = new UChar_t[needed];
00105 
00106       memcpy(fAllBits,old_location,needed);
00107       delete [] old_location;
00108 
00109       fNbytes = needed;
00110       fNbits = 8*fNbytes;
00111    }
00112 }
00113 
00114 //______________________________________________________________________________
00115 UInt_t TBits::CountBits(UInt_t startBit) const
00116 {
00117    // Return number of bits set to 1 starting at bit startBit
00118 
00119    static const Int_t nbits[256] = {
00120              0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
00121              1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
00122              1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
00123              2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
00124              1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
00125              2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
00126              2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
00127              3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
00128              1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
00129              2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
00130              2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
00131              3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
00132              2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
00133              3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
00134              3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
00135              4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
00136 
00137    UInt_t i,count = 0;
00138    if (startBit == 0) {
00139       for(i=0; i<fNbytes; i++) {
00140          count += nbits[fAllBits[i]];
00141       }
00142       return count;
00143    }
00144    if (startBit >= fNbits) return count;
00145    UInt_t startByte = startBit/8;
00146    UInt_t ibit = startBit%8;
00147    if (ibit) {
00148       for (i=ibit;i<8;i++) {
00149          if (fAllBits[startByte] & (1<<ibit)) count++;
00150       }
00151       startByte++;
00152    }
00153    for(i=startByte; i<fNbytes; i++) {
00154       count += nbits[fAllBits[i]];
00155    }
00156    return count;
00157 }
00158 
00159 //______________________________________________________________________________
00160 void TBits::DoAndEqual(const TBits& rhs)
00161 {
00162    // Execute (*this) &= rhs;
00163    // Extra bits in rhs are ignored
00164    // Missing bits in rhs are assumed to be zero.
00165 
00166    UInt_t min = (fNbytes<rhs.fNbytes) ? fNbytes : rhs.fNbytes;
00167    for(UInt_t i=0; i<min; ++i) {
00168       fAllBits[i] &= rhs.fAllBits[i];
00169    }
00170    if (fNbytes>min) {
00171       memset(&(fAllBits[min]),0,fNbytes-min);
00172    }
00173 }
00174 
00175 //______________________________________________________________________________
00176 void TBits::DoOrEqual(const TBits& rhs)
00177 {
00178    // Execute (*this) &= rhs;
00179    // Extra bits in rhs are ignored
00180    // Missing bits in rhs are assumed to be zero.
00181 
00182    UInt_t min = (fNbytes<rhs.fNbytes) ? fNbytes : rhs.fNbytes;
00183    for(UInt_t i=0; i<min; ++i) {
00184       fAllBits[i] |= rhs.fAllBits[i];
00185    }
00186 }
00187 
00188 //______________________________________________________________________________
00189 void TBits::DoXorEqual(const TBits& rhs)
00190 {
00191    // Execute (*this) ^= rhs;
00192    // Extra bits in rhs are ignored
00193    // Missing bits in rhs are assumed to be zero.
00194 
00195    UInt_t min = (fNbytes<rhs.fNbytes) ? fNbytes : rhs.fNbytes;
00196    for(UInt_t i=0; i<min; ++i) {
00197       fAllBits[i] ^= rhs.fAllBits[i];
00198    }
00199 }
00200 
00201 //______________________________________________________________________________
00202 void TBits::DoFlip()
00203 {
00204    // Execute ~(*this)
00205 
00206    for(UInt_t i=0; i<fNbytes; ++i) {
00207       fAllBits[i] = ~fAllBits[i];
00208    }
00209    // NOTE: out-of-bounds bit were also flipped!
00210 }
00211 
00212 //______________________________________________________________________________
00213 void TBits::DoLeftShift(UInt_t shift)
00214 {
00215    // Execute the left shift operation.
00216 
00217    if (shift==0) return;
00218    const UInt_t wordshift = shift / 8;
00219    const UInt_t offset = shift % 8;
00220    if (offset==0) {
00221       for(UInt_t n = fNbytes - 1; n >= wordshift; --n) {
00222          fAllBits[n] = fAllBits[ n - wordshift ];
00223       }
00224    } else {
00225       const UInt_t sub_offset = 8 - offset;
00226       for(UInt_t n = fNbytes - 1; n > wordshift; --n) {
00227          fAllBits[n] = (fAllBits[n - wordshift] << offset) |
00228                        (fAllBits[n - wordshift - 1] >> sub_offset);
00229       }
00230       fAllBits[wordshift] = fAllBits[0] << offset;
00231    }
00232    memset(fAllBits,0,wordshift);
00233 }
00234 
00235 //______________________________________________________________________________
00236 void TBits::DoRightShift(UInt_t shift)
00237 {
00238    // Execute the left shift operation.
00239 
00240    if (shift==0) return;
00241    const UInt_t wordshift = shift / 8;
00242    const UInt_t offset = shift % 8;
00243    const UInt_t limit = fNbytes - wordshift - 1;
00244 
00245    if (offset == 0)
00246       for (UInt_t n = 0; n <= limit; ++n)
00247          fAllBits[n] = fAllBits[n + wordshift];
00248    else
00249    {
00250       const UInt_t sub_offset = 8 - offset;
00251       for (UInt_t n = 0; n < limit; ++n)
00252          fAllBits[n] = (fAllBits[n + wordshift] >> offset) |
00253                        (fAllBits[n + wordshift + 1] << sub_offset);
00254       fAllBits[limit] = fAllBits[fNbytes-1] >> offset;
00255    }
00256 
00257    memset(&(fAllBits[limit + 1]),0, fNbytes - limit - 1);
00258 }
00259 
00260 //______________________________________________________________________________
00261 UInt_t TBits::FirstNullBit(UInt_t startBit) const
00262 {
00263    // Return position of first null bit (starting from position 0 and up)
00264 
00265    static const Int_t fbits[256] = {
00266              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00267              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
00268              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00269              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
00270              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00271              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
00272              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00273              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
00274              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00275              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
00276              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00277              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
00278              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00279              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
00280              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
00281              0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8};
00282 
00283    UInt_t i;
00284    if (startBit == 0) {
00285       for(i=0; i<fNbytes; i++) {
00286          if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
00287       }
00288       return fNbits;
00289    }
00290    if (startBit >= fNbits) return fNbits;
00291    UInt_t startByte = startBit/8;
00292    UInt_t ibit = startBit%8;
00293    if (ibit) {
00294       for (i=ibit;i<8;i++) {
00295          if ((fAllBits[startByte] & (1<<i)) == 0) return 8*startByte+i;
00296       }
00297       startByte++;
00298    }
00299    for(i=startByte; i<fNbytes; i++) {
00300       if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
00301    }
00302    return fNbits;
00303 }
00304 
00305 //______________________________________________________________________________
00306 UInt_t TBits::FirstSetBit(UInt_t startBit) const
00307 {
00308    // Return position of first non null bit (starting from position 0 and up)
00309 
00310    static const Int_t fbits[256] = {
00311              8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00312              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00313              5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00314              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00315              6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00316              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00317              5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00318              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00319              7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00320              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00321              5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00322              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00323              6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00324              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00325              5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
00326              4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
00327 
00328    UInt_t i;
00329    if (startBit == 0) {
00330       for(i=0; i<fNbytes; i++) {
00331          if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
00332       }
00333       return fNbits;
00334    }
00335    if (startBit >= fNbits) return fNbits;
00336    UInt_t startByte = startBit/8;
00337    UInt_t ibit = startBit%8;
00338    if (ibit) {
00339       for (i=ibit;i<8;i++) {
00340          if ((fAllBits[startByte] & (1<<i)) != 0) return 8*startByte+i;
00341       }
00342       startByte++;
00343    }
00344    for(i=startByte; i<fNbytes; i++) {
00345       if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
00346    }
00347    return fNbits;
00348 }
00349 
00350 //______________________________________________________________________________
00351 void TBits::Output(ostream &os) const
00352 {
00353    // Print the value to the ostream
00354 
00355    for(UInt_t i=0; i<fNbytes; ++i) {
00356       UChar_t val = fAllBits[fNbytes - 1 - i];
00357       for (UInt_t j=0; j<8; ++j) {
00358          os << (bool)(val&0x80);
00359          val <<= 1;
00360       }
00361    }
00362 }
00363 
00364 //______________________________________________________________________________
00365 void TBits::Paint(Option_t *)
00366 {
00367    // Once implemented, it will draw the bit field as an histogram.
00368    // use the TVirtualPainter as the usual trick
00369 
00370 }
00371 
00372 //______________________________________________________________________________
00373 void TBits::Print(Option_t *) const
00374 {
00375    // Print the list of active bits
00376 
00377    Int_t count = 0;
00378    for(UInt_t i=0; i<fNbytes; ++i) {
00379       UChar_t val = fAllBits[i];
00380       for (UInt_t j=0; j<8; ++j) {
00381          if (val & 1) printf(" bit:%4d = 1\n",count);
00382          count++;
00383          val = val >> 1;
00384       }
00385    }
00386 }
00387 
00388 //______________________________________________________________________________
00389 void TBits::ResetAllBits(Bool_t)
00390 {
00391    // Reset all bits to 0 (false).
00392 
00393    if (fAllBits) memset(fAllBits,0,fNbytes);
00394 }
00395 
00396 //______________________________________________________________________________
00397 void TBits::ReserveBytes(UInt_t nbytes)
00398 {
00399    // Reverse each bytes.
00400 
00401    if (nbytes > fNbytes) {
00402       // do it in this order to remain exception-safe.
00403       UChar_t *newBits=new UChar_t[nbytes];
00404       delete[] fAllBits;
00405       fNbytes=nbytes;
00406       fAllBits=newBits;
00407    }
00408 }
00409 
00410 //______________________________________________________________________________
00411 void TBits::Set(UInt_t nbits, const Char_t *array)
00412 {
00413    // Set all the bytes.
00414 
00415    UInt_t nbytes=(nbits+7)>>3;
00416 
00417    ReserveBytes(nbytes);
00418 
00419    fNbits=nbits;
00420    memcpy(fAllBits, array, nbytes);
00421 }
00422 
00423 //______________________________________________________________________________
00424 void TBits::Get(Char_t *array) const
00425 {
00426    // Copy all the byes.
00427 
00428    memcpy(array, fAllBits, (fNbits+7)>>3);
00429 }
00430 
00431  #ifdef R__BYTESWAP  /* means we are on little endian */
00432 
00433  /*
00434  If we are on a little endian machine, a bitvector represented using
00435  any integer type is identical to a bitvector represented using bytes.
00436  -- FP.
00437  */
00438 
00439 void TBits::Set(UInt_t nbits, const Short_t *array)
00440 {
00441    // Set all the bytes.
00442 
00443    Set(nbits, (const Char_t*)array);
00444 }
00445 
00446 void TBits::Set(UInt_t nbits, const Int_t *array)
00447 {
00448    // Set all the bytes.
00449 
00450    Set(nbits, (const Char_t*)array);
00451 }
00452 
00453 void TBits::Set(UInt_t nbits, const Long64_t *array)
00454 {
00455    // Set all the bytes.
00456 
00457    Set(nbits, (const Char_t*)array);
00458 }
00459 
00460 void TBits::Get(Short_t *array) const
00461 {
00462    // Get all the bytes.
00463 
00464    Get((Char_t*)array);
00465 }
00466 
00467 void TBits::Get(Int_t *array) const
00468 {
00469    // Get all the bytes.
00470 
00471    Get((Char_t*)array);
00472 }
00473 
00474 void TBits::Get(Long64_t *array) const
00475 {
00476    // Get all the bytes.
00477 
00478    Get((Char_t*)array);
00479 }
00480 
00481 #else
00482 
00483  /*
00484  If we are on a big endian machine, some swapping around is required.
00485  */
00486 
00487 void TBits::Set(UInt_t nbits, const Short_t *array)
00488 {
00489    // make nbytes even so that the loop below is neat.
00490    UInt_t nbytes = ((nbits+15)>>3)&~1;
00491 
00492    ReserveBytes(nbytes);
00493 
00494    fNbits=nbits;
00495 
00496    const UChar_t *cArray = (const UChar_t*)array;
00497    for (UInt_t i=0; i<nbytes; i+=2) {
00498       fAllBits[i] = cArray[i+1];
00499       fAllBits[i+1] = cArray[i];
00500    }
00501 }
00502 
00503 void TBits::Set(UInt_t nbits, const Int_t *array)
00504 {
00505    // make nbytes a multiple of 4 so that the loop below is neat.
00506    UInt_t nbytes = ((nbits+31)>>3)&~3;
00507 
00508    ReserveBytes(nbytes);
00509 
00510    fNbits=nbits;
00511 
00512    const UChar_t *cArray = (const UChar_t*)array;
00513    for (UInt_t i=0; i<nbytes; i+=4) {
00514       fAllBits[i] = cArray[i+3];
00515       fAllBits[i+1] = cArray[i+2];
00516       fAllBits[i+2] = cArray[i+1];
00517       fAllBits[i+3] = cArray[i];
00518    }
00519 }
00520 
00521 void TBits::Set(UInt_t nbits, const Long64_t *array)
00522 {
00523    // make nbytes a multiple of 8 so that the loop below is neat.
00524    UInt_t nbytes = ((nbits+63)>>3)&~7;
00525 
00526    ReserveBytes(nbytes);
00527 
00528    fNbits=nbits;
00529 
00530    const UChar_t *cArray = (const UChar_t*)array;
00531    for (UInt_t i=0; i<nbytes; i+=8) {
00532       fAllBits[i] = cArray[i+7];
00533       fAllBits[i+1] = cArray[i+6];
00534       fAllBits[i+2] = cArray[i+5];
00535       fAllBits[i+3] = cArray[i+4];
00536       fAllBits[i+4] = cArray[i+3];
00537       fAllBits[i+5] = cArray[i+2];
00538       fAllBits[i+6] = cArray[i+1];
00539       fAllBits[i+7] = cArray[i];
00540    }
00541 }
00542 
00543 void TBits::Get(Short_t *array) const
00544 {
00545    // Get all the bytes.
00546 
00547    UInt_t nBytes = (fNbits+7)>>3;
00548    UInt_t nSafeBytes = nBytes&~1;
00549 
00550    UChar_t *cArray=(UChar_t*)array;
00551    for (UInt_t i=0; i<nSafeBytes; i+=2) {
00552       cArray[i] = fAllBits[i+1];
00553       cArray[i+1] = fAllBits[i];
00554    }
00555 
00556    if (nBytes>nSafeBytes) {
00557       cArray[nSafeBytes+1] = fAllBits[nSafeBytes];
00558    }
00559 }
00560 
00561 void TBits::Get(Int_t *array) const
00562 {
00563    // Get all the bytes.
00564 
00565    UInt_t nBytes = (fNbits+7)>>3;
00566    UInt_t nSafeBytes = nBytes&~3;
00567 
00568    UChar_t *cArray=(UChar_t*)array;
00569    UInt_t i;
00570    for (i=0; i<nSafeBytes; i+=4) {
00571       cArray[i] = fAllBits[i+3];
00572       cArray[i+1] = fAllBits[i+2];
00573       cArray[i+2] = fAllBits[i+1];
00574       cArray[i+3] = fAllBits[i];
00575    }
00576 
00577    for (i=0; i<nBytes-nSafeBytes; ++i) {
00578       cArray[nSafeBytes + (3 - i)] = fAllBits[nSafeBytes + i];
00579    }
00580 }
00581 
00582 void TBits::Get(Long64_t *array) const
00583 {
00584    // Get all the bytes.
00585 
00586    UInt_t nBytes = (fNbits+7)>>3;
00587    UInt_t nSafeBytes = nBytes&~7;
00588 
00589    UChar_t *cArray=(UChar_t*)array;
00590    UInt_t i;
00591    for (i=0; i<nSafeBytes; i+=8) {
00592       cArray[i] = fAllBits[i+7];
00593       cArray[i+1] = fAllBits[i+6];
00594       cArray[i+2] = fAllBits[i+5];
00595       cArray[i+3] = fAllBits[i+4];
00596       cArray[i+4] = fAllBits[i+3];
00597       cArray[i+5] = fAllBits[i+2];
00598       cArray[i+6] = fAllBits[i+1];
00599       cArray[i+7] = fAllBits[i];
00600    }
00601 
00602    for (i=0; i<nBytes-nSafeBytes; ++i) {
00603       cArray[nSafeBytes + (7 - i)] = fAllBits[nSafeBytes + i];
00604    }
00605 }
00606 
00607 #endif
00608 
00609 Bool_t TBits::operator==(const TBits &other) const
00610 {
00611    // Compare object.
00612 
00613    if (fNbits == other.fNbits) {
00614       return !memcmp(fAllBits, other.fAllBits, (fNbits+7)>>3);
00615    } else if (fNbits <  other.fNbits) {
00616       return !memcmp(fAllBits, other.fAllBits, (fNbits+7)>>3) && other.FirstSetBit(fNbits) == other.fNbits;
00617    } else {
00618       return !memcmp(fAllBits, other.fAllBits, (other.fNbits+7)>>3) && FirstSetBit(other.fNbits) == fNbits;
00619    }
00620 }
00621 

Generated on Tue Jul 5 14:11:36 2011 for ROOT_528-00b_version by  doxygen 1.5.1