Skip to content

Commit 83f6838

Browse files
authored
Merge pull request #123 from hacatu/master
Added `nth` to `BitVec::Iter` so that `.skip(n)` gets optimized
2 parents 0e846ab + e68a004 commit 83f6838

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

benches/bench.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,23 @@ fn bench_erathostenes_set_all(b: &mut test::Bencher) {
260260
black_box(&mut sieve);
261261
});
262262
}
263+
264+
#[bench]
265+
fn bench_iter_skip(b: &mut test::Bencher) {
266+
let start = 3 << 20;
267+
let p = 16411;
268+
let g = 9749; // 9749 is a primitive root modulo 16411, so we can generate numbers mod p in a seemingly random order
269+
let end = start + p;
270+
let mut tbl = BitVec::from_elem(end, false);
271+
let mut r = g;
272+
for i in start..end {
273+
tbl.set(i, r & 1 != 0);
274+
r = r * g % p;
275+
}
276+
b.iter(|| {
277+
black_box(&mut tbl);
278+
// start is large relative to end-start, so before Iterator::nth was implemented for bitvec this would
279+
// have been much slower
280+
black_box(tbl.iter().skip(start).filter(|&v| v).count());
281+
});
282+
}

src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,13 @@ impl<'a, B: BitBlock> Iterator for Iter<'a, B> {
19371937
self.range.next().map(|i| self.bit_vec.get(i).unwrap())
19381938
}
19391939

1940+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1941+
// This override is used by the compiler to optimize Iterator::skip.
1942+
// Without this, the default implementation of Iterator::nth is used, which walks over
1943+
// the whole iterator up to n.
1944+
self.range.nth(n).and_then(|i| self.bit_vec.get(i))
1945+
}
1946+
19401947
fn size_hint(&self) -> (usize, Option<usize>) {
19411948
self.range.size_hint()
19421949
}

0 commit comments

Comments
 (0)