1
Fork 0

Tiny ChunkedBitSet improvements.

- Fix a typo in a comment.
- Remove unnecessary `Chunk::` qualifiers.
- Rename `ChunkedBitIter::bitset` as `ChunkedBitIter::bit_set`, because
  `bit_set` is the form used everywhere else.
- Avoid some unnecessary local variables.
This commit is contained in:
Nicholas Nethercote 2024-11-23 13:14:29 +11:00
parent 15b24c46b4
commit ff78002566

View file

@ -383,8 +383,7 @@ enum Chunk {
/// turns out to be both simpler and have better performance than /// turns out to be both simpler and have better performance than
/// allocating the minimum number of words, largely because we avoid having /// allocating the minimum number of words, largely because we avoid having
/// to store the length, which would make this type larger. These excess /// to store the length, which would make this type larger. These excess
/// words are always be zero, as are any excess bits in the final in-use /// words are always zero, as are any excess bits in the final in-use word.
/// word.
/// ///
/// The first `ChunkSize` field is always non-zero. /// The first `ChunkSize` field is always non-zero.
/// ///
@ -465,7 +464,7 @@ impl<T: Idx> ChunkedBitSet<T> {
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..))) self.chunks.iter().all(|chunk| matches!(chunk, Zeros(..)))
} }
/// Returns `true` if `self` contains `elem`. /// Returns `true` if `self` contains `elem`.
@ -855,7 +854,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for BitSet<T> {
words = &mut words[..CHUNK_WORDS]; words = &mut words[..CHUNK_WORDS];
} }
match chunk { match chunk {
Chunk::Zeros(..) => { Zeros(..) => {
for word in words { for word in words {
if *word != 0 { if *word != 0 {
changed = true; changed = true;
@ -863,8 +862,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for BitSet<T> {
} }
} }
} }
Chunk::Ones(..) => (), Ones(..) => (),
Chunk::Mixed(_, _, data) => { Mixed(_, _, data) => {
for (i, word) in words.iter_mut().enumerate() { for (i, word) in words.iter_mut().enumerate() {
let new_val = *word & data[i]; let new_val = *word & data[i];
if new_val != *word { if new_val != *word {
@ -902,22 +901,22 @@ impl<T> Clone for ChunkedBitSet<T> {
pub struct ChunkedBitIter<'a, T: Idx> { pub struct ChunkedBitIter<'a, T: Idx> {
index: usize, index: usize,
bitset: &'a ChunkedBitSet<T>, bit_set: &'a ChunkedBitSet<T>,
} }
impl<'a, T: Idx> ChunkedBitIter<'a, T> { impl<'a, T: Idx> ChunkedBitIter<'a, T> {
#[inline] #[inline]
fn new(bitset: &'a ChunkedBitSet<T>) -> ChunkedBitIter<'a, T> { fn new(bit_set: &'a ChunkedBitSet<T>) -> ChunkedBitIter<'a, T> {
ChunkedBitIter { index: 0, bitset } ChunkedBitIter { index: 0, bit_set }
} }
} }
impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> { impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> {
type Item = T; type Item = T;
fn next(&mut self) -> Option<T> { fn next(&mut self) -> Option<T> {
while self.index < self.bitset.domain_size() { while self.index < self.bit_set.domain_size() {
let elem = T::new(self.index); let elem = T::new(self.index);
let chunk = &self.bitset.chunks[chunk_index(elem)]; let chunk = &self.bit_set.chunks[chunk_index(elem)];
match &chunk { match &chunk {
Zeros(chunk_domain_size) => { Zeros(chunk_domain_size) => {
self.index += *chunk_domain_size as usize; self.index += *chunk_domain_size as usize;
@ -954,17 +953,17 @@ impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> {
init = f(init, item); init = f(init, item);
} }
let start_chunk = self.index / CHUNK_BITS; let start_chunk = self.index / CHUNK_BITS;
let chunks = &self.bitset.chunks[start_chunk..]; let chunks = &self.bit_set.chunks[start_chunk..];
for (i, chunk) in chunks.iter().enumerate() { for (i, chunk) in chunks.iter().enumerate() {
let base = (start_chunk + i) * CHUNK_BITS; let base = (start_chunk + i) * CHUNK_BITS;
match chunk { match chunk {
Chunk::Zeros(_) => (), Zeros(_) => (),
Chunk::Ones(limit) => { Ones(limit) => {
for j in 0..(*limit as usize) { for j in 0..(*limit as usize) {
init = f(init, T::new(base + j)); init = f(init, T::new(base + j));
} }
} }
Chunk::Mixed(_, _, words) => { Mixed(_, _, words) => {
init = BitIter::new(&**words).fold(init, |val, mut item: T| { init = BitIter::new(&**words).fold(init, |val, mut item: T| {
item.increment_by(base); item.increment_by(base);
f(val, item) f(val, item)
@ -1302,15 +1301,13 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> {
// Get the position of the next set bit in the current word, // Get the position of the next set bit in the current word,
// then clear the bit. // then clear the bit.
let bit_pos = self.word.trailing_zeros() as usize; let bit_pos = self.word.trailing_zeros() as usize;
let bit = 1 << bit_pos; self.word ^= 1 << bit_pos;
self.word ^= bit;
return Some(T::new(bit_pos + self.offset)); return Some(T::new(bit_pos + self.offset));
} }
// Move onto the next word. `wrapping_add()` is needed to handle // Move onto the next word. `wrapping_add()` is needed to handle
// the degenerate initial value given to `offset` in `new()`. // the degenerate initial value given to `offset` in `new()`.
let word = self.iter.next()?; self.word = *self.iter.next()?;
self.word = *word;
self.offset = self.offset.wrapping_add(WORD_BITS); self.offset = self.offset.wrapping_add(WORD_BITS);
} }
} }