// 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.
// 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
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))
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
import (
. "math/bits"
+ "runtime"
"testing"
"unsafe"
)
}
}
+const (
+ divZeroError = "runtime error: integer divide by zero"
+ overflowError = "runtime error: integer overflow"
+)
+
+func TestDivPanicOverflow(t *testing.T) {
+ // Expect a panic
+ defer func() {
+ if err := recover(); err == nil {
+ t.Error("Div should have panicked when y<=hi")
+ } else if e, ok := err.(runtime.Error); !ok || e.Error() != overflowError {
+ t.Errorf("Div expected panic: %q, got: %q ", overflowError, e.Error())
+ }
+ }()
+ q, r := Div(1, 0, 1)
+ t.Errorf("undefined q, r = %v, %v calculated when Div should have panicked", q, r)
+}
+
+func TestDiv32PanicOverflow(t *testing.T) {
+ // Expect a panic
+ defer func() {
+ if err := recover(); err == nil {
+ t.Error("Div32 should have panicked when y<=hi")
+ } else if e, ok := err.(runtime.Error); !ok || e.Error() != overflowError {
+ t.Errorf("Div32 expected panic: %q, got: %q ", overflowError, e.Error())
+ }
+ }()
+ q, r := Div32(1, 0, 1)
+ t.Errorf("undefined q, r = %v, %v calculated when Div32 should have panicked", q, r)
+}
+
+func TestDiv64PanicOverflow(t *testing.T) {
+ // Expect a panic
+ defer func() {
+ if err := recover(); err == nil {
+ t.Error("Div64 should have panicked when y<=hi")
+ } else if e, ok := err.(runtime.Error); !ok || e.Error() != overflowError {
+ t.Errorf("Div64 expected panic: %q, got: %q ", overflowError, e.Error())
+ }
+ }()
+ q, r := Div64(1, 0, 1)
+ t.Errorf("undefined q, r = %v, %v calculated when Div64 should have panicked", q, r)
+}
+
+func TestDivPanicZero(t *testing.T) {
+ // Expect a panic
+ defer func() {
+ if err := recover(); err == nil {
+ t.Error("Div should have panicked when y==0")
+ } else if e, ok := err.(runtime.Error); !ok || e.Error() != divZeroError {
+ t.Errorf("Div expected panic: %q, got: %q ", divZeroError, e.Error())
+ }
+ }()
+ q, r := Div(1, 1, 0)
+ t.Errorf("undefined q, r = %v, %v calculated when Div should have panicked", q, r)
+}
+
+func TestDiv32PanicZero(t *testing.T) {
+ // Expect a panic
+ defer func() {
+ if err := recover(); err == nil {
+ t.Error("Div32 should have panicked when y==0")
+ } else if e, ok := err.(runtime.Error); !ok || e.Error() != divZeroError {
+ t.Errorf("Div32 expected panic: %q, got: %q ", divZeroError, e.Error())
+ }
+ }()
+ q, r := Div32(1, 1, 0)
+ t.Errorf("undefined q, r = %v, %v calculated when Div32 should have panicked", q, r)
+}
+
+func TestDiv64PanicZero(t *testing.T) {
+ // Expect a panic
+ defer func() {
+ if err := recover(); err == nil {
+ t.Error("Div64 should have panicked when y==0")
+ } else if e, ok := err.(runtime.Error); !ok || e.Error() != divZeroError {
+ t.Errorf("Div64 expected panic: %q, got: %q ", divZeroError, e.Error())
+ }
+ }()
+ q, r := Div64(1, 1, 0)
+ t.Errorf("undefined q, r = %v, %v calculated when Div64 should have panicked", q, r)
+}
+
func BenchmarkAdd(b *testing.B) {
var z, c uint
for i := 0; i < b.N; i++ {