CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CondFormats/L1TObjects/interface/DTTFBitArray.h

Go to the documentation of this file.
00001 //-------------------------------------------------
00002 //
00003 //   Class: DTTFBitArray
00004 //
00005 //   Description: Manipulates arrays of bits
00006 //
00007 //
00008 //   Author List:
00009 //   C. Grandi
00010 //   Modifications: 
00011 //
00012 //
00013 //--------------------------------------------------
00014 #ifndef BIT_ARRAY_H_
00015 #define BIT_ARRAY_H_
00016 
00017 
00018 
00019 //---------------
00020 // C++ Headers --
00021 //---------------
00022 #include <cassert>
00023 #include <iostream>
00024 
00025 //              ---------------------
00026 //              -- Class Interface --
00027 //              ---------------------
00028 
00029 template<int N>
00030 class DTTFBitArray {
00031 
00032  public:
00033   class refToBit;
00034   friend class refToBit;
00035 
00036   // reference to bit class
00037   class refToBit{
00038     friend class DTTFBitArray;
00039 
00040     //refToBit();
00041 
00042   public:
00043     refToBit() {}
00044     refToBit(DTTFBitArray& b, int pos) {
00045       _word = &b.getWord(pos);
00046       _pos = getPosInWord(pos);
00047     }
00048     ~refToBit() {}
00049 
00050     refToBit& operator=(const int val) {
00051       if(val) {
00052         *_word |= getPosMask(_pos);
00053       } else {
00054         *_word &= ~(getPosMask(_pos));
00055       }
00056       return *this;
00057     }
00058 
00059     refToBit& operator=(const refToBit& rtb) {
00060       if( (*(rtb._word) & getPosMask(rtb._pos)) ) {
00061         *_word |= getPosMask(_pos);
00062       } else { 
00063         *_word &= ~getPosMask(_pos);
00064       }
00065       return *this;
00066     }
00067 
00068     int operator~() const { return ((*_word)&getPosMask(_pos))==0; }
00069 
00070     operator int() const { return ((*_word)&getPosMask(_pos))!=0; }
00071 
00072     refToBit& flip() {
00073       *_word^=getPosMask(_pos);
00074       return *this;
00075     }
00076     
00077   private:
00078     unsigned* _word;
00079     int _pos;
00080 
00081   };
00082 
00083   DTTFBitArray() {this->zero();}
00084 
00085   DTTFBitArray(const DTTFBitArray<N>& br) {
00086     for (int i=0;i<this->nWords();i++) {
00087       _data[i] = br._data[i];         
00088     }
00089     this->cleanUnused();
00090   }
00091   DTTFBitArray(const char* str) { 
00092     this->zero(); 
00093     this->assign(0,this->nBits(),str); 
00094     this->cleanUnused();
00095   }
00096   DTTFBitArray(const char* str, const int p, const int n) {
00097     this->zero(); 
00098     this->assign(p, n, str);
00099   }
00100   DTTFBitArray(const unsigned i) { 
00101     this->zero();
00102     _data[0] = i;                 // the nBit least sign. bits are considered
00103     this->cleanUnused();
00104   }
00105 /*
00106   DTTFBitArray(const unsigned long i) { 
00107     this->zero();
00108     unsigned j = i&static_cast<unsigned long>(0xffffffff);
00109     _data[0] = j;                 // the nBit least sign. bits are considered
00110     if(this->nBits()>32) {
00111       j=i>>32;
00112       _data[1] = j;
00113     }
00114     this->cleanUnused();
00115   }
00116 */
00117   //  Destructor 
00118   // ~DTTFBitArray() {}
00119   
00120   // Return number of bits
00121   inline int nBits() const { return N; }
00122   inline int size() const { return this->nBits(); }
00123   
00124   // Return number of words
00125   inline int nWords() const { return N/32+1; }
00126   
00127   // Return a data word
00128   unsigned dataWord(const int i) const {
00129     assert(i>=0 && i<this->nWords());
00130     return _data[i];
00131   }
00132   unsigned & dataWord(const int i) {
00133     assert(i>=0 && i<this->nWords());
00134     return _data[i];
00135   }
00136 
00137   // Return the dataword which contains bit in position
00138   unsigned & getWord(const int pos) {
00139     assert(pos>=0&& pos<this->nBits());
00140     return _data[pos/32];
00141   }
00142   unsigned getWord(const int pos) const {
00143     assert(pos>=0&& pos<this->nBits());
00144     return _data[pos/32];
00145   }
00146 
00147   // Return the position inside a word given the position in bitArray
00148   static int getPosInWord(const int pos) {
00149     // assert(pos>=0&& pos<this->nBits());
00150     return pos%32;
00151   }
00152   
00153   // Return the word mask for a given bit
00154   static unsigned getPosMask(const int pos) {
00155     return static_cast<unsigned>(1)<<getPosInWord(pos);
00156   }
00157 
00158   // how many bits are not used (most significative bits of last word)
00159   int unusedBits() const {
00160     if(this->nBits()==0)return 32;
00161     return 31-((this->nBits()-1)%32);
00162   }
00163  
00164   // mask to get rid of last word unused bits
00165   unsigned lastWordMask() const {
00166     return static_cast<unsigned>(0xffffffff)>>(this->unusedBits());
00167   }
00168 
00169   // set unused bits to 0
00170   void cleanUnused() {
00171     _data[this->nWords()-1] &= (this->lastWordMask());
00172   }
00173  
00174   // count non 0 bits
00175   int count() const {
00176     int n=0;
00177     for(int i=0;i<this->nBits();i++) {
00178       if(this->element(i))n++;
00179     }
00180     return n;
00181   }
00182  
00183   // true if any bit == 1
00184   int any() {
00185     int nw = this->nWords();
00186     int ub = unusedBits();
00187     if(this->dataWord(nw-1)<<ub!=0)return 1;
00188     if(nw>1){
00189       for (int iw=0;iw<nw-1;iw++){
00190         if(this->dataWord(iw)!=0) return 1;
00191       }
00192     }
00193     return 0;
00194   }    
00195  
00196   // true if any bit == 0
00197   int none() {
00198     int nw = this->nWords();
00199     int ub = unusedBits();
00200     if(this->dataWord(nw-1)<<ub!=0xffffffff)return 1;
00201     if(nw>1){
00202       for (int iw=0;iw<nw-1;iw++){
00203         if(this->dataWord(iw)!=0xffffffff) return 1;
00204       }
00205     }
00206     return 0;
00207   }    
00208  
00209   // Return i^th elemnet
00210   int element(const int pos) const {
00211     return (getWord(pos)&getPosMask(pos))!=static_cast<unsigned>(0);
00212   }
00213   inline int test(const int i) const { return element(i); }
00214 
00215   // Set/unset all elements
00216   void zero() {
00217     for (int i=0;i<this->nWords();i++) {
00218       _data[i] = 0x0;                // set to 0
00219     }
00220   }
00221   inline void reset() { zero(); }
00222 
00223   void one() {
00224     for (int i=0;i<this->nWords();i++) {
00225       _data[i] = 0xffffffff;       // set to 1
00226     }
00227   }
00228   
00229   // Set/unset i^th element
00230   void set(const int i)  { getWord(i) |= getPosMask(i); }
00231   void unset(const int i) { getWord(i) &= ~getPosMask(i); }
00232   inline void reset(const int i) { this->unset(i); }
00233   
00234   // Set the i^th element to a given value
00235   inline void set(const int i, const int val) { this->assign(i,1,val); }
00236   inline void set(const int i, const char* str) { this->assign(i,1,str); }
00237 
00238   // Set/unset many bits to a given integer/bitArray/string
00239   void assign(const int p, const int n, const int val) {
00240     assert(p>=0 && p+n<=this->nBits());  
00241     // only the n least significant bits of val are considered
00242     for(int i=0; i<n;i++){
00243       if(val>>i&1) {
00244         this->set(p+i);
00245       } else {
00246         this->unset(p+i);
00247       }
00248     }
00249   }
00250   void assign(const int p, const int n, const DTTFBitArray<N>& val) {
00251     assert(p>=0 && p+n<=this->nBits());  
00252     // only the n least significant bits of val are considered
00253     for(int i=0; i<n;i++){
00254       if(val.element(i)) {
00255         this->set(p+i);
00256       } else {
00257         this->unset(p+i);
00258       }
00259     }
00260   }
00261   void assign(const int p, const int n, const char* str) {
00262     assert(p>=0 && p+n<=this->nBits());  
00263     // only the n least significant bits of val are considered
00264     for(int i=0; i<n;i++){
00265       assert(str[i]=='1'||str[i]=='0');  
00266       if(str[i]=='1') {
00267         this->set(p+n-i-1);   // reading a string from left to right 
00268       } else {                // --> most significative bit is the one 
00269         this->unset(p+n-i-1); // with lower string index
00270       }
00271     }
00272   }
00273       
00274   // Read a given range in an unsigned integer 
00275   unsigned read(const int p, const int n) const {
00276     assert(p>=0 && p+n<=this->nBits());  
00277     assert(n<=32); // the output must fit in a 32 bit word
00278     // only the n least significant bits of val are considered
00279     unsigned out=0x0;
00280     for(int i=0; i<n;i++){
00281       if(this->test(p+i)) out |= 1<<i;
00282     }
00283     return out;
00284   }
00285 
00286   // Read DTTFBitArray in bytes. Returns a DTTFBitArray<8>
00287   DTTFBitArray<8> byte(const int i) const {
00288     DTTFBitArray<8> out;
00289     if(i>=0&&i<4*this->nWords()){
00290       unsigned k=(_data[i/4]>>8*(i%4))&0xff;
00291       out=k;
00292     }
00293     return out;
00294   }
00295   // Assignment
00296   DTTFBitArray<N>& operator=(const DTTFBitArray<N>& a) {
00297     if(this != &a) {
00298       for (int i=0;i<this->nWords();i++) {
00299         _data[i] = a._data[i];
00300       }
00301     }
00302     this->cleanUnused();
00303     return *this;
00304   }
00305   
00306   // Conversion from unsigned
00307   DTTFBitArray<N>& operator=(const unsigned i) {
00308     this->zero();
00309     _data[0] = i;                 // the nBit least sign. bits are considered
00310     this->cleanUnused();
00311     return *this;
00312   }
00313 /*    
00314   // Conversion from unsigned long
00315   DTTFBitArray<N>& operator=(const unsigned long i) {
00316     this->zero();
00317     unsigned j = i&0xffffffff;
00318     _data[0] = j;                 // the nBit least sign. bits are considered
00319     if(this->nBits()>32) {
00320       j=i>>32;
00321       _data[1] = j;
00322     }
00323     this->cleanUnused();
00324     return *this;
00325   }
00326 */    
00327   // Conversion from char
00328   DTTFBitArray<N>& operator=(const char* str) {
00329     this->zero();
00330     for(int i=0; i<this->nBits();i++){
00331       assert(str[i]=='1'||str[i]=='0');  
00332       if(str[i]=='1') {
00333         this->set(this->nBits()-i-1);   // reading a string from left to right 
00334       } else if(str[i]=='0') {    // --> most significative bit is the one 
00335         this->unset(this->nBits()-i-1); // with lower string index
00336       } else {
00337         break;                    // exit when find a char which is not 0 or 1
00338       }
00339     }
00340     this->cleanUnused();
00341     return *this;
00342   }
00343     
00344   // Print
00345   std::ostream & print(std::ostream& o=std::cout) const {
00346     for(int i = this->nBits()-1; i>=0; i--){
00347       o << this->element(i);
00348     }
00349     return o;
00350   }
00351   
00352   // direct access to set/read elements
00353   refToBit operator[](const int pos) { return refToBit(*this,pos); }
00354   int operator[](const int pos) const { return element(pos); }
00355   
00356   // logical operators ==
00357   bool operator==(const DTTFBitArray<N>& a) const {
00358    int nw = this->nWords();
00359     int ub = this->unusedBits();
00360     if(this->dataWord(nw-1)<<ub!=         // check last word
00361            a.dataWord(nw-1)<<ub)return 0;
00362     if(nw>1){
00363       for (int iw=0;iw<nw-1;iw++){
00364         if(this->dataWord(iw)!=a.dataWord(iw)) return 0;
00365       }
00366     }
00367     return 1;
00368   }
00369   
00370   // logical operators <
00371   bool operator<(const DTTFBitArray<N>& a) const {
00372     int nw = this->nWords();
00373     int ub = this->unusedBits();
00374     unsigned aaa = this->dataWord(nw-1)<<ub; // ignore unused bits
00375     unsigned bbb =     a.dataWord(nw-1)<<ub; // in both operands
00376     if        (aaa<bbb) {
00377       return 1;
00378     } else if (aaa>bbb) {
00379       return 0;
00380     }
00381     if(nw>1){
00382       for (int iw=nw-2;iw>=0;iw--){
00383         if        (this->dataWord(iw)<a.dataWord(iw)) {
00384           return 1;
00385         } else if (this->dataWord(iw)>a.dataWord(iw)) {
00386           return 0;
00387         }
00388       }
00389     }
00390     return 0;
00391   }
00392   
00393   // logical operators !=
00394   bool operator!=(const DTTFBitArray<N>& a) const { return !(a==*this); }
00395   
00396   // logical operators >=
00397   bool operator>=(const DTTFBitArray<N>& a) const{ return !(*this<a); }
00398   
00399   // logical operators >
00400   bool operator>(const DTTFBitArray<N>& a) const { return !(*this<a||*this==a); }
00401   
00402   // logical operators <=
00403   bool operator<=(const DTTFBitArray<N>& a) const { return !(*this>a); }
00404   
00405   // non-const bit by bit negation
00406   DTTFBitArray<N>& flip () {
00407     for(int i=0;i<this->nWords();i++) {
00408       _data[i] = ~_data[i];
00409     }
00410     return *this;
00411   }
00412 
00413   // const bit by bit negation
00414   DTTFBitArray<N> operator~ () const { return DTTFBitArray<N> (*this).flip(); }
00415 
00416   // bit by bit AND and assignment
00417   DTTFBitArray<N>& operator&= (const DTTFBitArray<N>& a) {
00418     for(int i = 0;i<this->nWords();i++) {
00419       this->dataWord(i) &= a.dataWord(i);
00420     }
00421     return *this;
00422   }    
00423 
00424   // bit by bit AND
00425   DTTFBitArray<N> operator&(const DTTFBitArray<N>& a) {return DTTFBitArray<N> (*this)&=a; }
00426   
00427   // bit by bit OR and assignment
00428   DTTFBitArray<N>& operator|=(const DTTFBitArray<N>& a) {
00429     for(int i = 0;i<this->nWords();i++) {
00430       this->dataWord(i) |= a.dataWord(i);
00431     }
00432     return *this;
00433   }    
00434 
00435   // bit by bit AND
00436   DTTFBitArray<N> operator|(const DTTFBitArray<N>& a) {return DTTFBitArray<N> (*this)|=a;}
00437   
00438   // bit by bit XOR and assignment
00439   DTTFBitArray<N>& operator^=(const DTTFBitArray<N>& a) {
00440     for(int i = 0;i<this->nWords();i++) {
00441       this->dataWord(i) ^= a.dataWord(i);
00442     }
00443     return *this;
00444   }    
00445 
00446   // bit by bit XOR
00447   DTTFBitArray<N> operator^(const DTTFBitArray<N>& a) {return DTTFBitArray<N> (*this)^=a; }
00448   
00449   // left shift and assignment
00450   DTTFBitArray<N>& operator<<=(const int n) {
00451     assert(n>=0&&n<this->nBits());
00452     if(n==0)return *this;
00453     int i=0;
00454     for(i=this->nBits()-1;i>=n;i--) this->set(i,this->element(i-n));
00455     for(i=n-1;i>=0;i--) this->unset(i);
00456     return *this;
00457   }
00458 
00459   // left shift 
00460   DTTFBitArray<N> operator<<(const int n) { return DTTFBitArray<N> (*this)<<=n; }
00461 
00462   // right shift and assignment
00463   DTTFBitArray<N>& operator>>=(const int n) {
00464     assert(n>=0&&n<this->nBits());
00465     if(n==0)return *this;
00466     int i=0;
00467     for(i=0;i<this->nBits()-n;i++) this->set(i,this->element(i+n));
00468     for(i=this->nBits()-n;i<this->nBits();i++) this->unset(i);
00469     return *this;
00470   }
00471 
00472   // right shift
00473   DTTFBitArray<N> operator>>(const int n) { return DTTFBitArray<N> (*this)>>=n; }
00474 
00475   // sum and assignment
00476   DTTFBitArray<N>& operator+=(const DTTFBitArray<N>& a) {
00477     int rep=0;
00478     int sum=0;
00479     for(int i=0;i<this->nBits();i++) {
00480       sum=this->element(i)^rep;
00481       rep=this->element(i)&rep;
00482       this->set(i,sum^a.element(i));
00483       rep|=(sum&a.element(i));
00484     }
00485     return *this;
00486   }
00487 
00488   // sum
00489   DTTFBitArray<N> operator+(const DTTFBitArray<N>& a) {return DTTFBitArray<N> (*this)+=a; }
00490 
00491   // postfix increment
00492   DTTFBitArray<N>& operator++(int) {
00493     int i = 0;
00494     while(i<this->nBits()&&this->element(i)==1) { this->unset(i); i++; }
00495     if(i<this->nBits())this->set(i);
00496     return *this;
00497   }
00498 
00499   // const 2 complement
00500   DTTFBitArray<N> twoComplement() const { return DTTFBitArray<N> (~*this)++; }
00501 
00502   // non-const 2 complement
00503   DTTFBitArray<N>& twoComplement() { 
00504     (*this).flip();
00505     (*this)++;
00506     return *this;
00507   }
00508 
00509   // subtract and assignment
00510   DTTFBitArray<N>& operator-=(const DTTFBitArray<N>& a) {
00511     return *this+=a.twoComplement();
00512   }
00513 
00514   // subtract
00515   DTTFBitArray<N> operator-(const DTTFBitArray<N>& a) {return DTTFBitArray<N> (*this)-=a; }
00516 
00517 private:
00518   
00519   unsigned _data[N/32+1];
00520 };
00521 
00522 /*
00523 template<int N>
00524 ostream & operator <<(ostream & o, const DTTFBitArray<N> &b) {
00525   b.print(o); return o;
00526 }
00527 */
00528 
00529 #endif