Merge pull request #469 from czurnieden/radix_overestimate_29bits

Radix overestimate with 29 bits precision
This commit is contained in:
Steffen Jaeckel 2019-12-04 22:27:09 +01:00 committed by GitHub
commit 6ac0b0c1b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 317 additions and 60 deletions

View File

@ -6,8 +6,8 @@ void ndraw(const mp_int *a, const char *name)
size_t size = 0;
mp_err err;
if ((err = mp_radix_size(a, 10, &size)) != MP_OKAY) {
fprintf(stderr, "\nndraw: mp_radix_size(a, 10, %zu) failed - %s\n", size, mp_error_to_string(err));
if ((err = mp_radix_size_overestimate(a, 10, &size)) != MP_OKAY) {
fprintf(stderr, "\nndraw: mp_radix_size_overestimate(a, 10, %zu) failed - %s\n", size, mp_error_to_string(err));
exit(EXIT_FAILURE);
}
buf = (char *)malloc(size);

View File

@ -2016,6 +2016,7 @@ LBL_ERR:
return EXIT_FAILURE;
}
static int test_mp_radix_size(void)
{
mp_int a;
@ -2201,6 +2202,104 @@ LBL_ERR:
}
static int test_s_mp_radix_size_overestimate(void)
{
mp_err err;
mp_int a;
int radix;
size_t size;
/* *INDENT-OFF* */
size_t results[65] = {
0u, 0u, 1627u, 1027u, 814u, 702u, 630u, 581u, 543u,
514u, 491u, 471u, 455u, 441u, 428u, 418u, 408u, 399u,
391u, 384u, 378u, 372u, 366u, 361u, 356u, 352u, 347u,
343u, 340u, 336u, 333u, 330u, 327u, 324u, 321u, 318u,
316u, 314u, 311u, 309u, 307u, 305u, 303u, 301u, 299u,
298u, 296u, 294u, 293u, 291u, 290u, 288u, 287u, 285u,
284u, 283u, 281u, 280u, 279u, 278u, 277u, 276u, 275u,
273u, 272u
};
size_t big_results[65] = {
0u, 0u, 0u, 1354911329u, 1073741825u,
924870867u, 830760078u, 764949110u, 715827883u, 677455665u,
646456994u, 620761988u, 599025415u, 580332018u, 564035582u,
549665673u, 536870913u, 525383039u, 514993351u, 505536793u,
496880930u, 488918137u, 481559946u, 474732892u, 468375401u,
462435434u, 456868672u, 451637110u, 446707948u, 442052707u,
437646532u, 433467613u, 429496730u, 425716865u, 422112892u,
418671312u, 415380039u, 412228213u, 409206043u, 406304679u,
403516096u, 400833001u, 398248746u, 395757256u, 393352972u,
391030789u, 388786017u, 386614331u, 384511740u, 382474555u,
380499357u, 378582973u, 376722456u, 374915062u, 373158233u,
371449582u, 369786879u, 368168034u, 366591092u, 365054217u,
363555684u, 362093873u, 360667257u, 359274399u, 357913942
};
/* *INDENT-ON* */
if ((err = mp_init(&a)) != MP_OKAY) goto LBL_ERR;
/* number to result in a different size for every base: 67^(4 * 67) */
mp_set(&a, 67);
if ((err = mp_expt_n(&a, 268, &a)) != MP_OKAY) {
goto LBL_ERR;
}
for (radix = 2; radix < 65; radix++) {
if ((err = s_mp_radix_size_overestimate(&a, radix, &size)) != MP_OKAY) {
goto LBL_ERR;
}
if (size < results[radix]) {
fprintf(stderr, "s_mp_radix_size_overestimate: result for base %d was %zu instead of %zu\n",
radix, size, results[radix]);
goto LBL_ERR;
}
a.sign = MP_NEG;
if ((err = s_mp_radix_size_overestimate(&a, radix, &size)) != MP_OKAY) {
goto LBL_ERR;
}
if (size < results[radix]) {
fprintf(stderr, "s_mp_radix_size_overestimate: result for base %d was %zu instead of %zu\n",
radix, size, results[radix]);
goto LBL_ERR;
}
a.sign = MP_ZPOS;
}
if ((err = mp_2expt(&a, INT_MAX - 1)) != MP_OKAY) {
goto LBL_ERR;
}
printf("bitcount = %d, alloc = %d\n", mp_count_bits(&a), a.alloc);
/* Start at 3 to avoid integer overflow */
for (radix = 3; radix < 65; radix++) {
printf("radix = %d, ",radix);
if ((err = s_mp_radix_size_overestimate(&a, radix, &size)) != MP_OKAY) {
goto LBL_ERR;
}
printf("size = %zu, diff = %zu\n", size, size - big_results[radix]);
if (size < big_results[radix]) {
fprintf(stderr, "s_mp_radix_size_overestimate: result for base %d was %zu instead of %zu\n",
radix, size, results[radix]);
goto LBL_ERR;
}
a.sign = MP_NEG;
if ((err = s_mp_radix_size_overestimate(&a, radix, &size)) != MP_OKAY) {
goto LBL_ERR;
}
if (size < big_results[radix]) {
fprintf(stderr, "s_mp_radix_size_overestimate: result for base %d was %zu instead of %zu\n",
radix, size, results[radix]);
goto LBL_ERR;
}
a.sign = MP_ZPOS;
}
mp_clear(&a);
return EXIT_SUCCESS;
LBL_ERR:
mp_clear(&a);
return EXIT_FAILURE;
}
static int test_mp_read_write_ubin(void)
{
mp_int a, b, c;
@ -2359,6 +2458,7 @@ static int unit_tests(int argc, char **argv)
T1(mp_reduce_2k, MP_REDUCE_2K),
T1(mp_reduce_2k_l, MP_REDUCE_2K_L),
T1(mp_radix_size, MP_RADIX_SIZE),
T1(s_mp_radix_size_overestimate, S_MP_RADIX_SIZE_OVERESTIMATE),
#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559)
T1(mp_set_double, MP_SET_DOUBLE),
#endif

View File

@ -2380,7 +2380,21 @@ mp_err mp_radix_size (const mp_int *a, int radix, int *size)
\end{alltt}
This stores in \texttt{size} the number of characters (including space for the \texttt{NUL}
terminator) required. Upon error this function returns an error code and \texttt{size} will be
zero.
zero. This version of \texttt{mp\_radix\_size} uses \texttt{mp\_log} to calculate the size. It
is exact but slow for larger numbers.
\index{mp\_radix\_size\_overestimate}
\begin{alltt}
mp_err mp_radix_size_overestimate (const mp_int *a, int radix, int *size)
\end{alltt}
This stores in \texttt{size} the number of characters (including space for the \texttt{NUL}
terminator) required. Upon error this function returns an error code and \texttt{size} will be
zero. This version of \texttt{mp\_radix\_size} is much faster than the exact version above but
introduces the relative error $\approx 10^{-8}$. That would be $22$ for $2^{2^{31}}-1$, the
largest possible number in LibTomMath. Experiments gave no absolute error over $+5$.
The result is \emph{always} either exact or too large but it is \emph{never} too small.
If \texttt{MP\_NO\_FILE} is not defined a function to write to a file is also available.

View File

@ -640,6 +640,10 @@
RelativePath="mp_radix_size.c"
>
</File>
<File
RelativePath="mp_radix_size_overestimate.c"
>
</File>
<File
RelativePath="mp_rand.c"
>
@ -884,6 +888,10 @@
RelativePath="s_mp_radix_map.c"
>
</File>
<File
RelativePath="s_mp_radix_size_overestimate.c"
>
</File>
<File
RelativePath="s_mp_rand_jenkins.c"
>

View File

@ -38,17 +38,18 @@ mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o mp_reduce_2k_setup.o \
mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o mp_root_n.o mp_rshd.o \
mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o mp_set_u32.o mp_set_u64.o \
mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o \
mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o \
s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o \
s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o s_mp_log_2expt.o \
s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o \
s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o \
s_mp_prime_tab.o s_mp_radix_map.o s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
mp_radix_size_overestimate.o mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o \
mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o \
mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o \
mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o \
mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o \
mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o \
s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o \
s_mp_log_2expt.o s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o s_mp_sqr_toom.o \
s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
#END_INS

View File

@ -40,17 +40,18 @@ mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o mp_reduce_2k_setup.o \
mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o mp_root_n.o mp_rshd.o \
mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o mp_set_u32.o mp_set_u64.o \
mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o \
mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o \
s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o \
s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o s_mp_log_2expt.o \
s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o \
s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o \
s_mp_prime_tab.o s_mp_radix_map.o s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
mp_radix_size_overestimate.o mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o \
mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o \
mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o \
mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o \
mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o \
mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o \
s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o \
s_mp_log_2expt.o s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o s_mp_sqr_toom.o \
s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

View File

@ -33,17 +33,18 @@ mp_montgomery_calc_normalization.obj mp_montgomery_reduce.obj mp_montgomery_setu
mp_mul_2d.obj mp_mul_d.obj mp_mulmod.obj mp_neg.obj mp_or.obj mp_pack.obj mp_pack_count.obj mp_prime_fermat.obj \
mp_prime_frobenius_underwood.obj mp_prime_is_prime.obj mp_prime_miller_rabin.obj mp_prime_next_prime.obj \
mp_prime_rabin_miller_trials.obj mp_prime_rand.obj mp_prime_strong_lucas_selfridge.obj mp_radix_size.obj \
mp_rand.obj mp_read_radix.obj mp_reduce.obj mp_reduce_2k.obj mp_reduce_2k_l.obj mp_reduce_2k_setup.obj \
mp_reduce_2k_setup_l.obj mp_reduce_is_2k.obj mp_reduce_is_2k_l.obj mp_reduce_setup.obj mp_root_n.obj mp_rshd.obj \
mp_sbin_size.obj mp_set.obj mp_set_double.obj mp_set_i32.obj mp_set_i64.obj mp_set_l.obj mp_set_u32.obj mp_set_u64.obj \
mp_set_ul.obj mp_shrink.obj mp_signed_rsh.obj mp_sqrmod.obj mp_sqrt.obj mp_sqrtmod_prime.obj mp_sub.obj mp_sub_d.obj \
mp_submod.obj mp_to_radix.obj mp_to_sbin.obj mp_to_ubin.obj mp_ubin_size.obj mp_unpack.obj mp_xor.obj mp_zero.obj s_mp_add.obj \
s_mp_copy_digs.obj s_mp_div_3.obj s_mp_div_recursive.obj s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj \
s_mp_exptmod_fast.obj s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log.obj s_mp_log_2expt.obj \
s_mp_log_d.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj s_mp_mul_balance.obj s_mp_mul_comba.obj \
s_mp_mul_high.obj s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj s_mp_mul_toom.obj s_mp_prime_is_divisible.obj \
s_mp_prime_tab.obj s_mp_radix_map.obj s_mp_rand_jenkins.obj s_mp_rand_platform.obj s_mp_sqr.obj s_mp_sqr_comba.obj \
s_mp_sqr_karatsuba.obj s_mp_sqr_toom.obj s_mp_sub.obj s_mp_zero_buf.obj s_mp_zero_digs.obj
mp_radix_size_overestimate.obj mp_rand.obj mp_read_radix.obj mp_reduce.obj mp_reduce_2k.obj mp_reduce_2k_l.obj \
mp_reduce_2k_setup.obj mp_reduce_2k_setup_l.obj mp_reduce_is_2k.obj mp_reduce_is_2k_l.obj mp_reduce_setup.obj \
mp_root_n.obj mp_rshd.obj mp_sbin_size.obj mp_set.obj mp_set_double.obj mp_set_i32.obj mp_set_i64.obj mp_set_l.obj \
mp_set_u32.obj mp_set_u64.obj mp_set_ul.obj mp_shrink.obj mp_signed_rsh.obj mp_sqrmod.obj mp_sqrt.obj mp_sqrtmod_prime.obj \
mp_sub.obj mp_sub_d.obj mp_submod.obj mp_to_radix.obj mp_to_sbin.obj mp_to_ubin.obj mp_ubin_size.obj mp_unpack.obj mp_xor.obj \
mp_zero.obj s_mp_add.obj s_mp_copy_digs.obj s_mp_div_3.obj s_mp_div_recursive.obj s_mp_div_school.obj s_mp_div_small.obj \
s_mp_exptmod.obj s_mp_exptmod_fast.obj s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log.obj \
s_mp_log_2expt.obj s_mp_log_d.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj s_mp_mul_balance.obj \
s_mp_mul_comba.obj s_mp_mul_high.obj s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj s_mp_mul_toom.obj \
s_mp_prime_is_divisible.obj s_mp_prime_tab.obj s_mp_radix_map.obj s_mp_radix_size_overestimate.obj \
s_mp_rand_jenkins.obj s_mp_rand_platform.obj s_mp_sqr.obj s_mp_sqr_comba.obj s_mp_sqr_karatsuba.obj s_mp_sqr_toom.obj \
s_mp_sub.obj s_mp_zero_buf.obj s_mp_zero_digs.obj
HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

View File

@ -35,17 +35,18 @@ mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o mp_reduce_2k_setup.o \
mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o mp_root_n.o mp_rshd.o \
mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o mp_set_u32.o mp_set_u64.o \
mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o \
mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o \
s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o \
s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o s_mp_log_2expt.o \
s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o \
s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o \
s_mp_prime_tab.o s_mp_radix_map.o s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
mp_radix_size_overestimate.o mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o \
mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o \
mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o \
mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o \
mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o \
mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o \
s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o \
s_mp_log_2expt.o s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o s_mp_sqr_toom.o \
s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
#END_INS

View File

@ -41,17 +41,19 @@ mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o mp_reduce_2k_setup.o \
mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o mp_root_n.o mp_rshd.o \
mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o mp_set_u32.o mp_set_u64.o \
mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o \
mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o \
s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o \
s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o s_mp_log_2expt.o \
s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o s_mp_mul_comba.o \
s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o s_mp_prime_is_divisible.o \
s_mp_prime_tab.o s_mp_radix_map.o s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o \
s_mp_sqr_karatsuba.o s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
mp_radix_size_overestimate.o mp_rand.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o mp_reduce_2k_l.o \
mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o mp_reduce_setup.o \
mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o mp_set_l.o \
mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o mp_sqrtmod_prime.o \
mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o mp_unpack.o mp_xor.o \
mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o s_mp_div_school.o s_mp_div_small.o \
s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log.o \
s_mp_log_2expt.o s_mp_log_d.o s_mp_montgomery_reduce_comba.o s_mp_mul.o s_mp_mul_balance.o \
s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o s_mp_mul_toom.o \
s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o s_mp_radix_size_overestimate.o \
s_mp_rand_jenkins.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o s_mp_sqr_toom.o \
s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o
HEADERS_PUB=tommath.h
HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB)

