Skip to content

Commit 47d125d

Browse files
committed
Auto merge of #28436 - ranma42:faster-partialord, r=bluss
This branch improves the performance of Ord and PartialOrd methods for slices compared to the iter-based implementation. Based on the approach used in #26884.
2 parents f18c2aa + 74dc146 commit 47d125d

File tree

2 files changed

+50
-23
lines changed

2 files changed

+50
-23
lines changed

src/libcore/cmp.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -463,17 +463,33 @@ mod impls {
463463
}
464464
}
465465

466-
partial_ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
466+
partial_ord_impl! { f32 f64 }
467467

468468
macro_rules! ord_impl {
469469
($($t:ty)*) => ($(
470+
#[stable(feature = "rust1", since = "1.0.0")]
471+
impl PartialOrd for $t {
472+
#[inline]
473+
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
474+
Some(self.cmp(other))
475+
}
476+
#[inline]
477+
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
478+
#[inline]
479+
fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
480+
#[inline]
481+
fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
482+
#[inline]
483+
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
484+
}
485+
470486
#[stable(feature = "rust1", since = "1.0.0")]
471487
impl Ord for $t {
472488
#[inline]
473489
fn cmp(&self, other: &$t) -> Ordering {
474-
if *self < *other { Less }
475-
else if *self > *other { Greater }
476-
else { Equal }
490+
if *self == *other { Equal }
491+
else if *self < *other { Less }
492+
else { Greater }
477493
}
478494
}
479495
)*)

src/libcore/slice.rs

+30-19
Original file line numberDiff line numberDiff line change
@@ -1559,30 +1559,41 @@ impl<T: Eq> Eq for [T] {}
15591559
#[stable(feature = "rust1", since = "1.0.0")]
15601560
impl<T: Ord> Ord for [T] {
15611561
fn cmp(&self, other: &[T]) -> Ordering {
1562-
self.iter().cmp(other.iter())
1562+
let l = cmp::min(self.len(), other.len());
1563+
1564+
// Slice to the loop iteration range to enable bound check
1565+
// elimination in the compiler
1566+
let lhs = &self[..l];
1567+
let rhs = &other[..l];
1568+
1569+
for i in 0..l {
1570+
match lhs[i].cmp(&rhs[i]) {
1571+
Ordering::Equal => (),
1572+
non_eq => return non_eq,
1573+
}
1574+
}
1575+
1576+
self.len().cmp(&other.len())
15631577
}
15641578
}
15651579

15661580
#[stable(feature = "rust1", since = "1.0.0")]
15671581
impl<T: PartialOrd> PartialOrd for [T] {
1568-
#[inline]
15691582
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
1570-
self.iter().partial_cmp(other.iter())
1571-
}
1572-
#[inline]
1573-
fn lt(&self, other: &[T]) -> bool {
1574-
self.iter().lt(other.iter())
1575-
}
1576-
#[inline]
1577-
fn le(&self, other: &[T]) -> bool {
1578-
self.iter().le(other.iter())
1579-
}
1580-
#[inline]
1581-
fn ge(&self, other: &[T]) -> bool {
1582-
self.iter().ge(other.iter())
1583-
}
1584-
#[inline]
1585-
fn gt(&self, other: &[T]) -> bool {
1586-
self.iter().gt(other.iter())
1583+
let l = cmp::min(self.len(), other.len());
1584+
1585+
// Slice to the loop iteration range to enable bound check
1586+
// elimination in the compiler
1587+
let lhs = &self[..l];
1588+
let rhs = &other[..l];
1589+
1590+
for i in 0..l {
1591+
match lhs[i].partial_cmp(&rhs[i]) {
1592+
Some(Ordering::Equal) => (),
1593+
non_eq => return non_eq,
1594+
}
1595+
}
1596+
1597+
self.len().partial_cmp(&other.len())
15871598
}
15881599
}

0 commit comments

Comments
 (0)