Skip to content

Commit

Permalink
Improve PartialOrd for slices
Browse files Browse the repository at this point in the history
Reusing the same idea as in rust-lang#26884, we can exploit the fact that the
length of slices is known, hence we can use a counted loop instead of
iterators, which means that we only need a single counter, instead of
having to increment and check one pointer for each iterator.

Using the generic implementation of the boolean comparison operators
(`lt`, `le`, `gt`, `ge`) provides further speedup for simple
types. This happens because the loop scans elements checking for
equality and dispatches to element comparison or length comparison
depending on the result of the prefix comparison.

```
test u8_cmp          ... bench:      14,043 ns/iter (+/- 1,732)
test u8_lt           ... bench:      16,156 ns/iter (+/- 1,864)
test u8_partial_cmp  ... bench:      16,250 ns/iter (+/- 2,608)
test u16_cmp         ... bench:      15,764 ns/iter (+/- 1,420)
test u16_lt          ... bench:      19,833 ns/iter (+/- 2,826)
test u16_partial_cmp ... bench:      19,811 ns/iter (+/- 2,240)
test u32_cmp         ... bench:      15,792 ns/iter (+/- 3,409)
test u32_lt          ... bench:      18,577 ns/iter (+/- 2,075)
test u32_partial_cmp ... bench:      18,603 ns/iter (+/- 5,666)
test u64_cmp         ... bench:      16,337 ns/iter (+/- 2,511)
test u64_lt          ... bench:      18,074 ns/iter (+/- 7,914)
test u64_partial_cmp ... bench:      17,909 ns/iter (+/- 1,105)
```

```
test u8_cmp          ... bench:       6,511 ns/iter (+/- 982)
test u8_lt           ... bench:       6,671 ns/iter (+/- 919)
test u8_partial_cmp  ... bench:       7,118 ns/iter (+/- 1,623)
test u16_cmp         ... bench:       6,689 ns/iter (+/- 921)
test u16_lt          ... bench:       6,712 ns/iter (+/- 947)
test u16_partial_cmp ... bench:       6,725 ns/iter (+/- 780)
test u32_cmp         ... bench:       7,704 ns/iter (+/- 1,294)
test u32_lt          ... bench:       7,611 ns/iter (+/- 3,062)
test u32_partial_cmp ... bench:       7,640 ns/iter (+/- 1,149)
test u64_cmp         ... bench:       7,517 ns/iter (+/- 2,164)
test u64_lt          ... bench:       7,579 ns/iter (+/- 1,048)
test u64_partial_cmp ... bench:       7,629 ns/iter (+/- 1,195)
```
  • Loading branch information
ranma42 committed Sep 16, 2015
1 parent 1614173 commit d04b8b5
Showing 1 changed file with 21 additions and 18 deletions.
39 changes: 21 additions & 18 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1558,31 +1558,34 @@ impl<T: Eq> Eq for [T] {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Ord for [T] {
#[inline]
fn cmp(&self, other: &[T]) -> Ordering {
self.iter().cmp(other.iter())
let l = cmp::min(self.len(), other.len());

for i in 0..l {
match self[i].cmp(&other[i]) {
Ordering::Equal => (),
non_eq => return non_eq,
}
}

self.len().cmp(&other.len())
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd> PartialOrd for [T] {
#[inline]
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
#[inline]
fn lt(&self, other: &[T]) -> bool {
self.iter().lt(other.iter())
}
#[inline]
fn le(&self, other: &[T]) -> bool {
self.iter().le(other.iter())
}
#[inline]
fn ge(&self, other: &[T]) -> bool {
self.iter().ge(other.iter())
}
#[inline]
fn gt(&self, other: &[T]) -> bool {
self.iter().gt(other.iter())
let l = cmp::min(self.len(), other.len());

for i in 0..l {
match self[i].partial_cmp(&other[i]) {
Some(Ordering::Equal) => (),
non_eq => return non_eq,
}
}

self.len().partial_cmp(&other.len())
}
}

0 comments on commit d04b8b5

Please sign in to comment.