Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e4a10ae

Browse filesBrowse files
committed
Improve slice::binary_search_by
1 parent 4bc39f0 commit e4a10ae
Copy full SHA for e4a10ae

File tree

2 files changed

+15
-13
lines changed
Filter options

2 files changed

+15
-13
lines changed

‎library/core/src/slice/mod.rs

Copy file name to clipboardExpand all lines: library/core/src/slice/mod.rs
+14-12Lines changed: 14 additions & 12 deletions
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.

‎library/core/tests/slice.rs

Copy file name to clipboardExpand all lines: library/core/tests/slice.rs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ fn test_binary_search_implementation_details() {
9090
assert_eq!(b.binary_search(&3), Ok(5));
9191
let b = [1, 1, 1, 1, 1, 3, 3, 3, 3];
9292
assert_eq!(b.binary_search(&1), Ok(4));
93-
assert_eq!(b.binary_search(&3), Ok(7));
93+
assert_eq!(b.binary_search(&3), Ok(6));
9494
let b = [1, 1, 1, 1, 3, 3, 3, 3, 3];
9595
assert_eq!(b.binary_search(&1), Ok(2));
9696
assert_eq!(b.binary_search(&3), Ok(4));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.