Rollup merge of #155381 - nnethercote:fix-ChunkedBitSet-subtract, r=Zalathar

Fix a bug in `ChunkedBitSet::subtract`

An operator precedence bug means an incorrect mask is used in `ChunkedBitSet::subtract`. Details in individual commits.

r? @dingxiangfei2009
This commit is contained in:
Jacob Pratt
2026-04-28 05:37:21 -04:00
committed by GitHub
2 changed files with 35 additions and 5 deletions
+8 -5
View File
@@ -833,13 +833,16 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
changed = true;
let num_words = num_words(*chunk_domain_size as usize);
debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS);
let mut tail_mask =
1 << (*chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1;
// Set `self_chunk_words` to `other_chunk_words`, then invert all bits and
// clear any excess bits in the final word.
let mut self_chunk_words = **other_chunk_words;
for word in self_chunk_words[0..num_words].iter_mut().rev() {
*word = !*word & tail_mask;
tail_mask = Word::MAX;
for word in self_chunk_words[0..num_words].iter_mut() {
*word = !*word;
}
clear_excess_bits_in_final_word(
*chunk_domain_size as usize,
&mut self_chunk_words[..num_words],
);
let self_chunk_ones_count = *chunk_domain_size - *other_chunk_ones_count;
debug_assert_eq!(
self_chunk_ones_count,
+27
View File
@@ -333,6 +333,33 @@ fn chunked_bitset() {
assert_eq!(b10000.count(), 6000);
b10000.assert_valid();
b10000b.assert_valid();
//-----------------------------------------------------------------------
let mut b64 = ChunkedBitSet::<usize>::new_filled(64);
let mut b64b = ChunkedBitSet::<usize>::new_empty(64);
b64b.insert(0);
b64.subtract(&b64b);
assert!(!b64.contains(0));
assert!(b64.contains(10));
assert!(b64.contains(50));
assert!(b64.contains(63));
assert_eq!(
b64.chunks(),
#[rustfmt::skip]
vec![
Mixed {
chunk_domain_size: 64,
ones_count: 63,
words: Rc::new([
0xfffffffffffffffe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
])
},
],
);
}
fn with_elements_chunked(elements: &[usize], domain_size: usize) -> ChunkedBitSet<usize> {