github.com/consensys/gnark-crypto@v0.14.0/internal/generator/tower/template/fq12over6over2/fq6.go.tmpl (about)

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