Skip to content

Commit 5fffb2c

Browse files
committed
Make secp256k1_i128_check_pow2 support -(2^n)
1 parent cbd2555 commit 5fffb2c

5 files changed

+43
-15
lines changed

src/int128.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_
8080
/* Compare two 128-bit values for equality. */
8181
static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b);
8282

83-
/* Tests if r is equal to 2^n.
83+
/* Tests if r is equal to sign*2^n (sign must be 1 or -1).
8484
* n must be strictly less than 127.
8585
*/
86-
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n);
86+
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign);
8787

8888
#endif
8989

src/int128_native_impl.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, con
8484
return *a == *b;
8585
}
8686

87-
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
87+
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) {
8888
VERIFY_CHECK(n < 127);
89-
return (*r == (int128_t)1 << n);
89+
VERIFY_CHECK(sign == 1 || sign == -1);
90+
return (*r == (int128_t)((uint128_t)sign << n));
9091
}
9192

9293
#endif

src/int128_struct_impl.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,11 @@ static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, con
189189
return a->hi == b->hi && a->lo == b->lo;
190190
}
191191

192-
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
193-
VERIFY_CHECK(n < 127);
194-
return n >= 64 ? r->hi == (uint64_t)1 << (n - 64) && r->lo == 0
195-
: r->hi == 0 && r->lo == (uint64_t)1 << n;
192+
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) {
193+
VERIFY_CHECK(n < 127);
194+
VERIFY_CHECK(sign == 1 || sign == -1);
195+
return n >= 64 ? r->hi == (uint64_t)sign << (n - 64) && r->lo == 0
196+
: r->hi == (uint64_t)((sign - 1) >> 1) && r->lo == (uint64_t)sign << n;
196197
}
197198

198199
#endif

src/modinv64_impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, i
7575
static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n) {
7676
secp256k1_int128 a;
7777
secp256k1_i128_det(&a, t->u, t->v, t->q, t->r);
78-
return secp256k1_i128_check_pow2(&a, n);
78+
return secp256k1_i128_check_pow2(&a, n, 1);
7979
}
8080
#endif
8181

src/tests.c

+32-6
Original file line numberDiff line numberDiff line change
@@ -2022,30 +2022,56 @@ static void run_int128_test_case(void) {
20222022
}
20232023
CHECK(secp256k1_i128_eq_var(&swa, &swz) == expect);
20242024
}
2025-
/* test secp256k1_i128_check_pow2 */
2025+
/* test secp256k1_i128_check_pow2 (sign == 1) */
20262026
{
20272027
int expect = (uc & 1);
20282028
int pos = ub % 127;
20292029
if (expect) {
2030-
/* If expect==1, set swz to exactly (2 << pos). */
2030+
/* If expect==1, set swz to exactly 2^pos. */
20312031
uint64_t hi = 0;
20322032
uint64_t lo = 0;
2033-
if (pos & 64) {
2033+
if (pos >= 64) {
20342034
hi = (((uint64_t)1) << (pos & 63));
20352035
} else {
20362036
lo = (((uint64_t)1) << (pos & 63));
20372037
}
20382038
secp256k1_i128_load(&swz, hi, lo);
20392039
} else {
2040-
/* If expect==0, set swz = swa, but update expect=1 if swa happens to equal (2 << pos). */
2041-
if (pos & 64) {
2040+
/* If expect==0, set swz = swa, but update expect=1 if swa happens to equal 2^pos. */
2041+
if (pos >= 64) {
20422042
if ((v[1] == (((uint64_t)1) << (pos & 63))) && v[0] == 0) expect = 1;
20432043
} else {
20442044
if ((v[0] == (((uint64_t)1) << (pos & 63))) && v[1] == 0) expect = 1;
20452045
}
20462046
swz = swa;
20472047
}
2048-
CHECK(secp256k1_i128_check_pow2(&swz, pos) == expect);
2048+
CHECK(secp256k1_i128_check_pow2(&swz, pos, 1) == expect);
2049+
}
2050+
/* test secp256k1_i128_check_pow2 (sign == -1) */
2051+
{
2052+
int expect = (uc & 1);
2053+
int pos = ub % 127;
2054+
if (expect) {
2055+
/* If expect==1, set swz to exactly -2^pos. */
2056+
uint64_t hi = ~(uint64_t)0;
2057+
uint64_t lo = ~(uint64_t)0;
2058+
if (pos >= 64) {
2059+
hi <<= (pos & 63);
2060+
lo = 0;
2061+
} else {
2062+
lo <<= (pos & 63);
2063+
}
2064+
secp256k1_i128_load(&swz, hi, lo);
2065+
} else {
2066+
/* If expect==0, set swz = swa, but update expect=1 if swa happens to equal -2^pos. */
2067+
if (pos >= 64) {
2068+
if ((v[1] == ((~(uint64_t)0) << (pos & 63))) && v[0] == 0) expect = 1;
2069+
} else {
2070+
if ((v[0] == ((~(uint64_t)0) << (pos & 63))) && v[1] == ~(uint64_t)0) expect = 1;
2071+
}
2072+
swz = swa;
2073+
}
2074+
CHECK(secp256k1_i128_check_pow2(&swz, pos, -1) == expect);
20492075
}
20502076
}
20512077

0 commit comments

Comments
 (0)