diff options
| author | Brian Kessler <brian.m.kessler@gmail.com> | 2018-10-23 20:20:44 -0600 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2018-11-27 05:04:14 +0000 |
| commit | ead5d1e316873a63471de31f3d70f97aeb7969f5 (patch) | |
| tree | 15fa27f2ec6ebf0f70af9451117e4f3ab551756d /src/math/bits/bits.go | |
| parent | eb6c433eb38d9a0e9ecfcc1604f9ff8e035768f6 (diff) | |
| download | go-ead5d1e316873a63471de31f3d70f97aeb7969f5.tar.xz | |
math/bits: panic when y<=hi in Div
Explicitly check for divide-by-zero/overflow and panic with the appropriate
runtime error. The additional checks have basically no effect on performance
since the branch is easily predicted.
name old time/op new time/op delta
Div-4 53.9ns ± 1% 53.0ns ± 1% -1.59% (p=0.016 n=4+5)
Div32-4 17.9ns ± 0% 18.4ns ± 0% +2.56% (p=0.008 n=5+5)
Div64-4 53.5ns ± 0% 53.3ns ± 0% ~ (p=0.095 n=5+5)
Updates #28316
Change-Id: I36297ee9946cbbc57fefb44d1730283b049ecf57
Reviewed-on: https://go-review.googlesource.com/c/144377
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/math/bits/bits.go')
| -rw-r--r-- | src/math/bits/bits.go | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/math/bits/bits.go b/src/math/bits/bits.go index 58cf52d2a7..fbf4966157 100644 --- a/src/math/bits/bits.go +++ b/src/math/bits/bits.go @@ -8,6 +8,8 @@ // functions for the predeclared unsigned integer types. package bits +import _ "unsafe" // for go:linkname + const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64 // UintSize is the size of a uint in bits. @@ -469,6 +471,9 @@ func Div(hi, lo, y uint) (quo, rem uint) { // hi must be < y otherwise the behavior is undefined (the quotient // won't fit into quo). func Div32(hi, lo, y uint32) (quo, rem uint32) { + if y != 0 && y <= hi { + panic(overflowError) + } z := uint64(hi)<<32 | uint64(lo) quo, rem = uint32(z/uint64(y)), uint32(z%uint64(y)) return @@ -484,8 +489,11 @@ func Div64(hi, lo, y uint64) (quo, rem uint64) { two32 = 1 << 32 mask32 = two32 - 1 ) - if hi >= y { - return 1<<64 - 1, 1<<64 - 1 + if y == 0 { + panic(divideError) + } + if y <= hi { + panic(overflowError) } s := uint(LeadingZeros64(y)) @@ -522,3 +530,9 @@ func Div64(hi, lo, y uint64) (quo, rem uint64) { return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s } + +//go:linkname overflowError runtime.overflowError +var overflowError error + +//go:linkname divideError runtime.divideError +var divideError error |
