github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-381/internal/fptower/e6.go (about) 1 // Copyright 2020 Consensys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package fptower 18 19 // E6 is a degree three finite field extension of fp2 20 type E6 struct { 21 B0, B1, B2 E2 22 } 23 24 // Equal returns true if z equals x, false otherwise 25 func (z *E6) Equal(x *E6) bool { 26 return z.B0.Equal(&x.B0) && z.B1.Equal(&x.B1) && z.B2.Equal(&x.B2) 27 } 28 29 // SetString sets a E6 elmt from stringf 30 func (z *E6) SetString(s1, s2, s3, s4, s5, s6 string) *E6 { 31 z.B0.SetString(s1, s2) 32 z.B1.SetString(s3, s4) 33 z.B2.SetString(s5, s6) 34 return z 35 } 36 37 // Set Sets a E6 elmt form another E6 elmt 38 func (z *E6) Set(x *E6) *E6 { 39 z.B0 = x.B0 40 z.B1 = x.B1 41 z.B2 = x.B2 42 return z 43 } 44 45 // SetOne sets z to 1 in Montgomery form and returns z 46 func (z *E6) SetOne() *E6 { 47 *z = E6{} 48 z.B0.A0.SetOne() 49 return z 50 } 51 52 // SetRandom set z to a random elmt 53 func (z *E6) SetRandom() (*E6, error) { 54 if _, err := z.B0.SetRandom(); err != nil { 55 return nil, err 56 } 57 if _, err := z.B1.SetRandom(); err != nil { 58 return nil, err 59 } 60 if _, err := z.B2.SetRandom(); err != nil { 61 return nil, err 62 } 63 return z, nil 64 } 65 66 // IsZero returns true if z is zero, false otherwise 67 func (z *E6) IsZero() bool { 68 return z.B0.IsZero() && z.B1.IsZero() && z.B2.IsZero() 69 } 70 71 // IsOne returns true if z is one, false otherwise 72 func (z *E6) IsOne() bool { 73 return z.B0.IsOne() && z.B1.IsZero() && z.B2.IsZero() 74 } 75 76 // Add adds two elements of E6 77 func (z *E6) Add(x, y *E6) *E6 { 78 z.B0.Add(&x.B0, &y.B0) 79 z.B1.Add(&x.B1, &y.B1) 80 z.B2.Add(&x.B2, &y.B2) 81 return z 82 } 83 84 // Neg negates the E6 number 85 func (z *E6) Neg(x *E6) *E6 { 86 z.B0.Neg(&x.B0) 87 z.B1.Neg(&x.B1) 88 z.B2.Neg(&x.B2) 89 return z 90 } 91 92 // Sub subtracts two elements of E6 93 func (z *E6) Sub(x, y *E6) *E6 { 94 z.B0.Sub(&x.B0, &y.B0) 95 z.B1.Sub(&x.B1, &y.B1) 96 z.B2.Sub(&x.B2, &y.B2) 97 return z 98 } 99 100 // Double doubles an element in E6 101 func (z *E6) Double(x *E6) *E6 { 102 z.B0.Double(&x.B0) 103 z.B1.Double(&x.B1) 104 z.B2.Double(&x.B2) 105 return z 106 } 107 108 // String puts E6 elmt in string form 109 func (z *E6) String() string { 110 return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2") 111 } 112 113 // MulByNonResidue mul x by (0,1,0) 114 func (z *E6) MulByNonResidue(x *E6) *E6 { 115 z.B2, z.B1, z.B0 = x.B1, x.B0, x.B2 116 z.B0.MulByNonResidue(&z.B0) 117 return z 118 } 119 120 // MulByE2 multiplies an element in E6 by an element in E2 121 func (z *E6) MulByE2(x *E6, y *E2) *E6 { 122 var yCopy E2 123 yCopy.Set(y) 124 z.B0.Mul(&x.B0, &yCopy) 125 z.B1.Mul(&x.B1, &yCopy) 126 z.B2.Mul(&x.B2, &yCopy) 127 return z 128 } 129 130 // MulBy12 multiplication by sparse element (0,b1,b2) 131 func (x *E6) MulBy12(b1, b2 *E2) *E6 { 132 var t1, t2, c0, tmp, c1, c2 E2 133 t1.Mul(&x.B1, b1) 134 t2.Mul(&x.B2, b2) 135 c0.Add(&x.B1, &x.B2) 136 tmp.Add(b1, b2) 137 c0.Mul(&c0, &tmp) 138 c0.Sub(&c0, &t1) 139 c0.Sub(&c0, &t2) 140 c0.MulByNonResidue(&c0) 141 c1.Add(&x.B0, &x.B1) 142 c1.Mul(&c1, b1) 143 c1.Sub(&c1, &t1) 144 tmp.MulByNonResidue(&t2) 145 c1.Add(&c1, &tmp) 146 tmp.Add(&x.B0, &x.B2) 147 c2.Mul(b2, &tmp) 148 c2.Sub(&c2, &t2) 149 c2.Add(&c2, &t1) 150 151 x.B0 = c0 152 x.B1 = c1 153 x.B2 = c2 154 155 return x 156 } 157 158 // MulBy01 multiplication by sparse element (c0,c1,0) 159 func (z *E6) MulBy01(c0, c1 *E2) *E6 { 160 161 var a, b, tmp, t0, t1, t2 E2 162 163 a.Mul(&z.B0, c0) 164 b.Mul(&z.B1, c1) 165 166 tmp.Add(&z.B1, &z.B2) 167 t0.Mul(c1, &tmp) 168 t0.Sub(&t0, &b) 169 t0.MulByNonResidue(&t0) 170 t0.Add(&t0, &a) 171 172 tmp.Add(&z.B0, &z.B2) 173 t2.Mul(c0, &tmp) 174 t2.Sub(&t2, &a) 175 t2.Add(&t2, &b) 176 177 t1.Add(c0, c1) 178 tmp.Add(&z.B0, &z.B1) 179 t1.Mul(&t1, &tmp) 180 t1.Sub(&t1, &a) 181 t1.Sub(&t1, &b) 182 183 z.B0.Set(&t0) 184 z.B1.Set(&t1) 185 z.B2.Set(&t2) 186 187 return z 188 } 189 190 // MulBy1 multiplication of E6 by sparse element (0, c1, 0) 191 func (z *E6) MulBy1(c1 *E2) *E6 { 192 193 var b, tmp, t0, t1 E2 194 b.Mul(&z.B1, c1) 195 196 tmp.Add(&z.B1, &z.B2) 197 t0.Mul(c1, &tmp) 198 t0.Sub(&t0, &b) 199 t0.MulByNonResidue(&t0) 200 201 tmp.Add(&z.B0, &z.B1) 202 t1.Mul(c1, &tmp) 203 t1.Sub(&t1, &b) 204 205 z.B0.Set(&t0) 206 z.B1.Set(&t1) 207 z.B2.Set(&b) 208 209 return z 210 } 211 212 // Mul sets z to the E6 product of x,y, returns z 213 func (z *E6) Mul(x, y *E6) *E6 { 214 // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf 215 var t0, t1, t2, c0, c1, c2, tmp E2 216 t0.Mul(&x.B0, &y.B0) 217 t1.Mul(&x.B1, &y.B1) 218 t2.Mul(&x.B2, &y.B2) 219 220 c0.Add(&x.B1, &x.B2) 221 tmp.Add(&y.B1, &y.B2) 222 c0.Mul(&c0, &tmp).Sub(&c0, &t1).Sub(&c0, &t2).MulByNonResidue(&c0).Add(&c0, &t0) 223 224 c1.Add(&x.B0, &x.B1) 225 tmp.Add(&y.B0, &y.B1) 226 c1.Mul(&c1, &tmp).Sub(&c1, &t0).Sub(&c1, &t1) 227 tmp.MulByNonResidue(&t2) 228 c1.Add(&c1, &tmp) 229 230 tmp.Add(&x.B0, &x.B2) 231 c2.Add(&y.B0, &y.B2).Mul(&c2, &tmp).Sub(&c2, &t0).Sub(&c2, &t2).Add(&c2, &t1) 232 233 z.B0.Set(&c0) 234 z.B1.Set(&c1) 235 z.B2.Set(&c2) 236 237 return z 238 } 239 240 // Square sets z to the E6 product of x,x, returns z 241 func (z *E6) Square(x *E6) *E6 { 242 243 // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf 244 var c4, c5, c1, c2, c3, c0 E2 245 c4.Mul(&x.B0, &x.B1).Double(&c4) 246 c5.Square(&x.B2) 247 c1.MulByNonResidue(&c5).Add(&c1, &c4) 248 c2.Sub(&c4, &c5) 249 c3.Square(&x.B0) 250 c4.Sub(&x.B0, &x.B1).Add(&c4, &x.B2) 251 c5.Mul(&x.B1, &x.B2).Double(&c5) 252 c4.Square(&c4) 253 c0.MulByNonResidue(&c5).Add(&c0, &c3) 254 z.B2.Add(&c2, &c4).Add(&z.B2, &c5).Sub(&z.B2, &c3) 255 z.B0.Set(&c0) 256 z.B1.Set(&c1) 257 258 return z 259 } 260 261 // Inverse an element in E6 262 // 263 // if x == 0, sets and returns z = x 264 func (z *E6) Inverse(x *E6) *E6 { 265 // Algorithm 17 from https://eprint.iacr.org/2010/354.pdf 266 // step 9 is wrong in the paper it's t1-t4 267 var t0, t1, t2, t3, t4, t5, t6, c0, c1, c2, d1, d2 E2 268 t0.Square(&x.B0) 269 t1.Square(&x.B1) 270 t2.Square(&x.B2) 271 t3.Mul(&x.B0, &x.B1) 272 t4.Mul(&x.B0, &x.B2) 273 t5.Mul(&x.B1, &x.B2) 274 c0.MulByNonResidue(&t5).Neg(&c0).Add(&c0, &t0) 275 c1.MulByNonResidue(&t2).Sub(&c1, &t3) 276 c2.Sub(&t1, &t4) 277 t6.Mul(&x.B0, &c0) 278 d1.Mul(&x.B2, &c1) 279 d2.Mul(&x.B1, &c2) 280 d1.Add(&d1, &d2).MulByNonResidue(&d1) 281 t6.Add(&t6, &d1) 282 t6.Inverse(&t6) 283 z.B0.Mul(&c0, &t6) 284 z.B1.Mul(&c1, &t6) 285 z.B2.Mul(&c2, &t6) 286 287 return z 288 } 289 290 // BatchInvertE6 returns a new slice with every element in a inverted. 291 // It uses Montgomery batch inversion trick. 292 // 293 // if a[i] == 0, returns result[i] = a[i] 294 func BatchInvertE6(a []E6) []E6 { 295 res := make([]E6, len(a)) 296 if len(a) == 0 { 297 return res 298 } 299 300 zeroes := make([]bool, len(a)) 301 var accumulator E6 302 accumulator.SetOne() 303 304 for i := 0; i < len(a); i++ { 305 if a[i].IsZero() { 306 zeroes[i] = true 307 continue 308 } 309 res[i].Set(&accumulator) 310 accumulator.Mul(&accumulator, &a[i]) 311 } 312 313 accumulator.Inverse(&accumulator) 314 315 for i := len(a) - 1; i >= 0; i-- { 316 if zeroes[i] { 317 continue 318 } 319 res[i].Mul(&res[i], &accumulator) 320 accumulator.Mul(&accumulator, &a[i]) 321 } 322 323 return res 324 } 325 326 // Select is conditional move. 327 // If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. 328 func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { 329 //Might be able to save a nanosecond or two by an aggregate implementation 330 331 z.B0.Select(cond, &caseZ.B0, &caseNz.B0) 332 z.B1.Select(cond, &caseZ.B1, &caseNz.B1) 333 z.B2.Select(cond, &caseZ.B2, &caseNz.B2) 334 335 return z 336 } 337 338 // Div divides an element in E6 by an element in E6 339 func (z *E6) Div(x *E6, y *E6) *E6 { 340 var r E6 341 r.Inverse(y).Mul(x, &r) 342 return z.Set(&r) 343 }