diff options
| author | Lukas Bergdoll <lukas.bergdoll@gmail.com> | 2023-10-25 19:37:14 +0200 |
|---|---|---|
| committer | Lukas Bergdoll <lukas.bergdoll@gmail.com> | 2023-10-25 19:37:14 +0200 |
| commit | e501add1f9addf72a30a333ec57ccb4e2ac5a8e4 (patch) | |
| tree | 6b30a8e7bb6a38b6f907504d3d8aee90cb6e817c | |
| parent | b66fe58f68d84cf422ff50c362ac5ad245cd9ce7 (diff) | |
| download | rust-e501add1f9addf72a30a333ec57ccb4e2ac5a8e4.tar.gz rust-e501add1f9addf72a30a333ec57ccb4e2ac5a8e4.zip | |
Avoid unnecessary comparison in partition_equal
The branchy Hoare partition `partition_equal` as part of `slice::sort_unstable` has a bug that makes it perform a comparison of the last element twice. Measuring inputs with a Zipfian distribution with characterizing exponent s == 1.0, yields a ~0.05% reduction in the total number of comparisons performed.
| -rw-r--r-- | library/core/src/slice/sort.rs | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index db76d26257a..993a608f42b 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -628,9 +628,14 @@ where let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot }; let pivot = &*tmp; + let len = v.len(); + if len == 0 { + return 0; + } + // Now partition the slice. let mut l = 0; - let mut r = v.len(); + let mut r = len; loop { // SAFETY: The unsafety below involves indexing an array. // For the first one: We already do the bounds checking here with `l < r`. @@ -643,8 +648,11 @@ where } // Find the last element equal to the pivot. - while l < r && is_less(pivot, v.get_unchecked(r - 1)) { + loop { r -= 1; + if l >= r || !is_less(pivot, v.get_unchecked(r)) { + break; + } } // Are we done? @@ -653,7 +661,6 @@ where } // Swap the found pair of out-of-order elements. - r -= 1; let ptr = v.as_mut_ptr(); ptr::swap(ptr.add(l), ptr.add(r)); l += 1; |
