@@ -48,21 +48,21 @@ where
4848 S : DataMut ,
4949 S2 : Data < Elem = usize > ;
5050
51- /// Partitions the array in increasing order based on the values initially located at `0` and
52- /// `n - 1` where `n` is the number of elements in the array and returns the new indexes of the
53- /// values.
51+ /// Partitions the array in increasing order at two skewed pivot values as 1st and 3rd element
52+ /// of a sorted sample of 5 equally spaced elements around the center and returns their indexes.
53+ /// For arrays of less than 42 elements the outermost elements serve as sample for pivot values.
5454 ///
55- /// The elements are rearranged in such a way that the values initially located at `0` and
56- /// `n - 1` are moved to the position it would be in an array sorted in increasing order. The
57- /// return values are the new indexes of the values after rearrangement. All elements less than
58- /// the values are moved to their left and all elements equal or greater than the values are
59- /// moved to their right. The ordering of the elements in the three partitions is undefined.
55+ /// The elements are rearranged in such a way that the two pivot values are moved to the indexes
56+ /// they would be in an array sorted in increasing order. The return values are the new indexes
57+ /// of the values after rearrangement. All elements less than the values are moved to their left
58+ /// and all elements equal or greater than the values are moved to their right. The ordering of
59+ /// the elements in the three partitions is undefined.
6060 ///
6161 /// The array is shuffled **in place**, no copy of the array is allocated.
6262 ///
63- /// This method implements the partitioning scheme of [Yaroslavskiy-Bentley-Bloch Quicksort] .
63+ /// This method performs [dual-pivot partitioning] with skewed pivot sampling .
6464 ///
65- /// [Yaroslavskiy-Bentley-Bloch Quicksort ]: https://api.semanticscholar.org/CorpusID:51871084
65+ /// [dual-pivot partitioning ]: https://www.wild-inter.net/publications/wild-2018b.pdf
6666 ///
6767 /// # Example
6868 ///
@@ -151,11 +151,33 @@ where
151151 A : Ord + Clone ,
152152 S : DataMut ,
153153 {
154- // Sort `lowermost` and `uppermost` elements and use them as dual pivot.
155154 let lowermost = 0 ;
156155 let uppermost = self . len ( ) - 1 ;
157- if self [ lowermost] > self [ uppermost] {
158- self . swap ( lowermost, uppermost) ;
156+ if self . len ( ) < 42 {
157+ // Sort outermost elements and use them as pivots.
158+ if self [ lowermost] > self [ uppermost] {
159+ self . swap ( lowermost, uppermost) ;
160+ }
161+ } else {
162+ // Sample indexes of 5 evenly spaced elements around the center element.
163+ let mut samples = [ 0 ; 5 ] ;
164+ // Assume array of at least 7 elements.
165+ let seventh = self . len ( ) / ( samples. len ( ) + 2 ) ;
166+ samples[ 2 ] = self . len ( ) / 2 ;
167+ samples[ 1 ] = samples[ 2 ] - seventh;
168+ samples[ 0 ] = samples[ 1 ] - seventh;
169+ samples[ 3 ] = samples[ 2 ] + seventh;
170+ samples[ 4 ] = samples[ 3 ] + seventh;
171+ // Use insertion sort for sample elements by looking up their indexes.
172+ for mut index in 1 ..samples. len ( ) {
173+ while index > 0 && self [ samples[ index - 1 ] ] > self [ samples[ index] ] {
174+ self . swap ( samples[ index - 1 ] , samples[ index] ) ;
175+ index -= 1 ;
176+ }
177+ }
178+ // Use 1st and 3rd element of sorted sample as skewed pivots.
179+ self . swap ( lowermost, samples[ 0 ] ) ;
180+ self . swap ( uppermost, samples[ 2 ] ) ;
159181 }
160182 // Increasing running and partition index starting after lower pivot.
161183 let mut index = lowermost + 1 ;
0 commit comments