func (p *G2Affine) ToJacobian(Q *G2Jac) *G2Jac {
	if p.X.IsZero() && p.Y.IsZero() {
		Q.Z.SetZero()
		Q.X.SetOne()
		Q.Y.SetOne()
		return Q
	}
	Q.Z.SetOne()
	Q.X.Set(&p.X)
	Q.Y.Set(&p.Y)
	return Q
}
ToJacobian sets Q = p, Q in Jacboian, p in affine
package bn256
import (
	"runtime"
	"sync"
	"github.com/consensys/gurvy/bn256/fr"
	"github.com/consensys/gurvy/utils/debug"
	"github.com/consensys/gurvy/utils/parallel"
)
type G2Jac struct {
	X, Y, Z e2
}
type G2Affine struct {
	X, Y e2
}
type g2JacExtended struct {
	X, Y, ZZ, ZZZ e2
}
func (p *g2JacExtended) SetInfinity() *g2JacExtended {
	p.X.SetOne()
	p.Y.SetOne()
	p.ZZ.SetZero()
	p.ZZZ.SetZero()
	return p
}
func (p *g2JacExtended) ToAffine(Q *G2Affine) *G2Affine {
	Q.X.Inverse(&p.ZZ).MulAssign(&p.X)
	Q.Y.Inverse(&p.ZZZ).MulAssign(&p.Y)
	return Q
}
func (p *g2JacExtended) ToJac(Q *G2Jac) *G2Jac {
	Q.X.Mul(&p.ZZ, &p.X).MulAssign(&p.ZZ)
	Q.Y.Mul(&p.ZZZ, &p.Y).MulAssign(&p.ZZZ)
	Q.Z.Set(&p.ZZZ)
	return Q
}
func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended {
	if a.X.IsZero() && a.Y.IsZero() {
		return p
	}
	if p.ZZ.IsZero() {
		p.X = a.X
		p.Y = a.Y
		p.ZZ.SetOne()
		p.ZZZ.SetOne()
		return p
	}
	var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 e2
	U2.Mul(&a.X, &p.ZZ)
	S2.Mul(&a.Y, &p.ZZZ)
	if U2.Equal(&p.X) && S2.Equal(&p.Y) {
		return p.double(a)
	}
	P.Sub(&U2, &p.X)
	R.Sub(&S2, &p.Y)
	PP.Square(&P)
	PPP.Mul(&P, &PP)
	Q.Mul(&p.X, &PP)
	RR.Square(&R)
	X3.Sub(&RR, &PPP)
	Q2.AddAssign(&Q).AddAssign(&Q)
	p.X.Sub(&X3, &Q2)
	Y3.Sub(&Q, &p.X).MulAssign(&R)
	R.Mul(&p.Y, &PPP)
	p.Y.Sub(&Y3, &R)
	p.ZZ.MulAssign(&PP)
	p.ZZZ.MulAssign(&PPP)
	return p
}
func (p *g2JacExtended) double(q *G2Affine) *g2JacExtended {
	var U, S, M, _M, Y3 e2
	U.Double(&q.Y)
	p.ZZ.Square(&U)
	p.ZZZ.Mul(&U, &p.ZZ)
	S.Mul(&q.X, &p.ZZ)
	_M.Square(&q.X)
	M.Double(&_M).
		AddAssign(&_M)  
	p.X.Square(&M).
		SubAssign(&S).
		SubAssign(&S)
	Y3.Sub(&S, &p.X).MulAssign(&M)
	U.Mul(&p.ZZZ, &q.Y)
	p.Y.Sub(&Y3, &U)
	return p
}
func (p *G2Jac) Set(a *G2Jac) *G2Jac {
	p.X.Set(&a.X)
	p.Y.Set(&a.Y)
	p.Z.Set(&a.Z)
	return p
}
func (p *G2Jac) Equal(a *G2Jac) bool {
	if p.Z.IsZero() && a.Z.IsZero() {
		return true
	}
	_p := G2Affine{}
	p.ToAffineFromJac(&_p)
	_a := G2Affine{}
	a.ToAffineFromJac(&_a)
	return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y)
}
func (p *G2Affine) Equal(a *G2Affine) bool {
	return p.X.Equal(&a.X) && p.Y.Equal(&a.Y)
}
func (p *G2Jac) Clone() *G2Jac {
	return &G2Jac{
		p.X, p.Y, p.Z,
	}
}
func (p *G2Jac) Neg(a *G2Jac) *G2Jac {
	p.Set(a)
	p.Y.Neg(&a.Y)
	return p
}
func (p *G2Affine) Neg(a *G2Affine) *G2Affine {
	p.X.Set(&a.X)
	p.Y.Neg(&a.Y)
	return p
}
func (p *G2Jac) Sub(curve *Curve, a G2Jac) *G2Jac {
	a.Y.Neg(&a.Y)
	p.Add(curve, &a)
	return p
}
func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine {
	var bufs [3]e2
	if p.Z.IsZero() {
		res.X.SetZero()
		res.Y.SetZero()
		return res
	}
	bufs[0].Inverse(&p.Z)
	bufs[2].Square(&bufs[0])
	bufs[1].Mul(&bufs[2], &bufs[0])
	res.Y.Mul(&p.Y, &bufs[1])
	res.X.Mul(&p.X, &bufs[2])
	return res
}
func (p *G2Jac) ToProjFromJac() *G2Jac {
	var buf e2
	buf.Square(&p.Z)
	p.X.Mul(&p.X, &p.Z)
	p.Z.Mul(&p.Z, &buf)
	return p
}
func (p *G2Jac) String(curve *Curve) string {
	if p.Z.IsZero() {
		return "O"
	}
	_p := G2Affine{}
	p.ToAffineFromJac(&_p)
	_p.X.FromMont()
	_p.Y.FromMont()
	return "E([" + _p.X.String() + "," + _p.Y.String() + "]),"
}