@@ -2887,36 +2887,28 @@ impl<T> [T] {
28872887 }
28882888 let mut base = 0usize ;
28892889
2890- // This loop intentionally doesn't have an early exit if the comparison
2891- // returns Equal. We want the number of loop iterations to depend *only*
2892- // on the size of the input slice so that the CPU can reliably predict
2893- // the loop count.
28942890 while size > 1 {
2895- let half = size / 2 ;
2896- let mid = base + half ;
2891+ size >>= 1 ;
2892+ let mid = base + size ;
28972893
2898- // SAFETY: the call is made safe by the following invariants:
2899- // - `mid >= 0`: by definition
2900- // - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...`
2894+ // SAFETY: `mid < self.len()`:
2895+ // mid = self.len() / 2 + self.len() / 4 + self.len() / 8 ...
29012896 let cmp = f ( unsafe { self . get_unchecked ( mid) } ) ;
29022897
2903- // Binary search interacts poorly with branch prediction, so force
2904- // the compiler to use conditional moves if supported by the target
2905- // architecture.
2906- base = hint:: select_unpredictable ( cmp == Greater , base, mid) ;
2907-
2908- // This is imprecise in the case where `size` is odd and the
2909- // comparison returns Greater: the mid element still gets included
2910- // by `size` even though it's known to be larger than the element
2911- // being searched for.
2912- //
2913- // This is fine though: we gain more performance by keeping the
2914- // loop iteration count invariant (and thus predictable) than we
2915- // lose from considering one additional element.
2916- size -= half;
2898+ if cmp == Equal {
2899+ // SAFETY: same as the `get_unchecked` above.
2900+ unsafe { hint:: assert_unchecked ( mid < self . len ( ) ) } ;
2901+ return Ok ( mid) ;
2902+ }
2903+ base = hint:: select_unpredictable ( cmp == Less , mid + ( size & 1 ) , base) ;
2904+ }
2905+
2906+ // when always `Less` (base = mid + 1)
2907+ if base == self . len ( ) {
2908+ return Err ( base) ;
29172909 }
29182910
2919- // SAFETY: base is always in [0, size) because base <= mid.
2911+ // SAFETY: ` base < self.len()` because ` base <= mid` .
29202912 let cmp = f ( unsafe { self . get_unchecked ( base) } ) ;
29212913 if cmp == Equal {
29222914 // SAFETY: same as the `get_unchecked` above.
0 commit comments