diff --git a/bn_mp_to_decimal.c b/bn_mp_to_decimal.c new file mode 100644 index 000000000..43398dd64 --- /dev/null +++ b/bn_mp_to_decimal.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef BN_MP_TO_DECIMAL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* stores a bignum as a decimal ASCII string, using Barrett + * reduction if available. + */ + +mp_err mp_to_decimal(const mp_int *a, char *str, size_t maxlen) +{ + mp_err err; + + if (MP_HAS(S_MP_TO_DECIMAL_FAST) && (a->used > 10)) { + err = s_mp_to_decimal_fast(a, str, maxlen); + } else { + err = mp_to_radix(a, str, maxlen, 10); + } + + return err; +} + +#endif diff --git a/bn_s_mp_to_decimal_fast.c b/bn_s_mp_to_decimal_fast.c new file mode 100644 index 000000000..476f786a2 --- /dev/null +++ b/bn_s_mp_to_decimal_fast.c @@ -0,0 +1,246 @@ +#include "tommath_private.h" +#include +#ifdef BN_S_MP_TO_DECIMAL_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store a bignum as a decimal ASCII string */ +static mp_err s_mp_to_decimal_fast_rec(const mp_int *number, mp_int *nL, mp_int *shiftL, mp_int *mL, + int precalc_array_index, + int left, + char **result, + size_t *maxlen) +{ + mp_int q, nLq, r; + mp_err err; + + if (precalc_array_index < 0) { + int n = mp_get_i32(number), n_orig = n, digits_to_copy = 0, copy_counter; + char *result_str = *result; + char sprintf_str[4] = "000"; + + while (n) { + sprintf_str[2 - digits_to_copy] = mp_s_rmap[n % 10]; + digits_to_copy++; + n /= 10; + } + + if (!left && n_orig < 100) { + digits_to_copy++; + if (n_orig < 10) { + digits_to_copy++; + } + if (n_orig == 0) { + digits_to_copy++; + } + } + + if (*maxlen < ((size_t)digits_to_copy + 1)) { + /* no more room */ + return MP_VAL; + } + + for (copy_counter = 0; copy_counter < digits_to_copy; copy_counter++) { + result_str[copy_counter] = sprintf_str[3 - digits_to_copy + copy_counter]; + } + + *maxlen -= (size_t)digits_to_copy; + *result += digits_to_copy; + + return MP_OKAY; + } + + if ((err = mp_init_multi(&q, &nLq, &r, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul(number, &mL[precalc_array_index], &q)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2d(&q, mp_get_i32(&shiftL[precalc_array_index]), &q, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_mul(&nL[precalc_array_index], &q, &nLq)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_sub(number, &nLq, &r)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_isneg(&r)) { + if ((err = mp_decr(&q)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(&r, &nL[precalc_array_index], &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + + --precalc_array_index; + if (left && mp_iszero(&q)) { + if ((err = s_mp_to_decimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 1, result, maxlen)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + if ((err = s_mp_to_decimal_fast_rec(&q, nL, shiftL, mL, precalc_array_index, left, result, maxlen)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = s_mp_to_decimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 0, result, maxlen)) != MP_OKAY) { + goto LBL_ERR; + } + } + + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&q, &nLq, &r, NULL); + return err; +} + +mp_err s_mp_to_decimal_fast(const mp_int *a, char *result, size_t maxlen) +{ + mp_int number, n, shift, M, M2, M22, M4, M44; + mp_int nL[20], shiftL[20], mL[20]; + mp_err err; + char **result_addr = &result; + int precalc_array_index = 1, c; + + /* check range of the maxlen */ + if (maxlen < 2) { + return MP_VAL; + } + + MP_ZERO_BUFFER(nL, sizeof(nL)); + MP_ZERO_BUFFER(shiftL, sizeof(shiftL)); + MP_ZERO_BUFFER(mL, sizeof(mL)); + + if ((err = mp_init_multi(&number, &n, &shift, &M, &M2, &M22, &M4, &M44, &nL[0], &shiftL[0], &mL[0], NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_copy(a, &number)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_isneg(&number)) { + if ((err = mp_neg(&number, &number)) != MP_OKAY) { + goto LBL_ERR; + } + result[0] = '-'; + *result_addr += 1; + maxlen -= 1; + } + mp_set_u32(&n, 1000); + + if ((err = mp_copy(&n, &nL[0])) != MP_OKAY) { + goto LBL_ERR; + } + + mp_set_u32(&shift, 20); + + if ((err = mp_copy(&shift, &shiftL[0])) != MP_OKAY) { + goto LBL_ERR; + } + + /* (8 * 2**$shift) / $n rounded up */ + mp_set_u32(&M, 8389); + + /* $M / 8, rounded up */ + mp_set_u32(&mL[0], 1049); + + for (precalc_array_index = 1; precalc_array_index < 20; precalc_array_index++) { + if ((err = mp_sqr(&n, &n)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp(&n, &number) == MP_GT) { + break; + } + + if ((err = mp_mul_2(&shift, &shift)) != MP_OKAY) { + goto LBL_ERR; + } + + /* The following is a Newton-Raphson step, to restore the invariant + * that $M is (8 * 2**$shift) / $n, rounded up. */ + { + if ((err = mp_sqr(&M, &M2)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sqr(&M2, &M4)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_mul(&M4, &n, &M4)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2d(&M4, mp_get_i32(&shift) + 6, &M4, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul_2(&M2, &M2)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sub(&M4, &M2, &M4)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_incr(&M4)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2d(&M4, 3, &M4, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_decr(&M4)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_neg(&M4, &M)) != MP_OKAY) { + goto LBL_ERR; + } + } + + if ((err = mp_init_copy(&nL[precalc_array_index], &n)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_init_copy(&shiftL[precalc_array_index], &shift)) != MP_OKAY) { + goto LBL_ERR; + } + + /* Divide by 8, round up */ + { + if ((err = mp_add_d(&M4, 1, &M4)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2d(&M4, 3, &M4, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sub_d(&M4, 1, &M4)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_neg(&M4, &M4)) != MP_OKAY) { + goto LBL_ERR; + } + } + if ((err = mp_init_copy(&mL[precalc_array_index], &M4)) != MP_OKAY) { + goto LBL_ERR; + } + } + if (precalc_array_index >= 20) { + err = MP_VAL; + goto LBL_ERR; + } + + if ((err = s_mp_to_decimal_fast_rec(&number, nL, shiftL, mL, precalc_array_index - 1, 1, result_addr, + &maxlen)) != MP_OKAY) { + goto LBL_ERR; + } + *result_addr[0] = '\0'; + + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&number, &n, &shift, &M, &M2, &M22, &M4, &M44, &nL[0], &shiftL[0], &mL[0], NULL); + for (c = 1; c < precalc_array_index; c++) { + mp_clear_multi(&nL[c], &shiftL[c], &mL[c], NULL); + } + return err; +} + +#endif diff --git a/demo/test.c b/demo/test.c index 79cfb3855..57eda2c79 100644 --- a/demo/test.c +++ b/demo/test.c @@ -2214,6 +2214,54 @@ static int test_s_mp_toom_sqr(void) return EXIT_FAILURE; } +static int test_mp_to_decimal(void) +{ + mp_int a, b; + int size, err, strlength; + char *str; + + if ((err = mp_init_multi(&a, &b, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + for (size = 1; size <= 1001; size += 10) { + int times; + printf("Testing mp_to_decimal: %5d digits \r", size); + fflush(stdout); + for (times = 0; times < 5; times++) { + if ((err = mp_rand(&a, size)) != MP_OKAY) { + goto LTM_ERR; + } + if (times % 2) { + /* also test some negative numbers */ + if ((err = mp_neg(&a, &a)) != MP_OKAY) { + goto LTM_ERR; + } + } + if ((err = mp_radix_size(&a, 10, &strlength)) != MP_OKAY) { + goto LTM_ERR; + } + str = (char *)malloc((size_t)strlength); + if ((err = mp_to_decimal(&a, str, (size_t)strlength)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_read_radix(&b, str, 10)) != MP_OKAY) { + goto LTM_ERR; + } + free(str); + if (mp_cmp(&a, &b) != MP_EQ) { + fprintf(stderr, "mp_to_decimal failed at size %d\n", size); + goto LTM_ERR; + } + } + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + int unit_tests(int argc, char **argv) { static const struct { @@ -2264,8 +2312,10 @@ int unit_tests(int argc, char **argv) T1(s_mp_karatsuba_sqr, S_MP_KARATSUBA_SQR), T1(s_mp_toom_mul, S_MP_TOOM_MUL), T1(s_mp_toom_sqr, S_MP_TOOM_SQR), + T1(mp_to_decimal, S_MP_TO_DECIMAL_FAST) #undef T2 #undef T1 +#undef T0 }; unsigned long i, ok, fail, nop; uint64_t t; diff --git a/libtommath_VS2008.vcproj b/libtommath_VS2008.vcproj index f61123e2a..e8b5b6adf 100644 --- a/libtommath_VS2008.vcproj +++ b/libtommath_VS2008.vcproj @@ -816,6 +816,10 @@ RelativePath="bn_mp_submod.c" > + + @@ -936,6 +940,10 @@ RelativePath="bn_s_mp_sub.c" > + + diff --git a/makefile b/makefile index 89d2b3b89..f7aa5a826 100644 --- a/makefile +++ b/makefile @@ -48,13 +48,14 @@ bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32. bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o \ bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_bin_size.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ -bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin.o \ -bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o \ -bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o \ -bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o \ -bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o \ -bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o \ -bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_submod.o bn_mp_to_decimal.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o \ +bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_to_decimal_fast.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o #END_INS diff --git a/makefile.mingw b/makefile.mingw index 5497a1f7a..3b858385b 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -51,13 +51,14 @@ bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32. bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o \ bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_bin_size.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ -bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin.o \ -bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o \ -bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o \ -bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o \ -bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o \ -bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o \ -bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_submod.o bn_mp_to_decimal.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o \ +bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_to_decimal_fast.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h $(HEADERS_PUB) diff --git a/makefile.msvc b/makefile.msvc index bddadd100..e06a47cbb 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -43,13 +43,14 @@ bn_mp_reduce_is_2k.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj bn_mp_roo bn_mp_set.obj bn_mp_set_double.obj bn_mp_set_i32.obj bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_ll.obj \ bn_mp_set_u32.obj bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_set_ull.obj bn_mp_shrink.obj bn_mp_signed_bin_size.obj \ bn_mp_signed_rsh.obj bn_mp_sqr.obj bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj \ -bn_mp_submod.obj bn_mp_to_radix.obj bn_mp_to_signed_bin.obj bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin.obj \ -bn_mp_to_unsigned_bin_n.obj bn_mp_unsigned_bin_size.obj bn_mp_xor.obj bn_mp_zero.obj bn_prime_tab.obj bn_s_mp_add.obj \ -bn_s_mp_balance_mul.obj bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj \ -bn_s_mp_invmod_slow.obj bn_s_mp_karatsuba_mul.obj bn_s_mp_karatsuba_sqr.obj bn_s_mp_montgomery_reduce_fast.obj \ -bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj bn_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs_fast.obj \ -bn_s_mp_prime_is_divisible.obj bn_s_mp_rand_jenkins.obj bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj \ -bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj bn_s_mp_sub.obj bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj +bn_mp_submod.obj bn_mp_to_decimal.obj bn_mp_to_radix.obj bn_mp_to_signed_bin.obj bn_mp_to_signed_bin_n.obj \ +bn_mp_to_unsigned_bin.obj bn_mp_to_unsigned_bin_n.obj bn_mp_unsigned_bin_size.obj bn_mp_xor.obj bn_mp_zero.obj \ +bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj \ +bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj bn_s_mp_karatsuba_mul.obj \ +bn_s_mp_karatsuba_sqr.obj bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj \ +bn_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj \ +bn_s_mp_rand_jenkins.obj bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj \ +bn_s_mp_sub.obj bn_s_mp_to_decimal_fast.obj bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h $(HEADERS_PUB) diff --git a/makefile.shared b/makefile.shared index f77b5e592..6dd88dd2c 100644 --- a/makefile.shared +++ b/makefile.shared @@ -45,13 +45,14 @@ bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32. bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o \ bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_bin_size.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ -bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin.o \ -bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o \ -bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o \ -bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o \ -bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o \ -bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o \ -bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_submod.o bn_mp_to_decimal.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o \ +bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_to_decimal_fast.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o #END_INS diff --git a/makefile.unix b/makefile.unix index 4bdb5d5b6..365036578 100644 --- a/makefile.unix +++ b/makefile.unix @@ -52,13 +52,14 @@ bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32. bn_mp_set.o bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o \ bn_mp_set_u32.o bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_bin_size.o \ bn_mp_signed_rsh.o bn_mp_sqr.o bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o \ -bn_mp_submod.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin.o \ -bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_prime_tab.o bn_s_mp_add.o \ -bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o \ -bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o \ -bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o \ -bn_s_mp_prime_is_divisible.o bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o \ -bn_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o +bn_mp_submod.o bn_mp_to_decimal.o bn_mp_to_radix.o bn_mp_to_signed_bin.o bn_mp_to_signed_bin_n.o \ +bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_to_decimal_fast.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h $(HEADERS_PUB) diff --git a/tommath.def b/tommath.def index 1deeb948b..9a2614e3c 100644 --- a/tommath.def +++ b/tommath.def @@ -136,6 +136,7 @@ EXPORTS mp_sub mp_sub_d mp_submod + mp_to_decimal mp_to_radix mp_to_signed_bin mp_to_signed_bin_n diff --git a/tommath.h b/tommath.h index 8550340cd..126eaab83 100644 --- a/tommath.h +++ b/tommath.h @@ -703,6 +703,7 @@ MP_DEPRECATED(mp_to_radix) mp_err mp_toradix(const mp_int *a, char *str, int rad MP_DEPRECATED(mp_to_radix) mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) MP_WUR; mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, int radix) MP_WUR; mp_err mp_radix_size(const mp_int *a, int radix, int *size) MP_WUR; +mp_err mp_to_decimal(const mp_int *a, char *str, size_t maxlen) MP_WUR; #ifndef MP_NO_FILE mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR; @@ -723,7 +724,6 @@ mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; #define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), 2) #define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), 8) -#define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), 10) #define mp_to_hex(M, S, N) mp_to_radix((M), (S), (N), 16) #ifdef __cplusplus diff --git a/tommath_class.h b/tommath_class.h index 32d1b2dcf..5baf8c0d7 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -137,6 +137,7 @@ # define BN_MP_SUB_C # define BN_MP_SUB_D_C # define BN_MP_SUBMOD_C +# define BN_MP_TO_DECIMAL_C # define BN_MP_TO_RADIX_C # define BN_MP_TO_SIGNED_BIN_C # define BN_MP_TO_SIGNED_BIN_N_C @@ -167,6 +168,7 @@ # define BN_S_MP_SQR_C # define BN_S_MP_SQR_FAST_C # define BN_S_MP_SUB_C +# define BN_S_MP_TO_DECIMAL_FAST_C # define BN_S_MP_TOOM_MUL_C # define BN_S_MP_TOOM_SQR_C #endif @@ -1052,6 +1054,11 @@ # define BN_MP_SUB_C #endif +#if defined(BN_MP_TO_DECIMAL_C) +# define BN_MP_TO_RADIX_C +# define BN_S_MP_TO_DECIMAL_FAST_C +#endif + #if defined(BN_MP_TO_RADIX_C) # define BN_MP_CLEAR_C # define BN_MP_DIV_D_C @@ -1267,6 +1274,28 @@ # define BN_MP_GROW_C #endif +#if defined(BN_S_MP_TO_DECIMAL_FAST_C) +# define BN_MP_ADD_C +# define BN_MP_ADD_D_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_C +# define BN_MP_COPY_C +# define BN_MP_DECR_C +# define BN_MP_DIV_2D_C +# define BN_MP_GET_I32_C +# define BN_MP_INCR_C +# define BN_MP_INIT_COPY_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_NEG_C +# define BN_MP_SET_U32_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +# define BN_S_MP_TO_DECIMAL_FAST_REC_C +#endif + #if defined(BN_S_MP_TOOM_MUL_C) # define BN_MP_ADD_C # define BN_MP_CLAMP_C diff --git a/tommath_private.h b/tommath_private.h index b5650424a..a98fee515 100644 --- a/tommath_private.h +++ b/tommath_private.h @@ -205,6 +205,7 @@ MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat); MP_PRIVATE void s_mp_reverse(unsigned char *s, int len); MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result); +MP_PRIVATE mp_err s_mp_to_decimal_fast(const mp_int *a, char *result, size_t maxlen) MP_WUR; /* TODO: jenkins prng is not thread safe as of now */ MP_PRIVATE mp_err s_mp_rand_jenkins(void *p, size_t n) MP_WUR; diff --git a/tommath_superclass.h b/tommath_superclass.h index b007c243d..e2b13b521 100644 --- a/tommath_superclass.h +++ b/tommath_superclass.h @@ -37,6 +37,7 @@ # define BN_MP_SET_UL_C # define BN_MP_SIGNED_BIN_SIZE_C # define BN_MP_TO_RADIX_C +# define BN_MP_TO_DECIMAL_C # define BN_MP_TO_SIGNED_BIN_C # define BN_S_MP_RAND_JENKINS_C # define BN_S_MP_RAND_PLATFORM_C