174 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			174 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								// +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)
							 | 
						||
| 
								 | 
							
								}
							 |