98
98
#![ cfg_attr( test, allow( unused_imports, dead_code) ) ]
99
99
100
100
use alloc:: boxed:: Box ;
101
- use core:: cmp:: Ordering :: { self , Greater } ;
101
+ use core:: cmp:: Ordering :: { self , Less } ;
102
102
use core:: mem:: size_of;
103
103
use core:: mem;
104
104
use core:: ptr;
@@ -1089,7 +1089,7 @@ impl<T> [T] {
1089
1089
pub fn sort ( & mut self )
1090
1090
where T : Ord
1091
1091
{
1092
- self . sort_by ( |a, b| a. cmp ( b) )
1092
+ merge_sort ( self , |a, b| a. lt ( b) ) ;
1093
1093
}
1094
1094
1095
1095
/// Sorts the slice using `f` to extract a key to compare elements by.
@@ -1119,7 +1119,7 @@ impl<T> [T] {
1119
1119
pub fn sort_by_key < B , F > ( & mut self , mut f : F )
1120
1120
where F : FnMut ( & T ) -> B , B : Ord
1121
1121
{
1122
- self . sort_by ( |a, b| f ( a) . cmp ( & f ( b) ) )
1122
+ merge_sort ( self , |a, b| f ( a) . lt ( & f ( b) ) ) ;
1123
1123
}
1124
1124
1125
1125
/// Sorts the slice using `compare` to compare elements.
@@ -1149,10 +1149,10 @@ impl<T> [T] {
1149
1149
/// ```
1150
1150
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1151
1151
#[ inline]
1152
- pub fn sort_by < F > ( & mut self , compare : F )
1152
+ pub fn sort_by < F > ( & mut self , mut compare : F )
1153
1153
where F : FnMut ( & T , & T ) -> Ordering
1154
1154
{
1155
- merge_sort ( self , compare)
1155
+ merge_sort ( self , |a , b| compare ( a , b ) == Less ) ;
1156
1156
}
1157
1157
1158
1158
/// Copies the elements from `src` into `self`.
@@ -1355,10 +1355,10 @@ impl<T: Clone> ToOwned for [T] {
1355
1355
/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted.
1356
1356
///
1357
1357
/// This is the integral subroutine of insertion sort.
1358
- fn insert_head < T , F > ( v : & mut [ T ] , compare : & mut F )
1359
- where F : FnMut ( & T , & T ) -> Ordering
1358
+ fn insert_head < T , F > ( v : & mut [ T ] , is_less : & mut F )
1359
+ where F : FnMut ( & T , & T ) -> bool
1360
1360
{
1361
- if v. len ( ) >= 2 && compare ( & v[ 0 ] , & v[ 1 ] ) == Greater {
1361
+ if v. len ( ) >= 2 && is_less ( & v[ 1 ] , & v[ 0 ] ) {
1362
1362
unsafe {
1363
1363
// There are three ways to implement insertion here:
1364
1364
//
@@ -1381,12 +1381,12 @@ fn insert_head<T, F>(v: &mut [T], compare: &mut F)
1381
1381
1382
1382
// Intermediate state of the insertion process is always tracked by `hole`, which
1383
1383
// serves two purposes:
1384
- // 1. Protects integrity of `v` from panics in `compare `.
1384
+ // 1. Protects integrity of `v` from panics in `is_less `.
1385
1385
// 2. Fills the remaining hole in `v` in the end.
1386
1386
//
1387
1387
// Panic safety:
1388
1388
//
1389
- // If `compare ` panics at any point during the process, `hole` will get dropped and
1389
+ // If `is_less ` panics at any point during the process, `hole` will get dropped and
1390
1390
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
1391
1391
// initially held exactly once.
1392
1392
let mut hole = InsertionHole {
@@ -1396,7 +1396,7 @@ fn insert_head<T, F>(v: &mut [T], compare: &mut F)
1396
1396
ptr:: copy_nonoverlapping ( & v[ 1 ] , & mut v[ 0 ] , 1 ) ;
1397
1397
1398
1398
for i in 2 ..v. len ( ) {
1399
- if compare ( & tmp . value , & v[ i] ) != Greater {
1399
+ if ! is_less ( & v[ i] , & tmp . value ) {
1400
1400
break ;
1401
1401
}
1402
1402
ptr:: copy_nonoverlapping ( & v[ i] , & mut v[ i - 1 ] , 1 ) ;
@@ -1432,8 +1432,8 @@ fn insert_head<T, F>(v: &mut [T], compare: &mut F)
1432
1432
///
1433
1433
/// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough
1434
1434
/// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type.
1435
- unsafe fn merge < T , F > ( v : & mut [ T ] , mid : usize , buf : * mut T , compare : & mut F )
1436
- where F : FnMut ( & T , & T ) -> Ordering
1435
+ unsafe fn merge < T , F > ( v : & mut [ T ] , mid : usize , buf : * mut T , is_less : & mut F )
1436
+ where F : FnMut ( & T , & T ) -> bool
1437
1437
{
1438
1438
let len = v. len ( ) ;
1439
1439
let v = v. as_mut_ptr ( ) ;
@@ -1449,12 +1449,12 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
1449
1449
// hole in `v`.
1450
1450
//
1451
1451
// Intermediate state of the process is always tracked by `hole`, which serves two purposes:
1452
- // 1. Protects integrity of `v` from panics in `compare `.
1452
+ // 1. Protects integrity of `v` from panics in `is_less `.
1453
1453
// 2. Fills the remaining hole in `v` if the longer run gets consumed first.
1454
1454
//
1455
1455
// Panic safety:
1456
1456
//
1457
- // If `compare ` panics at any point during the process, `hole` will get dropped and fill the
1457
+ // If `is_less ` panics at any point during the process, `hole` will get dropped and fill the
1458
1458
// hole in `v` with the unconsumed range in `buf`, thus ensuring that `v` still holds every
1459
1459
// object it initially held exactly once.
1460
1460
let mut hole;
@@ -1476,7 +1476,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
1476
1476
while * left < hole. end && right < v_end {
1477
1477
// Consume the lesser side.
1478
1478
// If equal, prefer the left run to maintain stability.
1479
- let to_copy = if compare ( & * * left , & * right ) == Greater {
1479
+ let to_copy = if is_less ( & * right , & * * left ) {
1480
1480
get_and_increment ( & mut right)
1481
1481
} else {
1482
1482
get_and_increment ( left)
@@ -1500,7 +1500,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
1500
1500
while v < * left && buf < * right {
1501
1501
// Consume the greater side.
1502
1502
// If equal, prefer the right run to maintain stability.
1503
- let to_copy = if compare ( & * left . offset ( -1 ) , & * right . offset ( -1 ) ) == Greater {
1503
+ let to_copy = if is_less ( & * right . offset ( -1 ) , & * left . offset ( -1 ) ) {
1504
1504
decrement_and_get ( left)
1505
1505
} else {
1506
1506
decrement_and_get ( right)
@@ -1550,8 +1550,8 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F)
1550
1550
/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len`
1551
1551
///
1552
1552
/// The invariants ensure that the total running time is `O(n log n)` worst-case.
1553
- fn merge_sort < T , F > ( v : & mut [ T ] , mut compare : F )
1554
- where F : FnMut ( & T , & T ) -> Ordering
1553
+ fn merge_sort < T , F > ( v : & mut [ T ] , mut is_less : F )
1554
+ where F : FnMut ( & T , & T ) -> bool
1555
1555
{
1556
1556
// Sorting has no meaningful behavior on zero-sized types.
1557
1557
if size_of :: < T > ( ) == 0 {
@@ -1565,7 +1565,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F)
1565
1565
//
1566
1566
// Short runs are extended using insertion sort to span at least `min_run` elements, in order
1567
1567
// to improve performance.
1568
- let ( max_insertion, min_run) = if size_of :: < T > ( ) <= 16 {
1568
+ let ( max_insertion, min_run) = if size_of :: < T > ( ) <= 2 * mem :: size_of :: < usize > ( ) {
1569
1569
( 64 , 32 )
1570
1570
} else {
1571
1571
( 32 , 16 )
@@ -1577,15 +1577,15 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F)
1577
1577
if len <= max_insertion {
1578
1578
if len >= 2 {
1579
1579
for i in ( 0 ..len-1 ) . rev ( ) {
1580
- insert_head ( & mut v[ i..] , & mut compare ) ;
1580
+ insert_head ( & mut v[ i..] , & mut is_less ) ;
1581
1581
}
1582
1582
}
1583
1583
return ;
1584
1584
}
1585
1585
1586
1586
// Allocate a buffer to use as scratch memory. We keep the length 0 so we can keep in it
1587
1587
// shallow copies of the contents of `v` without risking the dtors running on copies if
1588
- // `compare ` panics. When merging two sorted runs, this buffer holds a copy of the shorter run,
1588
+ // `is_less ` panics. When merging two sorted runs, this buffer holds a copy of the shorter run,
1589
1589
// which will always have length at most `len / 2`.
1590
1590
let mut buf = Vec :: with_capacity ( len / 2 ) ;
1591
1591
@@ -1600,14 +1600,18 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F)
1600
1600
let mut start = end - 1 ;
1601
1601
if start > 0 {
1602
1602
start -= 1 ;
1603
- if compare ( & v[ start] , & v[ start + 1 ] ) == Greater {
1604
- while start > 0 && compare ( & v[ start - 1 ] , & v[ start] ) == Greater {
1605
- start -= 1 ;
1606
- }
1607
- v[ start..end] . reverse ( ) ;
1608
- } else {
1609
- while start > 0 && compare ( & v[ start - 1 ] , & v[ start] ) != Greater {
1610
- start -= 1 ;
1603
+ unsafe {
1604
+ if is_less ( v. get_unchecked ( start + 1 ) , v. get_unchecked ( start) ) {
1605
+ while start > 0 && is_less ( v. get_unchecked ( start) ,
1606
+ v. get_unchecked ( start - 1 ) ) {
1607
+ start -= 1 ;
1608
+ }
1609
+ v[ start..end] . reverse ( ) ;
1610
+ } else {
1611
+ while start > 0 && !is_less ( v. get_unchecked ( start) ,
1612
+ v. get_unchecked ( start - 1 ) ) {
1613
+ start -= 1 ;
1614
+ }
1611
1615
}
1612
1616
}
1613
1617
}
@@ -1616,7 +1620,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F)
1616
1620
// merge sort on short sequences, so this significantly improves performance.
1617
1621
while start > 0 && end - start < min_run {
1618
1622
start -= 1 ;
1619
- insert_head ( & mut v[ start..end] , & mut compare ) ;
1623
+ insert_head ( & mut v[ start..end] , & mut is_less ) ;
1620
1624
}
1621
1625
1622
1626
// Push this run onto the stack.
@@ -1632,7 +1636,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F)
1632
1636
let right = runs[ r] ;
1633
1637
unsafe {
1634
1638
merge ( & mut v[ left. start .. right. start + right. len ] , left. len , buf. as_mut_ptr ( ) ,
1635
- & mut compare ) ;
1639
+ & mut is_less ) ;
1636
1640
}
1637
1641
runs[ r] = Run {
1638
1642
start : left. start ,
0 commit comments