group_double_32bit.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 half-free Decred-style formula because half() has a carry bug
7 // in the 10×26-bit limb representation used on 32-bit/WASM.
8 // A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C)
9 // E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C, Z3 = 2*Y1*Z1
10 func (r *GroupElementJacobian) double(a *GroupElementJacobian) {
11 r.infinity = a.infinity
12
13 var aa, b, c, d, e, f FieldElement
14
15 // Z3 = 2*Y1*Z1
16 r.z.mul(&a.y, &a.z)
17 r.z.mulInt(2)
18
19 // A = X1^2
20 aa.sqr(&a.x)
21
22 // B = Y1^2
23 b.sqr(&a.y)
24
25 // C = B^2 = Y1^4
26 c.sqr(&b)
27
28 // D = 2*((X1+B)^2 - A - C) = 4*X1*Y1^2
29 b.add(&a.x)
30 b.sqr(&b)
31 d = aa
32 d.add(&c)
33 d.negate(&d, 2)
34 d.add(&b)
35 d.mulInt(2)
36
37 // E = 3*A = 3*X1^2
38 e = aa
39 e.mulInt(3)
40
41 // F = E^2
42 f.sqr(&e)
43
44 // X3 = F - 2*D
45 r.x = d
46 r.x.mulInt(2)
47 r.x.negate(&r.x, 16)
48 r.x.add(&f)
49 r.x.normalize()
50
51 // Y3 = E*(D-X3) - 8*C
52 f.negate(&r.x, 1)
53 f.add(&d)
54 f.normalize()
55 f.mul(&f, &e)
56
57 c.mulInt(8)
58 c.negate(&c, 8)
59 r.y = f
60 r.y.add(&c)
61
62 r.x.normalize()
63 r.y.normalize()
64 r.z.normalize()
65 }
66