github.com/consensys/gnark-crypto@v0.14.0/internal/generator/tower/template/fq12over6over2/fq6.go.tmpl (about) 1 // E6 is a degree three finite field extension of fp2 2 type E6 struct { 3 B0, B1, B2 E2 4 } 5 6 // Equal returns true if z equals x, false otherwise 7 func (z *E6) Equal(x *E6) bool { 8 return z.B0.Equal(&x.B0) && z.B1.Equal(&x.B1) && z.B2.Equal(&x.B2) 9 } 10 11 // SetString sets a E6 elmt from stringf 12 func (z *E6) SetString(s1, s2, s3, s4, s5, s6 string) *E6 { 13 z.B0.SetString(s1, s2) 14 z.B1.SetString(s3, s4) 15 z.B2.SetString(s5, s6) 16 return z 17 } 18 19 // Set Sets a E6 elmt form another E6 elmt 20 func (z *E6) Set(x *E6) *E6 { 21 z.B0 = x.B0 22 z.B1 = x.B1 23 z.B2 = x.B2 24 return z 25 } 26 27 // SetOne sets z to 1 in Montgomery form and returns z 28 func (z *E6) SetOne() *E6 { 29 *z = E6{} 30 z.B0.A0.SetOne() 31 return z 32 } 33 34 // SetRandom set z to a random elmt 35 func (z *E6) SetRandom() (*E6, error) { 36 if _, err := z.B0.SetRandom(); err != nil { 37 return nil, err 38 } 39 if _, err := z.B1.SetRandom(); err != nil { 40 return nil, err 41 } 42 if _, err := z.B2.SetRandom(); err != nil { 43 return nil, err 44 } 45 return z, nil 46 } 47 48 // IsZero returns true if z is zero, false otherwise 49 func (z *E6) IsZero() bool { 50 return z.B0.IsZero() && z.B1.IsZero() && z.B2.IsZero() 51 } 52 53 // IsOne returns true if z is one, false otherwise 54 func (z *E6) IsOne() bool { 55 return z.B0.IsOne() && z.B1.IsZero() && z.B2.IsZero() 56 } 57 58 // Add adds two elements of E6 59 func (z *E6) Add(x, y *E6) *E6 { 60 z.B0.Add(&x.B0, &y.B0) 61 z.B1.Add(&x.B1, &y.B1) 62 z.B2.Add(&x.B2, &y.B2) 63 return z 64 } 65 66 // Neg negates the E6 number 67 func (z *E6) Neg(x *E6) *E6 { 68 z.B0.Neg(&x.B0) 69 z.B1.Neg(&x.B1) 70 z.B2.Neg(&x.B2) 71 return z 72 } 73 74 // Sub subtracts two elements of E6 75 func (z *E6) Sub(x, y *E6) *E6 { 76 z.B0.Sub(&x.B0, &y.B0) 77 z.B1.Sub(&x.B1, &y.B1) 78 z.B2.Sub(&x.B2, &y.B2) 79 return z 80 } 81 82 // Double doubles an element in E6 83 func (z *E6) Double(x *E6) *E6 { 84 z.B0.Double(&x.B0) 85 z.B1.Double(&x.B1) 86 z.B2.Double(&x.B2) 87 return z 88 } 89 90 // String puts E6 elmt in string form 91 func (z *E6) String() string { 92 return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2") 93 } 94 95 // MulByNonResidue mul x by (0,1,0) 96 func (z *E6) MulByNonResidue(x *E6) *E6 { 97 z.B2, z.B1, z.B0 = x.B1, x.B0, x.B2 98 z.B0.MulByNonResidue(&z.B0) 99 return z 100 } 101 102 // MulByE2 multiplies an element in E6 by an element in E2 103 func (z *E6) MulByE2(x *E6, y *E2) *E6 { 104 var yCopy E2 105 yCopy.Set(y) 106 z.B0.Mul(&x.B0, &yCopy) 107 z.B1.Mul(&x.B1, &yCopy) 108 z.B2.Mul(&x.B2, &yCopy) 109 return z 110 } 111 112 // MulBy12 multiplication by sparse element (0,b1,b2) 113 func (x *E6) MulBy12(b1, b2 *E2) *E6 { 114 var t1, t2, c0, tmp, c1, c2 E2 115 t1.Mul(&x.B1, b1) 116 t2.Mul(&x.B2, b2) 117 c0.Add(&x.B1, &x.B2) 118 tmp.Add(b1, b2) 119 c0.Mul(&c0, &tmp) 120 c0.Sub(&c0, &t1) 121 c0.Sub(&c0, &t2) 122 c0.MulByNonResidue(&c0) 123 c1.Add(&x.B0, &x.B1) 124 c1.Mul(&c1, b1) 125 c1.Sub(&c1, &t1) 126 tmp.MulByNonResidue(&t2) 127 c1.Add(&c1, &tmp) 128 tmp.Add(&x.B0, &x.B2) 129 c2.Mul(b2, &tmp) 130 c2.Sub(&c2, &t2) 131 c2.Add(&c2, &t1) 132 133 x.B0 = c0 134 x.B1 = c1 135 x.B2 = c2 136 137 return x 138 } 139 140 // MulBy01 multiplication by sparse element (c0,c1,0) 141 func (z *E6) MulBy01(c0, c1 *E2) *E6 { 142 143 var a, b, tmp, t0, t1, t2 E2 144 145 a.Mul(&z.B0, c0) 146 b.Mul(&z.B1, c1) 147 148 tmp.Add(&z.B1, &z.B2) 149 t0.Mul(c1, &tmp) 150 t0.Sub(&t0, &b) 151 t0.MulByNonResidue(&t0) 152 t0.Add(&t0, &a) 153 154 tmp.Add(&z.B0, &z.B2) 155 t2.Mul(c0, &tmp) 156 t2.Sub(&t2, &a) 157 t2.Add(&t2, &b) 158 159 t1.Add(c0, c1) 160 tmp.Add(&z.B0, &z.B1) 161 t1.Mul(&t1, &tmp) 162 t1.Sub(&t1, &a) 163 t1.Sub(&t1, &b) 164 165 z.B0.Set(&t0) 166 z.B1.Set(&t1) 167 z.B2.Set(&t2) 168 169 return z 170 } 171 172 // MulBy1 multiplication of E6 by sparse element (0, c1, 0) 173 func (z *E6) MulBy1(c1 *E2) *E6 { 174 175 var b, tmp, t0, t1 E2 176 b.Mul(&z.B1, c1) 177 178 tmp.Add(&z.B1, &z.B2) 179 t0.Mul(c1, &tmp) 180 t0.Sub(&t0, &b) 181 t0.MulByNonResidue(&t0) 182 183 tmp.Add(&z.B0, &z.B1) 184 t1.Mul(c1, &tmp) 185 t1.Sub(&t1, &b) 186 187 z.B0.Set(&t0) 188 z.B1.Set(&t1) 189 z.B2.Set(&b) 190 191 return z 192 } 193 194 // Mul sets z to the E6 product of x,y, returns z 195 func (z *E6) Mul(x, y *E6) *E6 { 196 // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf 197 var t0, t1, t2, c0, c1, c2, tmp E2 198 t0.Mul(&x.B0, &y.B0) 199 t1.Mul(&x.B1, &y.B1) 200 t2.Mul(&x.B2, &y.B2) 201 202 c0.Add(&x.B1, &x.B2) 203 tmp.Add(&y.B1, &y.B2) 204 c0.Mul(&c0, &tmp).Sub(&c0, &t1).Sub(&c0, &t2).MulByNonResidue(&c0).Add(&c0, &t0) 205 206 c1.Add(&x.B0, &x.B1) 207 tmp.Add(&y.B0, &y.B1) 208 c1.Mul(&c1, &tmp).Sub(&c1, &t0).Sub(&c1, &t1) 209 tmp.MulByNonResidue(&t2) 210 c1.Add(&c1, &tmp) 211 212 tmp.Add(&x.B0, &x.B2) 213 c2.Add(&y.B0, &y.B2).Mul(&c2, &tmp).Sub(&c2, &t0).Sub(&c2, &t2).Add(&c2, &t1) 214 215 z.B0.Set(&c0) 216 z.B1.Set(&c1) 217 z.B2.Set(&c2) 218 219 return z 220 } 221 222 // Square sets z to the E6 product of x,x, returns z 223 func (z *E6) Square(x *E6) *E6 { 224 225 // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf 226 var c4, c5, c1, c2, c3, c0 E2 227 c4.Mul(&x.B0, &x.B1).Double(&c4) 228 c5.Square(&x.B2) 229 c1.MulByNonResidue(&c5).Add(&c1, &c4) 230 c2.Sub(&c4, &c5) 231 c3.Square(&x.B0) 232 c4.Sub(&x.B0, &x.B1).Add(&c4, &x.B2) 233 c5.Mul(&x.B1, &x.B2).Double(&c5) 234 c4.Square(&c4) 235 c0.MulByNonResidue(&c5).Add(&c0, &c3) 236 z.B2.Add(&c2, &c4).Add(&z.B2, &c5).Sub(&z.B2, &c3) 237 z.B0.Set(&c0) 238 z.B1.Set(&c1) 239 240 return z 241 } 242 243 // Inverse an element in E6 244 // 245 // if x == 0, sets and returns z = x 246 func (z *E6) Inverse(x *E6) *E6 { 247 // Algorithm 17 from https://eprint.iacr.org/2010/354.pdf 248 // step 9 is wrong in the paper it's t1-t4 249 var t0, t1, t2, t3, t4, t5, t6, c0, c1, c2, d1, d2 E2 250 t0.Square(&x.B0) 251 t1.Square(&x.B1) 252 t2.Square(&x.B2) 253 t3.Mul(&x.B0, &x.B1) 254 t4.Mul(&x.B0, &x.B2) 255 t5.Mul(&x.B1, &x.B2) 256 c0.MulByNonResidue(&t5).Neg(&c0).Add(&c0, &t0) 257 c1.MulByNonResidue(&t2).Sub(&c1, &t3) 258 c2.Sub(&t1, &t4) 259 t6.Mul(&x.B0, &c0) 260 d1.Mul(&x.B2, &c1) 261 d2.Mul(&x.B1, &c2) 262 d1.Add(&d1, &d2).MulByNonResidue(&d1) 263 t6.Add(&t6, &d1) 264 t6.Inverse(&t6) 265 z.B0.Mul(&c0, &t6) 266 z.B1.Mul(&c1, &t6) 267 z.B2.Mul(&c2, &t6) 268 269 return z 270 } 271 272 // BatchInvertE6 returns a new slice with every element in a inverted. 273 // It uses Montgomery batch inversion trick. 274 // 275 // if a[i] == 0, returns result[i] = a[i] 276 func BatchInvertE6(a []E6) []E6 { 277 res := make([]E6, len(a)) 278 if len(a) == 0 { 279 return res 280 } 281 282 zeroes := make([]bool, len(a)) 283 var accumulator E6 284 accumulator.SetOne() 285 286 for i := 0; i < len(a); i++ { 287 if a[i].IsZero() { 288 zeroes[i] = true 289 continue 290 } 291 res[i].Set(&accumulator) 292 accumulator.Mul(&accumulator, &a[i]) 293 } 294 295 accumulator.Inverse(&accumulator) 296 297 for i := len(a) - 1; i >= 0; i-- { 298 if zeroes[i] { 299 continue 300 } 301 res[i].Mul(&res[i], &accumulator) 302 accumulator.Mul(&accumulator, &a[i]) 303 } 304 305 return res 306 } 307 {{ template "base" .}}