github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-381/internal/fptower/e12.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  	"errors"
    21  	"github.com/consensys/gnark-crypto/ecc"
    22  	"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
    23  	"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
    24  	"math/big"
    25  	"sync"
    26  )
    27  
    28  var bigIntPool = sync.Pool{
    29  	New: func() interface{} {
    30  		return new(big.Int)
    31  	},
    32  }
    33  
    34  // E12 is a degree two finite field extension of fp6
    35  type E12 struct {
    36  	C0, C1 E6
    37  }
    38  
    39  // Equal returns true if z equals x, false otherwise
    40  func (z *E12) Equal(x *E12) bool {
    41  	return z.C0.Equal(&x.C0) && z.C1.Equal(&x.C1)
    42  }
    43  
    44  // String puts E12 in string form
    45  func (z *E12) String() string {
    46  	return (z.C0.String() + "+(" + z.C1.String() + ")*w")
    47  }
    48  
    49  // SetString sets a E12 from string
    50  func (z *E12) SetString(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 string) *E12 {
    51  	z.C0.SetString(s0, s1, s2, s3, s4, s5)
    52  	z.C1.SetString(s6, s7, s8, s9, s10, s11)
    53  	return z
    54  }
    55  
    56  // Set copies x into z and returns z
    57  func (z *E12) Set(x *E12) *E12 {
    58  	z.C0 = x.C0
    59  	z.C1 = x.C1
    60  	return z
    61  }
    62  
    63  // SetOne sets z to 1 in Montgomery form and returns z
    64  func (z *E12) SetOne() *E12 {
    65  	*z = E12{}
    66  	z.C0.B0.A0.SetOne()
    67  	return z
    68  }
    69  
    70  // Add sets z=x+y in E12 and returns z
    71  func (z *E12) Add(x, y *E12) *E12 {
    72  	z.C0.Add(&x.C0, &y.C0)
    73  	z.C1.Add(&x.C1, &y.C1)
    74  	return z
    75  }
    76  
    77  // Sub sets z to x-y and returns z
    78  func (z *E12) Sub(x, y *E12) *E12 {
    79  	z.C0.Sub(&x.C0, &y.C0)
    80  	z.C1.Sub(&x.C1, &y.C1)
    81  	return z
    82  }
    83  
    84  // Double sets z=2*x and returns z
    85  func (z *E12) Double(x *E12) *E12 {
    86  	z.C0.Double(&x.C0)
    87  	z.C1.Double(&x.C1)
    88  	return z
    89  }
    90  
    91  // SetRandom used only in tests
    92  func (z *E12) SetRandom() (*E12, error) {
    93  	if _, err := z.C0.SetRandom(); err != nil {
    94  		return nil, err
    95  	}
    96  	if _, err := z.C1.SetRandom(); err != nil {
    97  		return nil, err
    98  	}
    99  	return z, nil
   100  }
   101  
   102  // IsZero returns true if z is zero, false otherwise
   103  func (z *E12) IsZero() bool {
   104  	return z.C0.IsZero() && z.C1.IsZero()
   105  }
   106  
   107  // IsOne returns true if z is one, false otherwise
   108  func (z *E12) IsOne() bool {
   109  	return z.C0.IsOne() && z.C1.IsZero()
   110  }
   111  
   112  // Mul sets z=x*y in E12 and returns z
   113  func (z *E12) Mul(x, y *E12) *E12 {
   114  	var a, b, c E6
   115  	a.Add(&x.C0, &x.C1)
   116  	b.Add(&y.C0, &y.C1)
   117  	a.Mul(&a, &b)
   118  	b.Mul(&x.C0, &y.C0)
   119  	c.Mul(&x.C1, &y.C1)
   120  	z.C1.Sub(&a, &b).Sub(&z.C1, &c)
   121  	z.C0.MulByNonResidue(&c).Add(&z.C0, &b)
   122  	return z
   123  }
   124  
   125  // Square sets z=x*x in E12 and returns z
   126  func (z *E12) Square(x *E12) *E12 {
   127  
   128  	//Algorithm 22 from https://eprint.iacr.org/2010/354.pdf
   129  	var c0, c2, c3 E6
   130  	c0.Sub(&x.C0, &x.C1)
   131  	c3.MulByNonResidue(&x.C1).Neg(&c3).Add(&x.C0, &c3)
   132  	c2.Mul(&x.C0, &x.C1)
   133  	c0.Mul(&c0, &c3).Add(&c0, &c2)
   134  	z.C1.Double(&c2)
   135  	c2.MulByNonResidue(&c2)
   136  	z.C0.Add(&c0, &c2)
   137  
   138  	return z
   139  }
   140  
   141  // Karabina's compressed cyclotomic square
   142  // https://eprint.iacr.org/2010/542.pdf
   143  // Th. 3.2 with minor modifications to fit our tower
   144  func (z *E12) CyclotomicSquareCompressed(x *E12) *E12 {
   145  
   146  	var t [7]E2
   147  
   148  	// t0 = g1^2
   149  	t[0].Square(&x.C0.B1)
   150  	// t1 = g5^2
   151  	t[1].Square(&x.C1.B2)
   152  	// t5 = g1 + g5
   153  	t[5].Add(&x.C0.B1, &x.C1.B2)
   154  	// t2 = (g1 + g5)^2
   155  	t[2].Square(&t[5])
   156  
   157  	// t3 = g1^2 + g5^2
   158  	t[3].Add(&t[0], &t[1])
   159  	// t5 = 2 * g1 * g5
   160  	t[5].Sub(&t[2], &t[3])
   161  
   162  	// t6 = g3 + g2
   163  	t[6].Add(&x.C1.B0, &x.C0.B2)
   164  	// t3 = (g3 + g2)^2
   165  	t[3].Square(&t[6])
   166  	// t2 = g3^2
   167  	t[2].Square(&x.C1.B0)
   168  
   169  	// t6 = 2 * nr * g1 * g5
   170  	t[6].MulByNonResidue(&t[5])
   171  	// t5 = 4 * nr * g1 * g5 + 2 * g3
   172  	t[5].Add(&t[6], &x.C1.B0).
   173  		Double(&t[5])
   174  	// z3 = 6 * nr * g1 * g5 + 2 * g3
   175  	z.C1.B0.Add(&t[5], &t[6])
   176  
   177  	// t4 = nr * g5^2
   178  	t[4].MulByNonResidue(&t[1])
   179  	// t5 = nr * g5^2 + g1^2
   180  	t[5].Add(&t[0], &t[4])
   181  	// t6 = nr * g5^2 + g1^2 - g2
   182  	t[6].Sub(&t[5], &x.C0.B2)
   183  
   184  	// t1 = g2^2
   185  	t[1].Square(&x.C0.B2)
   186  
   187  	// t6 = 2 * nr * g5^2 + 2 * g1^2 - 2*g2
   188  	t[6].Double(&t[6])
   189  	// z2 = 3 * nr * g5^2 + 3 * g1^2 - 2*g2
   190  	z.C0.B2.Add(&t[6], &t[5])
   191  
   192  	// t4 = nr * g2^2
   193  	t[4].MulByNonResidue(&t[1])
   194  	// t5 = g3^2 + nr * g2^2
   195  	t[5].Add(&t[2], &t[4])
   196  	// t6 = g3^2 + nr * g2^2 - g1
   197  	t[6].Sub(&t[5], &x.C0.B1)
   198  	// t6 = 2 * g3^2 + 2 * nr * g2^2 - 2 * g1
   199  	t[6].Double(&t[6])
   200  	// z1 = 3 * g3^2 + 3 * nr * g2^2 - 2 * g1
   201  	z.C0.B1.Add(&t[6], &t[5])
   202  
   203  	// t0 = g2^2 + g3^2
   204  	t[0].Add(&t[2], &t[1])
   205  	// t5 = 2 * g3 * g2
   206  	t[5].Sub(&t[3], &t[0])
   207  	// t6 = 2 * g3 * g2 + g5
   208  	t[6].Add(&t[5], &x.C1.B2)
   209  	// t6 = 4 * g3 * g2 + 2 * g5
   210  	t[6].Double(&t[6])
   211  	// z5 = 6 * g3 * g2 + 2 * g5
   212  	z.C1.B2.Add(&t[5], &t[6])
   213  
   214  	return z
   215  }
   216  
   217  // DecompressKarabina Karabina's cyclotomic square result
   218  // if g3 != 0
   219  //
   220  //	g4 = (E * g5^2 + 3 * g1^2 - 2 * g2)/4g3
   221  //
   222  // if g3 == 0
   223  //
   224  //	g4 = 2g1g5/g2
   225  //
   226  // if g3=g2=0 then g4=g5=g1=0 and g0=1 (x=1)
   227  // Theorem 3.1 is well-defined for all x in Gϕₙ\{1}
   228  func (z *E12) DecompressKarabina(x *E12) *E12 {
   229  
   230  	var t [3]E2
   231  	var one E2
   232  	one.SetOne()
   233  
   234  	if x.C1.B2.IsZero() /* g3 == 0 */ {
   235  		t[0].Mul(&x.C0.B1, &x.C1.B2).
   236  			Double(&t[0])
   237  		// t1 = g2
   238  		t[1].Set(&x.C0.B2)
   239  
   240  		if t[1].IsZero() /* g2 == g3 == 0 */ {
   241  			return z.SetOne()
   242  		}
   243  	} else /* g3 != 0 */ {
   244  
   245  		// t0 = g1^2
   246  		t[0].Square(&x.C0.B1)
   247  		// t1 = 3 * g1^2 - 2 * g2
   248  		t[1].Sub(&t[0], &x.C0.B2).
   249  			Double(&t[1]).
   250  			Add(&t[1], &t[0])
   251  			// t0 = E * g5^2 + t1
   252  		t[2].Square(&x.C1.B2)
   253  		t[0].MulByNonResidue(&t[2]).
   254  			Add(&t[0], &t[1])
   255  		// t1 = 4 * g3
   256  		t[1].Double(&x.C1.B0).
   257  			Double(&t[1])
   258  	}
   259  
   260  	// z4 = g4
   261  	z.C1.B1.Div(&t[0], &t[1]) // costly
   262  
   263  	// t1 = g2 * g1
   264  	t[1].Mul(&x.C0.B2, &x.C0.B1)
   265  	// t2 = 2 * g4^2 - 3 * g2 * g1
   266  	t[2].Square(&z.C1.B1).
   267  		Sub(&t[2], &t[1]).
   268  		Double(&t[2]).
   269  		Sub(&t[2], &t[1])
   270  	// t1 = g3 * g5 (g3 can be 0)
   271  	t[1].Mul(&x.C1.B0, &x.C1.B2)
   272  	// c_0 = E * (2 * g4^2 + g3 * g5 - 3 * g2 * g1) + 1
   273  	t[2].Add(&t[2], &t[1])
   274  	z.C0.B0.MulByNonResidue(&t[2]).
   275  		Add(&z.C0.B0, &one)
   276  
   277  	z.C0.B1.Set(&x.C0.B1)
   278  	z.C0.B2.Set(&x.C0.B2)
   279  	z.C1.B0.Set(&x.C1.B0)
   280  	z.C1.B2.Set(&x.C1.B2)
   281  
   282  	return z
   283  }
   284  
   285  // BatchDecompressKarabina multiple Karabina's cyclotomic square results
   286  // if g3 != 0
   287  //
   288  //	g4 = (E * g5^2 + 3 * g1^2 - 2 * g2)/4g3
   289  //
   290  // if g3 == 0
   291  //
   292  //	g4 = 2g1g5/g2
   293  //
   294  // if g3=g2=0 then g4=g5=g1=0 and g0=1 (x=1)
   295  // Theorem 3.1 is well-defined for all x in Gϕₙ\{1}
   296  //
   297  // Divisions by 4g3 or g2 is batched using Montgomery batch inverse
   298  func BatchDecompressKarabina(x []E12) []E12 {
   299  
   300  	n := len(x)
   301  	if n == 0 {
   302  		return x
   303  	}
   304  
   305  	t0 := make([]E2, n)
   306  	t1 := make([]E2, n)
   307  	t2 := make([]E2, n)
   308  	zeroes := make([]bool, n)
   309  
   310  	var one E2
   311  	one.SetOne()
   312  
   313  	for i := 0; i < n; i++ {
   314  		if x[i].C1.B2.IsZero() /* g3 == 0 */ {
   315  			t0[i].Mul(&x[i].C0.B1, &x[i].C1.B2).
   316  				Double(&t0[i])
   317  			// t1 = g2
   318  			t1[i].Set(&x[i].C0.B2)
   319  
   320  			if t1[i].IsZero() /* g3 == g2 == 0 */ {
   321  				x[i].SetOne()
   322  				zeroes[i] = true
   323  				continue
   324  			}
   325  		} else /* g3 != 0 */ {
   326  			// t0 = g1^2
   327  			t0[i].Square(&x[i].C0.B1)
   328  			// t1 = 3 * g1^2 - 2 * g2
   329  			t1[i].Sub(&t0[i], &x[i].C0.B2).
   330  				Double(&t1[i]).
   331  				Add(&t1[i], &t0[i])
   332  				// t0 = E * g5^2 + t1
   333  			t2[i].Square(&x[i].C1.B2)
   334  			t0[i].MulByNonResidue(&t2[i]).
   335  				Add(&t0[i], &t1[i])
   336  			// t1 = 4 * g3
   337  			t1[i].Double(&x[i].C1.B0).
   338  				Double(&t1[i])
   339  		}
   340  	}
   341  
   342  	t1 = BatchInvertE2(t1) // costs 1 inverse
   343  
   344  	for i := 0; i < n; i++ {
   345  		if zeroes[i] {
   346  			continue
   347  		}
   348  
   349  		// z4 = g4
   350  		x[i].C1.B1.Mul(&t0[i], &t1[i])
   351  
   352  		// t1 = g2 * g1
   353  		t1[i].Mul(&x[i].C0.B2, &x[i].C0.B1)
   354  		// t2 = 2 * g4^2 - 3 * g2 * g1
   355  		t2[i].Square(&x[i].C1.B1)
   356  		t2[i].Sub(&t2[i], &t1[i])
   357  		t2[i].Double(&t2[i])
   358  		t2[i].Sub(&t2[i], &t1[i])
   359  
   360  		// t1 = g3 * g5 (g3s can be 0s)
   361  		t1[i].Mul(&x[i].C1.B0, &x[i].C1.B2)
   362  		// z0 = E * (2 * g4^2 + g3 * g5 - 3 * g2 * g1) + 1
   363  		t2[i].Add(&t2[i], &t1[i])
   364  		x[i].C0.B0.MulByNonResidue(&t2[i]).
   365  			Add(&x[i].C0.B0, &one)
   366  	}
   367  
   368  	return x
   369  }
   370  
   371  // Granger-Scott's cyclotomic square
   372  // https://eprint.iacr.org/2009/565.pdf, 3.2
   373  func (z *E12) CyclotomicSquare(x *E12) *E12 {
   374  
   375  	// x=(x0,x1,x2,x3,x4,x5,x6,x7) in E2^6
   376  	// cyclosquare(x)=(3*x4^2*u + 3*x0^2 - 2*x0,
   377  	//					3*x2^2*u + 3*x3^2 - 2*x1,
   378  	//					3*x5^2*u + 3*x1^2 - 2*x2,
   379  	//					6*x1*x5*u + 2*x3,
   380  	//					6*x0*x4 + 2*x4,
   381  	//					6*x2*x3 + 2*x5)
   382  
   383  	var t [9]E2
   384  
   385  	t[0].Square(&x.C1.B1)
   386  	t[1].Square(&x.C0.B0)
   387  	t[6].Add(&x.C1.B1, &x.C0.B0).Square(&t[6]).Sub(&t[6], &t[0]).Sub(&t[6], &t[1]) // 2*x4*x0
   388  	t[2].Square(&x.C0.B2)
   389  	t[3].Square(&x.C1.B0)
   390  	t[7].Add(&x.C0.B2, &x.C1.B0).Square(&t[7]).Sub(&t[7], &t[2]).Sub(&t[7], &t[3]) // 2*x2*x3
   391  	t[4].Square(&x.C1.B2)
   392  	t[5].Square(&x.C0.B1)
   393  	t[8].Add(&x.C1.B2, &x.C0.B1).Square(&t[8]).Sub(&t[8], &t[4]).Sub(&t[8], &t[5]).MulByNonResidue(&t[8]) // 2*x5*x1*u
   394  
   395  	t[0].MulByNonResidue(&t[0]).Add(&t[0], &t[1]) // x4^2*u + x0^2
   396  	t[2].MulByNonResidue(&t[2]).Add(&t[2], &t[3]) // x2^2*u + x3^2
   397  	t[4].MulByNonResidue(&t[4]).Add(&t[4], &t[5]) // x5^2*u + x1^2
   398  
   399  	z.C0.B0.Sub(&t[0], &x.C0.B0).Double(&z.C0.B0).Add(&z.C0.B0, &t[0])
   400  	z.C0.B1.Sub(&t[2], &x.C0.B1).Double(&z.C0.B1).Add(&z.C0.B1, &t[2])
   401  	z.C0.B2.Sub(&t[4], &x.C0.B2).Double(&z.C0.B2).Add(&z.C0.B2, &t[4])
   402  
   403  	z.C1.B0.Add(&t[8], &x.C1.B0).Double(&z.C1.B0).Add(&z.C1.B0, &t[8])
   404  	z.C1.B1.Add(&t[6], &x.C1.B1).Double(&z.C1.B1).Add(&z.C1.B1, &t[6])
   405  	z.C1.B2.Add(&t[7], &x.C1.B2).Double(&z.C1.B2).Add(&z.C1.B2, &t[7])
   406  
   407  	return z
   408  }
   409  
   410  // Inverse sets z to the inverse of x in E12 and returns z
   411  //
   412  // if x == 0, sets and returns z = x
   413  func (z *E12) Inverse(x *E12) *E12 {
   414  	// Algorithm 23 from https://eprint.iacr.org/2010/354.pdf
   415  
   416  	var t0, t1, tmp E6
   417  	t0.Square(&x.C0)
   418  	t1.Square(&x.C1)
   419  	tmp.MulByNonResidue(&t1)
   420  	t0.Sub(&t0, &tmp)
   421  	t1.Inverse(&t0)
   422  	z.C0.Mul(&x.C0, &t1)
   423  	z.C1.Mul(&x.C1, &t1).Neg(&z.C1)
   424  
   425  	return z
   426  }
   427  
   428  // BatchInvertE12 returns a new slice with every element in a inverted.
   429  // It uses Montgomery batch inversion trick.
   430  //
   431  // if a[i] == 0, returns result[i] = a[i]
   432  func BatchInvertE12(a []E12) []E12 {
   433  	res := make([]E12, len(a))
   434  	if len(a) == 0 {
   435  		return res
   436  	}
   437  
   438  	zeroes := make([]bool, len(a))
   439  	var accumulator E12
   440  	accumulator.SetOne()
   441  
   442  	for i := 0; i < len(a); i++ {
   443  		if a[i].IsZero() {
   444  			zeroes[i] = true
   445  			continue
   446  		}
   447  		res[i].Set(&accumulator)
   448  		accumulator.Mul(&accumulator, &a[i])
   449  	}
   450  
   451  	accumulator.Inverse(&accumulator)
   452  
   453  	for i := len(a) - 1; i >= 0; i-- {
   454  		if zeroes[i] {
   455  			continue
   456  		}
   457  		res[i].Mul(&res[i], &accumulator)
   458  		accumulator.Mul(&accumulator, &a[i])
   459  	}
   460  
   461  	return res
   462  }
   463  
   464  // Exp sets z=xᵏ (mod q¹²) and returns it
   465  // uses 2-bits windowed method
   466  func (z *E12) Exp(x E12, k *big.Int) *E12 {
   467  	if k.IsUint64() && k.Uint64() == 0 {
   468  		return z.SetOne()
   469  	}
   470  
   471  	e := k
   472  	if k.Sign() == -1 {
   473  		// negative k, we invert
   474  		// if k < 0: xᵏ (mod q¹²) == (x⁻¹)ᵏ (mod q¹²)
   475  		x.Inverse(&x)
   476  
   477  		// we negate k in a temp big.Int since
   478  		// Int.Bit(_) of k and -k is different
   479  		e = bigIntPool.Get().(*big.Int)
   480  		defer bigIntPool.Put(e)
   481  		e.Neg(k)
   482  	}
   483  
   484  	var res E12
   485  	var ops [3]E12
   486  
   487  	res.SetOne()
   488  	ops[0].Set(&x)
   489  	ops[1].Square(&ops[0])
   490  	ops[2].Set(&ops[0]).Mul(&ops[2], &ops[1])
   491  
   492  	b := e.Bytes()
   493  	for i := range b {
   494  		w := b[i]
   495  		mask := byte(0xc0)
   496  		for j := 0; j < 4; j++ {
   497  			res.Square(&res).Square(&res)
   498  			c := (w & mask) >> (6 - 2*j)
   499  			if c != 0 {
   500  				res.Mul(&res, &ops[c-1])
   501  			}
   502  			mask = mask >> 2
   503  		}
   504  	}
   505  	z.Set(&res)
   506  
   507  	return z
   508  }
   509  
   510  // CyclotomicExp sets z=xᵏ (mod q¹²) and returns it
   511  // uses 2-NAF decomposition
   512  // x must be in the cyclotomic subgroup
   513  // TODO: use a windowed method
   514  func (z *E12) CyclotomicExp(x E12, k *big.Int) *E12 {
   515  	if k.IsUint64() && k.Uint64() == 0 {
   516  		return z.SetOne()
   517  	}
   518  
   519  	e := k
   520  	if k.Sign() == -1 {
   521  		// negative k, we invert (=conjugate)
   522  		// if k < 0: xᵏ (mod q¹²) == (x⁻¹)ᵏ (mod q¹²)
   523  		x.Conjugate(&x)
   524  
   525  		// we negate k in a temp big.Int since
   526  		// Int.Bit(_) of k and -k is different
   527  		e = bigIntPool.Get().(*big.Int)
   528  		defer bigIntPool.Put(e)
   529  		e.Neg(k)
   530  	}
   531  
   532  	var res, xInv E12
   533  	xInv.InverseUnitary(&x)
   534  	res.SetOne()
   535  	eNAF := make([]int8, e.BitLen()+3)
   536  	n := ecc.NafDecomposition(e, eNAF[:])
   537  	for i := n - 1; i >= 0; i-- {
   538  		res.CyclotomicSquare(&res)
   539  		if eNAF[i] == 1 {
   540  			res.Mul(&res, &x)
   541  		} else if eNAF[i] == -1 {
   542  			res.Mul(&res, &xInv)
   543  		}
   544  	}
   545  	z.Set(&res)
   546  	return z
   547  }
   548  
   549  // ExpGLV sets z=xᵏ (q¹²) and returns it
   550  // uses 2-dimensional GLV with 2-bits windowed method
   551  // x must be in GT
   552  // TODO: use 2-NAF
   553  // TODO: use higher dimensional decomposition
   554  func (z *E12) ExpGLV(x E12, k *big.Int) *E12 {
   555  	if k.IsUint64() && k.Uint64() == 0 {
   556  		return z.SetOne()
   557  	}
   558  
   559  	e := k
   560  	if k.Sign() == -1 {
   561  		// negative k, we invert (=conjugate)
   562  		// if k < 0: xᵏ (mod q¹²) == (x⁻¹)ᵏ (mod q¹²)
   563  		x.Conjugate(&x)
   564  
   565  		// we negate k in a temp big.Int since
   566  		// Int.Bit(_) of k and -k is different
   567  		e = bigIntPool.Get().(*big.Int)
   568  		defer bigIntPool.Put(e)
   569  		e.Neg(k)
   570  	}
   571  
   572  	var table [15]E12
   573  	var res E12
   574  	var s1, s2 fr.Element
   575  
   576  	res.SetOne()
   577  
   578  	// table[b3b2b1b0-1] = b3b2*Frobinius(x) + b1b0*x
   579  	table[0].Set(&x)
   580  	table[3].Frobenius(&x)
   581  
   582  	// split the scalar, modifies ±x, Frob(x) accordingly
   583  	s := ecc.SplitScalar(e, &glvBasis)
   584  
   585  	if s[0].Sign() == -1 {
   586  		s[0].Neg(&s[0])
   587  		table[0].InverseUnitary(&table[0])
   588  	}
   589  	if s[1].Sign() == -1 {
   590  		s[1].Neg(&s[1])
   591  		table[3].InverseUnitary(&table[3])
   592  	}
   593  
   594  	// precompute table (2 bits sliding window)
   595  	// table[b3b2b1b0-1] = b3b2*Frobenius(x) + b1b0*x if b3b2b1b0 != 0
   596  	table[1].CyclotomicSquare(&table[0])
   597  	table[2].Mul(&table[1], &table[0])
   598  	table[4].Mul(&table[3], &table[0])
   599  	table[5].Mul(&table[3], &table[1])
   600  	table[6].Mul(&table[3], &table[2])
   601  	table[7].CyclotomicSquare(&table[3])
   602  	table[8].Mul(&table[7], &table[0])
   603  	table[9].Mul(&table[7], &table[1])
   604  	table[10].Mul(&table[7], &table[2])
   605  	table[11].Mul(&table[7], &table[3])
   606  	table[12].Mul(&table[11], &table[0])
   607  	table[13].Mul(&table[11], &table[1])
   608  	table[14].Mul(&table[11], &table[2])
   609  
   610  	// bounds on the lattice base vectors guarantee that s1, s2 are len(r)/2 bits long max
   611  	s1 = s1.SetBigInt(&s[0]).Bits()
   612  	s2 = s2.SetBigInt(&s[1]).Bits()
   613  
   614  	maxBit := s1.BitLen()
   615  	if s2.BitLen() > maxBit {
   616  		maxBit = s2.BitLen()
   617  	}
   618  	hiWordIndex := (maxBit - 1) / 64
   619  
   620  	// loop starts from len(s1)/2 due to the bounds
   621  	for i := hiWordIndex; i >= 0; i-- {
   622  		mask := uint64(3) << 62
   623  		for j := 0; j < 32; j++ {
   624  			res.CyclotomicSquare(&res).CyclotomicSquare(&res)
   625  			b1 := (s1[i] & mask) >> (62 - 2*j)
   626  			b2 := (s2[i] & mask) >> (62 - 2*j)
   627  			if b1|b2 != 0 {
   628  				s := (b2<<2 | b1)
   629  				res.Mul(&res, &table[s-1])
   630  			}
   631  			mask = mask >> 2
   632  		}
   633  	}
   634  
   635  	z.Set(&res)
   636  	return z
   637  }
   638  
   639  // InverseUnitary inverses a unitary element
   640  func (z *E12) InverseUnitary(x *E12) *E12 {
   641  	return z.Conjugate(x)
   642  }
   643  
   644  // Conjugate sets z to x conjugated and returns z
   645  func (z *E12) Conjugate(x *E12) *E12 {
   646  	*z = *x
   647  	z.C1.Neg(&z.C1)
   648  	return z
   649  }
   650  
   651  // SizeOfGT represents the size in bytes that a GT element need in binary form
   652  const SizeOfGT = 48 * 12
   653  
   654  // Marshal converts z to a byte slice
   655  func (z *E12) Marshal() []byte {
   656  	b := z.Bytes()
   657  	return b[:]
   658  }
   659  
   660  // Unmarshal is an alias to SetBytes()
   661  func (z *E12) Unmarshal(buf []byte) error {
   662  	return z.SetBytes(buf)
   663  }
   664  
   665  // Bytes returns the regular (non montgomery) value
   666  // of z as a big-endian byte array.
   667  // z.C1.B2.A1 | z.C1.B2.A0 | z.C1.B1.A1 | ...
   668  func (z *E12) Bytes() (r [SizeOfGT]byte) {
   669  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[528:528+fp.Bytes]), z.C0.B0.A0)
   670  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[480:480+fp.Bytes]), z.C0.B0.A1)
   671  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[432:432+fp.Bytes]), z.C0.B1.A0)
   672  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[384:384+fp.Bytes]), z.C0.B1.A1)
   673  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[336:336+fp.Bytes]), z.C0.B2.A0)
   674  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[288:288+fp.Bytes]), z.C0.B2.A1)
   675  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[240:240+fp.Bytes]), z.C1.B0.A0)
   676  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[192:192+fp.Bytes]), z.C1.B0.A1)
   677  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[144:144+fp.Bytes]), z.C1.B1.A0)
   678  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[96:96+fp.Bytes]), z.C1.B1.A1)
   679  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[48:48+fp.Bytes]), z.C1.B2.A0)
   680  	fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[0:0+fp.Bytes]), z.C1.B2.A1)
   681  
   682  	return
   683  }
   684  
   685  // SetBytes interprets e as the bytes of a big-endian GT
   686  // sets z to that value (in Montgomery form), and returns z.
   687  // size(e) == 48 * 12
   688  // z.C1.B2.A1 | z.C1.B2.A0 | z.C1.B1.A1 | ...
   689  func (z *E12) SetBytes(e []byte) error {
   690  	if len(e) != SizeOfGT {
   691  		return errors.New("invalid buffer size")
   692  	}
   693  	if err := z.C0.B0.A0.SetBytesCanonical(e[528 : 528+fp.Bytes]); err != nil {
   694  		return err
   695  	}
   696  	if err := z.C0.B0.A1.SetBytesCanonical(e[480 : 480+fp.Bytes]); err != nil {
   697  		return err
   698  	}
   699  	if err := z.C0.B1.A0.SetBytesCanonical(e[432 : 432+fp.Bytes]); err != nil {
   700  		return err
   701  	}
   702  	if err := z.C0.B1.A1.SetBytesCanonical(e[384 : 384+fp.Bytes]); err != nil {
   703  		return err
   704  	}
   705  	if err := z.C0.B2.A0.SetBytesCanonical(e[336 : 336+fp.Bytes]); err != nil {
   706  		return err
   707  	}
   708  	if err := z.C0.B2.A1.SetBytesCanonical(e[288 : 288+fp.Bytes]); err != nil {
   709  		return err
   710  	}
   711  	if err := z.C1.B0.A0.SetBytesCanonical(e[240 : 240+fp.Bytes]); err != nil {
   712  		return err
   713  	}
   714  	if err := z.C1.B0.A1.SetBytesCanonical(e[192 : 192+fp.Bytes]); err != nil {
   715  		return err
   716  	}
   717  	if err := z.C1.B1.A0.SetBytesCanonical(e[144 : 144+fp.Bytes]); err != nil {
   718  		return err
   719  	}
   720  	if err := z.C1.B1.A1.SetBytesCanonical(e[96 : 96+fp.Bytes]); err != nil {
   721  		return err
   722  	}
   723  	if err := z.C1.B2.A0.SetBytesCanonical(e[48 : 48+fp.Bytes]); err != nil {
   724  		return err
   725  	}
   726  	if err := z.C1.B2.A1.SetBytesCanonical(e[0 : 0+fp.Bytes]); err != nil {
   727  		return err
   728  	}
   729  
   730  	return nil
   731  }
   732  
   733  // IsInSubGroup ensures GT/E12 is in correct subgroup
   734  func (z *E12) IsInSubGroup() bool {
   735  	var a, b E12
   736  
   737  	// check z^(phi_k(p)) == 1
   738  	a.FrobeniusSquare(z)
   739  	b.FrobeniusSquare(&a).Mul(&b, z)
   740  
   741  	if !a.Equal(&b) {
   742  		return false
   743  	}
   744  
   745  	// check z^(p+1-t) == 1
   746  	a.Frobenius(z)
   747  	b.Expt(z)
   748  
   749  	return a.Equal(&b)
   750  }
   751  
   752  // CompressTorus GT/E12 element to half its size
   753  // z must be in the cyclotomic subgroup
   754  // i.e. z^(p^4-p^2+1)=1
   755  // e.g. GT
   756  // "COMPRESSION IN FINITE FIELDS AND TORUS-BASED CRYPTOGRAPHY", K. RUBIN AND A. SILVERBERG
   757  // z.C1 == 0 only when z \in {-1,1}
   758  func (z *E12) CompressTorus() (E6, error) {
   759  
   760  	if z.C1.IsZero() {
   761  		return E6{}, errors.New("invalid input")
   762  	}
   763  
   764  	var res, tmp, one E6
   765  	one.SetOne()
   766  	tmp.Inverse(&z.C1)
   767  	res.Add(&z.C0, &one).
   768  		Mul(&res, &tmp)
   769  
   770  	return res, nil
   771  }
   772  
   773  // BatchCompressTorus GT/E12 elements to half their size using a batch inversion.
   774  //
   775  // if len(x) == 0 or if any of the x[i].C1 coordinate is 0, this function returns an error.
   776  func BatchCompressTorus(x []E12) ([]E6, error) {
   777  
   778  	n := len(x)
   779  	if n == 0 {
   780  		return nil, errors.New("invalid input size")
   781  	}
   782  
   783  	var one E6
   784  	one.SetOne()
   785  	res := make([]E6, n)
   786  
   787  	for i := 0; i < n; i++ {
   788  		res[i].Set(&x[i].C1)
   789  		//  throw an error if any of the x[i].C1 is 0
   790  		if res[i].IsZero() {
   791  			return nil, errors.New("invalid input; C1 is 0")
   792  		}
   793  	}
   794  
   795  	t := BatchInvertE6(res) // costs 1 inverse
   796  
   797  	for i := 0; i < n; i++ {
   798  		res[i].Add(&x[i].C0, &one).
   799  			Mul(&res[i], &t[i])
   800  	}
   801  
   802  	return res, nil
   803  }
   804  
   805  // DecompressTorus GT/E12 a compressed element
   806  // element must be in the cyclotomic subgroup
   807  // "COMPRESSION IN FINITE FIELDS AND TORUS-BASED CRYPTOGRAPHY", K. RUBIN AND A. SILVERBERG
   808  func (z *E6) DecompressTorus() E12 {
   809  
   810  	var res, num, denum E12
   811  	num.C0.Set(z)
   812  	num.C1.SetOne()
   813  	denum.C0.Set(z)
   814  	denum.C1.SetOne().Neg(&denum.C1)
   815  	res.Inverse(&denum).
   816  		Mul(&res, &num)
   817  
   818  	return res
   819  }
   820  
   821  // BatchDecompressTorus GT/E12 compressed elements
   822  // using a batch inversion
   823  func BatchDecompressTorus(x []E6) ([]E12, error) {
   824  
   825  	n := len(x)
   826  	if n == 0 {
   827  		return []E12{}, errors.New("invalid input size")
   828  	}
   829  
   830  	res := make([]E12, n)
   831  	num := make([]E12, n)
   832  	denum := make([]E12, n)
   833  
   834  	for i := 0; i < n; i++ {
   835  		num[i].C0.Set(&x[i])
   836  		num[i].C1.SetOne()
   837  		denum[i].C0.Set(&x[i])
   838  		denum[i].C1.SetOne().Neg(&denum[i].C1)
   839  	}
   840  
   841  	denum = BatchInvertE12(denum) // costs 1 inverse
   842  
   843  	for i := 0; i < n; i++ {
   844  		res[i].Mul(&num[i], &denum[i])
   845  	}
   846  
   847  	return res, nil
   848  }
   849  
   850  // Select is conditional move.
   851  // If cond = 0, it sets z to caseZ and returns it. otherwise caseNz.
   852  func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 {
   853  	//Might be able to save a nanosecond or two by an aggregate implementation
   854  
   855  	z.C0.Select(cond, &caseZ.C0, &caseNz.C0)
   856  	z.C1.Select(cond, &caseZ.C1, &caseNz.C1)
   857  
   858  	return z
   859  }
   860  
   861  // Div divides an element in E12 by an element in E12
   862  func (z *E12) Div(x *E12, y *E12) *E12 {
   863  	var r E12
   864  	r.Inverse(y).Mul(x, &r)
   865  	return z.Set(&r)
   866  }