Skip to content

Commit 9f3a182

Browse files
committed
Use double-wide types for additions in scalar code
1 parent 6034a04 commit 9f3a182

File tree

2 files changed

+66
-96
lines changed

2 files changed

+66
-96
lines changed

src/scalar_4x64_impl.h

+33-48
Original file line numberDiff line numberDiff line change
@@ -185,70 +185,55 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
185185

186186
/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
187187
#define muladd(a,b) { \
188-
uint64_t tl, th; \
189-
{ \
190-
uint128_t t = (uint128_t)a * b; \
191-
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
192-
tl = t; \
193-
} \
194-
c0 += tl; /* overflow is handled on the next line */ \
195-
th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
196-
c1 += th; /* overflow is handled on the next line */ \
197-
c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \
198-
VERIFY_CHECK((c1 >= th) || (c2 != 0)); \
188+
uint128_t t = (uint128_t)a * b + c0; \
189+
c0 = t; \
190+
t >>= 64; \
191+
t += c1; \
192+
c1 = t; \
193+
c2 += (t >> 64); \
194+
VERIFY_CHECK(c2 >= (t >> 64)); /* c2 must never overflow. */ \
199195
}
200196

201197
/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */
202198
#define muladd_fast(a,b) { \
203-
uint64_t tl, th; \
204-
{ \
205-
uint128_t t = (uint128_t)a * b; \
206-
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
207-
tl = t; \
208-
} \
209-
c0 += tl; /* overflow is handled on the next line */ \
210-
th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
211-
c1 += th; /* never overflows by contract (verified in the next line) */ \
212-
VERIFY_CHECK(c1 >= th); \
199+
uint128_t t = (uint128_t)a * b + c0; \
200+
c0 = t; \
201+
c1 += (t >> 64); \
202+
VERIFY_CHECK(c1 >= (t >> 64)); /* c1 must never overflow. */ \
213203
}
214204

215205
/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
216206
#define muladd2(a,b) { \
217-
uint64_t tl, th, th2, tl2; \
218-
{ \
219-
uint128_t t = (uint128_t)a * b; \
220-
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
221-
tl = t; \
222-
} \
223-
th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \
224-
c2 += (th2 < th); /* never overflows by contract (verified the next line) */ \
225-
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
226-
tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \
227-
th2 += (tl2 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
228-
c0 += tl2; /* overflow is handled on the next line */ \
229-
th2 += (c0 < tl2); /* second overflow is handled on the next line */ \
230-
c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \
231-
VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \
232-
c1 += th2; /* overflow is handled on the next line */ \
233-
c2 += (c1 < th2); /* never overflows by contract (verified the next line) */ \
234-
VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \
207+
uint128_t t1 = (uint128_t)a * b; \
208+
uint64_t t1l = t1; \
209+
uint64_t t1h = t1 >> 64; \
210+
uint128_t t = (uint128_t)t1l + t1l + c0; \
211+
c0 = t; \
212+
t >>= 64; \
213+
t += c1 + t1h + t1h; \
214+
c1 = t; \
215+
c2 += (t >> 64); \
216+
VERIFY_CHECK(c2 >= (t >> 64)); /* c2 must never overflow. */ \
235217
}
236218

237219
/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */
238220
#define sumadd(a) { \
239-
unsigned int over; \
240-
c0 += (a); /* overflow is handled on the next line */ \
241-
over = (c0 < (a)); \
242-
c1 += over; /* overflow is handled on the next line */ \
243-
c2 += (c1 < over); /* never overflows by contract */ \
221+
uint128_t t = (uint128_t)a + c0; \
222+
c0 = t; \
223+
t >>= 64; \
224+
t += c1; \
225+
c1 = t; \
226+
c2 += (t >> 64); \
227+
VERIFY_CHECK(c2 >= (t >> 64)); /* c2 must never overflow. */ \
244228
}
245229

246230
/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */
247231
#define sumadd_fast(a) { \
248-
c0 += (a); /* overflow is handled on the next line */ \
249-
c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \
250-
VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \
251-
VERIFY_CHECK(c2 == 0); \
232+
uint128_t t = (uint128_t)a + c0; \
233+
c0 = t; \
234+
c1 += (t >> 64); \
235+
VERIFY_CHECK(c1 >= (t >> 64)); /* c1 must never overflow. */ \
236+
VERIFY_CHECK(c2 == 0); /* c2 must be zero. */ \
252237
}
253238

254239
/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */

src/scalar_8x32_impl.h

