diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-17 20:22:39 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-17 20:22:39 +0000 |
commit | 7af96fb3afd6725a2824a0a5ca5dad34e5e0b056 (patch) | |
tree | 6661ffbabf869009597684462f5a3df3beccc952 /include/llvm/ADT/BitVector.h | |
parent | 6b3f41ed88e8e440e11a4fbf20b6600529f80049 (diff) |
Diffstat (limited to 'include/llvm/ADT/BitVector.h')
-rw-r--r-- | include/llvm/ADT/BitVector.h | 273 |
1 files changed, 178 insertions, 95 deletions
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 4a2af7cd68a6d..e68ef5f53d106 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -15,6 +15,7 @@ #define LLVM_ADT_BITVECTOR_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/MathExtras.h" #include <algorithm> #include <cassert> @@ -26,6 +27,50 @@ namespace llvm { +/// ForwardIterator for the bits that are set. +/// Iterators get invalidated when resize / reserve is called. +template <typename BitVectorT> class const_set_bits_iterator_impl { + const BitVectorT &Parent; + int Current = 0; + + void advance() { + assert(Current != -1 && "Trying to advance past end."); + Current = Parent.find_next(Current); + } + +public: + const_set_bits_iterator_impl(const BitVectorT &Parent, int Current) + : Parent(Parent), Current(Current) {} + explicit const_set_bits_iterator_impl(const BitVectorT &Parent) + : const_set_bits_iterator_impl(Parent, Parent.find_first()) {} + const_set_bits_iterator_impl(const const_set_bits_iterator_impl &) = default; + + const_set_bits_iterator_impl operator++(int) { + auto Prev = *this; + advance(); + return Prev; + } + + const_set_bits_iterator_impl &operator++() { + advance(); + return *this; + } + + unsigned operator*() const { return Current; } + + bool operator==(const const_set_bits_iterator_impl &Other) const { + assert(&Parent == &Other.Parent && + "Comparing iterators from different BitVectors"); + return Current == Other.Current; + } + + bool operator!=(const const_set_bits_iterator_impl &Other) const { + assert(&Parent == &Other.Parent && + "Comparing iterators from different BitVectors"); + return Current != Other.Current; + } +}; + class BitVector { typedef unsigned long BitWord; @@ -73,6 +118,18 @@ public: } }; + typedef const_set_bits_iterator_impl<BitVector> const_set_bits_iterator; + typedef const_set_bits_iterator set_iterator; + + const_set_bits_iterator set_bits_begin() const { + return const_set_bits_iterator(*this); + } + const_set_bits_iterator set_bits_end() const { + return const_set_bits_iterator(*this, -1); + } + iterator_range<const_set_bits_iterator> set_bits() const { + return make_range(set_bits_begin(), set_bits_end()); + } /// BitVector default ctor - Creates an empty bitvector. BitVector() : Size(0) {} @@ -146,138 +203,164 @@ public: return !any(); } - /// find_first - Returns the index of the first set bit, -1 if none - /// of the bits are set. - int find_first() const { - for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - return -1; - } - - /// find_last - Returns the index of the last set bit, -1 if none of the bits - /// are set. - int find_last() const { - if (Size == 0) + /// find_first_in - Returns the index of the first set bit in the range + /// [Begin, End). Returns -1 if all bits in the range are unset. + int find_first_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) return -1; - unsigned N = NumBitWords(size()); - assert(N > 0); + unsigned FirstWord = Begin / BITWORD_SIZE; + unsigned LastWord = (End - 1) / BITWORD_SIZE; - unsigned i = N - 1; - while (i > 0 && Bits[i] == BitWord(0)) - --i; + // Check subsequent words. + for (unsigned i = FirstWord; i <= LastWord; ++i) { + BitWord Copy = Bits[i]; - return int((i + 1) * BITWORD_SIZE - countLeadingZeros(Bits[i])) - 1; - } + if (i == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy &= maskTrailingZeros<BitWord>(FirstBit); + } - /// find_first_unset - Returns the index of the first unset bit, -1 if all - /// of the bits are set. - int find_first_unset() const { - for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (Bits[i] != ~0UL) { - unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]); - return Result < size() ? Result : -1; + if (i == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy &= maskTrailingOnes<BitWord>(LastBit + 1); } + if (Copy != 0) + return i * BITWORD_SIZE + countTrailingZeros(Copy); + } return -1; } - /// find_last_unset - Returns the index of the last unset bit, -1 if all of - /// the bits are set. - int find_last_unset() const { - if (Size == 0) + /// find_last_in - Returns the index of the last set bit in the range + /// [Begin, End). Returns -1 if all bits in the range are unset. + int find_last_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) return -1; - const unsigned N = NumBitWords(size()); - assert(N > 0); + unsigned LastWord = (End - 1) / BITWORD_SIZE; + unsigned FirstWord = Begin / BITWORD_SIZE; - unsigned i = N - 1; - BitWord W = Bits[i]; + for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) { + unsigned CurrentWord = i - 1; - // The last word in the BitVector has some unused bits, so we need to set - // them all to 1 first. Set them all to 1 so they don't get treated as - // valid unset bits. - unsigned UnusedCount = BITWORD_SIZE - size() % BITWORD_SIZE; - W |= maskLeadingOnes<BitWord>(UnusedCount); + BitWord Copy = Bits[CurrentWord]; + if (CurrentWord == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy &= maskTrailingOnes<BitWord>(LastBit + 1); + } - while (W == ~BitWord(0) && --i > 0) - W = Bits[i]; + if (CurrentWord == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy &= maskTrailingZeros<BitWord>(FirstBit); + } + + if (Copy != 0) + return (CurrentWord + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1; + } - return int((i + 1) * BITWORD_SIZE - countLeadingOnes(W)) - 1; + return -1; } - /// find_next - Returns the index of the next set bit following the - /// "Prev" bit. Returns -1 if the next set bit is not found. - int find_next(unsigned Prev) const { - ++Prev; - if (Prev >= Size) + /// find_first_unset_in - Returns the index of the first unset bit in the + /// range [Begin, End). Returns -1 if all bits in the range are set. + int find_first_unset_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) return -1; - unsigned WordPos = Prev / BITWORD_SIZE; - unsigned BitPos = Prev % BITWORD_SIZE; - BitWord Copy = Bits[WordPos]; - // Mask off previous bits. - Copy &= maskTrailingZeros<BitWord>(BitPos); - - if (Copy != 0) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); + unsigned FirstWord = Begin / BITWORD_SIZE; + unsigned LastWord = (End - 1) / BITWORD_SIZE; // Check subsequent words. - for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); + for (unsigned i = FirstWord; i <= LastWord; ++i) { + BitWord Copy = Bits[i]; + + if (i == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy |= maskTrailingOnes<BitWord>(FirstBit); + } + + if (i == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy |= maskTrailingZeros<BitWord>(LastBit + 1); + } + if (Copy != ~0UL) { + unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy); + return Result < size() ? Result : -1; + } + } return -1; } - /// find_next_unset - Returns the index of the next unset bit following the - /// "Prev" bit. Returns -1 if all remaining bits are set. - int find_next_unset(unsigned Prev) const { - ++Prev; - if (Prev >= Size) + /// find_last_unset_in - Returns the index of the last unset bit in the + /// range [Begin, End). Returns -1 if all bits in the range are set. + int find_last_unset_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) return -1; - unsigned WordPos = Prev / BITWORD_SIZE; - unsigned BitPos = Prev % BITWORD_SIZE; - BitWord Copy = Bits[WordPos]; - // Mask in previous bits. - BitWord Mask = (1 << BitPos) - 1; - Copy |= Mask; + unsigned LastWord = (End - 1) / BITWORD_SIZE; + unsigned FirstWord = Begin / BITWORD_SIZE; - if (Copy != ~0UL) - return next_unset_in_word(WordPos, Copy); + for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) { + unsigned CurrentWord = i - 1; - // Check subsequent words. - for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i) - if (Bits[i] != ~0UL) - return next_unset_in_word(i, Bits[i]); + BitWord Copy = Bits[CurrentWord]; + if (CurrentWord == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy |= maskTrailingZeros<BitWord>(LastBit + 1); + } + + if (CurrentWord == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy |= maskTrailingOnes<BitWord>(FirstBit); + } + + if (Copy != ~0UL) { + unsigned Result = + (CurrentWord + 1) * BITWORD_SIZE - countLeadingOnes(Copy) - 1; + return Result < Size ? Result : -1; + } + } return -1; } + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { return find_first_in(0, Size); } + + /// find_last - Returns the index of the last set bit, -1 if none of the bits + /// are set. + int find_last() const { return find_last_in(0, Size); } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { return find_first_in(Prev + 1, Size); } + /// 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 (PriorTo == 0) - return -1; + int find_prev(unsigned PriorTo) const { return find_last_in(0, PriorTo); } - --PriorTo; + /// find_first_unset - Returns the index of the first unset bit, -1 if all + /// of the bits are set. + int find_first_unset() const { return find_first_unset_in(0, Size); } - unsigned WordPos = PriorTo / BITWORD_SIZE; - unsigned BitPos = PriorTo % BITWORD_SIZE; - BitWord Copy = Bits[WordPos]; - // Mask off next bits. - Copy &= maskTrailingOnes<BitWord>(BitPos + 1); + /// find_next_unset - Returns the index of the next unset bit following the + /// "Prev" bit. Returns -1 if all remaining bits are set. + int find_next_unset(unsigned Prev) const { + return find_first_unset_in(Prev + 1, Size); + } - if (Copy != 0) - return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1; + /// find_last_unset - Returns the index of the last unset bit, -1 if all of + /// the bits are set. + int find_last_unset() const { return find_last_unset_in(0, Size); } - // 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; + /// find_prev_unset - Returns the index of the first unset bit that precedes + /// the bit at \p PriorTo. Returns -1 if all previous bits are set. + int find_prev_unset(unsigned PriorTo) { + return find_last_unset_in(0, PriorTo); } /// clear - Removes all bits from the bitvector. Does not change capacity. |