github.com/consensys/gnark-crypto@v0.14.0/internal/generator/ecc/template/point.go.tmpl (about)

     1  
     2  {{ $TAffine := print (toUpper .PointName) "Affine" }}
     3  {{ $TJacobian := print (toUpper .PointName) "Jac" }}
     4  {{ $TJacobianExtended := print (toLower .PointName) "JacExtended" }}
     5  {{ $TProjective := print (toLower .PointName) "Proj" }}
     6  
     7  
     8  import (
     9  	{{- if eq .PointName "g2"}}
    10  	"crypto/rand"
    11  	{{- end}}
    12  	"math/big"
    13  	"runtime"
    14  
    15  	{{- if .GLV}}
    16  	"github.com/consensys/gnark-crypto/ecc"
    17  	{{- end}}
    18  	"github.com/consensys/gnark-crypto/internal/parallel"
    19  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr"
    20  	{{- if or (eq .CoordType "fptower.E2") (eq .CoordType "fptower.E4") }}
    21  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/internal/fptower"
    22  	{{else}}
    23  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp"
    24  	{{- end}}
    25  )
    26  
    27  
    28  // {{ $TAffine }} is a point in affine coordinates (x,y)
    29  type {{ $TAffine }} struct {
    30  	X, Y {{.CoordType}}
    31  }
    32  
    33  // {{ $TJacobian }} is a point in Jacobian coordinates (x=X/Z², y=Y/Z³)
    34  type {{ $TJacobian }} struct {
    35  	X, Y, Z {{.CoordType}}
    36  }
    37  
    38  // {{ $TJacobianExtended }} is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²)
    39  type {{ $TJacobianExtended }} struct {
    40  	X, Y, ZZ, ZZZ {{.CoordType}}
    41  }
    42  
    43  {{- if .Projective}}
    44  // {{ $TProjective }} point in projective coordinates
    45  type {{ $TProjective }} struct {
    46  	x, y, z {{.CoordType}}
    47  }
    48  {{- end}}
    49  
    50  
    51  
    52  // -------------------------------------------------------------------------------------------------
    53  // Affine coordinates
    54  
    55  // Set sets p to a in affine coordinates.
    56  func (p *{{ $TAffine }}) Set(a *{{ $TAffine }}) *{{ $TAffine }} {
    57         p.X, p.Y = a.X, a.Y
    58         return p
    59  }
    60  
    61  // setInfinity sets p to the infinity point, which is encoded as (0,0).
    62  // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B).
    63  func (p *{{ $TAffine }}) setInfinity() *{{ $TAffine }} {
    64  	p.X.SetZero()
    65  	p.Y.SetZero()
    66  	return p
    67  }
    68  
    69  // ScalarMultiplication computes and returns p = [s]a
    70  // where p and a are affine points.
    71  func (p *{{ $TAffine }}) ScalarMultiplication(a *{{ $TAffine }}, s *big.Int) *{{ $TAffine }} {
    72  	var _p {{ $TJacobian }}
    73  	_p.FromAffine(a)
    74  	{{- if .GLV}}
    75          _p.mulGLV(&_p, s)
    76  	{{- else }}
    77          _p.mulWindowed(&_p, s)
    78  	{{- end }}
    79  	p.FromJacobian(&_p)
    80  	return p
    81  }
    82  
    83  // ScalarMultiplicationBase computes and returns p = [s]g
    84  // where g is the affine point generating the prime subgroup.
    85  func (p *{{ $TAffine }}) ScalarMultiplicationBase(s *big.Int) *{{ $TAffine }} {
    86  	var _p {{ $TJacobian }}
    87  	{{- if .GLV}}
    88  	_p.mulGLV(&{{ toLower .PointName}}Gen, s)
    89  	{{- else }}
    90          _p.mulWindowed(&{{ toLower .PointName}}Gen, s)
    91  	{{- end }}
    92  	p.FromJacobian(&_p)
    93  	return p
    94  }
    95  
    96  
    97  // Add adds two points in affine coordinates.
    98  // It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates.
    99  //
   100  // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl
   101  func (p *{{ $TAffine }}) Add(a, b *{{ $TAffine }}) *{{ $TAffine }} {
   102  	var q {{ $TJacobian }}
   103  	// a is infinity, return b
   104  	if a.IsInfinity() {
   105  		p.Set(b)
   106  		return p
   107  	}
   108  	// b is infinity, return a
   109  	if b.IsInfinity() {
   110  		p.Set(a)
   111  		return p
   112  	}
   113  	if a.X.Equal(&b.X) {
   114  		// if b == a, we double instead
   115  		if a.Y.Equal(&b.Y) {
   116  			q.DoubleMixed(a)
   117  			return p.FromJacobian(&q)
   118  		} else {
   119  			// if b == -a, we return 0
   120  			return p.setInfinity()
   121  		}
   122  	}
   123  	var H, HH, I, J, r, V {{.CoordType}}
   124  	H.Sub(&b.X, &a.X)
   125  	HH.Square(&H)
   126  	I.Double(&HH).Double(&I)
   127  	J.Mul(&H, &I)
   128  	r.Sub(&b.Y, &a.Y)
   129  	r.Double(&r)
   130  	V.Mul(&a.X, &I)
   131  	q.X.Square(&r).
   132  		Sub(&q.X, &J).
   133  		Sub(&q.X, &V).
   134  		Sub(&q.X, &V)
   135  	q.Y.Sub(&V, &q.X).
   136  		Mul(&q.Y, &r)
   137  	J.Mul(&a.Y, &J).Double(&J)
   138  	q.Y.Sub(&q.Y, &J)
   139  	q.Z.Double(&H)
   140  
   141  	return p.FromJacobian(&q)
   142  }
   143  
   144  // Double doubles a point in affine coordinates.
   145  // It converts the point to Jacobian coordinates, doubles it using Jacobian
   146  // addition with a.Z=1, and converts it back to affine coordinates.
   147  //
   148  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
   149  func (p *{{ $TAffine }}) Double(a *{{ $TAffine }}) *{{ $TAffine }} {
   150  	var q {{ $TJacobian }}
   151  	q.FromAffine(a)
   152  	q.DoubleMixed(a)
   153  	p.FromJacobian(&q)
   154  	return p
   155  }
   156  
   157  // Sub subtracts two points in affine coordinates.
   158  // It uses a similar approach to Add, but negates the second point before adding.
   159  func (p *{{ $TAffine }}) Sub(a, b *{{ $TAffine }}) *{{ $TAffine }} {
   160  	var bneg {{ $TAffine }}
   161  	bneg.Neg(b)
   162  	p.Add(a, &bneg)
   163  	return p
   164  }
   165  
   166  // Equal tests if two points in affine coordinates are equal.
   167  func (p *{{ $TAffine }}) Equal(a *{{ $TAffine }}) bool {
   168  	return p.X.Equal(&a.X) && p.Y.Equal(&a.Y)
   169  }
   170  
   171  
   172  // Neg sets p to the affine negative point -a = (a.X, -a.Y).
   173  func (p *{{ $TAffine }}) Neg(a *{{ $TAffine }}) *{{ $TAffine }} {
   174  	p.X = a.X
   175  	p.Y.Neg(&a.Y)
   176  	return p
   177  }
   178  
   179  // FromJacobian converts a point p1 from Jacobian to affine coordinates.
   180  func (p *{{ $TAffine }}) FromJacobian(p1 *{{ $TJacobian }}) *{{ $TAffine }} {
   181  
   182  	var a, b {{.CoordType}}
   183  
   184  	if p1.Z.IsZero() {
   185  		p.X.SetZero()
   186  		p.Y.SetZero()
   187  		return p
   188  	}
   189  
   190  	a.Inverse(&p1.Z)
   191  	b.Square(&a)
   192  	p.X.Mul(&p1.X, &b)
   193  	p.Y.Mul(&p1.Y, &b).Mul(&p.Y, &a)
   194  
   195  	return p
   196  }
   197  
   198  // String returns the string representation E(x,y) of the affine point p or "O" if it is infinity.
   199  func (p *{{ $TAffine }}) String() string {
   200  	if p.IsInfinity() {
   201  		return "O"
   202  	}
   203  	return "E([" + p.X.String() + "," + p.Y.String() + "])"
   204  }
   205  
   206  // IsInfinity checks if the affine point p is infinity, which is encoded as (0,0).
   207  // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B).
   208  func (p *{{ $TAffine }}) IsInfinity() bool {
   209  	return p.X.IsZero() && p.Y.IsZero()
   210  }
   211  
   212  // IsOnCurve returns true if the affine point p in on the curve.
   213  func (p *{{ $TAffine }}) IsOnCurve() bool {
   214  	var point {{ $TJacobian }}
   215  	point.FromAffine(p)
   216  	return point.IsOnCurve() // call this function to handle infinity point
   217  }
   218  
   219  // IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise.
   220  func (p *{{ $TAffine }}) IsInSubGroup() bool {
   221  	var _p {{ $TJacobian }}
   222  	_p.FromAffine(p)
   223  	return _p.IsInSubGroup()
   224  }
   225  
   226  
   227  // -------------------------------------------------------------------------------------------------
   228  // Jacobian coordinates
   229  
   230  // Set sets p to a in Jacobian coordinates.
   231  func (p *{{ $TJacobian }}) Set(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   232  	p.X, p.Y, p.Z = q.X, q.Y, q.Z
   233  	return p
   234  }
   235  
   236  // Equal tests if two points in Jacobian coordinates are equal.
   237  func (p *{{ $TJacobian }}) Equal(q *{{ $TJacobian }}) bool {
   238  	// If one point is infinity, the other must also be infinity.
   239  	if p.Z.IsZero() {
   240  		return q.Z.IsZero()
   241  	}
   242  	// If the other point is infinity, return false since we can't
   243  	// the following checks would be incorrect.
   244  	if q.Z.IsZero() {
   245  		return false
   246  	}
   247  
   248  	var pZSquare, aZSquare {{.CoordType}}
   249  	pZSquare.Square(&p.Z)
   250  	aZSquare.Square(&q.Z)
   251  
   252  	var lhs, rhs {{.CoordType}}
   253  	lhs.Mul(&p.X, &aZSquare)
   254  	rhs.Mul(&q.X, &pZSquare)
   255  	if !lhs.Equal(&rhs) {
   256  		return false
   257  	}
   258  	lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z)
   259  	rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z)
   260  
   261  	return lhs.Equal(&rhs)
   262  }
   263  
   264  // Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z).
   265  func (p *{{ $TJacobian }}) Neg(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   266  	*p = *q
   267  	p.Y.Neg(&q.Y)
   268  	return p
   269  }
   270  
   271  // AddAssign sets p to p+a in Jacobian coordinates.
   272  //
   273  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
   274  func (p *{{ $TJacobian }}) AddAssign(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   275  
   276  	// p is infinity, return q
   277  	if p.Z.IsZero() {
   278  		p.Set(q)
   279  		return p
   280  	}
   281  
   282  	// q is infinity, return p
   283  	if q.Z.IsZero() {
   284  		return p
   285  	}
   286  
   287  	var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V {{.CoordType}}
   288  	Z1Z1.Square(&q.Z)
   289  	Z2Z2.Square(&p.Z)
   290  	U1.Mul(&q.X, &Z2Z2)
   291  	U2.Mul(&p.X, &Z1Z1)
   292  	S1.Mul(&q.Y, &p.Z).
   293  		Mul(&S1, &Z2Z2)
   294  	S2.Mul(&p.Y, &q.Z).
   295  		Mul(&S2, &Z1Z1)
   296  
   297  	// if p == q, we double instead
   298  	if U1.Equal(&U2) && S1.Equal(&S2) {
   299  		return p.DoubleAssign()
   300  	}
   301  
   302  	H.Sub(&U2, &U1)
   303  	I.Double(&H).
   304  		Square(&I)
   305  	J.Mul(&H, &I)
   306  	r.Sub(&S2, &S1).Double(&r)
   307  	V.Mul(&U1, &I)
   308  	p.X.Square(&r).
   309  		Sub(&p.X, &J).
   310  		Sub(&p.X, &V).
   311  		Sub(&p.X, &V)
   312  	p.Y.Sub(&V, &p.X).
   313  		Mul(&p.Y, &r)
   314  	S1.Mul(&S1, &J).Double(&S1)
   315  	p.Y.Sub(&p.Y, &S1)
   316  	p.Z.Add(&p.Z, &q.Z)
   317  	p.Z.Square(&p.Z).
   318  		Sub(&p.Z, &Z1Z1).
   319  		Sub(&p.Z, &Z2Z2).
   320  		Mul(&p.Z, &H)
   321  
   322  	return p
   323  }
   324  
   325  // SubAssign sets p to p-a in Jacobian coordinates.
   326  // It uses a similar approach to AddAssign, but negates the point a before adding.
   327  func (p *{{ $TJacobian }}) SubAssign(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   328  	var tmp {{ $TJacobian }}
   329  	tmp.Set(q)
   330  	tmp.Y.Neg(&tmp.Y)
   331  	p.AddAssign(&tmp)
   332  	return p
   333  }
   334  
   335  // Double sets p to [2]q in Jacobian coordinates.
   336  //
   337  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   338  func (p *{{ $TJacobian }}) DoubleMixed(a *{{ $TAffine }}) *{{ $TJacobian }} {
   339  	var XX, YY, YYYY, S, M, T {{.CoordType}}
   340  	XX.Square(&a.X)
   341  	YY.Square(&a.Y)
   342  	YYYY.Square(&YY)
   343  	S.Add(&a.X, &YY).
   344  		Square(&S).
   345  		Sub(&S, &XX).
   346  		Sub(&S, &YYYY).
   347  		Double(&S)
   348  	M.Double(&XX).
   349  		Add(&M, &XX) // -> + A, but A=0 here
   350  	T.Square(&M).
   351  		Sub(&T, &S).
   352  		Sub(&T, &S)
   353  	p.X.Set(&T)
   354  	p.Y.Sub(&S, &T).
   355  		Mul(&p.Y, &M)
   356  	YYYY.Double(&YYYY).
   357  		Double(&YYYY).
   358  		Double(&YYYY)
   359  	p.Y.Sub(&p.Y, &YYYY)
   360  	p.Z.Double(&a.Y)
   361  
   362  	return p
   363  }
   364  
   365  // AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1.
   366  //
   367  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
   368  func (p *{{ $TJacobian }}) AddMixed(a *{{ $TAffine }}) *{{ $TJacobian }} {
   369  
   370  	//if a is infinity return p
   371  	if a.IsInfinity() {
   372  		return p
   373  	}
   374  	// p is infinity, return a
   375  	if p.Z.IsZero() {
   376  		p.X = a.X
   377  		p.Y = a.Y
   378  		p.Z.SetOne()
   379  		return p
   380  	}
   381  
   382  	var Z1Z1, U2, S2, H, HH, I, J, r, V {{.CoordType}}
   383  	Z1Z1.Square(&p.Z)
   384  	U2.Mul(&a.X, &Z1Z1)
   385  	S2.Mul(&a.Y, &p.Z).
   386  		Mul(&S2, &Z1Z1)
   387  
   388  	// if p == a, we double instead
   389  	if U2.Equal(&p.X) && S2.Equal(&p.Y) {
   390  		return p.DoubleMixed(a)
   391  	}
   392  
   393  	H.Sub(&U2, &p.X)
   394  	HH.Square(&H)
   395  	I.Double(&HH).Double(&I)
   396  	J.Mul(&H, &I)
   397  	r.Sub(&S2, &p.Y).Double(&r)
   398  	V.Mul(&p.X, &I)
   399  	p.X.Square(&r).
   400  		Sub(&p.X, &J).
   401  		Sub(&p.X, &V).
   402  		Sub(&p.X, &V)
   403  	J.Mul(&J, &p.Y).Double(&J)
   404  	p.Y.Sub(&V, &p.X).
   405  		Mul(&p.Y, &r)
   406  	p.Y.Sub(&p.Y, &J)
   407  	p.Z.Add(&p.Z, &H)
   408  	p.Z.Square(&p.Z).
   409  		Sub(&p.Z, &Z1Z1).
   410  		Sub(&p.Z, &HH)
   411  
   412  	return p
   413  }
   414  
   415  // Double sets p to [2]q in Jacobian coordinates.
   416  //
   417  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   418  func (p *{{ $TJacobian }}) Double(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   419  	p.Set(q)
   420  	p.DoubleAssign()
   421  	return p
   422  }
   423  
   424  // DoubleAssign doubles p in Jacobian coordinates.
   425  //
   426  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   427  func (p *{{ $TJacobian }}) DoubleAssign() *{{ $TJacobian }} {
   428  
   429  	var XX, YY, YYYY, ZZ, S, M, T {{.CoordType}}
   430  
   431  	XX.Square(&p.X)
   432  	YY.Square(&p.Y)
   433  	YYYY.Square(&YY)
   434  	ZZ.Square(&p.Z)
   435  	S.Add(&p.X, &YY)
   436  	S.Square(&S).
   437  		Sub(&S, &XX).
   438  		Sub(&S, &YYYY).
   439  		Double(&S)
   440  	M.Double(&XX).Add(&M, &XX)
   441  	p.Z.Add(&p.Z, &p.Y).
   442  		Square(&p.Z).
   443  		Sub(&p.Z, &YY).
   444  		Sub(&p.Z, &ZZ)
   445  	T.Square(&M)
   446  	p.X = T
   447  	T.Double(&S)
   448  	p.X.Sub(&p.X, &T)
   449  	p.Y.Sub(&S, &p.X).
   450  		Mul(&p.Y, &M)
   451  	YYYY.Double(&YYYY).Double(&YYYY).Double(&YYYY)
   452  	p.Y.Sub(&p.Y, &YYYY)
   453  
   454  	return p
   455  }
   456  
   457  // ScalarMultiplication computes and returns p = [s]a
   458  // where p and a are Jacobian points.
   459  {{- if .GLV}}
   460  // using the GLV technique.
   461  // see https://www.iacr.org/archive/crypto2001/21390189.pdf
   462  {{- else }}
   463  // using a 2-bits windowed double-and-add method.
   464  {{- end }}
   465  func (p *{{ $TJacobian }}) ScalarMultiplication(q *{{ $TJacobian }}, s *big.Int) *{{ $TJacobian }} {
   466  	{{- if .GLV}}
   467  		return p.mulGLV(q, s)
   468  	{{- else }}
   469  		return p.mulWindowed(q, s)
   470  	{{- end }}
   471  }
   472  
   473  // ScalarMultiplicationBase computes and returns p = [s]g
   474  // where g is the prime subgroup generator.
   475  func (p *{{ $TJacobian  }}) ScalarMultiplicationBase(s *big.Int) *{{ $TJacobian  }} {
   476      {{- if .GLV}}
   477          return p.mulGLV(&{{ toLower .PointName }}Gen, s)
   478      {{- else }}
   479          _p.mulWindowed(&{{ toLower .PointName }}Gen, s)
   480      {{- end }}
   481  
   482  }
   483  
   484  // String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity.
   485  func (p *{{ $TJacobian }}) String() string {
   486  	_p := {{ $TAffine }}{}
   487  	_p.FromJacobian(p)
   488  	return _p.String()
   489  }
   490  
   491  // FromAffine converts a point a from affine to Jacobian coordinates.
   492  func (p *{{ $TJacobian }}) FromAffine(a *{{ $TAffine }}) *{{ $TJacobian }} {
   493  	if a.IsInfinity() {
   494  		p.Z.SetZero()
   495  		p.X.SetOne()
   496  		p.Y.SetOne()
   497  		return p
   498  	}
   499  	p.Z.SetOne()
   500  	p.X.Set(&a.X)
   501  	p.Y.Set(&a.Y)
   502  	return p
   503  }
   504  
   505  // IsOnCurve returns true if the Jacobian point p in on the curve.
   506  func (p *{{ $TJacobian }}) IsOnCurve() bool {
   507  	var left, right, tmp, ZZ  {{.CoordType}}
   508  	left.Square(&p.Y)
   509  	right.Square(&p.X).Mul(&right, &p.X)
   510  	ZZ.Square(&p.Z)
   511      tmp.Square(&ZZ).Mul(&tmp, &ZZ)
   512  		{{- if eq .PointName "g1"}}
   513              {{- if or (eq .Name "bls12-381") (eq .Name "bls24-317") (eq .Name "bw6-633")}}
   514                  // Mul tmp by bCurveCoeff=4
   515                  tmp.Double(&tmp).Double(&tmp)
   516              {{- else if eq .Name "bn254"}}
   517                  // Mul tmp by bCurveCoeff=3
   518                  fp.MulBy3(&tmp)
   519              {{- else if eq .Name "bw6-761"}}
   520                  // Mul tmp by bCurveCoeff=-1
   521                  tmp.Neg(&tmp)
   522              {{- else if or (eq .Name "bls12-377") (eq .Name "bls12-378") (eq .Name "bls24-315") (eq .Name "bw6-756")}}
   523                  // Mul tmp by bCurveCoeff=1 (nothing to do)
   524              {{- else}}
   525                  tmp.Mul(&tmp, &bCurveCoeff)
   526              {{- end}}
   527  		{{- else}}
   528              {{- if or (eq .Name "bls12-377") (eq .Name "bls12-381") (eq .Name "bn254") (eq .Name "bls24-315") (eq .Name "bls24-317")}}
   529                  tmp.MulBybTwistCurveCoeff(&tmp)
   530              {{- else if eq .Name "bw6-761"}}
   531                  // Mul tmp by bTwistCurveCoeff=4
   532                  tmp.Double(&tmp).Double(&tmp)
   533              {{- else if eq .Name "bw6-633"}}
   534                  // Mul tmp by bTwistCurveCoeff=8
   535                  tmp.Double(&tmp).Double(&tmp).Double(&tmp)
   536              {{- else}}
   537                  tmp.Mul(&tmp, &bTwistCurveCoeff)
   538              {{- end}}
   539  		{{- end}}
   540  	right.Add(&right, &tmp)
   541  	return left.Equal(&right)
   542  }
   543  
   544  
   545  
   546  {{- if or (eq .Name "bn254") (eq .Name "secp256k1")}}
   547  	{{- if eq .PointName "g1"}}
   548  		// IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   549          // the curve is of prime order i.e. E(𝔽p) is the full group
   550          // so we just check that the point is on the curve.
   551  		func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   552  
   553  			return p.IsOnCurve()
   554  
   555  		}
   556  	{{else if eq .PointName "g2"}}
   557  		// IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   558          // https://eprint.iacr.org/2022/348.pdf, sec. 3 and 5.1
   559          // [r]P == 0 <==> [x₀+1]P + ψ([x₀]P) + ψ²([x₀]P) = ψ³([2x₀]P)
   560  		func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   561              var a, b, c, res G2Jac
   562              a.ScalarMultiplication(p, &xGen)
   563              b.psi(&a)
   564              a.AddAssign(p)
   565              res.psi(&b)
   566              c.Set(&res).
   567                  AddAssign(&b).
   568                  AddAssign(&a)
   569              res.psi(&res).
   570                  Double(&res).
   571              SubAssign(&c)
   572  
   573              return res.IsOnCurve() && res.Z.IsZero()
   574  		}
   575  	{{- end}}
   576  {{else if or (eq .Name "bw6-761") (eq .Name "bw6-756")}}
   577  	// IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   578      {{ if .GLV}}
   579  	// Z[r,0]+Z[-lambda{{ $TAffine }}, 1] is the kernel
   580  	// of (u,v)->u+lambda{{ $TAffine }}v mod r. Expressing r, lambda{{ $TAffine }} as
   581  	// polynomials in x, a short vector of this Zmodule is
   582  	// (x+1), (x³-x²+1). So we check that (x+1)p+(x³-x²+1)ϕ(p)
   583  	// is the infinity.
   584  	func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   585  
   586  		var res, phip {{ $TJacobian }}
   587  		phip.phi(p)
   588  		res.ScalarMultiplication(&phip, &xGen).
   589  			SubAssign(&phip).
   590  			ScalarMultiplication(&res, &xGen).
   591  			ScalarMultiplication(&res, &xGen).
   592  			AddAssign(&phip)
   593  
   594  		phip.ScalarMultiplication(p, &xGen).AddAssign(p).AddAssign(&res)
   595  
   596  		return phip.IsOnCurve() && phip.Z.IsZero()
   597      {{ else}}
   598  	func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   599  
   600  		var res {{ $TJacobian }}
   601          res.ScalarMultiplication(p, fr.Modulus())
   602  		return res.IsOnCurve() && res.Z.IsZero()
   603      {{ end}}
   604  
   605  	}
   606  {{else if eq .Name "bw6-633"}}
   607      // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   608      {{ if .GLV}}
   609      // 3r P = (x+1)ϕ(P) + (-x^5 + x⁴ + x)P
   610  	func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   611  
   612          var uP, u4P, u5P, q, r {{ $TJacobian }}
   613          uP.ScalarMultiplication(p, &xGen)
   614          u4P.ScalarMultiplication(&uP, &xGen).
   615              ScalarMultiplication(&u4P, &xGen).
   616              ScalarMultiplication(&u4P, &xGen)
   617          u5P.ScalarMultiplication(&u4P, &xGen)
   618          q.Set(p).SubAssign(&uP)
   619          r.phi(&q).SubAssign(&uP).
   620              AddAssign(&u4P).
   621              AddAssign(&u5P)
   622  
   623      {{ else}}
   624  	func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   625  
   626          var r {{ $TJacobian }}
   627          r.ScalarMultiplication(p, fr.Modulus())
   628      {{ end}}
   629  		return r.IsOnCurve() && r.Z.IsZero()
   630  	}
   631  {{else if or (eq .Name "bls24-315") (eq .Name "bls24-317")}}
   632  	{{- if eq .PointName "g1"}}
   633          // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   634          {{ if .GLV}}
   635          // Z[r,0]+Z[-lambda{{ $TAffine }}, 1] is the kernel
   636          // of (u,v)->u+lambda{{ $TAffine }}v mod r. Expressing r, lambda{{ $TAffine }} as
   637          // polynomials in x, a short vector of this Zmodule is
   638          // 1, x⁴. So we check that p+x⁴ϕ(p)
   639          // is the infinity.
   640          func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   641  
   642              var res {{ $TJacobian }}
   643              res.phi(p).
   644                  ScalarMultiplication(&res, &xGen).
   645                  ScalarMultiplication(&res, &xGen).
   646                  ScalarMultiplication(&res, &xGen).
   647                  ScalarMultiplication(&res, &xGen).
   648                  AddAssign(p)
   649      {{ else}}
   650  	func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   651  
   652          var res {{ $TJacobian }}
   653          res.ScalarMultiplication(p, fr.Modulus())
   654  		return res.IsOnCurve() && res.Z.IsZero()
   655      {{ end}}
   656  
   657              return res.IsOnCurve() && res.Z.IsZero()
   658  
   659          }
   660  	{{else if eq .PointName "g2"}}
   661          // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   662          // https://eprint.iacr.org/2021/1130.pdf, sec.4
   663          // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2
   664          // ψ(p) = [x₀]P
   665          func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   666              var res, tmp {{ $TJacobian }}
   667              tmp.psi(p)
   668              res.ScalarMultiplication(p, &xGen).
   669              {{ if eq .Name "bls24-315"}}
   670                  AddAssign(&tmp)
   671              {{ else }}
   672                  SubAssign(&tmp)
   673              {{ end }}
   674  
   675              return res.IsOnCurve() && res.Z.IsZero()
   676  
   677          }
   678      {{- end}}
   679  {{else}}
   680  	{{- if eq .PointName "g1"}}
   681          // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   682          // Z[r,0]+Z[-lambda{{ $TAffine }}, 1] is the kernel
   683          // of (u,v)->u+lambda{{ $TAffine }}v mod r. Expressing r, lambda{{ $TAffine }} as
   684          // polynomials in x, a short vector of this Zmodule is
   685          // 1, x². So we check that p+x²ϕ(p)
   686          // is the infinity.
   687          func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   688  
   689              var res {{ $TJacobian }}
   690              {{ if .GLV}}
   691              res.phi(p).
   692                  ScalarMultiplication(&res, &xGen).
   693                  ScalarMultiplication(&res, &xGen).
   694                  AddAssign(p)
   695              {{ else}}
   696              res.ScalarMultiplication(p, fr.Modulus())
   697              {{ end}}
   698  
   699              return res.IsOnCurve() && res.Z.IsZero()
   700  
   701          }
   702  	{{else if eq .PointName "g2"}}
   703          {{if eq .Name "bls12-381"}}
   704              // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   705              // https://eprint.iacr.org/2021/1130.pdf, sec.4
   706              // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2
   707              // ψ(p) = [x₀]P
   708              func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   709                  var res, tmp {{ $TJacobian }}
   710                  tmp.psi(p)
   711                  res.ScalarMultiplication(p, &xGen).
   712                      AddAssign(&tmp)
   713  
   714                  return res.IsOnCurve() && res.Z.IsZero()
   715          }
   716          {{else if or (eq .Name "bls12-377") (eq .Name "bls12-378")}}
   717              // https://eprint.iacr.org/2021/1130.pdf, sec.4
   718              // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2
   719              // ψ(p) = [x₀]P
   720              func (p *{{ $TJacobian }}) IsInSubGroup() bool {
   721                  var res, tmp {{ $TJacobian }}
   722                  tmp.psi(p)
   723                  res.ScalarMultiplication(p, &xGen).
   724                      SubAssign(&tmp)
   725  
   726                  return res.IsOnCurve() && res.Z.IsZero()
   727          }
   728          {{- end}}
   729  	{{- end}}
   730  {{- end}}
   731  
   732  
   733  // mulWindowed computes the 2-bits windowed double-and-add scalar
   734  // multiplication p=[s]q in Jacobian coordinates.
   735  func (p *{{ $TJacobian }}) mulWindowed(q *{{ $TJacobian }}, s *big.Int) *{{ $TJacobian }} {
   736  
   737  	var res {{ $TJacobian }}
   738  	var ops [3]{{ $TJacobian }}
   739  
   740  	ops[0].Set(q)
   741  	if s.Sign() == -1 {
   742  		ops[0].Neg(&ops[0])
   743  	}
   744  	res.Set(&{{ toLower .PointName}}Infinity)
   745  	ops[1].Double(&ops[0])
   746  	ops[2].Set(&ops[0]).AddAssign(&ops[1])
   747  
   748  	b := s.Bytes()
   749  	for i := range b {
   750  		w := b[i]
   751  		mask := byte(0xc0)
   752  		for j := 0; j < 4; j++ {
   753  			res.DoubleAssign().DoubleAssign()
   754  			c := (w & mask) >> (6 - 2*j)
   755  			if c != 0 {
   756  				res.AddAssign(&ops[c-1])
   757  			}
   758  			mask = mask >> 2
   759  		}
   760  	}
   761  	p.Set(&res)
   762  
   763  	return p
   764  
   765  }
   766  
   767  {{ if eq .CoordType "fptower.E2"  }}
   768  	// psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map.
   769  	func (p *{{ $TJacobian }}) psi(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   770  		p.Set(q)
   771  		p.X.Conjugate(&p.X).Mul(&p.X, &endo.u)
   772  		p.Y.Conjugate(&p.Y).Mul(&p.Y, &endo.v)
   773  		p.Z.Conjugate(&p.Z)
   774  		return p
   775  	}
   776  {{ else if eq .CoordType "fptower.E4"}}
   777  	// psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map.
   778  	func (p *{{ $TJacobian }}) psi(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   779  		p.Set(q)
   780  		p.X.Frobenius(&p.X).Mul(&p.X, &endo.u)
   781  		p.Y.Frobenius(&p.Y).Mul(&p.Y, &endo.v)
   782  		p.Z.Frobenius(&p.Z)
   783  		return p
   784  	}
   785  {{ end }}
   786  
   787  {{ if .GLV}}
   788  
   789  // phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y),
   790  // where w is a third root of unity.
   791  func (p *{{ $TJacobian }}) phi(q *{{ $TJacobian }}) *{{ $TJacobian }} {
   792  	p.Set(q)
   793  	{{- if or (eq .CoordType "fptower.E2" ) (eq .CoordType "fptower.E4" )}}
   794  		p.X.MulByElement(&p.X, &thirdRootOne{{toUpper .PointName}})
   795  	{{- else}}
   796  		p.X.Mul(&p.X, &thirdRootOne{{toUpper .PointName}})
   797  	{{- end}}
   798  	return p
   799  }
   800  
   801  // mulGLV computes the scalar multiplication using a windowed-GLV method
   802  //
   803  // see https://www.iacr.org/archive/crypto2001/21390189.pdf
   804  func (p *{{ $TJacobian }}) mulGLV(q *{{ $TJacobian }}, s *big.Int) *{{ $TJacobian }} {
   805  
   806  	var table [15]{{ $TJacobian }}
   807  	var res {{ $TJacobian }}
   808  	var k1, k2 fr.Element
   809  
   810  	res.Set(&{{ toLower .PointName}}Infinity)
   811  
   812  	// table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q
   813  	table[0].Set(q)
   814  	table[3].phi(q)
   815  
   816  	// split the scalar, modifies ±q, ϕ(q) accordingly
   817  	k := ecc.SplitScalar(s, &glvBasis)
   818  
   819  	if k[0].Sign() == -1 {
   820  		k[0].Neg(&k[0])
   821  		table[0].Neg(&table[0])
   822  	}
   823  	if k[1].Sign() == -1 {
   824  		k[1].Neg(&k[1])
   825  		table[3].Neg(&table[3])
   826  	}
   827  
   828  	// precompute table (2 bits sliding window)
   829  	// table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0
   830  	table[1].Double(&table[0])
   831  	table[2].Set(&table[1]).AddAssign(&table[0])
   832  	table[4].Set(&table[3]).AddAssign(&table[0])
   833  	table[5].Set(&table[3]).AddAssign(&table[1])
   834  	table[6].Set(&table[3]).AddAssign(&table[2])
   835  	table[7].Double(&table[3])
   836  	table[8].Set(&table[7]).AddAssign(&table[0])
   837  	table[9].Set(&table[7]).AddAssign(&table[1])
   838  	table[10].Set(&table[7]).AddAssign(&table[2])
   839  	table[11].Set(&table[7]).AddAssign(&table[3])
   840  	table[12].Set(&table[11]).AddAssign(&table[0])
   841  	table[13].Set(&table[11]).AddAssign(&table[1])
   842  	table[14].Set(&table[11]).AddAssign(&table[2])
   843  
   844  	// bounds on the lattice base vectors guarantee that k1, k2 are len(r)/2 or len(r)/2+1 bits long max
   845  	// this is because we use a probabilistic scalar decomposition that replaces a division by a right-shift
   846  	k1 = k1.SetBigInt(&k[0]).Bits()
   847  	k2 = k2.SetBigInt(&k[1]).Bits()
   848  
   849      // we don't target constant-timeness so we check first if we increase the bounds or not
   850  	maxBit := k1.BitLen()
   851  	if k2.BitLen() > maxBit {
   852  		maxBit = k2.BitLen()
   853  	}
   854  	hiWordIndex := (maxBit - 1) / 64
   855  
   856  	// loop starts from len(k1)/2 or len(k1)/2+1 due to the bounds
   857  	for i := hiWordIndex; i >= 0; i-- {
   858  		mask := uint64(3) << 62
   859  		for j := 0; j < 32; j++ {
   860  			res.Double(&res).Double(&res)
   861  			b1 := (k1[i] & mask) >> (62 - 2*j)
   862  			b2 := (k2[i] & mask) >> (62 - 2*j)
   863  			if b1|b2 != 0 {
   864  				s := (b2<<2 | b1)
   865  				res.AddAssign(&table[s-1])
   866  			}
   867  			mask = mask >> 2
   868  		}
   869  	}
   870  
   871  	p.Set(&res)
   872  	return p
   873  }
   874  
   875  
   876  {{ end }}
   877  
   878  {{ if .CofactorCleaning}}
   879  
   880  // ClearCofactor maps a point in curve to r-torsion
   881  func (p *{{ $TAffine }}) ClearCofactor(a *{{ $TAffine }}) *{{ $TAffine }} {
   882  	var _p {{$TJacobian}}
   883  	_p.FromAffine(a)
   884  	_p.ClearCofactor(&_p)
   885  	p.FromJacobian(&_p)
   886  	return p
   887  }
   888  
   889  {{- if eq .PointName "g1"}}
   890  
   891  // ClearCofactor maps a point in E(Fp) to E(Fp)[r]
   892  func (p *{{$TJacobian}}) ClearCofactor(q *{{$TJacobian}}) *{{$TJacobian}} {
   893  {{- if or (eq .Name "bls12-381") (eq .Name "bls24-315")}}
   894  	// cf https://eprint.iacr.org/2019/403.pdf, 5
   895  	var res {{$TJacobian}}
   896  	res.ScalarMultiplication(q, &xGen).AddAssign(q)
   897  	p.Set(&res)
   898  	return p
   899  {{else if or (eq .Name "bls12-377") (eq .Name "bls12-378") (eq .Name "bls24-317")}}
   900  	// cf https://eprint.iacr.org/2019/403.pdf, 5
   901  	var res {{$TJacobian}}
   902  	res.ScalarMultiplication(q, &xGen).Neg(&res).AddAssign(q)
   903  	p.Set(&res)
   904  	return p
   905  {{else if eq .Name "bw6-761"}}
   906  {{ if .GLV}}
   907  	// https://eprint.iacr.org/2020/351.pdf
   908  	var points [4]{{$TJacobian}}
   909  	points[0].Set(q)
   910  	points[1].ScalarMultiplication(q, &xGen)
   911  	points[2].ScalarMultiplication(&points[1], &xGen)
   912  	points[3].ScalarMultiplication(&points[2], &xGen)
   913  
   914  	var scalars [7]big.Int
   915  	scalars[0].SetInt64(103)
   916  	scalars[1].SetInt64(83)
   917  	scalars[2].SetInt64(40)
   918  	scalars[3].SetInt64(136)
   919  
   920  	scalars[4].SetInt64(7)
   921  	scalars[5].SetInt64(89)
   922  	scalars[6].SetInt64(130)
   923  
   924  	var p1, p2, tmp {{$TJacobian}}
   925  	p1.ScalarMultiplication(&points[3], &scalars[0])
   926  	tmp.ScalarMultiplication(&points[2], &scalars[1]).Neg(&tmp)
   927  	p1.AddAssign(&tmp)
   928  	tmp.ScalarMultiplication(&points[1], &scalars[2]).Neg(&tmp)
   929  	p1.AddAssign(&tmp)
   930  	tmp.ScalarMultiplication(&points[0], &scalars[3])
   931  	p1.AddAssign(&tmp)
   932  
   933  	p2.ScalarMultiplication(&points[2], &scalars[4])
   934  	tmp.ScalarMultiplication(&points[1], &scalars[5])
   935  	p2.AddAssign(&tmp)
   936  	tmp.ScalarMultiplication(&points[0], &scalars[6])
   937  	p2.AddAssign(&tmp)
   938  	p2.phi(&p2)
   939  
   940  	p.Set(&p1).AddAssign(&p2)
   941  {{ else}}
   942      var c1 big.Int
   943      c1.SetString("26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194876", 10)
   944      p.ScalarMultiplication(q, &c1)
   945  {{ end}}
   946  
   947  	return p
   948  {{else if eq .Name "bw6-633"}}
   949  {{ if .GLV}}
   950  	var uP, vP, wP, L0, L1, tmp {{$TJacobian}}
   951  	var v, one, uPlusOne, uMinusOne, d1, d2, ht big.Int
   952  	one.SetInt64(1)
   953  	uPlusOne.Add(&one, &xGen)
   954  	uMinusOne.Sub(&xGen, &one)
   955  	d1.SetInt64(13)
   956  	d2.SetInt64(5)
   957  	ht.SetInt64(7)
   958  	v.Mul(&xGen, &xGen).Add(&v, &one).Mul(&v, &uPlusOne)
   959  
   960  	uP.ScalarMultiplication(q, &xGen).Neg(&uP)
   961  	vP.Set(q).SubAssign(&uP).
   962          ScalarMultiplication(&vP, &v)
   963  	wP.ScalarMultiplication(&vP, &uMinusOne).Neg(&wP).
   964          AddAssign(&uP)
   965  	L0.ScalarMultiplication(&wP, &d1)
   966  	tmp.ScalarMultiplication(&vP, &ht)
   967  	L0.AddAssign(&tmp)
   968  	tmp.Double(q)
   969  	L0.AddAssign(&tmp)
   970  	L1.Set(&uP).AddAssign(q).ScalarMultiplication(&L1, &d1)
   971  	tmp.ScalarMultiplication(&vP, &d2)
   972  	L1.AddAssign(&tmp)
   973  	tmp.ScalarMultiplication(q, &ht)
   974  	L1.AddAssign(&tmp)
   975  
   976  	p.phi(&L1).AddAssign(&L0)
   977  {{ else}}
   978      var c1 big.Int
   979      c1.SetString("516166855112631370346774477030598579858367278343565509012644853411927535599366632765988905418773", 10)
   980      p.ScalarMultiplication(q, &c1)
   981  {{ end}}
   982  
   983      return p
   984  {{else if eq .Name "bw6-756"}}
   985  {{ if .GLV}}
   986  	var L0, L1, uP, u2P, u3P, tmp G1Jac
   987  
   988  	uP.ScalarMultiplication(q, &xGen)
   989  	u2P.ScalarMultiplication(&uP, &xGen)
   990  	u3P.ScalarMultiplication(&u2P, &xGen)
   991  
   992  	L0.Set(q).AddAssign(&u3P).
   993  		SubAssign(&u2P)
   994  	tmp.Set(q).AddAssign(&u2P).
   995  		SubAssign(&uP).
   996  		SubAssign(&uP).
   997  		Double(&tmp)
   998  	L0.SubAssign(&tmp).
   999  		SubAssign(q)
  1000  
  1001  	L1.Set(q).AddAssign(&uP)
  1002  	tmp.Set(&uP).SubAssign(q).
  1003  		Double(&tmp).
  1004  		SubAssign(&u2P)
  1005  	L1.AddAssign(&tmp).
  1006  		SubAssign(q)
  1007  
  1008  	p.phi(&L1).
  1009  		AddAssign(&L0)
  1010  {{ else}}
  1011      var c1 big.Int
  1012      c1.SetString("605248206075306171568857128027361794400937215108643640003009340657451546212610770151705515081537938829431808196608", 10)
  1013      p.ScalarMultiplication(q, &c1)
  1014  {{ end}}
  1015  
  1016  	return p
  1017  {{- end}}
  1018  }
  1019  {{ else }}
  1020  
  1021  // ClearCofactor maps a point in curve to r-torsion
  1022  func (p *{{$TJacobian}}) ClearCofactor(q *{{$TJacobian}}) *{{$TJacobian}} {
  1023  {{- if eq .Name "bn254"}}
  1024  	// cf http://cacr.uwaterloo.ca/techreports/2011/cacr2011-26.pdf, 6.1
  1025  	var points [4]{{$TJacobian}}
  1026  
  1027  	points[0].ScalarMultiplication(q, &xGen)
  1028  
  1029  	points[1].Double(&points[0]).
  1030  		AddAssign(&points[0]).
  1031  		psi(&points[1])
  1032  
  1033  	points[2].psi(&points[0]).
  1034  		psi(&points[2])
  1035  
  1036  	points[3].psi(q).psi(&points[3]).psi(&points[3])
  1037  
  1038  	var res {{$TJacobian}}
  1039  	res.Set(&g2Infinity)
  1040  	for i := 0; i < 4; i++ {
  1041  		res.AddAssign(&points[i])
  1042  	}
  1043  	p.Set(&res)
  1044  	return p
  1045  {{else if eq .Name "bls12-381"}}
  1046  	// https://eprint.iacr.org/2017/419.pdf, 4.1
  1047  	var xg, xxg, res, t G2Jac
  1048  	xg.ScalarMultiplication(q, &xGen).Neg(&xg)
  1049  	xxg.ScalarMultiplication(&xg, &xGen).Neg(&xxg)
  1050  
  1051  	res.Set(&xxg).
  1052  		SubAssign(&xg).
  1053  		SubAssign(q)
  1054  
  1055  	t.Set(&xg).
  1056  		SubAssign(q).
  1057  		psi(&t)
  1058  
  1059  	res.AddAssign(&t)
  1060  
  1061  	t.Double(q)
  1062  	t.X.MulByElement(&t.X, &thirdRootOneG1)
  1063  
  1064  	res.SubAssign(&t)
  1065  
  1066  	p.Set(&res)
  1067  
  1068  	return p
  1069  
  1070  {{else if or (eq .Name "bls12-377") (eq .Name "bls12-378")}}
  1071      // https://eprint.iacr.org/2017/419.pdf, 4.1
  1072  	var xg, xxg, res, t G2Jac
  1073  	xg.ScalarMultiplication(q, &xGen)
  1074  	xxg.ScalarMultiplication(&xg, &xGen)
  1075  
  1076  	res.Set(&xxg).
  1077  		SubAssign(&xg).
  1078  		SubAssign(q)
  1079  
  1080  	t.Set(&xg).
  1081  		SubAssign(q).
  1082  		psi(&t)
  1083  
  1084  	res.AddAssign(&t)
  1085  
  1086  	t.Double(q)
  1087  	t.X.MulByElement(&t.X, &thirdRootOneG1)
  1088  
  1089  	res.SubAssign(&t)
  1090  
  1091  	p.Set(&res)
  1092  
  1093  	return p
  1094  
  1095  {{else if or (eq .Name "bls24-315") (eq .Name "bls24-317")}}
  1096  	// https://eprint.iacr.org/2017/419.pdf, section 4.2
  1097  	// multiply by (3x⁴-3)*cofacor
  1098      {{ if eq .Name "bls24-315"}}
  1099  	var xg, xxg, xxxg, xxxxg, res, t G2Jac
  1100  	xg.ScalarMultiplication(q, &xGen).Neg(&xg).SubAssign(q)
  1101  	xxg.ScalarMultiplication(&xg, &xGen).Neg(&xxg)
  1102  	xxxg.ScalarMultiplication(&xxg, &xGen).Neg(&xxxg)
  1103  	xxxxg.ScalarMultiplication(&xxxg, &xGen).Neg(&xxxxg)
  1104      {{ else }}
  1105  	var xg, xxg, xxxg, xxxxg, res, t G2Jac
  1106  	xg.ScalarMultiplication(q, &xGen).SubAssign(q)
  1107  	xxg.ScalarMultiplication(&xg, &xGen)
  1108  	xxxg.ScalarMultiplication(&xxg, &xGen)
  1109  	xxxxg.ScalarMultiplication(&xxxg, &xGen)
  1110      {{ end }}
  1111  
  1112  	res.Set(&xxxxg).
  1113  		SubAssign(q)
  1114  
  1115  	t.Set(&xxxg).
  1116  		psi(&t).
  1117  		AddAssign(&res)
  1118  
  1119  	res.Set(&xxg).
  1120  		psi(&res).
  1121  		psi(&res).
  1122  		AddAssign(&t)
  1123  
  1124  	t.Set(&xg).
  1125  		psi(&t).
  1126  		psi(&t).
  1127  		psi(&t).
  1128  		AddAssign(&res)
  1129  
  1130  	res.Double(q).
  1131  		psi(&res).
  1132  		psi(&res).
  1133  		psi(&res).
  1134  		psi(&res).
  1135  		AddAssign(&t)
  1136  
  1137  	p.Set(&res)
  1138  
  1139  	return p
  1140  {{else if eq .Name "bw6-761"}}
  1141  
  1142  {{- if .GLV}}
  1143  	var points [4]{{$TJacobian}}
  1144  	points[0].Set(q)
  1145  	points[1].ScalarMultiplication(q, &xGen)
  1146  	points[2].ScalarMultiplication(&points[1], &xGen)
  1147  	points[3].ScalarMultiplication(&points[2], &xGen)
  1148  
  1149  	var scalars [7]big.Int
  1150  	scalars[0].SetInt64(103)
  1151  	scalars[1].SetInt64(83)
  1152  	scalars[2].SetInt64(143)
  1153  	scalars[3].SetInt64(27)
  1154  
  1155  	scalars[4].SetInt64(7)
  1156  	scalars[5].SetInt64(117)
  1157  	scalars[6].SetInt64(109)
  1158  
  1159  	var p1, p2, tmp {{$TJacobian}}
  1160  	p1.ScalarMultiplication(&points[3], &scalars[0])
  1161  	tmp.ScalarMultiplication(&points[2], &scalars[1]).Neg(&tmp)
  1162  	p1.AddAssign(&tmp)
  1163  	tmp.ScalarMultiplication(&points[1], &scalars[2]).Neg(&tmp)
  1164  	p1.AddAssign(&tmp)
  1165  	tmp.ScalarMultiplication(&points[0], &scalars[3])
  1166  	p1.AddAssign(&tmp)
  1167  
  1168  	p2.ScalarMultiplication(&points[2], &scalars[4])
  1169  	tmp.ScalarMultiplication(&points[1], &scalars[5]).Neg(&tmp)
  1170  	p2.AddAssign(&tmp)
  1171  	tmp.ScalarMultiplication(&points[0], &scalars[6]).Neg(&tmp)
  1172  	p2.AddAssign(&tmp)
  1173  	p2.phi(&p2).phi(&p2)
  1174  
  1175  	p.Set(&p1).AddAssign(&p2)
  1176  {{else}}
  1177      var c2 big.Int
  1178      c2.SetString("26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194869", 10)
  1179      p.ScalarMultiplication(q, &c2)
  1180  {{end}}
  1181  
  1182  	return p
  1183  {{else if eq .Name "bw6-633"}}
  1184  {{- if .GLV}}
  1185  	var uP, u2P, u3P, u4P, u5P, xP, vP, wP, L0, L1, tmp {{$TJacobian}}
  1186  	var ht, d1, d3 big.Int
  1187  	ht.SetInt64(7) // negative
  1188  	d1.SetInt64(13)
  1189  	d3.SetInt64(5) // negative
  1190  
  1191  	uP.ScalarMultiplication(q, &xGen) // negative
  1192  	u2P.ScalarMultiplication(&uP, &xGen)
  1193  	u3P.ScalarMultiplication(&u2P, &xGen) // negative
  1194  	u4P.ScalarMultiplication(&u3P, &xGen)
  1195  	u5P.ScalarMultiplication(&u4P, &xGen) // negative
  1196  	vP.Set(&u2P).AddAssign(&uP).
  1197  	    AddAssign(&u3P).
  1198  	    Double(&vP).
  1199  	    AddAssign(&u4P).
  1200  	    AddAssign(q)
  1201  	wP.Set(&uP).SubAssign(&u4P).SubAssign(&u5P)
  1202      xP.Set(q).AddAssign(&vP)
  1203  	L0.Set(&uP).SubAssign(q).ScalarMultiplication(&L0, &d1)
  1204  	tmp.ScalarMultiplication(&xP, &d3)
  1205  	L0.AddAssign(&tmp)
  1206      tmp.ScalarMultiplication(q, &ht) // negative
  1207  	L0.SubAssign(&tmp)
  1208  	L1.ScalarMultiplication(&wP, &d1)
  1209  	tmp.ScalarMultiplication(&vP, &ht)
  1210  	L1.AddAssign(&tmp)
  1211  	tmp.ScalarMultiplication(q, &d3)
  1212  	L1.AddAssign(&tmp)
  1213  
  1214  	p.phi(&L1).AddAssign(&L0)
  1215  {{else}}
  1216      var c2 big.Int
  1217      c2.SetString("516166855112631370346774477030598579858367278343565509012644853411927535599366632765988905418768", 10)
  1218      p.ScalarMultiplication(q, &c2)
  1219  {{end}}
  1220  
  1221  	return p
  1222  {{else if eq .Name "bw6-756"}}
  1223  
  1224  {{- if .GLV}}
  1225  	var L0, L1, uP, u2P, u3P, tmp G2Jac
  1226  
  1227  	uP.ScalarMultiplication(q, &xGen)
  1228  	u2P.ScalarMultiplication(&uP, &xGen)
  1229  	u3P.ScalarMultiplication(&u2P, &xGen)
  1230  	// ht=-2, hy=0
  1231  	// d1=1, d2=-1, d3=-1
  1232  
  1233  	L0.Set(q).
  1234  		AddAssign(&u2P).
  1235  		SubAssign(&uP)
  1236  	tmp.Set(&u2P).
  1237  		AddAssign(q).
  1238  		SubAssign(&uP).
  1239  		Double(&tmp)
  1240  	L1.Set(&u3P).
  1241  		SubAssign(&tmp)
  1242  
  1243  	p.phi(&L0).
  1244  		AddAssign(&L1)
  1245  {{else}}
  1246      var c2 big.Int
  1247      c2.SetString("605248206075306171568857128027361794400937215108643640003009340657451546212610770151705515081537938829431808196609", 10)
  1248      p.ScalarMultiplication(q, &c2)
  1249  {{end}}
  1250  
  1251  	return p
  1252  
  1253  {{- end}}
  1254  }
  1255  {{- end}}
  1256  
  1257  
  1258  {{ end }}
  1259  
  1260  {{ if eq .PointName "g1" }}
  1261  // JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique
  1262  // where a1 and a2 are affine points.
  1263  func (p *{{$TJacobian}}) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *{{$TJacobian}} {
  1264  
  1265  	var res, p1, p2 {{$TJacobian}}
  1266  	res.Set(&{{ toLower .PointName }}Infinity)
  1267  	p1.FromAffine(a1)
  1268  	p2.FromAffine(a2)
  1269  
  1270  	var table [15]{{$TJacobian}}
  1271  
  1272  	var k1, k2 big.Int
  1273  	if s1.Sign() == -1 {
  1274  		k1.Neg(s1)
  1275  		table[0].Neg(&p1)
  1276  	} else {
  1277  		k1.Set(s1)
  1278  		table[0].Set(&p1)
  1279  	}
  1280  	if s2.Sign() == -1 {
  1281  		k2.Neg(s2)
  1282  		table[3].Neg(&p2)
  1283  	} else {
  1284  		k2.Set(s2)
  1285  		table[3].Set(&p2)
  1286  	}
  1287  
  1288  	// precompute table (2 bits sliding window)
  1289  	table[1].Double(&table[0])
  1290  	table[2].Set(&table[1]).AddAssign(&table[0])
  1291  	table[4].Set(&table[3]).AddAssign(&table[0])
  1292  	table[5].Set(&table[3]).AddAssign(&table[1])
  1293  	table[6].Set(&table[3]).AddAssign(&table[2])
  1294  	table[7].Double(&table[3])
  1295  	table[8].Set(&table[7]).AddAssign(&table[0])
  1296  	table[9].Set(&table[7]).AddAssign(&table[1])
  1297  	table[10].Set(&table[7]).AddAssign(&table[2])
  1298  	table[11].Set(&table[7]).AddAssign(&table[3])
  1299  	table[12].Set(&table[11]).AddAssign(&table[0])
  1300  	table[13].Set(&table[11]).AddAssign(&table[1])
  1301  	table[14].Set(&table[11]).AddAssign(&table[2])
  1302  
  1303  	var s [2]fr.Element
  1304  	s[0] = s[0].SetBigInt(&k1).Bits()
  1305  	s[1] = s[1].SetBigInt(&k2).Bits()
  1306  
  1307  	maxBit := k1.BitLen()
  1308  	if k2.BitLen() > maxBit {
  1309  		maxBit = k2.BitLen()
  1310  	}
  1311  	hiWordIndex := (maxBit - 1) / 64
  1312  
  1313  	for i := hiWordIndex; i >= 0; i-- {
  1314  		mask := uint64(3) << 62
  1315  		for j := 0; j < 32; j++ {
  1316  			res.Double(&res).Double(&res)
  1317  			b1 := (s[0][i] & mask) >> (62 - 2*j)
  1318  			b2 := (s[1][i] & mask) >> (62 - 2*j)
  1319  			if b1|b2 != 0 {
  1320  				s := (b2<<2 | b1)
  1321  				res.AddAssign(&table[s-1])
  1322  			}
  1323  			mask = mask >> 2
  1324  		}
  1325  	}
  1326  
  1327  	p.Set(&res)
  1328  	return p
  1329  
  1330  }
  1331  
  1332  // JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique
  1333  // where g is the prime subgroup generator.
  1334  func (p *{{$TJacobian}}) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *{{$TJacobian}} {
  1335      return p.JointScalarMultiplication(&g1GenAff, a, s1, s2)
  1336  
  1337  }
  1338  
  1339  {{ end }}
  1340  
  1341  
  1342  // -------------------------------------------------------------------------------------------------
  1343  // extended Jacobian coordinates
  1344  
  1345  // Set sets p to a in extended Jacobian coordinates.
  1346  func (p *{{ $TJacobianExtended }}) Set(q *{{ $TJacobianExtended }}) *{{ $TJacobianExtended }} {
  1347  	p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ
  1348  	return p
  1349  }
  1350  
  1351  // setInfinity sets p to the infinity point (1,1,0,0).
  1352  func (p *{{ $TJacobianExtended }}) setInfinity() *{{ $TJacobianExtended }} {
  1353  	p.X.SetOne()
  1354  	p.Y.SetOne()
  1355  	p.ZZ = {{.CoordType}}{}
  1356  	p.ZZZ = {{.CoordType}}{}
  1357  	return p
  1358  }
  1359  
  1360  // IsInfinity checks if the p is infinity, i.e. p.ZZ=0.
  1361  func (p *{{ $TJacobianExtended }}) IsInfinity() bool {
  1362  	return p.ZZ.IsZero()
  1363  }
  1364  
  1365  // fromJacExtended converts an extended Jacobian point to an affine point.
  1366  func (p *{{ $TAffine }})  fromJacExtended (q *{{ $TJacobianExtended }}) *{{ $TAffine }} {
  1367  	if q.ZZ.IsZero() {
  1368  		p.X = {{.CoordType}}{}
  1369  		p.Y = {{.CoordType}}{}
  1370  		return p
  1371  	}
  1372  	p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X)
  1373  	p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y)
  1374  	return p
  1375  }
  1376  
  1377  // fromJacExtended converts an extended Jacobian point to a Jacobian point.
  1378  func (p *{{ $TJacobian }}) fromJacExtended(q *{{ $TJacobianExtended }}) *{{ $TJacobian }} {
  1379  	if q.ZZ.IsZero() {
  1380  		p.Set(&{{ toLower .PointName }}Infinity)
  1381  		return p
  1382  	}
  1383  	p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ)
  1384  	p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ)
  1385  	p.Z.Set(&q.ZZZ)
  1386  	return p
  1387  }
  1388  
  1389  // unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point.
  1390  func (p *{{ $TJacobian }}) unsafeFromJacExtended(q *{{ $TJacobianExtended }}) *{{ $TJacobian }} {
  1391  	p.X.Square(&q.ZZ).Mul(&p.X, &q.X)
  1392  	p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y)
  1393  	p.Z = q.ZZZ
  1394  	return p
  1395  }
  1396  
  1397  // add sets p to p+q in extended Jacobian coordinates.
  1398  //
  1399  // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s
  1400  func (p *{{ $TJacobianExtended }}) add(q *{{ $TJacobianExtended }}) *{{ $TJacobianExtended }} {
  1401  	//if q is infinity return p
  1402  	if q.ZZ.IsZero() {
  1403  		return p
  1404  	}
  1405  	// p is infinity, return q
  1406  	if p.ZZ.IsZero() {
  1407  		p.Set(q)
  1408  		return p
  1409  	}
  1410  
  1411  	var A, B, U1, U2, S1, S2 {{.CoordType}}
  1412  
  1413  	// p2: q, p1: p
  1414  	U2.Mul(&q.X, &p.ZZ)
  1415  	U1.Mul(&p.X, &q.ZZ)
  1416  	A.Sub(&U2, &U1)
  1417  	S2.Mul(&q.Y, &p.ZZZ)
  1418  	S1.Mul(&p.Y, &q.ZZZ)
  1419  	B.Sub(&S2, &S1)
  1420  
  1421   	if A.IsZero() {
  1422  		if B.IsZero() {
  1423  				return p.double(q)
  1424  
  1425  		}
  1426  		p.ZZ = {{.CoordType}}{}
  1427  		p.ZZZ = {{.CoordType}}{}
  1428  		return p
  1429  	}
  1430  
  1431  
  1432  	var P, R, PP, PPP, Q, V {{.CoordType}}
  1433      P.Sub(&U2, &U1)
  1434      R.Sub(&S2, &S1)
  1435      PP.Square(&P)
  1436      PPP.Mul(&P, &PP)
  1437      Q.Mul(&U1, &PP)
  1438      V.Mul(&S1, &PPP)
  1439  
  1440      p.X.Square(&R).
  1441          Sub(&p.X, &PPP).
  1442          Sub(&p.X, &Q).
  1443          Sub(&p.X, &Q)
  1444      p.Y.Sub(&Q, &p.X).
  1445          Mul(&p.Y, &R).
  1446          Sub(&p.Y, &V)
  1447      p.ZZ.Mul(&p.ZZ, &q.ZZ).
  1448          Mul(&p.ZZ, &PP)
  1449      p.ZZZ.Mul(&p.ZZZ, &q.ZZZ).
  1450          Mul(&p.ZZZ, &PPP)
  1451  
  1452      return p
  1453  }
  1454  
  1455  // double sets p to [2]q in Jacobian extended coordinates.
  1456  //
  1457  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
  1458  // N.B.: since we consider any point on Z=0 as the point at infinity
  1459  // this doubling formula works for infinity points as well.
  1460  func (p *{{ $TJacobianExtended }}) double(q *{{ $TJacobianExtended }}) *{{ $TJacobianExtended }} {
  1461  	var U, V, W, S, XX, M {{.CoordType}}
  1462  
  1463  	U.Double(&q.Y)
  1464  	V.Square(&U)
  1465  	W.Mul(&U, &V)
  1466  	S.Mul(&q.X, &V)
  1467  	XX.Square(&q.X)
  1468  	M.Double(&XX).
  1469  		Add(&M, &XX) // -> + A, but A=0 here
  1470  	U.Mul(&W, &q.Y)
  1471  
  1472  	p.X.Square(&M).
  1473  		Sub(&p.X, &S).
  1474  		Sub(&p.X, &S)
  1475  	p.Y.Sub(&S, &p.X).
  1476  		Mul(&p.Y, &M).
  1477  		Sub(&p.Y, &U)
  1478  	p.ZZ.Mul(&V, &q.ZZ)
  1479  	p.ZZZ.Mul(&W, &q.ZZZ)
  1480  
  1481  	return p
  1482  }
  1483  
  1484  // addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1.
  1485  //
  1486  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
  1487  func (p *{{ $TJacobianExtended }}) addMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} {
  1488  	{{ template "mAdd" dict "all" . "negate" false}}
  1489  }
  1490  
  1491  // subMixed works the same as addMixed, but negates a.Y.
  1492  //
  1493  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
  1494  func (p *{{ $TJacobianExtended }}) subMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} {
  1495  	{{ template "mAdd" dict "all" . "negate" true}}
  1496  }
  1497  
  1498  // doubleNegMixed works the same as double, but negates q.Y.
  1499  func (p *{{ $TJacobianExtended }}) doubleNegMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} {
  1500  	{{ template "mDouble" dict "all" . "negate" true}}
  1501  }
  1502  
  1503  // doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1.
  1504  //
  1505  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
  1506  func (p *{{ $TJacobianExtended }}) doubleMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} {
  1507  	{{ template "mDouble" dict "all" . "negate" false}}
  1508  }
  1509  
  1510  {{define "mDouble" }}
  1511  	var U, V, W, S, XX, M, S2, L {{.all.CoordType}}
  1512  
  1513  	U.Double(&a.Y)
  1514  	{{- if .negate}}
  1515  		U.Neg(&U)
  1516  	{{- end}}
  1517  	V.Square(&U)
  1518      W.Mul(&U, &V)
  1519      S.Mul(&a.X, &V)
  1520      XX.Square(&a.X)
  1521      M.Double(&XX).
  1522          Add(&M, &XX) // -> + A, but A=0 here
  1523      S2.Double(&S)
  1524      L.Mul(&W, &a.Y)
  1525  
  1526      p.X.Square(&M).
  1527          Sub(&p.X, &S2)
  1528      p.Y.Sub(&S, &p.X).
  1529          Mul(&p.Y, &M).
  1530  	{{- if .negate}}
  1531          Add(&p.Y, &L)
  1532  	{{- else}}
  1533          Sub(&p.Y, &L)
  1534  	{{- end}}
  1535      p.ZZ.Set(&V)
  1536      p.ZZZ.Set(&W)
  1537  
  1538  	return p
  1539  {{- end}}
  1540  
  1541  {{define "mAdd" }}
  1542  	//if a is infinity return p
  1543  	if a.IsInfinity() {
  1544  		return p
  1545  	}
  1546  	// p is infinity, return a
  1547  	if p.ZZ.IsZero() {
  1548  		p.X = a.X
  1549  		{{- if .negate}}
  1550  			p.Y.Neg(&a.Y)
  1551  		{{- else }}
  1552  			p.Y = a.Y
  1553  		{{- end}}
  1554  		p.ZZ.SetOne()
  1555  		p.ZZZ.SetOne()
  1556  		return p
  1557  	}
  1558  
  1559  	var P, R {{.all.CoordType}}
  1560  
  1561  	// p2: a, p1: p
  1562  	P.Mul(&a.X, &p.ZZ)
  1563  	P.Sub(&P, &p.X)
  1564  
  1565  	R.Mul(&a.Y, &p.ZZZ)
  1566  	{{- if .negate}}
  1567  		R.Neg(&R)
  1568  	{{- end}}
  1569  	R.Sub(&R, &p.Y)
  1570  
  1571  	if P.IsZero() {
  1572  		if R.IsZero() {
  1573  			{{- if .negate}}
  1574  				return p.doubleNegMixed(a)
  1575  			{{ else }}
  1576  				return p.doubleMixed(a)
  1577  			{{- end}}
  1578  
  1579  		}
  1580  		p.ZZ = {{.all.CoordType}}{}
  1581  		p.ZZZ = {{.all.CoordType}}{}
  1582  		return p
  1583  	}
  1584  
  1585  	var PP, PPP, Q, Q2, RR, X3, Y3 {{.all.CoordType}}
  1586  
  1587  
  1588  	PP.Square(&P)
  1589  	PPP.Mul(&P, &PP)
  1590  	Q.Mul(&p.X, &PP)
  1591  	RR.Square(&R)
  1592  	X3.Sub(&RR, &PPP)
  1593  	Q2.Double(&Q)
  1594  	p.X.Sub(&X3, &Q2)
  1595  	Y3.Sub(&Q, &p.X).Mul(&Y3, &R)
  1596  	R.Mul(&p.Y, &PPP)
  1597  	p.Y.Sub(&Y3, &R)
  1598  	p.ZZ.Mul(&p.ZZ, &PP)
  1599  	p.ZZZ.Mul(&p.ZZZ, &PPP)
  1600  
  1601  	return p
  1602  {{ end }}
  1603  
  1604  
  1605  {{- if .Projective }}
  1606  // -------------------------------------------------------------------------------------------------
  1607  // Homogenous projective coordinates
  1608  
  1609  // Set sets p to a in projective coordinates.
  1610  func (p *{{ $TProjective }}) Set(q *{{ $TProjective }}) *{{ $TProjective }} {
  1611  	p.x, p.y, p.z = q.x, q.y, q.z
  1612  	return p
  1613  }
  1614  
  1615  // Neg sets p to the projective negative point -q = (q.X, -q.Y).
  1616  func (p *{{ $TProjective }}) Neg(q *{{ $TProjective }}) *{{ $TProjective }} {
  1617  	*p = *q
  1618  	p.y.Neg(&q.y)
  1619  	return p
  1620  }
  1621  
  1622  // FromAffine converts q in affine to p in projective coordinates.
  1623  func (p *{{ $TProjective }}) FromAffine(a *{{ $TAffine }}) *{{ $TProjective }} {
  1624  	if a.X.IsZero() && a.Y.IsZero() {
  1625  		p.z.SetZero()
  1626  		p.x.SetOne()
  1627  		p.y.SetOne()
  1628  		return p
  1629  	}
  1630  	p.z.SetOne()
  1631  	p.x.Set(&a.X)
  1632  	p.y.Set(&a.Y)
  1633  	return p
  1634  }
  1635  
  1636  {{end }}
  1637  
  1638  
  1639  {{/* note batch inversion for g2 elements with E2 that is curve specific is a bit more troublesome to implement */}}
  1640  {{- if eq .PointName "g1"}}
  1641  
  1642  // BatchJacobianToAffine{{ toUpper .PointName }} converts points in Jacobian coordinates to Affine coordinates
  1643  // performing a single field inversion using the Montgomery batch inversion trick.
  1644  func BatchJacobianToAffine{{ toUpper .PointName }}(points []{{ $TJacobian }}) []{{ $TAffine }} {
  1645  	result := make([]{{ $TAffine }}, len(points))
  1646  	zeroes := make([]bool, len(points))
  1647  	accumulator := fp.One()
  1648  
  1649  	// batch invert all points[].Z coordinates with Montgomery batch inversion trick
  1650  	// (stores points[].Z^-1 in result[i].X to avoid allocating a slice of fr.Elements)
  1651  	for i:=0; i < len(points); i++ {
  1652  		if points[i].Z.IsZero() {
  1653  			zeroes[i] = true
  1654  			continue
  1655  		}
  1656  		result[i].X = accumulator
  1657  		accumulator.Mul(&accumulator, &points[i].Z)
  1658  	}
  1659  
  1660  	var accInverse fp.Element
  1661  	accInverse.Inverse(&accumulator)
  1662  
  1663  	for i := len(points) - 1; i >= 0; i-- {
  1664  		if zeroes[i] {
  1665  			// do nothing, (X=0, Y=0) is infinity point in affine
  1666  			continue
  1667  		}
  1668  		result[i].X.Mul(&result[i].X, &accInverse)
  1669  		accInverse.Mul(&accInverse, &points[i].Z)
  1670  	}
  1671  
  1672  	// batch convert to affine.
  1673  	parallel.Execute( len(points), func(start, end int) {
  1674  		for i:=start; i < end; i++ {
  1675  			if zeroes[i] {
  1676  				// do nothing, (X=0, Y=0) is infinity point in affine
  1677  				continue
  1678  			}
  1679  			var a, b fp.Element
  1680  			a = result[i].X
  1681  			b.Square(&a)
  1682  			result[i].X.Mul(&points[i].X, &b)
  1683  			result[i].Y.Mul(&points[i].Y, &b).
  1684  				Mul(&result[i].Y, &a)
  1685  		}
  1686  	})
  1687  
  1688      return result
  1689  }
  1690  {{- end}}
  1691  
  1692  
  1693  // BatchScalarMultiplication{{ toUpper .PointName }} multiplies the same base by all scalars
  1694  // and return resulting points in affine coordinates
  1695  // uses a simple windowed-NAF-like multiplication algorithm.
  1696  func BatchScalarMultiplication{{ toUpper .PointName }}(base *{{ $TAffine }}, scalars []fr.Element) []{{ $TAffine }} {
  1697  	// approximate cost in group ops is
  1698  	// cost = 2^{c-1} + n(scalar.nbBits+nbChunks)
  1699  
  1700  	nbPoints := uint64(len(scalars))
  1701  	min := ^uint64(0)
  1702  	bestC := 0
  1703  	for c := 2; c <= 16; c++  {
  1704  		cost := uint64(1 << (c-1)) // pre compute the table
  1705  		nbChunks := computeNbChunks(uint64(c))
  1706  		cost += nbPoints * (uint64(c) + 1) * nbChunks // doublings + point add
  1707  		if cost < min {
  1708  			min = cost
  1709  			bestC = c
  1710  		}
  1711  	}
  1712  	c := uint64(bestC)  // window size
  1713  	nbChunks := int(computeNbChunks(c))
  1714  
  1715  	// last window may be slightly larger than c; in which case we need to compute one
  1716  	// extra element in the baseTable
  1717  	maxC := lastC(c)
  1718  	if c > maxC {
  1719  		maxC = c
  1720  	}
  1721  
  1722  	// precompute all powers of base for our window
  1723  	// note here that if performance is critical, we can implement as in the msmX methods
  1724  	// this allocation to be on the stack
  1725  	baseTable := make([]{{ $TJacobian }}, (1<<(maxC-1)))
  1726  	baseTable[0].FromAffine(base)
  1727  	for i:=1;i<len(baseTable);i++ {
  1728  		baseTable[i] = baseTable[i-1]
  1729  		baseTable[i].AddMixed(base)
  1730  	}
  1731  
  1732  	{{- if eq .PointName "g1"}}
  1733  		// convert our base exp table into affine to use AddMixed
  1734  		baseTableAff := BatchJacobianToAffine{{ toUpper .PointName}}(baseTable)
  1735  		toReturn := make([]{{ $TJacobian }}, len(scalars))
  1736  	{{- else}}
  1737  		toReturn := make([]{{ $TAffine }}, len(scalars))
  1738  	{{- end}}
  1739  
  1740  	// partition the scalars into digits
  1741  	digits, _ := partitionScalars(scalars, c, runtime.NumCPU())
  1742  
  1743  	// for each digit, take value in the base table, double it c time, voilà.
  1744  	parallel.Execute( len(scalars), func(start, end int) {
  1745  		var p {{ $TJacobian }}
  1746  		for i:=start; i < end; i++ {
  1747  			p.Set(&{{ toLower .PointName}}Infinity)
  1748  			for chunk := nbChunks - 1; chunk >=0; chunk-- {
  1749  				if chunk != nbChunks -1 {
  1750  					for j:=uint64(0); j<c; j++ {
  1751  						p.DoubleAssign()
  1752  					}
  1753  				}
  1754  				offset := chunk*len(scalars)
  1755  				digit := digits[i+offset]
  1756  
  1757  				if digit == 0 {
  1758  					continue
  1759  				}
  1760  
  1761  				// if msbWindow bit is set, we need to subtract
  1762  				if digit & 1 == 0 {
  1763  					// add
  1764  					{{- if eq .PointName "g1"}}
  1765  						p.AddMixed(&baseTableAff[(digit >> 1)-1])
  1766  					{{- else}}
  1767  						p.AddAssign(&baseTable[(digit >> 1)-1])
  1768  					{{- end}}
  1769  				} else {
  1770  					// sub
  1771  					{{- if eq .PointName "g1"}}
  1772  						t := baseTableAff[digit >> 1]
  1773  						t.Neg(&t)
  1774  						p.AddMixed(&t)
  1775  					{{- else}}
  1776  						t := baseTable[digit >> 1]
  1777  						t.Neg(&t)
  1778  						p.AddAssign(&t)
  1779  					{{- end}}
  1780  				}
  1781  			}
  1782  
  1783  			// set our result point
  1784  			{{- if eq .PointName "g1"}}
  1785  				toReturn[i] = p
  1786  			{{- else}}
  1787  				toReturn[i].FromJacobian(&p)
  1788  			{{- end}}
  1789  
  1790  		}
  1791  	})
  1792  
  1793  	{{- if eq .PointName "g1"}}
  1794  		toReturnAff := BatchJacobianToAffine{{ toUpper .PointName}}(toReturn)
  1795  		return toReturnAff
  1796  	{{- else}}
  1797  		return toReturn
  1798  	{{- end}}
  1799  }
  1800  
  1801  // batchAdd{{ $TAffine }} adds affine points using the Montgomery batch inversion trick.
  1802  // Special cases (doubling, infinity) must be filtered out before this call.
  1803  func batchAdd{{ $TAffine }}[TP p{{ $TAffine }}, TPP pp{{ $TAffine }}, TC c{{ $TAffine }}](R *TPP,P *TP, batchSize int) {
  1804  	var lambda, lambdain TC
  1805  
  1806  
  1807  	// add part
  1808  	for j := 0; j < batchSize; j++ {
  1809  		lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X)
  1810  	}
  1811  
  1812  	// invert denominator using montgomery batch invert technique
  1813  	{
  1814  		var accumulator {{.CoordType}}
  1815  		lambda[0].SetOne()
  1816  		accumulator.Set(&lambdain[0])
  1817  
  1818  		for i := 1; i < batchSize; i++ {
  1819  			lambda[i] = accumulator
  1820  			accumulator.Mul(&accumulator, &lambdain[i])
  1821  		}
  1822  
  1823  		accumulator.Inverse(&accumulator)
  1824  
  1825  		for i := batchSize - 1; i > 0; i-- {
  1826  			lambda[i].Mul(&lambda[i], &accumulator)
  1827  			accumulator.Mul(&accumulator, &lambdain[i])
  1828  		}
  1829  		lambda[0].Set(&accumulator)
  1830  	}
  1831  
  1832  	var d {{.CoordType}}
  1833  	var rr {{ $TAffine }}
  1834  
  1835  	// add part
  1836  	for j := 0; j < batchSize; j++ {
  1837  		// computa lambda
  1838  		d.Sub(&(*P)[j].Y, &(*R)[j].Y)
  1839  		lambda[j].Mul(&lambda[j], &d)
  1840  
  1841  		// compute X, Y
  1842  		rr.X.Square(&lambda[j])
  1843  		rr.X.Sub(&rr.X, &(*R)[j].X)
  1844  		rr.X.Sub(&rr.X, &(*P)[j].X)
  1845  		d.Sub(&(*R)[j].X, &rr.X)
  1846  		rr.Y.Mul(&lambda[j], &d)
  1847  		rr.Y.Sub(&rr.Y, &(*R)[j].Y)
  1848  		(*R)[j].Set(&rr)
  1849  	}
  1850  }
  1851  
  1852  {{ if eq .PointName "g2"}}
  1853  // RandomOnG2 produces a random point in G2
  1854  // using standard map-to-curve methods, which means the relative discrete log
  1855  // of the generated point with respect to the canonical generator is not known.
  1856  func RandomOnG2() (G2Affine, error) {
  1857  	if gBytes, err := randomFrSizedBytes(); err != nil {
  1858  		return G2Affine{}, err
  1859  	} else {
  1860  		return HashToG2(gBytes, []byte("random on g2"))
  1861  	}
  1862  }
  1863  
  1864  func randomFrSizedBytes() ([]byte, error) {
  1865  	res := make([]byte, fr.Bytes)
  1866  	_, err := rand.Read(res)
  1867  	return res, err
  1868  }
  1869  {{- end}}