View File

@ -10,7 +10,7 @@ mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream)
mp_err err;
size_t size, written;
if ((err = mp_radix_size(a, radix, &size)) != MP_OKAY) {
if ((err = mp_radix_size_overestimate(a, radix, &size)) != MP_OKAY) {
return err;
}

View File

@ -0,0 +1,17 @@
#include "tommath_private.h"
#ifdef MP_RADIX_SIZE_OVERESTIMATE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
mp_err mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size)
{
if (MP_HAS(S_MP_RADIX_SIZE_OVERESTIMATE)) {
return s_mp_radix_size_overestimate(a, radix, size);
}
if (MP_HAS(MP_RADIX_SIZE)) {
return mp_radix_size(a, radix, size);
}
return MP_ERR;
}
#endif

View File

@ -0,0 +1,87 @@
#include "tommath_private.h"
#ifdef S_MP_RADIX_SIZE_OVERESTIMATE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/*
Overestimate the size needed for the bigint to string conversion by a very small amount.
The error is about 10^-8; it will overestimate the result by at most 11 elements for
a number of the size 2^(2^31)-1 which is currently the largest possible in this library.
Some short tests gave no results larger than 5 (plus 2 for sign and EOS).
*/
/*
Table of {0, INT(log_2([1..64])*2^p)+1 } where p is the scale
factor defined in MP_RADIX_SIZE_SCALE and INT() extracts the integer part (truncating).
Good for 32 bit "int". Set MP_RADIX_SIZE_SCALE = 61 and recompute values
for 64 bit "int".
*/
/* *INDENT-OFF* */
#define MP_RADIX_SIZE_SCALE 29
static const uint32_t s_log_bases[65] = {
0u, 0u, 0x20000001u, 0x14309399u, 0x10000001u,
0xdc81a35u, 0xc611924u, 0xb660c9eu, 0xaaaaaabu, 0xa1849cdu,
0x9a209a9u, 0x94004e1u, 0x8ed19c2u, 0x8a5ca7du, 0x867a000u,
0x830cee3u, 0x8000001u, 0x7d42d60u, 0x7ac8b32u, 0x7887847u,
0x7677349u, 0x749131fu, 0x72d0163u, 0x712f657u, 0x6fab5dbu,
0x6e40d1bu, 0x6ced0d0u, 0x6badbdeu, 0x6a80e3bu, 0x6964c19u,
0x6857d31u, 0x6758c38u, 0x6666667u, 0x657fb21u, 0x64a3b9fu,
0x63d1ab4u, 0x6308c92u, 0x624869eu, 0x618ff47u, 0x60dedeau,
0x6034ab0u, 0x5f90e7bu, 0x5ef32cbu, 0x5e5b1b2u, 0x5dc85c3u,
0x5d3aa02u, 0x5cb19d9u, 0x5c2d10fu, 0x5bacbbfu, 0x5b3064fu,
0x5ab7d68u, 0x5a42df0u, 0x59d1506u, 0x5962ffeu, 0x58f7c57u,
0x588f7bcu, 0x582a000u, 0x57c7319u, 0x5766f1du, 0x5709243u,
0x56adad9u, 0x565474du, 0x55fd61fu, 0x55a85e8u, 0x5555556u
};
/* *INDENT-ON* */
mp_err s_mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size)
{
int bit_count;
mp_int bi_bit_count, bi_k;
mp_err err = MP_OKAY;
if ((radix < 2) || (radix > 64)) {
return MP_VAL;
}
if (mp_iszero(a)) {
*size = 2U;
return MP_OKAY;
}
if (MP_HAS(S_MP_LOG_2EXPT) && MP_IS_2EXPT((mp_digit)radix)) {
/* floor(log_{2^n}(a)) + 1 + EOS + sign */
*size = (size_t)(s_mp_log_2expt(a, (mp_digit)radix));
/* Would overflow with base 2 otherwise */
if (*size > (INT_MAX - 4)) {
return MP_VAL;
}
*size += 3u;
return MP_OKAY;
}
if ((err = mp_init_multi(&bi_bit_count, &bi_k, NULL)) != MP_OKAY) {
return err;
}
/* la = floor(log_2(a)) + 1 */
bit_count = mp_count_bits(a);
mp_set_u32(&bi_bit_count, (uint32_t)bit_count);
/* k = floor(2^29/log_2(radix)) + 1 */
mp_set_u32(&bi_k, s_log_bases[radix]);
/* n = floor((la * k) / 2^29) + 1 */
if ((err = mp_mul(&bi_bit_count, &bi_k, &bi_bit_count)) != MP_OKAY) goto LBL_ERR;
if ((err = mp_div_2d(&bi_bit_count, MP_RADIX_SIZE_SCALE, &bi_bit_count, NULL)) != MP_OKAY) goto LBL_ERR;
/* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */
/* n = n + 1 + EOS + sign */
*size = (size_t)(mp_get_u64(&bi_bit_count) + 3U);
LBL_ERR:
mp_clear_multi(&bi_bit_count, &bi_k, NULL);
return err;
}
#endif

