LLVM API Documentation

BitVector.h

Go to the documentation of this file.
00001 //===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the BitVector class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_ADT_BITVECTOR_H
00015 #define LLVM_ADT_BITVECTOR_H
00016 
00017 #include "llvm/Support/MathExtras.h"
00018 #include <algorithm>
00019 #include <cassert>
00020 #include <cstring>
00021 
00022 namespace llvm {
00023 
00024 class BitVector {
00025   typedef unsigned long BitWord;
00026 
00027   enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * 8 };
00028 
00029   BitWord  *Bits;        // Actual bits. 
00030   unsigned Size;         // Size of bitvector in bits.
00031   unsigned Capacity;     // Size of allocated memory in BitWord.
00032 
00033 public:
00034   // Encapsulation of a single bit.
00035   class reference {
00036     friend class BitVector;
00037 
00038     BitWord *WordRef;
00039     unsigned BitPos;
00040 
00041     reference();  // Undefined
00042 
00043   public:
00044     reference(BitVector &b, unsigned Idx) {
00045       WordRef = &b.Bits[Idx / BITWORD_SIZE];
00046       BitPos = Idx % BITWORD_SIZE;
00047     }
00048 
00049     ~reference() {}
00050 
00051     reference& operator=(bool t) {
00052       if (t)
00053         *WordRef |= 1L << BitPos;
00054       else
00055         *WordRef &= ~(1L << BitPos);
00056       return *this;
00057     }
00058 
00059     operator bool() const {
00060       return ((*WordRef) & (1L << BitPos)) ? true : false;
00061     }
00062   };
00063 
00064 
00065   /// BitVector default ctor - Creates an empty bitvector.
00066   BitVector() : Size(0), Capacity(0) {
00067     Bits = 0;
00068   }
00069 
00070   /// BitVector ctor - Creates a bitvector of specified number of bits. All
00071   /// bits are initialized to the specified value.
00072   explicit BitVector(unsigned s, bool t = false) : Size(s) {
00073     Capacity = NumBitWords(s);
00074     Bits = new BitWord[Capacity];
00075     init_words(Bits, Capacity, t);
00076     if (t)
00077       clear_unused_bits();
00078   }
00079 
00080   /// BitVector copy ctor.
00081   BitVector(const BitVector &RHS) : Size(RHS.size()) {
00082     if (Size == 0) {
00083       Bits = 0;
00084       Capacity = 0;
00085       return;
00086     }
00087 
00088     Capacity = NumBitWords(RHS.size());
00089     Bits = new BitWord[Capacity];
00090     std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits);
00091   }
00092   
00093   ~BitVector() {
00094     delete[] Bits;
00095   }
00096 
00097   /// size - Returns the number of bits in this bitvector.
00098   unsigned size() const { return Size; }
00099 
00100   /// count - Returns the number of bits which are set.
00101   unsigned count() const {
00102     unsigned NumBits = 0;
00103     for (unsigned i = 0; i < NumBitWords(size()); ++i)
00104       if (sizeof(BitWord) == 4)
00105         NumBits += CountPopulation_32((uint32_t)Bits[i]);
00106       else if (sizeof(BitWord) == 8)
00107         NumBits += CountPopulation_64(Bits[i]);
00108       else
00109         assert(0 && "Unsupported!");
00110     return NumBits;
00111   }
00112 
00113   /// any - Returns true if any bit is set.
00114   bool any() const {
00115     for (unsigned i = 0; i < NumBitWords(size()); ++i)
00116       if (Bits[i] != 0)
00117         return true;
00118     return false;
00119   }
00120 
00121   /// none - Returns true if none of the bits are set.
00122   bool none() const {
00123     return !any();
00124   }
00125 
00126   /// find_first - Returns the index of the first set bit, -1 if none
00127   /// of the bits are set.
00128   int find_first() const {
00129     for (unsigned i = 0; i < NumBitWords(size()); ++i)
00130       if (Bits[i] != 0) {
00131         if (sizeof(BitWord) == 4)
00132           return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]);
00133         else if (sizeof(BitWord) == 8)
00134           return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
00135         else
00136           assert(0 && "Unsupported!");
00137       }
00138     return -1;
00139   }
00140 
00141   /// find_next - Returns the index of the next set bit following the
00142   /// "Prev" bit. Returns -1 if the next set bit is not found.
00143   int find_next(unsigned Prev) const {
00144     ++Prev;
00145     if (Prev >= Size)
00146       return -1;
00147 
00148     unsigned WordPos = Prev / BITWORD_SIZE;
00149     unsigned BitPos = Prev % BITWORD_SIZE;
00150     BitWord Copy = Bits[WordPos];
00151     // Mask off previous bits.
00152     Copy &= ~0L << BitPos;
00153 
00154     if (Copy != 0) {
00155       if (sizeof(BitWord) == 4)
00156         return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy);
00157       else if (sizeof(BitWord) == 8)
00158         return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
00159       else
00160         assert(0 && "Unsupported!");
00161     }
00162 
00163     // Check subsequent words.
00164     for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
00165       if (Bits[i] != 0) {
00166         if (sizeof(BitWord) == 4)
00167           return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]);
00168         else if (sizeof(BitWord) == 8)
00169           return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
00170         else
00171           assert(0 && "Unsupported!");
00172       }
00173     return -1;
00174   }
00175 
00176   /// clear - Clear all bits.
00177   void clear() {
00178     Size = 0;
00179   }
00180 
00181   /// resize - Grow or shrink the bitvector.
00182   void resize(unsigned N, bool t = false) {
00183     if (N > Capacity * BITWORD_SIZE) {
00184       unsigned OldCapacity = Capacity;
00185       grow(N);
00186       init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t);
00187     }
00188     
00189     // Set any old unused bits that are now included in the BitVector. This 
00190     // may set bits that are not included in the new vector, but we will clear 
00191     // them back out below.
00192     if (N > Size)
00193       set_unused_bits(t);
00194     
00195     // Update the size, and clear out any bits that are now unused
00196     unsigned OldSize = Size;
00197     Size = N;
00198     if (t || N < OldSize)
00199       clear_unused_bits();
00200   }
00201 
00202   void reserve(unsigned N) {
00203     if (N > Capacity * BITWORD_SIZE)
00204       grow(N);
00205   }
00206 
00207   // Set, reset, flip
00208   BitVector &set() {
00209     init_words(Bits, Capacity, true);
00210     clear_unused_bits();
00211     return *this;
00212   }
00213 
00214   BitVector &set(unsigned Idx) {
00215     Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
00216     return *this;
00217   }
00218 
00219   BitVector &reset() {
00220     init_words(Bits, Capacity, false);
00221     return *this;
00222   }
00223 
00224   BitVector &reset(unsigned Idx) {
00225     Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
00226     return *this;
00227   }
00228 
00229   BitVector &flip() {
00230     for (unsigned i = 0; i < NumBitWords(size()); ++i)
00231       Bits[i] = ~Bits[i];
00232     clear_unused_bits();
00233     return *this;
00234   }
00235 
00236   BitVector &flip(unsigned Idx) {
00237     Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE);
00238     return *this;
00239   }
00240 
00241   // No argument flip.
00242   BitVector operator~() const {
00243     return BitVector(*this).flip();
00244   }
00245 
00246   // Indexing.
00247   reference operator[](unsigned Idx) {
00248     assert (Idx < Size && "Out-of-bounds Bit access.");
00249     return reference(*this, Idx);
00250   }
00251 
00252   bool operator[](unsigned Idx) const {
00253     assert (Idx < Size && "Out-of-bounds Bit access.");   
00254     BitWord Mask = 1L << (Idx % BITWORD_SIZE);
00255     return (Bits[Idx / BITWORD_SIZE] & Mask) != 0;
00256   }
00257 
00258   bool test(unsigned Idx) const {
00259     return (*this)[Idx];
00260   }
00261 
00262   // Comparison operators.
00263   bool operator==(const BitVector &RHS) const {
00264     unsigned ThisWords = NumBitWords(size());
00265     unsigned RHSWords  = NumBitWords(RHS.size());
00266     unsigned i;
00267     for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
00268       if (Bits[i] != RHS.Bits[i])
00269         return false;
00270     
00271     // Verify that any extra words are all zeros.
00272     if (i != ThisWords) {
00273       for (; i != ThisWords; ++i)
00274         if (Bits[i])
00275           return false;
00276     } else if (i != RHSWords) {
00277       for (; i != RHSWords; ++i)
00278         if (RHS.Bits[i])
00279           return false;
00280     }
00281     return true;
00282   }
00283 
00284   bool operator!=(const BitVector &RHS) const {
00285     return !(*this == RHS);
00286   }
00287 
00288   // Intersection, union, disjoint union.
00289   BitVector operator&=(const BitVector &RHS) {
00290     unsigned ThisWords = NumBitWords(size());
00291     unsigned RHSWords  = NumBitWords(RHS.size());
00292     unsigned i;
00293     for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
00294       Bits[i] &= RHS.Bits[i];
00295     
00296     // Any bits that are just in this bitvector become zero, because they aren't
00297     // in the RHS bit vector.  Any words only in RHS are ignored because they
00298     // are already zero in the LHS.
00299     for (; i != ThisWords; ++i)
00300       Bits[i] = 0;
00301     
00302     return *this;
00303   }
00304 
00305   BitVector operator|=(const BitVector &RHS) {
00306     assert(Size == RHS.Size && "Illegal operation!");
00307     for (unsigned i = 0; i < NumBitWords(size()); ++i)
00308       Bits[i] |= RHS.Bits[i];
00309     return *this;
00310   }
00311 
00312   BitVector operator^=(const BitVector &RHS) {
00313     assert(Size == RHS.Size && "Illegal operation!");
00314     for (unsigned i = 0; i < NumBitWords(size()); ++i)
00315       Bits[i] ^= RHS.Bits[i];
00316     return *this;
00317   }
00318   
00319   // Assignment operator.
00320   const BitVector &operator=(const BitVector &RHS) {
00321     if (this == &RHS) return *this;
00322 
00323     Size = RHS.size();
00324     unsigned RHSWords = NumBitWords(Size);
00325     if (Size <= Capacity * BITWORD_SIZE) {
00326       std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits);
00327       clear_unused_bits();
00328       return *this;
00329     }
00330   
00331     // Grow the bitvector to have enough elements.
00332     Capacity = RHSWords;
00333     BitWord *NewBits = new BitWord[Capacity];
00334     std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits);
00335 
00336     // Destroy the old bits.
00337     delete[] Bits;
00338     Bits = NewBits;
00339 
00340     return *this;
00341   }
00342 
00343 private:
00344   unsigned NumBitWords(unsigned S) const {
00345     return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
00346   }
00347   
00348   // Set the unused bits in the high words.
00349   void set_unused_bits(bool t = true) {
00350     //  Set high words first.
00351     unsigned UsedWords = NumBitWords(Size);
00352     if (Capacity > UsedWords)
00353       init_words(&Bits[UsedWords], (Capacity-UsedWords), t);
00354     
00355     //  Then set any stray high bits of the last used word.
00356     unsigned ExtraBits = Size % BITWORD_SIZE;
00357     if (ExtraBits) {
00358       Bits[UsedWords-1] &= ~(~0L << ExtraBits);
00359       Bits[UsedWords-1] |= (0 - (BitWord)t) << ExtraBits;
00360     }
00361   }
00362 
00363   // Clear the unused bits in the high words.
00364   void clear_unused_bits() {
00365     set_unused_bits(false);
00366   }
00367 
00368   void grow(unsigned NewSize) {
00369     unsigned OldCapacity = Capacity;
00370     Capacity = NumBitWords(NewSize);
00371     BitWord *NewBits = new BitWord[Capacity];
00372 
00373     // Copy the old bits over.
00374     if (OldCapacity != 0)
00375       std::copy(Bits, &Bits[OldCapacity], NewBits);
00376 
00377     // Destroy the old bits.
00378     delete[] Bits;
00379     Bits = NewBits;
00380     
00381     clear_unused_bits();
00382   }
00383 
00384   void init_words(BitWord *B, unsigned NumWords, bool t) {
00385     memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
00386   } 
00387 };
00388 
00389 inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) {
00390   BitVector Result(LHS);
00391   Result &= RHS;
00392   return Result;
00393 }
00394 
00395 inline BitVector operator|(const BitVector &LHS, const BitVector &RHS) {
00396   BitVector Result(LHS);
00397   Result |= RHS;
00398   return Result;
00399 }
00400 
00401 inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) {
00402   BitVector Result(LHS);
00403   Result ^= RHS;
00404   return Result;
00405 }
00406  
00407 } // End llvm namespace
00408 #endif



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.