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