make operator== work with non-equal sized bitvectors, as long as
[oota-llvm.git] / include / llvm / ADT / BitVector.h
index 79c3f585677353e7219029879ce0c2c12190d3d4..000cdd3d67e34656e9ceec0c8c878b5177018471 100644 (file)
 #define LLVM_ADT_BITVECTOR_H
 
 #include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cstdlib>
+#include <cassert>
 
 namespace llvm {
 
 class BitVector {
   typedef unsigned long BitWord;
 
-  enum { BITS_PER_WORD = sizeof(BitWord) * 8 };
+  enum { BITWORD_SIZE = sizeof(BitWord) * 8 };
 
   BitWord  *Bits;        // Actual bits. 
   unsigned Size;         // Size of bitvector in bits.
@@ -39,8 +42,8 @@ public:
 
   public:
     reference(BitVector &b, unsigned Idx) {
-      WordRef = &b.Bits[Idx / BITS_PER_WORD];
-      BitPos = Idx % BITS_PER_WORD;
+      WordRef = &b.Bits[Idx / BITWORD_SIZE];
+      BitPos = Idx % BITWORD_SIZE;
     }
 
     ~reference() {}
@@ -86,6 +89,10 @@ public:
     Bits = new BitWord[Capacity];
     std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits);
   }
+  
+  ~BitVector() {
+    delete[] Bits;
+  }
 
   /// size - Returns the number of bits in this bitvector.
   unsigned size() const { return Size; }
@@ -120,8 +127,14 @@ public:
   /// of the bits are set.
   int find_first() const {
     for (unsigned i = 0; i < NumBitWords(size()); ++i)
-      if (Bits[i] != 0)
-        return i * BITS_PER_WORD + CountTrailingZeros_32(Bits[i]);
+      if (Bits[i] != 0) {
+        if (sizeof(BitWord) == 4)
+          return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
+        else if (sizeof(BitWord) == 8)
+          return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
+        else
+          assert(0 && "Unsupported!");
+      }
     return -1;
   }
 
@@ -132,19 +145,31 @@ public:
     if (Prev >= Size)
       return -1;
 
-    unsigned WordPos = Prev / BITS_PER_WORD;
-    unsigned BitPos = Prev % BITS_PER_WORD;
+    unsigned WordPos = Prev / BITWORD_SIZE;
+    unsigned BitPos = Prev % BITWORD_SIZE;
     BitWord Copy = Bits[WordPos];
     // Mask off previous bits.
-    Copy &= ~0 << BitPos;
+    Copy &= ~0L << BitPos;
 
-    if (Copy != 0)
-      return WordPos * BITS_PER_WORD + CountTrailingZeros_32(Copy);
+    if (Copy != 0) {
+      if (sizeof(BitWord) == 4)
+        return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy);
+      else if (sizeof(BitWord) == 8)
+        return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
+      else
+        assert(0 && "Unsupported!");
+    }
 
     // Check subsequent words.
     for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
-      if (Bits[i] != 0)
-        return i * BITS_PER_WORD + CountTrailingZeros_32(Bits[i]);
+      if (Bits[i] != 0) {
+        if (sizeof(BitWord) == 4)
+          return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
+        else if (sizeof(BitWord) == 8)
+          return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
+        else
+          assert(0 && "Unsupported!");
+      }
     return -1;
   }
 
@@ -155,17 +180,27 @@ public:
 
   /// resize - Grow or shrink the bitvector.
   void resize(unsigned N, bool t = false) {
-    if (N > Capacity * BITS_PER_WORD) {
+    if (N > Capacity * BITWORD_SIZE) {
       unsigned OldCapacity = Capacity;
       grow(N);
       init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t);
     }
+    
+    // Set any old unused bits that are now included in the BitVector. This 
+    // may set bits that are not included in the new vector, but we will clear 
+    // them back out below.
+    if (N > Size)
+      set_unused_bits(t);
+    
+    // Update the size, and clear out any bits that are now unused
+    unsigned OldSize = Size;
     Size = N;
-    clear_unused_bits();
+    if (t || N < OldSize)
+      clear_unused_bits();
   }
 
   void reserve(unsigned N) {
-    if (N > Capacity * BITS_PER_WORD)
+    if (N > Capacity * BITWORD_SIZE)
       grow(N);
   }
 
@@ -177,7 +212,7 @@ public:
   }
 
   BitVector &set(unsigned Idx) {
-    Bits[Idx / BITS_PER_WORD] |= 1L << (Idx % BITS_PER_WORD);
+    Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
     return *this;
   }
 
