From d61a151900a08022f2243808fd28b8b076979d3e Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 28 Jun 2016 20:05:01 +0200 Subject: [PATCH] add bn_divmod1000 including unit test --- bignum.c | 24 ++++++++++++++++++++++++ bignum.h | 2 ++ tests.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/bignum.c b/bignum.c index 6de4a3c22..20e3718c3 100644 --- a/bignum.c +++ b/bignum.c @@ -804,6 +804,30 @@ void bn_divmod58(bignum256 *a, uint32_t *r) *r = rem; } +// a / 1000 = a (+r) +void bn_divmod1000(bignum256 *a, uint32_t *r) +{ + int i; + uint32_t rem, tmp; + rem = a->val[8] % 1000; + a->val[8] /= 1000; + for (i = 7; i >= 0; i--) { + // invariants: + // rem = old(a) >> 30(i+1) % 1000 + // a[i+1..8] = old(a[i+1..8])/1000 + // a[0..i] = old(a[0..i]) + // 2^30 == 1073741*1000 + 824 + tmp = rem * 824 + a->val[i]; + // set a[i] = (rem * 2^30 + a[i])/1000 + // = rem * 1073741 + (rem * 824 + a[i])/1000 + a->val[i] = rem * 1073741 + (tmp / 1000); + // set rem = (rem * 2^30 + a[i]) mod 1000 + // = (rem * 824 + a[i]) mod 1000 + rem = tmp % 1000; + } + *r = rem; +} + #if USE_BN_PRINT void bn_print(const bignum256 *a) { diff --git a/bignum.h b/bignum.h index 8778aec7b..4b51c5d42 100644 --- a/bignum.h +++ b/bignum.h @@ -87,6 +87,8 @@ void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res); void bn_divmod58(bignum256 *a, uint32_t *r); +void bn_divmod1000(bignum256 *a, uint32_t *r); + #if USE_BN_PRINT void bn_print(const bignum256 *a); void bn_print_raw(const bignum256 *a); diff --git a/tests.c b/tests.c index 051f52b9b..d0148c90b 100644 --- a/tests.c +++ b/tests.c @@ -161,6 +161,35 @@ START_TEST(test_base58) } END_TEST +START_TEST(test_bignum_divmod) +{ + uint32_t r; + int i; + + bignum256 a = { { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} }; + uint32_t ar[] = { 15, 14, 55, 29, 44, 24, 53, 49, 18, 55, 2, 28, 5, 4, 12, 43, 18, 37, 28, 14, 30, 46, 12, 11, 17, 10, 10, 13, 24, 45, 4, 33, 44, 42, 2, 46, 34, 43, 45, 28, 21, 18, 13, 17 }; + + i = 0; + while (!bn_is_zero(&a) && i < 44) { + bn_divmod58(&a, &r); + ck_assert_int_eq(r, ar[i]); + i++; + } + ck_assert_int_eq(i, 44); + + bignum256 b = { { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} }; + uint32_t br[] = { 935, 639, 129, 913, 7, 584, 457, 39, 564, 640, 665, 984, 269, 853, 907, 687, 8, 985, 570, 423, 195, 316, 237, 89, 792, 115 }; + + i = 0; + while (!bn_is_zero(&b) && i < 26) { + bn_divmod1000(&b, &r); + ck_assert_int_eq(r, br[i]); + i++; + } + ck_assert_int_eq(i, 26); + +} +END_TEST // test vector 1 from https://en.bitcoin.it/wiki/BIP_0032_TestVectors START_TEST(test_bip32_vector_1) @@ -1981,6 +2010,10 @@ Suite *test_suite(void) tcase_add_test(tc, test_base58); suite_add_tcase(s, tc); + tc = tcase_create("bignum_divmod"); + tcase_add_test(tc, test_bignum_divmod); + suite_add_tcase(s, tc); + tc = tcase_create("bip32"); tcase_add_test(tc, test_bip32_vector_1); tcase_add_test(tc, test_bip32_vector_2);