@@ -800,27 +800,39 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
800800 // words, and this happens often enough that it's a
801801 // performance win. Also, we only need to operate on the
802802 // in-use words, hence the slicing.
803- let op = |a, b| a | b;
804803 let num_words = num_words ( chunk_domain_size as usize ) ;
805- if bitwise_changes (
804+
805+ // If both sides are the same, nothing will change. This
806+ // case is very common and it's a pretty fast check, so
807+ // it's a performance win to do it.
808+ if self_chunk_words[ 0 ..num_words] == other_chunk_words[ 0 ..num_words] {
809+ continue ;
810+ }
811+
812+ // Do a more precise "will anything change?" test. Also a
813+ // performance win.
814+ let op = |a, b| a | b;
815+ if !bitwise_changes (
806816 & self_chunk_words[ 0 ..num_words] ,
807817 & other_chunk_words[ 0 ..num_words] ,
808818 op,
809819 ) {
810- let self_chunk_words = Rc :: make_mut ( self_chunk_words) ;
811- let has_changed = bitwise (
812- & mut self_chunk_words[ 0 ..num_words] ,
813- & other_chunk_words[ 0 ..num_words] ,
814- op,
815- ) ;
816- debug_assert ! ( has_changed) ;
817- * self_chunk_count =
818- count_ones ( & self_chunk_words[ 0 ..num_words] ) as ChunkSize ;
819- if * self_chunk_count == chunk_domain_size {
820- * self_chunk = Ones ;
821- }
822- changed = true ;
820+ continue ;
821+ }
822+
823+ // If we reach here, `self_chunk_words` is definitely changing.
824+ let self_chunk_words = Rc :: make_mut ( self_chunk_words) ;
825+ let has_changed = bitwise (
826+ & mut self_chunk_words[ 0 ..num_words] ,
827+ & other_chunk_words[ 0 ..num_words] ,
828+ op,
829+ ) ;
830+ debug_assert ! ( has_changed) ;
831+ * self_chunk_count = count_ones ( & self_chunk_words[ 0 ..num_words] ) as ChunkSize ;
832+ if * self_chunk_count == chunk_domain_size {
833+ * self_chunk = Ones ;
823834 }
835+ changed = true ;
824836 }
825837 }
826838 }
@@ -874,28 +886,29 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
874886 Mixed ( self_chunk_count, self_chunk_words) ,
875887 Mixed ( _other_chunk_count, other_chunk_words) ,
876888 ) => {
877- // See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
878- let op = |a : u64 , b : u64 | a & !b;
889+ // See `ChunkedBitSet::union` for details on what is happening here.
879890 let num_words = num_words ( chunk_domain_size as usize ) ;
880- if bitwise_changes (
891+ let op = |a : u64 , b : u64 | a & !b;
892+ if !bitwise_changes (
881893 & self_chunk_words[ 0 ..num_words] ,
882894 & other_chunk_words[ 0 ..num_words] ,
883895 op,
884896 ) {
885- let self_chunk_words = Rc :: make_mut ( self_chunk_words) ;
886- let has_changed = bitwise (
887- & mut self_chunk_words[ 0 ..num_words] ,
888- & other_chunk_words[ 0 ..num_words] ,
889- op,
890- ) ;
891- debug_assert ! ( has_changed) ;
892- * self_chunk_count =
893- count_ones ( & self_chunk_words[ 0 ..num_words] ) as ChunkSize ;
894- if * self_chunk_count == 0 {
895- * self_chunk = Zeros ;
896- }
897- changed = true ;
897+ continue ;
898898 }
899+
900+ let self_chunk_words = Rc :: make_mut ( self_chunk_words) ;
901+ let has_changed = bitwise (
902+ & mut self_chunk_words[ 0 ..num_words] ,
903+ & other_chunk_words[ 0 ..num_words] ,
904+ op,
905+ ) ;
906+ debug_assert ! ( has_changed) ;
907+ * self_chunk_count = count_ones ( & self_chunk_words[ 0 ..num_words] ) as ChunkSize ;
908+ if * self_chunk_count == 0 {
909+ * self_chunk = Zeros ;
910+ }
911+ changed = true ;
899912 }
900913 }
901914 }
@@ -931,28 +944,29 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
931944 Mixed ( self_chunk_count, self_chunk_words) ,
932945 Mixed ( _other_chunk_count, other_chunk_words) ,
933946 ) => {
934- // See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
935- let op = |a, b| a & b;
947+ // See `ChunkedBitSet::union` for details on what is happening here.
936948 let num_words = num_words ( chunk_domain_size as usize ) ;
937- if bitwise_changes (
949+ let op = |a, b| a & b;
950+ if !bitwise_changes (
938951 & self_chunk_words[ 0 ..num_words] ,
939952 & other_chunk_words[ 0 ..num_words] ,
940953 op,
941954 ) {
942- let self_chunk_words = Rc :: make_mut ( self_chunk_words) ;
943- let has_changed = bitwise (
944- & mut self_chunk_words[ 0 ..num_words] ,
945- & other_chunk_words[ 0 ..num_words] ,
946- op,
947- ) ;
948- debug_assert ! ( has_changed) ;
949- * self_chunk_count =
950- count_ones ( & self_chunk_words[ 0 ..num_words] ) as ChunkSize ;
951- if * self_chunk_count == 0 {
952- * self_chunk = Zeros ;
953- }
954- changed = true ;
955+ continue ;
955956 }
957+
958+ let self_chunk_words = Rc :: make_mut ( self_chunk_words) ;
959+ let has_changed = bitwise (
960+ & mut self_chunk_words[ 0 ..num_words] ,
961+ & other_chunk_words[ 0 ..num_words] ,
962+ op,
963+ ) ;
964+ debug_assert ! ( has_changed) ;
965+ * self_chunk_count = count_ones ( & self_chunk_words[ 0 ..num_words] ) as ChunkSize ;
966+ if * self_chunk_count == 0 {
967+ * self_chunk = Zeros ;
968+ }
969+ changed = true ;
956970 }
957971 }
958972 }
0 commit comments