github.com/consensys/gnark-crypto@v0.14.0/internal/generator/tower/template/fq12over6over2/fq2.go.tmpl (about) 1 2 import ( 3 "math/big" 4 "github.com/consensys/gnark-crypto/ecc/{{.Curve.Name}}/fp" 5 ) 6 7 // E2 is a degree two finite field extension of fp.Element 8 type E2 struct { 9 A0, A1 fp.Element 10 } 11 12 // Equal returns true if z equals x, false otherwise 13 func (z *E2) Equal(x *E2) bool { 14 return z.A0.Equal(&x.A0) && z.A1.Equal(&x.A1) 15 } 16 17 // Bits 18 // TODO @gbotrel fixme this shouldn't return a E2 19 func (z *E2) Bits() E2 { 20 r := E2 {} 21 r.A0 = z.A0.Bits() 22 r.A1 = z.A1.Bits() 23 return r 24 } 25 26 27 // Cmp compares (lexicographic order) z and x and returns: 28 // 29 // -1 if z < x 30 // 0 if z == x 31 // +1 if z > x 32 // 33 func (z *E2) Cmp(x *E2) int { 34 if a1 := z.A1.Cmp(&x.A1); a1 != 0 { 35 return a1 36 } 37 return z.A0.Cmp(&x.A0) 38 } 39 40 // LexicographicallyLargest returns true if this element is strictly lexicographically 41 // larger than its negation, false otherwise 42 func (z *E2) LexicographicallyLargest() bool { 43 // adapted from github.com/zkcrypto/bls12_381 44 if z.A1.IsZero() { 45 return z.A0.LexicographicallyLargest() 46 } 47 return z.A1.LexicographicallyLargest() 48 } 49 50 // SetString sets a E2 element from strings 51 func (z *E2) SetString(s1, s2 string) *E2 { 52 z.A0.SetString(s1) 53 z.A1.SetString(s2) 54 return z 55 } 56 57 // SetZero sets an E2 elmt to zero 58 func (z *E2) SetZero() *E2 { 59 z.A0.SetZero() 60 z.A1.SetZero() 61 return z 62 } 63 64 // Set sets an E2 from x 65 func (z *E2) Set(x *E2) *E2 { 66 z.A0 = x.A0 67 z.A1 = x.A1 68 return z 69 } 70 71 // SetOne sets z to 1 in Montgomery form and returns z 72 func (z *E2) SetOne() *E2 { 73 z.A0.SetOne() 74 z.A1.SetZero() 75 return z 76 } 77 78 // SetRandom sets a0 and a1 to random values 79 func (z *E2) SetRandom() (*E2, error) { 80 if _, err := z.A0.SetRandom(); err != nil { 81 return nil, err 82 } 83 if _, err := z.A1.SetRandom(); err != nil { 84 return nil, err 85 } 86 return z, nil 87 } 88 89 // IsZero returns true if z is zero, false otherwise 90 func (z *E2) IsZero() bool { 91 return z.A0.IsZero() && z.A1.IsZero() 92 } 93 94 // IsOne returns true if z is one, false otherwise 95 func (z *E2) IsOne() bool { 96 return z.A0.IsOne() && z.A1.IsZero() 97 } 98 99 // Add adds two elements of E2 100 func (z *E2) Add(x, y *E2) *E2 { 101 addE2(z, x, y) 102 return z 103 } 104 105 // Sub subtracts two elements of E2 106 func (z *E2) Sub(x, y *E2) *E2 { 107 subE2(z, x, y) 108 return z 109 } 110 111 112 // Double doubles an E2 element 113 func (z *E2) Double(x *E2) *E2 { 114 doubleE2(z, x) 115 return z 116 } 117 118 119 // Neg negates an E2 element 120 func (z *E2) Neg(x *E2) *E2 { 121 negE2(z, x) 122 return z 123 } 124 125 // String implements Stringer interface for fancy printing 126 func (z *E2) String() string { 127 return z.A0.String() + "+" + z.A1.String() + "*u" 128 } 129 130 // MulByElement multiplies an element in E2 by an element in fp 131 func (z *E2) MulByElement(x *E2, y *fp.Element) *E2 { 132 var yCopy fp.Element 133 yCopy.Set(y) 134 z.A0.Mul(&x.A0, &yCopy) 135 z.A1.Mul(&x.A1, &yCopy) 136 return z 137 } 138 139 // Conjugate conjugates an element in E2 140 func (z *E2) Conjugate(x *E2) *E2 { 141 z.A0 = x.A0 142 z.A1.Neg(&x.A1) 143 return z 144 } 145 146 // Halve sets z to z / 2 147 func (z *E2) Halve() { 148 z.A0.Halve() 149 z.A1.Halve() 150 } 151 152 // Legendre returns the Legendre symbol of z 153 func (z *E2) Legendre() int { 154 var n fp.Element 155 z.norm(&n) 156 return n.Legendre() 157 } 158 159 // Exp sets z=xᵏ (mod q²) and returns it 160 func (z *E2) Exp(x E2, k *big.Int) *E2 { 161 if k.IsUint64() && k.Uint64() == 0 { 162 return z.SetOne() 163 } 164 165 e := k 166 if k.Sign() == -1 { 167 // negative k, we invert 168 // if k < 0: xᵏ (mod q²) == (x⁻¹)ᵏ (mod q²) 169 x.Inverse(&x) 170 171 // we negate k in a temp big.Int since 172 // Int.Bit(_) of k and -k is different 173 e = bigIntPool.Get().(*big.Int) 174 defer bigIntPool.Put(e) 175 e.Neg(k) 176 } 177 178 z.SetOne() 179 b := e.Bytes() 180 for i := 0; i < len(b); i++ { 181 w := b[i] 182 for j := 0; j < 8; j++ { 183 z.Square(z) 184 if (w & (0b10000000 >> j)) != 0 { 185 z.Mul(z, &x) 186 } 187 } 188 } 189 190 return z 191 } 192 193 {{if .Curve.Fp.SqrtQ3Mod4 }} 194 func init() { 195 q := fp.Modulus() 196 tmp := big.NewInt(3) 197 sqrtExp1.Set(q).Sub(&sqrtExp1, tmp).Rsh(&sqrtExp1, 2) 198 199 tmp.SetUint64(1) 200 sqrtExp2.Set(q).Sub(&sqrtExp2, tmp).Rsh(&sqrtExp2, 1) 201 } 202 203 var sqrtExp1, sqrtExp2 big.Int 204 205 // Sqrt sets z to the square root of x and returns z 206 // The function does not test whether the square root 207 // exists or not, it's up to the caller to call 208 // Legendre beforehand. 209 // cf https://eprint.iacr.org/2012/685.pdf (algo 9) 210 func (z *E2) Sqrt(x *E2) *E2 { 211 212 var a1, alpha, b, x0, minusone E2 213 214 minusone.SetOne().Neg(&minusone) 215 216 a1.Exp(*x, &sqrtExp1) 217 alpha.Square(&a1). 218 Mul(&alpha, x) 219 x0.Mul(x, &a1) 220 if alpha.Equal(&minusone) { 221 var c fp.Element 222 c.Set(&x0.A0) 223 z.A0.Neg(&x0.A1) 224 z.A1.Set(&c) 225 return z 226 } 227 a1.SetOne() 228 b.Add(&a1, &alpha) 229 230 b.Exp(b, &sqrtExp2).Mul(&x0, &b) 231 z.Set(&b) 232 return z 233 } 234 {{else }} 235 // Sqrt sets z to the square root of and returns z 236 // The function does not test whether the square root 237 // exists or not, it's up to the caller to call 238 // Legendre beforehand. 239 // cf https://eprint.iacr.org/2012/685.pdf (algo 10) 240 func (z *E2) Sqrt(x *E2) *E2 { 241 242 // precomputation 243 var b, c, d, e, f, x0 E2 244 var _b, o fp.Element 245 246 // c must be a non square (works for p=1 mod 12 hence 1 mod 4, only bls377 has such a p currently) 247 c.A1.SetOne() 248 249 q := fp.Modulus() 250 var exp, one big.Int 251 one.SetUint64(1) 252 exp.Set(q).Sub(&exp, &one).Rsh(&exp, 1) 253 d.Exp(c, &exp) 254 e.Mul(&d, &c).Inverse(&e) 255 f.Mul(&d, &c).Square(&f) 256 257 // computation 258 exp.Rsh(&exp, 1) 259 b.Exp(*x, &exp) 260 b.norm(&_b) 261 o.SetOne() 262 if _b.Equal(&o) { 263 x0.Square(&b).Mul(&x0, x) 264 _b.Set(&x0.A0).Sqrt(&_b) 265 z.Conjugate(&b).MulByElement(z, &_b) 266 return z 267 } 268 x0.Square(&b).Mul(&x0, x).Mul(&x0, &f) 269 _b.Set(&x0.A0).Sqrt(&_b) 270 z.Conjugate(&b).MulByElement(z, &_b).Mul(z, &e) 271 272 return z 273 } 274 {{end}} 275 276 // BatchInvertE2 returns a new slice with every element in a inverted. 277 // It uses Montgomery batch inversion trick. 278 // 279 // if a[i] == 0, returns result[i] = a[i] 280 func BatchInvertE2(a []E2) []E2 { 281 res := make([]E2, len(a)) 282 if len(a) == 0 { 283 return res 284 } 285 286 zeroes := make([]bool, len(a)) 287 var accumulator E2 288 accumulator.SetOne() 289 290 for i := 0; i < len(a); i++ { 291 if a[i].IsZero() { 292 zeroes[i] = true 293 continue 294 } 295 res[i].Set(&accumulator) 296 accumulator.Mul(&accumulator, &a[i]) 297 } 298 299 accumulator.Inverse(&accumulator) 300 301 for i := len(a) - 1; i >= 0; i-- { 302 if zeroes[i] { 303 continue 304 } 305 res[i].Mul(&res[i], &accumulator) 306 accumulator.Mul(&accumulator, &a[i]) 307 } 308 309 return res 310 } 311 312 {{ template "base" .}}