aboutsummaryrefslogtreecommitdiff
path: root/src/math/bits/bits.go
diff options
context:
space:
mode:
authorAlberto Donizetti <alb.donizetti@gmail.com>2019-09-28 19:02:15 +0200
committerAlberto Donizetti <alb.donizetti@gmail.com>2019-10-18 13:47:36 +0000
commit57c63e0fb2ec624f97153bcef8c0d014fe1653be (patch)
treeda3d1a7e1012ef98bee98a52f1c780a1808a9f61 /src/math/bits/bits.go
parent584ef455ac0cd08833c3d4c7f6cb284bdba627a0 (diff)
downloadgo-57c63e0fb2ec624f97153bcef8c0d014fe1653be.tar.xz
math/bits: add Rem, Rem32, Rem64
The Div functions in math/bits (Div, Div32, and Div64) compute both quotients and remainders, but they panic if the quotients do not not fit a 32/64 uint. Since, on the other hand, the remainder will always fit the size of the divisor, it is useful to have Div variants that only compute the remainder, and don't panic on a quotient overflow. This change adds to the math/bits package three new functions: Rem(hi, lo, y uint) uint Rem32(hi, lo, y uint32) uint32 Rem64(hi, lo, y uint64) uint64 which can be used to compute (hi,lo)%y even when the quotient overflows the uint size. Fixes #28970 Change-Id: I119948429f737670c5e5ceb8756121e6a738dbdc Reviewed-on: https://go-review.googlesource.com/c/go/+/197838 Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/math/bits/bits.go')
-rw-r--r--src/math/bits/bits.go31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/math/bits/bits.go b/src/math/bits/bits.go
index 385c0648e3..879ef2da54 100644
--- a/src/math/bits/bits.go
+++ b/src/math/bits/bits.go
@@ -555,3 +555,34 @@ func Div64(hi, lo, y uint64) (quo, rem uint64) {
return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s
}
+
+// Rem returns the remainder of (hi, lo) divided by y. Rem panics for
+// y == 0 (division by zero) but, unlike Div, it doesn't panic on a
+// quotient overflow.
+func Rem(hi, lo, y uint) uint {
+ if UintSize == 32 {
+ return uint(Rem32(uint32(hi), uint32(lo), uint32(y)))
+ }
+ return uint(Rem64(uint64(hi), uint64(lo), uint64(y)))
+}
+
+// Rem32 returns the remainder of (hi, lo) divided by y. Rem32 panics
+// for y == 0 (division by zero) but, unlike Div32, it doesn't panic
+// on a quotient overflow.
+func Rem32(hi, lo, y uint32) uint32 {
+ return uint32((uint64(hi)<<32 | uint64(lo)) % uint64(y))
+}
+
+// Rem64 returns the remainder of (hi, lo) divided by y. Rem64 panics
+// for y == 0 (division by zero) but, unlike Div64, it doesn't panic
+// on a quotient overflow.
+func Rem64(hi, lo, y uint64) uint64 {
+ // We scale down hi so that hi < y, then use Div64 to compute the
+ // rem with the guarantee that it won't panic on quotient overflow.
+ // Given that
+ // hi ≡ hi%y (mod y)
+ // we have
+ // hi<<64 + lo ≡ (hi%y)<<64 + lo (mod y)
+ _, rem := Div64(hi%y, lo, y)
+ return rem
+}