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