@@ -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