Skip to content

Commit 514601a

Browse files
authored
fix constant divisions (#89)
Constant divisions were optimised using multiplications, but the result was sometimes off in the least significant digit. Reverting to a slower but more precise algo. Also fix a bug in divrem64, which checked the wrong input for lo == 0. This was previously benign, since the input and output arguments were always the same variable.
1 parent 713e426 commit 514601a

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

uint128.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (a *uint128T) sub(x, y *uint128T) *uint128T {
6060

6161
func (a *uint128T) divrem64(x *uint128T, d uint64) uint64 {
6262
var r uint64
63-
if a.hi == 0 {
63+
if x.hi == 0 {
6464
a.lo, r = x.lo/d, x.lo%d
6565
} else {
6666
a.hi, r = bits.Div64(0, x.hi, d)
@@ -70,10 +70,16 @@ func (a *uint128T) divrem64(x *uint128T, d uint64) uint64 {
7070
}
7171

7272
// divbase divides a by [decimal64Base].
73-
func (a *uint128T) divbase(x *uint128T) *uint128T { return a.divc(x, 113, 0x901d7cf73ab0acd9) }
73+
func (a *uint128T) divbase(x *uint128T) *uint128T {
74+
a.divrem64(x, decimal64Base)
75+
return a
76+
}
7477

7578
// div10base divides a by 10*[decimal64Base].
76-
func (a *uint128T) div10base(x *uint128T) *uint128T { return a.divc(x, 117, 0xe69594bec44de15b) }
79+
func (a *uint128T) div10base(x *uint128T) *uint128T {
80+
a.divrem64(x, 10*decimal64Base)
81+
return a
82+
}
7783

7884
// divc divides a by n where 1<<po2/rdenom ~ n and po2 is chosen such that rdenom is the largest possible value < 1<<64.
7985
func (a *uint128T) divc(x *uint128T, po2 int, rdenom uint64) *uint128T {

0 commit comments

Comments
 (0)