[ADT] Add BitVector::find_prev.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zachary Turner 2017-05-05 17:00:04 +00:00
parent 91c57a1252
commit 6a4e43bdd4
3 changed files with 55 additions and 0 deletions

View 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;

View 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())

View 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));