Skip to content

Commit

Permalink
Make secp256k1_i128_check_pow2 support -(2^n)
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa committed Feb 27, 2023
1 parent cbd2555 commit 5fffb2c
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/int128.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_
/* Compare two 128-bit values for equality. */
static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b);

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

#endif

Expand Down
5 changes: 3 additions & 2 deletions src/int128_native_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, con
return *a == *b;
}

static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) {
VERIFY_CHECK(n < 127);
return (*r == (int128_t)1 << n);
VERIFY_CHECK(sign == 1 || sign == -1);
return (*r == (int128_t)((uint128_t)sign << n));
}

#endif
9 changes: 5 additions & 4 deletions src/int128_struct_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,11 @@ static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, con
return a->hi == b->hi && a->lo == b->lo;
}

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

#endif
2 changes: 1 addition & 1 deletion src/modinv64_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, i
static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n) {
secp256k1_int128 a;
secp256k1_i128_det(&a, t->u, t->v, t->q, t->r);
return secp256k1_i128_check_pow2(&a, n);
return secp256k1_i128_check_pow2(&a, n, 1);
}
#endif

Expand Down
38 changes: 32 additions & 6 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -2022,30 +2022,56 @@ static void run_int128_test_case(void) {
}
CHECK(secp256k1_i128_eq_var(&swa, &swz) == expect);
}
/* test secp256k1_i128_check_pow2 */
/* test secp256k1_i128_check_pow2 (sign == 1) */
{
int expect = (uc & 1);
int pos = ub % 127;
if (expect) {
/* If expect==1, set swz to exactly (2 << pos). */
/* If expect==1, set swz to exactly 2^pos. */
uint64_t hi = 0;
uint64_t lo = 0;
if (pos & 64) {
if (pos >= 64) {
hi = (((uint64_t)1) << (pos & 63));
} else {
lo = (((uint64_t)1) << (pos & 63));
}
secp256k1_i128_load(&swz, hi, lo);
} else {
/* If expect==0, set swz = swa, but update expect=1 if swa happens to equal (2 << pos). */
if (pos & 64) {
/* If expect==0, set swz = swa, but update expect=1 if swa happens to equal 2^pos. */
if (pos >= 64) {
if ((v[1] == (((uint64_t)1) << (pos & 63))) && v[0] == 0) expect = 1;
} else {
if ((v[0] == (((uint64_t)1) << (pos & 63))) && v[1] == 0) expect = 1;
}
swz = swa;
}
CHECK(secp256k1_i128_check_pow2(&swz, pos) == expect);
CHECK(secp256k1_i128_check_pow2(&swz, pos, 1) == expect);
}
/* test secp256k1_i128_check_pow2 (sign == -1) */
{
int expect = (uc & 1);
int pos = ub % 127;
if (expect) {
/* If expect==1, set swz to exactly -2^pos. */
uint64_t hi = ~(uint64_t)0;
uint64_t lo = ~(uint64_t)0;
if (pos >= 64) {
hi <<= (pos & 63);
lo = 0;
} else {
lo <<= (pos & 63);
}
secp256k1_i128_load(&swz, hi, lo);
} else {
/* If expect==0, set swz = swa, but update expect=1 if swa happens to equal -2^pos. */
if (pos >= 64) {
if ((v[1] == ((~(uint64_t)0) << (pos & 63))) && v[0] == 0) expect = 1;
} else {
if ((v[0] == ((~(uint64_t)0) << (pos & 63))) && v[1] == ~(uint64_t)0) expect = 1;
}
swz = swa;
}
CHECK(secp256k1_i128_check_pow2(&swz, pos, -1) == expect);
}
}

Expand Down

0 comments on commit 5fffb2c

Please sign in to comment.