diff --git a/bignum.c b/bignum.c index 7548bd1d3..1bd65b605 100644 --- a/bignum.c +++ b/bignum.c @@ -182,6 +182,19 @@ void bn_read_uint64(uint64_t in_number, bignum256 *out_number) out_number->val[8] = 0; } +// a must be normalized +int bn_bitcount(const bignum256 *a) +{ + int i; + for (i = 8; i >= 0; i--) { + int tmp = a->val[i]; + if (tmp != 0) { + return i * 30 + (32 - __builtin_clz(tmp)); + } + } + return 0; +} + // sets a bignum to zero. void bn_zero(bignum256 *a) { diff --git a/bignum.h b/bignum.h index 377bf1274..f0877c3e1 100644 --- a/bignum.h +++ b/bignum.h @@ -63,6 +63,8 @@ static inline void bn_copy(const bignum256 *a, bignum256 *b) { *b = *a; } +int bn_bitcount(const bignum256 *a); + void bn_zero(bignum256 *a); int bn_is_zero(const bignum256 *a); diff --git a/tests.c b/tests.c index 804969bbf..b9b87ffc3 100644 --- a/tests.c +++ b/tests.c @@ -275,6 +275,24 @@ START_TEST(test_bignum_is_odd) } END_TEST +START_TEST(test_bignum_bitcount) +{ + bignum256 a; + + bn_zero(&a); + ck_assert_int_eq(bn_bitcount(&a), 0); + + bn_read_uint32(0x3fffffff, &a); + ck_assert_int_eq(bn_bitcount(&a), 30); + + bn_read_uint32(0xffffffff, &a); + ck_assert_int_eq(bn_bitcount(&a), 32); + + bn_read_be(fromhex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); + ck_assert_int_eq(bn_bitcount(&a), 256); +} +END_TEST + // from https://github.com/bitcoin/bitcoin/blob/master/src/test/data/base58_keys_valid.json START_TEST(test_base58) { @@ -2532,6 +2550,7 @@ Suite *test_suite(void) tcase_add_test(tc, test_bignum_copy); tcase_add_test(tc, test_bignum_is_even); tcase_add_test(tc, test_bignum_is_odd); + tcase_add_test(tc, test_bignum_bitcount); suite_add_tcase(s, tc); tc = tcase_create("base58");