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