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" .}}