github.com/theQRL/go-zond@v0.1.1/crypto/bn256/cloudflare/gfp_generic.go (about) 1 //go:build (!amd64 && !arm64) || generic 2 // +build !amd64,!arm64 generic 3 4 package bn256 5 6 func gfpCarry(a *gfP, head uint64) { 7 b := &gfP{} 8 9 var carry uint64 10 for i, pi := range p2 { 11 ai := a[i] 12 bi := ai - pi - carry 13 b[i] = bi 14 carry = (pi&^ai | (pi|^ai)&bi) >> 63 15 } 16 carry = carry &^ head 17 18 // If b is negative, then return a. 19 // Else return b. 20 carry = -carry 21 ncarry := ^carry 22 for i := 0; i < 4; i++ { 23 a[i] = (a[i] & carry) | (b[i] & ncarry) 24 } 25 } 26 27 func gfpNeg(c, a *gfP) { 28 var carry uint64 29 for i, pi := range p2 { 30 ai := a[i] 31 ci := pi - ai - carry 32 c[i] = ci 33 carry = (ai&^pi | (ai|^pi)&ci) >> 63 34 } 35 gfpCarry(c, 0) 36 } 37 38 func gfpAdd(c, a, b *gfP) { 39 var carry uint64 40 for i, ai := range a { 41 bi := b[i] 42 ci := ai + bi + carry 43 c[i] = ci 44 carry = (ai&bi | (ai|bi)&^ci) >> 63 45 } 46 gfpCarry(c, carry) 47 } 48 49 func gfpSub(c, a, b *gfP) { 50 t := &gfP{} 51 52 var carry uint64 53 for i, pi := range p2 { 54 bi := b[i] 55 ti := pi - bi - carry 56 t[i] = ti 57 carry = (bi&^pi | (bi|^pi)&ti) >> 63 58 } 59 60 carry = 0 61 for i, ai := range a { 62 ti := t[i] 63 ci := ai + ti + carry 64 c[i] = ci 65 carry = (ai&ti | (ai|ti)&^ci) >> 63 66 } 67 gfpCarry(c, carry) 68 } 69 70 func mul(a, b [4]uint64) [8]uint64 { 71 const ( 72 mask16 uint64 = 0x0000ffff 73 mask32 uint64 = 0xffffffff 74 ) 75 76 var buff [32]uint64 77 for i, ai := range a { 78 a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 79 80 for j, bj := range b { 81 b0, b2 := bj&mask32, bj>>32 82 83 off := 4 * (i + j) 84 buff[off+0] += a0 * b0 85 buff[off+1] += a1 * b0 86 buff[off+2] += a2*b0 + a0*b2 87 buff[off+3] += a3*b0 + a1*b2 88 buff[off+4] += a2 * b2 89 buff[off+5] += a3 * b2 90 } 91 } 92 93 for i := uint(1); i < 4; i++ { 94 shift := 16 * i 95 96 var head, carry uint64 97 for j := uint(0); j < 8; j++ { 98 block := 4 * j 99 100 xi := buff[block] 101 yi := (buff[block+i] << shift) + head 102 zi := xi + yi + carry 103 buff[block] = zi 104 carry = (xi&yi | (xi|yi)&^zi) >> 63 105 106 head = buff[block+i] >> (64 - shift) 107 } 108 } 109 110 return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]} 111 } 112 113 func halfMul(a, b [4]uint64) [4]uint64 { 114 const ( 115 mask16 uint64 = 0x0000ffff 116 mask32 uint64 = 0xffffffff 117 ) 118 119 var buff [18]uint64 120 for i, ai := range a { 121 a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 122 123 for j, bj := range b { 124 if i+j > 3 { 125 break 126 } 127 b0, b2 := bj&mask32, bj>>32 128 129 off := 4 * (i + j) 130 buff[off+0] += a0 * b0 131 buff[off+1] += a1 * b0 132 buff[off+2] += a2*b0 + a0*b2 133 buff[off+3] += a3*b0 + a1*b2 134 buff[off+4] += a2 * b2 135 buff[off+5] += a3 * b2 136 } 137 } 138 139 for i := uint(1); i < 4; i++ { 140 shift := 16 * i 141 142 var head, carry uint64 143 for j := uint(0); j < 4; j++ { 144 block := 4 * j 145 146 xi := buff[block] 147 yi := (buff[block+i] << shift) + head 148 zi := xi + yi + carry 149 buff[block] = zi 150 carry = (xi&yi | (xi|yi)&^zi) >> 63 151 152 head = buff[block+i] >> (64 - shift) 153 } 154 } 155 156 return [4]uint64{buff[0], buff[4], buff[8], buff[12]} 157 } 158 159 func gfpMul(c, a, b *gfP) { 160 T := mul(*a, *b) 161 m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np) 162 t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2) 163 164 var carry uint64 165 for i, Ti := range T { 166 ti := t[i] 167 zi := Ti + ti + carry 168 T[i] = zi 169 carry = (Ti&ti | (Ti|ti)&^zi) >> 63 170 } 171 172 *c = gfP{T[4], T[5], T[6], T[7]} 173 gfpCarry(c, carry) 174 }