@@ -93,10 +93,62 @@ impl<T> UnstableSmallSortTypeImpl for T {
9393impl < T : FreezeMarker > UnstableSmallSortTypeImpl for T {
9494 #[ inline( always) ]
9595 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
100152 }
101153 }
102154
@@ -105,9 +157,13 @@ impl<T: FreezeMarker> UnstableSmallSortTypeImpl for T {
105157 where
106158 F : FnMut ( & T , & T ) -> bool ,
107159 {
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+ }
111167 }
112168}
113169
@@ -137,37 +193,6 @@ const SMALL_SORT_NETWORK_SCRATCH_LEN: usize = SMALL_SORT_NETWORK_THRESHOLD;
137193/// within this limit.
138194const MAX_STACK_ARRAY_SIZE : usize = 4096 ;
139195
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-
171196fn small_sort_fallback < T , F : FnMut ( & T , & T ) -> bool > ( v : & mut [ T ] , is_less : & mut F ) {
172197 if v. len ( ) >= 2 {
173198 insertion_sort_shift_left ( v, 1 , is_less) ;
@@ -822,25 +847,3 @@ pub(crate) const fn has_efficient_in_place_swap<T>() -> bool {
822847 // Heuristic that holds true on all tested 64-bit capable architectures.
823848 mem:: size_of :: < T > ( ) <= 8 // mem::size_of::<u64>()
824849}
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