Add optimized sparse-hybrid / dense-hybrid intersect

This commit is contained in:
Will Crichton 2021-08-25 15:10:33 -07:00
parent 415d5e860f
commit 2110ac303e

View File

@ -267,6 +267,16 @@ fn sparse_intersect<T: Idx>(
set.elems.len() != size set.elems.len() != size
} }
fn dense_sparse_intersect<T: Idx>(
dense: &BitSet<T>,
sparse: &SparseBitSet<T>,
) -> (SparseBitSet<T>, bool) {
let n = dense.count();
let mut sparse_copy = sparse.clone();
sparse_intersect(&mut sparse_copy, |el| !dense.contains(*el));
(sparse_copy, dense.count() != n)
}
impl<T: Idx> BitRelations<HybridBitSet<T>> for BitSet<T> { impl<T: Idx> BitRelations<HybridBitSet<T>> for BitSet<T> {
fn union(&mut self, other: &HybridBitSet<T>) -> bool { fn union(&mut self, other: &HybridBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size()); assert_eq!(self.domain_size, other.domain_size());
@ -292,11 +302,9 @@ fn intersect(&mut self, other: &HybridBitSet<T>) -> bool {
assert_eq!(self.domain_size, other.domain_size()); assert_eq!(self.domain_size, other.domain_size());
match other { match other {
HybridBitSet::Sparse(sparse) => { HybridBitSet::Sparse(sparse) => {
let n = self.count(); let (updated, changed) = dense_sparse_intersect(self, sparse);
let mut sparse_copy = sparse.clone(); *self = updated.to_dense();
sparse_intersect(&mut sparse_copy, |el| !self.contains(*el)); changed
*self = sparse_copy.to_dense();
self.count() != n
} }
HybridBitSet::Dense(dense) => self.intersect(dense), HybridBitSet::Dense(dense) => self.intersect(dense),
} }
@ -364,7 +372,14 @@ fn intersect(&mut self, other: &HybridBitSet<T>) -> bool {
HybridBitSet::Sparse(self_sparse) => { HybridBitSet::Sparse(self_sparse) => {
sparse_intersect(self_sparse, |elem| other.contains(*elem)) sparse_intersect(self_sparse, |elem| other.contains(*elem))
} }
HybridBitSet::Dense(self_dense) => self_dense.intersect(other), HybridBitSet::Dense(self_dense) => match other {
HybridBitSet::Sparse(other_sparse) => {
let (updated, changed) = dense_sparse_intersect(self_dense, other_sparse);
*self = HybridBitSet::Sparse(updated);
changed
}
HybridBitSet::Dense(other_dense) => self_dense.intersect(other_dense),
},
} }
} }
} }