From cfe175667238055609c42d96552919b43e90e4ab Mon Sep 17 00:00:00 2001 From: Daniel Green Date: Tue, 20 Aug 2019 17:10:44 -0400 Subject: [PATCH 1/4] Add a new mp_todec_fast... that uses Barrett reduction to speed up stringifying large integers. --- bn_mp_todecimal_fast.c | 199 +++++++++++++++++++++++++++++++++++++++ libtommath_VS2008.vcproj | 4 + makefile | 14 +-- makefile.mingw | 14 +-- makefile.msvc | 14 +-- makefile.shared | 14 +-- makefile.unix | 14 +-- tommath_class.h | 23 +++++ 8 files changed, 261 insertions(+), 35 deletions(-) create mode 100644 bn_mp_todecimal_fast.c diff --git a/bn_mp_todecimal_fast.c b/bn_mp_todecimal_fast.c new file mode 100644 index 000000000..77d3a37fc --- /dev/null +++ b/bn_mp_todecimal_fast.c @@ -0,0 +1,199 @@ +#include "tommath_private.h" +#include +#ifdef BN_MP_TODECIMAL_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store a bignum as a decimal ASCII string */ +mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int *mL, int index, int left, char **result) { + mp_int q, nLq, r; + mp_err err; + + if (index < 0) { + char *next_piece = calloc(4, sizeof(char)); + int s_s = snprintf(next_piece, 4, left ? "%u" : "%03u", mp_get_u32(number)); + int r_s = strlen(*result); + (*result) = realloc(*result, r_s + s_s + 2); + strcat(*result, next_piece); + return MP_OKAY; + } + + if ((err = mp_init_multi(&q, &nLq, &r, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul(number, &mL[index], &q)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2d(&q, mp_get_u32(&shiftL[index]), &q, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_mul(&nL[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_sub_d(&q, 1, &q)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(&r, &nL[index], &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + + --index; + if (left && mp_iszero(&q)) { + if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, index, 1, result)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + if ((err = mp_todecimal_fast_rec(&q, nL, shiftL, mL, index, left, result)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, index, 0, result)) != MP_OKAY) { + goto LBL_ERR; + } + } + + err = MP_OKAY; + +LBL_ERR:mp_clear_multi (&q, &nLq, &r, NULL); + return err; +} + +mp_err mp_todecimal_fast(mp_int *number, char **result) { + mp_int n, shift, M, M2, M22, M4, M44; + mp_int *nL, *shiftL, *mL; + mp_err err; + int index = 1; + + if ((err = mp_init_multi(&M2, &M22, &M4, &M44, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_isneg(number)) { + if ((err = mp_neg(number, number)) != MP_OKAY) { + goto LBL_ERR; + } + *result[0] = '-'; + } + if ((err = mp_init_set(&n, 1000)) != MP_OKAY) { + goto LBL_ERR; + } + + nL = malloc(20 * sizeof(mp_int)); + if ((err = mp_init_copy(&nL[0], &n)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_init_set(&shift, 20)) != MP_OKAY) { + goto LBL_ERR; + } + + shiftL = malloc(20 * sizeof(mp_int)); + if ((err = mp_init_copy(&shiftL[0], &shift)) != MP_OKAY) { + goto LBL_ERR; + } + + /* (8 * 2**$shift) / $n rounded up */ + if ((err = mp_init_set(&M, 8389)) != MP_OKAY) { + goto LBL_ERR; + } + + /* $M / 8, rounded up */ + mL = malloc(20 * sizeof(mp_int)); + if ((err = mp_init_set(&mL[0], 1049)) != MP_OKAY) { + goto LBL_ERR; + } + + while (1) { + 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_ul(&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_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, &M)) != MP_OKAY) { + goto LBL_ERR; + } + } + + if ((err = mp_init_copy(&nL[index], &n)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_init_copy(&shiftL[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[index], &M4)) != MP_OKAY) { + goto LBL_ERR; + } + index++; + } + + if ((err = mp_todecimal_fast_rec(number, nL, shiftL, mL, index - 1, 1, result)) != MP_OKAY) { + goto LBL_ERR; + } + + err = MP_OKAY; + +LBL_ERR:mp_clear_multi (&n, &shift, &M, &M2, &M22, &M4, &M44, NULL); + return err; +} + +#endif diff --git a/libtommath_VS2008.vcproj b/libtommath_VS2008.vcproj index bfe9bfd32..0708eb71e 100644 --- a/libtommath_VS2008.vcproj +++ b/libtommath_VS2008.vcproj @@ -832,6 +832,10 @@ RelativePath="bn_mp_to_unsigned_bin_n.c" > + + diff --git a/makefile b/makefile index ea4df4cd6..193eae2e7 100644 --- a/makefile +++ b/makefile @@ -49,13 +49,13 @@ 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_ 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_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_toradix.o bn_mp_toradix_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_to_unsigned_bin_n.o bn_mp_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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 #END_INS diff --git a/makefile.mingw b/makefile.mingw index 793415d48..2761cc5eb 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -52,13 +52,13 @@ 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_ 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_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_toradix.o bn_mp_toradix_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_to_unsigned_bin_n.o bn_mp_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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 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 736cc1071..66dbf7e05 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -44,13 +44,13 @@ bn_mp_set.obj bn_mp_set_double.obj bn_mp_set_i32.obj bn_mp_set_i64.obj bn_mp_set 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_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_toradix.obj bn_mp_toradix_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_to_unsigned_bin_n.obj bn_mp_todecimal_fast.obj bn_mp_toradix.obj bn_mp_toradix_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 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 f000b4689..c76f93974 100644 --- a/makefile.shared +++ b/makefile.shared @@ -46,13 +46,13 @@ 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_ 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_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_toradix.o bn_mp_toradix_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_to_unsigned_bin_n.o bn_mp_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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 #END_INS diff --git a/makefile.unix b/makefile.unix index 5a9767ddf..fe9cde71d 100644 --- a/makefile.unix +++ b/makefile.unix @@ -53,13 +53,13 @@ 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_ 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_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_toradix.o bn_mp_toradix_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_to_unsigned_bin_n.o bn_mp_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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 HEADERS_PUB=tommath.h HEADERS=tommath_private.h tommath_class.h tommath_superclass.h $(HEADERS_PUB) diff --git a/tommath_class.h b/tommath_class.h index cc94e1601..251324777 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -141,6 +141,7 @@ # define BN_MP_TO_SIGNED_BIN_N_C # define BN_MP_TO_UNSIGNED_BIN_C # define BN_MP_TO_UNSIGNED_BIN_N_C +# define BN_MP_TODECIMAL_FAST_C # define BN_MP_TORADIX_C # define BN_MP_TORADIX_N_C # define BN_MP_UNSIGNED_BIN_SIZE_C @@ -1071,6 +1072,28 @@ # define BN_MP_UNSIGNED_BIN_SIZE_C #endif +#if defined(BN_MP_TODECIMAL_FAST_C) +# define BN_MP_2EXPT_C +# define BN_MP_ADD_C +# define BN_MP_ADD_D_C +# define BN_MP_BARRETT_TODECIMAL_C +# define BN_MP_BARRETT_TODECIMAL_REC_C +# define BN_MP_CMP_C +# define BN_MP_DIV_2D_C +# define BN_MP_GET_INT_C +# define BN_MP_GET_LONG_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INIT_SET_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_NEG_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +#endif + #if defined(BN_MP_TORADIX_C) # define BN_MP_CLEAR_C # define BN_MP_DIV_D_C From e629c1e02c657af047cec7c1a636b93790af9654 Mon Sep 17 00:00:00 2001 From: Daniel Green Date: Fri, 23 Aug 2019 13:45:51 -0400 Subject: [PATCH 2/4] Fix problems found by travis and appveyor --- bn_mp_todecimal_fast.c | 358 +++++++++++++++++++++-------------------- tommath.def | 1 + tommath_class.h | 9 +- 3 files changed, 185 insertions(+), 183 deletions(-) diff --git a/bn_mp_todecimal_fast.c b/bn_mp_todecimal_fast.c index 77d3a37fc..b07ec69dc 100644 --- a/bn_mp_todecimal_fast.c +++ b/bn_mp_todecimal_fast.c @@ -1,199 +1,203 @@ #include "tommath_private.h" #include +#include #ifdef BN_MP_TODECIMAL_FAST_C /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* store a bignum as a decimal ASCII string */ -mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int *mL, int index, int left, char **result) { - mp_int q, nLq, r; - mp_err err; - - if (index < 0) { - char *next_piece = calloc(4, sizeof(char)); - int s_s = snprintf(next_piece, 4, left ? "%u" : "%03u", mp_get_u32(number)); - int r_s = strlen(*result); - (*result) = realloc(*result, r_s + s_s + 2); - strcat(*result, next_piece); - return MP_OKAY; - } - - if ((err = mp_init_multi(&q, &nLq, &r, NULL)) != MP_OKAY) { - goto LBL_ERR; - } - if ((err = mp_mul(number, &mL[index], &q)) != MP_OKAY) { - goto LBL_ERR; - } - if ((err = mp_div_2d(&q, mp_get_u32(&shiftL[index]), &q, NULL)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((err = mp_mul(&nL[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_sub_d(&q, 1, &q)) != MP_OKAY) { +mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int *mL, int precalc_array_index, int left, + char **result) +{ + mp_int q, nLq, r; + mp_err err; + + if (precalc_array_index < 0) { + char *next_piece = calloc(4, sizeof(char)); + int s_s = left ? snprintf(next_piece, 4, "%u", mp_get_i32(number)) : snprintf(next_piece, 4, "%03u", + mp_get_i32(number)); + int r_s = (int)strlen(*result); + (*result) = realloc(*result, (size_t)(r_s + s_s + 2)); + strcat(*result, next_piece); + 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_sub_d(&q, 1, &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 = mp_todecimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 1, result)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + if ((err = mp_todecimal_fast_rec(&q, nL, shiftL, mL, precalc_array_index, left, result)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 0, result)) != MP_OKAY) { + goto LBL_ERR; + } + } + + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&q, &nLq, &r, NULL); + return err; +} + +mp_err mp_todecimal_fast(mp_int *number, char **result) +{ + mp_int n, shift, M, M2, M22, M4, M44; + mp_int nL[20], shiftL[20], mL[20]; + mp_err err; + int precalc_array_index = 1; + + if ((err = mp_init_multi(&M2, &M22, &M4, &M44, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_isneg(number)) { + if ((err = mp_neg(number, number)) != MP_OKAY) { + goto LBL_ERR; + } + *result[0] = '-'; + } + if ((err = mp_init_set(&n, (mp_digit)1000)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_init_copy(&nL[0], &n)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_init_set(&shift, (mp_digit)20)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = mp_init_copy(&shiftL[0], &shift)) != MP_OKAY) { + goto LBL_ERR; + } + + /* (8 * 2**$shift) / $n rounded up */ + if ((err = mp_init_set(&M, (mp_digit)8389)) != MP_OKAY) { + goto LBL_ERR; + } + + /* $M / 8, rounded up */ + if ((err = mp_init_set(&mL[0], (mp_digit)1049)) != MP_OKAY) { + goto LBL_ERR; + } + + while (1) { + 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_add(&r, &nL[index], &r)) != MP_OKAY) { + } + if ((err = mp_sqr(&M2, &M4)) != MP_OKAY) { goto LBL_ERR; - } - } + } - --index; - if (left && mp_iszero(&q)) { - if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, index, 1, result)) != MP_OKAY) { + if ((err = mp_mul(&M4, &n, &M4)) != MP_OKAY) { goto LBL_ERR; - } - } else { - if ((err = mp_todecimal_fast_rec(&q, nL, shiftL, mL, index, left, result)) != MP_OKAY) { + } + if ((err = mp_div_2d(&M4, mp_get_i32(&shift) + 6, &M4, NULL)) != MP_OKAY) { goto LBL_ERR; - } - if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, index, 0, result)) != MP_OKAY) { + } + if ((err = mp_mul_2(&M2, &M2)) != MP_OKAY) { goto LBL_ERR; - } - } - - err = MP_OKAY; - -LBL_ERR:mp_clear_multi (&q, &nLq, &r, NULL); - return err; -} - -mp_err mp_todecimal_fast(mp_int *number, char **result) { - mp_int n, shift, M, M2, M22, M4, M44; - mp_int *nL, *shiftL, *mL; - mp_err err; - int index = 1; - - if ((err = mp_init_multi(&M2, &M22, &M4, &M44, NULL)) != MP_OKAY) { - goto LBL_ERR; - } - - if (mp_isneg(number)) { - if ((err = mp_neg(number, number)) != MP_OKAY) { + } + if ((err = mp_sub(&M4, &M2, &M4)) != MP_OKAY) { goto LBL_ERR; - } - *result[0] = '-'; - } - if ((err = mp_init_set(&n, 1000)) != MP_OKAY) { - goto LBL_ERR; - } - - nL = malloc(20 * sizeof(mp_int)); - if ((err = mp_init_copy(&nL[0], &n)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((err = mp_init_set(&shift, 20)) != MP_OKAY) { - goto LBL_ERR; - } - - shiftL = malloc(20 * sizeof(mp_int)); - if ((err = mp_init_copy(&shiftL[0], &shift)) != MP_OKAY) { - goto LBL_ERR; - } - - /* (8 * 2**$shift) / $n rounded up */ - if ((err = mp_init_set(&M, 8389)) != MP_OKAY) { - goto LBL_ERR; - } - - /* $M / 8, rounded up */ - mL = malloc(20 * sizeof(mp_int)); - if ((err = mp_init_set(&mL[0], 1049)) != MP_OKAY) { - goto LBL_ERR; - } - - while (1) { - if ((err = mp_sqr(&n, &n)) != MP_OKAY) { + } + if ((err = mp_add_d(&M4, 1, &M4)) != MP_OKAY) { goto LBL_ERR; - } - if (mp_cmp(&n, number) == MP_GT) { - break; - } - - if ((err = mp_mul_2(&shift, &shift)) != MP_OKAY) { + } + if ((err = mp_div_2d(&M4, 3, &M4, NULL)) != 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_ul(&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_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, &M)) != MP_OKAY) { - goto LBL_ERR; - } - } - - if ((err = mp_init_copy(&nL[index], &n)) != MP_OKAY) { + } + if ((err = mp_sub_d(&M4, 1, &M4)) != MP_OKAY) { goto LBL_ERR; - } - if ((err = mp_init_copy(&shiftL[index], &shift)) != MP_OKAY) { + } + if ((err = mp_neg(&M4, &M)) != 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[index], &M4)) != MP_OKAY) { + } + } + + 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; - } - index++; - } - - if ((err = mp_todecimal_fast_rec(number, nL, shiftL, mL, index - 1, 1, result)) != MP_OKAY) { - goto LBL_ERR; - } - - err = MP_OKAY; - -LBL_ERR:mp_clear_multi (&n, &shift, &M, &M2, &M22, &M4, &M44, NULL); - return 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; + } + precalc_array_index++; + } + + if ((err = mp_todecimal_fast_rec(number, nL, shiftL, mL, precalc_array_index - 1, 1, result)) != MP_OKAY) { + goto LBL_ERR; + } + + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&n, &shift, &M, &M2, &M22, &M4, &M44, NULL); + return err; } #endif diff --git a/tommath.def b/tommath.def index 841884302..f58ece2af 100644 --- a/tommath.def +++ b/tommath.def @@ -140,6 +140,7 @@ EXPORTS mp_to_signed_bin_n mp_to_unsigned_bin mp_to_unsigned_bin_n + mp_todecimal_fast mp_toradix mp_toradix_n mp_unsigned_bin_size diff --git a/tommath_class.h b/tommath_class.h index 251324777..7f2ddbdda 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -1073,16 +1073,12 @@ #endif #if defined(BN_MP_TODECIMAL_FAST_C) -# define BN_MP_2EXPT_C # define BN_MP_ADD_C # define BN_MP_ADD_D_C -# define BN_MP_BARRETT_TODECIMAL_C -# define BN_MP_BARRETT_TODECIMAL_REC_C +# define BN_MP_CLEAR_MULTI_C # define BN_MP_CMP_C # define BN_MP_DIV_2D_C -# define BN_MP_GET_INT_C -# define BN_MP_GET_LONG_C -# define BN_MP_INIT_C +# define BN_MP_GET_I32_C # define BN_MP_INIT_COPY_C # define BN_MP_INIT_MULTI_C # define BN_MP_INIT_SET_C @@ -1092,6 +1088,7 @@ # define BN_MP_SQR_C # define BN_MP_SUB_C # define BN_MP_SUB_D_C +# define BN_MP_TODECIMAL_FAST_REC_C #endif #if defined(BN_MP_TORADIX_C) From 4accd98109502cd60cef1c83c33ca4fbd8a33712 Mon Sep 17 00:00:00 2001 From: Daniel Green Date: Mon, 26 Aug 2019 16:09:10 -0400 Subject: [PATCH 3/4] Make `mp_todecimal_fast` take a pre-allocated... buffer like `mp_toradix` does. --- bn_mp_todecimal_fast.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/bn_mp_todecimal_fast.c b/bn_mp_todecimal_fast.c index b07ec69dc..f44cb2574 100644 --- a/bn_mp_todecimal_fast.c +++ b/bn_mp_todecimal_fast.c @@ -1,6 +1,5 @@ #include "tommath_private.h" #include -#include #ifdef BN_MP_TODECIMAL_FAST_C /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ @@ -13,12 +12,9 @@ mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int mp_err err; if (precalc_array_index < 0) { - char *next_piece = calloc(4, sizeof(char)); - int s_s = left ? snprintf(next_piece, 4, "%u", mp_get_i32(number)) : snprintf(next_piece, 4, "%03u", - mp_get_i32(number)); - int r_s = (int)strlen(*result); - (*result) = realloc(*result, (size_t)(r_s + s_s + 2)); - strcat(*result, next_piece); + int new_pos = left ? snprintf(*result, 4, "%u", mp_get_i32(number)) : snprintf(*result, 4, "%03u", + mp_get_i32(number)); + *result += new_pos; return MP_OKAY; } @@ -70,11 +66,12 @@ mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int return err; } -mp_err mp_todecimal_fast(mp_int *number, char **result) +mp_err mp_todecimal_fast(mp_int *number, char *result) { mp_int 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; if ((err = mp_init_multi(&M2, &M22, &M4, &M44, NULL)) != MP_OKAY) { @@ -85,7 +82,8 @@ mp_err mp_todecimal_fast(mp_int *number, char **result) if ((err = mp_neg(number, number)) != MP_OKAY) { goto LBL_ERR; } - *result[0] = '-'; + result[0] = '-'; + result_addr += 1; } if ((err = mp_init_set(&n, (mp_digit)1000)) != MP_OKAY) { goto LBL_ERR; @@ -189,7 +187,7 @@ mp_err mp_todecimal_fast(mp_int *number, char **result) precalc_array_index++; } - if ((err = mp_todecimal_fast_rec(number, nL, shiftL, mL, precalc_array_index - 1, 1, result)) != MP_OKAY) { + if ((err = mp_todecimal_fast_rec(number, nL, shiftL, mL, precalc_array_index - 1, 1, result_addr)) != MP_OKAY) { goto LBL_ERR; } From f84b69ceeaa85a18186c366587eac025cfe4606f Mon Sep 17 00:00:00 2001 From: Daniel Green Date: Sat, 31 Aug 2019 16:20:20 +0100 Subject: [PATCH 4/4] Turn the `mp_todecimal` macro into a function... that uses MP_HAS to decide whether to use `mp_toradix` or `s_mp_todecimal_fast`. --- bn_mp_todecimal.c | 23 ++++++++++ ...decimal_fast.c => bn_s_mp_todecimal_fast.c | 28 +++++++------ libtommath_VS2008.vcproj | 6 ++- makefile | 9 ++-- makefile.mingw | 9 ++-- makefile.msvc | 9 ++-- makefile.shared | 9 ++-- makefile.unix | 9 ++-- tommath.def | 2 +- tommath.h | 2 +- tommath_class.h | 42 +++++++++++-------- tommath_private.h | 1 + 12 files changed, 96 insertions(+), 53 deletions(-) create mode 100644 bn_mp_todecimal.c rename bn_mp_todecimal_fast.c => bn_s_mp_todecimal_fast.c (82%) diff --git a/bn_mp_todecimal.c b/bn_mp_todecimal.c new file mode 100644 index 000000000..f9e0b7649 --- /dev/null +++ b/bn_mp_todecimal.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef BN_MP_TODECIMAL_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_todecimal(const mp_int *a, char *str) +{ + mp_err err; + + if (MP_HAS(S_MP_TODECIMAL_FAST)) { + err = s_mp_todecimal_fast(a, str); + } else { + err = mp_toradix(a, str, 10); + } + + return err; +} + +#endif diff --git a/bn_mp_todecimal_fast.c b/bn_s_mp_todecimal_fast.c similarity index 82% rename from bn_mp_todecimal_fast.c rename to bn_s_mp_todecimal_fast.c index f44cb2574..77883f9aa 100644 --- a/bn_mp_todecimal_fast.c +++ b/bn_s_mp_todecimal_fast.c @@ -1,12 +1,13 @@ #include "tommath_private.h" #include -#ifdef BN_MP_TODECIMAL_FAST_C +#ifdef BN_S_MP_TODECIMAL_FAST_C /* LibTomMath, multiple-precision integer library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* store a bignum as a decimal ASCII string */ -mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int *mL, int precalc_array_index, int left, - char **result) +mp_err s_mp_todecimal_fast_rec(const mp_int *number, mp_int *nL, mp_int *shiftL, mp_int *mL, int precalc_array_index, + int left, + char **result) { mp_int q, nLq, r; mp_err err; @@ -47,14 +48,14 @@ mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int --precalc_array_index; if (left && mp_iszero(&q)) { - if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 1, result)) != MP_OKAY) { + if ((err = s_mp_todecimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 1, result)) != MP_OKAY) { goto LBL_ERR; } } else { - if ((err = mp_todecimal_fast_rec(&q, nL, shiftL, mL, precalc_array_index, left, result)) != MP_OKAY) { + if ((err = s_mp_todecimal_fast_rec(&q, nL, shiftL, mL, precalc_array_index, left, result)) != MP_OKAY) { goto LBL_ERR; } - if ((err = mp_todecimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 0, result)) != MP_OKAY) { + if ((err = s_mp_todecimal_fast_rec(&r, nL, shiftL, mL, precalc_array_index, 0, result)) != MP_OKAY) { goto LBL_ERR; } } @@ -66,9 +67,9 @@ mp_err mp_todecimal_fast_rec(mp_int *number, mp_int *nL, mp_int *shiftL, mp_int return err; } -mp_err mp_todecimal_fast(mp_int *number, char *result) +mp_err s_mp_todecimal_fast(const mp_int *a, char *result) { - mp_int n, shift, M, M2, M22, M4, M44; + 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; @@ -78,8 +79,11 @@ mp_err mp_todecimal_fast(mp_int *number, char *result) goto LBL_ERR; } - if (mp_isneg(number)) { - if ((err = mp_neg(number, number)) != MP_OKAY) { + if ((err = mp_init_copy(&number, a)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_isneg(&number)) { + if ((err = mp_neg(&number, &number)) != MP_OKAY) { goto LBL_ERR; } result[0] = '-'; @@ -115,7 +119,7 @@ mp_err mp_todecimal_fast(mp_int *number, char *result) if ((err = mp_sqr(&n, &n)) != MP_OKAY) { goto LBL_ERR; } - if (mp_cmp(&n, number) == MP_GT) { + if (mp_cmp(&n, &number) == MP_GT) { break; } @@ -187,7 +191,7 @@ mp_err mp_todecimal_fast(mp_int *number, char *result) precalc_array_index++; } - if ((err = mp_todecimal_fast_rec(number, nL, shiftL, mL, precalc_array_index - 1, 1, result_addr)) != MP_OKAY) { + if ((err = s_mp_todecimal_fast_rec(&number, nL, shiftL, mL, precalc_array_index - 1, 1, result_addr)) != MP_OKAY) { goto LBL_ERR; } diff --git a/libtommath_VS2008.vcproj b/libtommath_VS2008.vcproj index 0708eb71e..939dcf165 100644 --- a/libtommath_VS2008.vcproj +++ b/libtommath_VS2008.vcproj @@ -833,7 +833,7 @@ > + + diff --git a/makefile b/makefile index 193eae2e7..fabd2c4d7 100644 --- a/makefile +++ b/makefile @@ -49,13 +49,14 @@ 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_ 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_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_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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_mp_to_unsigned_bin_n.o bn_mp_todecimal.o bn_mp_toradix.o bn_mp_toradix_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_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_todecimal_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 2761cc5eb..1d5a51c02 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -52,13 +52,14 @@ 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_ 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_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_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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_mp_to_unsigned_bin_n.o bn_mp_todecimal.o bn_mp_toradix.o bn_mp_toradix_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_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_todecimal_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 66dbf7e05..10be2b242 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -44,13 +44,14 @@ bn_mp_set.obj bn_mp_set_double.obj bn_mp_set_i32.obj bn_mp_set_i64.obj bn_mp_set 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_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_todecimal_fast.obj bn_mp_toradix.obj bn_mp_toradix_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_mp_to_unsigned_bin_n.obj bn_mp_todecimal.obj bn_mp_toradix.obj bn_mp_toradix_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_s_mp_sqr.obj bn_s_mp_sqr_fast.obj bn_s_mp_sub.obj bn_s_mp_todecimal_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 c76f93974..613b13a5c 100644 --- a/makefile.shared +++ b/makefile.shared @@ -46,13 +46,14 @@ 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_ 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_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_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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_mp_to_unsigned_bin_n.o bn_mp_todecimal.o bn_mp_toradix.o bn_mp_toradix_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_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_todecimal_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 fe9cde71d..bb9d192d3 100644 --- a/makefile.unix +++ b/makefile.unix @@ -53,13 +53,14 @@ 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_ 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_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_todecimal_fast.o bn_mp_toradix.o bn_mp_toradix_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_mp_to_unsigned_bin_n.o bn_mp_todecimal.o bn_mp_toradix.o bn_mp_toradix_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_s_mp_sqr.o bn_s_mp_sqr_fast.o bn_s_mp_sub.o bn_s_mp_todecimal_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 f58ece2af..f1befa086 100644 --- a/tommath.def +++ b/tommath.def @@ -140,7 +140,7 @@ EXPORTS mp_to_signed_bin_n mp_to_unsigned_bin mp_to_unsigned_bin_n - mp_todecimal_fast + mp_todecimal mp_toradix mp_toradix_n mp_unsigned_bin_size diff --git a/tommath.h b/tommath.h index 8efb9f931..93ef2cf23 100644 --- a/tommath.h +++ b/tommath.h @@ -702,6 +702,7 @@ mp_err mp_read_radix(mp_int *a, const char *str, int radix) MP_WUR; mp_err mp_toradix(const mp_int *a, char *str, int radix) MP_WUR; mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) MP_WUR; mp_err mp_radix_size(const mp_int *a, int radix, int *size) MP_WUR; +mp_err mp_todecimal(const mp_int *a, char *str) MP_WUR; #ifndef MP_NO_FILE mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR; @@ -717,7 +718,6 @@ mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; #define mp_tobinary(M, S) mp_toradix((M), (S), 2) #define mp_tooctal(M, S) mp_toradix((M), (S), 8) -#define mp_todecimal(M, S) mp_toradix((M), (S), 10) #define mp_tohex(M, S) mp_toradix((M), (S), 16) #ifdef __cplusplus diff --git a/tommath_class.h b/tommath_class.h index 7f2ddbdda..16162b6b9 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -141,7 +141,7 @@ # define BN_MP_TO_SIGNED_BIN_N_C # define BN_MP_TO_UNSIGNED_BIN_C # define BN_MP_TO_UNSIGNED_BIN_N_C -# define BN_MP_TODECIMAL_FAST_C +# define BN_MP_TODECIMAL_C # define BN_MP_TORADIX_C # define BN_MP_TORADIX_N_C # define BN_MP_UNSIGNED_BIN_SIZE_C @@ -169,6 +169,7 @@ # define BN_S_MP_SQR_C # define BN_S_MP_SQR_FAST_C # define BN_S_MP_SUB_C +# define BN_S_MP_TODECIMAL_FAST_C # define BN_S_MP_TOOM_MUL_C # define BN_S_MP_TOOM_SQR_C #endif @@ -1072,23 +1073,9 @@ # define BN_MP_UNSIGNED_BIN_SIZE_C #endif -#if defined(BN_MP_TODECIMAL_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_DIV_2D_C -# define BN_MP_GET_I32_C -# define BN_MP_INIT_COPY_C -# define BN_MP_INIT_MULTI_C -# define BN_MP_INIT_SET_C -# define BN_MP_MUL_2_C -# define BN_MP_MUL_C -# define BN_MP_NEG_C -# define BN_MP_SQR_C -# define BN_MP_SUB_C -# define BN_MP_SUB_D_C -# define BN_MP_TODECIMAL_FAST_REC_C +#if defined(BN_MP_TODECIMAL_C) +# define BN_MP_TORADIX_C +# define BN_S_MP_TODECIMAL_FAST_C #endif #if defined(BN_MP_TORADIX_C) @@ -1286,6 +1273,25 @@ # define BN_MP_GROW_C #endif +#if defined(BN_S_MP_TODECIMAL_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_DIV_2D_C +# define BN_MP_GET_I32_C +# define BN_MP_INIT_COPY_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INIT_SET_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_NEG_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +# define BN_S_MP_TODECIMAL_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 4c25fa082..7bf7522e9 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_todecimal_fast(const mp_int *a, char *result) 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;