Skip to content

Commit 4c3ae67

Browse files
committed
Fix sample, allow single-pivot in bulk mode again.
* Move single-index delegation into recursion allowing single-pivoting in bulk mode. * Avoid worst case complexity in non-bulk and bulk mode by using dual-pivot if both sample choices of single-pivot are equal. * Fix first sample index from being skipped.
1 parent 359dc0c commit 4c3ae67

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

src/sort.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ where
183183
// Adapt pivot sampling to relative sought rank and switch from dual-pivot to
184184
// single-pivot partitioning for extreme sought ranks.
185185
let sought_rank = i as f64 / n as f64;
186-
if (0.036..=0.964).contains(&sought_rank) {
186+
if (0.036..=0.964).contains(&sought_rank) || self[sample[0]] == self[sample[4]] {
187187
let (lower_index, upper_index) = if sought_rank <= 0.5 {
188188
if sought_rank <= 0.153 {
189189
(0, 1) // (0, 0, 3)
@@ -366,23 +366,17 @@ where
366366
A: Ord + Clone,
367367
S: DataMut<Elem = A>,
368368
{
369-
match indexes.len() {
370-
0 => IndexMap::new(),
371-
1 => IndexMap::from([(indexes[0], array.get_from_sorted_mut(indexes[0]))]),
372-
_ => {
373-
// Since `!indexes.is_empty()` and indexes must be in-bounds, `array` must
374-
// be non-empty.
375-
let mut values = vec![array[0].clone(); indexes.len()];
376-
_get_many_from_sorted_mut_unchecked(
377-
array.view_mut(),
378-
&mut indexes.to_owned(),
379-
&mut values,
380-
);
381-
382-
// We convert the vector to a more search-friendly `IndexMap`.
383-
indexes.iter().cloned().zip(values.into_iter()).collect()
384-
}
369+
if indexes.is_empty() {
370+
return IndexMap::new();
385371
}
372+
373+
// Since `!indexes.is_empty()` and indexes must be in-bounds, `array` must
374+
// be non-empty.
375+
let mut values = vec![array[0].clone(); indexes.len()];
376+
_get_many_from_sorted_mut_unchecked(array.view_mut(), &mut indexes.to_owned(), &mut values);
377+
378+
// We convert the vector to a more search-friendly `IndexMap`.
379+
indexes.iter().cloned().zip(values.into_iter()).collect()
386380
}
387381

388382
/// This is the recursive portion of `get_many_from_sorted_mut_unchecked`.
@@ -408,6 +402,10 @@ fn _get_many_from_sorted_mut_unchecked<A>(
408402
// Nothing to do in this case.
409403
return;
410404
}
405+
if indexes.len() == 1 {
406+
values[0] = array.get_from_sorted_mut(indexes[0]);
407+
return;
408+
}
411409

412410
// Recursion cutoff at integer multiple of sample space divider of 7 elements.
413411
if n < 21 {
@@ -523,7 +521,7 @@ where
523521
// Lowermost sample index.
524522
let lowermost = array.len() / 2 - (sample.len() / 2) * space;
525523
// Equally space sample indexes and sort them by their values by looking up their indexes.
526-
for mut index in 1..sample.len() {
524+
for mut index in 0..sample.len() {
527525
// Equally space sample indexes based on their lowermost index.
528526
sample[index] = lowermost + index * space;
529527
// Insertion sort looking up only the already equally spaced sample indexes.

0 commit comments

Comments
 (0)