Skip to content

Commit 84c1324

Browse files
authored
Add DoubleEndedIterator to Ones for reverse iteration (#98)
1 parent bfc667c commit 84c1324

2 files changed

Lines changed: 245 additions & 20 deletions

File tree

benches/benches/benches.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,25 @@ fn iter_ones_all_zeros(c: &mut Criterion) {
5555
});
5656
}
5757

58+
fn iter_ones_sparse(c: &mut Criterion) {
59+
const N: usize = 1_000_000;
60+
let mut fb = FixedBitSet::with_capacity(N);
61+
for i in 0..N {
62+
if i % 2 == 0 {
63+
fb.insert(i);
64+
}
65+
}
66+
c.bench_function("iter_ones/sparse", |b| {
67+
b.iter(|| {
68+
let mut count = 0;
69+
for _ in fb.ones() {
70+
count += 1;
71+
}
72+
count
73+
})
74+
});
75+
}
76+
5877
fn iter_ones_all_ones(c: &mut Criterion) {
5978
const N: usize = 1_000_000;
6079
let mut fb = FixedBitSet::with_capacity(N);
@@ -71,6 +90,22 @@ fn iter_ones_all_ones(c: &mut Criterion) {
7190
});
7291
}
7392

93+
fn iter_ones_all_ones_rev(c: &mut Criterion) {
94+
const N: usize = 1_000_000;
95+
let mut fb = FixedBitSet::with_capacity(N);
96+
fb.insert_range(..);
97+
98+
c.bench_function("iter_ones/all_ones", |b| {
99+
b.iter(|| {
100+
let mut count = 0;
101+
for _ in fb.ones().rev() {
102+
count += 1;
103+
}
104+
count
105+
})
106+
});
107+
}
108+
74109
fn insert_range(c: &mut Criterion) {
75110
const N: usize = 1_000_000;
76111
let mut fb = FixedBitSet::with_capacity(N);
@@ -160,9 +195,11 @@ fn count_ones(c: &mut Criterion) {
160195

161196
criterion_group!(
162197
benches,
198+
bitchange,
163199
iter_ones_using_contains_all_zeros,
164200
iter_ones_using_contains_all_ones,
165201
iter_ones_all_zeros,
202+
iter_ones_sparse,
166203
iter_ones_all_ones,
167204
insert_range,
168205
insert,

src/lib.rs

Lines changed: 208 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,21 @@ impl FixedBitSet {
410410
#[inline]
411411
pub fn ones(&self) -> Ones {
412412
match self.as_slice().split_first() {
413-
Some((&block, rem)) => Ones {
414-
bitset: block,
415-
block_idx: 0,
416-
remaining_blocks: rem.iter(),
417-
},
413+
Some((&first_block, rem)) => {
414+
let (&last_block, rem) = rem.split_last().unwrap_or((&0, rem));
415+
Ones {
416+
bitset_front: first_block,
417+
bitset_back: last_block,
418+
block_idx_front: 0,
419+
block_idx_back: (1 + rem.len()) * BITS,
420+
remaining_blocks: rem.iter(),
421+
}
422+
}
418423
None => Ones {
419-
bitset: 0,
420-
block_idx: 0,
424+
bitset_front: 0,
425+
bitset_back: 0,
426+
block_idx_front: 0,
427+
block_idx_back: 0,
421428
remaining_blocks: [].iter(),
422429
},
423430
}
@@ -764,29 +771,109 @@ impl ExactSizeIterator for Masks {}
764771
///
765772
/// This struct is created by the [`FixedBitSet::ones`] method.
766773
pub struct Ones<'a> {
767-
bitset: Block,
768-
block_idx: usize,
774+
bitset_front: Block,
775+
bitset_back: Block,
776+
block_idx_front: usize,
777+
block_idx_back: usize,
769778
remaining_blocks: std::slice::Iter<'a, Block>,
770779
}
771780

781+
impl<'a> Ones<'a> {
782+
#[inline]
783+
pub fn last_positive_bit_and_unset(n: &mut Block) -> usize {
784+
// Find the last set bit using x & -x
785+
let last_bit = *n & n.wrapping_neg();
786+
787+
// Find the position of the last set bit
788+
let position = last_bit.trailing_zeros();
789+
790+
// Unset the last set bit
791+
*n &= *n - 1;
792+
793+
position as usize
794+
}
795+
796+
#[inline]
797+
fn first_positive_bit_and_unset(n: &mut Block) -> usize {
798+
/* Identify the first non zero bit */
799+
let bit_idx = n.leading_zeros();
800+
801+
/* set that bit to zero */
802+
let mask = !((1 as Block) << (BITS as u32 - bit_idx - 1));
803+
n.bitand_assign(mask);
804+
805+
bit_idx as usize
806+
}
807+
}
808+
809+
impl<'a> DoubleEndedIterator for Ones<'a> {
810+
fn next_back(&mut self) -> Option<Self::Item> {
811+
while self.bitset_back == 0 {
812+
match self.remaining_blocks.next_back() {
813+
None => {
814+
if self.bitset_front != 0 {
815+
self.bitset_back = 0;
816+
self.block_idx_back = self.block_idx_front;
817+
return Some(
818+
self.block_idx_front + BITS
819+
- Self::first_positive_bit_and_unset(&mut self.bitset_front)
820+
- 1,
821+
);
822+
} else {
823+
return None;
824+
}
825+
}
826+
Some(next_block) => {
827+
self.bitset_back = *next_block;
828+
self.block_idx_back -= BITS;
829+
}
830+
};
831+
}
832+
833+
Some(
834+
self.block_idx_back - Self::first_positive_bit_and_unset(&mut self.bitset_back) + BITS
835+
- 1,
836+
)
837+
}
838+
}
839+
772840
impl<'a> Iterator for Ones<'a> {
773841
type Item = usize; // the bit position of the '1'
774842

775843
#[inline]
776844
fn next(&mut self) -> Option<Self::Item> {
777-
while self.bitset == 0 {
778-
self.bitset = *self.remaining_blocks.next()?;
779-
self.block_idx += BITS;
845+
while self.bitset_front == 0 {
846+
match self.remaining_blocks.next() {
847+
Some(next_block) => {
848+
self.bitset_front = *next_block;
849+
self.block_idx_front += BITS;
850+
}
851+
None => {
852+
if self.bitset_back != 0 {
853+
// not needed for iteration, but for size_hint
854+
self.block_idx_front = self.block_idx_back;
855+
self.bitset_front = 0;
856+
857+
return Some(
858+
self.block_idx_back
859+
+ Self::last_positive_bit_and_unset(&mut self.bitset_back),
860+
);
861+
} else {
862+
return None;
863+
}
864+
}
865+
};
780866
}
781-
let t = self.bitset & (0 as Block).wrapping_sub(self.bitset);
782-
let r = self.bitset.trailing_zeros() as usize;
783-
self.bitset ^= t;
784-
Some(self.block_idx + r)
867+
868+
Some(self.block_idx_front + Self::last_positive_bit_and_unset(&mut self.bitset_front))
785869
}
786870

787871
#[inline]
788872
fn size_hint(&self) -> (usize, Option<usize>) {
789-
(0, Some(self.remaining_blocks.as_slice().len() * BITS))
873+
(
874+
0,
875+
(Some(self.block_idx_back - self.block_idx_front + 2 * BITS)),
876+
)
790877
}
791878
}
792879

@@ -1015,6 +1102,12 @@ mod tests {
10151102

10161103
let ones: Vec<_> = fb.ones().collect();
10171104
assert_eq!(ones.len(), 1);
1105+
1106+
let ones: Vec<_> = fb.ones().rev().collect();
1107+
assert_eq!(ones.len(), 1);
1108+
1109+
let ones: Vec<_> = fb.ones().rev().alternate().collect();
1110+
assert_eq!(ones.len(), 1);
10181111
}
10191112

10201113
#[test]
@@ -1133,6 +1226,43 @@ mod tests {
11331226
assert_eq!(fb.count_ones(8..), 8);
11341227
}
11351228

1229+
/* Helper for testing double ended iterator */
1230+
#[cfg(test)]
1231+
struct Alternating<I> {
1232+
iter: I,
1233+
front: bool,
1234+
}
1235+
1236+
#[cfg(test)]
1237+
impl<I: Iterator + DoubleEndedIterator> Iterator for Alternating<I> {
1238+
type Item = I::Item;
1239+
1240+
fn size_hint(&self) -> (usize, Option<usize>) {
1241+
self.iter.size_hint()
1242+
}
1243+
fn next(&mut self) -> Option<Self::Item> {
1244+
if self.front {
1245+
self.front = false;
1246+
self.iter.next()
1247+
} else {
1248+
self.front = true;
1249+
self.iter.next_back()
1250+
}
1251+
}
1252+
}
1253+
#[cfg(test)]
1254+
trait AlternatingExt: Iterator + DoubleEndedIterator + Sized {
1255+
fn alternate(self) -> Alternating<Self> {
1256+
Alternating {
1257+
iter: self,
1258+
front: true,
1259+
}
1260+
}
1261+
}
1262+
1263+
#[cfg(test)]
1264+
impl<I: Iterator + DoubleEndedIterator> AlternatingExt for I {}
1265+
11361266
#[test]
11371267
fn ones() {
11381268
let mut fb = FixedBitSet::with_capacity(100);
@@ -1147,8 +1277,60 @@ mod tests {
11471277
fb.set(99, true);
11481278

11491279
let ones: Vec<_> = fb.ones().collect();
1280+
let ones_rev: Vec<_> = fb.ones().rev().collect();
1281+
let ones_alternating: Vec<_> = fb.ones().alternate().collect();
1282+
1283+
let mut known_result = vec![7, 11, 12, 35, 40, 50, 77, 95, 99];
1284+
1285+
assert_eq!(known_result, ones);
1286+
known_result.reverse();
1287+
assert_eq!(known_result, ones_rev);
1288+
let known_result: Vec<_> = known_result.into_iter().rev().alternate().collect();
1289+
assert_eq!(known_result, ones_alternating);
1290+
}
1291+
1292+
#[test]
1293+
fn size_hint() {
1294+
for s in 0..1000 {
1295+
let mut bitset = FixedBitSet::with_capacity(s);
1296+
bitset.insert_range(..);
1297+
let mut t = s;
1298+
let mut iter = bitset.ones().rev();
1299+
loop {
1300+
match iter.next() {
1301+
None => break,
1302+
Some(_) => {
1303+
t -= 1;
1304+
assert!(iter.size_hint().1.unwrap() >= t);
1305+
// factor two, because we have first block and last block
1306+
assert!(iter.size_hint().1.unwrap() <= t + 2 * BITS);
1307+
}
1308+
}
1309+
}
1310+
assert_eq!(t, 0);
1311+
}
1312+
}
11501313

1151-
assert_eq!(vec![7, 11, 12, 35, 40, 50, 77, 95, 99], ones);
1314+
#[test]
1315+
fn size_hint_alternate() {
1316+
for s in 0..1000 {
1317+
let mut bitset = FixedBitSet::with_capacity(s);
1318+
bitset.insert_range(..);
1319+
let mut t = s;
1320+
let mut iter = bitset.ones().alternate();
1321+
loop {
1322+
match iter.next() {
1323+
None => break,
1324+
Some(_) => {
1325+
t -= 1;
1326+
//println!("{:?} < {}", iter.size_hint(), t);
1327+
assert!(iter.size_hint().1.unwrap() >= t);
1328+
assert!(iter.size_hint().1.unwrap() <= t + 3 * BITS);
1329+
}
1330+
}
1331+
}
1332+
assert_eq!(t, 0);
1333+
}
11521334
}
11531335

11541336
#[test]
@@ -1161,7 +1343,13 @@ mod tests {
11611343
}
11621344
let ones: Vec<_> = fb.ones().collect();
11631345
let expected: Vec<_> = (from..to).collect();
1346+
let ones_rev: Vec<_> = fb.ones().rev().collect();
1347+
let expected_rev: Vec<_> = (from..to).rev().collect();
1348+
let ones_rev_alt: Vec<_> = fb.ones().rev().alternate().collect();
1349+
let expected_rev_alt: Vec<_> = (from..to).rev().alternate().collect();
11641350
assert_eq!(expected, ones);
1351+
assert_eq!(expected_rev, ones_rev);
1352+
assert_eq!(expected_rev_alt, ones_rev_alt);
11651353
}
11661354

11671355
for i in 0..100 {
@@ -1631,7 +1819,7 @@ mod tests {
16311819
let b = b_ones.iter().cloned().collect::<FixedBitSet>();
16321820
a |= b;
16331821
let res = a.ones().collect::<Vec<usize>>();
1634-
assert!(res == a_or_b);
1822+
assert_eq!(res, a_or_b);
16351823
}
16361824

16371825
#[test]
@@ -1750,7 +1938,7 @@ mod tests {
17501938
tmp
17511939
};
17521940

1753-
assert!(ones == expected);
1941+
assert_eq!(ones, expected);
17541942
}
17551943

17561944
#[test]

0 commit comments

Comments
 (0)