[ADT] Add BitVector::find_prev.
authorZachary Turner <zturner@google.com>
Fri, 5 May 2017 17:00:04 +0000 (17:00 +0000)
committerZachary Turner <zturner@google.com>
Fri, 5 May 2017 17:00:04 +0000 (17:00 +0000)
This almost completes the matrix of all possible find
functions.

*EXISTING*
----------
find_first
find_first_unset
find_next
find_next_unset
find_last
find_last_unset

*NEW*
----
find_prev

*STILL MISSING*
---------------
find_prev_unset

Differential Revision: https://reviews.llvm.org/D32885

llvm-svn: 302254

llvm/include/llvm/ADT/BitVector.h
llvm/include/llvm/ADT/SmallBitVector.h
llvm/unittests/ADT/BitVectorTest.cpp

index 01a3220..315d52a 100644 (file)
@@ -253,6 +253,33 @@ public:
     return -1;
   }
 
+  /// find_prev - Returns the index of the first set bit that precedes the
+  /// the bit at \p PriorTo.  Returns -1 if all previous bits are unset.
+  int find_prev(unsigned PriorTo) {
+    if (PriorTo == 0)
+      return -1;
+
+    --PriorTo;
+
+    unsigned WordPos = PriorTo / BITWORD_SIZE;
+    unsigned BitPos = PriorTo % BITWORD_SIZE;
+    BitWord Copy = Bits[WordPos];
+    // Mask off next bits.
+    Copy &= maskTrailingOnes<BitWord>(BitPos + 1);
+
+    if (Copy != 0)
+      return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
+
+    // Check previous words.
+    for (unsigned i = 1; i <= WordPos; ++i) {
+      unsigned Index = WordPos - i;
+      if (Bits[Index] == 0)
+        continue;
+      return (Index + 1) * BITWORD_SIZE - countLeadingZeros(Bits[Index]) - 1;
+    }
+    return -1;
+  }
+
   /// clear - Clear all bits.
   void clear() {
     Size = 0;
index bf16af5..0eeacc1 100644 (file)
@@ -278,6 +278,24 @@ public:
     return getPointer()->find_next_unset(Prev);
   }
 
+  /// find_prev - Returns the index of the first set bit that precedes the
+  /// the bit at \p PriorTo.  Returns -1 if all previous bits are unset.
+  int find_prev(unsigned PriorTo) const {
+    if (isSmall()) {
+      if (PriorTo == 0)
+        return -1;
+
+      --PriorTo;
+      uintptr_t Bits = getSmallBits();
+      Bits &= maskTrailingOnes<uintptr_t>(PriorTo + 1);
+      if (Bits == 0)
+        return -1;
+
+      return NumBaseBits - countLeadingZeros(Bits) - 1;
+    }
+    return getPointer()->find_prev(PriorTo);
+  }
+
   /// Clear all bits.
   void clear() {
     if (!isSmall())
index 1a87a56..faf362a 100644 (file)
@@ -204,6 +204,11 @@ TYPED_TEST(BitVectorTest, FindOperations) {
   EXPECT_EQ(75, A.find_next(13));
   EXPECT_EQ(-1, A.find_next(75));
 
+  EXPECT_EQ(-1, A.find_prev(12));
+  EXPECT_EQ(12, A.find_prev(13));
+  EXPECT_EQ(13, A.find_prev(75));
+  EXPECT_EQ(75, A.find_prev(90));
+
   EXPECT_EQ(0, A.find_first_unset());
   EXPECT_EQ(99, A.find_last_unset());
   EXPECT_EQ(14, A.find_next_unset(11));
@@ -240,6 +245,11 @@ TYPED_TEST(BitVectorTest, FindOperations) {
   EXPECT_EQ(16, A.find_next(4));
   EXPECT_EQ(-1, A.find_next(16));
 
+  EXPECT_EQ(-1, A.find_prev(3));
+  EXPECT_EQ(3, A.find_prev(4));
+  EXPECT_EQ(4, A.find_prev(16));
+  EXPECT_EQ(16, A.find_prev(18));
+
   EXPECT_EQ(0, A.find_first_unset());
   EXPECT_EQ(19, A.find_last_unset());
   EXPECT_EQ(5, A.find_next_unset(3));