init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+245
View File
@@ -0,0 +1,245 @@
//go:build (!amd64 && !arm64) || generic
// +build !amd64,!arm64 generic
package bn256
/*
判断进位的规则
设B=2^w, w = 64 or 32.
假设a op b = c + carry·B.
注:若carry =0 or 1, 则a + b + carry是否产生进位和carry无关。
因为若a+b+carry当carry=0不产生进位,当carry=1产生进位,当且仅当
a+b = B-1, 则a,b中必然有一个数(不妨设为a)的某个非最高比特为0,则
a'=a+carry, a'与a的最高比特相同。因此a'+b 与a+b的进位相同。因此
我们只需要考虑carry为0的情况。
# Add
carry如下:
a[w-1] 0 0 0 1 1 1
b[w-1] 0 1 1 0 0 1
c[w-1] x 0 1 0 1 x
carry 0 1 0 1 0 1
carry>0 <=> a或b都为1(第w-1bit) 或 ab其中一个为1,但c为0.
# Sub
carry如下:
a[w-1] 0 0 0 1 1 1
b[w-1] 0 0 1 0 1 1
c[w-1] 1 0 x x 0 1
carry 1 0 1 0 0 1
carry = (b&^a | (b|^a)&c) >> 63
carry>0 <=> a为0b为1 或 (a,b)!=(1,0)并且c=1.
*/
// gfpCarry compute (a, head) mod p, input (a,head) < 2p
//
// 先计算 (b,carry) = a - p
//
// carry head ret
// 0(a>p) 0 b
// 0 1 b(此情形下,(a,head) > 2p, 不应出现。此时,应再调用一次gfpCarry)
// 1(a<p) 0 a
// 1 1 b
//
// so, carry &^ head = 1, return a, otherwise return b
func gfpCarry(a *gfP, head uint64) {
b := &gfP{}
var carry uint64
for i, pi := range p2 {
ai := a[i]
bi := ai - pi - carry
b[i] = bi
carry = (pi&^ai | (pi|^ai)&bi) >> 63
}
carry = carry &^ head
// If b is negative, then return a.
// Else return b.
carry = -carry
ncarry := ^carry
for i := 0; i < 4; i++ {
a[i] = (a[i] & carry) | (b[i] & ncarry)
}
}
// gfpNeg set c = -a, input a < p
func gfpNeg(c, a *gfP) {
var carry uint64
for i, pi := range p2 {
ai := a[i]
ci := pi - ai - carry
c[i] = ci
carry = (ai&^pi | (ai|^pi)&ci) >> 63
}
// FIXME: carry?
gfpCarry(c, 0)
}
// gfpAdd set c = a+b
func gfpAdd(c, a, b *gfP) {
var carry uint64
for i, ai := range a {
bi := b[i]
ci := ai + bi + carry
c[i] = ci
carry = (ai&bi | (ai|bi)&^ci) >> 63
}
gfpCarry(c, carry)
}
func gfpSub(c, a, b *gfP) {
t := &gfP{}
// t = p-b
var carry uint64
for i, pi := range p2 {
bi := b[i]
ti := pi - bi - carry
t[i] = ti
carry = (bi&^pi | (bi|^pi)&ti) >> 63
}
// c = a+t
carry = 0
for i, ai := range a {
ti := t[i]
ci := ai + ti + carry
c[i] = ci
carry = (ai&ti | (ai|ti)&^ci) >> 63
}
gfpCarry(c, carry)
}
// mul returns the multiplication of a*b. a,b are no restrictions.
func mul(a, b [4]uint64) [8]uint64 {
const (
mask16 uint64 = 0x0000ffff
mask32 uint64 = 0xffffffff
)
// Let B = 2^16, then
// buff = buff[0] + buff[1]*B + ... + buff[31]*B^31
var buff [32]uint64
for i, ai := range a {
a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
for j, bj := range b {
// compute ai * bj and save to buff[4*(i+j):]
// (a0 + a1*B + a2*B^2 + a3*B^3) * (b0 + b2*B^2)
// = a0*b0 + a1*b0*B + (a2*b0 + a0*b2)*B^2 + (a1*b2 + a3*b0)*B^3 + a2*b2*B^4 + a3*b2*B^5
b0, b2 := bj&mask32, bj>>32
off := 4 * (i + j)
buff[off+0] += a0 * b0
buff[off+1] += a1 * b0
buff[off+2] += a2*b0 + a0*b2
buff[off+3] += a3*b0 + a1*b2
buff[off+4] += a2 * b2
buff[off+5] += a3 * b2
}
}
// buff:
// 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15
// 外循环对将1,2,3加到0上
// 内循环处理0,4,8,12...
for i := uint(1); i < 4; i++ {
shift := 16 * i
var head, carry uint64
for j := uint(0); j < 8; j++ {
block := 4 * j
xi := buff[block]
yi := (buff[block+i] << shift) + head
zi := xi + yi + carry
buff[block] = zi
carry = (xi&yi | (xi|yi)&^zi) >> 63
head = buff[block+i] >> (64 - shift)
}
}
return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]}
}
// halfMul returns a*b mod R, where R = 2^256.
func halfMul(a, b [4]uint64) [4]uint64 {
const (
mask16 uint64 = 0x0000ffff
mask32 uint64 = 0xffffffff
)
var buff [18]uint64
for i, ai := range a {
a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
for j, bj := range b {
if i+j > 3 {
break
}
b0, b2 := bj&mask32, bj>>32
off := 4 * (i + j)
buff[off+0] += a0 * b0
buff[off+1] += a1 * b0
buff[off+2] += a2*b0 + a0*b2
buff[off+3] += a3*b0 + a1*b2
buff[off+4] += a2 * b2
buff[off+5] += a3 * b2
}
}
for i := uint(1); i < 4; i++ {
shift := 16 * i
var head, carry uint64
for j := uint(0); j < 4; j++ {
block := 4 * j
xi := buff[block]
yi := (buff[block+i] << shift) + head
zi := xi + yi + carry
buff[block] = zi
carry = (xi&yi | (xi|yi)&^zi) >> 63
head = buff[block+i] >> (64 - shift)
}
}
return [4]uint64{buff[0], buff[4], buff[8], buff[12]}
}
// gfpMul implements the Montgomery multiplication of a*b, i.e.,
// c = a*b*R^{-1} mod p
//
// Let T = a*b = T_h*R + T_l, then
//
// a*b = T_h*R + T_l
// = T_h*R + T_l + (T_l*np mod R)*P mod P
// (For np*P = -1 mod R, so T_l + (T_l*np mod R)*P = 0 mod R.)
// = higher parts of T + (T_l*np mod R)*P
func gfpMul(c, a, b *gfP) {
T := mul(*a, *b)
m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np) // m = T_l *np mod R
t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2) // t = (T_l*np mod R)*P
// (T, carry) = a*b and (c, carry) = a*b/R
// T[0:4] must be 0.
var carry uint64
for i, Ti := range T {
ti := t[i]
zi := Ti + ti + carry
T[i] = zi
carry = (Ti&ti | (Ti|ti)&^zi) >> 63
}
*c = gfP{T[4], T[5], T[6], T[7]}
// TODO: can c >= p?
gfpCarry(c, carry)
}