Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/tl/tlbitfield.h

Go to the documentation of this file.
00001  /*
00002  * lib/tl/tlbitfield.h 
00003  * 
00004  * Implementation of several bitfield templates for space-effcient storage 
00005  * of bits. 
00006  * 
00007  * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00008  * 
00009  * This file may be distributed and/or modified under the terms of the 
00010  * GNU General Public License version 2 as published by the Free Software 
00011  * Foundation. (See COPYING.GPL for details.)
00012  * 
00013  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00014  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00015  * 
00016  */
00017 
00018 #ifndef _TemplateLibrary_BitField_H_
00019 #define _TemplateLibrary_BitField_H_ 1
00020 
00029 #include <lib/sconfig.h>    /* MUST be first */
00030 
00031 #include <lib/salloc.h>
00032 
00033 
00043 template<typename T>inline uint CountBitsSet(T x)
00044 {
00045     uint sum=0;
00046 #if 0
00047     // According to tests, this is slightly slower. (WW)
00048     while(x)
00049     {  sum+=uint(x&T(1));  x>>=1;  }
00050 #else
00051     // According to tests, this is slightly faster. (WW)
00052     for(; x; sum++)
00053     {  x &= x-T(1);  }
00054 #endif
00055     return(sum);
00056 }
00057 
00065 template<typename T>inline uint CountBitsCleared(T x)
00066     {  return(uint(8*sizeof(T))-CountBitsSet(x));  }
00067 
00068 
00081 template<typename T>inline int SearchFirstSetBit(T x)
00082 {
00083 #if 1
00084     T tst=T(1);
00085     for(int s=0; s<int(8*sizeof(T)); tst<<=1,s++)  if(x&tst)  return(s);
00086     return(-1);
00087 #else
00088     // NOTE: This is actually SLOWER than the above!
00089     // Also, only works for sizeof(T)=sizeof(int). 
00090     return(x ? __builtin_ctz(x) : -1);   DO NOT USE.
00091 #endif
00092 }
00093 
00104 template<typename T>inline int SearchFirstClearedBit(T x)
00105 {
00106     T tst=T(1);
00107     for(int s=0; s<int(8*sizeof(T)); tst<<=1,s++)  if(!(x&tst))  return(s);
00108     return(-1);
00109 }
00110 
00111 
00136 template<typename T,size_t N>class TLStaticBitField
00137 {
00138     friend int DoTestBitFields();
00139     public:
00142         typedef uint nents_t;
00143         
00144     private:
00146         static const nents_t nents = (N+8*sizeof(T)-1)/(8*sizeof(T));
00148         static const T band = T(8*sizeof(T)-1);
00150         static const int bshift = 
00151             sizeof(T)==1 ? 3 : 
00152             sizeof(T)==2 ? 4 : 
00153             sizeof(T)==4 ? 5 : 
00154             sizeof(T)==8 ? 6 : 
00155             sizeof(T)==16 ? 7 : 8;
00157         static const size_t bits_per_ent=8*sizeof(T);
00159         //--------
00160         // Ignore warning about left shift count >= width of type; this only 
00161         // happens for fast=1 which is caught in the other branch of the ?:. 
00162         static const T exmask = ( (N % (8*sizeof(T)))==0 ) ? 
00163             T(0) : ~((T(1)<<(N % (8*sizeof(T))))-1);
00164         
00166         static const T all_clr = T(0);
00168         static const T all_set = ~all_clr;
00169         
00171         T bits[nents];
00172         
00174         inline void _SetAllEnts(T val)
00175             {  for(nents_t i=0; i<nents; i++)  bits[i]=val;  }
00177         inline void _CopyFrom(const TLStaticBitField<T,N> &b)
00178             {  for(nents_t i=0; i<nents; i++)  bits[i]=b.bits[i];  }
00179         
00180     public:
00182         inline TLStaticBitField() {}
00184         inline TLStaticBitField(bool bitval)
00185             {  _SetAllEnts(bitval ? all_set : all_clr);  }
00187         inline TLStaticBitField(const TLStaticBitField<T,N> &b)
00188             {  _CopyFrom(b);  }
00190         inline ~TLStaticBitField() {}
00191         
00193         inline TLStaticBitField &operator=(const TLStaticBitField<T,N> &b)
00194             {  _CopyFrom(b);  return(*this);  }
00195         
00197         inline void SetBit(size_t bit)
00198             {  bits[bit>>bshift]|=T(1)<<(bit & band);  }
00200         inline void ClrBit(size_t bit)
00201             {  bits[bit>>bshift]&=~(T(1)<<(bit & band));  }
00203         inline bool GetBit(size_t bit)
00204             {  return((bits[bit>>bshift]>>(bit & band))&T(1));  }
00206         inline void AssBit(size_t bit,bool val)
00207             {  if(val) SetBit(bit); else ClrBit(bit);  }
00208         
00210         inline void SetAll()
00211             {  _SetAllEnts(all_set);  }
00213         inline void ClrAll()
00214             {  _SetAllEnts(all_clr);  }
00215         
00217         inline size_t CountSet()  // non-const!
00218         {
00219             bits[nents-1]&=~exmask;   // Clear excess bits. 
00220             size_t sum=0;
00221             for(nents_t i=0; i<nents; i++)  sum+=CountBitsSet(bits[i]);
00222             return(sum);
00223         }
00224         
00226         inline size_t CountClr()  // non-const!
00227         {
00228             bits[nents-1]|=exmask;   // Set excess bits. 
00229             size_t sum=0;
00230             for(nents_t i=0; i<nents; i++)  sum+=CountBitsCleared(bits[i]);
00231             return(sum);
00232         }
00233         
00239         inline ssize_t SearchFirstSet()  // non-const!
00240         {
00241             bits[nents-1]&=~exmask;   // Clear excess bits. 
00242             for(nents_t i=0; i<nents; i++)
00243                 if(bits[i]!=all_clr)
00244                     return(SearchFirstSetBit(bits[i])+ssize_t(i*bits_per_ent));
00245             return(-1);
00246         }
00247         
00253         inline ssize_t SearchFirstClr()  // non-const!
00254         {
00255             bits[nents-1]|=exmask;   // Set excess bits. 
00256             for(nents_t i=0; i<nents; i++)
00257                 if(bits[i]!=all_set)
00258                     return(SearchFirstClearedBit(bits[i])+
00259                         ssize_t(i*bits_per_ent));
00260             return(-1);
00261         }
00262 };
00263 
00264 
00283 template<typename T>class TLDynamicBitField
00284 {
00285     friend int DoTestBitFields();
00286     public:
00289         typedef uint nents_t;
00290         
00291     private:
00293         static const T band = T(8*sizeof(T)-1);
00295         static const int bshift = 
00296             sizeof(T)==1 ? 3 : 
00297             sizeof(T)==2 ? 4 : 
00298             sizeof(T)==4 ? 5 : 
00299             sizeof(T)==8 ? 6 : 
00300             sizeof(T)==16 ? 7 : 8;
00302         static const size_t bits_per_ent=8*sizeof(T);
00303         
00305         static const T all_clr = T(0);
00307         static const T all_set = ~all_clr;
00308         
00310         size_t N;
00312         nents_t nents;
00314         T *bits;
00316         //--------
00317         // Ignore warning about left shift count >= width of type; this only 
00318         // happens for fast=1 which is caught in the other branch of the ?:. 
00319         T exmask;
00320         
00322         inline void _SetAllEnts(T val)
00323             {  for(nents_t i=0; i<nents; i++)  bits[i]=val;  }
00325         inline void _CopyFrom(const TLDynamicBitField<T> &b)
00326         {
00327             N=b.N;  nents=b.nents;  exmask=b.exmask;  bits=ALLOC<T>(nents);
00328             for(nents_t i=0; i<nents; i++)  bits[i]=b.bits[i];
00329         }
00331         static inline nents_t _NEntsOfN(size_t _N)
00332             {  return( (_N+8*sizeof(T)-1)/(8*sizeof(T)) );  }
00334         inline void _SetVals(size_t _N)
00335         {
00336             N=_N;  nents = _NEntsOfN(N);
00337             uint32 md = N % (8*sizeof(T));
00338             exmask = ( md==0 ) ? T(0) : ~((T(1)<<md)-1);
00339         }
00341         inline void _Initialize(size_t _N)
00342             {  _SetVals(_N);  bits=ALLOC<T>(nents);  }
00344         inline void _Free()
00345             {  bits=FREE(bits);  N=0;  nents=0;  }
00346         
00347     public:
00349         inline TLDynamicBitField(size_t _N)  {  _Initialize(_N);  }
00352         inline TLDynamicBitField(size_t _N,bool bitval)
00353             {  _Initialize(_N);  _SetAllEnts(bitval ? all_set : all_clr);  }
00355         inline TLDynamicBitField(const TLDynamicBitField<T> &b)
00356             {  _CopyFrom(b);  }
00358         inline ~TLDynamicBitField()
00359             {  _Free();  }
00360         
00362         inline TLDynamicBitField &operator=(const TLDynamicBitField<T> &b)
00363             {  _Free();  _CopyFrom(b);  return(*this);  }
00364         
00375         inline void resize(size_t newN)
00376         {
00377             if(_NEntsOfN(newN)!=nents)
00378             {  _SetVals(newN);  bits=REALLOC<T>(nents);  }
00379         }
00380         
00392         inline void resize(size_t newN,bool ini_val)
00393         {
00394             T val;   // The following does also set/clear excess bits. 
00395             if(ini_val) {  val=all_set;  bits[nents-1]|=exmask;  }
00396             else        {  val=all_clr;  bits[nents-1]&=~exmask;  }
00397             nents_t old_nents=nents;  resize(newN);
00398             for(; old_nents<nents; old_nents++)  bits[old_nents]=val;
00399         }
00400         
00402         inline void SetBit(size_t bit)
00403             {  bits[bit>>bshift]|=T(1)<<(bit & band);  }
00405         inline void ClrBit(size_t bit)
00406             {  bits[bit>>bshift]&=~(T(1)<<(bit & band));  }
00408         inline bool GetBit(size_t bit)
00409             {  return((bits[bit>>bshift]>>(bit & band))&T(1));  }
00411         inline void AssBit(size_t bit,bool val)
00412             {  if(val) SetBit(bit); else ClrBit(bit);  }
00413         
00415         inline void SetAll()
00416             {  _SetAllEnts(all_set);  }
00418         inline void ClrAll()
00419             {  _SetAllEnts(all_clr);  }
00420         
00422         inline size_t CountSet()  // non-const!
00423         {
00424             bits[nents-1]&=~exmask;   // Clear excess bits. 
00425             size_t sum=0;
00426             for(nents_t i=0; i<nents; i++)  sum+=CountBitsSet(bits[i]);
00427             return(sum);
00428         }
00429         
00431         inline size_t CountClr()  // non-const!
00432         {
00433             bits[nents-1]|=exmask;   // Set excess bits. 
00434             size_t sum=0;
00435             for(nents_t i=0; i<nents; i++)  sum+=CountBitsCleared(bits[i]);
00436             return(sum);
00437         }
00438         
00444         inline ssize_t SearchFirstSet()  // non-const!
00445         {
00446             bits[nents-1]&=~exmask;   // Clear excess bits. 
00447             for(nents_t i=0; i<nents; i++)
00448                 if(bits[i]!=all_clr)
00449                     return(SearchFirstSetBit(bits[i])+ssize_t(i*bits_per_ent));
00450             return(-1);
00451         }
00452         
00458         inline ssize_t SearchFirstClr()  // non-const!
00459         {
00460             bits[nents-1]|=exmask;   // Set excess bits. 
00461             for(nents_t i=0; i<nents; i++)
00462                 if(bits[i]!=all_set)
00463                     return(SearchFirstClearedBit(bits[i])+
00464                         ssize_t(i*bits_per_ent));
00465             return(-1);
00466         }
00467 };
00468 
00471 
00472 #endif  /* _TemplateLibrary_BitField_H_ */

Generated on Sat Feb 19 22:33:46 2005 for Ray by doxygen 1.3.5