Commit fd37b8cc authored by David R. Jenni's avatar David R. Jenni Committed by Robert Griesemer

sort: optimize average calculation in binary search

Use fewer instructions to calculate the average of i and j without
overflowing at the addition.

Even if both i and j are math.MaxInt{32,64}, the sum fits into a
uint{32,64}. Because the sum of i and j is always ≥ 0, the right
shift by one does the same as a division by two. The result of the
shift operation is at most math.MaxInt{32,64} and fits again into
an int{32,64}.

name              old time/op  new time/op  delta
SearchWrappers-4   153ns ± 3%   143ns ± 6%  -6.33%  (p=0.000 n=90+100)

This calculation is documented in:
https://research.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html

Change-Id: I2be7922afc03b3617fce32e59364606c37a83678
Reviewed-on: https://go-review.googlesource.com/36332Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 91ad2a21
...@@ -61,7 +61,7 @@ func Search(n int, f func(int) bool) int { ...@@ -61,7 +61,7 @@ func Search(n int, f func(int) bool) int {
// Invariant: f(i-1) == false, f(j) == true. // Invariant: f(i-1) == false, f(j) == true.
i, j := 0, n i, j := 0, n
for i < j { for i < j {
h := i + (j-i)/2 // avoid overflow when computing h h := int(uint(i+j) >> 1) // avoid overflow when computing h
// i ≤ h < j // i ≤ h < j
if !f(h) { if !f(h) {
i = h + 1 // preserves f(i-1) == false i = h + 1 // preserves f(i-1) == false
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment