Rename some confusing bitset helper functions

This commit is contained in:
Zalathar
2026-03-10 16:07:34 +11:00
parent 63b1dfc0e0
commit 766aa193e7
+25 -25
View File
@@ -319,7 +319,7 @@ pub fn union_not(&mut self, other: &DenseBitSet<T>) {
// quickly and accurately detect whether the update changed anything.
// But that's only worth doing if there's an actual use-case.
bitwise(&mut self.words, &other.words, |a, b| a | !b);
update_words(&mut self.words, &other.words, |a, b| a | !b);
// The bitwise update `a | !b` can result in the last word containing
// out-of-domain bits, so we need to clear them.
self.clear_excess_bits();
@@ -330,17 +330,17 @@ pub fn union_not(&mut self, other: &DenseBitSet<T>) {
impl<T: Idx> BitRelations<DenseBitSet<T>> for DenseBitSet<T> {
fn union(&mut self, other: &DenseBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
bitwise(&mut self.words, &other.words, |a, b| a | b)
update_words(&mut self.words, &other.words, |a, b| a | b)
}
fn subtract(&mut self, other: &DenseBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
bitwise(&mut self.words, &other.words, |a, b| a & !b)
update_words(&mut self.words, &other.words, |a, b| a & !b)
}
fn intersect(&mut self, other: &DenseBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size);
bitwise(&mut self.words, &other.words, |a, b| a & b)
update_words(&mut self.words, &other.words, |a, b| a & b)
}
}
@@ -787,7 +787,7 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
// Do a more precise "will anything change?" test. Also a
// performance win.
let op = |a, b| a | b;
if !bitwise_changes(
if !would_modify_words(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
@@ -797,7 +797,7 @@ fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
// If we reach here, `self_chunk_words` is definitely changing.
let self_chunk_words = Rc::make_mut(self_chunk_words);
let has_changed = bitwise(
let has_changed = update_words(
&mut self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
@@ -865,7 +865,7 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
// See `ChunkedBitSet::union` for details on what is happening here.
let num_words = num_words(*chunk_domain_size as usize);
let op = |a: Word, b: Word| a & !b;
if !bitwise_changes(
if !would_modify_words(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
@@ -874,7 +874,7 @@ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
}
let self_chunk_words = Rc::make_mut(self_chunk_words);
let has_changed = bitwise(
let has_changed = update_words(
&mut self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
@@ -914,7 +914,7 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
// See `ChunkedBitSet::union` for details on what is happening here.
let num_words = num_words(*chunk_domain_size as usize);
let op = |a, b| a & b;
if !bitwise_changes(
if !would_modify_words(
&self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
@@ -923,7 +923,7 @@ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
}
let self_chunk_words = Rc::make_mut(self_chunk_words);
let has_changed = bitwise(
let has_changed = update_words(
&mut self_chunk_words[0..num_words],
&other_chunk_words[0..num_words],
op,
@@ -1052,10 +1052,10 @@ fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
/// Sets `out_vec[i] = op(out_vec[i], in_vec[i])` for each index `i` in both
/// Sets `lhs[i] = op(lhs[i], rhs[i])` for each index `i` in both
/// slices. The slices must have the same length.
///
/// Returns true if at least one bit in `out_vec` was changed.
/// Returns true if at least one bit in `lhs` was changed.
///
/// ## Warning
/// Some bitwise operations (e.g. union-not, xor) can set output bits that were
@@ -1065,16 +1065,16 @@ fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
/// "changed" return value unreliable, because the change might have only
/// affected excess bits.
#[inline]
fn bitwise<Op>(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool
fn update_words<Op>(lhs: &mut [Word], rhs: &[Word], op: Op) -> bool
where
Op: Fn(Word, Word) -> Word,
{
assert_eq!(out_vec.len(), in_vec.len());
assert_eq!(lhs.len(), rhs.len());
let mut changed = 0;
for (out_elem, in_elem) in iter::zip(out_vec, in_vec) {
let old_val = *out_elem;
let new_val = op(old_val, *in_elem);
*out_elem = new_val;
for (lhs_slot, &rhs_val) in iter::zip(lhs, rhs) {
let old_val = *lhs_slot;
let new_val = op(old_val, rhs_val);
*lhs_slot = new_val;
// This is essentially equivalent to a != with changed being a bool, but
// in practice this code gets auto-vectorized by the compiler for most
// operators. Using != here causes us to generate quite poor code as the
@@ -1084,16 +1084,16 @@ fn bitwise<Op>(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool
changed != 0
}
/// Does this bitwise operation change `out_vec`?
/// Returns true if a call to [`update_words`] would modify `lhs`, i.e.
/// `lhs[i] != op(lhs[i], rhs[i])` for some `i`.
#[inline]
fn bitwise_changes<Op>(out_vec: &[Word], in_vec: &[Word], op: Op) -> bool
fn would_modify_words<Op>(lhs: &[Word], rhs: &[Word], op: Op) -> bool
where
Op: Fn(Word, Word) -> Word,
{
assert_eq!(out_vec.len(), in_vec.len());
for (out_elem, in_elem) in iter::zip(out_vec, in_vec) {
let old_val = *out_elem;
let new_val = op(old_val, *in_elem);
assert_eq!(lhs.len(), rhs.len());
for (&old_val, &rhs_val) in iter::zip(lhs, rhs) {
let new_val = op(old_val, rhs_val);
if old_val != new_val {
return true;
}
@@ -1499,7 +1499,7 @@ pub fn union_row_with(&mut self, with: &DenseBitSet<C>, write: R) -> bool {
assert!(write.index() < self.num_rows);
assert_eq!(with.domain_size(), self.num_columns);
let (write_start, write_end) = self.range(write);
bitwise(&mut self.words[write_start..write_end], &with.words, |a, b| a | b)
update_words(&mut self.words[write_start..write_end], &with.words, |a, b| a | b)
}
/// Sets every cell in `row` to true.