+33-48
Original file line numberDiff line numberDiff line change
@@ -264,70 +264,55 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
264264

265265
/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
266266
#define muladd(a,b) { \
267-
uint32_t tl, th; \
268-
{ \
269-
uint64_t t = (uint64_t)a * b; \
270-
th = t >> 32; /* at most 0xFFFFFFFE */ \
271-
tl = t; \
272-
} \
273-
c0 += tl; /* overflow is handled on the next line */ \
274-
th += (c0 < tl); /* at most 0xFFFFFFFF */ \
275-
c1 += th; /* overflow is handled on the next line */ \
276-
c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \
277-
VERIFY_CHECK((c1 >= th) || (c2 != 0)); \
267+
uint64_t t = (uint64_t)a * b + c0; \
268+
c0 = t; \
269+
t >>= 32; \
270+
t += c1; \
271+
c1 = t; \
272+
c2 += (t >> 32); \
273+
VERIFY_CHECK(c2 >= (t >> 32)); /* c2 must never overflow. */ \
278274
}
279275

280276
/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */
281277
#define muladd_fast(a,b) { \
282-
uint32_t tl, th; \
283-
{ \
284-
uint64_t t = (uint64_t)a * b; \
285-
th = t >> 32; /* at most 0xFFFFFFFE */ \
286-
tl = t; \
287-
} \
288-
c0 += tl; /* overflow is handled on the next line */ \
289-
th += (c0 < tl); /* at most 0xFFFFFFFF */ \
290-
c1 += th; /* never overflows by contract (verified in the next line) */ \
291-
VERIFY_CHECK(c1 >= th); \
278+
uint64_t t = (uint64_t)a * b + c0; \
279+
c0 = t; \
280+
c1 += (t >> 32); \
281+
VERIFY_CHECK(c1 >= (t >> 32)); /* c1 must never overflow. */ \
292282
}
293283

294284
/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
295285
#define muladd2(a,b) { \
296-
uint32_t tl, th, th2, tl2; \
297-
{ \
298-
uint64_t t = (uint64_t)a * b; \
299-
th = t >> 32; /* at most 0xFFFFFFFE */ \
300-
tl = t; \
301-
} \
302-
th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \
303-
c2 += (th2 < th); /* never overflows by contract (verified the next line) */ \
304-
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
305-
tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \
306-
th2 += (tl2 < tl); /* at most 0xFFFFFFFF */ \
307-
c0 += tl2; /* overflow is handled on the next line */ \
308-
th2 += (c0 < tl2); /* second overflow is handled on the next line */ \
309-
c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \
310-
VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \
311-
c1 += th2; /* overflow is handled on the next line */ \
312-
c2 += (c1 < th2); /* never overflows by contract (verified the next line) */ \
313-
VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \
286+
uint64_t t1 = (uint64_t)a * b; \
287+
uint64_t t1l = t1; \
288+
uint64_t t1h = t1 >> 32; \
289+
uint64_t t = (uint64_t)t1l + t1l + c0; \
290+
c0 = t; \
291+
t >>= 32; \
292+
t += c1 + t1h + t1h; \
293+
c1 = t; \
294+
c2 += (t >> 32); \
295+
VERIFY_CHECK(c2 >= (t >> 32)); /* c2 must never overflow. */ \
314296
}
315297

316298
/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */
317299
#define sumadd(a) { \
318-
unsigned int over; \
319-
c0 += (a); /* overflow is handled on the next line */ \
320-
over = (c0 < (a)); \
321-
c1 += over; /* overflow is handled on the next line */ \
322-
c2 += (c1 < over); /* never overflows by contract */ \
300+
uint64_t t = (uint64_t)a + c0; \
301+
c0 = t; \
302+
t >>= 32; \
303+
t += c1; \
304+
c1 = t; \
305+
c2 += (t >> 32); \
306+
VERIFY_CHECK(c2 >= (t >> 32)); /* c2 must never overflow. */ \
323307
}
324308

325309
/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */
326310
#define sumadd_fast(a) { \
327-
c0 += (a); /* overflow is handled on the next line */ \
328-
c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \
329-
VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \
330-
VERIFY_CHECK(c2 == 0); \
311+
uint64_t t = (uint64_t)a + c0; \
312+
c0 = t; \
313+
c1 += (t >> 32); \
314+
VERIFY_CHECK(c1 >= (t >> 32)); /* c1 must never overflow. */ \
315+
VERIFY_CHECK(c2 == 0); /* c2 must be zero. */ \
331316
}
332317

333318
/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */

0 commit comments

Comments
 (0)