github.com/consensys/gnark-crypto@v0.14.0/ecc/bn254/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/bn254/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  func init() {
   207  	q := fp.Modulus()
   208  	tmp := big.NewInt(3)
   209  	sqrtExp1.Set(q).Sub(&sqrtExp1, tmp).Rsh(&sqrtExp1, 2)
   210  
   211  	tmp.SetUint64(1)
   212  	sqrtExp2.Set(q).Sub(&sqrtExp2, tmp).Rsh(&sqrtExp2, 1)
   213  }
   214  
   215  var sqrtExp1, sqrtExp2 big.Int
   216  
   217  // Sqrt sets z to the square root of x and returns z
   218  // The function does not test whether the square root
   219  // exists or not, it's up to the caller to call
   220  // Legendre beforehand.
   221  // cf https://eprint.iacr.org/2012/685.pdf (algo 9)
   222  func (z *E2) Sqrt(x *E2) *E2 {
   223  
   224  	var a1, alpha, b, x0, minusone E2
   225  
   226  	minusone.SetOne().Neg(&minusone)
   227  
   228  	a1.Exp(*x, &sqrtExp1)
   229  	alpha.Square(&a1).
   230  		Mul(&alpha, x)
   231  	x0.Mul(x, &a1)
   232  	if alpha.Equal(&minusone) {
   233  		var c fp.Element
   234  		c.Set(&x0.A0)
   235  		z.A0.Neg(&x0.A1)
   236  		z.A1.Set(&c)
   237  		return z
   238  	}
   239  	a1.SetOne()
   240  	b.Add(&a1, &alpha)
   241  
   242  	b.Exp(b, &sqrtExp2).Mul(&x0, &b)
   243  	z.Set(&b)
   244  	return z
   245  }
   246  
   247  // BatchInvertE2 returns a new slice with every element in a inverted.
   248  // It uses Montgomery batch inversion trick.
   249  //
   250  // if a[i] == 0, returns result[i] = a[i]
   251  func BatchInvertE2(a []E2) []E2 {
   252  	res := make([]E2, len(a))
   253  	if len(a) == 0 {
   254  		return res
   255  	}
   256  
   257  	zeroes := make([]bool, len(a))
   258  	var accumulator E2
   259  	accumulator.SetOne()
   260  
   261  	for i := 0; i < len(a); i++ {
   262  		if a[i].IsZero() {
   263  			zeroes[i] = true
   264  			continue
   265  		}
   266  		res[i].Set(&accumulator)
   267  		accumulator.Mul(&accumulator, &a[i])
   268  	}
   269  
   270  	accumulator.Inverse(&accumulator)
   271  
   272  	for i := len(a) - 1; i >= 0; i-- {
   273  		if zeroes[i] {
   274  			continue
   275  		}
   276  		res[i].Mul(&res[i], &accumulator)
   277  		accumulator.Mul(&accumulator, &a[i])
   278  	}
   279  
   280  	return res
   281  }
   282  
   283  // Select is conditional move.
   284  // If cond = 0, it sets z to caseZ and returns it. otherwise caseNz.
   285  func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 {
   286  	//Might be able to save a nanosecond or two by an aggregate implementation
   287  
   288  	z.A0.Select(cond, &caseZ.A0, &caseNz.A0)
   289  	z.A1.Select(cond, &caseZ.A1, &caseNz.A1)
   290  
   291  	return z
   292  }
   293  
   294  // Div divides an element in E2 by an element in E2
   295  func (z *E2) Div(x *E2, y *E2) *E2 {
   296  	var r E2
   297  	r.Inverse(y).Mul(x, &r)
   298  	return z.Set(&r)
   299  }