Introduction of a fast but slightly over-estimating radix_size
This commit is contained in:
parent
220a4deb31
commit
1e65c0bfe4
@ -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);
|
||||
|
104
demo/test.c
104
demo/test.c
@ -2016,6 +2016,7 @@ LBL_ERR:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static int test_mp_radix_size(void)
|
||||
{
|
||||
mp_int a;
|
||||
@ -2201,6 +2202,108 @@ 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
|
||||
};
|
||||
#ifdef MP_RADIX_SIZE_OVERESTIMATE_TEST_BIG
|
||||
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
|
||||
};
|
||||
#endif
|
||||
|
||||
/* *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;
|
||||
}
|
||||
#ifdef MP_RADIX_SIZE_OVERESTIMATE_TEST_BIG
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
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 +2462,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
|
||||
|
16
doc/bn.tex
16
doc/bn.tex
@ -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.
|
||||
|
||||
|
@ -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"
|
||||
>
|
||||
|
23
makefile
23
makefile
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
17
mp_radix_size_overestimate.c
Normal file
17
mp_radix_size_overestimate.c
Normal 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
|
87
s_mp_radix_size_overestimate.c
Normal file
87
s_mp_radix_size_overestimate.c
Normal 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
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user