github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/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-378/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  }