Skip to content

Commit 7aa251c

Browse files
committed
Improve slice::binary_search_by
1 parent 4bc39f0 commit 7aa251c

File tree

1 file changed

+14
-12
lines changed

1 file changed

+14
-12
lines changed

library/core/src/slice/mod.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -2788,13 +2788,12 @@ impl<T> [T] {
27882788
F: FnMut(&'a T) -> Ordering,
27892789
{
27902790
// INVARIANTS:
2791-
// - 0 <= left <= left + size = right <= self.len()
2791+
// - 0 <= left <= left + size <= self.len()
27922792
// - f returns Less for everything in self[..left]
2793-
// - f returns Greater for everything in self[right..]
2793+
// - f returns Greater for everything in self[left + size..]
27942794
let mut size = self.len();
27952795
let mut left = 0;
2796-
let mut right = size;
2797-
while left < right {
2796+
while size > 1 {
27982797
let mid = left + size / 2;
27992798

28002799
// SAFETY: the while condition means `size` is strictly positive, so
@@ -2807,21 +2806,24 @@ impl<T> [T] {
28072806
// fewer branches and instructions than if/else or matching on
28082807
// cmp::Ordering.
28092808
// This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx.
2810-
left = if cmp == Less { mid + 1 } else { left };
2811-
right = if cmp == Greater { mid } else { right };
2809+
2810+
left = if cmp == Less { mid } else { left };
2811+
size = if cmp == Greater { size / 2 } else { size - size / 2 };
28122812
if cmp == Equal {
28132813
// SAFETY: same as the `get_unchecked` above
28142814
unsafe { hint::assert_unchecked(mid < self.len()) };
28152815
return Ok(mid);
28162816
}
2817-
2818-
size = right - left;
28192817
}
28202818

2821-
// SAFETY: directly true from the overall invariant.
2822-
// Note that this is `<=`, unlike the assume in the `Ok` path.
2823-
unsafe { hint::assert_unchecked(left <= self.len()) };
2824-
Err(left)
2819+
if size == 0 {
2820+
Err(left)
2821+
} else {
2822+
// SAFETY: allowed per the invariants
2823+
let cmp = f(unsafe { self.get_unchecked(left) });
2824+
let res_idx = if cmp == Less { left + 1 } else { left };
2825+
if cmp == Equal { Ok(res_idx) } else { Err(res_idx) }
2826+
}
28252827
}
28262828

28272829
/// Binary searches this slice with a key extraction function.

0 commit comments

Comments
 (0)