123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- // +build !amd64,!arm64 generic
- package bn256
- 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)
- }
- }
- 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
- }
- gfpCarry(c, 0)
- }
- 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{}
- 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
- }
- 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)
- }
- func mul(a, b [4]uint64) [8]uint64 {
- const (
- mask16 uint64 = 0x0000ffff
- mask32 uint64 = 0xffffffff
- )
- 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 {
- 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 < 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]}
- }
- 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]}
- }
- func gfpMul(c, a, b *gfP) {
- T := mul(*a, *b)
- m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np)
- t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2)
- 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]}
- gfpCarry(c, carry)
- }
|