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