Skip to content

Commit cbc20b8

Browse files
committed
Merge bitcoin#452: Minor optimizations to _scalar_inverse to save 4M
465159c Further shorten the addition chain for scalar inversion. (Brian Smith) cf12fa1 Minor optimizations to _scalar_inverse to save 4M (Peter Dettman) Tree-SHA512: b03ae53bd48435f8ef8a89ba3b45f9a35f3f3c6cfba7deb6820ab2146205656d198e4317a4cb98a986f434df244ae735313d303d0ce5a5c40519d37621238957
2 parents 4cc8f52 + 465159c commit cbc20b8

File tree

1 file changed

+67
-104
lines changed

1 file changed

+67
-104
lines changed

src/scalar_impl.h

Lines changed: 67 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -66,88 +66,79 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
6666
#else
6767
secp256k1_scalar *t;
6868
int i;
69-
/* First compute x ^ (2^N - 1) for some values of N. */
70-
secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127;
69+
/* First compute xN as x ^ (2^N - 1) for some values of N,
70+
* and uM as x ^ M for some values of M. */
71+
secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126;
72+
secp256k1_scalar u2, u5, u9, u11, u13;
7173

72-
secp256k1_scalar_sqr(&x2, x);
73-
secp256k1_scalar_mul(&x2, &x2, x);
74+
secp256k1_scalar_sqr(&u2, x);
75+
secp256k1_scalar_mul(&x2, &u2, x);
76+
secp256k1_scalar_mul(&u5, &u2, &x2);
77+
secp256k1_scalar_mul(&x3, &u5, &u2);
78+
secp256k1_scalar_mul(&u9, &x3, &u2);
79+
secp256k1_scalar_mul(&u11, &u9, &u2);
80+
secp256k1_scalar_mul(&u13, &u11, &u2);
7481

75-
secp256k1_scalar_sqr(&x3, &x2);
76-
secp256k1_scalar_mul(&x3, &x3, x);
77-
78-
secp256k1_scalar_sqr(&x4, &x3);
79-
secp256k1_scalar_mul(&x4, &x4, x);
80-
81-
secp256k1_scalar_sqr(&x6, &x4);
82+
secp256k1_scalar_sqr(&x6, &u13);
8283
secp256k1_scalar_sqr(&x6, &x6);
83-
secp256k1_scalar_mul(&x6, &x6, &x2);
84-
85-
secp256k1_scalar_sqr(&x7, &x6);
86-
secp256k1_scalar_mul(&x7, &x7, x);
84+
secp256k1_scalar_mul(&x6, &x6, &u11);
8785

88-
secp256k1_scalar_sqr(&x8, &x7);
89-
secp256k1_scalar_mul(&x8, &x8, x);
86+
secp256k1_scalar_sqr(&x8, &x6);
87+
secp256k1_scalar_sqr(&x8, &x8);
88+
secp256k1_scalar_mul(&x8, &x8, &x2);
9089

