From 4b465c27625ab8297ce82a9076b76fb48be5451b Mon Sep 17 00:00:00 2001 From: Christoph Zurnieden Date: Mon, 29 May 2023 22:18:26 +0200 Subject: [PATCH] Print big integers with (f)printf --- demo/test.c | 122 ++++++++++++++++++++++++++++++++++++++ doc/bn.tex | 20 +++++++ helper.pl | 2 +- libtommath_VS2008.vcproj | 4 ++ makefile | 26 ++++----- makefile.mingw | 26 ++++----- makefile.msvc | 26 ++++----- makefile.shared | 26 ++++----- makefile.unix | 26 ++++----- mp_printf_extension.c | 123 +++++++++++++++++++++++++++++++++++++++ sources.cmake | 1 + tommath.def | 1 + tommath.h | 1 + tommath_class.h | 8 +++ 14 files changed, 346 insertions(+), 66 deletions(-) create mode 100644 mp_printf_extension.c diff --git a/demo/test.c b/demo/test.c index 939fcc0e..2afa6407 100644 --- a/demo/test.c +++ b/demo/test.c @@ -315,6 +315,122 @@ static int test_mp_fread_fwrite(void) return EXIT_FAILURE; } +#if (!(defined LTM_NOTHING) && !(defined MP_NO_FILE) && (defined __GLIBC__)) +#include +#define LTM_TEST_BUFSIZ 1024 +static int test_mp_printf_extension(void) +{ + FILE *test_file = NULL; + + char line_buffer[LTM_TEST_BUFSIZ] = {0}; + bool write_only = false; + size_t slen = 0; + int characters_printed = 0; + char *fgets_return; + int idx = 0; + + const char *test_values[2] = { + "4DDCFDE0D20EF8663B34D19F829FDD", + "-51D9769BDAE5B38121F2A31D881E5F" + }; + const char *test_strings[12] = { + "Right aligned AAA 404289102523688521157725445716877277 BBB\n", + "Left aligned AAA 404289102523688521157725445716877277 BBB\n", + "hex with right align AAA 0x4DDCFDE0D20EF8663B34D19F829FDD BBB\n", + "hex with left align AAA 0x4DDCFDE0D20EF8663B34D19F829FDD BBB\n", + "Right aligned AAA -424986725583297217766029037085924959 BBB\n", + "Left aligned AAA -424986725583297217766029037085924959 BBB\n", + "hex with right align AAA -0x51D9769BDAE5B38121F2A31D881E5F BBB\n", + "hex with left align AAA -0x51D9769BDAE5B38121F2A31D881E5F BBB\n", + "Right aligned AAA 0 BBB\n", + "Left aligned AAA 0 BBB\n", + "hex with right align AAA 0x0 BBB\n", + "hex with left align AAA 0x0 BBB\n" + }; + + const char *print_strings[12] = { + "Right aligned AAA %50N BBB\n", + "Left aligned AAA %-50N BBB\n", + "hex with right align AAA %#50N BBB\n", + "hex with left align AAA %#-50N BBB\n", + /* at idx == 4 mp_exch(&p,&q); */ + "Right aligned AAA %50N BBB\n", + "Left aligned AAA %-50N BBB\n", + "hex with right align AAA %#50N BBB\n", + "hex with left align AAA %#-50N BBB\n", + /* at idx == 8 mp_zero(&p); */ + "Right aligned AAA %50N BBB\n", + "Left aligned AAA %-50N BBB\n", + "hex with right align AAA %#50N BBB\n", + "hex with left align AAA %#-50N BBB\n", + }; + + + mp_int p, q; + + test_file = fopen("ltm_testing_mp_fprintf_88a43603fcfc2f7e7c6646cd4b89180a", "w+"); + if (test_file == NULL) { + /* use logfile instead to have at least sth. in case of an error */ + test_file = stdout; + write_only = true; + } + + DOR(mp_init_multi(&p, &q, NULL)); + + DO(mp_read_radix(&p, test_values[0], 16)); + DO(mp_read_radix(&q, test_values[1], 16)); + + DO(mp_printf_extension()); + + for (idx = 0; idx < 12; idx++) { + if (idx == 4) { + mp_exch(&p,&q); + } + if (idx == 8) { + mp_zero(&p); + } + characters_printed = fprintf(test_file, print_strings[idx], &p); + slen = strlen(test_strings[idx]); + if ((characters_printed - (int)slen) != 0) { + fprintf(stderr, "%d test_mp_print_extension: failed to print o:%zu t:%d\n", + idx, slen, characters_printed); + goto LBL_ERR; + } + if (!write_only) { + rewind(test_file); + fgets_return = fgets(line_buffer, LTM_TEST_BUFSIZ, test_file); + if (fgets_return == NULL) { + fprintf(stderr, "%d test_mp_fprintf: failed to read from file\n", idx); + goto LBL_ERR; + } + if (strcmp(line_buffer, test_strings[idx]) != 0) { + fprintf(stderr, "test_mp_fprintf: file content is not equal to test string #%d\n",idx); + goto LBL_ERR; + } + } + /* Clear file content */ + test_file = freopen("ltm_testing_mp_fprintf_88a43603fcfc2f7e7c6646cd4b89180a","w+", test_file); + if (test_file == NULL) { + /* use logfile instead to have at least sth. in case of an error */ + test_file = stdout; + write_only = true; + } + } + + mp_clear_multi(&p, &q, NULL); + fclose(test_file); + if (remove("ltm_testing_mp_fprintf_88a43603fcfc2f7e7c6646cd4b89180a") != 0) { + fprintf(stderr, "Could not delete file ltm_testing_mp_fprintf_88a43603fcfc2f7e7c6646cd4b89180a\n"); + } + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&p, &q, NULL); + fclose(test_file); + /* We don't delete the testfile in case of error, conrtent might be helpful. */ + return EXIT_FAILURE; +} +#endif + static mp_err very_random_source(void *out, size_t size) { memset(out, 0xff, size); @@ -1576,6 +1692,9 @@ static int test_mp_log(void) DO(mp_rand(&a, i)); for (j = 1; j < ((i/2)+1); j++) { DO(mp_rand(&base, j)); + if (mp_cmp_d(&base,2u) == MP_LT) { + continue; + } DO(mp_log(&a, &base, &lb)); DO(mp_expt_n(&base, lb, &bn)); /* "bn" must be smaller than or equal to "a" at this point. */ @@ -2453,6 +2572,9 @@ static int unit_tests(int argc, char **argv) T1(mp_dr_reduce, MP_DR_REDUCE), T2(mp_pack_unpack,MP_PACK, MP_UNPACK), T2(mp_fread_fwrite, MP_FREAD, MP_FWRITE), +#if (!(defined LTM_NOTHING) && !(defined MP_NO_FILE) && (defined __GLIBC__)) + T1(mp_printf_extension, MP_READ_RADIX), +#endif T1(mp_get_u32, MP_GET_I32), T1(mp_get_u64, MP_GET_I64), T1(mp_get_ul, MP_GET_L), diff --git a/doc/bn.tex b/doc/bn.tex index 711ad0e5..afb16bd9 100644 --- a/doc/bn.tex +++ b/doc/bn.tex @@ -2421,6 +2421,26 @@ \subsection{To ASCII} mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream); \end{alltt} +Also available in that case is a small extension to \texttt{printf(3)} to print +a big integer in a formated way. Not every formating is supported (e.g.: no +thousands separator) but normal alignment works well. Only representations available +are hexadecimal (slaways with prefix) and decimal. +\index{mp\_printf\_extension} +\begin{alltt} +mp_err p_printf_extension(void); +\end{alltt} +Example: +\begin{alltt} + +/* Switch on the extension */ +if((err = mp_printf_extension(void)) != MP_OKAY) goto LTM_ERR; + ... +/* Do some calculation */ + ... +/* print them out */ +printf("In hex: %#N and in decimal: %N\textbackslash{}n"); +\end{alltt} + \subsection{From ASCII} \index{mp\_read\_radix} \begin{alltt} diff --git a/helper.pl b/helper.pl index e5ad27ac..dcea224e 100755 --- a/helper.pl +++ b/helper.pl @@ -446,7 +446,7 @@ sub update_dep sub generate_def { my @files = glob '*mp_*.c'; - @files = map { my $x = $_; $x =~ s/\.c$//g; $x; } @files; + @files = map { my $x = $_; $x =~ s/\.c$//g;$x; } @files; @files = grep(!/mp_cutoffs/, @files); my $files = join("\n ", sort(grep(/^mp_/, @files))); diff --git a/libtommath_VS2008.vcproj b/libtommath_VS2008.vcproj index 13158a09..1db05ca9 100644 --- a/libtommath_VS2008.vcproj +++ b/libtommath_VS2008.vcproj @@ -644,6 +644,10 @@ RelativePath="mp_prime_strong_lucas_selfridge.c" > + + diff --git a/makefile b/makefile index b2cb16a3..b7a8a61e 100644 --- a/makefile +++ b/makefile @@ -37,19 +37,19 @@ mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.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_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_printf_extension.o \ +mp_radix_size.o mp_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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 diff --git a/makefile.mingw b/makefile.mingw index 532747be..dc138b98 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -39,19 +39,19 @@ mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.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_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_printf_extension.o \ +mp_radix_size.o mp_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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) diff --git a/makefile.msvc b/makefile.msvc index 5d128549..5a491c3a 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -35,19 +35,19 @@ mp_invmod.obj mp_is_square.obj mp_kronecker.obj mp_lcm.obj mp_log.obj mp_log_n.o mp_montgomery_calc_normalization.obj mp_montgomery_reduce.obj mp_montgomery_setup.obj mp_mul.obj mp_mul_2.obj \ 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_radix_size_overestimate.obj mp_rand.obj mp_rand_source.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_fp_log.obj s_mp_fp_log_d.obj \ -s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.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_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_prime_rabin_miller_trials.obj mp_prime_rand.obj mp_prime_strong_lucas_selfridge.obj mp_printf_extension.obj \ +mp_radix_size.obj mp_radix_size_overestimate.obj mp_rand.obj mp_rand_source.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_fp_log.obj \ +s_mp_fp_log_d.obj s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.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_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) diff --git a/makefile.shared b/makefile.shared index fe077fc8..aa01b222 100644 --- a/makefile.shared +++ b/makefile.shared @@ -34,19 +34,19 @@ mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.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_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_printf_extension.o \ +mp_radix_size.o mp_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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 diff --git a/makefile.unix b/makefile.unix index 9fe939f0..b586264b 100644 --- a/makefile.unix +++ b/makefile.unix @@ -40,19 +40,19 @@ mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.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_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o s_mp_fp_log_d.o \ -s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_printf_extension.o \ +mp_radix_size.o mp_radix_size_overestimate.o mp_rand.o mp_rand_source.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_fp_log.o \ +s_mp_fp_log_d.o s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.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_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 diff --git a/mp_printf_extension.c b/mp_printf_extension.c new file mode 100644 index 00000000..d4e69329 --- /dev/null +++ b/mp_printf_extension.c @@ -0,0 +1,123 @@ +#include "tommath_private.h" +#ifdef MP_PRINTF_EXTENSION_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef _MSC_VER +mp_err mp_printf_extension(void) +{ + return MP_VAL; +} + +#else + +/* TODO: find min version of glibc. Seems to be >2.9, check */ +#if (!(defined MP_NO_FILE) && (defined __GLIBC__)) +#include +static int s_mp_print_mp_int(FILE *stream, const struct printf_info *info, const void *const *args) +{ + mp_err err = MP_OKAY; + const mp_int *a; + char *buf, *start_buf; + int base = 10; + size_t size, written; + int len; + size_t extra_len = 0u; + int idx = 0; + + /* Fiddle our bigint out of the argument list */ + a = *((const mp_int * const *)(args[0])); + + /* The only way to change base without changing identifier */ + if (info->alt == 1u) { + base = 16; + } + + if (mp_iszero(a)) { + return fprintf(stream, "%*s", + (info->left ? -info->width : info->width), + (base == 16 ? "0x0" : "0")); + } + + + /* Get some estimate of the size of "a" in the given base */ + if ((err = mp_radix_size_overestimate(a, base, &size)) != MP_OKAY) { + return -1; + } + + /* The minus sign comes before the "0x", we have to take precaution */ + if (base == 16) { + extra_len += 2; + } + + if (mp_isneg(a) || (info->space) || (info->showsign)) { + extra_len++; + } + + buf = MP_MALLOC(size + extra_len); + if (buf == NULL) { + return -1; + } + + /* Keep a feet on the beginning of the rope. */ + start_buf = buf; + /* Make some space for the prefix and the sign */ + buf += extra_len; + + /* We overwrite the minus-sign */ + if (mp_isneg(a)) { + buf--; + } + + if ((err = mp_to_radix(a, buf, size, &written, base)) != MP_OKAY) { + MP_FREE(start_buf, size + extra_len); + return -1; + } + + if (mp_isneg(a)) { + start_buf[idx++] = '-'; + } else { + if (info->space) { + start_buf[idx++] = ' '; + } else if (info->showsign) { + start_buf[idx++] = '+'; + } + } + + if (base == 16) { + start_buf[idx++] = '0'; + start_buf[idx] = 'x'; + } + len = fprintf(stream, "%*s", (info->left ? -info->width : info->width), start_buf); + + MP_FREE(start_buf, size + extra_len); + return len; +} +static int s_mp_print_mp_int_arginfo(const struct printf_info *info, size_t n, + int *argtypes, int *size) +{ + (void)(info); + + if (n > 0) { + argtypes[0] = PA_POINTER; + size[0] = sizeof(mp_int *); + } + return 1; +} + +/* Fixed value: 'N' */ +mp_err mp_printf_extension(void) +{ + mp_err err = MP_OKAY; + + if (register_printf_specifier('N', s_mp_print_mp_int, s_mp_print_mp_int_arginfo) < 0) { + /* Out of spec, which cannot happen if spec is fixed as we do it here. */ + err = MP_VAL; + } + + return err; +} +#endif +#endif +#endif diff --git a/sources.cmake b/sources.cmake index bbb2aeab..e190e7fc 100644 --- a/sources.cmake +++ b/sources.cmake @@ -85,6 +85,7 @@ mp_prime_next_prime.c mp_prime_rabin_miller_trials.c mp_prime_rand.c mp_prime_strong_lucas_selfridge.c +mp_printf_extension.c mp_radix_size.c mp_radix_size_overestimate.c mp_rand.c diff --git a/tommath.def b/tommath.def index 86f34872..91efb3b4 100644 --- a/tommath.def +++ b/tommath.def @@ -88,6 +88,7 @@ EXPORTS mp_prime_rabin_miller_trials mp_prime_rand mp_prime_strong_lucas_selfridge + mp_printf_extension mp_radix_size mp_radix_size_overestimate mp_rand diff --git a/tommath.h b/tommath.h index 7994b6e1..e9cd9c19 100644 --- a/tommath.h +++ b/tommath.h @@ -585,6 +585,7 @@ mp_err mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size #ifndef MP_NO_FILE mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR; mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; +mp_err mp_printf_extension(void) MP_WUR; #endif #define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), NULL, 2) diff --git a/tommath_class.h b/tommath_class.h index e08bc5f3..96ee248c 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -94,6 +94,7 @@ # define MP_PRIME_RABIN_MILLER_TRIALS_C # define MP_PRIME_RAND_C # define MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define MP_PRINTF_EXTENSION_C # define MP_RADIX_SIZE_C # define MP_RADIX_SIZE_OVERESTIMATE_C # define MP_RAND_C @@ -714,6 +715,13 @@ # define S_MP_GET_BIT_C #endif +#if defined(MP_PRINTF_EXTENSION_C) +# define MP_RADIX_SIZE_OVERESTIMATE_C +# define MP_TO_RADIX_C +# define S_MP_PRINT_MP_INT_ARGINFO_C +# define S_MP_PRINT_MP_INT_C +#endif + #if defined(MP_RADIX_SIZE_C) # define MP_LOG_N_C #endif