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