91-
secp256k1_scalar_sqr(&x15, &x8);
92-
for (i = 0; i < 6; i++) {
93-
secp256k1_scalar_sqr(&x15, &x15);
90+
secp256k1_scalar_sqr(&x14, &x8);
91+
for (i = 0; i < 5; i++) {
92+
secp256k1_scalar_sqr(&x14, &x14);
9493
}
95-
secp256k1_scalar_mul(&x15, &x15, &x7);
94+
secp256k1_scalar_mul(&x14, &x14, &x6);
9695

97-
secp256k1_scalar_sqr(&x30, &x15);
98-
for (i = 0; i < 14; i++) {
99-
secp256k1_scalar_sqr(&x30, &x30);
96+
secp256k1_scalar_sqr(&x28, &x14);
97+
for (i = 0; i < 13; i++) {
98+
secp256k1_scalar_sqr(&x28, &x28);
10099
}
101-
secp256k1_scalar_mul(&x30, &x30, &x15);
100+
secp256k1_scalar_mul(&x28, &x28, &x14);
102101

103-
secp256k1_scalar_sqr(&x60, &x30);
104-
for (i = 0; i < 29; i++) {
105-
secp256k1_scalar_sqr(&x60, &x60);
102+
secp256k1_scalar_sqr(&x56, &x28);
103+
for (i = 0; i < 27; i++) {
104+
secp256k1_scalar_sqr(&x56, &x56);
106105
}
107-
secp256k1_scalar_mul(&x60, &x60, &x30);
106+
secp256k1_scalar_mul(&x56, &x56, &x28);
108107

109-
secp256k1_scalar_sqr(&x120, &x60);
110-
for (i = 0; i < 59; i++) {
111-
secp256k1_scalar_sqr(&x120, &x120);
108+
secp256k1_scalar_sqr(&x112, &x56);
109+
for (i = 0; i < 55; i++) {
110+
secp256k1_scalar_sqr(&x112, &x112);
112111
}
113-
secp256k1_scalar_mul(&x120, &x120, &x60);
112+
secp256k1_scalar_mul(&x112, &x112, &x56);
114113

115-
secp256k1_scalar_sqr(&x127, &x120);
116-
for (i = 0; i < 6; i++) {
117-
secp256k1_scalar_sqr(&x127, &x127);
114+
secp256k1_scalar_sqr(&x126, &x112);
115+
for (i = 0; i < 13; i++) {
116+
secp256k1_scalar_sqr(&x126, &x126);
118117
}
119-
secp256k1_scalar_mul(&x127, &x127, &x7);
118+
secp256k1_scalar_mul(&x126, &x126, &x14);
120119

121-
/* Then accumulate the final result (t starts at x127). */
122-
t = &x127;
123-
for (i = 0; i < 2; i++) { /* 0 */
120+
/* Then accumulate the final result (t starts at x126). */
121+
t = &x126;
122+
for (i = 0; i < 3; i++) {
124123
secp256k1_scalar_sqr(t, t);
125124
}
126-
secp256k1_scalar_mul(t, t, x); /* 1 */
125+
secp256k1_scalar_mul(t, t, &u5); /* 101 */
127126
for (i = 0; i < 4; i++) { /* 0 */
128127
secp256k1_scalar_sqr(t, t);
129128
}
130129
secp256k1_scalar_mul(t, t, &x3); /* 111 */
131-
for (i = 0; i < 2; i++) { /* 0 */
132-
secp256k1_scalar_sqr(t, t);
133-
}
134-
secp256k1_scalar_mul(t, t, x); /* 1 */
135-
for (i = 0; i < 2; i++) { /* 0 */
136-
secp256k1_scalar_sqr(t, t);
137-
}
138-
secp256k1_scalar_mul(t, t, x); /* 1 */
139-
for (i = 0; i < 2; i++) { /* 0 */
130+
for (i = 0; i < 4; i++) { /* 0 */
140131
secp256k1_scalar_sqr(t, t);
141132
}
142-
secp256k1_scalar_mul(t, t, x); /* 1 */
143-
for (i = 0; i < 4; i++) { /* 0 */
133+
secp256k1_scalar_mul(t, t, &u5); /* 101 */
134+
for (i = 0; i < 5; i++) { /* 0 */
144135
secp256k1_scalar_sqr(t, t);
145136
}
146-
secp256k1_scalar_mul(t, t, &x3); /* 111 */
147-
for (i = 0; i < 3; i++) { /* 0 */
137+
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
138+
for (i = 0; i < 4; i++) {
148139
secp256k1_scalar_sqr(t, t);
149140
}
150-
secp256k1_scalar_mul(t, t, &x2); /* 11 */
141+
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
151142
for (i = 0; i < 4; i++) { /* 0 */
152143
secp256k1_scalar_sqr(t, t);
153144
}
@@ -156,38 +147,26 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
156147
secp256k1_scalar_sqr(t, t);
157148
}
158149
secp256k1_scalar_mul(t, t, &x3); /* 111 */
159-
for (i = 0; i < 4; i++) { /* 00 */
150+
for (i = 0; i < 6; i++) { /* 00 */
160151
secp256k1_scalar_sqr(t, t);
161152
}
162-
secp256k1_scalar_mul(t, t, &x2); /* 11 */
163-
for (i = 0; i < 2; i++) { /* 0 */
153+
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
154+
for (i = 0; i < 4; i++) { /* 0 */
164155
secp256k1_scalar_sqr(t, t);
165156
}
166-
secp256k1_scalar_mul(t, t, x); /* 1 */
167-
for (i = 0; i < 2; i++) { /* 0 */
157+
secp256k1_scalar_mul(t, t, &u5); /* 101 */
158+
for (i = 0; i < 3; i++) {
168159
secp256k1_scalar_sqr(t, t);
169160
}
170-
secp256k1_scalar_mul(t, t, x); /* 1 */
161+
secp256k1_scalar_mul(t, t, &x3); /* 111 */
171162
for (i = 0; i < 5; i++) { /* 0 */
172163
secp256k1_scalar_sqr(t, t);
173164
}
174-
secp256k1_scalar_mul(t, t, &x4); /* 1111 */
175-
for (i = 0; i < 2; i++) { /* 0 */
176-
secp256k1_scalar_sqr(t, t);
177-
}
178-
secp256k1_scalar_mul(t, t, x); /* 1 */
179-
for (i = 0; i < 3; i++) { /* 00 */
180-
secp256k1_scalar_sqr(t, t);
181-
}
182-
secp256k1_scalar_mul(t, t, x); /* 1 */
183-
for (i = 0; i < 4; i++) { /* 000 */
184-
secp256k1_scalar_sqr(t, t);
185-
}
186-
secp256k1_scalar_mul(t, t, x); /* 1 */
187-
for (i = 0; i < 2; i++) { /* 0 */
165+
secp256k1_scalar_mul(t, t, &u9); /* 1001 */
166+
for (i = 0; i < 6; i++) { /* 000 */
188167
secp256k1_scalar_sqr(t, t);
189168
}
190-
secp256k1_scalar_mul(t, t, x); /* 1 */
169+
secp256k1_scalar_mul(t, t, &u5); /* 101 */
191170
for (i = 0; i < 10; i++) { /* 0000000 */
192171
secp256k1_scalar_sqr(t, t);
193172
}
@@ -200,50 +179,34 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
200179
secp256k1_scalar_sqr(t, t);
201180
}
202181
secp256k1_scalar_mul(t, t, &x8); /* 11111111 */
203-
for (i = 0; i < 2; i++) { /* 0 */
204-
secp256k1_scalar_sqr(t, t);
205-
}
206-
secp256k1_scalar_mul(t, t, x); /* 1 */
207-
for (i = 0; i < 3; i++) { /* 00 */
208-
secp256k1_scalar_sqr(t, t);
209-
}
210-
secp256k1_scalar_mul(t, t, x); /* 1 */
211-
for (i = 0; i < 3; i++) { /* 00 */
212-
secp256k1_scalar_sqr(t, t);
213-
}
214-
secp256k1_scalar_mul(t, t, x); /* 1 */
215182
for (i = 0; i < 5; i++) { /* 0 */
216183
secp256k1_scalar_sqr(t, t);
217184
}
218-
secp256k1_scalar_mul(t, t, &x4); /* 1111 */
219-
for (i = 0; i < 2; i++) { /* 0 */
185+
secp256k1_scalar_mul(t, t, &u9); /* 1001 */
186+
for (i = 0; i < 6; i++) { /* 00 */
220187
secp256k1_scalar_sqr(t, t);
221188
}
222-
secp256k1_scalar_mul(t, t, x); /* 1 */
223-
for (i = 0; i < 5; i++) { /* 000 */
189+
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
190+
for (i = 0; i < 4; i++) {
224191
secp256k1_scalar_sqr(t, t);
225192
}
226-
secp256k1_scalar_mul(t, t, &x2); /* 11 */
227-
for (i = 0; i < 4; i++) { /* 00 */
193+
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
194+
for (i = 0; i < 5; i++) {
228195
secp256k1_scalar_sqr(t, t);
229196
}
230197
secp256k1_scalar_mul(t, t, &x2); /* 11 */
231-
for (i = 0; i < 2; i++) { /* 0 */
198+
for (i = 0; i < 6; i++) { /* 00 */
232199
secp256k1_scalar_sqr(t, t);
233200
}
234-
secp256k1_scalar_mul(t, t, x); /* 1 */
235-
for (i = 0; i < 8; i++) { /* 000000 */
236-
secp256k1_scalar_sqr(t, t);
237-
}
238-
secp256k1_scalar_mul(t, t, &x2); /* 11 */
239-
for (i = 0; i < 3; i++) { /* 0 */
201+
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
202+
for (i = 0; i < 10; i++) { /* 000000 */
240203
secp256k1_scalar_sqr(t, t);
241204
}
242-
secp256k1_scalar_mul(t, t, &x2); /* 11 */
243-
for (i = 0; i < 3; i++) { /* 00 */
205+
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
206+
for (i = 0; i < 4; i++) {
244207
secp256k1_scalar_sqr(t, t);
245208
}
246-
secp256k1_scalar_mul(t, t, x); /* 1 */
209+
secp256k1_scalar_mul(t, t, &u9); /* 1001 */
247210
for (i = 0; i < 6; i++) { /* 00000 */
248211
secp256k1_scalar_sqr(t, t);
249212
}

0 commit comments

Comments
 (0)