group_double_native.go raw

   1  //go:build !js && !wasm && !tinygo && !wasm32
   2  
   3  package p256k1
   4  
   5  // double sets r = 2*a (point doubling in Jacobian coordinates)
   6  // Uses the bitcoin-core half()-based formula (correct on 64-bit field elements).
   7  func (r *GroupElementJacobian) double(a *GroupElementJacobian) {
   8  	var l, s, t FieldElement
   9  
  10  	r.infinity = a.infinity
  11  
  12  	// Z3 = Y1*Z1 (1)
  13  	r.z.mul(&a.z, &a.y)
  14  
  15  	// S = Y1^2 (1)
  16  	s.sqr(&a.y)
  17  
  18  	// L = X1^2 (1)
  19  	l.sqr(&a.x)
  20  
  21  	// L = 3*X1^2 (3)
  22  	l.mulInt(3)
  23  
  24  	// L = 3/2*X1^2 (2)
  25  	l.half(&l)
  26  
  27  	// T = -S (2) where S = Y1^2
  28  	t.negate(&s, 1)
  29  
  30  	// T = -X1*S = -X1*Y1^2 (1)
  31  	t.mul(&t, &a.x)
  32  
  33  	// X3 = L^2 (1)
  34  	r.x.sqr(&l)
  35  
  36  	// X3 = L^2 + T (2)
  37  	r.x.add(&t)
  38  
  39  	// X3 = L^2 + 2*T (3)
  40  	r.x.add(&t)
  41  
  42  	// S = S^2 = (Y1^2)^2 = Y1^4 (1)
  43  	s.sqr(&s)
  44  
  45  	// T = X3 + T = X3 + (-X1*Y1^2) (4)
  46  	t.add(&r.x)
  47  
  48  	// Y3 = L*(X3 + T) = L*(X3 + (-X1*Y1^2)) (1)
  49  	r.y.mul(&t, &l)
  50  
  51  	// Y3 = L*(X3 + T) + S^2 = L*(X3 + (-X1*Y1^2)) + Y1^4 (2)
  52  	r.y.add(&s)
  53  
  54  	// Y3 = -(L*(X3 + T) + S^2) (3)
  55  	r.y.negate(&r.y, 2)
  56  }
  57