Skip to content

Commit 7d078cf

Browse files
committed
Simplify binary search logic to full branch code to let CPU guessing branch more precisely
1 parent 18e44a1 commit 7d078cf

File tree

2 files changed

+17
-22
lines changed

2 files changed

+17
-22
lines changed

library/core/src/slice/mod.rs

+16-21
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
#![stable(feature = "rust1", since = "1.0.0")]
1010

11-
use crate::cmp::Ordering::{self, Equal, Greater, Less};
11+
use crate::cmp::Ordering::{self, Greater, Less};
1212
use crate::marker::Copy;
1313
use crate::mem;
1414
use crate::num::NonZeroUsize;
@@ -2154,29 +2154,24 @@ impl<T> [T] {
21542154
where
21552155
F: FnMut(&'a T) -> Ordering,
21562156
{
2157-
let s = self;
2158-
let mut size = s.len();
2159-
if size == 0 {
2160-
return Err(0);
2161-
}
2162-
let mut base = 0usize;
2163-
while size > 1 {
2164-
let half = size / 2;
2165-
let mid = base + half;
2166-
// SAFETY: the call is made safe by the following inconstants:
2167-
// - `mid >= 0`: by definition
2168-
// - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...`
2169-
let cmp = f(unsafe { s.get_unchecked(mid) });
2170-
if cmp == Equal {
2157+
let mut left = 0;
2158+
let mut right = self.len();
2159+
while left < right {
2160+
// never overflow because `slice::len()` max is `isize::MAX`.
2161+
let mid = (left + right) / 2;
2162+
// SAFETY: the call is made safe by the following invariants:
2163+
// - `mid >= 0`
2164+
// - `mid < size`: `mid` is limited by `[left; right)` bound.
2165+
let cmp = f(unsafe { self.get_unchecked(mid) });
2166+
if cmp == Less {
2167+
left = mid + 1;
2168+
} else if cmp == Greater {
2169+
right = mid;
2170+
} else {
21712171
return Ok(mid);
2172-
} else if cmp == Less {
2173-
base = mid
21742172
}
2175-
size -= half;
21762173
}
2177-
// SAFETY: base is always in [0, size) because base <= mid.
2178-
let cmp = f(unsafe { s.get_unchecked(base) });
2179-
if cmp == Equal { Ok(base) } else { Err(base + (cmp == Less) as usize) }
2174+
Err(left)
21802175
}
21812176

21822177
/// Binary searches this sorted slice with a key extraction function.

library/core/tests/slice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn test_binary_search_implementation_details() {
7676
assert_eq!(b.binary_search(&3), Ok(5));
7777
let b = [1, 1, 1, 1, 1, 3, 3, 3, 3];
7878
assert_eq!(b.binary_search(&1), Ok(4));
79-
assert_eq!(b.binary_search(&3), Ok(6));
79+
assert_eq!(b.binary_search(&3), Ok(7));
8080
let b = [1, 1, 1, 1, 3, 3, 3, 3, 3];
8181
assert_eq!(b.binary_search(&1), Ok(2));
8282
assert_eq!(b.binary_search(&3), Ok(4));

0 commit comments

Comments
 (0)