aboutsummaryrefslogtreecommitdiff
path: root/src/math/bits/bits.go
diff options
context:
space:
mode:
authorBrian Kessler <brian.m.kessler@gmail.com>2018-10-23 20:20:44 -0600
committerKeith Randall <khr@golang.org>2018-11-27 05:04:14 +0000
commitead5d1e316873a63471de31f3d70f97aeb7969f5 (patch)
tree15fa27f2ec6ebf0f70af9451117e4f3ab551756d /src/math/bits/bits.go
parenteb6c433eb38d9a0e9ecfcc1604f9ff8e035768f6 (diff)
downloadgo-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.go18
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