mirror of
https://github.com/emmansun/gmsm.git
synced 2025-10-14 07:10:45 +08:00
66 lines
1.5 KiB
Go
66 lines
1.5 KiB
Go
![]() |
// Copyright 2024 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
//go:build !purego
|
||
|
|
||
|
package bigmod
|
||
|
|
||
|
import "unsafe"
|
||
|
|
||
|
// The generic implementation relies on 64x64->128 bit multiplication and
|
||
|
// 64-bit add-with-carry, which are compiler intrinsics on many architectures.
|
||
|
// Wasm doesn't support those. Here we implement it with 32x32->64 bit
|
||
|
// operations, which is more efficient on Wasm.
|
||
|
|
||
|
func idx(x *uint, i uintptr) *uint {
|
||
|
return (*uint)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + i*8))
|
||
|
}
|
||
|
|
||
|
func addMulVVWWasm(z, x *uint, y uint, n uintptr) (carry uint) {
|
||
|
const mask32 = 1<<32 - 1
|
||
|
y0 := y & mask32
|
||
|
y1 := y >> 32
|
||
|
for i := range n {
|
||
|
xi := *idx(x, i)
|
||
|
x0 := xi & mask32
|
||
|
x1 := xi >> 32
|
||
|
zi := *idx(z, i)
|
||
|
z0 := zi & mask32
|
||
|
z1 := zi >> 32
|
||
|
c0 := carry & mask32
|
||
|
c1 := carry >> 32
|
||
|
|
||
|
w00 := x0*y0 + z0 + c0
|
||
|
l00 := w00 & mask32
|
||
|
h00 := w00 >> 32
|
||
|
|
||
|
w01 := x0*y1 + z1 + h00
|
||
|
l01 := w01 & mask32
|
||
|
h01 := w01 >> 32
|
||
|
|
||
|
w10 := x1*y0 + c1 + l01
|
||
|
h10 := w10 >> 32
|
||
|
|
||
|
carry = x1*y1 + h10 + h01
|
||
|
*idx(z, i) = w10<<32 + l00
|
||
|
}
|
||
|
return carry
|
||
|
}
|
||
|
|
||
|
func addMulVVW256(z, x *uint, y uint) (c uint) {
|
||
|
return addMulVVWWasm(z, x, y, 256/_W)
|
||
|
}
|
||
|
|
||
|
func addMulVVW1024(z, x *uint, y uint) (c uint) {
|
||
|
return addMulVVWWasm(z, x, y, 1024/_W)
|
||
|
}
|
||
|
|
||
|
func addMulVVW1536(z, x *uint, y uint) (c uint) {
|
||
|
return addMulVVWWasm(z, x, y, 1536/_W)
|
||
|
}
|
||
|
|
||
|
func addMulVVW2048(z, x *uint, y uint) (c uint) {
|
||
|
return addMulVVWWasm(z, x, y, 2048/_W)
|
||
|
}
|