github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/g1.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 bw6761
    18  
    19  import (
    20  	"github.com/consensys/gnark-crypto/ecc"
    21  	"github.com/consensys/gnark-crypto/ecc/bw6-761/fp"
    22  	"github.com/consensys/gnark-crypto/ecc/bw6-761/fr"
    23  	"github.com/consensys/gnark-crypto/internal/parallel"
    24  	"math/big"
    25  	"runtime"
    26  )
    27  
    28  // G1Affine is a point in affine coordinates (x,y)
    29  type G1Affine struct {
    30  	X, Y fp.Element
    31  }
    32  
    33  // G1Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³)
    34  type G1Jac struct {
    35  	X, Y, Z fp.Element
    36  }
    37  
    38  // g1JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²)
    39  type g1JacExtended struct {
    40  	X, Y, ZZ, ZZZ fp.Element
    41  }
    42  
    43  // -------------------------------------------------------------------------------------------------
    44  // Affine coordinates
    45  
    46  // Set sets p to a in affine coordinates.
    47  func (p *G1Affine) Set(a *G1Affine) *G1Affine {
    48  	p.X, p.Y = a.X, a.Y
    49  	return p
    50  }
    51  
    52  // setInfinity sets p to the infinity point, which is encoded as (0,0).
    53  // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B).
    54  func (p *G1Affine) setInfinity() *G1Affine {
    55  	p.X.SetZero()
    56  	p.Y.SetZero()
    57  	return p
    58  }
    59  
    60  // ScalarMultiplication computes and returns p = [s]a
    61  // where p and a are affine points.
    62  func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine {
    63  	var _p G1Jac
    64  	_p.FromAffine(a)
    65  	_p.mulGLV(&_p, s)
    66  	p.FromJacobian(&_p)
    67  	return p
    68  }
    69  
    70  // ScalarMultiplicationBase computes and returns p = [s]g
    71  // where g is the affine point generating the prime subgroup.
    72  func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine {
    73  	var _p G1Jac
    74  	_p.mulGLV(&g1Gen, s)
    75  	p.FromJacobian(&_p)
    76  	return p
    77  }
    78  
    79  // Add adds two points in affine coordinates.
    80  // It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates.
    81  //
    82  // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl
    83  func (p *G1Affine) Add(a, b *G1Affine) *G1Affine {
    84  	var q G1Jac
    85  	// a is infinity, return b
    86  	if a.IsInfinity() {
    87  		p.Set(b)
    88  		return p
    89  	}
    90  	// b is infinity, return a
    91  	if b.IsInfinity() {
    92  		p.Set(a)
    93  		return p
    94  	}
    95  	if a.X.Equal(&b.X) {
    96  		// if b == a, we double instead
    97  		if a.Y.Equal(&b.Y) {
    98  			q.DoubleMixed(a)
    99  			return p.FromJacobian(&q)
   100  		} else {
   101  			// if b == -a, we return 0
   102  			return p.setInfinity()
   103  		}
   104  	}
   105  	var H, HH, I, J, r, V fp.Element
   106  	H.Sub(&b.X, &a.X)
   107  	HH.Square(&H)
   108  	I.Double(&HH).Double(&I)
   109  	J.Mul(&H, &I)
   110  	r.Sub(&b.Y, &a.Y)
   111  	r.Double(&r)
   112  	V.Mul(&a.X, &I)
   113  	q.X.Square(&r).
   114  		Sub(&q.X, &J).
   115  		Sub(&q.X, &V).
   116  		Sub(&q.X, &V)
   117  	q.Y.Sub(&V, &q.X).
   118  		Mul(&q.Y, &r)
   119  	J.Mul(&a.Y, &J).Double(&J)
   120  	q.Y.Sub(&q.Y, &J)
   121  	q.Z.Double(&H)
   122  
   123  	return p.FromJacobian(&q)
   124  }
   125  
   126  // Double doubles a point in affine coordinates.
   127  // It converts the point to Jacobian coordinates, doubles it using Jacobian
   128  // addition with a.Z=1, and converts it back to affine coordinates.
   129  //
   130  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
   131  func (p *G1Affine) Double(a *G1Affine) *G1Affine {
   132  	var q G1Jac
   133  	q.FromAffine(a)
   134  	q.DoubleMixed(a)
   135  	p.FromJacobian(&q)
   136  	return p
   137  }
   138  
   139  // Sub subtracts two points in affine coordinates.
   140  // It uses a similar approach to Add, but negates the second point before adding.
   141  func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine {
   142  	var bneg G1Affine
   143  	bneg.Neg(b)
   144  	p.Add(a, &bneg)
   145  	return p
   146  }
   147  
   148  // Equal tests if two points in affine coordinates are equal.
   149  func (p *G1Affine) Equal(a *G1Affine) bool {
   150  	return p.X.Equal(&a.X) && p.Y.Equal(&a.Y)
   151  }
   152  
   153  // Neg sets p to the affine negative point -a = (a.X, -a.Y).
   154  func (p *G1Affine) Neg(a *G1Affine) *G1Affine {
   155  	p.X = a.X
   156  	p.Y.Neg(&a.Y)
   157  	return p
   158  }
   159  
   160  // FromJacobian converts a point p1 from Jacobian to affine coordinates.
   161  func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine {
   162  
   163  	var a, b fp.Element
   164  
   165  	if p1.Z.IsZero() {
   166  		p.X.SetZero()
   167  		p.Y.SetZero()
   168  		return p
   169  	}
   170  
   171  	a.Inverse(&p1.Z)
   172  	b.Square(&a)
   173  	p.X.Mul(&p1.X, &b)
   174  	p.Y.Mul(&p1.Y, &b).Mul(&p.Y, &a)
   175  
   176  	return p
   177  }
   178  
   179  // String returns the string representation E(x,y) of the affine point p or "O" if it is infinity.
   180  func (p *G1Affine) String() string {
   181  	if p.IsInfinity() {
   182  		return "O"
   183  	}
   184  	return "E([" + p.X.String() + "," + p.Y.String() + "])"
   185  }
   186  
   187  // IsInfinity checks if the affine point p is infinity, which is encoded as (0,0).
   188  // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B).
   189  func (p *G1Affine) IsInfinity() bool {
   190  	return p.X.IsZero() && p.Y.IsZero()
   191  }
   192  
   193  // IsOnCurve returns true if the affine point p in on the curve.
   194  func (p *G1Affine) IsOnCurve() bool {
   195  	var point G1Jac
   196  	point.FromAffine(p)
   197  	return point.IsOnCurve() // call this function to handle infinity point
   198  }
   199  
   200  // IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise.
   201  func (p *G1Affine) IsInSubGroup() bool {
   202  	var _p G1Jac
   203  	_p.FromAffine(p)
   204  	return _p.IsInSubGroup()
   205  }
   206  
   207  // -------------------------------------------------------------------------------------------------
   208  // Jacobian coordinates
   209  
   210  // Set sets p to a in Jacobian coordinates.
   211  func (p *G1Jac) Set(q *G1Jac) *G1Jac {
   212  	p.X, p.Y, p.Z = q.X, q.Y, q.Z
   213  	return p
   214  }
   215  
   216  // Equal tests if two points in Jacobian coordinates are equal.
   217  func (p *G1Jac) Equal(q *G1Jac) bool {
   218  	// If one point is infinity, the other must also be infinity.
   219  	if p.Z.IsZero() {
   220  		return q.Z.IsZero()
   221  	}
   222  	// If the other point is infinity, return false since we can't
   223  	// the following checks would be incorrect.
   224  	if q.Z.IsZero() {
   225  		return false
   226  	}
   227  
   228  	var pZSquare, aZSquare fp.Element
   229  	pZSquare.Square(&p.Z)
   230  	aZSquare.Square(&q.Z)
   231  
   232  	var lhs, rhs fp.Element
   233  	lhs.Mul(&p.X, &aZSquare)
   234  	rhs.Mul(&q.X, &pZSquare)
   235  	if !lhs.Equal(&rhs) {
   236  		return false
   237  	}
   238  	lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z)
   239  	rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z)
   240  
   241  	return lhs.Equal(&rhs)
   242  }
   243  
   244  // Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z).
   245  func (p *G1Jac) Neg(q *G1Jac) *G1Jac {
   246  	*p = *q
   247  	p.Y.Neg(&q.Y)
   248  	return p
   249  }
   250  
   251  // AddAssign sets p to p+a in Jacobian coordinates.
   252  //
   253  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
   254  func (p *G1Jac) AddAssign(q *G1Jac) *G1Jac {
   255  
   256  	// p is infinity, return q
   257  	if p.Z.IsZero() {
   258  		p.Set(q)
   259  		return p
   260  	}
   261  
   262  	// q is infinity, return p
   263  	if q.Z.IsZero() {
   264  		return p
   265  	}
   266  
   267  	var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element
   268  	Z1Z1.Square(&q.Z)
   269  	Z2Z2.Square(&p.Z)
   270  	U1.Mul(&q.X, &Z2Z2)
   271  	U2.Mul(&p.X, &Z1Z1)
   272  	S1.Mul(&q.Y, &p.Z).
   273  		Mul(&S1, &Z2Z2)
   274  	S2.Mul(&p.Y, &q.Z).
   275  		Mul(&S2, &Z1Z1)
   276  
   277  	// if p == q, we double instead
   278  	if U1.Equal(&U2) && S1.Equal(&S2) {
   279  		return p.DoubleAssign()
   280  	}
   281  
   282  	H.Sub(&U2, &U1)
   283  	I.Double(&H).
   284  		Square(&I)
   285  	J.Mul(&H, &I)
   286  	r.Sub(&S2, &S1).Double(&r)
   287  	V.Mul(&U1, &I)
   288  	p.X.Square(&r).
   289  		Sub(&p.X, &J).
   290  		Sub(&p.X, &V).
   291  		Sub(&p.X, &V)
   292  	p.Y.Sub(&V, &p.X).
   293  		Mul(&p.Y, &r)
   294  	S1.Mul(&S1, &J).Double(&S1)
   295  	p.Y.Sub(&p.Y, &S1)
   296  	p.Z.Add(&p.Z, &q.Z)
   297  	p.Z.Square(&p.Z).
   298  		Sub(&p.Z, &Z1Z1).
   299  		Sub(&p.Z, &Z2Z2).
   300  		Mul(&p.Z, &H)
   301  
   302  	return p
   303  }
   304  
   305  // SubAssign sets p to p-a in Jacobian coordinates.
   306  // It uses a similar approach to AddAssign, but negates the point a before adding.
   307  func (p *G1Jac) SubAssign(q *G1Jac) *G1Jac {
   308  	var tmp G1Jac
   309  	tmp.Set(q)
   310  	tmp.Y.Neg(&tmp.Y)
   311  	p.AddAssign(&tmp)
   312  	return p
   313  }
   314  
   315  // Double sets p to [2]q in Jacobian coordinates.
   316  //
   317  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   318  func (p *G1Jac) DoubleMixed(a *G1Affine) *G1Jac {
   319  	var XX, YY, YYYY, S, M, T fp.Element
   320  	XX.Square(&a.X)
   321  	YY.Square(&a.Y)
   322  	YYYY.Square(&YY)
   323  	S.Add(&a.X, &YY).
   324  		Square(&S).
   325  		Sub(&S, &XX).
   326  		Sub(&S, &YYYY).
   327  		Double(&S)
   328  	M.Double(&XX).
   329  		Add(&M, &XX) // -> + A, but A=0 here
   330  	T.Square(&M).
   331  		Sub(&T, &S).
   332  		Sub(&T, &S)
   333  	p.X.Set(&T)
   334  	p.Y.Sub(&S, &T).
   335  		Mul(&p.Y, &M)
   336  	YYYY.Double(&YYYY).
   337  		Double(&YYYY).
   338  		Double(&YYYY)
   339  	p.Y.Sub(&p.Y, &YYYY)
   340  	p.Z.Double(&a.Y)
   341  
   342  	return p
   343  }
   344  
   345  // AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1.
   346  //
   347  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
   348  func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac {
   349  
   350  	//if a is infinity return p
   351  	if a.IsInfinity() {
   352  		return p
   353  	}
   354  	// p is infinity, return a
   355  	if p.Z.IsZero() {
   356  		p.X = a.X
   357  		p.Y = a.Y
   358  		p.Z.SetOne()
   359  		return p
   360  	}
   361  
   362  	var Z1Z1, U2, S2, H, HH, I, J, r, V fp.Element
   363  	Z1Z1.Square(&p.Z)
   364  	U2.Mul(&a.X, &Z1Z1)
   365  	S2.Mul(&a.Y, &p.Z).
   366  		Mul(&S2, &Z1Z1)
   367  
   368  	// if p == a, we double instead
   369  	if U2.Equal(&p.X) && S2.Equal(&p.Y) {
   370  		return p.DoubleMixed(a)
   371  	}
   372  
   373  	H.Sub(&U2, &p.X)
   374  	HH.Square(&H)
   375  	I.Double(&HH).Double(&I)
   376  	J.Mul(&H, &I)
   377  	r.Sub(&S2, &p.Y).Double(&r)
   378  	V.Mul(&p.X, &I)
   379  	p.X.Square(&r).
   380  		Sub(&p.X, &J).
   381  		Sub(&p.X, &V).
   382  		Sub(&p.X, &V)
   383  	J.Mul(&J, &p.Y).Double(&J)
   384  	p.Y.Sub(&V, &p.X).
   385  		Mul(&p.Y, &r)
   386  	p.Y.Sub(&p.Y, &J)
   387  	p.Z.Add(&p.Z, &H)
   388  	p.Z.Square(&p.Z).
   389  		Sub(&p.Z, &Z1Z1).
   390  		Sub(&p.Z, &HH)
   391  
   392  	return p
   393  }
   394  
   395  // Double sets p to [2]q in Jacobian coordinates.
   396  //
   397  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   398  func (p *G1Jac) Double(q *G1Jac) *G1Jac {
   399  	p.Set(q)
   400  	p.DoubleAssign()
   401  	return p
   402  }
   403  
   404  // DoubleAssign doubles p in Jacobian coordinates.
   405  //
   406  // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl
   407  func (p *G1Jac) DoubleAssign() *G1Jac {
   408  
   409  	var XX, YY, YYYY, ZZ, S, M, T fp.Element
   410  
   411  	XX.Square(&p.X)
   412  	YY.Square(&p.Y)
   413  	YYYY.Square(&YY)
   414  	ZZ.Square(&p.Z)
   415  	S.Add(&p.X, &YY)
   416  	S.Square(&S).
   417  		Sub(&S, &XX).
   418  		Sub(&S, &YYYY).
   419  		Double(&S)
   420  	M.Double(&XX).Add(&M, &XX)
   421  	p.Z.Add(&p.Z, &p.Y).
   422  		Square(&p.Z).
   423  		Sub(&p.Z, &YY).
   424  		Sub(&p.Z, &ZZ)
   425  	T.Square(&M)
   426  	p.X = T
   427  	T.Double(&S)
   428  	p.X.Sub(&p.X, &T)
   429  	p.Y.Sub(&S, &p.X).
   430  		Mul(&p.Y, &M)
   431  	YYYY.Double(&YYYY).Double(&YYYY).Double(&YYYY)
   432  	p.Y.Sub(&p.Y, &YYYY)
   433  
   434  	return p
   435  }
   436  
   437  // ScalarMultiplication computes and returns p = [s]a
   438  // where p and a are Jacobian points.
   439  // using the GLV technique.
   440  // see https://www.iacr.org/archive/crypto2001/21390189.pdf
   441  func (p *G1Jac) ScalarMultiplication(q *G1Jac, s *big.Int) *G1Jac {
   442  	return p.mulGLV(q, s)
   443  }
   444  
   445  // ScalarMultiplicationBase computes and returns p = [s]g
   446  // where g is the prime subgroup generator.
   447  func (p *G1Jac) ScalarMultiplicationBase(s *big.Int) *G1Jac {
   448  	return p.mulGLV(&g1Gen, s)
   449  
   450  }
   451  
   452  // String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity.
   453  func (p *G1Jac) String() string {
   454  	_p := G1Affine{}
   455  	_p.FromJacobian(p)
   456  	return _p.String()
   457  }
   458  
   459  // FromAffine converts a point a from affine to Jacobian coordinates.
   460  func (p *G1Jac) FromAffine(a *G1Affine) *G1Jac {
   461  	if a.IsInfinity() {
   462  		p.Z.SetZero()
   463  		p.X.SetOne()
   464  		p.Y.SetOne()
   465  		return p
   466  	}
   467  	p.Z.SetOne()
   468  	p.X.Set(&a.X)
   469  	p.Y.Set(&a.Y)
   470  	return p
   471  }
   472  
   473  // IsOnCurve returns true if the Jacobian point p in on the curve.
   474  func (p *G1Jac) IsOnCurve() bool {
   475  	var left, right, tmp, ZZ fp.Element
   476  	left.Square(&p.Y)
   477  	right.Square(&p.X).Mul(&right, &p.X)
   478  	ZZ.Square(&p.Z)
   479  	tmp.Square(&ZZ).Mul(&tmp, &ZZ)
   480  	// Mul tmp by bCurveCoeff=-1
   481  	tmp.Neg(&tmp)
   482  	right.Add(&right, &tmp)
   483  	return left.Equal(&right)
   484  }
   485  
   486  // IsInSubGroup returns true if p is on the r-torsion, false otherwise.
   487  
   488  // Z[r,0]+Z[-lambdaG1Affine, 1] is the kernel
   489  // of (u,v)->u+lambdaG1Affinev mod r. Expressing r, lambdaG1Affine as
   490  // polynomials in x, a short vector of this Zmodule is
   491  // (x+1), (x³-x²+1). So we check that (x+1)p+(x³-x²+1)ϕ(p)
   492  // is the infinity.
   493  func (p *G1Jac) IsInSubGroup() bool {
   494  
   495  	var res, phip G1Jac
   496  	phip.phi(p)
   497  	res.ScalarMultiplication(&phip, &xGen).
   498  		SubAssign(&phip).
   499  		ScalarMultiplication(&res, &xGen).
   500  		ScalarMultiplication(&res, &xGen).
   501  		AddAssign(&phip)
   502  
   503  	phip.ScalarMultiplication(p, &xGen).AddAssign(p).AddAssign(&res)
   504  
   505  	return phip.IsOnCurve() && phip.Z.IsZero()
   506  
   507  }
   508  
   509  // mulWindowed computes the 2-bits windowed double-and-add scalar
   510  // multiplication p=[s]q in Jacobian coordinates.
   511  func (p *G1Jac) mulWindowed(q *G1Jac, s *big.Int) *G1Jac {
   512  
   513  	var res G1Jac
   514  	var ops [3]G1Jac
   515  
   516  	ops[0].Set(q)
   517  	if s.Sign() == -1 {
   518  		ops[0].Neg(&ops[0])
   519  	}
   520  	res.Set(&g1Infinity)
   521  	ops[1].Double(&ops[0])
   522  	ops[2].Set(&ops[0]).AddAssign(&ops[1])
   523  
   524  	b := s.Bytes()
   525  	for i := range b {
   526  		w := b[i]
   527  		mask := byte(0xc0)
   528  		for j := 0; j < 4; j++ {
   529  			res.DoubleAssign().DoubleAssign()
   530  			c := (w & mask) >> (6 - 2*j)
   531  			if c != 0 {
   532  				res.AddAssign(&ops[c-1])
   533  			}
   534  			mask = mask >> 2
   535  		}
   536  	}
   537  	p.Set(&res)
   538  
   539  	return p
   540  
   541  }
   542  
   543  // phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y),
   544  // where w is a third root of unity.
   545  func (p *G1Jac) phi(q *G1Jac) *G1Jac {
   546  	p.Set(q)
   547  	p.X.Mul(&p.X, &thirdRootOneG1)
   548  	return p
   549  }
   550  
   551  // mulGLV computes the scalar multiplication using a windowed-GLV method
   552  //
   553  // see https://www.iacr.org/archive/crypto2001/21390189.pdf
   554  func (p *G1Jac) mulGLV(q *G1Jac, s *big.Int) *G1Jac {
   555  
   556  	var table [15]G1Jac
   557  	var res G1Jac
   558  	var k1, k2 fr.Element
   559  
   560  	res.Set(&g1Infinity)
   561  
   562  	// table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q
   563  	table[0].Set(q)
   564  	table[3].phi(q)
   565  
   566  	// split the scalar, modifies ±q, ϕ(q) accordingly
   567  	k := ecc.SplitScalar(s, &glvBasis)
   568  
   569  	if k[0].Sign() == -1 {
   570  		k[0].Neg(&k[0])
   571  		table[0].Neg(&table[0])
   572  	}
   573  	if k[1].Sign() == -1 {
   574  		k[1].Neg(&k[1])
   575  		table[3].Neg(&table[3])
   576  	}
   577  
   578  	// precompute table (2 bits sliding window)
   579  	// table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0
   580  	table[1].Double(&table[0])
   581  	table[2].Set(&table[1]).AddAssign(&table[0])
   582  	table[4].Set(&table[3]).AddAssign(&table[0])
   583  	table[5].Set(&table[3]).AddAssign(&table[1])
   584  	table[6].Set(&table[3]).AddAssign(&table[2])
   585  	table[7].Double(&table[3])
   586  	table[8].Set(&table[7]).AddAssign(&table[0])
   587  	table[9].Set(&table[7]).AddAssign(&table[1])
   588  	table[10].Set(&table[7]).AddAssign(&table[2])
   589  	table[11].Set(&table[7]).AddAssign(&table[3])
   590  	table[12].Set(&table[11]).AddAssign(&table[0])
   591  	table[13].Set(&table[11]).AddAssign(&table[1])
   592  	table[14].Set(&table[11]).AddAssign(&table[2])
   593  
   594  	// bounds on the lattice base vectors guarantee that k1, k2 are len(r)/2 or len(r)/2+1 bits long max
   595  	// this is because we use a probabilistic scalar decomposition that replaces a division by a right-shift
   596  	k1 = k1.SetBigInt(&k[0]).Bits()
   597  	k2 = k2.SetBigInt(&k[1]).Bits()
   598  
   599  	// we don't target constant-timeness so we check first if we increase the bounds or not
   600  	maxBit := k1.BitLen()
   601  	if k2.BitLen() > maxBit {
   602  		maxBit = k2.BitLen()
   603  	}
   604  	hiWordIndex := (maxBit - 1) / 64
   605  
   606  	// loop starts from len(k1)/2 or len(k1)/2+1 due to the bounds
   607  	for i := hiWordIndex; i >= 0; i-- {
   608  		mask := uint64(3) << 62
   609  		for j := 0; j < 32; j++ {
   610  			res.Double(&res).Double(&res)
   611  			b1 := (k1[i] & mask) >> (62 - 2*j)
   612  			b2 := (k2[i] & mask) >> (62 - 2*j)
   613  			if b1|b2 != 0 {
   614  				s := (b2<<2 | b1)
   615  				res.AddAssign(&table[s-1])
   616  			}
   617  			mask = mask >> 2
   618  		}
   619  	}
   620  
   621  	p.Set(&res)
   622  	return p
   623  }
   624  
   625  // ClearCofactor maps a point in curve to r-torsion
   626  func (p *G1Affine) ClearCofactor(a *G1Affine) *G1Affine {
   627  	var _p G1Jac
   628  	_p.FromAffine(a)
   629  	_p.ClearCofactor(&_p)
   630  	p.FromJacobian(&_p)
   631  	return p
   632  }
   633  
   634  // ClearCofactor maps a point in E(Fp) to E(Fp)[r]
   635  func (p *G1Jac) ClearCofactor(q *G1Jac) *G1Jac {
   636  
   637  	// https://eprint.iacr.org/2020/351.pdf
   638  	var points [4]G1Jac
   639  	points[0].Set(q)
   640  	points[1].ScalarMultiplication(q, &xGen)
   641  	points[2].ScalarMultiplication(&points[1], &xGen)
   642  	points[3].ScalarMultiplication(&points[2], &xGen)
   643  
   644  	var scalars [7]big.Int
   645  	scalars[0].SetInt64(103)
   646  	scalars[1].SetInt64(83)
   647  	scalars[2].SetInt64(40)
   648  	scalars[3].SetInt64(136)
   649  
   650  	scalars[4].SetInt64(7)
   651  	scalars[5].SetInt64(89)
   652  	scalars[6].SetInt64(130)
   653  
   654  	var p1, p2, tmp G1Jac
   655  	p1.ScalarMultiplication(&points[3], &scalars[0])
   656  	tmp.ScalarMultiplication(&points[2], &scalars[1]).Neg(&tmp)
   657  	p1.AddAssign(&tmp)
   658  	tmp.ScalarMultiplication(&points[1], &scalars[2]).Neg(&tmp)
   659  	p1.AddAssign(&tmp)
   660  	tmp.ScalarMultiplication(&points[0], &scalars[3])
   661  	p1.AddAssign(&tmp)
   662  
   663  	p2.ScalarMultiplication(&points[2], &scalars[4])
   664  	tmp.ScalarMultiplication(&points[1], &scalars[5])
   665  	p2.AddAssign(&tmp)
   666  	tmp.ScalarMultiplication(&points[0], &scalars[6])
   667  	p2.AddAssign(&tmp)
   668  	p2.phi(&p2)
   669  
   670  	p.Set(&p1).AddAssign(&p2)
   671  
   672  	return p
   673  
   674  }
   675  
   676  // JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique
   677  // where a1 and a2 are affine points.
   678  func (p *G1Jac) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *G1Jac {
   679  
   680  	var res, p1, p2 G1Jac
   681  	res.Set(&g1Infinity)
   682  	p1.FromAffine(a1)
   683  	p2.FromAffine(a2)
   684  
   685  	var table [15]G1Jac
   686  
   687  	var k1, k2 big.Int
   688  	if s1.Sign() == -1 {
   689  		k1.Neg(s1)
   690  		table[0].Neg(&p1)
   691  	} else {
   692  		k1.Set(s1)
   693  		table[0].Set(&p1)
   694  	}
   695  	if s2.Sign() == -1 {
   696  		k2.Neg(s2)
   697  		table[3].Neg(&p2)
   698  	} else {
   699  		k2.Set(s2)
   700  		table[3].Set(&p2)
   701  	}
   702  
   703  	// precompute table (2 bits sliding window)
   704  	table[1].Double(&table[0])
   705  	table[2].Set(&table[1]).AddAssign(&table[0])
   706  	table[4].Set(&table[3]).AddAssign(&table[0])
   707  	table[5].Set(&table[3]).AddAssign(&table[1])
   708  	table[6].Set(&table[3]).AddAssign(&table[2])
   709  	table[7].Double(&table[3])
   710  	table[8].Set(&table[7]).AddAssign(&table[0])
   711  	table[9].Set(&table[7]).AddAssign(&table[1])
   712  	table[10].Set(&table[7]).AddAssign(&table[2])
   713  	table[11].Set(&table[7]).AddAssign(&table[3])
   714  	table[12].Set(&table[11]).AddAssign(&table[0])
   715  	table[13].Set(&table[11]).AddAssign(&table[1])
   716  	table[14].Set(&table[11]).AddAssign(&table[2])
   717  
   718  	var s [2]fr.Element
   719  	s[0] = s[0].SetBigInt(&k1).Bits()
   720  	s[1] = s[1].SetBigInt(&k2).Bits()
   721  
   722  	maxBit := k1.BitLen()
   723  	if k2.BitLen() > maxBit {
   724  		maxBit = k2.BitLen()
   725  	}
   726  	hiWordIndex := (maxBit - 1) / 64
   727  
   728  	for i := hiWordIndex; i >= 0; i-- {
   729  		mask := uint64(3) << 62
   730  		for j := 0; j < 32; j++ {
   731  			res.Double(&res).Double(&res)
   732  			b1 := (s[0][i] & mask) >> (62 - 2*j)
   733  			b2 := (s[1][i] & mask) >> (62 - 2*j)
   734  			if b1|b2 != 0 {
   735  				s := (b2<<2 | b1)
   736  				res.AddAssign(&table[s-1])
   737  			}
   738  			mask = mask >> 2
   739  		}
   740  	}
   741  
   742  	p.Set(&res)
   743  	return p
   744  
   745  }
   746  
   747  // JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique
   748  // where g is the prime subgroup generator.
   749  func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac {
   750  	return p.JointScalarMultiplication(&g1GenAff, a, s1, s2)
   751  
   752  }
   753  
   754  // -------------------------------------------------------------------------------------------------
   755  // extended Jacobian coordinates
   756  
   757  // Set sets p to a in extended Jacobian coordinates.
   758  func (p *g1JacExtended) Set(q *g1JacExtended) *g1JacExtended {
   759  	p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ
   760  	return p
   761  }
   762  
   763  // setInfinity sets p to the infinity point (1,1,0,0).
   764  func (p *g1JacExtended) setInfinity() *g1JacExtended {
   765  	p.X.SetOne()
   766  	p.Y.SetOne()
   767  	p.ZZ = fp.Element{}
   768  	p.ZZZ = fp.Element{}
   769  	return p
   770  }
   771  
   772  // IsInfinity checks if the p is infinity, i.e. p.ZZ=0.
   773  func (p *g1JacExtended) IsInfinity() bool {
   774  	return p.ZZ.IsZero()
   775  }
   776  
   777  // fromJacExtended converts an extended Jacobian point to an affine point.
   778  func (p *G1Affine) fromJacExtended(q *g1JacExtended) *G1Affine {
   779  	if q.ZZ.IsZero() {
   780  		p.X = fp.Element{}
   781  		p.Y = fp.Element{}
   782  		return p
   783  	}
   784  	p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X)
   785  	p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y)
   786  	return p
   787  }
   788  
   789  // fromJacExtended converts an extended Jacobian point to a Jacobian point.
   790  func (p *G1Jac) fromJacExtended(q *g1JacExtended) *G1Jac {
   791  	if q.ZZ.IsZero() {
   792  		p.Set(&g1Infinity)
   793  		return p
   794  	}
   795  	p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ)
   796  	p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ)
   797  	p.Z.Set(&q.ZZZ)
   798  	return p
   799  }
   800  
   801  // unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point.
   802  func (p *G1Jac) unsafeFromJacExtended(q *g1JacExtended) *G1Jac {
   803  	p.X.Square(&q.ZZ).Mul(&p.X, &q.X)
   804  	p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y)
   805  	p.Z = q.ZZZ
   806  	return p
   807  }
   808  
   809  // add sets p to p+q in extended Jacobian coordinates.
   810  //
   811  // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s
   812  func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended {
   813  	//if q is infinity return p
   814  	if q.ZZ.IsZero() {
   815  		return p
   816  	}
   817  	// p is infinity, return q
   818  	if p.ZZ.IsZero() {
   819  		p.Set(q)
   820  		return p
   821  	}
   822  
   823  	var A, B, U1, U2, S1, S2 fp.Element
   824  
   825  	// p2: q, p1: p
   826  	U2.Mul(&q.X, &p.ZZ)
   827  	U1.Mul(&p.X, &q.ZZ)
   828  	A.Sub(&U2, &U1)
   829  	S2.Mul(&q.Y, &p.ZZZ)
   830  	S1.Mul(&p.Y, &q.ZZZ)
   831  	B.Sub(&S2, &S1)
   832  
   833  	if A.IsZero() {
   834  		if B.IsZero() {
   835  			return p.double(q)
   836  
   837  		}
   838  		p.ZZ = fp.Element{}
   839  		p.ZZZ = fp.Element{}
   840  		return p
   841  	}
   842  
   843  	var P, R, PP, PPP, Q, V fp.Element
   844  	P.Sub(&U2, &U1)
   845  	R.Sub(&S2, &S1)
   846  	PP.Square(&P)
   847  	PPP.Mul(&P, &PP)
   848  	Q.Mul(&U1, &PP)
   849  	V.Mul(&S1, &PPP)
   850  
   851  	p.X.Square(&R).
   852  		Sub(&p.X, &PPP).
   853  		Sub(&p.X, &Q).
   854  		Sub(&p.X, &Q)
   855  	p.Y.Sub(&Q, &p.X).
   856  		Mul(&p.Y, &R).
   857  		Sub(&p.Y, &V)
   858  	p.ZZ.Mul(&p.ZZ, &q.ZZ).
   859  		Mul(&p.ZZ, &PP)
   860  	p.ZZZ.Mul(&p.ZZZ, &q.ZZZ).
   861  		Mul(&p.ZZZ, &PPP)
   862  
   863  	return p
   864  }
   865  
   866  // double sets p to [2]q in Jacobian extended coordinates.
   867  //
   868  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
   869  // N.B.: since we consider any point on Z=0 as the point at infinity
   870  // this doubling formula works for infinity points as well.
   871  func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended {
   872  	var U, V, W, S, XX, M fp.Element
   873  
   874  	U.Double(&q.Y)
   875  	V.Square(&U)
   876  	W.Mul(&U, &V)
   877  	S.Mul(&q.X, &V)
   878  	XX.Square(&q.X)
   879  	M.Double(&XX).
   880  		Add(&M, &XX) // -> + A, but A=0 here
   881  	U.Mul(&W, &q.Y)
   882  
   883  	p.X.Square(&M).
   884  		Sub(&p.X, &S).
   885  		Sub(&p.X, &S)
   886  	p.Y.Sub(&S, &p.X).
   887  		Mul(&p.Y, &M).
   888  		Sub(&p.Y, &U)
   889  	p.ZZ.Mul(&V, &q.ZZ)
   890  	p.ZZZ.Mul(&W, &q.ZZZ)
   891  
   892  	return p
   893  }
   894  
   895  // addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1.
   896  //
   897  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
   898  func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended {
   899  
   900  	//if a is infinity return p
   901  	if a.IsInfinity() {
   902  		return p
   903  	}
   904  	// p is infinity, return a
   905  	if p.ZZ.IsZero() {
   906  		p.X = a.X
   907  		p.Y = a.Y
   908  		p.ZZ.SetOne()
   909  		p.ZZZ.SetOne()
   910  		return p
   911  	}
   912  
   913  	var P, R fp.Element
   914  
   915  	// p2: a, p1: p
   916  	P.Mul(&a.X, &p.ZZ)
   917  	P.Sub(&P, &p.X)
   918  
   919  	R.Mul(&a.Y, &p.ZZZ)
   920  	R.Sub(&R, &p.Y)
   921  
   922  	if P.IsZero() {
   923  		if R.IsZero() {
   924  			return p.doubleMixed(a)
   925  
   926  		}
   927  		p.ZZ = fp.Element{}
   928  		p.ZZZ = fp.Element{}
   929  		return p
   930  	}
   931  
   932  	var PP, PPP, Q, Q2, RR, X3, Y3 fp.Element
   933  
   934  	PP.Square(&P)
   935  	PPP.Mul(&P, &PP)
   936  	Q.Mul(&p.X, &PP)
   937  	RR.Square(&R)
   938  	X3.Sub(&RR, &PPP)
   939  	Q2.Double(&Q)
   940  	p.X.Sub(&X3, &Q2)
   941  	Y3.Sub(&Q, &p.X).Mul(&Y3, &R)
   942  	R.Mul(&p.Y, &PPP)
   943  	p.Y.Sub(&Y3, &R)
   944  	p.ZZ.Mul(&p.ZZ, &PP)
   945  	p.ZZZ.Mul(&p.ZZZ, &PPP)
   946  
   947  	return p
   948  
   949  }
   950  
   951  // subMixed works the same as addMixed, but negates a.Y.
   952  //
   953  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s
   954  func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended {
   955  
   956  	//if a is infinity return p
   957  	if a.IsInfinity() {
   958  		return p
   959  	}
   960  	// p is infinity, return a
   961  	if p.ZZ.IsZero() {
   962  		p.X = a.X
   963  		p.Y.Neg(&a.Y)
   964  		p.ZZ.SetOne()
   965  		p.ZZZ.SetOne()
   966  		return p
   967  	}
   968  
   969  	var P, R fp.Element
   970  
   971  	// p2: a, p1: p
   972  	P.Mul(&a.X, &p.ZZ)
   973  	P.Sub(&P, &p.X)
   974  
   975  	R.Mul(&a.Y, &p.ZZZ)
   976  	R.Neg(&R)
   977  	R.Sub(&R, &p.Y)
   978  
   979  	if P.IsZero() {
   980  		if R.IsZero() {
   981  			return p.doubleNegMixed(a)
   982  
   983  		}
   984  		p.ZZ = fp.Element{}
   985  		p.ZZZ = fp.Element{}
   986  		return p
   987  	}
   988  
   989  	var PP, PPP, Q, Q2, RR, X3, Y3 fp.Element
   990  
   991  	PP.Square(&P)
   992  	PPP.Mul(&P, &PP)
   993  	Q.Mul(&p.X, &PP)
   994  	RR.Square(&R)
   995  	X3.Sub(&RR, &PPP)
   996  	Q2.Double(&Q)
   997  	p.X.Sub(&X3, &Q2)
   998  	Y3.Sub(&Q, &p.X).Mul(&Y3, &R)
   999  	R.Mul(&p.Y, &PPP)
  1000  	p.Y.Sub(&Y3, &R)
  1001  	p.ZZ.Mul(&p.ZZ, &PP)
  1002  	p.ZZZ.Mul(&p.ZZZ, &PPP)
  1003  
  1004  	return p
  1005  
  1006  }
  1007  
  1008  // doubleNegMixed works the same as double, but negates q.Y.
  1009  func (p *g1JacExtended) doubleNegMixed(a *G1Affine) *g1JacExtended {
  1010  
  1011  	var U, V, W, S, XX, M, S2, L fp.Element
  1012  
  1013  	U.Double(&a.Y)
  1014  	U.Neg(&U)
  1015  	V.Square(&U)
  1016  	W.Mul(&U, &V)
  1017  	S.Mul(&a.X, &V)
  1018  	XX.Square(&a.X)
  1019  	M.Double(&XX).
  1020  		Add(&M, &XX) // -> + A, but A=0 here
  1021  	S2.Double(&S)
  1022  	L.Mul(&W, &a.Y)
  1023  
  1024  	p.X.Square(&M).
  1025  		Sub(&p.X, &S2)
  1026  	p.Y.Sub(&S, &p.X).
  1027  		Mul(&p.Y, &M).
  1028  		Add(&p.Y, &L)
  1029  	p.ZZ.Set(&V)
  1030  	p.ZZZ.Set(&W)
  1031  
  1032  	return p
  1033  }
  1034  
  1035  // doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1.
  1036  //
  1037  // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
  1038  func (p *g1JacExtended) doubleMixed(a *G1Affine) *g1JacExtended {
  1039  
  1040  	var U, V, W, S, XX, M, S2, L fp.Element
  1041  
  1042  	U.Double(&a.Y)
  1043  	V.Square(&U)
  1044  	W.Mul(&U, &V)
  1045  	S.Mul(&a.X, &V)
  1046  	XX.Square(&a.X)
  1047  	M.Double(&XX).
  1048  		Add(&M, &XX) // -> + A, but A=0 here
  1049  	S2.Double(&S)
  1050  	L.Mul(&W, &a.Y)
  1051  
  1052  	p.X.Square(&M).
  1053  		Sub(&p.X, &S2)
  1054  	p.Y.Sub(&S, &p.X).
  1055  		Mul(&p.Y, &M).
  1056  		Sub(&p.Y, &L)
  1057  	p.ZZ.Set(&V)
  1058  	p.ZZZ.Set(&W)
  1059  
  1060  	return p
  1061  }
  1062  
  1063  // BatchJacobianToAffineG1 converts points in Jacobian coordinates to Affine coordinates
  1064  // performing a single field inversion using the Montgomery batch inversion trick.
  1065  func BatchJacobianToAffineG1(points []G1Jac) []G1Affine {
  1066  	result := make([]G1Affine, len(points))
  1067  	zeroes := make([]bool, len(points))
  1068  	accumulator := fp.One()
  1069  
  1070  	// batch invert all points[].Z coordinates with Montgomery batch inversion trick
  1071  	// (stores points[].Z^-1 in result[i].X to avoid allocating a slice of fr.Elements)
  1072  	for i := 0; i < len(points); i++ {
  1073  		if points[i].Z.IsZero() {
  1074  			zeroes[i] = true
  1075  			continue
  1076  		}
  1077  		result[i].X = accumulator
  1078  		accumulator.Mul(&accumulator, &points[i].Z)
  1079  	}
  1080  
  1081  	var accInverse fp.Element
  1082  	accInverse.Inverse(&accumulator)
  1083  
  1084  	for i := len(points) - 1; i >= 0; i-- {
  1085  		if zeroes[i] {
  1086  			// do nothing, (X=0, Y=0) is infinity point in affine
  1087  			continue
  1088  		}
  1089  		result[i].X.Mul(&result[i].X, &accInverse)
  1090  		accInverse.Mul(&accInverse, &points[i].Z)
  1091  	}
  1092  
  1093  	// batch convert to affine.
  1094  	parallel.Execute(len(points), func(start, end int) {
  1095  		for i := start; i < end; i++ {
  1096  			if zeroes[i] {
  1097  				// do nothing, (X=0, Y=0) is infinity point in affine
  1098  				continue
  1099  			}
  1100  			var a, b fp.Element
  1101  			a = result[i].X
  1102  			b.Square(&a)
  1103  			result[i].X.Mul(&points[i].X, &b)
  1104  			result[i].Y.Mul(&points[i].Y, &b).
  1105  				Mul(&result[i].Y, &a)
  1106  		}
  1107  	})
  1108  
  1109  	return result
  1110  }
  1111  
  1112  // BatchScalarMultiplicationG1 multiplies the same base by all scalars
  1113  // and return resulting points in affine coordinates
  1114  // uses a simple windowed-NAF-like multiplication algorithm.
  1115  func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affine {
  1116  	// approximate cost in group ops is
  1117  	// cost = 2^{c-1} + n(scalar.nbBits+nbChunks)
  1118  
  1119  	nbPoints := uint64(len(scalars))
  1120  	min := ^uint64(0)
  1121  	bestC := 0
  1122  	for c := 2; c <= 16; c++ {
  1123  		cost := uint64(1 << (c - 1)) // pre compute the table
  1124  		nbChunks := computeNbChunks(uint64(c))
  1125  		cost += nbPoints * (uint64(c) + 1) * nbChunks // doublings + point add
  1126  		if cost < min {
  1127  			min = cost
  1128  			bestC = c
  1129  		}
  1130  	}
  1131  	c := uint64(bestC) // window size
  1132  	nbChunks := int(computeNbChunks(c))
  1133  
  1134  	// last window may be slightly larger than c; in which case we need to compute one
  1135  	// extra element in the baseTable
  1136  	maxC := lastC(c)
  1137  	if c > maxC {
  1138  		maxC = c
  1139  	}
  1140  
  1141  	// precompute all powers of base for our window
  1142  	// note here that if performance is critical, we can implement as in the msmX methods
  1143  	// this allocation to be on the stack
  1144  	baseTable := make([]G1Jac, (1 << (maxC - 1)))
  1145  	baseTable[0].FromAffine(base)
  1146  	for i := 1; i < len(baseTable); i++ {
  1147  		baseTable[i] = baseTable[i-1]
  1148  		baseTable[i].AddMixed(base)
  1149  	}
  1150  	// convert our base exp table into affine to use AddMixed
  1151  	baseTableAff := BatchJacobianToAffineG1(baseTable)
  1152  	toReturn := make([]G1Jac, len(scalars))
  1153  
  1154  	// partition the scalars into digits
  1155  	digits, _ := partitionScalars(scalars, c, runtime.NumCPU())
  1156  
  1157  	// for each digit, take value in the base table, double it c time, voilà.
  1158  	parallel.Execute(len(scalars), func(start, end int) {
  1159  		var p G1Jac
  1160  		for i := start; i < end; i++ {
  1161  			p.Set(&g1Infinity)
  1162  			for chunk := nbChunks - 1; chunk >= 0; chunk-- {
  1163  				if chunk != nbChunks-1 {
  1164  					for j := uint64(0); j < c; j++ {
  1165  						p.DoubleAssign()
  1166  					}
  1167  				}
  1168  				offset := chunk * len(scalars)
  1169  				digit := digits[i+offset]
  1170  
  1171  				if digit == 0 {
  1172  					continue
  1173  				}
  1174  
  1175  				// if msbWindow bit is set, we need to subtract
  1176  				if digit&1 == 0 {
  1177  					// add
  1178  					p.AddMixed(&baseTableAff[(digit>>1)-1])
  1179  				} else {
  1180  					// sub
  1181  					t := baseTableAff[digit>>1]
  1182  					t.Neg(&t)
  1183  					p.AddMixed(&t)
  1184  				}
  1185  			}
  1186  
  1187  			// set our result point
  1188  			toReturn[i] = p
  1189  
  1190  		}
  1191  	})
  1192  	toReturnAff := BatchJacobianToAffineG1(toReturn)
  1193  	return toReturnAff
  1194  }
  1195  
  1196  // batchAddG1Affine adds affine points using the Montgomery batch inversion trick.
  1197  // Special cases (doubling, infinity) must be filtered out before this call.
  1198  func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, batchSize int) {
  1199  	var lambda, lambdain TC
  1200  
  1201  	// add part
  1202  	for j := 0; j < batchSize; j++ {
  1203  		lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X)
  1204  	}
  1205  
  1206  	// invert denominator using montgomery batch invert technique
  1207  	{
  1208  		var accumulator fp.Element
  1209  		lambda[0].SetOne()
  1210  		accumulator.Set(&lambdain[0])
  1211  
  1212  		for i := 1; i < batchSize; i++ {
  1213  			lambda[i] = accumulator
  1214  			accumulator.Mul(&accumulator, &lambdain[i])
  1215  		}
  1216  
  1217  		accumulator.Inverse(&accumulator)
  1218  
  1219  		for i := batchSize - 1; i > 0; i-- {
  1220  			lambda[i].Mul(&lambda[i], &accumulator)
  1221  			accumulator.Mul(&accumulator, &lambdain[i])
  1222  		}
  1223  		lambda[0].Set(&accumulator)
  1224  	}
  1225  
  1226  	var d fp.Element
  1227  	var rr G1Affine
  1228  
  1229  	// add part
  1230  	for j := 0; j < batchSize; j++ {
  1231  		// computa lambda
  1232  		d.Sub(&(*P)[j].Y, &(*R)[j].Y)
  1233  		lambda[j].Mul(&lambda[j], &d)
  1234  
  1235  		// compute X, Y
  1236  		rr.X.Square(&lambda[j])
  1237  		rr.X.Sub(&rr.X, &(*R)[j].X)
  1238  		rr.X.Sub(&rr.X, &(*P)[j].X)
  1239  		d.Sub(&(*R)[j].X, &rr.X)
  1240  		rr.Y.Mul(&lambda[j], &d)
  1241  		rr.Y.Sub(&rr.Y, &(*R)[j].Y)
  1242  		(*R)[j].Set(&rr)
  1243  	}
  1244  }