@@ -187,7 +222,7 @@ public:
   }
 
   BitVector &reset(unsigned Idx) {
-    Bits[Idx / BITS_PER_WORD] &= ~(1L << (Idx % BITS_PER_WORD));
+    Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
     return *this;
   }
 
@@ -199,7 +234,7 @@ public:
   }
 
   BitVector &flip(unsigned Idx) {
-    Bits[Idx / BITS_PER_WORD] ^= 1L << (Idx % BITS_PER_WORD);
+    Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE);
     return *this;
   }
 
@@ -214,8 +249,8 @@ public:
   }
 
   bool operator[](unsigned Idx) const {
-    BitWord Mask = 1L << (Idx % BITS_PER_WORD);
-    return (Bits[Idx / BITS_PER_WORD] & Mask) != 0;
+    BitWord Mask = 1L << (Idx % BITWORD_SIZE);
+    return (Bits[Idx / BITWORD_SIZE] & Mask) != 0;
   }
 
   bool test(unsigned Idx) const {
@@ -224,12 +259,23 @@ public:
 
   // Comparison operators.
   bool operator==(const BitVector &RHS) const {
-    if (Size != RHS.Size)
-      return false;
-
-    for (unsigned i = 0; i < NumBitWords(size()); ++i)
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    unsigned i;
+    for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
       if (Bits[i] != RHS.Bits[i])
         return false;
+    
+    // Verify that any extra words are all zeros.
+    if (i != ThisWords) {
+      for (; i != ThisWords; ++i)
+        if (Bits[i])
+          return false;
+    } else if (i != RHSWords) {
+      for (; i != RHSWords; ++i)
+        if (RHS.Bits[i])
+          return false;
+    }
     return true;
   }
 
@@ -239,9 +285,18 @@ public:
 
   // Intersection, union, disjoint union.
   BitVector operator&=(const BitVector &RHS) {
-    assert(Size == RHS.Size && "Illegal operation!");
-    for (unsigned i = 0; i < NumBitWords(size()); ++i)
+    unsigned ThisWords = NumBitWords(size());
+    unsigned RHSWords  = NumBitWords(RHS.size());
+    unsigned i;
+    for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
       Bits[i] &= RHS.Bits[i];
+    
+    // Any bits that are just in this bitvector become zero, because they aren't
+    // in the RHS bit vector.  Any words only in RHS are ignored because they
+    // are already zero in the LHS.
+    for (; i != ThisWords; ++i)
+      Bits[i] = 0;
+    
     return *this;
   }
 
@@ -265,14 +320,14 @@ public:
 
     Size = RHS.size();
     unsigned RHSWords = NumBitWords(Size);
-    if (Size <= Capacity * BITS_PER_WORD) {
+    if (Size <= Capacity * BITWORD_SIZE) {
       std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits);
       clear_unused_bits();
       return *this;
     }
   
     // Grow the bitvector to have enough elements.
-    Capacity = NumBitWords(Size);
+    Capacity = RHSWords;
     BitWord *NewBits = new BitWord[Capacity];
     std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits);
 
@@ -285,18 +340,27 @@ public:
 
 private:
   unsigned NumBitWords(unsigned S) const {
-    return (S + BITS_PER_WORD-1) / BITS_PER_WORD;
+    return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
+  }
+  
+  // Set the unused bits in the high words.
+  void set_unused_bits(bool t = true) {
+    //  Set high words first.
+    unsigned UsedWords = NumBitWords(Size);
+    if (Capacity > UsedWords)
+      init_words(&Bits[UsedWords], (Capacity-UsedWords), t);
+    
+    //  Then set any stray high bits of the last used word.
+    unsigned ExtraBits = Size % BITWORD_SIZE;
+    if (ExtraBits) {
+      Bits[UsedWords-1] &= ~(~0L << ExtraBits);
+      Bits[UsedWords-1] |= (0 - (BitWord)t) << ExtraBits;
+    }
   }
 
-  // Clear the unused top bits in the high word.
+  // Clear the unused bits in the high words.
   void clear_unused_bits() {
-    if (Size) {
-      unsigned ExtraBits = Size % BITS_PER_WORD;
-      unsigned index = Size / BITS_PER_WORD;
-      if (Size % BITS_PER_WORD == 0)
-        index--;
-      Bits[index] &= ~(~0 << ExtraBits);
-    }
+    set_unused_bits(false);
   }
 
   void grow(unsigned NewSize) {