diff options
| author | Alberto Donizetti <alb.donizetti@gmail.com> | 2019-09-28 19:02:15 +0200 |
|---|---|---|
| committer | Alberto Donizetti <alb.donizetti@gmail.com> | 2019-10-18 13:47:36 +0000 |
| commit | 57c63e0fb2ec624f97153bcef8c0d014fe1653be (patch) | |
| tree | da3d1a7e1012ef98bee98a52f1c780a1808a9f61 /src/math/bits/bits.go | |
| parent | 584ef455ac0cd08833c3d4c7f6cb284bdba627a0 (diff) | |
| download | go-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.go | 31 |
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 +} |
