arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

bitVector.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 * CVS version control block - do not edit manually
00003 *  $RCSfile: bitVector.cpp,v $
00004 *  $Revision: 1.1 $
00005 *  $Date: 2003/09/05 04:20:11 $
00006 *  $Source: /usr/sci/projects/chimera/cvsroot/arbeit/gutz/mathGutz/bitVector.cpp,v $
00007 *************************************************************************
00008 * Aaron Lefohn
00009 * Userid:       lefohn
00010 * Email:        lefohn@eng.utah.edu
00011 **************************************************************************
00012 * This is the implementation for BitVector and BitRef classes
00013 *************************************************************************/
00014 
00015 #include "bitVector.h"
00016 #include <assert.h>
00017 
00018 namespace gutz {
00019 
00020 using namespace std;
00021 
00022 const uint g_BITS_PER_WORD = 8 * sizeof(uint);
00023 const uint g_POW_OF_2_BITS_PER_WORD = log(g_BITS_PER_WORD) / log(2);
00024 
00025 // ********* BitRef Class *************
00026 BitRef::BitRef( uint* wordPtr, uint bitNum) //Constructor 
00027 {
00028   m_wordPtr = wordPtr;
00029   m_mask    = bitMask(bitNum);
00030 }
00031 
00032 BitRef::BitRef( const BitRef& rhs)
00033 {
00034   m_wordPtr = rhs.m_wordPtr;
00035   m_mask    = rhs.m_mask;
00036 }
00037 
00038 //Test whether bit is TRUE or FALSE 
00039 bool BitRef::operator()() const
00040 {
00041   return ((*m_wordPtr) & m_mask) > 0;
00042 }
00043 
00044 //Assignment to other BitRef
00045 BitRef& BitRef::operator=(const BitRef& rhs)
00046 {
00047   if(this==&rhs) {return *this;}
00048 
00049   m_wordPtr = rhs.m_wordPtr;
00050   m_mask    = rhs.m_mask;
00051   
00052   return *this;
00053 } 
00054 
00055 //Set value 
00056 bool BitRef::operator=(const bool bVal)
00057 {
00058   if(bVal) {
00059     (*m_wordPtr) |= m_mask;
00060   }
00061   else {
00062     (*m_wordPtr) &= ~m_mask;
00063   }
00064   
00065   return bVal;
00066 }
00067 
00068 // ********* BitVector Class *************
00069 //Constructors
00070 
00071 // Create uninitialized BitVec of 'size' 
00072 BitVector::BitVector(const int numBits)
00073 {
00074   uint numWords = bits2Words(numBits);
00075   m_vec = arrayo1ui(numWords, (int)0);
00076   m_numBits = numBits;
00077 }
00078 
00079 // Create BitVec of 'size', with all elts init'd to 'initVal' 
00080 BitVector::BitVector(const int numBits, const bool initVal)
00081 {
00082   m_vec = arrayo1ui( bits2Words(numBits), (int)0 );
00083   m_numBits = numBits;
00084 
00085   //Set bits to all 1's or all 0's
00086   uint bits = fillWord(initVal);
00087   
00088   for(uint i=0; i<m_vec.size(); i++) {
00089     m_vec[i] = bits;
00090   }
00091 }
00092 
00093 // Create a BitVec from a 0/1 character string
00094 // NOTE: Will have an assertion failure if non-0/1 chars are found in char string
00095 BitVector::BitVector(const string& bitStr)
00096 {
00097   m_numBits = bitStr.size();
00098   m_vec = arrayo1ui( bits2Words(m_numBits), (int)0 );
00099 
00100   uint bitNum = 0;
00101   for(uint w=0; w < m_vec.size(); w++) {//Words (array elts)
00102     uint bitWord = 0;
00103     
00104     for(uint b=0; (b < g_BITS_PER_WORD) && (bitNum < m_numBits); b++) {//Bits in each word
00105       char aBit = bitStr[bitNum];
00106       assert( aBit=='0' || aBit=='1' );
00107       
00108       uint valMask = (aBit == '0') ? 0 : bitMask(b);
00109       bitWord |= valMask; // Add the new bit to the bitWord
00110       bitNum++;
00111     }
00112     m_vec[w] = bitWord;   // Add the new bitWord to the array
00113   }
00114       
00115   /* This should work, but is "might be" less efficient than the code above
00116   for(uint i=0; i < m_numBits; i++) {
00117     char aBit = bitString[i];
00118     assert( aBit=='0' || aBit=='1' );
00119     (*this)[i] = aBit=='0' ? false : true;
00120   }
00121   */
00122 }
00123 
00124 // Create BitVec from single word
00125 BitVector::BitVector( uint word )
00126 {
00127         m_vec = arrayo1ui( 1, word );
00128         m_numBits = 8 * sizeof(uint);
00129 }
00130 
00131 // Create BitVec from array of unsigned ints
00132 BitVector::BitVector( const arrayw1ui& data )      
00133 {
00134         m_vec = arrayo1ui( data.size(), (int)0 );
00135         m_numBits = 8 * sizeof(uint) * data.size();
00136 
00137         for(uint i=0; i < m_vec.size(); i++) {
00138                 m_vec[i] = data[i];
00139         }
00140 }
00141 
00142 // Create BitVec from array of unsigned bytes
00143 BitVector::BitVector(const arrayw1ub& data )
00144 {
00145         m_numBits = 8 * data.size();
00146         uint numWords = bits2Words(m_numBits);
00147         m_vec = arrayo1ui( numWords, (int)0 );
00148 
00149         int b = 0;//Byte index
00150         for(uint i=0; i < m_vec.size(); i++) {
00151                 uint word = 0;
00152                 word |= data[b+0];
00153                 word |= data[b+1];
00154                 word |= data[b+2];
00155                 word |= data[b+3];
00156                 b+=4;
00157 
00158                 m_vec[i] = word;
00159         }
00160 }
00161 
00162 //Copy Constructor
00163 BitVector::BitVector(const BitVector& rhs)
00164 {
00165   m_vec = rhs.m_vec;
00166   m_numBits = rhs.m_numBits;
00167 }
00168 
00169 BitVector::~BitVector()
00170 {}
00171 
00172 // Copy a bit vector
00173 BitVector& BitVector::operator= (const BitVector& rhs)
00174 {
00175   if(this==&rhs) {return *this;}
00176 
00177   m_vec = rhs.m_vec;
00178   m_numBits = rhs.m_numBits;
00179 
00180   return *this;
00181 }
00182 
00183 // Fill a bit_vector with value 
00184 BitVector& BitVector::operator= (const bool value)
00185 {
00186   uint bits = fillWord(value);
00187   
00188   for(uint i=0; i<m_vec.size(); i++) {
00189     m_vec[i] = bits;
00190   }
00191 
00192   return *this;
00193 }
00194 
00195 // Fill bit vector with a word-sized value
00196 BitVector& BitVector::operator= (const uint valWord)
00197 {
00198         for(uint i=0; i < m_vec.size(); i++) {
00199                 m_vec[i] = valWord;
00200         }
00201 
00202         return *this;
00203 }
00204 
00205 // Boolean NOT on a bit vector in-place 
00206 BitVector& BitVector::not()
00207 {
00208   for(uint i=0; i < m_vec.size(); i++) {
00209     m_vec[i] = ~(m_vec[i]);
00210   }
00211 
00212   return *this;
00213 }
00214 
00215 // Boolean AND operation on two bit vectors in-place 
00216 BitVector& BitVector::operator&= (const BitVector& rhs)
00217 {
00218   assert( this->size() == rhs.size() );
00219   for(uint i=0; i < m_vec.size(); i++) {
00220     m_vec[i] &= rhs.m_vec[i];
00221   }
00222 
00223   return *this;
00224 }
00225 
00226 // Boolean OR operation on two bit vectors in-place 
00227 BitVector& BitVector::operator|= (const BitVector& rhs)
00228 {
00229   assert( this->size() == rhs.size() );
00230   for(uint i=0; i < m_vec.size(); i++) {
00231     m_vec[i] |= rhs.m_vec[i];
00232   }
00233 
00234   return *this;
00235 }
00236 
00237 // Boolean XOR operation on two bit vectors in-place 
00238 BitVector& BitVector::operator^= (const BitVector& rhs)
00239 {
00240   assert( this->size() == rhs.size() );
00241   for(uint i=0; i < m_vec.size(); i++) {
00242     m_vec[i] ^= rhs.m_vec[i];
00243   }
00244 
00245   return *this;
00246 }
00247 
00248 // Difference set on two bit vectors in-place (creates 1 temporary)
00249 BitVector& BitVector::operator-= (const BitVector& rhs)
00250 {
00251   assert( this->size() == rhs.size() );
00252 
00253   return ((*this) &= ~rhs);
00254 }
00255 
00256 // Do all elts in bitVec have value 'u'?
00257 // NOTE: This is NOT an optimized operation!
00258 bool BitVector::operator== (const bool u)
00259 {
00260   //old version
00261   bool equal=true;
00262 
00263   for(uint i=0; i<m_numBits && equal; i++) {
00264     bool val = (*this)[i]();
00265     equal = (val == u);
00266   }
00267   
00268 
00269   /* (CURRENTLY BROKEN)
00270   //new version
00271   bool equal = true;
00272   uint inVal = fillWord(u);
00273 
00274   for(uint i=0; i<m_vec.size() && equal; i++) {
00275     if( (m_vec[i] & inVal) != m_vec[i] ) {
00276       equal = false;
00277     }
00278   }*/
00279 
00280   return equal;
00281 }
00282 
00283 // Check if no bit of vector has the value u
00284 // NOTE: This is NOT an optimized operation!
00285 // TODO: Optimize this function
00286 bool BitVector::operator!= (const bool u)
00287 {
00288   bool notEqual=false;
00289 
00290   for(uint i=0; i<m_numBits && (notEqual == false); i++) {
00291     bool val = (*this)[i]();
00292     notEqual = (val != u);
00293   }
00294   return notEqual;
00295 }
00296 
00297 // Returns number of true bits in vector
00298 uint BitVector::numTrueBits() const
00299 {
00300 /*  uint tCount = 0;         // # of true bits we found
00301   uint trueVal = UINT_MAX;
00302 
00303   for(uint w=0; w < m_vec.size(); w++) {
00304     uint word = m_vec[w];
00305     
00306     if( (trueVal & word) != 0 ) { //If the word contains some 1's, then find the individual bits
00307       uint mask = 1 << (g_BITS_PER_WORD-1);
00308 
00309       for(uint b=0; b < g_BITS_PER_WORD; b++) {
00310         if( (word & mask) != 0 ) {// If bit is 1
00311           tCount++;
00312         }
00313         mask >>= 1;
00314       }
00315     }
00316   }
00317 */
00318         uint tCount = 0;//# of true bit found in the bitVec
00319         for(uint w=0; w < m_vec.size(); w++) {//Loop over words 
00320                 tCount += numOnesInWord( m_vec[w] );
00321         }
00322 
00323         return tCount;
00324 }
00325 
00326 //TODO: Make this general for true or false?
00327 // Return a vector of bitIndices for all true bits in the bitVector
00328 // Note: Despite the similarity between this 'numTrueBits', they
00329 //       are separte for the sake of optimizations
00330 vector<uint> BitVector::trueBits() const
00331 {
00332         vector<uint> trueIndices(m_numBits); // Make it too big to avoid resizing inside loop
00333         uint tCount = 0;                     // # of true bits we found
00334         uint trueVal = UINT_MAX;
00335 
00336         for(uint w=0; w < m_vec.size(); w++) {
00337                 uint word = m_vec[w];
00338     
00339                 if( (trueVal & word) != 0 ) { //If the word contains some 1's, then find the individual bits
00340                         uint mask = 1 << (g_BITS_PER_WORD-1);
00341 
00342                         for(uint b=0; b < g_BITS_PER_WORD; b++) {
00343                                 if( (word & mask) != 0 ) {// If bit is 1
00344                                         trueIndices[tCount] = w * g_BITS_PER_WORD + b;
00345                                         tCount++;
00346                                 }
00347                                 mask >>= 1;
00348                         }
00349                 }
00350         }
00351 
00352         trueIndices.resize(tCount);
00353         return trueIndices;
00354 }
00355 
00356 // Non-memory-allocating version of 'trueBits()'
00357 void BitVector::trueBits( arrayw1ui& trueIndices ) const
00358 {
00359         assert( trueIndices.size() >= m_numBits );
00360         trueIndices.reshape( trueIndices.size() );
00361         
00362         uint tCount = 0;                     // # of true bits we found
00363         uint trueVal = UINT_MAX;
00364 
00365         for(uint w=0; w < m_vec.size(); w++) {
00366                 uint word = m_vec[w];
00367 
00368                 if( (trueVal & word) != 0 ) { //If the word contains some 1's, then find the individual bits
00369                         uint mask = 1 << (g_BITS_PER_WORD-1);
00370 
00371                         // TODO: Could speed this up by checking if byte is 0 before checking bits
00372                         for(uint b=0; b < g_BITS_PER_WORD; b++) {
00373                                 if( (word & mask) != 0 ) {// If bit is 1
00374                                         trueIndices[tCount] = w * g_BITS_PER_WORD + b;
00375                                         tCount++;
00376                                 }
00377                                 mask >>= 1;
00378                         }
00379                 }
00380         }
00381 
00382         trueIndices.reshape(tCount);
00383 }
00384 
00385 /* TODO: THis is WRONG!!
00386 // Return a vector of bitIndices for all false bits in the bitVector
00387 vector<uint> BitVector::falseBits() const
00388 {
00389   vector<uint> falseIndices(m_numBits); // Make it too big to avoid resizing inside loop. Fixed after loop.
00390   uint fCount = 0;                      // # of false bits we found
00391 
00392   for(uint w=0; w < m_vec.size(); w++) {
00393     uint word = m_vec[w];
00394     
00395     if( (word | 0) != 0 ) { //If the word contains some 1's, then find the individual bits
00396       uint mask = 1 << (g_BITS_PER_WORD-1);
00397 
00398       for(uint b=0; b < g_BITS_PER_WORD; b++) {
00399         if( (word & mask) != 0 ) {// If bit is 1
00400           trueIndices[tCount] = w * g_BITS_PER_WORD + b;
00401           tCount++;
00402         }
00403         mask >>= 1;
00404       }
00405     }
00406   }
00407 
00408   trueIndices.resize(tCount);
00409   return trueIndices;
00410 }*/
00411 
00412 // Compare two bit vectors for EQUALITY
00413 bool BitVector::operator== (const BitVector& bv)
00414 {
00415   assert( this->size() == bv.size() );
00416   bool equal=true;
00417 
00418   for(uint i=0; i<m_vec.size() && equal; i++) {
00419     equal = (m_vec[i] == bv.m_vec[i]);
00420   }
00421 
00422   return equal;
00423 }
00424 
00425 // Compare two bit vectors for INEQUALITY 
00426 bool BitVector::operator!= (const BitVector& bv)
00427 {
00428   assert( this->size() == bv.size() );
00429   bool equal = false;
00430   for(uint i=0; i<m_vec.size() && !equal; i++) {
00431     equal = (m_vec[i] != bv.m_vec[i]);
00432   }
00433 
00434   return equal;
00435 }
00436 
00437 // Boolean NOT on a bit vector 
00438 BitVector operator~ (const BitVector& rhs)
00439 {
00440   BitVector newVec = rhs;
00441   return newVec.not();
00442 }
00443 
00444 //For all ops that need 2 BitVectors as args, both vecs MUST be same length. Assertion failure if not same size.
00445 // Boolean AND operation on two bit vectors
00446 BitVector operator& (const BitVector& lhs, const BitVector& rhs)
00447 {
00448   assert( lhs.size() == rhs.size() );
00449   BitVector newVec = lhs;
00450   return newVec &= rhs;
00451 }
00452 
00453 // Boolean OR operation on two bit vectors 
00454 BitVector operator| (const BitVector& lhs, const BitVector& rhs)
00455 {
00456   assert( lhs.size() == rhs.size() );
00457   BitVector newVec = lhs;
00458   return newVec |= rhs;
00459 }
00460 
00461 // Boolean XOR operation on two bit vectors 
00462 BitVector operator^ (const BitVector& lhs, const BitVector& rhs)
00463 {
00464   assert( lhs.size() == rhs.size() );
00465   BitVector newVec = lhs;
00466   return newVec ^= rhs;
00467 }
00468 
00469 // Difference set on two bit vectors (creates 2 temporaries)
00470 BitVector operator- (const BitVector& lhs, const BitVector& rhs)
00471 {
00472   assert( lhs.size() == rhs.size() );
00473   return lhs & (~rhs);
00474 }
00475 
00476 ostream &operator<<(ostream& ostr, const BitVector& bv)
00477 {
00478   uint bitNum=0;
00479   for(uint w=0; w < bv.m_vec.size(); w++) {
00480     uint num = bv.m_vec[w];
00481     
00482     /*for(int b=g_BITS_PER_WORD - 1; (b>=0) && (bitNum<bv.m_numBits); b--) {
00483           if( modPowOf2( b+1, 2 ) == 0) { ostr << " ";}//if((b+1)%4 == 0) { ostr << " ";}
00484           ostr << getBinary(num, b);
00485       bitNum++;
00486      }*/
00487         for(int b=0; b < g_BITS_PER_WORD && (bitNum < bv.m_numBits); b++) {//(b>=0) && (bitNum<bv.m_numBits); b--) {
00488           if( modPowOf2( b, 2 ) == 0) { ostr << " ";}//if((b+1)%4 == 0) { ostr << " ";}
00489           ostr << getBinary(num, b);
00490       bitNum++;
00491      }
00492   }
00493   
00494   return ostr;
00495 }
00496 
00497 ostream &operator<<(ostream & ostr, const BitRef& bv)
00498 {
00499   ostr << (((*bv.m_wordPtr) & bv.m_mask) > 0);
00500   return ostr;
00501 }
00502 
00503 } // End of namespace gutz
00504 
00505 
00506 
00507 

Send questions, comments, and bug reports to:
jmk