github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp12.go (about)

     1  package bn256
     2  
     3  import "math/big"
     4  
     5  // For details of the algorithms used, see "Multiplication and Squaring on
     6  // Pairing-Friendly Fields, Devegili et al.
     7  // http://eprint.iacr.org/2006/471.pdf.
     8  //
     9  
    10  // gfP12 implements the field of size p¹² as a cubic extension of gfP4 where v³=u
    11  type gfP12 struct {
    12  	x, y, z gfP4 // value is xw² + yw + z
    13  }
    14  
    15  func gfP12Decode(in *gfP12) *gfP12 {
    16  	out := &gfP12{}
    17  	out.x = *gfP4Decode(&in.x)
    18  	out.y = *gfP4Decode(&in.y)
    19  	out.z = *gfP4Decode(&in.z)
    20  	return out
    21  }
    22  
    23  var gfP12Gen *gfP12 = &gfP12{
    24  	x: gfP4{
    25  		x: gfP2{
    26  			x: *fromBigInt(bigFromHex("256943fbdb2bf87ab91ae7fbeaff14e146cf7e2279b9d155d13461e09b22f523")),
    27  			y: *fromBigInt(bigFromHex("0167b0280051495c6af1ec23ba2cd2ff1cdcdeca461a5ab0b5449e9091308310")),
    28  		},
    29  		y: gfP2{
    30  			x: *fromBigInt(bigFromHex("5e7addaddf7fbfe16291b4e89af50b8217ddc47ba3cba833c6e77c3fb027685e")),
    31  			y: *fromBigInt(bigFromHex("79d0c8337072c93fef482bb055f44d6247ccac8e8e12525854b3566236337ebe")),
    32  		},
    33  	},
    34  	y: gfP4{
    35  		x: gfP2{
    36  			x: *fromBigInt(bigFromHex("082cde173022da8cd09b28a2d80a8cee53894436a52007f978dc37f36116d39b")),
    37  			y: *fromBigInt(bigFromHex("3fa7ed741eaed99a58f53e3df82df7ccd3407bcc7b1d44a9441920ced5fb824f")),
    38  		},
    39  		y: gfP2{
    40  			x: *fromBigInt(bigFromHex("7fc6eb2aa771d99c9234fddd31752edfd60723e05a4ebfdeb5c33fbd47e0cf06")),
    41  			y: *fromBigInt(bigFromHex("6fa6b6fa6dd6b6d3b19a959a110e748154eef796dc0fc2dd766ea414de786968")),
    42  		},
    43  	},
    44  	z: gfP4{
    45  		x: gfP2{
    46  			x: *fromBigInt(bigFromHex("8ffe1c0e9de45fd0fed790ac26be91f6b3f0a49c084fe29a3fb6ed288ad7994d")),
    47  			y: *fromBigInt(bigFromHex("1664a1366beb3196f0443e15f5f9042a947354a5678430d45ba031cff06db927")),
    48  		},
    49  		y: gfP2{
    50  			x: *fromBigInt(bigFromHex("7f7c6d52b475e6aaa827fdc5b4175ac6929320f782d998f86b6b57cda42a0426")),
    51  			y: *fromBigInt(bigFromHex("36a699de7c136f78eee2dbac4ca9727bff0cee02ee920f5822e65ea170aa9669")),
    52  		},
    53  	},
    54  }
    55  
    56  func (e *gfP12) String() string {
    57  	return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")"
    58  }
    59  
    60  func (e *gfP12) Set(a *gfP12) *gfP12 {
    61  	gfp12Copy(e, a)
    62  	return e
    63  }
    64  
    65  func (e *gfP12) SetZero() *gfP12 {
    66  	e.x.SetZero()
    67  	e.y.SetZero()
    68  	e.z.SetZero()
    69  	return e
    70  }
    71  
    72  func (e *gfP12) SetOne() *gfP12 {
    73  	e.x.SetZero()
    74  	e.y.SetZero()
    75  	e.z.SetOne()
    76  	return e
    77  }
    78  
    79  func (e *gfP12) SetW() *gfP12 {
    80  	e.x.SetZero()
    81  	e.y.SetOne()
    82  	e.z.SetZero()
    83  	return e
    84  }
    85  
    86  func (e *gfP12) SetW2() *gfP12 {
    87  	e.x.SetOne()
    88  	e.y.SetZero()
    89  	e.z.SetZero()
    90  	return e
    91  }
    92  
    93  func (e *gfP12) IsZero() bool {
    94  	return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
    95  }
    96  
    97  func (e *gfP12) IsOne() bool {
    98  	return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
    99  }
   100  
   101  func (e *gfP12) Add(a, b *gfP12) *gfP12 {
   102  	e.x.Add(&a.x, &b.x)
   103  	e.y.Add(&a.y, &b.y)
   104  	e.z.Add(&a.z, &b.z)
   105  	return e
   106  }
   107  
   108  func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
   109  	e.x.Sub(&a.x, &b.x)
   110  	e.y.Sub(&a.y, &b.y)
   111  	e.z.Sub(&a.z, &b.z)
   112  	return e
   113  }
   114  
   115  func (e *gfP12) MulScalar(a *gfP12, b *gfP4) *gfP12 {
   116  	e.x.Mul(&a.x, b)
   117  	e.y.Mul(&a.y, b)
   118  	e.z.Mul(&a.z, b)
   119  	return e
   120  }
   121  
   122  func (e *gfP12) MulGFP2(a *gfP12, b *gfP2) *gfP12 {
   123  	e.x.MulScalar(&a.x, b)
   124  	e.y.MulScalar(&a.y, b)
   125  	e.z.MulScalar(&a.z, b)
   126  	return e
   127  }
   128  
   129  func (e *gfP12) MulGFP(a *gfP12, b *gfP) *gfP12 {
   130  	e.x.MulGFP(&a.x, b)
   131  	e.y.MulGFP(&a.y, b)
   132  	e.z.MulGFP(&a.z, b)
   133  	return e
   134  }
   135  
   136  func (e *gfP12) Mul(a, b *gfP12) *gfP12 {
   137  	tmp := &gfP12{}
   138  	tmp.MulNC(a, b)
   139  	gfp12Copy(e, tmp)
   140  	return e
   141  }
   142  
   143  // Mul without value copy, will use e directly, so e can't be same as a and b.
   144  func (e *gfP12) MulNC(a, b *gfP12) *gfP12 {
   145  	// (z0 + y0*w + x0*w^2)* (z1 + y1*w + x1*w^2)
   146  	//  z0*z1 + z0*y1*w + z0*x1*w^2
   147  	// +y0*z1*w + y0*y1*w^2 + y0*x1*v
   148  	// +x0*z1*w^2 + x0*y1*v + x0*x1*v*w
   149  	//=(z0*z1+y0*x1*v+x0*y1*v) + (z0*y1+y0*z1+x0*x1*v)w + (z0*x1 + y0*y1 + x0*z1)*w^2
   150  	// Karatsuba method
   151  	tx := &e.x
   152  	ty := &e.y
   153  	tz := &e.z
   154  	t, v0, v1, v2 := &gfP4{}, &gfP4{}, &gfP4{}, &gfP4{}
   155  	v0.MulNC(&a.z, &b.z)
   156  	v1.MulNC(&a.y, &b.y)
   157  	v2.MulNC(&a.x, &b.x)
   158  
   159  	t.Add(&a.y, &a.x)
   160  	tz.Add(&b.y, &b.x)
   161  	t.Mul(t, tz)
   162  	t.Sub(t, v1)
   163  	t.Sub(t, v2)
   164  	t.MulV1(t)
   165  	tz.Add(t, v0)
   166  
   167  	t.Add(&a.z, &a.y)
   168  	ty.Add(&b.z, &b.y)
   169  	ty.Mul(t, ty)
   170  	ty.Sub(ty, v0)
   171  	ty.Sub(ty, v1)
   172  	t.MulV1(v2)
   173  	ty.Add(ty, t)
   174  
   175  	t.Add(&a.z, &a.x)
   176  	tx.Add(&b.z, &b.x)
   177  	tx.Mul(tx, t)
   178  	tx.Sub(tx, v0)
   179  	tx.Add(tx, v1)
   180  	tx.Sub(tx, v2)
   181  	return e
   182  }
   183  
   184  func (e *gfP12) Square(a *gfP12) *gfP12 {
   185  	tmp := &gfP12{}
   186  	tmp.SquareNC(a)
   187  	gfp12Copy(e, tmp)
   188  	return e
   189  }
   190  
   191  // Square without value copy, will use e directly, so e can't be same as a.
   192  func (e *gfP12) SquareNC(a *gfP12) *gfP12 {
   193  	// (z + y*w + x*w^2)* (z + y*w + x*w^2)
   194  	// z^2 + z*y*w + z*x*w^2 + y*z*w + y^2*w^2 + y*x*v + x*z*w^2 + x*y*v + x^2 *v *w
   195  	// (z^2 + y*x*v + x*y*v) + (z*y + y*z + v * x^2)w + (z*x + y^2 + x*z)*w^2
   196  	// (z^2 + 2*x*y*v) + (v*x^2 + 2*y*z) *w + (y^2 + 2*x*z) * w^2
   197  	// Karatsuba method
   198  	tx := &e.x
   199  	ty := &e.y
   200  	tz := &e.z
   201  	t, v0, v1, v2 := &gfP4{}, &gfP4{}, &gfP4{}, &gfP4{}
   202  	v0.SquareNC(&a.z)
   203  	v1.SquareNC(&a.y)
   204  	v2.SquareNC(&a.x)
   205  
   206  	t.Add(&a.y, &a.x)
   207  	tz.SquareNC(t)
   208  	tz.Sub(tz, v1)
   209  	tz.Sub(tz, v2)
   210  	tz.MulV1(tz)
   211  	tz.Add(tz, v0)
   212  
   213  	t.Add(&a.z, &a.y)
   214  	ty.SquareNC(t)
   215  	ty.Sub(ty, v0)
   216  	ty.Sub(ty, v1)
   217  	t.MulV1(v2)
   218  	ty.Add(ty, t)
   219  
   220  	t.Add(&a.z, &a.x)
   221  	tx.SquareNC(t)
   222  	tx.Sub(tx, v0)
   223  	tx.Add(tx, v1)
   224  	tx.Sub(tx, v2)
   225  
   226  	return e
   227  }
   228  
   229  // Cyclo6Square is used in final exponentiation after easy part(a ^ ((p^2 + 1)(p^6-1))).
   230  // Note that after the easy part of the final exponentiation, 
   231  // the resulting element lies in cyclotomic subgroup. 
   232  // "New software speed records for cryptographic pairings"
   233  // Section 3.3, Final exponentiation
   234  // https://cryptojedi.org/papers/dclxvi-20100714.pdf
   235  // The fomula reference:
   236  // Granger/Scott (PKC2010). 
   237  // Section 3.2
   238  // https://eprint.iacr.org/2009/565.pdf
   239  func (e *gfP12) Cyclo6Square(a *gfP12) *gfP12 {
   240  	tmp := &gfP12{}
   241  	tmp.Cyclo6SquareNC(a)
   242  	gfp12Copy(e, tmp)
   243  	return e
   244  }
   245  
   246  // Special squaring loop for use on elements in T_6(fp2) (after the
   247  // easy part of the final exponentiation. Used in the hard part
   248  // of the final exponentiation. Function uses formulas in
   249  // Granger/Scott (PKC2010).
   250  func (e *gfP12) Cyclo6Squares(a *gfP12, n int) *gfP12 {
   251  	// Square first round
   252  	in := &gfP12{}
   253  	tx, ty, tz := &gfP4{}, &gfP4{}, &gfP4{}
   254  
   255  	v0 := &in.x
   256  	v1 := &in.y
   257  	v2 := &in.z
   258  
   259  	v0.SquareVNC(&a.x) // (t02, t10)
   260  	v1.SquareNC(&a.y)  // (t12, t01)
   261  	v2.SquareNC(&a.z)  // (t11, t00)
   262  
   263  	tx.Triple(v0)
   264  	ty.Triple(v1)
   265  	tz.Triple(v2)
   266  
   267  	v0.Double(&a.x) // (f12, f01)
   268  	v0.y.Neg(&v0.y)
   269  	v1.Double(&a.y) // (f02, f10)
   270  	v1.x.Neg(&v1.x)
   271  	v2.Double(&a.z) // (f11, f00)
   272  	v2.y.Neg(&v2.y)
   273  
   274  	v0.Add(ty, v0)
   275  	v1.Add(tx, v1)
   276  	v2.Add(tz, v2)
   277  
   278  	tmp := &gfP12{}
   279  	var tmp2 *gfP12
   280  
   281  	for i := 1; i < n; i++ {
   282  		v0 = &tmp.x
   283  		v1 = &tmp.y
   284  		v2 = &tmp.z
   285  
   286  		v0.SquareVNC(&in.x) // (t02, t10)
   287  		v1.SquareNC(&in.y)  // (t12, t01)
   288  		v2.SquareNC(&in.z)  // (t11, t00)
   289  
   290  		tx.Triple(v0)
   291  		ty.Triple(v1)
   292  		tz.Triple(v2)
   293  
   294  		v0.Double(&in.x) // (f12, f01)
   295  		v0.y.Neg(&v0.y)
   296  		v1.Double(&in.y) // (f02, f10)
   297  		v1.x.Neg(&v1.x)
   298  		v2.Double(&in.z) // (f11, f00)
   299  		v2.y.Neg(&v2.y)
   300  
   301  		v0.Add(ty, v0)
   302  		v1.Add(tx, v1)
   303  		v2.Add(tz, v2)
   304  
   305  		// Switch references
   306  		tmp2 = in
   307  		in = tmp
   308  		tmp = tmp2
   309  	}
   310  	gfp12Copy(e, in)
   311  	return e
   312  }
   313  
   314  // Special Square without value copy, will use e directly, so e can't be same as a.
   315  func (e *gfP12) Cyclo6SquareNC(a *gfP12) *gfP12 {
   316  	tx, ty, tz := &gfP4{}, &gfP4{}, &gfP4{}
   317  
   318  	v0 := &e.x
   319  	v1 := &e.y
   320  	v2 := &e.z
   321  
   322  	v0.SquareVNC(&a.x) // (t02, t10)
   323  	v1.SquareNC(&a.y)  // (t12, t01)
   324  	v2.SquareNC(&a.z)  // (t11, t00)
   325  
   326  	tx.Triple(v0)
   327  	ty.Triple(v1)
   328  	tz.Triple(v2)
   329  
   330  	v0.Double(&a.x) // (f12, f01)
   331  	v0.y.Neg(&v0.y)
   332  	v1.Double(&a.y) // (f02, f10)
   333  	v1.x.Neg(&v1.x)
   334  	v2.Double(&a.z) // (f11, f00)
   335  	v2.y.Neg(&v2.y)
   336  
   337  	v0.Add(ty, v0)
   338  	v1.Add(tx, v1)
   339  	v2.Add(tz, v2)
   340  
   341  	return e
   342  }
   343  
   344  func (e *gfP12) Squares(a *gfP12, n int) *gfP12 {
   345  	// Square first round
   346  	in := &gfP12{}
   347  	tx := &in.x
   348  	ty := &in.y
   349  	tz := &in.z
   350  	t, v0, v1, v2 := &gfP4{}, &gfP4{}, &gfP4{}, &gfP4{}
   351  
   352  	v0.SquareNC(&a.z)
   353  	v1.SquareNC(&a.y)
   354  	v2.SquareNC(&a.x)
   355  
   356  	t.Add(&a.y, &a.x)
   357  	tz.SquareNC(t)
   358  	tz.Sub(tz, v1)
   359  	tz.Sub(tz, v2)
   360  	tz.MulV1(tz)
   361  	tz.Add(tz, v0)
   362  
   363  	t.Add(&a.z, &a.y)
   364  	ty.SquareNC(t)
   365  	ty.Sub(ty, v0)
   366  	ty.Sub(ty, v1)
   367  	t.MulV1(v2)
   368  	ty.Add(ty, t)
   369  
   370  	t.Add(&a.z, &a.x)
   371  	tx.SquareNC(t)
   372  	tx.Sub(tx, v0)
   373  	tx.Add(tx, v1)
   374  	tx.Sub(tx, v2)
   375  
   376  	tmp := &gfP12{}
   377  	var tmp2 *gfP12
   378  
   379  	for i := 1; i < n; i++ {
   380  		tx = &tmp.x
   381  		ty = &tmp.y
   382  		tz = &tmp.z
   383  
   384  		v0.SquareNC(&in.z)
   385  		v1.SquareNC(&in.y)
   386  		v2.SquareNC(&in.x)
   387  
   388  		t.Add(&in.y, &in.x)
   389  		tz.SquareNC(t)
   390  		tz.Sub(tz, v1)
   391  		tz.Sub(tz, v2)
   392  		tz.MulV1(tz)
   393  		tz.Add(tz, v0)
   394  
   395  		t.Add(&in.z, &in.y)
   396  		ty.SquareNC(t)
   397  		ty.Sub(ty, v0)
   398  		ty.Sub(ty, v1)
   399  		t.MulV1(v2)
   400  		ty.Add(ty, t)
   401  
   402  		t.Add(&in.z, &in.x)
   403  		tx.SquareNC(t)
   404  		tx.Sub(tx, v0)
   405  		tx.Add(tx, v1)
   406  		tx.Sub(tx, v2)
   407  
   408  		// Switch references
   409  		tmp2 = in
   410  		in = tmp
   411  		tmp = tmp2
   412  	}
   413  	gfp12Copy(e, in)
   414  	return e
   415  }
   416  
   417  func (e *gfP12) Exp(f *gfP12, power *big.Int) *gfP12 {
   418  	sum := (&gfP12{}).SetOne()
   419  	t := &gfP12{}
   420  
   421  	for i := power.BitLen() - 1; i >= 0; i-- {
   422  		t.Square(sum)
   423  		if power.Bit(i) != 0 {
   424  			sum.Mul(t, f)
   425  		} else {
   426  			sum.Set(t)
   427  		}
   428  	}
   429  	gfp12Copy(e, sum)
   430  	return e
   431  }
   432  
   433  func (e *gfP12) Invert(a *gfP12) *gfP12 {
   434  	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
   435  	// ftp://136.206.11.249/pub/crypto/pairings.pdf
   436  
   437  	// Here we can give a short explanation of how it works: let j be a cubic root of
   438  	// unity in GF(p^4) so that 1+j+j²=0.
   439  	// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
   440  	// = (xτ² + yτ + z)(Cτ²+Bτ+A)
   441  	// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
   442  	//
   443  	// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
   444  	// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
   445  	//
   446  	// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
   447  	t1 := (&gfP4{}).MulVNC(&a.x, &a.y)
   448  	A := (&gfP4{}).SquareNC(&a.z)
   449  	A.Sub(A, t1)
   450  
   451  	B := (&gfP4{}).SquareVNC(&a.x)
   452  	t1.Mul(&a.y, &a.z)
   453  	B.Sub(B, t1)
   454  
   455  	C := (&gfP4{}).SquareNC(&a.y)
   456  	t1.Mul(&a.x, &a.z)
   457  	C.Sub(C, t1)
   458  
   459  	F := (&gfP4{}).MulVNC(C, &a.y)
   460  	t1.Mul(A, &a.z)
   461  	F.Add(F, t1)
   462  	t1.MulV(B, &a.x)
   463  	F.Add(F, t1)
   464  
   465  	F.Invert(F)
   466  
   467  	e.x.Mul(C, F)
   468  	e.y.Mul(B, F)
   469  	e.z.Mul(A, F)
   470  	return e
   471  }
   472  
   473  func (e *gfP12) Neg(a *gfP12) *gfP12 {
   474  	e.x.Neg(&a.x)
   475  	e.y.Neg(&a.y)
   476  	e.z.Neg(&a.z)
   477  	return e
   478  }
   479  
   480  // (z + y*w + x*w^2)^p
   481  // = z^p + y^p*w*w^(p-1)+x^p*w^2*(w^2)^(p-1)
   482  // w2ToP2Minus1 = vToPMinus1 * wToPMinus1
   483  func (e *gfP12) Frobenius(a *gfP12) *gfP12 {
   484  	tmp := &gfP4{}
   485  	x := &tmp.x
   486  	y := &tmp.y
   487  
   488  	x.Conjugate(&a.z.x)
   489  	y.Conjugate(&a.z.y)
   490  	x.MulScalar(x, vToPMinus1)
   491  	gfp4Copy(&e.z, tmp)
   492  
   493  	x.Conjugate(&a.y.x)
   494  	y.Conjugate(&a.y.y)
   495  	x.MulScalar(x, w2ToP2Minus1)
   496  	y.MulScalar(y, wToPMinus1)
   497  	gfp4Copy(&e.y, tmp)
   498  
   499  	x.Conjugate(&a.x.x)
   500  	y.Conjugate(&a.x.y)
   501  	x.MulScalar(x, vToPMinus1Mw2ToPMinus1)
   502  	y.MulScalar(y, w2ToPMinus1)
   503  	gfp4Copy(&e.x, tmp)
   504  
   505  	return e
   506  }
   507  
   508  // (z + y*w + x*w^2)^(p^2)
   509  // = z^(p^2) + y^(p^2)*w*w^((p^2)-1)+x^(p^2)*w^2*(w^2)^((p^2)-1)
   510  func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 {
   511  	tx := &e.x
   512  	ty := &e.y
   513  	tz := &e.z
   514  
   515  	tz.Conjugate(&a.z)
   516  
   517  	ty.Conjugate(&a.y)
   518  	ty.MulGFP(ty, wToP2Minus1)
   519  
   520  	tx.Conjugate(&a.x)
   521  	tx.MulGFP(tx, w2ToP2Minus1)
   522  	return e
   523  }
   524  
   525  // (z + y*w + x*w^2)^(p^3)
   526  // =z^(p^3) + y^(p^3)*w*w^((p^3)-1)+x^(p^3)*w^2*(w^2)^((p^3)-1)
   527  // =z^(p^3) + y^(p^3)*w*vToPMinus1-x^(p^3)*w^2
   528  // vToPMinus1 * vToPMinus1 = -1
   529  func (e *gfP12) FrobeniusP3(a *gfP12) *gfP12 {
   530  	x, y := &gfP2{}, &gfP2{}
   531  
   532  	x.Conjugate(&a.z.x)
   533  	y.Conjugate(&a.z.y)
   534  	x.MulScalar(x, vToPMinus1)
   535  	x.Neg(x)
   536  	e.z.x.Set(x)
   537  	e.z.y.Set(y)
   538  
   539  	x.Conjugate(&a.y.x)
   540  	y.Conjugate(&a.y.y)
   541  	//x.MulScalar(x, vToPMinus1)
   542  	//x.Neg(x)
   543  	//x.MulScalar(x, vToPMinus1)
   544  	y.MulScalar(y, vToPMinus1)
   545  	e.y.x.Set(x)
   546  	e.y.y.Set(y)
   547  
   548  	x.Conjugate(&a.x.x)
   549  	y.Conjugate(&a.x.y)
   550  	x.MulScalar(x, vToPMinus1)
   551  	y.Neg(y)
   552  	e.x.x.Set(x)
   553  	e.x.y.Set(y)
   554  
   555  	return e
   556  }
   557  
   558  // (z + y*w + x*w^2)^(p^6)
   559  // = ((z + y*w + x*w^2)^(p^3))^(p^3)
   560  func (e *gfP12) FrobeniusP6(a *gfP12) *gfP12 {
   561  	tx := &e.x
   562  	ty := &e.y
   563  	tz := &e.z
   564  
   565  	tz.Conjugate(&a.z)
   566  
   567  	ty.Conjugate(&a.y)
   568  	ty.Neg(ty)
   569  
   570  	tx.Conjugate(&a.x)
   571  
   572  	return e
   573  }
   574  
   575  // code logic from https://github.com/miracl/MIRACL/blob/master/source/curve/pairing/zzn12a.h
   576  func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
   577  	e.z.Conjugate(&a.z)
   578  	e.y.Conjugate(&a.y)
   579  	e.y.Neg(&e.y)
   580  	e.x.Conjugate(&a.x)
   581  	return e
   582  }
   583  
   584  // Select sets q to p1 if cond == 1, and to p2 if cond == 0.
   585  func (q *gfP12) Select(p1, p2 *gfP12, cond int) *gfP12 {
   586  	q.x.Select(&p1.x, &p2.x, cond)
   587  	q.y.Select(&p1.y, &p2.y, cond)
   588  	q.z.Select(&p1.z, &p2.z, cond)
   589  	return q
   590  }