@@ -366,17 +366,23 @@ where
366366 A : Ord + Clone ,
367367 S : DataMut < Elem = A > ,
368368{
369- if indexes. is_empty ( ) {
370- return IndexMap :: new ( ) ;
371- }
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) ;
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+ ) ;
377381
378- // We convert the vector to a more search-friendly `IndexMap`.
379- indexes. iter ( ) . cloned ( ) . zip ( values. into_iter ( ) ) . collect ( )
382+ // We convert the vector to a more search-friendly `IndexMap`.
383+ indexes. iter ( ) . cloned ( ) . zip ( values. into_iter ( ) ) . collect ( )
384+ }
385+ }
380386}
381387
382388/// This is the recursive portion of `get_many_from_sorted_mut_unchecked`.
@@ -420,81 +426,10 @@ fn _get_many_from_sorted_mut_unchecked<A>(
420426 // Sorted sample of 5 equally spaced elements around the center.
421427 let mut sample = [ 0 ; 5 ] ;
422428 sample_mut ( & mut array, & mut sample) ;
423- let ( lower_index, upper_index) = if indexes. len ( ) == 1 {
424- // Adapt pivot sampling to relative sought rank and switch from dual-pivot to single-pivot
425- // partitioning for extreme sought ranks.
426- let sought_rank = indexes[ 0 ] as f64 / n as f64 ;
427- if ( 0.036 ..=0.964 ) . contains ( & sought_rank) {
428- if sought_rank <= 0.5 {
429- if sought_rank <= 0.153 {
430- ( 0 , 1 ) // (0, 0, 3)
431- } else {
432- ( 0 , 2 ) // (0, 1, 2)
433- }
434- } else {
435- if sought_rank <= 0.847 {
436- ( 2 , 4 ) // (2, 1, 0)
437- } else {
438- ( 3 , 4 ) // (3, 0, 0)
439- }
440- }
441- } else {
442- let pivot_index = if sought_rank <= 0.5 {
443- 0 // (0, 4)
444- } else {
445- 4 // (4, 0)
446- } ;
447-
448- // We partition the array with respect to the pivot value. The pivot value moves to the
449- // new `pivot_index`.
450- //
451- // Elements strictly less than the pivot value have indexes < `pivot_index`.
452- //
453- // Elements greater than or equal the pivot value have indexes > `pivot_index`.
454- let pivot_index = array. partition_mut ( sample[ pivot_index] ) ;
455- let ( found_exact, split_index) = match indexes. binary_search ( & pivot_index) {
456- Ok ( index) => ( true , index) ,
457- Err ( index) => ( false , index) ,
458- } ;
459- let ( lower_indexes, upper_indexes) = indexes. split_at_mut ( split_index) ;
460- let ( lower_values, upper_values) = values. split_at_mut ( split_index) ;
461- let ( upper_indexes, upper_values) = if found_exact {
462- upper_values[ 0 ] = array[ pivot_index] . clone ( ) ; // Write exactly found value.
463- ( & mut upper_indexes[ 1 ..] , & mut upper_values[ 1 ..] )
464- } else {
465- ( upper_indexes, upper_values)
466- } ;
467-
468- // We search recursively for the values corresponding to indexes strictly less than
469- // `pivot_index` in the lower partition.
470- maybe_grow ( RED_ZONE , STACK_SIZE , || {
471- _get_many_from_sorted_mut_unchecked (
472- array. slice_axis_mut ( Axis ( 0 ) , Slice :: from ( ..pivot_index) ) ,
473- lower_indexes,
474- lower_values,
475- ) ;
476- } ) ;
477-
478- // We search recursively for the values corresponding to indexes greater than or equal
479- // `pivot_index` in the upper partition. Since only the upper partition of the array is
480- // passed in, the indexes need to be shifted by length of the lower partition.
481- upper_indexes. iter_mut ( ) . for_each ( |x| * x -= pivot_index + 1 ) ;
482- maybe_grow ( RED_ZONE , STACK_SIZE , || {
483- _get_many_from_sorted_mut_unchecked (
484- array. slice_axis_mut ( Axis ( 0 ) , Slice :: from ( pivot_index + 1 ..) ) ,
485- upper_indexes,
486- upper_values,
487- ) ;
488- } ) ;
489-
490- return ;
491- }
492- } else {
493- // Since there is no single sought rank to adapt pivot sampling to, the recommended skewed
494- // pivot sampling of dual-pivot Quicksort is used in the assumption that multiple indexes
495- // change characteristics from Quickselect towards Quicksort.
496- ( 0 , 2 ) // (0, 1, 2)
497- } ;
429+ // Since there is no single sought rank to adapt pivot sampling to, the recommended skewed
430+ // pivot sampling of dual-pivot Quicksort is used in the assumption that multiple indexes
431+ // change characteristics from Quickselect towards Quicksort.
432+ let ( lower_index, upper_index) = ( 0 , 2 ) ; // (0, 1, 2)
498433
499434 // We partition the array with respect to the two pivot values. The pivot values move to the new
500435 // `lower_index` and `upper_index`.
0 commit comments