@@ -460,6 +460,10 @@ impl<T: Idx> ChunkedBitSet<T> {
460
460
self.chunks.iter().map(|chunk| chunk.count()).sum()
461
461
}
462
462
463
+ pub fn is_empty(&self) -> bool {
464
+ self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..) | Chunk::Ones(0)))
465
+ }
466
+
463
467
/// Returns `true` if `self` contains `elem`.
464
468
#[inline]
465
469
pub fn contains(&self, elem: T) -> bool {
@@ -668,12 +672,138 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
668
672
changed
669
673
}
670
674
671
- fn subtract(&mut self, _other: &ChunkedBitSet<T>) -> bool {
672
- unimplemented!("implement if/when necessary");
675
+ fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
676
+ assert_eq!(self.domain_size, other.domain_size);
677
+ debug_assert_eq!(self.chunks.len(), other.chunks.len());
678
+
679
+ let mut changed = false;
680
+ for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
681
+ match (&mut self_chunk, &other_chunk) {
682
+ (Zeros(..), _) | (_, Zeros(..)) => {}
683
+ (Ones(self_chunk_domain_size), Ones(other_chunk_domain_size)) => {
684
+ debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
685
+ changed = true;
686
+ *self_chunk = Zeros(*self_chunk_domain_size);
687
+ }
688
+ (_, Ones(_)) => {}
689
+ (
690
+ Ones(self_chunk_domain_size),
691
+ Mixed(other_chunk_domain_size, other_chunk_count, other_chunk_words),
692
+ ) => {
693
+ debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
694
+ changed = true;
695
+ let num_words = num_words(*self_chunk_domain_size as usize);
696
+ debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS);
697
+ let mut tail_mask =
698
+ 1 << (*other_chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1;
699
+ let mut self_chunk_words = **other_chunk_words;
700
+ for word in self_chunk_words[0..num_words].iter_mut().rev() {
701
+ *word = !*word & tail_mask;
702
+ tail_mask = u64::MAX;
703
+ }
704
+ let self_chunk_count = *self_chunk_domain_size - *other_chunk_count;
705
+ debug_assert_eq!(
706
+ self_chunk_count,
707
+ self_chunk_words[0..num_words]
708
+ .iter()
709
+ .map(|w| w.count_ones() as ChunkSize)
710
+ .sum()
711
+ );
712
+ *self_chunk =
713
+ Mixed(*self_chunk_domain_size, self_chunk_count, Rc::new(self_chunk_words));
714
+ }
715
+ (
716
+ Mixed(
717
+ self_chunk_domain_size,
718
+ ref mut self_chunk_count,
719
+ ref mut self_chunk_words,
720
+ ),
721
+ Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
722
+ ) => {
723
+ // See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
724
+ let op = |a: u64, b: u64| a & !b;
725
+ let num_words = num_words(*self_chunk_domain_size as usize);
726
+ if bitwise_changes(
727
+ &self_chunk_words[0..num_words],
728
+ &other_chunk_words[0..num_words],
729
+ op,
730
+ ) {
731
+ let self_chunk_words = Rc::make_mut(self_chunk_words);
732
+ let has_changed = bitwise(
733
+ &mut self_chunk_words[0..num_words],
734
+ &other_chunk_words[0..num_words],
735
+ op,
736
+ );
737
+ debug_assert!(has_changed);
738
+ *self_chunk_count = self_chunk_words[0..num_words]
739
+ .iter()
740
+ .map(|w| w.count_ones() as ChunkSize)
741
+ .sum();
742
+ if *self_chunk_count == 0 {
743
+ *self_chunk = Zeros(*self_chunk_domain_size);
744
+ }
745
+ changed = true;
746
+ }
747
+ }
748
+ }
749
+ }
750
+ changed
673
751
}
674
752
675
- fn intersect(&mut self, _other: &ChunkedBitSet<T>) -> bool {
676
- unimplemented!("implement if/when necessary");
753
+ fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
754
+ assert_eq!(self.domain_size, other.domain_size);
755
+ debug_assert_eq!(self.chunks.len(), other.chunks.len());
756
+
757
+ let mut changed = false;
758
+ for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
759
+ match (&mut self_chunk, &other_chunk) {
760
+ (Zeros(..), _) | (_, Ones(..)) => {}
761
+ (
762
+ Ones(self_chunk_domain_size),
763
+ Zeros(other_chunk_domain_size) | Mixed(other_chunk_domain_size, ..),
764
+ )
765
+ | (Mixed(self_chunk_domain_size, ..), Zeros(other_chunk_domain_size)) => {
766
+ debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
767
+ changed = true;
768
+ *self_chunk = other_chunk.clone();
769
+ }
770
+ (
771
+ Mixed(
772
+ self_chunk_domain_size,
773
+ ref mut self_chunk_count,
774
+ ref mut self_chunk_words,
775
+ ),
776
+ Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
777
+ ) => {
778
+ // See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
779
+ let op = |a, b| a & b;
780
+ let num_words = num_words(*self_chunk_domain_size as usize);
781
+ if bitwise_changes(
782
+ &self_chunk_words[0..num_words],
783
+ &other_chunk_words[0..num_words],
784
+ op,
785
+ ) {
786
+ let self_chunk_words = Rc::make_mut(self_chunk_words);
787
+ let has_changed = bitwise(
788
+ &mut self_chunk_words[0..num_words],
789
+ &other_chunk_words[0..num_words],
790
+ op,
791
+ );
792
+ debug_assert!(has_changed);
793
+ *self_chunk_count = self_chunk_words[0..num_words]
794
+ .iter()
795
+ .map(|w| w.count_ones() as ChunkSize)
796
+ .sum();
797
+ if *self_chunk_count == 0 {
798
+ *self_chunk = Zeros(*self_chunk_domain_size);
799
+ }
800
+ changed = true;
801
+ }
802
+ }
803
+ }
804
+ }
805
+
806
+ changed
677
807
}
678
808
}
679
809
0 commit comments