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

     1  import (
     2  	"crypto/subtle"
     3  	"io"
     4  	"math/big"
     5  	"math/bits"
     6  
     7  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr"
     8  )
     9  
    10  // PointAffine point on a twisted Edwards curve
    11  type PointAffine struct {
    12  	X, Y fr.Element
    13  }
    14  
    15  // PointProj point in projective coordinates
    16  type PointProj struct {
    17  	X, Y, Z fr.Element
    18  }
    19  
    20  // PointExtended point in extended coordinates
    21  type PointExtended struct {
    22  	X, Y, Z, T fr.Element
    23  }
    24  
    25  const (
    26  	//following https://tools.ietf.org/html/rfc8032#section-3.1,
    27  	// an fr element x is negative if its binary encoding is
    28  	// lexicographically larger than -x.
    29  	mCompressedNegative = 0x80
    30  	mCompressedPositive = 0x00
    31  	mUnmask             = 0x7f
    32  
    33  	// size in byte of a compressed point (point.Y --> fr.Element)
    34  	sizePointCompressed = fr.Bytes
    35  )
    36  
    37  // Bytes returns the compressed point as a byte array
    38  // Follows https://tools.ietf.org/html/rfc8032#section-3.1,
    39  // as the twisted Edwards implementation is primarily used
    40  // for eddsa.
    41  func (p *PointAffine) Bytes() [sizePointCompressed]byte {
    42  
    43  	var res [sizePointCompressed]byte
    44  	var mask uint
    45  
    46  	y := p.Y.Bytes()
    47  
    48  	if p.X.LexicographicallyLargest() {
    49  		mask = mCompressedNegative
    50  	} else {
    51  		mask = mCompressedPositive
    52  	}
    53  	// p.Y must be in little endian
    54  	y[0] |= byte(mask) // msb of y
    55  	for i, j := 0, sizePointCompressed-1; i < j; i, j = i+1, j-1 {
    56  		y[i], y[j] = y[j], y[i]
    57  	}
    58  	subtle.ConstantTimeCopy(1, res[:], y[:])
    59  	return res
    60  }
    61  
    62  // Marshal converts p to a byte slice
    63  func (p *PointAffine) Marshal() []byte {
    64  	b := p.Bytes()
    65  	return b[:]
    66  }
    67  
    68  func computeX(y *fr.Element) (x fr.Element) {
    69  	initOnce.Do(initCurveParams)
    70  
    71  	var one, num, den fr.Element
    72  	one.SetOne()
    73  	num.Square(y)
    74  	den.Mul(&num, &curveParams.D)
    75  	num.Sub(&one, &num)
    76  	den.Sub(&curveParams.A, &den)
    77  	x.Div(&num, &den)
    78  	x.Sqrt(&x)
    79  	return
    80  }
    81  
    82  // SetBytes sets p from buf
    83  // len(buf) >= sizePointCompressed
    84  // buf contains the Y coordinate masked with a parity bit to recompute the X coordinate
    85  // from the curve equation. See Bytes() and https://tools.ietf.org/html/rfc8032#section-3.1
    86  // Returns the number of read bytes and an error if the buffer is too short.
    87  func (p *PointAffine) SetBytes(buf []byte) (int, error) {
    88  
    89  	if len(buf) < sizePointCompressed {
    90  		return 0, io.ErrShortBuffer
    91  	}
    92  	bufCopy := make([]byte, sizePointCompressed)
    93  	subtle.ConstantTimeCopy(1, bufCopy, buf[:sizePointCompressed])
    94  	for i, j := 0, sizePointCompressed-1; i < j; i, j = i+1, j-1 {
    95  		bufCopy[i], bufCopy[j] = bufCopy[j], bufCopy[i]
    96  	}
    97  	isLexicographicallyLargest := (mCompressedNegative&bufCopy[0])>>7 == 1
    98  	bufCopy[0] &= mUnmask
    99  	p.Y.SetBytes(bufCopy)
   100  	p.X = computeX(&p.Y)
   101  	if isLexicographicallyLargest {
   102  		if !p.X.LexicographicallyLargest() {
   103  			p.X.Neg(&p.X)
   104  		}
   105  	} else {
   106  		if p.X.LexicographicallyLargest() {
   107  			p.X.Neg(&p.X)
   108  		}
   109  	}
   110  
   111  	return sizePointCompressed, nil
   112  }
   113  
   114  // Unmarshal alias to SetBytes()
   115  func (p *PointAffine) Unmarshal(b []byte) error {
   116  	_, err := p.SetBytes(b)
   117  	return err
   118  }
   119  
   120  // Set sets p to p1 and return it
   121  func (p *PointAffine) Set(p1 *PointAffine) *PointAffine {
   122  	p.X.Set(&p1.X)
   123  	p.Y.Set(&p1.Y)
   124  	return p
   125  }
   126  
   127  // Equal returns true if p=p1 false otherwise
   128  func (p *PointAffine) Equal(p1 *PointAffine) bool {
   129  	return p.X.Equal(&p1.X) && p.Y.Equal(&p1.Y)
   130  }
   131  
   132  // IsZero returns true if p=0 false otherwise
   133  func (p *PointAffine) IsZero() bool {
   134  	var one fr.Element
   135  	one.SetOne()
   136  	return p.X.IsZero() && p.Y.Equal(&one)
   137  }
   138  
   139  // NewPointAffine creates a new instance of PointAffine
   140  func NewPointAffine(x, y fr.Element) PointAffine {
   141  	return PointAffine{x, y}
   142  }
   143  
   144  // IsOnCurve checks if a point is on the twisted Edwards curve
   145  func (p *PointAffine) IsOnCurve() bool {
   146  	initOnce.Do(initCurveParams)
   147  
   148  	var lhs, rhs, tmp fr.Element
   149  
   150  	tmp.Mul(&p.Y, &p.Y)
   151  	lhs.Mul(&p.X, &p.X)
   152  	mulByA(&lhs)
   153  	lhs.Add(&lhs, &tmp)
   154  
   155  	tmp.Mul(&p.X, &p.X).
   156  		Mul(&tmp, &p.Y).
   157  		Mul(&tmp, &p.Y).
   158  		Mul(&tmp, &curveParams.D)
   159  	rhs.SetOne().Add(&rhs, &tmp)
   160  
   161  	return lhs.Equal(&rhs)
   162  }
   163  
   164  // Neg sets p to -p1 and returns it
   165  func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
   166  	p.X.Neg(&p1.X)
   167  	p.Y = p1.Y
   168  	return p
   169  }
   170  
   171  // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
   172  // modifies p
   173  func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
   174  	initOnce.Do(initCurveParams)
   175  
   176  	var xu, yv, xv, yu, dxyuv, one, denx, deny fr.Element
   177  	pRes := new(PointAffine)
   178  	xv.Mul(&p1.X, &p2.Y)
   179  	yu.Mul(&p1.Y, &p2.X)
   180  	pRes.X.Add(&xv, &yu)
   181  
   182  	xu.Mul(&p1.X, &p2.X)
   183  	mulByA(&xu)
   184  	yv.Mul(&p1.Y, &p2.Y)
   185  	pRes.Y.Sub(&yv, &xu)
   186  
   187  	dxyuv.Mul(&xv, &yu).Mul(&dxyuv, &curveParams.D)
   188  	one.SetOne()
   189  	denx.Add(&one, &dxyuv)
   190  	deny.Sub(&one, &dxyuv)
   191  
   192  	p.X.Div(&pRes.X, &denx)
   193  	p.Y.Div(&pRes.Y, &deny)
   194  
   195  	return p
   196  }
   197  
   198  // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
   199  // modifies p
   200  func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
   201  
   202  	p.Set(p1)
   203  	var xx, yy, xy, denum, two fr.Element
   204  
   205  	xx.Square(&p.X)
   206  	yy.Square(&p.Y)
   207  	xy.Mul(&p.X, &p.Y)
   208  	mulByA(&xx)
   209  	denum.Add(&xx, &yy)
   210  
   211  	p.X.Double(&xy).Div(&p.X, &denum)
   212  
   213  	two.SetOne().Double(&two)
   214  	denum.Neg(&denum).Add(&denum, &two)
   215  
   216  	p.Y.Sub(&yy, &xx).Div(&p.Y, &denum)
   217  
   218  	return p
   219  }
   220  
   221  // FromProj sets p in affine from p in projective
   222  func (p *PointAffine) FromProj(p1 *PointProj) *PointAffine {
   223  	var I fr.Element
   224  	I.Inverse(&p1.Z)
   225  	p.X.Mul(&p1.X, &I)
   226  	p.Y.Mul(&p1.Y, &I)
   227  	return p
   228  }
   229  
   230  // FromExtended sets p in affine from p in extended coordinates
   231  func (p *PointAffine) FromExtended(p1 *PointExtended) *PointAffine {
   232  	var I fr.Element
   233  	I.Inverse(&p1.Z)
   234  	p.X.Mul(&p1.X, &I)
   235  	p.Y.Mul(&p1.Y, &I)
   236  	return p
   237  }
   238  
   239  // ScalarMultiplication scalar multiplication of a point
   240  // p1 in affine coordinates with a scalar in big.Int
   241  func (p *PointAffine) ScalarMultiplication(p1 *PointAffine, scalar *big.Int) *PointAffine {
   242  
   243  	var p1Extended, resExtended PointExtended
   244  	p1Extended.FromAffine(p1)
   245  	resExtended.ScalarMultiplication(&p1Extended, scalar)
   246  	p.FromExtended(&resExtended)
   247  
   248  	return p
   249  }
   250  
   251  // setInfinity sets p to O (0:1)
   252  func (p *PointAffine) setInfinity() *PointAffine {
   253         p.X.SetZero()
   254         p.Y.SetOne()
   255         return p
   256  }
   257  
   258  //-------- Projective coordinates
   259  
   260  // Set sets p to p1 and return it
   261  func (p *PointProj) Set(p1 *PointProj) *PointProj {
   262  	p.X.Set(&p1.X)
   263  	p.Y.Set(&p1.Y)
   264  	p.Z.Set(&p1.Z)
   265  	return p
   266  }
   267  
   268  // setInfinity sets p to O (0:1:1)
   269  func (p *PointProj) setInfinity() *PointProj {
   270  	p.X.SetZero()
   271  	p.Y.SetOne()
   272  	p.Z.SetOne()
   273  	return p
   274  }
   275  
   276  // Equal returns true if p=p1 false otherwise
   277  // If one point is on the affine chart Z=0 it returns false
   278  func (p *PointProj) Equal(p1 *PointProj) bool {
   279  	// If one point is infinity, the other must also be infinity.
   280  	if p.Z.IsZero()  {
   281  		return p1.Z.IsZero()
   282  	}
   283  	// If the other point is infinity, return false since we can't
   284  	// the following checks would be incorrect.
   285  	if p1.Z.IsZero() {
   286  		return false
   287  	}
   288  
   289  	var lhs, rhs fr.Element
   290  	lhs.Mul(&p.X, &p1.Z)
   291  	rhs.Mul(&p1.X, &p.Z)
   292  	if !lhs.Equal(&rhs) {
   293  		return false
   294  	}
   295  	lhs.Mul(&p.Y, &p1.Z)
   296  	rhs.Mul(&p1.Y, &p.Z)
   297  
   298  	return lhs.Equal(&rhs)
   299  }
   300  
   301  // IsZero returns true if p=0 false otherwise
   302  func (p *PointProj) IsZero() bool {
   303  	return p.X.IsZero() && p.Y.Equal(&p.Z)
   304  }
   305  
   306  // Neg negates point (x,y) on a twisted Edwards curve with parameters a, d
   307  // modifies p
   308  func (p *PointProj) Neg(p1 *PointProj) *PointProj {
   309  	p.X.Neg(&p1.X)
   310  	p.Y = p1.Y
   311  	p.Z = p1.Z
   312  	return p
   313  }
   314  
   315  // FromAffine sets p in projective from p in affine
   316  func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
   317  	p.X.Set(&p1.X)
   318  	p.Y.Set(&p1.Y)
   319  	p.Z.SetOne()
   320  	return p
   321  }
   322  
   323  // MixedAdd adds a point in projective to a point in affine coordinates
   324  // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
   325  func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
   326  	initOnce.Do(initCurveParams)
   327  
   328  	var B, C, D, E, F, G, H, I fr.Element
   329  	B.Square(&p1.Z)
   330  	C.Mul(&p1.X, &p2.X)
   331  	D.Mul(&p1.Y, &p2.Y)
   332  	E.Mul(&curveParams.D, &C).Mul(&E, &D)
   333  	F.Sub(&B, &E)
   334  	G.Add(&B, &E)
   335  	H.Add(&p1.X, &p1.Y)
   336  	I.Add(&p2.X, &p2.Y)
   337  	p.X.Mul(&H, &I).
   338  		Sub(&p.X, &C).
   339  		Sub(&p.X, &D).
   340  		Mul(&p.X, &p1.Z).
   341  		Mul(&p.X, &F)
   342  	mulByA(&C)
   343  	p.Y.Sub(&D, &C).
   344  		Mul(&p.Y, &p1.Z).
   345  		Mul(&p.Y, &G)
   346  	p.Z.Mul(&F, &G)
   347  
   348  	return p
   349  }
   350  
   351  // Double adds points in projective coordinates
   352  // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
   353  func (p *PointProj) Double(p1 *PointProj) *PointProj {
   354  
   355  	var B, C, D, E, F, H, J fr.Element
   356  
   357  	B.Add(&p1.X, &p1.Y).Square(&B)
   358  	C.Square(&p1.X)
   359  	D.Square(&p1.Y)
   360  	E.Set(&C)
   361  	mulByA(&E)
   362  	F.Add(&E, &D)
   363  	H.Square(&p1.Z)
   364  	J.Sub(&F, &H).Sub(&J, &H)
   365  	p.X.Sub(&B, &C).
   366  		Sub(&p.X, &D).
   367  		Mul(&p.X, &J)
   368  	p.Y.Sub(&E, &D).Mul(&p.Y, &F)
   369  	p.Z.Mul(&F, &J)
   370  
   371  	return p
   372  }
   373  
   374  // Add adds points in projective coordinates
   375  // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
   376  func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
   377  	initOnce.Do(initCurveParams)
   378  
   379  	var A, B, C, D, E, F, G, H, I fr.Element
   380  	A.Mul(&p1.Z, &p2.Z)
   381  	B.Square(&A)
   382  	C.Mul(&p1.X, &p2.X)
   383  	D.Mul(&p1.Y, &p2.Y)
   384  	E.Mul(&curveParams.D, &C).Mul(&E, &D)
   385  	F.Sub(&B, &E)
   386  	G.Add(&B, &E)
   387  	H.Add(&p1.X, &p1.Y)
   388  	I.Add(&p2.X, &p2.Y)
   389  	p.X.Mul(&H, &I).
   390  		Sub(&p.X, &C).
   391  		Sub(&p.X, &D).
   392  		Mul(&p.X, &A).
   393  		Mul(&p.X, &F)
   394  	mulByA(&C)
   395  	C.Neg(&C)
   396  	p.Y.Add(&D, &C).
   397  		Mul(&p.Y, &A).
   398  		Mul(&p.Y, &G)
   399  	p.Z.Mul(&F, &G)
   400  
   401  	return p
   402  }
   403  
   404  // scalarMulWindowed scalar multiplication of a point
   405  // p1 in projective coordinates with a scalar in big.Int
   406  // using the windowed double-and-add method.
   407  func (p *PointProj) scalarMulWindowed(p1 *PointProj, scalar *big.Int) *PointProj {
   408  	var _scalar big.Int
   409  	_scalar.Set(scalar)
   410  	p.Set(p1)
   411  	if _scalar.Sign() == -1 {
   412  		_scalar.Neg(&_scalar)
   413  		p.Neg(p)
   414  	}
   415  	var resProj PointProj
   416  	resProj.setInfinity()
   417  	const wordSize = bits.UintSize
   418  	sWords := _scalar.Bits()
   419  
   420  	for i := len(sWords) - 1; i >= 0; i-- {
   421  		ithWord := sWords[i]
   422  		for k := 0; k < wordSize; k++ {
   423  			resProj.Double(&resProj)
   424  			kthBit := (ithWord >> (wordSize - 1 - k)) & 1
   425  			if kthBit == 1 {
   426  				resProj.Add(&resProj, p)
   427  			}
   428  		}
   429  	}
   430  
   431  	p.Set(&resProj)
   432  	return p
   433  }
   434  
   435  // ScalarMultiplication scalar multiplication of a point
   436  // p1 in projective coordinates with a scalar in big.Int
   437  func (p *PointProj) ScalarMultiplication(p1 *PointProj, scalar *big.Int) *PointProj {
   438  	{{- if .HasEndomorphism}}
   439  		return p.scalarMulGLV(p1, scalar)
   440  	{{- else }}
   441  		return p.scalarMulWindowed(p1, scalar)
   442  	{{- end}}
   443  }
   444  
   445  // ------- Extended coordinates
   446  
   447  // Set sets p to p1 and return it
   448  func (p *PointExtended) Set(p1 *PointExtended) *PointExtended {
   449  	p.X.Set(&p1.X)
   450  	p.Y.Set(&p1.Y)
   451  	p.T.Set(&p1.T)
   452  	p.Z.Set(&p1.Z)
   453  	return p
   454  }
   455  
   456  // IsZero returns true if p=0 false otherwise
   457  func (p *PointExtended) IsZero() bool {
   458  	return p.X.IsZero() && p.Y.Equal(&p.Z) && p.T.IsZero()
   459  }
   460  
   461  // Equal returns true if p=p1 false otherwise
   462  // If one point is on the affine chart Z=0 it returns false
   463  func (p *PointExtended) Equal(p1 *PointExtended) bool {
   464  	if p.Z.IsZero() || p1.Z.IsZero() {
   465  		return false
   466  	}
   467  	var pAffine, p1Affine PointAffine
   468  	pAffine.FromExtended(p)
   469  	p1Affine.FromExtended(p1)
   470  	return pAffine.Equal(&p1Affine)
   471  }
   472  
   473  // Neg negates point (x,y) on a twisted Edwards curve with parameters a, d
   474  // modifies p
   475  func (p *PointExtended) Neg(p1 *PointExtended) *PointExtended {
   476  	p.X.Neg(&p1.X)
   477  	p.Y = p1.Y
   478  	p.Z = p1.Z
   479  	p.T.Neg(&p1.T)
   480  	return p
   481  }
   482  
   483  // FromAffine sets p in projective from p in affine
   484  func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
   485  	p.X.Set(&p1.X)
   486  	p.Y.Set(&p1.Y)
   487  	p.Z.SetOne()
   488  	p.T.Mul(&p1.X, &p1.Y)
   489  	return p
   490  }
   491  
   492  // Add adds points in extended coordinates
   493  // See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
   494  func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
   495  	var A, B, C, D, E, F, G, H, tmp fr.Element
   496  	A.Mul(&p1.X, &p2.X)
   497  	B.Mul(&p1.Y, &p2.Y)
   498  	C.Mul(&p1.T, &p2.T).Mul(&C, &curveParams.D)
   499  	D.Mul(&p1.Z, &p2.Z)
   500  	tmp.Add(&p1.X, &p1.Y)
   501  	E.Add(&p2.X, &p2.Y).
   502  		Mul(&E, &tmp).
   503  		Sub(&E, &A).
   504  		Sub(&E, &B)
   505  	F.Sub(&D, &C)
   506  	G.Add(&D, &C)
   507  	H.Set(&A)
   508  	mulByA(&H)
   509  	H.Sub(&B, &H)
   510  
   511  	p.X.Mul(&E, &F)
   512  	p.Y.Mul(&G, &H)
   513  	p.T.Mul(&E, &H)
   514  	p.Z.Mul(&F, &G)
   515  
   516  	return p
   517  }
   518  
   519  // MixedAdd adds a point in extended coordinates to a point in affine coordinates
   520  // See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
   521  func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
   522  	var A, B, C, D, E, F, G, H, tmp fr.Element
   523  
   524  	A.Mul(&p2.X, &p1.Z)
   525  	B.Mul(&p2.Y, &p1.Z)
   526  
   527  	if p1.X.Equal(&A) && p1.Y.Equal(&B) {
   528  		p.MixedDouble(p1)
   529  		return p
   530  	}
   531  
   532  	A.Mul(&p1.X, &p2.X)
   533  	B.Mul(&p1.Y, &p2.Y)
   534  	C.Mul(&p1.Z, &p2.X).
   535  		Mul(&C, &p2.Y)
   536  	D.Set(&p1.T)
   537  	E.Add(&D, &C)
   538  	tmp.Sub(&p1.X, &p1.Y)
   539  	F.Add(&p2.X, &p2.Y).
   540  		Mul(&F, &tmp).
   541  		Add(&F, &B).
   542  		Sub(&F, &A)
   543  	G.Set(&A)
   544  	mulByA(&G)
   545  	G.Add(&G, &B)
   546  	H.Sub(&D, &C)
   547  
   548  	p.X.Mul(&E, &F)
   549  	p.Y.Mul(&G, &H)
   550  	p.T.Mul(&E, &H)
   551  	p.Z.Mul(&F, &G)
   552  
   553  	return p
   554  }
   555  
   556  // Double adds points in extended coordinates
   557  // Dedicated doubling
   558  {{- if or (eq .Name "bls12-378") (eq .Name "bw6-756")}}
   559  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
   560  {{- else}}
   561  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
   562  {{- end}}
   563  func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
   564  
   565  	var A, B, C, D, E, F, G, H fr.Element
   566  
   567  	A.Square(&p1.X)
   568  	B.Square(&p1.Y)
   569  	C.Square(&p1.Z).
   570  		Double(&C)
   571  	D.Set(&A)
   572  	mulByA(&D)
   573  	E.Add(&p1.X, &p1.Y).
   574  		Square(&E).
   575  		Sub(&E, &A).
   576  		Sub(&E, &B)
   577  	G.Add(&D, &B)
   578  	F.Sub(&G, &C)
   579  	H.Sub(&D, &B)
   580  
   581  	p.X.Mul(&E, &F)
   582  	p.Y.Mul(&G, &H)
   583  	p.T.Mul(&H, &E)
   584  	p.Z.Mul(&F, &G)
   585  
   586  	return p
   587  }
   588  
   589  // MixedDouble adds points in extended coordinates
   590  // Dedicated mixed doubling
   591  {{- if or (eq .Name "bls12-378") (eq .Name "bw6-756")}}
   592  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-mdbl-2008-hwcd
   593  {{- else}}
   594  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
   595  {{- end}}
   596  func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
   597  
   598  	var A, B, D, E, G, H, two fr.Element
   599  	two.SetUint64(2)
   600  
   601  	A.Square(&p1.X)
   602  	B.Square(&p1.Y)
   603  	D.Set(&A)
   604  	mulByA(&D)
   605  	E.Add(&p1.X, &p1.Y).
   606  		Square(&E).
   607  		Sub(&E, &A).
   608  		Sub(&E, &B)
   609  	G.Add(&D, &B)
   610  	H.Sub(&D, &B)
   611  
   612  	p.X.Sub(&G, &two).
   613  		Mul(&p.X, &E)
   614  	p.Y.Mul(&G, &H)
   615  	p.T.Mul(&H, &E)
   616  	p.Z.Square(&G).
   617  		Sub(&p.Z, &G).
   618  		Sub(&p.Z, &G)
   619  
   620  	return p
   621  }
   622  
   623  // setInfinity sets p to O (0:1:1:0)
   624  func (p *PointExtended) setInfinity() *PointExtended {
   625  	p.X.SetZero()
   626  	p.Y.SetOne()
   627  	p.Z.SetOne()
   628  	p.T.SetZero()
   629  	return p
   630  }
   631  
   632  // scalarMulWindowed scalar multiplication of a point
   633  // p1 in extended coordinates with a scalar in big.Int
   634  // using the windowed double-and-add method.
   635  func (p *PointExtended) scalarMulWindowed(p1 *PointExtended, scalar *big.Int) *PointExtended {
   636  	var _scalar big.Int
   637  	_scalar.Set(scalar)
   638  	p.Set(p1)
   639  	if _scalar.Sign() == -1 {
   640  		_scalar.Neg(&_scalar)
   641  		p.Neg(p)
   642  	}
   643  	var resExtended PointExtended
   644  	resExtended.setInfinity()
   645  	const wordSize = bits.UintSize
   646  	sWords := _scalar.Bits()
   647  
   648  	for i := len(sWords) - 1; i >= 0; i-- {
   649  		ithWord := sWords[i]
   650  		for k := 0; k < wordSize; k++ {
   651  			resExtended.Double(&resExtended)
   652  			kthBit := (ithWord >> (wordSize - 1 - k)) & 1
   653  			if kthBit == 1 {
   654  				resExtended.Add(&resExtended, p)
   655  			}
   656  		}
   657  	}
   658  
   659  	p.Set(&resExtended)
   660  	return p
   661  }
   662  
   663  // ScalarMultiplication scalar multiplication of a point
   664  // p1 in extended coordinates with a scalar in big.Int
   665  func (p *PointExtended) ScalarMultiplication(p1 *PointExtended, scalar *big.Int) *PointExtended {
   666  	{{- if .HasEndomorphism}}
   667  		return p.scalarMulGLV(p1, scalar)
   668  	{{- else }}
   669  		return p.scalarMulWindowed(p1, scalar)
   670  	{{- end}}
   671  }