func (z *e12) FrobeniusCube(x *e12) *e12 {
	var t [6]e2
	t[0].Conjugate(&x.C0.B0)
	t[1].Conjugate(&x.C0.B1)
	t[2].Conjugate(&x.C0.B2)
	t[3].Conjugate(&x.C1.B0)
	t[4].Conjugate(&x.C1.B1)
	t[5].Conjugate(&x.C1.B2)
	t[1].MulByNonResiduePowerCube2(&t[1])
	t[2].MulByNonResiduePowerCube4(&t[2])
	t[3].MulByNonResiduePowerCube1(&t[3])
	t[4].MulByNonResiduePowerCube3(&t[4])
	t[5].MulByNonResiduePowerCube5(&t[5])
	z.C0.B0 = t[0]
	z.C0.B1 = t[1]
	z.C0.B2 = t[2]
	z.C1.B0 = t[3]
	z.C1.B1 = t[4]
	z.C1.B2 = t[5]
	return z
}
FrobeniusCube set z to Frobenius^3(x) in e12 and return z
package bn256
import (
	"math/bits"
	"github.com/consensys/gurvy/bn256/fp"
)
type e12 struct {
	C0, C1 e6
}
func (z *e12) Equal(x *e12) bool {
	return z.C0.Equal(&x.C0) && z.C1.Equal(&x.C1)
}
func (z *e12) String() string {
	return (z.C0.String() + "+(" + z.C1.String() + ")*w")
}
func (z *e12) SetString(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 string) *e12 {
	z.C0.SetString(s0, s1, s2, s3, s4, s5)
	z.C1.SetString(s6, s7, s8, s9, s10, s11)
	return z
}
func (z *e12) Set(x *e12) *e12 {
	z.C0 = x.C0
	z.C1 = x.C1
	return z
}
func (z *e12) SetOne() *e12 {
	z.C0.B0.A0.SetOne()
	z.C0.B0.A1.SetZero()
	z.C0.B1.A0.SetZero()
	z.C0.B1.A1.SetZero()
	z.C0.B2.A0.SetZero()
	z.C0.B2.A1.SetZero()
	z.C1.B0.A0.SetZero()
	z.C1.B0.A1.SetZero()
	z.C1.B1.A0.SetZero()
	z.C1.B1.A1.SetZero()
	z.C1.B2.A0.SetZero()
	z.C1.B2.A1.SetZero()
	return z
}
func (z *e12) ToMont() *e12 {
	z.C0.ToMont()
	z.C1.ToMont()
	return z
}
func (z *e12) FromMont() *e12 {
	z.C0.FromMont()
	z.C1.FromMont()
	return z
}
func (z *e12) Add(x, y *e12) *e12 {
	z.C0.Add(&x.C0, &y.C0)
	z.C1.Add(&x.C1, &y.C1)
	return z
}
func (z *e12) Sub(x, y *e12) *e12 {
	z.C0.Sub(&x.C0, &y.C0)
	z.C1.Sub(&x.C1, &y.C1)
	return z
}
func (z *e12) SetRandom() *e12 {
	z.C0.B0.A0.SetRandom()
	z.C0.B0.A1.SetRandom()
	z.C0.B1.A0.SetRandom()
	z.C0.B1.A1.SetRandom()
	z.C0.B2.A0.SetRandom()
	z.C0.B2.A1.SetRandom()
	z.C1.B0.A0.SetRandom()
	z.C1.B0.A1.SetRandom()
	z.C1.B1.A0.SetRandom()
	z.C1.B1.A1.SetRandom()
	z.C1.B2.A0.SetRandom()
	z.C1.B2.A1.SetRandom()
	return z
}
func (z *e12) Mul(x, y *e12) *e12 {
	var t0, t1, xSum, ySum e6
	t0.Mul(&x.C0, &y.C0)  
	t1.Mul(&x.C1, &y.C1)  
	xSum.Add(&x.C0, &x.C1)
	ySum.Add(&y.C0, &y.C1)
	{  
		var result e6
		result.B1.Set(&(&t1).B0)
		result.B2.Set(&(&t1).B1)
		{  
			var buf, buf9 e2
			buf.Set(&(&t1).B2)
			buf9.Double(&buf).
				Double(&buf9).
				Double(&buf9).
				Add(&buf9, &buf)
			result.B0.A1.Add(&buf.A0, &buf9.A1)
			{  
				(&(result.B0).A0).Neg(&buf.A1)
			}  
			result.B0.A0.AddAssign(&buf9.A0)
		}  
		z.C0.Set(&result)
	}  
	z.C0.Add(&z.C0, &t0)
	z.C1.Mul(&xSum, &ySum).
		Sub(&z.C1, &t0).
		Sub(&z.C1, &t1)
	return z
}
func (z *e12) Square(x *e12) *e12 {
	var b0, b1 e6
	b0.Square(&x.C0)
	b1.Square(&x.C1)
	{  
		var result e6
		result.B1.Set(&(&b1).B0)
		result.B2.Set(&(&b1).B1)
		{  
			var buf, buf9 e2
			buf.Set(&(&b1).B2)
			buf9.Double(&buf).
				Double(&buf9).
				Double(&buf9).
				Add(&buf9, &buf)
			result.B0.A1.Add(&buf.A0, &buf9.A1)
			{  
				(&(result.B0).A0).Neg(&buf.A1)
			}  
			result.B0.A0.AddAssign(&buf9.A0)
		}  
		b1.Set(&result)
	}  
	b1.Add(&b0, &b1)
	z.C1.Mul(&x.C0, &x.C1).Double(&z.C1)
	z.C0 = b1
	return z
}
func (z *e12) Inverse(x *e12) *e12 {
	var t [2]e6
	t[0].Square(&x.C0)  
	t[1].Square(&x.C1)  
	{                   
		var buf e6
		{  
			var result e6
			result.B1.Set(&(&t[1]).B0)
			result.B2.Set(&(&t[1]).B1)
			{  
				var buf, buf9 e2
				buf.Set(&(&t[1]).B2)
				buf9.Double(&buf).
					Double(&buf9).
					Double(&buf9).
					Add(&buf9, &buf)
				result.B0.A1.Add(&buf.A0, &buf9.A1)
				{  
					(&(result.B0).A0).Neg(&buf.A1)
				}  
				result.B0.A0.AddAssign(&buf9.A0)
			}  
			buf.Set(&result)
		}  
		t[0].Sub(&t[0], &buf)
	}
	t[1].Inverse(&t[0])                
	z.C0.Mul(&x.C0, &t[1])             
	z.C1.Mul(&x.C1, &t[1]).Neg(&z.C1)  
	return z
}
func (z *e12) InverseUnitary(x *e12) *e12 {
	return z.Conjugate(x)
}
func (z *e12) Conjugate(x *e12) *e12 {
	z.Set(x)
	z.C1.Neg(&z.C1)
	return z
}
func (z *e12) MulByVW(x *e12, y *e2) *e12 {
	var result e12
	var yNR e2
	{  
		var buf, buf9 e2
		buf.Set(y)
		buf9.Double(&buf).
			Double(&buf9).
			Double(&buf9).
			Add(&buf9, &buf)
		yNR.A1.Add(&buf.A0, &buf9.A1)
		{  
			(&(yNR).A0).Neg(&buf.A1)
		}  
		yNR.A0.AddAssign(&buf9.A0)
	}  
	result.C0.B0.Mul(&x.C1.B1, &yNR)
	result.C0.B1.Mul(&x.C1.B2, &yNR)
	result.C0.B2.Mul(&x.C1.B0, y)
	result.C1.B0.Mul(&x.C0.B2, &yNR)
	result.C1.B1.Mul(&x.C0.B0, y)
	result.C1.B2.Mul(&x.C0.B1, y)
	z.Set(&result)
	return z
}
func (z *e12) MulByV(x *e12, y *e2) *e12 {
	var result e12
	var yNR e2
	{  
		var buf, buf9 e2
		buf.Set(y)
		buf9.Double(&buf).
			Double(&buf9).
			Double(&buf9).
			Add(&buf9, &buf)
		yNR.A1.Add(&buf.A0, &buf9.A1)
		{  
			(&(yNR).A0).Neg(&buf.A1)
		}  
		yNR.A0.AddAssign(&buf9.A0)
	}  
	result.C0.B0.Mul(&x.C0.B2, &yNR)
	result.C0.B1.Mul(&x.C0.B0, y)
	result.C0.B2.Mul(&x.C0.B1, y)
	result.C1.B0.Mul(&x.C1.B2, &yNR)
	result.C1.B1.Mul(&x.C1.B0, y)
	result.C1.B2.Mul(&x.C1.B1, y)
	z.Set(&result)
	return z
}
func (z *e12) MulByV2W(x *e12, y *e2) *e12 {
	var result e12
	var yNR e2
	{  
		var buf, buf9 e2
		buf.Set(y)
		buf9.Double(&buf).
			Double(&buf9).
			Double(&buf9).
			Add(&buf9, &buf)
		yNR.A1.Add(&buf.A0, &buf9.A1)
		{  
			(&(yNR).A0).Neg(&buf.A1)
		}  
		yNR.A0.AddAssign(&buf9.A0)
	}  
	result.C0.B0.Mul(&x.C1.B0, &yNR)
	result.C0.B1.Mul(&x.C1.B1, &yNR)
	result.C0.B2.Mul(&x.C1.B2, &yNR)
	result.C1.B0.Mul(&x.C0.B1, &yNR)
	result.C1.B1.Mul(&x.C0.B2, &yNR)
	result.C1.B2.Mul(&x.C0.B0, y)
	z.Set(&result)
	return z
}
func (z *e12) MulByV2NRInv(x *e12, y *e2) *e12 {
	var result e12
	var yNRInv e2
	{  
		copy := *(y)
		var copy9 e2
		copy9.Double(&copy).
			Double(&copy9).
			Double(&copy9).
			AddAssign(&copy)
		(yNRInv).A0.Add(&copy9.A0, &copy.A1)
		(yNRInv).A1.Sub(&copy9.A1, &copy.A0)
		buf82inv := fp.Element{
			15263610803691847034,
			14617516054323294413,
			1961223913490700324,
			3456812345740674661,
		}
		(yNRInv).A0.MulAssign(&buf82inv)
		(yNRInv).A1.MulAssign(&buf82inv)
	}  
	result.C0.B0.Mul(&x.C0.B1, y)
	result.C0.B1.Mul(&x.C0.B2, y)
	result.C0.B2.Mul(&x.C0.B0, &yNRInv)
	result.C1.B0.Mul(&x.C1.B1, y)
	result.C1.B1.Mul(&x.C1.B2, y)
	result.C1.B2.Mul(&x.C1.B0, &yNRInv)
	z.Set(&result)
	return z
}
func (z *e12) MulByVWNRInv(x *e12, y *e2) *e12 {
	var result e12
	var yNRInv e2
	{  
		copy := *(y)
		var copy9 e2
		copy9.Double(&copy).
			Double(&copy9).
			Double(&copy9).
			AddAssign(&copy)
		(yNRInv).A0.Add(&copy9.A0, &copy.A1)
		(yNRInv).A1.Sub(&copy9.A1, &copy.A0)
		buf82inv := fp.Element{
			15263610803691847034,
			14617516054323294413,
			1961223913490700324,
			3456812345740674661,
		}
		(yNRInv).A0.MulAssign(&buf82inv)
		(yNRInv).A1.MulAssign(&buf82inv)
	}  
	result.C0.B0.Mul(&x.C1.B1, y)
	result.C0.B1.Mul(&x.C1.B2, y)
	result.C0.B2.Mul(&x.C1.B0, &yNRInv)
	result.C1.B0.Mul(&x.C0.B2, y)
	result.C1.B1.Mul(&x.C0.B0, &yNRInv)
	result.C1.B2.Mul(&x.C0.B1, &yNRInv)
	z.Set(&result)
	return z
}
func (z *e12) MulByWNRInv(x *e12, y *e2) *e12 {
	var result e12
	var yNRInv e2
	{  
		copy := *(y)
		var copy9 e2
		copy9.Double(&copy).
			Double(&copy9).
			Double(&copy9).
			AddAssign(&copy)
		(yNRInv).A0.Add(&copy9.A0, &copy.A1)
		(yNRInv).A1.Sub(&copy9.A1, &copy.A0)
		buf82inv := fp.Element{
			15263610803691847034,
			14617516054323294413,
			1961223913490700324,
			3456812345740674661,
		}
		(yNRInv).A0.MulAssign(&buf82inv)
		(yNRInv).A1.MulAssign(&buf82inv)
	}  
	result.C0.B0.Mul(&x.C1.B2, y)
	result.C0.B1.Mul(&x.C1.B0, &yNRInv)
	result.C0.B2.Mul(&x.C1.B1, &yNRInv)
	result.C1.B0.Mul(&x.C0.B0, &yNRInv)
	result.C1.B1.Mul(&x.C0.B1, &yNRInv)
	result.C1.B2.Mul(&x.C0.B2, &yNRInv)
	z.Set(&result)
	return z
}
func (z *e6) MulByNonResidue(x *e6) *e6 {
	var result e6
	result.B1.Set(&(x).B0)
	result.B2.Set(&(x).B1)
	{  
		var buf, buf9 e2
		buf.Set(&(x).B2)
		buf9.Double(&buf).
			Double(&buf9).
			Double(&buf9).
			Add(&buf9, &buf)
		result.B0.A1.Add(&buf.A0, &buf9.A1)
		{  
			(&(result.B0).A0).Neg(&buf.A1)
		}  
		result.B0.A0.AddAssign(&buf9.A0)
	}  
	z.Set(&result)
	return z
}
func (z *e12) Frobenius(x *e12) *e12 {
	var t [6]e2
	t[0].Conjugate(&x.C0.B0)
	t[1].Conjugate(&x.C0.B1)
	t[2].Conjugate(&x.C0.B2)
	t[3].Conjugate(&x.C1.B0)
	t[4].Conjugate(&x.C1.B1)
	t[5].Conjugate(&x.C1.B2)
	t[1].MulByNonResiduePower2(&t[1])
	t[2].MulByNonResiduePower4(&t[2])
	t[3].MulByNonResiduePower1(&t[3])
	t[4].MulByNonResiduePower3(&t[4])
	t[5].MulByNonResiduePower5(&t[5])
	z.C0.B0 = t[0]
	z.C0.B1 = t[1]
	z.C0.B2 = t[2]
	z.C1.B0 = t[3]
	z.C1.B1 = t[4]
	z.C1.B2 = t[5]
	return z
}
func (z *e12) FrobeniusSquare(x *e12) *e12 {
	var t [6]e2
	t[1].MulByNonResiduePowerSquare2(&x.C0.B1)
	t[2].MulByNonResiduePowerSquare4(&x.C0.B2)
	t[3].MulByNonResiduePowerSquare1(&x.C1.B0)
	t[4].MulByNonResiduePowerSquare3(&x.C1.B1)
	t[5].MulByNonResiduePowerSquare5(&x.C1.B2)
	z.C0.B0 = x.C0.B0
	z.C0.B1 = t[1]
	z.C0.B2 = t[2]
	z.C1.B0 = t[3]
	z.C1.B1 = t[4]
	z.C1.B2 = t[5]
	return z
}