Skip to content

Commit 6205ff8

Browse files
Adding bidirectional iterator functionality + unit tests.
1 parent ec27c2d commit 6205ff8

File tree

2 files changed

+116
-4
lines changed

2 files changed

+116
-4
lines changed

llvm/include/llvm/ADT/BitVector.h

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,20 @@ template <typename BitVectorT> class const_set_bits_iterator_impl {
4040
Current = Parent.find_next(Current);
4141
}
4242

43+
void retreat() {
44+
if (Current == -1) {
45+
Current = Parent.find_last();
46+
} else {
47+
Current = Parent.find_prev(Current);
48+
}
49+
}
50+
4351
public:
44-
using iterator_category = std::forward_iterator_tag;
52+
using iterator_category = std::bidirectional_iterator_tag;
4553
using difference_type = std::ptrdiff_t;
46-
using value_type = int;
47-
using pointer = value_type*;
48-
using reference = value_type&;
54+
using value_type = unsigned;
55+
using pointer = const value_type*;
56+
using reference = value_type;
4957

5058
const_set_bits_iterator_impl(const BitVectorT &Parent, int Current)
5159
: Parent(Parent), Current(Current) {}
@@ -64,6 +72,17 @@ template <typename BitVectorT> class const_set_bits_iterator_impl {
6472
return *this;
6573
}
6674

75+
const_set_bits_iterator_impl operator--(int) {
76+
auto Prev = *this;
77+
retreat();
78+
return Prev;
79+
}
80+
81+
const_set_bits_iterator_impl &operator--() {
82+
retreat();
83+
return *this;
84+
}
85+
6786
unsigned operator*() const { return Current; }
6887

6988
bool operator==(const const_set_bits_iterator_impl &Other) const {

llvm/unittests/ADT/BitVectorTest.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/ADT/BitVector.h"
1010
#include "llvm/ADT/DenseSet.h"
1111
#include "llvm/ADT/SmallBitVector.h"
12+
#include "llvm/ADT/STLExtras.h"
1213
#include "gtest/gtest.h"
1314

1415
using namespace llvm;
@@ -1177,6 +1178,98 @@ TYPED_TEST(BitVectorTest, Iterators) {
11771178
EXPECT_EQ(List[i++], Bit);
11781179
}
11791180

1181+
TYPED_TEST(BitVectorTest, BidirectionalIterator) {
1182+
// Test decrement operators
1183+
TypeParam Vec(100, false);
1184+
Vec.set(10);
1185+
Vec.set(20);
1186+
Vec.set(30);
1187+
Vec.set(40);
1188+
1189+
// Test that we can decrement from end()
1190+
auto EndIt = Vec.set_bits_end();
1191+
auto LastIt = EndIt;
1192+
--LastIt;
1193+
EXPECT_EQ(*LastIt, 40U);
1194+
1195+
// Test post-decrement
1196+
auto It = Vec.set_bits_end();
1197+
auto PrevIt = It--;
1198+
EXPECT_EQ(PrevIt, Vec.set_bits_end());
1199+
EXPECT_EQ(*It, 40U);
1200+
1201+
// Test pre-decrement
1202+
--It;
1203+
EXPECT_EQ(*It, 30U);
1204+
1205+
// Test full backward iteration
1206+
std::vector<unsigned> BackwardBits;
1207+
for (auto RIt = Vec.set_bits_end(); RIt != Vec.set_bits_begin(); ) {
1208+
--RIt;
1209+
BackwardBits.push_back(*RIt);
1210+
}
1211+
EXPECT_EQ(BackwardBits.size(), 4U);
1212+
EXPECT_EQ(BackwardBits[0], 40U);
1213+
EXPECT_EQ(BackwardBits[1], 30U);
1214+
EXPECT_EQ(BackwardBits[2], 20U);
1215+
EXPECT_EQ(BackwardBits[3], 10U);
1216+
}
1217+
1218+
TYPED_TEST(BitVectorTest, ReverseIteration) {
1219+
// Test using llvm::reverse
1220+
TypeParam Vec(100, false);
1221+
Vec.set(5);
1222+
Vec.set(15);
1223+
Vec.set(25);
1224+
Vec.set(35);
1225+
Vec.set(45);
1226+
1227+
std::vector<unsigned> ReversedBits;
1228+
for (unsigned Bit : llvm::reverse(Vec.set_bits())) {
1229+
ReversedBits.push_back(Bit);
1230+
}
1231+
1232+
EXPECT_EQ(ReversedBits.size(), 5U);
1233+
EXPECT_EQ(ReversedBits[0], 45U);
1234+
EXPECT_EQ(ReversedBits[1], 35U);
1235+
EXPECT_EQ(ReversedBits[2], 25U);
1236+
EXPECT_EQ(ReversedBits[3], 15U);
1237+
EXPECT_EQ(ReversedBits[4], 5U);
1238+
}
1239+
1240+
TYPED_TEST(BitVectorTest, BidirectionalIteratorEdgeCases) {
1241+
// Test empty BitVector
1242+
TypeParam Empty;
1243+
EXPECT_EQ(Empty.set_bits_begin(), Empty.set_bits_end());
1244+
1245+
// Decrementing end() on empty should give -1 (no bits set)
1246+
auto EmptyEndIt = Empty.set_bits_end();
1247+
--EmptyEndIt;
1248+
// After decrement on empty, iterator should still be at "no bit" position
1249+
EXPECT_EQ(*EmptyEndIt, static_cast<unsigned>(-1));
1250+
1251+
// Test single bit
1252+
TypeParam Single(10, false);
1253+
Single.set(5);
1254+
1255+
auto SingleIt = Single.set_bits_end();
1256+
--SingleIt;
1257+
EXPECT_EQ(*SingleIt, 5U);
1258+
// After decrementing past the first element, the iterator is in an
1259+
// undefined state (before begin), so we don't test this case
1260+
1261+
// Test all bits set
1262+
TypeParam AllSet(10, true);
1263+
std::vector<unsigned> AllBitsReverse;
1264+
for (unsigned Bit : llvm::reverse(AllSet.set_bits())) {
1265+
AllBitsReverse.push_back(Bit);
1266+
}
1267+
EXPECT_EQ(AllBitsReverse.size(), 10U);
1268+
for (unsigned i = 0; i < 10; ++i) {
1269+
EXPECT_EQ(AllBitsReverse[i], 9 - i);
1270+
}
1271+
}
1272+
11801273
TYPED_TEST(BitVectorTest, PushBack) {
11811274
TypeParam Vec(10, false);
11821275
EXPECT_EQ(-1, Vec.find_first());

0 commit comments

Comments
 (0)