Skip to content

Commit f9372b4

Browse files
committed
Implement DoubleEndedIterator for iter_set_bits.
1 parent 5e4aaf1 commit f9372b4

File tree

1 file changed

+62
-15
lines changed

1 file changed

+62
-15
lines changed

src/lib.rs

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77
cmp::{min, PartialEq},
88
fmt::{self, Debug},
99
hash::{Hash, Hasher},
10-
iter::FromIterator,
10+
iter::{DoubleEndedIterator, FromIterator},
1111
mem::{replace, size_of},
1212
ops::{
1313
Bound::{Excluded, Included, Unbounded},
@@ -1156,6 +1156,42 @@ impl<T: Debug + PrimInt> Iterator for IterSetBits<'_, T> {
11561156
}
11571157
}
11581158

1159+
impl<T: Debug + PrimInt> DoubleEndedIterator for IterSetBits<'_, T> {
1160+
fn next_back(&mut self) -> Option<usize> {
1161+
if let Some(i) = self.range.next_back() {
1162+
let mut b = block_offset::<T>(i);
1163+
let mut v = self.vob.vec[b];
1164+
// If all bits are set, we don't need to do any complicated checks.
1165+
if v == T::max_value() {
1166+
return Some(i);
1167+
}
1168+
// At this point we've got a block which might or might not have some bits set. We now
1169+
// fall back to the general case.
1170+
let mut i_off = i % bits_per_block::<T>();
1171+
loop {
1172+
let lz = (v << (bits_per_block::<T>() - 1 - i_off)).leading_zeros() as usize;
1173+
if lz < bits_per_block::<T>() {
1174+
let bs = b * bits_per_block::<T>() + i_off - lz;
1175+
self.range.end = bs;
1176+
if bs < self.range.start {
1177+
break;
1178+
}
1179+
return Some(bs);
1180+
}
1181+
if b == block_offset::<T>(self.range.start) {
1182+
// We've exhausted the iterator.
1183+
self.range.start = self.range.end;
1184+
break;
1185+
}
1186+
b -= 1;
1187+
v = self.vob.vec[b];
1188+
i_off = bits_per_block::<T>() - 1;
1189+
}
1190+
}
1191+
None
1192+
}
1193+
}
1194+
11591195
#[derive(Clone)]
11601196
pub struct IterUnsetBits<'a, T: 'a> {
11611197
vob: &'a Vob<T>,
@@ -1542,6 +1578,7 @@ mod tests {
15421578
hash::{Hash, Hasher},
15431579
iter::FromIterator,
15441580
mem::size_of,
1581+
ops::RangeBounds,
15451582
};
15461583

15471584
#[test]
@@ -1791,28 +1828,38 @@ mod tests {
17911828

17921829
#[test]
17931830
fn test_iter_set_bits() {
1831+
fn t<R>(v: &Vob, range: R, expected: Vec<usize>)
1832+
where
1833+
R: Clone + RangeBounds<usize>,
1834+
{
1835+
let rev = expected.iter().cloned().rev().collect::<Vec<usize>>();
1836+
assert_eq!(
1837+
v.iter_set_bits(range.clone()).collect::<Vec<usize>>(),
1838+
expected
1839+
);
1840+
assert_eq!(v.iter_set_bits(range).rev().collect::<Vec<usize>>(), rev);
1841+
}
1842+
1843+
t(&vob![], .., vec![]);
1844+
t(&Vob::from_elem(true, 131), .., (0..131).collect::<Vec<_>>());
1845+
17941846
let mut v1 = vob![false, true, false, true];
1795-
assert_eq!(v1.iter_set_bits(..).collect::<Vec<usize>>(), vec![1, 3]);
1847+
t(&v1, .., vec![1, 3]);
17961848
v1.resize(127, false);
17971849
v1.push(true);
17981850
v1.push(false);
17991851
v1.push(true);
18001852
v1.push(true);
18011853
v1.resize(256, false);
18021854
v1.push(true);
1803-
assert_eq!(
1804-
v1.iter_set_bits(..).collect::<Vec<usize>>(),
1805-
vec![1, 3, 127, 129, 130, 256]
1806-
);
1807-
assert_eq!(
1808-
v1.iter_set_bits(2..256).collect::<Vec<usize>>(),
1809-
vec![3, 127, 129, 130]
1810-
);
1811-
assert_eq!(
1812-
v1.iter_set_bits(2..).collect::<Vec<usize>>(),
1813-
vec![3, 127, 129, 130, 256]
1814-
);
1815-
assert_eq!(v1.iter_set_bits(..3).collect::<Vec<usize>>(), vec![1]);
1855+
assert_eq!(v1.len(), 257);
1856+
t(&v1, .., vec![1, 3, 127, 129, 130, 256]);
1857+
t(&v1, 2..257, vec![3, 127, 129, 130, 256]);
1858+
t(&v1, 2..256, vec![3, 127, 129, 130]);
1859+
t(&v1, 2.., vec![3, 127, 129, 130, 256]);
1860+
t(&v1, 1..255, vec![1, 3, 127, 129, 130]);
1861+
t(&v1, ..3, vec![1]);
1862+
t(&v1, 128.., vec![129, 130, 256]);
18161863
}
18171864

18181865
#[test]

0 commit comments

Comments
 (0)