Skip to content

Commit 6c79c7c

Browse files
committed
Implement ones() using trailing_zeros()
Fixes #17.
1 parent 1ffc9cb commit 6c79c7c

File tree

1 file changed

+16
-39
lines changed

1 file changed

+16
-39
lines changed

src/lib.rs

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -303,17 +303,15 @@ impl FixedBitSet
303303
match self.as_slice().split_first() {
304304
Some((&block, rem)) => {
305305
Ones {
306-
current_bit_idx: 0,
307-
current_block_idx: 0,
308-
current_block: block,
306+
bitset: block,
307+
block_idx: 0,
309308
remaining_blocks: rem
310309
}
311310
}
312311
None => {
313312
Ones {
314-
current_bit_idx: 0,
315-
current_block_idx: 0,
316-
current_block: 0,
313+
bitset: 0,
314+
block_idx: 0,
317315
remaining_blocks: &[]
318316
}
319317
}
@@ -594,49 +592,28 @@ impl Iterator for Masks {
594592
///
595593
/// This struct is created by the [`FixedBitSet::ones`] method.
596594
pub struct Ones<'a> {
597-
current_bit_idx: usize,
598-
current_block_idx: usize,
595+
bitset: Block,
596+
block_idx: usize,
599597
remaining_blocks: &'a [Block],
600-
current_block: Block
601598
}
602599

603600
impl<'a> Iterator for Ones<'a> {
604601
type Item = usize; // the bit position of the '1'
605602

606603
#[inline]
607604
fn next(&mut self) -> Option<Self::Item> {
608-
let mut block = self.current_block;
609-
let mut idx = self.current_bit_idx;
610-
611-
loop {
612-
loop {
613-
if (block & 1) == 1 {
614-
self.current_block = block >> 1;
615-
self.current_bit_idx = idx + 1;
616-
return Some(idx);
617-
}
618-
// reordering the two lines below makes a huge (2x) difference in performance!
619-
block = block >> 1;
620-
idx += 1;
621-
if block == 0 {
622-
break;
623-
}
624-
}
625-
626-
// go to next block
627-
match self.remaining_blocks.split_first() {
628-
Some((&next_block, rest)) => {
629-
self.remaining_blocks = rest;
630-
self.current_block_idx += 1;
631-
idx = self.current_block_idx * BITS;
632-
block = next_block;
633-
}
634-
None => {
635-
// last block => done
636-
return None;
637-
}
605+
while self.bitset == 0 {
606+
if self.remaining_blocks.is_empty() {
607+
return None;
638608
}
609+
self.bitset = self.remaining_blocks[0];
610+
self.remaining_blocks = &self.remaining_blocks[1..];
611+
self.block_idx += 1;
639612
}
613+
let t = self.bitset & (0 as Block).wrapping_sub(self.bitset);
614+
let r = self.bitset.trailing_zeros() as usize;
615+
self.bitset ^= t;
616+
Some(self.block_idx * BITS + r)
640617
}
641618
}
642619

0 commit comments

Comments
 (0)