[red-knot] add BitSet::is_empty and BitSet::union (#13333)

Add `::is_empty` and `::union` methods to the `BitSet` implementation.

Allowing unused for now, until these methods become used later with the
declared-types implementation.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Carl Meyer 2024-09-12 14:25:45 -04:00 committed by GitHub
parent 175d067250
commit 43a5922f6f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -32,17 +32,26 @@ impl<const B: usize> BitSet<B> {
bitset bitset
} }
#[allow(unused)]
pub(super) fn is_empty(&self) -> bool {
self.blocks().iter().all(|&b| b == 0)
}
/// Convert from Inline to Heap, if needed, and resize the Heap vector, if needed. /// Convert from Inline to Heap, if needed, and resize the Heap vector, if needed.
fn resize(&mut self, value: u32) { fn resize(&mut self, value: u32) {
let num_blocks_needed = (value / 64) + 1; let num_blocks_needed = (value / 64) + 1;
self.resize_blocks(num_blocks_needed as usize);
}
fn resize_blocks(&mut self, num_blocks_needed: usize) {
match self { match self {
Self::Inline(blocks) => { Self::Inline(blocks) => {
let mut vec = blocks.to_vec(); let mut vec = blocks.to_vec();
vec.resize(num_blocks_needed as usize, 0); vec.resize(num_blocks_needed, 0);
*self = Self::Heap(vec); *self = Self::Heap(vec);
} }
Self::Heap(vec) => { Self::Heap(vec) => {
vec.resize(num_blocks_needed as usize, 0); vec.resize(num_blocks_needed, 0);
} }
} }
} }
@ -89,6 +98,20 @@ impl<const B: usize> BitSet<B> {
} }
} }
/// Union in-place with another [`BitSet`].
#[allow(unused)]
pub(super) fn union(&mut self, other: &BitSet<B>) {
let mut max_len = self.blocks().len();
let other_len = other.blocks().len();
if other_len > max_len {
max_len = other_len;
self.resize_blocks(max_len);
}
for (my_block, other_block) in self.blocks_mut().iter_mut().zip(other.blocks()) {
*my_block |= other_block;
}
}
/// Return an iterator over the values (in ascending order) in this [`BitSet`]. /// Return an iterator over the values (in ascending order) in this [`BitSet`].
pub(super) fn iter(&self) -> BitSetIterator<'_, B> { pub(super) fn iter(&self) -> BitSetIterator<'_, B> {
let blocks = self.blocks(); let blocks = self.blocks();
@ -218,6 +241,59 @@ mod tests {
assert_bitset(&b1, &[89]); assert_bitset(&b1, &[89]);
} }
#[test]
fn union() {
let mut b1 = BitSet::<1>::with(2);
let b2 = BitSet::<1>::with(4);
b1.union(&b2);
assert_bitset(&b1, &[2, 4]);
}
#[test]
fn union_mixed_1() {
let mut b1 = BitSet::<1>::with(4);
let mut b2 = BitSet::<1>::with(4);
b1.insert(89);
b2.insert(5);
b1.union(&b2);
assert_bitset(&b1, &[4, 5, 89]);
}
#[test]
fn union_mixed_2() {
let mut b1 = BitSet::<1>::with(4);
let mut b2 = BitSet::<1>::with(4);
b1.insert(23);
b2.insert(89);
b1.union(&b2);
assert_bitset(&b1, &[4, 23, 89]);
}
#[test]
fn union_heap() {
let mut b1 = BitSet::<1>::with(4);
let mut b2 = BitSet::<1>::with(4);
b1.insert(89);
b2.insert(90);
b1.union(&b2);
assert_bitset(&b1, &[4, 89, 90]);
}
#[test]
fn union_heap_2() {
let mut b1 = BitSet::<1>::with(89);
let mut b2 = BitSet::<1>::with(89);
b1.insert(91);
b2.insert(90);
b1.union(&b2);
assert_bitset(&b1, &[89, 90, 91]);
}
#[test] #[test]
fn multiple_blocks() { fn multiple_blocks() {
let mut b = BitSet::<2>::with(120); let mut b = BitSet::<2>::with(120);
@ -225,4 +301,11 @@ mod tests {
assert!(matches!(b, BitSet::Inline(_))); assert!(matches!(b, BitSet::Inline(_)));
assert_bitset(&b, &[45, 120]); assert_bitset(&b, &[45, 120]);
} }
#[test]
fn empty() {
let b = BitSet::<1>::default();
assert!(b.is_empty());
}
} }