Skip to content

Commit 57ab800

Browse files
cleanup of mul64
1 parent ea00ed6 commit 57ab800

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

  • compiler/natives/src/math/bits

compiler/natives/src/math/bits/bits.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,50 @@ func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) {
238238
}
239239
return
240240
}
241+
242+
//gopherjs:replace
243+
func Mul64(x, y uint64) (uint64, uint64) {
244+
const (
245+
bit32 = 1 << 32
246+
bit16 = 1 << 16
247+
mask16 = bit16 - 1
248+
)
249+
// Get the 16-bits parts so that multiplication keeps under 32-bits.
250+
xLo := js.Uint64Low(x)
251+
x0 := xLo & mask16
252+
x1 := xLo >> 16
253+
xHi := js.Uint64High(x)
254+
x2 := xHi & mask16
255+
x3 := xHi >> 16
256+
yLo := js.Uint64Low(y)
257+
y0 := yLo & mask16
258+
y1 := yLo >> 16
259+
yHi := js.Uint64High(y)
260+
y2 := yHi & mask16
261+
y3 := yHi >> 16
262+
// Columns of the 128-bit product, identified by their bit offset.
263+
// Each c<k> holds the still-unreduced sum for bits k..k+16 and is at
264+
// most 2^32 - 2^16 (fits in uint32) before we shift the carry on.
265+
c0 := x0 * y0
266+
c16 := c0 >> 16
267+
c0 &= mask16
268+
c16 += x1 * y0
269+
c32 := c16 >> 16
270+
c16 &= mask16
271+
c16 += x0 * y1
272+
c32 += c16 >> 16
273+
c16 &= mask16
274+
// Pack the low 32 bits of the product.
275+
loLo := c16<<16 | c0
276+
// The remaining 96 bits are computed in float64. Max value of any
277+
// `cN` partial sum is 4*(2^32-1) + small carries ≈ 2^34, exact in
278+
// float64. js.MakeUint64 handles low->high carry on each output.
279+
mid := float64(c32) + float64(x2*y0) + float64(x1*y1) + float64(x0*y2)
280+
// Carry out of `mid` into bit 64
281+
midCarry := uint32(mid / bit32)
282+
hiLo := float64(midCarry) + float64(x3*y0) + float64(x2*y1) + float64(x1*y2) + float64(x0*y3)
283+
hiHi := float64(x3*y1+x2*y2+x1*y3) + // bits 64..96-ish, all 16x16
284+
bit16*float64(x3*y2+x2*y3) + // bits 80..96 contribute >>16 of these into bits 96+
285+
bit32*float64(x3*y3) // bits 96..128
286+
return js.MakeUint64(hiHi, hiLo), js.MakeUint64(mid, float64(loLo))
287+
}

0 commit comments

Comments
 (0)