View File

@ -87,6 +87,7 @@ EXPORTS
mp_prime_rand
mp_prime_strong_lucas_selfridge
mp_radix_size
mp_radix_size_overestimate
mp_rand
mp_read_radix
mp_reduce

View File

@ -565,7 +565,9 @@ mp_err mp_to_sbin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written)
mp_err mp_read_radix(mp_int *a, const char *str, int radix) MP_WUR;
mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR;
mp_err mp_radix_size(const mp_int *a, int radix, size_t *size) MP_WUR;
mp_err mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size) MP_WUR;
#ifndef MP_NO_FILE
mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR;

View File

@ -93,6 +93,7 @@
# define MP_PRIME_RAND_C
# define MP_PRIME_STRONG_LUCAS_SELFRIDGE_C
# define MP_RADIX_SIZE_C
# define MP_RADIX_SIZE_OVERESTIMATE_C
# define MP_RAND_C
# define MP_READ_RADIX_C
# define MP_REDUCE_C
@ -154,6 +155,7 @@
# define S_MP_PRIME_IS_DIVISIBLE_C
# define S_MP_PRIME_TAB_C
# define S_MP_RADIX_MAP_C
# define S_MP_RADIX_SIZE_OVERESTIMATE_C
# define S_MP_RAND_JENKINS_C
# define S_MP_RAND_PLATFORM_C
# define S_MP_SQR_C
@ -339,7 +341,7 @@
#endif
#if defined(MP_FWRITE_C)
# define MP_RADIX_SIZE_C
# define MP_RADIX_SIZE_OVERESTIMATE_C
# define MP_TO_RADIX_C
# define S_MP_ZERO_BUF_C
#endif
@ -688,6 +690,11 @@
# define MP_LOG_N_C
#endif
#if defined(MP_RADIX_SIZE_OVERESTIMATE_C)
# define MP_RADIX_SIZE_C
# define S_MP_RADIX_SIZE_OVERESTIMATE_C
#endif
#if defined(MP_RAND_C)
# define MP_GROW_C
# define MP_RAND_SOURCE_C
@ -1172,6 +1179,17 @@
#if defined(S_MP_RADIX_MAP_C)
#endif
#if defined(S_MP_RADIX_SIZE_OVERESTIMATE_C)
# define MP_CLEAR_MULTI_C
# define MP_COUNT_BITS_C
# define MP_DIV_2D_C
# define MP_GET_I64_C
# define MP_INIT_MULTI_C
# define MP_MUL_C
# define MP_SET_U32_C
# define S_MP_LOG_2EXPT_C
#endif
#if defined(S_MP_RAND_JENKINS_C)
# define S_MP_RAND_JENKINS_INIT_C
#endif

View File

@ -192,6 +192,7 @@ MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE void s_mp_copy_digs(mp_digit *d, const mp_digit *s, int digits);
MP_PRIVATE void s_mp_zero_buf(void *mem, size_t size);
MP_PRIVATE void s_mp_zero_digs(mp_digit *d, int digits);
MP_PRIVATE mp_err s_mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size);
/* 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;

View File

@ -28,6 +28,7 @@
# define MP_NEG_C
# define MP_PRIME_FROBENIUS_UNDERWOOD_C
# define MP_RADIX_SIZE_C
# define MP_RADIX_SIZE_OVERESTIMATE_C
# define MP_LOG_N_C
# define MP_RAND_C
# define MP_REDUCE_C
@ -36,6 +37,8 @@
# define MP_ROOT_N_C
# define MP_SET_L_C
# define MP_SET_UL_C
# define MP_SET_U64_C
# define MP_SET_I64_C
# define MP_SBIN_SIZE_C
# define MP_TO_RADIX_C
# define MP_TO_SBIN_C