@@ -93,10 +93,62 @@ impl<T> UnstableSmallSortTypeImpl for T {
93
93
impl < T : FreezeMarker > UnstableSmallSortTypeImpl for T {
94
94
#[ inline( always) ]
95
95
fn small_sort_threshold ( ) -> usize {
96
- match const { choose_unstable_small_sort :: < T > ( ) } {
97
- UnstableSmallSort :: Fallback => SMALL_SORT_FALLBACK_THRESHOLD ,
98
- UnstableSmallSort :: General => SMALL_SORT_GENERAL_THRESHOLD ,
99
- UnstableSmallSort :: Network => SMALL_SORT_NETWORK_THRESHOLD ,
96
+ <T as UnstableSmallSortFreezeTypeImpl >:: small_sort_threshold ( )
97
+ }
98
+
99
+ #[ inline( always) ]
100
+ fn small_sort < F > ( v : & mut [ T ] , is_less : & mut F )
101
+ where
102
+ F : FnMut ( & T , & T ) -> bool ,
103
+ {
104
+ <T as UnstableSmallSortFreezeTypeImpl >:: small_sort ( v, is_less) ;
105
+ }
106
+ }
107
+
108
+ /// FIXME(effects) use original ipnsort approach with choose_unstable_small_sort,
109
+ /// as found here https://github.com/Voultapher/sort-research-rs/blob/438fad5d0495f65d4b72aa87f0b62fc96611dff3/ipnsort/src/smallsort.rs#L83C10-L83C36.
110
+ pub ( crate ) trait UnstableSmallSortFreezeTypeImpl : Sized + FreezeMarker {
111
+ fn small_sort_threshold ( ) -> usize ;
112
+
113
+ fn small_sort < F : FnMut ( & Self , & Self ) -> bool > ( v : & mut [ Self ] , is_less : & mut F ) ;
114
+ }
115
+
116
+ impl < T : FreezeMarker > UnstableSmallSortFreezeTypeImpl for T {
117
+ #[ inline( always) ]
118
+ default fn small_sort_threshold ( ) -> usize {
119
+ if ( mem:: size_of :: < T > ( ) * SMALL_SORT_GENERAL_SCRATCH_LEN ) <= MAX_STACK_ARRAY_SIZE {
120
+ SMALL_SORT_GENERAL_THRESHOLD
121
+ } else {
122
+ SMALL_SORT_FALLBACK_THRESHOLD
123
+ }
124
+ }
125
+
126
+ #[ inline( always) ]
127
+ default fn small_sort < F > ( v : & mut [ T ] , is_less : & mut F )
128
+ where
129
+ F : FnMut ( & T , & T ) -> bool ,
130
+ {
131
+ if ( mem:: size_of :: < T > ( ) * SMALL_SORT_GENERAL_SCRATCH_LEN ) <= MAX_STACK_ARRAY_SIZE {
132
+ small_sort_general ( v, is_less) ;
133
+ } else {
134
+ small_sort_fallback ( v, is_less) ;
135
+ }
136
+ }
137
+ }
138
+
139
+ /// SAFETY: Only used for run-time optimization heuristic.
140
+ #[ rustc_unsafe_specialization_marker]
141
+ trait CopyMarker { }
142
+
143
+ impl < T : FreezeMarker + CopyMarker > UnstableSmallSortFreezeTypeImpl for T {
144
+ #[ inline( always) ]
145
+ fn small_sort_threshold ( ) -> usize {
146
+ if has_efficient_in_place_swap :: < T > ( )
147
+ && ( mem:: size_of :: < T > ( ) * SMALL_SORT_NETWORK_SCRATCH_LEN ) <= MAX_STACK_ARRAY_SIZE
148
+ {
149
+ SMALL_SORT_NETWORK_SCRATCH_LEN
150
+ } else {
151
+ SMALL_SORT_FALLBACK_THRESHOLD
100
152
}
101
153
}
102
154
@@ -105,9 +157,13 @@ impl<T: FreezeMarker> UnstableSmallSortTypeImpl for T {
105
157
where
106
158
F : FnMut ( & T , & T ) -> bool ,
107
159
{
108
- // This construct is used to limit the LLVM IR generated, which saves large amounts of
109
- // compile-time by only instantiating the code that is needed. Idea by Frank Steffahn.
110
- ( const { inst_unstable_small_sort :: < T , F > ( ) } ) ( v, is_less) ;
160
+ if has_efficient_in_place_swap :: < T > ( )
161
+ && ( mem:: size_of :: < T > ( ) * SMALL_SORT_NETWORK_SCRATCH_LEN ) <= MAX_STACK_ARRAY_SIZE
162
+ {
163
+ small_sort_network ( v, is_less) ;
164
+ } else {
165
+ small_sort_fallback ( v, is_less) ;
166
+ }
111
167
}
112
168
}
113
169
@@ -137,37 +193,6 @@ const SMALL_SORT_NETWORK_SCRATCH_LEN: usize = SMALL_SORT_NETWORK_THRESHOLD;
137
193
/// within this limit.
138
194
const MAX_STACK_ARRAY_SIZE : usize = 4096 ;
139
195
140
- enum UnstableSmallSort {
141
- Fallback ,
142
- General ,
143
- Network ,
144
- }
145
-
146
- const fn choose_unstable_small_sort < T : FreezeMarker > ( ) -> UnstableSmallSort {
147
- if T :: is_copy ( )
148
- && has_efficient_in_place_swap :: < T > ( )
149
- && ( mem:: size_of :: < T > ( ) * SMALL_SORT_NETWORK_SCRATCH_LEN ) <= MAX_STACK_ARRAY_SIZE
150
- {
151
- // Heuristic for int like types.
152
- return UnstableSmallSort :: Network ;
153
- }
154
-
155
- if ( mem:: size_of :: < T > ( ) * SMALL_SORT_GENERAL_SCRATCH_LEN ) <= MAX_STACK_ARRAY_SIZE {
156
- return UnstableSmallSort :: General ;
157
- }
158
-
159
- UnstableSmallSort :: Fallback
160
- }
161
-
162
- const fn inst_unstable_small_sort < T : FreezeMarker , F : FnMut ( & T , & T ) -> bool > ( )
163
- -> fn ( & mut [ T ] , & mut F ) {
164
- match const { choose_unstable_small_sort :: < T > ( ) } {
165
- UnstableSmallSort :: Fallback => small_sort_fallback :: < T , F > ,
166
- UnstableSmallSort :: General => small_sort_general :: < T , F > ,
167
- UnstableSmallSort :: Network => small_sort_network :: < T , F > ,
168
- }
169
- }
170
-
171
196
fn small_sort_fallback < T , F : FnMut ( & T , & T ) -> bool > ( v : & mut [ T ] , is_less : & mut F ) {
172
197
if v. len ( ) >= 2 {
173
198
insertion_sort_shift_left ( v, 1 , is_less) ;
@@ -822,25 +847,3 @@ pub(crate) const fn has_efficient_in_place_swap<T>() -> bool {
822
847
// Heuristic that holds true on all tested 64-bit capable architectures.
823
848
mem:: size_of :: < T > ( ) <= 8 // mem::size_of::<u64>()
824
849
}
825
-
826
- /// SAFETY: Only used for run-time optimization heuristic.
827
- #[ rustc_unsafe_specialization_marker]
828
- trait CopyMarker { }
829
-
830
- impl < T : Copy > CopyMarker for T { }
831
-
832
- #[ const_trait]
833
- trait IsCopy {
834
- fn is_copy ( ) -> bool ;
835
- }
836
-
837
- impl < T > const IsCopy for T {
838
- default fn is_copy ( ) -> bool {
839
- false
840
- }
841
- }
842
- impl < T : CopyMarker > const IsCopy for T {
843
- fn is_copy ( ) -> bool {
844
- true
845
- }
846
- }
0 commit comments