@@ -45,6 +45,11 @@ fn hash_elem_using<B: BuildHasher, K: ?Sized + Hash>(build: &B, k: &K) -> HashVa
45
45
#[ derive( Copy , Debug ) ]
46
46
struct HashValue ( usize ) ;
47
47
48
+ impl HashValue {
49
+ #[ inline( always) ]
50
+ fn get ( self ) -> usize { self . 0 }
51
+ }
52
+
48
53
impl Clone for HashValue {
49
54
#[ inline]
50
55
fn clone ( & self ) -> Self { * self }
@@ -1059,37 +1064,27 @@ impl<K, V, S> OrderMap<K, V, S>
1059
1064
pub fn sort_by < F > ( & mut self , mut compare : F )
1060
1065
where F : FnMut ( & K , & V , & K , & V ) -> Ordering ,
1061
1066
{
1062
- // new_index will form a lookup map from current index -> new index.
1063
- let mut new_index = Vec :: from_iter ( 0 ..self . len ( ) ) ;
1064
- new_index. sort_by ( |& i, & j| {
1065
- let ei = & self . entries [ i] ;
1066
- let ej = & self . entries [ j] ;
1067
- compare ( & ei. key , & ei. value , & ej. key , & ej. value )
1068
- } ) ;
1067
+ // a bucket is Key-Value-Hash; here we temporarily use the hash field to
1068
+ // store the old index instead.
1069
+ //
1070
+ // Save the old hash values in `side_index`.
1071
+ //
1072
+ // Then we can sort `self.entries` in place.
1073
+ let mut side_index = Vec :: from_iter ( enumerate ( & mut self . entries ) . map ( |( i, elt) | {
1074
+ replace ( & mut elt. hash , HashValue ( i) ) . get ( )
1075
+ } ) ) ;
1069
1076
1070
- // Apply new index to self.indices
1071
- dispatch_32_vs_64 ! ( self . apply_new_index( & new_index) ) ;
1072
-
1073
- // Apply new index to entries
1074
- apply_permutation ( & mut new_index, & mut self . entries ) ;
1075
-
1076
- /// Apply a permutation
1077
- ///
1078
- /// perm: Each index 0..v.len() appear exactly once.
1079
- fn apply_permutation < T > ( perm : & mut [ usize ] , v : & mut [ T ] ) {
1080
- debug_assert_eq ! ( perm. len( ) , v. len( ) ) ;
1081
-
1082
- for i in 0 ..perm. len ( ) {
1083
- let mut current = i;
1084
- while i != perm[ current] {
1085
- let next = replace ( & mut perm[ current] , current) ;
1086
- // move element from next to current
1087
- v. swap ( next, current) ;
1088
- current = next;
1089
- }
1090
- perm[ current] = current;
1091
- }
1077
+ self . entries . sort_by ( move |ei, ej| compare ( & ei. key , & ei. value , & ej. key , & ej. value ) ) ;
1078
+
1079
+ // Here we write back the hash values from side_index and fill
1080
+ // in side_index with a mapping from old the new index instead.
1081
+ for ( i, ent) in enumerate ( & mut self . entries ) {
1082
+ let old_index = ent. hash . get ( ) ;
1083
+ ent. hash = HashValue ( replace ( & mut side_index[ old_index] , i) ) ;
1092
1084
}
1085
+
1086
+ // Apply new index to self.indices
1087
+ dispatch_32_vs_64 ! ( self . apply_new_index( & side_index) ) ;
1093
1088
}
1094
1089
1095
1090
fn apply_new_index < Sz > ( & mut self , new_index : & [ usize ] )
0 commit comments