github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-377/internal/fptower/e6.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  // E6 is a degree three finite field extension of fp2
    20  type E6 struct {
    21  	B0, B1, B2 E2
    22  }
    23  
    24  // Equal returns true if z equals x, false otherwise
    25  func (z *E6) Equal(x *E6) bool {
    26  	return z.B0.Equal(&x.B0) && z.B1.Equal(&x.B1) && z.B2.Equal(&x.B2)
    27  }
    28  
    29  // SetString sets a E6 elmt from stringf
    30  func (z *E6) SetString(s1, s2, s3, s4, s5, s6 string) *E6 {
    31  	z.B0.SetString(s1, s2)
    32  	z.B1.SetString(s3, s4)
    33  	z.B2.SetString(s5, s6)
    34  	return z
    35  }
    36  
    37  // Set Sets a E6 elmt form another E6 elmt
    38  func (z *E6) Set(x *E6) *E6 {
    39  	z.B0 = x.B0
    40  	z.B1 = x.B1
    41  	z.B2 = x.B2
    42  	return z
    43  }
    44  
    45  // SetOne sets z to 1 in Montgomery form and returns z
    46  func (z *E6) SetOne() *E6 {
    47  	*z = E6{}
    48  	z.B0.A0.SetOne()
    49  	return z
    50  }
    51  
    52  // SetRandom set z to a random elmt
    53  func (z *E6) SetRandom() (*E6, error) {
    54  	if _, err := z.B0.SetRandom(); err != nil {
    55  		return nil, err
    56  	}
    57  	if _, err := z.B1.SetRandom(); err != nil {
    58  		return nil, err
    59  	}
    60  	if _, err := z.B2.SetRandom(); err != nil {
    61  		return nil, err
    62  	}
    63  	return z, nil
    64  }
    65  
    66  // IsZero returns true if z is zero, false otherwise
    67  func (z *E6) IsZero() bool {
    68  	return z.B0.IsZero() && z.B1.IsZero() && z.B2.IsZero()
    69  }
    70  
    71  // IsOne returns true if z is one, false otherwise
    72  func (z *E6) IsOne() bool {
    73  	return z.B0.IsOne() && z.B1.IsZero() && z.B2.IsZero()
    74  }
    75  
    76  // Add adds two elements of E6
    77  func (z *E6) Add(x, y *E6) *E6 {
    78  	z.B0.Add(&x.B0, &y.B0)
    79  	z.B1.Add(&x.B1, &y.B1)
    80  	z.B2.Add(&x.B2, &y.B2)
    81  	return z
    82  }
    83  
    84  // Neg negates the E6 number
    85  func (z *E6) Neg(x *E6) *E6 {
    86  	z.B0.Neg(&x.B0)
    87  	z.B1.Neg(&x.B1)
    88  	z.B2.Neg(&x.B2)
    89  	return z
    90  }
    91  
    92  // Sub subtracts two elements of E6
    93  func (z *E6) Sub(x, y *E6) *E6 {
    94  	z.B0.Sub(&x.B0, &y.B0)
    95  	z.B1.Sub(&x.B1, &y.B1)
    96  	z.B2.Sub(&x.B2, &y.B2)
    97  	return z
    98  }
    99  
   100  // Double doubles an element in E6
   101  func (z *E6) Double(x *E6) *E6 {
   102  	z.B0.Double(&x.B0)
   103  	z.B1.Double(&x.B1)
   104  	z.B2.Double(&x.B2)
   105  	return z
   106  }
   107  
   108  // String puts E6 elmt in string form
   109  func (z *E6) String() string {
   110  	return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2")
   111  }
   112  
   113  // MulByNonResidue mul x by (0,1,0)
   114  func (z *E6) MulByNonResidue(x *E6) *E6 {
   115  	z.B2, z.B1, z.B0 = x.B1, x.B0, x.B2
   116  	z.B0.MulByNonResidue(&z.B0)
   117  	return z
   118  }
   119  
   120  // MulByE2 multiplies an element in E6 by an element in E2
   121  func (z *E6) MulByE2(x *E6, y *E2) *E6 {
   122  	var yCopy E2
   123  	yCopy.Set(y)
   124  	z.B0.Mul(&x.B0, &yCopy)
   125  	z.B1.Mul(&x.B1, &yCopy)
   126  	z.B2.Mul(&x.B2, &yCopy)
   127  	return z
   128  }
   129  
   130  // MulBy12 multiplication by sparse element (0,b1,b2)
   131  func (x *E6) MulBy12(b1, b2 *E2) *E6 {
   132  	var t1, t2, c0, tmp, c1, c2 E2
   133  	t1.Mul(&x.B1, b1)
   134  	t2.Mul(&x.B2, b2)
   135  	c0.Add(&x.B1, &x.B2)
   136  	tmp.Add(b1, b2)
   137  	c0.Mul(&c0, &tmp)
   138  	c0.Sub(&c0, &t1)
   139  	c0.Sub(&c0, &t2)
   140  	c0.MulByNonResidue(&c0)
   141  	c1.Add(&x.B0, &x.B1)
   142  	c1.Mul(&c1, b1)
   143  	c1.Sub(&c1, &t1)
   144  	tmp.MulByNonResidue(&t2)
   145  	c1.Add(&c1, &tmp)
   146  	tmp.Add(&x.B0, &x.B2)
   147  	c2.Mul(b2, &tmp)
   148  	c2.Sub(&c2, &t2)
   149  	c2.Add(&c2, &t1)
   150  
   151  	x.B0 = c0
   152  	x.B1 = c1
   153  	x.B2 = c2
   154  
   155  	return x
   156  }
   157  
   158  // MulBy01 multiplication by sparse element (c0,c1,0)
   159  func (z *E6) MulBy01(c0, c1 *E2) *E6 {
   160  
   161  	var a, b, tmp, t0, t1, t2 E2
   162  
   163  	a.Mul(&z.B0, c0)
   164  	b.Mul(&z.B1, c1)
   165  
   166  	tmp.Add(&z.B1, &z.B2)
   167  	t0.Mul(c1, &tmp)
   168  	t0.Sub(&t0, &b)
   169  	t0.MulByNonResidue(&t0)
   170  	t0.Add(&t0, &a)
   171  
   172  	tmp.Add(&z.B0, &z.B2)
   173  	t2.Mul(c0, &tmp)
   174  	t2.Sub(&t2, &a)
   175  	t2.Add(&t2, &b)
   176  
   177  	t1.Add(c0, c1)
   178  	tmp.Add(&z.B0, &z.B1)
   179  	t1.Mul(&t1, &tmp)
   180  	t1.Sub(&t1, &a)
   181  	t1.Sub(&t1, &b)
   182  
   183  	z.B0.Set(&t0)
   184  	z.B1.Set(&t1)
   185  	z.B2.Set(&t2)
   186  
   187  	return z
   188  }
   189  
   190  // MulBy1 multiplication of E6 by sparse element (0, c1, 0)
   191  func (z *E6) MulBy1(c1 *E2) *E6 {
   192  
   193  	var b, tmp, t0, t1 E2
   194  	b.Mul(&z.B1, c1)
   195  
   196  	tmp.Add(&z.B1, &z.B2)
   197  	t0.Mul(c1, &tmp)
   198  	t0.Sub(&t0, &b)
   199  	t0.MulByNonResidue(&t0)
   200  
   201  	tmp.Add(&z.B0, &z.B1)
   202  	t1.Mul(c1, &tmp)
   203  	t1.Sub(&t1, &b)
   204  
   205  	z.B0.Set(&t0)
   206  	z.B1.Set(&t1)
   207  	z.B2.Set(&b)
   208  
   209  	return z
   210  }
   211  
   212  // Mul sets z to the E6 product of x,y, returns z
   213  func (z *E6) Mul(x, y *E6) *E6 {
   214  	// Algorithm 13 from https://eprint.iacr.org/2010/354.pdf
   215  	var t0, t1, t2, c0, c1, c2, tmp E2
   216  	t0.Mul(&x.B0, &y.B0)
   217  	t1.Mul(&x.B1, &y.B1)
   218  	t2.Mul(&x.B2, &y.B2)
   219  
   220  	c0.Add(&x.B1, &x.B2)
   221  	tmp.Add(&y.B1, &y.B2)
   222  	c0.Mul(&c0, &tmp).Sub(&c0, &t1).Sub(&c0, &t2).MulByNonResidue(&c0).Add(&c0, &t0)
   223  
   224  	c1.Add(&x.B0, &x.B1)
   225  	tmp.Add(&y.B0, &y.B1)
   226  	c1.Mul(&c1, &tmp).Sub(&c1, &t0).Sub(&c1, &t1)
   227  	tmp.MulByNonResidue(&t2)
   228  	c1.Add(&c1, &tmp)
   229  
   230  	tmp.Add(&x.B0, &x.B2)
   231  	c2.Add(&y.B0, &y.B2).Mul(&c2, &tmp).Sub(&c2, &t0).Sub(&c2, &t2).Add(&c2, &t1)
   232  
   233  	z.B0.Set(&c0)
   234  	z.B1.Set(&c1)
   235  	z.B2.Set(&c2)
   236  
   237  	return z
   238  }
   239  
   240  // Square sets z to the E6 product of x,x, returns z
   241  func (z *E6) Square(x *E6) *E6 {
   242  
   243  	// Algorithm 16 from https://eprint.iacr.org/2010/354.pdf
   244  	var c4, c5, c1, c2, c3, c0 E2
   245  	c4.Mul(&x.B0, &x.B1).Double(&c4)
   246  	c5.Square(&x.B2)
   247  	c1.MulByNonResidue(&c5).Add(&c1, &c4)
   248  	c2.Sub(&c4, &c5)
   249  	c3.Square(&x.B0)
   250  	c4.Sub(&x.B0, &x.B1).Add(&c4, &x.B2)
   251  	c5.Mul(&x.B1, &x.B2).Double(&c5)
   252  	c4.Square(&c4)
   253  	c0.MulByNonResidue(&c5).Add(&c0, &c3)
   254  	z.B2.Add(&c2, &c4).Add(&z.B2, &c5).Sub(&z.B2, &c3)
   255  	z.B0.Set(&c0)
   256  	z.B1.Set(&c1)
   257  
   258  	return z
   259  }
   260  
   261  // Inverse an element in E6
   262  //
   263  // if x == 0, sets and returns z = x
   264  func (z *E6) Inverse(x *E6) *E6 {
   265  	// Algorithm 17 from https://eprint.iacr.org/2010/354.pdf
   266  	// step 9 is wrong in the paper it's t1-t4
   267  	var t0, t1, t2, t3, t4, t5, t6, c0, c1, c2, d1, d2 E2
   268  	t0.Square(&x.B0)
   269  	t1.Square(&x.B1)
   270  	t2.Square(&x.B2)
   271  	t3.Mul(&x.B0, &x.B1)
   272  	t4.Mul(&x.B0, &x.B2)
   273  	t5.Mul(&x.B1, &x.B2)
   274  	c0.MulByNonResidue(&t5).Neg(&c0).Add(&c0, &t0)
   275  	c1.MulByNonResidue(&t2).Sub(&c1, &t3)
   276  	c2.Sub(&t1, &t4)
   277  	t6.Mul(&x.B0, &c0)
   278  	d1.Mul(&x.B2, &c1)
   279  	d2.Mul(&x.B1, &c2)
   280  	d1.Add(&d1, &d2).MulByNonResidue(&d1)
   281  	t6.Add(&t6, &d1)
   282  	t6.Inverse(&t6)
   283  	z.B0.Mul(&c0, &t6)
   284  	z.B1.Mul(&c1, &t6)
   285  	z.B2.Mul(&c2, &t6)
   286  
   287  	return z
   288  }
   289  
   290  // BatchInvertE6 returns a new slice with every element in a inverted.
   291  // It uses Montgomery batch inversion trick.
   292  //
   293  // if a[i] == 0, returns result[i] = a[i]
   294  func BatchInvertE6(a []E6) []E6 {
   295  	res := make([]E6, len(a))
   296  	if len(a) == 0 {
   297  		return res
   298  	}
   299  
   300  	zeroes := make([]bool, len(a))
   301  	var accumulator E6
   302  	accumulator.SetOne()
   303  
   304  	for i := 0; i < len(a); i++ {
   305  		if a[i].IsZero() {
   306  			zeroes[i] = true
   307  			continue
   308  		}
   309  		res[i].Set(&accumulator)
   310  		accumulator.Mul(&accumulator, &a[i])
   311  	}
   312  
   313  	accumulator.Inverse(&accumulator)
   314  
   315  	for i := len(a) - 1; i >= 0; i-- {
   316  		if zeroes[i] {
   317  			continue
   318  		}
   319  		res[i].Mul(&res[i], &accumulator)
   320  		accumulator.Mul(&accumulator, &a[i])
   321  	}
   322  
   323  	return res
   324  }
   325  
   326  // Select is conditional move.
   327  // If cond = 0, it sets z to caseZ and returns it. otherwise caseNz.
   328  func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 {
   329  	//Might be able to save a nanosecond or two by an aggregate implementation
   330  
   331  	z.B0.Select(cond, &caseZ.B0, &caseNz.B0)
   332  	z.B1.Select(cond, &caseZ.B1, &caseNz.B1)
   333  	z.B2.Select(cond, &caseZ.B2, &caseNz.B2)
   334  
   335  	return z
   336  }
   337  
   338  // Div divides an element in E6 by an element in E6
   339  func (z *E6) Div(x *E6, y *E6) *E6 {
   340  	var r E6
   341  	r.Inverse(y).Mul(x, &r)
   342  	return z.Set(&r)
   343  }