From 58a45a9d786d05c285f2731298d59991bfc93e2d Mon Sep 17 00:00:00 2001 From: dterazhao Date: Fri, 22 Nov 2024 11:25:54 +0800 Subject: [PATCH] fix: compile the libtommath with bazel to fix the error of undefined symbol on linux --- bazel/patches/libtommath.patch | 26 - bazel/patches/yacl.patch | 363 +++++ bazel/repositories.bzl | 18 - .../cn/cstn/algorithm/javacpp/heu/BUILD.bazel | 7 +- .../algorithm/javacpp/libtommath/BUILD.bazel | 24 + .../javacpp/libtommath/Package.swift | 40 + .../algorithm/javacpp/libtommath/README.md | 70 + .../algorithm/javacpp/libtommath/mp_2expt.c | 35 + .../algorithm/javacpp/libtommath/mp_abs.c | 24 + .../algorithm/javacpp/libtommath/mp_add.c | 29 + .../algorithm/javacpp/libtommath/mp_add_d.c | 86 ++ .../algorithm/javacpp/libtommath/mp_addmod.c | 15 + .../algorithm/javacpp/libtommath/mp_and.c | 54 + .../algorithm/javacpp/libtommath/mp_clamp.c | 27 + .../algorithm/javacpp/libtommath/mp_clear.c | 20 + .../javacpp/libtommath/mp_clear_multi.c | 18 + .../algorithm/javacpp/libtommath/mp_cmp.c | 21 + .../algorithm/javacpp/libtommath/mp_cmp_d.c | 26 + .../algorithm/javacpp/libtommath/mp_cmp_mag.c | 25 + .../algorithm/javacpp/libtommath/mp_cnt_lsb.c | 38 + .../javacpp/libtommath/mp_complement.c | 13 + .../algorithm/javacpp/libtommath/mp_copy.c | 29 + .../javacpp/libtommath/mp_count_bits.c | 28 + .../algorithm/javacpp/libtommath/mp_cutoffs.c | 14 + .../algorithm/javacpp/libtommath/mp_div.c | 42 + .../algorithm/javacpp/libtommath/mp_div_2.c | 40 + .../algorithm/javacpp/libtommath/mp_div_2d.c | 61 + .../algorithm/javacpp/libtommath/mp_div_d.c | 84 ++ .../javacpp/libtommath/mp_dr_is_modulus.c | 27 + .../javacpp/libtommath/mp_dr_reduce.c | 68 + .../javacpp/libtommath/mp_dr_setup.c | 15 + .../javacpp/libtommath/mp_error_to_string.c | 29 + .../algorithm/javacpp/libtommath/mp_exch.c | 13 + .../algorithm/javacpp/libtommath/mp_expt_n.c | 43 + .../algorithm/javacpp/libtommath/mp_exptmod.c | 78 + .../javacpp/libtommath/mp_exteuclid.c | 72 + .../algorithm/javacpp/libtommath/mp_fread.c | 66 + .../javacpp/libtommath/mp_from_sbin.c | 21 + .../javacpp/libtommath/mp_from_ubin.c | 30 + .../algorithm/javacpp/libtommath/mp_fwrite.c | 34 + .../algorithm/javacpp/libtommath/mp_gcd.c | 92 ++ .../javacpp/libtommath/mp_get_double.c | 18 + .../algorithm/javacpp/libtommath/mp_get_i32.c | 7 + .../algorithm/javacpp/libtommath/mp_get_i64.c | 7 + .../algorithm/javacpp/libtommath/mp_get_l.c | 7 + .../javacpp/libtommath/mp_get_mag_u32.c | 7 + .../javacpp/libtommath/mp_get_mag_u64.c | 7 + .../javacpp/libtommath/mp_get_mag_ul.c | 7 + .../algorithm/javacpp/libtommath/mp_grow.c | 44 + .../algorithm/javacpp/libtommath/mp_hash.c | 36 + .../algorithm/javacpp/libtommath/mp_init.c | 23 + .../javacpp/libtommath/mp_init_copy.c | 21 + .../javacpp/libtommath/mp_init_i32.c | 7 + .../javacpp/libtommath/mp_init_i64.c | 7 + .../algorithm/javacpp/libtommath/mp_init_l.c | 7 + .../javacpp/libtommath/mp_init_multi.c | 41 + .../javacpp/libtommath/mp_init_set.c | 16 + .../javacpp/libtommath/mp_init_size.c | 32 + .../javacpp/libtommath/mp_init_u32.c | 7 + .../javacpp/libtommath/mp_init_u64.c | 7 + .../algorithm/javacpp/libtommath/mp_init_ul.c | 7 + .../algorithm/javacpp/libtommath/mp_invmod.c | 29 + .../javacpp/libtommath/mp_is_square.c | 94 ++ .../javacpp/libtommath/mp_kronecker.c | 129 ++ .../algorithm/javacpp/libtommath/mp_lcm.c | 44 + .../algorithm/javacpp/libtommath/mp_log.c | 168 +++ .../algorithm/javacpp/libtommath/mp_log_n.c | 19 + .../algorithm/javacpp/libtommath/mp_lshd.c | 42 + .../algorithm/javacpp/libtommath/mp_mod.c | 15 + .../algorithm/javacpp/libtommath/mp_mod_2d.c | 40 + .../mp_montgomery_calc_normalization.c | 43 + .../javacpp/libtommath/mp_montgomery_reduce.c | 89 ++ .../javacpp/libtommath/mp_montgomery_setup.c | 40 + .../algorithm/javacpp/libtommath/mp_mul.c | 68 + .../algorithm/javacpp/libtommath/mp_mul_2.c | 53 + .../algorithm/javacpp/libtommath/mp_mul_2d.c | 63 + .../algorithm/javacpp/libtommath/mp_mul_d.c | 68 + .../algorithm/javacpp/libtommath/mp_mulmod.c | 15 + .../algorithm/javacpp/libtommath/mp_neg.c | 18 + .../cstn/algorithm/javacpp/libtommath/mp_or.c | 54 + .../algorithm/javacpp/libtommath/mp_pack.c | 69 + .../javacpp/libtommath/mp_pack_count.c | 12 + .../javacpp/libtommath/mp_prime_fermat.c | 41 + .../libtommath/mp_prime_frobenius_underwood.c | 127 ++ .../javacpp/libtommath/mp_prime_is_prime.c | 282 ++++ .../libtommath/mp_prime_miller_rabin.c | 91 ++ .../javacpp/libtommath/mp_prime_next_prime.c | 127 ++ .../libtommath/mp_prime_rabin_miller_trials.c | 48 + .../javacpp/libtommath/mp_prime_rand.c | 123 ++ .../mp_prime_strong_lucas_selfridge.c | 281 ++++ .../javacpp/libtommath/mp_radix_size.c | 34 + .../libtommath/mp_radix_size_overestimate.c | 17 + .../algorithm/javacpp/libtommath/mp_rand.c | 39 + .../javacpp/libtommath/mp_rand_source.c | 12 + .../javacpp/libtommath/mp_read_radix.c | 69 + .../algorithm/javacpp/libtommath/mp_reduce.c | 83 ++ .../javacpp/libtommath/mp_reduce_2k.c | 49 + .../javacpp/libtommath/mp_reduce_2k_l.c | 52 + .../javacpp/libtommath/mp_reduce_2k_setup.c | 30 + .../javacpp/libtommath/mp_reduce_2k_setup_l.c | 28 + .../javacpp/libtommath/mp_reduce_is_2k.c | 41 + .../javacpp/libtommath/mp_reduce_is_2k_l.c | 27 + .../javacpp/libtommath/mp_reduce_setup.c | 17 + .../algorithm/javacpp/libtommath/mp_root_n.c | 141 ++ .../algorithm/javacpp/libtommath/mp_rshd.c | 43 + .../javacpp/libtommath/mp_sbin_size.c | 11 + .../algorithm/javacpp/libtommath/mp_set.c | 15 + .../javacpp/libtommath/mp_set_double.c | 47 + .../algorithm/javacpp/libtommath/mp_set_i32.c | 7 + .../algorithm/javacpp/libtommath/mp_set_i64.c | 7 + .../algorithm/javacpp/libtommath/mp_set_l.c | 7 + .../algorithm/javacpp/libtommath/mp_set_u32.c | 7 + .../algorithm/javacpp/libtommath/mp_set_u64.c | 7 + .../algorithm/javacpp/libtommath/mp_set_ul.c | 7 + .../algorithm/javacpp/libtommath/mp_shrink.c | 22 + .../javacpp/libtommath/mp_signed_rsh.c | 21 + .../algorithm/javacpp/libtommath/mp_sqrmod.c | 15 + .../algorithm/javacpp/libtommath/mp_sqrt.c | 67 + .../javacpp/libtommath/mp_sqrtmod_prime.c | 133 ++ .../algorithm/javacpp/libtommath/mp_sub.c | 36 + .../algorithm/javacpp/libtommath/mp_sub_d.c | 78 + .../algorithm/javacpp/libtommath/mp_submod.c | 15 + .../javacpp/libtommath/mp_to_radix.c | 95 ++ .../algorithm/javacpp/libtommath/mp_to_sbin.c | 22 + .../algorithm/javacpp/libtommath/mp_to_ubin.c | 37 + .../javacpp/libtommath/mp_ubin_size.c | 12 + .../algorithm/javacpp/libtommath/mp_unpack.c | 49 + .../javacpp/libtommath/mp_warray_free.c | 28 + .../algorithm/javacpp/libtommath/mp_xor.c | 54 + .../algorithm/javacpp/libtommath/mp_zero.c | 13 + .../algorithm/javacpp/libtommath/s_mp_add.c | 70 + .../javacpp/libtommath/s_mp_copy_digs.c | 23 + .../algorithm/javacpp/libtommath/s_mp_div_3.c | 64 + .../javacpp/libtommath/s_mp_div_recursive.c | 159 ++ .../javacpp/libtommath/s_mp_div_school.c | 159 ++ .../javacpp/libtommath/s_mp_div_small.c | 51 + .../javacpp/libtommath/s_mp_exptmod.c | 198 +++ .../javacpp/libtommath/s_mp_exptmod_fast.c | 254 ++++ .../javacpp/libtommath/s_mp_fp_log.c | 83 ++ .../javacpp/libtommath/s_mp_fp_log_d.c | 83 ++ .../javacpp/libtommath/s_mp_get_bit.c | 21 + .../javacpp/libtommath/s_mp_invmod.c | 117 ++ .../javacpp/libtommath/s_mp_invmod_odd.c | 113 ++ .../javacpp/libtommath/s_mp_log_2expt.c | 12 + .../libtommath/s_mp_montgomery_reduce_comba.c | 124 ++ .../algorithm/javacpp/libtommath/s_mp_mul.c | 65 + .../javacpp/libtommath/s_mp_mul_balance.c | 71 + .../javacpp/libtommath/s_mp_mul_comba.c | 87 ++ .../javacpp/libtommath/s_mp_mul_high.c | 56 + .../javacpp/libtommath/s_mp_mul_high_comba.c | 79 + .../javacpp/libtommath/s_mp_mul_karatsuba.c | 151 ++ .../javacpp/libtommath/s_mp_mul_toom.c | 202 +++ .../libtommath/s_mp_prime_is_divisible.c | 33 + .../javacpp/libtommath/s_mp_prime_tab.c | 44 + .../javacpp/libtommath/s_mp_radix_map.c | 19 + .../libtommath/s_mp_radix_size_overestimate.c | 82 + .../javacpp/libtommath/s_mp_rand_platform.c | 149 ++ .../algorithm/javacpp/libtommath/s_mp_sqr.c | 78 + .../javacpp/libtommath/s_mp_sqr_comba.c | 91 ++ .../javacpp/libtommath/s_mp_sqr_karatsuba.c | 92 ++ .../javacpp/libtommath/s_mp_sqr_toom.c | 133 ++ .../algorithm/javacpp/libtommath/s_mp_sub.c | 56 + .../javacpp/libtommath/s_mp_warray.c | 8 + .../javacpp/libtommath/s_mp_warray_get.c | 18 + .../javacpp/libtommath/s_mp_warray_put.c | 14 + .../javacpp/libtommath/s_mp_zero_buf.c | 22 + .../javacpp/libtommath/s_mp_zero_digs.c | 23 + .../algorithm/javacpp/libtommath/tommath.h | 602 ++++++++ .../javacpp/libtommath/tommath_c89.h | 46 + .../javacpp/libtommath/tommath_class.h | 1323 +++++++++++++++++ .../javacpp/libtommath/tommath_cutoffs.h | 13 + .../javacpp/libtommath/tommath_private.h | 346 +++++ .../javacpp/libtommath/tommath_superclass.h | 115 ++ 173 files changed, 11468 insertions(+), 47 deletions(-) delete mode 100644 bazel/patches/libtommath.patch create mode 100644 bazel/patches/yacl.patch create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/BUILD.bazel create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/Package.swift create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/README.md create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_2expt.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_abs.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add_d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_addmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_and.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clamp.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear_multi.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_mag.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cnt_lsb.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_complement.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_copy.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_count_bits.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cutoffs.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_is_modulus.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_reduce.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_setup.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_error_to_string.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exch.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_expt_n.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exptmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exteuclid.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fread.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_sbin.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_ubin.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fwrite.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_gcd.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_double.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i32.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i64.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_l.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u32.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u64.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_ul.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_grow.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_hash.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_copy.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i32.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i64.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_l.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_multi.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_set.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_size.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u32.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u64.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_ul.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_invmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_is_square.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_kronecker.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lcm.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log_n.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lshd.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod_2d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_calc_normalization.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_reduce.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_setup.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mulmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_neg.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_or.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack_count.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_fermat.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_frobenius_underwood.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_is_prime.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_miller_rabin.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_next_prime.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rabin_miller_trials.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rand.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_strong_lucas_selfridge.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size_overestimate.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand_source.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_read_radix.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_l.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup_l.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k_l.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_setup.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_root_n.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rshd.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sbin_size.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_double.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i32.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i64.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_l.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u32.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u64.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_ul.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_shrink.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_signed_rsh.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrt.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrtmod_prime.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub_d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_submod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_radix.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_sbin.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_ubin.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_ubin_size.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_unpack.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_warray_free.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_xor.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_zero.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_add.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_copy_digs.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_3.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_recursive.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_school.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_small.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod_fast.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log_d.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_get_bit.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod_odd.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_log_2expt.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_montgomery_reduce_comba.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_balance.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_comba.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high_comba.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_karatsuba.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_toom.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_is_divisible.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_tab.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_map.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_size_overestimate.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_rand_platform.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_comba.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_karatsuba.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_toom.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sub.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_get.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_put.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_buf.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_digs.c create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath.h create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_c89.h create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_class.h create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_cutoffs.h create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_private.h create mode 100644 native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_superclass.h diff --git a/bazel/patches/libtommath.patch b/bazel/patches/libtommath.patch deleted file mode 100644 index 8c8c88a..0000000 --- a/bazel/patches/libtommath.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index dfbcb0f..72f9a46 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -113,7 +113,7 @@ set_target_properties(${PROJECT_NAME} PROPERTIES - OUTPUT_NAME tommath - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} -- PUBLIC_HEADER "${PUBLIC_HEADERS}" -+ PUBLIC_HEADER "${HEADERS}" - ) - - option(COMPILE_LTO "Build with LTO enabled") -diff --git a/tommath_private.h b/tommath_private.h -index d319a1d..5f4446e 100644 ---- a/tommath_private.h -+++ b/tommath_private.h -@@ -17,7 +17,7 @@ - * On Win32 a .def file must be used to specify the exported symbols. - */ - #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32) && !defined(__CYGWIN__) --# define MP_PRIVATE __attribute__ ((visibility ("hidden"))) -+# define MP_PRIVATE - #else - # define MP_PRIVATE - #endif diff --git a/bazel/patches/yacl.patch b/bazel/patches/yacl.patch new file mode 100644 index 0000000..1e638b6 --- /dev/null +++ b/bazel/patches/yacl.patch @@ -0,0 +1,363 @@ +diff --git a/yacl/math/mpint/tommath_ext_features.cc b/yacl/math/mpint/tommath_ext_features.cc +index cd9c019..073a829 100644 +--- a/yacl/math/mpint/tommath_ext_features.cc ++++ b/yacl/math/mpint/tommath_ext_features.cc +@@ -28,6 +28,340 @@ extern "C" { + #include "yacl/math/mpint/mp_int_enforce.h" + #include "yacl/utils/scope_guard.h" + ++//=================================libtomath================================= ++void mp_clear(mp_int *a) ++{ ++ /* only do anything if a hasn't been freed previously */ ++ if (a->dp != NULL) { ++ /* free ram */ ++ MP_FREE_DIGS(a->dp, a->alloc); ++ ++ /* reset members to make debugging easier */ ++ a->dp = NULL; ++ a->alloc = a->used = 0; ++ a->sign = MP_ZPOS; ++ } ++} ++mp_err mp_init_size(mp_int *a, int size) ++{ ++ if (size < 0) { ++ return MP_VAL; ++ } ++ ++ size = MP_MAX(MP_MIN_DIGIT_COUNT, size); ++ ++ if (size > MP_MAX_DIGIT_COUNT) { ++ return MP_OVF; ++ } ++ ++ /* alloc mem */ ++ a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit)); ++ if (a->dp == NULL) { ++ return MP_MEM; ++ } ++ ++ /* set the members */ ++ a->used = 0; ++ a->alloc = size; ++ a->sign = MP_ZPOS; ++ ++ return MP_OKAY; ++} ++void s_mp_zero_digs(mp_digit *d, int digits) ++{ ++#ifdef MP_USE_MEMOPS ++ if (digits > 0) { ++ memset(d, 0, (size_t)digits * sizeof(mp_digit)); ++ } ++#else ++ while (digits-- > 0) { ++ *d++ = 0; ++ } ++#endif ++} ++mp_err mp_grow(mp_int *a, int size) ++{ ++ if (size < 0) { ++ return MP_VAL; ++ } ++ ++ /* if the alloc size is smaller alloc more ram */ ++ if (a->alloc < size) { ++ mp_digit *dp; ++ ++ if (size > MP_MAX_DIGIT_COUNT) { ++ return MP_OVF; ++ } ++ ++ /* reallocate the array a->dp ++ * ++ * We store the return in a temporary variable ++ * in case the operation failed we don't want ++ * to overwrite the dp member of a. ++ */ ++ dp = (mp_digit *) MP_REALLOC(a->dp, ++ (size_t)a->alloc * sizeof(mp_digit), ++ (size_t)size * sizeof(mp_digit)); ++ if (dp == NULL) { ++ /* reallocation failed but "a" is still valid [can be freed] */ ++ return MP_MEM; ++ } ++ ++ /* reallocation succeeded so set a->dp */ ++ a->dp = dp; ++ ++ /* zero excess digits */ ++ s_mp_zero_digs(a->dp + a->alloc, size - a->alloc); ++ a->alloc = size; ++ } ++ return MP_OKAY; ++} ++#ifdef MP_USE_MEMOPS ++# include ++#endif ++void s_mp_copy_digs(mp_digit *d, const mp_digit *s, int digits) ++{ ++#ifdef MP_USE_MEMOPS ++ if (digits > 0) { ++ memcpy(d, s, (size_t)digits * sizeof(mp_digit)); ++ } ++#else ++ while (digits-- > 0) { ++ *d++ = *s++; ++ } ++#endif ++} ++mp_err mp_copy(const mp_int *a, mp_int *b) ++{ ++ mp_err err; ++ ++ /* if dst == src do nothing */ ++ if (a == b) { ++ return MP_OKAY; ++ } ++ ++ /* grow dest */ ++ if ((err = mp_grow(b, a->used)) != MP_OKAY) { ++ return err; ++ } ++ ++ /* copy everything over and zero high digits */ ++ s_mp_copy_digs(b->dp, a->dp, a->used); ++ s_mp_zero_digs(b->dp + a->used, b->used - a->used); ++ b->used = a->used; ++ b->sign = a->sign; ++ ++ return MP_OKAY; ++} ++mp_err mp_init_copy(mp_int *a, const mp_int *b) ++{ ++ mp_err err; ++ ++ if ((err = mp_init_size(a, b->used)) != MP_OKAY) { ++ return err; ++ } ++ ++ if ((err = mp_copy(b, a)) != MP_OKAY) { ++ mp_clear(a); ++ } ++ ++ return err; ++} ++static const struct { ++ int k, t; ++} sizes[] = { ++ { 80, -1 }, /* Use deterministic algorithm for size <= 80 bits */ ++ { 81, 37 }, /* max. error = 2^(-96)*/ ++ { 96, 32 }, /* max. error = 2^(-96)*/ ++ { 128, 40 }, /* max. error = 2^(-112)*/ ++ { 160, 35 }, /* max. error = 2^(-112)*/ ++ { 256, 27 }, /* max. error = 2^(-128)*/ ++ { 384, 16 }, /* max. error = 2^(-128)*/ ++ { 512, 18 }, /* max. error = 2^(-160)*/ ++ { 768, 11 }, /* max. error = 2^(-160)*/ ++ { 896, 10 }, /* max. error = 2^(-160)*/ ++ { 1024, 12 }, /* max. error = 2^(-192)*/ ++ { 1536, 8 }, /* max. error = 2^(-192)*/ ++ { 2048, 6 }, /* max. error = 2^(-192)*/ ++ { 3072, 4 }, /* max. error = 2^(-192)*/ ++ { 4096, 5 }, /* max. error = 2^(-256)*/ ++ { 5120, 4 }, /* max. error = 2^(-256)*/ ++ { 6144, 4 }, /* max. error = 2^(-256)*/ ++ { 8192, 3 }, /* max. error = 2^(-256)*/ ++ { 9216, 3 }, /* max. error = 2^(-256)*/ ++ { 10240, 2 } /* For bigger keysizes use always at least 2 Rounds */ ++}; ++/* returns # of RM trials required for a given bit size */ ++int mp_prime_rabin_miller_trials(int size) ++{ ++ int x; ++ ++ for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { ++ if (sizes[x].k == size) { ++ return sizes[x].t; ++ } ++ if (sizes[x].k > size) { ++ return (x == 0) ? sizes[0].t : sizes[x - 1].t; ++ } ++ } ++ return sizes[x-1].t; ++} ++ ++#ifndef MP_DEV_URANDOM ++#define MP_DEV_URANDOM "/dev/urandom" ++#endif ++#include ++#include ++#include ++static mp_err s_read_urandom(void *p, size_t n) ++{ ++ int fd; ++ char *q = (char *)p; ++ ++ do { ++ fd = open(MP_DEV_URANDOM, O_RDONLY); ++ } while ((fd == -1) && (errno == EINTR)); ++ if (fd == -1) return MP_ERR; ++ ++ while (n > 0u) { ++ ssize_t ret = read(fd, q, n); ++ if (ret < 0) { ++ if (errno == EINTR) { ++ continue; ++ } ++ close(fd); ++ return MP_ERR; ++ } ++ q += ret; ++ n -= (size_t)ret; ++ } ++ ++ close(fd); ++ return MP_OKAY; ++} ++mp_err s_mp_rand_platform(void *p, size_t n) ++{ ++ mp_err err = MP_ERR; ++ //if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n); ++ //if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n); ++ //if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n); ++ if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n); ++ return err; ++} ++mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) ++{ ++ uint8_t *tmp, maskAND, maskOR_msb, maskOR_lsb; ++ int bsize, maskOR_msb_offset; ++ bool res; ++ mp_err err; ++ ++ /* sanity check the input */ ++ if (size <= 1) { ++ return MP_VAL; ++ } ++ ++ /* MP_PRIME_SAFE implies MP_PRIME_BBS */ ++ if ((flags & MP_PRIME_SAFE) != 0) { ++ flags |= MP_PRIME_BBS; ++ } ++ ++ /* calc the byte size */ ++ bsize = (size>>3) + ((size&7)?1:0); ++ ++ /* we need a buffer of bsize bytes */ ++ tmp = (uint8_t *) MP_MALLOC((size_t)bsize); ++ if (tmp == NULL) { ++ return MP_MEM; ++ } ++ ++ /* calc the maskAND value for the MSbyte*/ ++ maskAND = ((size&7) == 0) ? 0xFFu : (uint8_t)(0xFFu >> (8 - (size & 7))); ++ ++ /* calc the maskOR_msb */ ++ maskOR_msb = 0; ++ maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; ++ if ((flags & MP_PRIME_2MSB_ON) != 0) { ++ maskOR_msb |= (uint8_t)(0x80 >> ((9 - size) & 7)); ++ } ++ ++ /* get the maskOR_lsb */ ++ maskOR_lsb = 1u; ++ if ((flags & MP_PRIME_BBS) != 0) { ++ maskOR_lsb |= 3u; ++ } ++ ++ do { ++ /* read the bytes */ ++ if ((err = s_mp_rand_platform(tmp, (size_t)bsize)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ ++ /* work over the MSbyte */ ++ tmp[0] &= maskAND; ++ tmp[0] |= (uint8_t)(1 << ((size - 1) & 7)); ++ ++ /* mix in the maskORs */ ++ tmp[maskOR_msb_offset] |= maskOR_msb; ++ tmp[bsize-1] |= maskOR_lsb; ++ ++ /* read it in */ ++ /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/ ++ if ((err = mp_from_ubin(a, tmp, (size_t)bsize)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ ++ /* is it prime? */ ++ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ if (!res) { ++ continue; ++ } ++ ++ if ((flags & MP_PRIME_SAFE) != 0) { ++ /* see if (a-1)/2 is prime */ ++ if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ if ((err = mp_div_2(a, a)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ ++ /* is it prime? */ ++ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ } ++ } while (!res); ++ ++ if ((flags & MP_PRIME_SAFE) != 0) { ++ /* restore a to the original value */ ++ if ((err = mp_mul_2(a, a)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) { ++ goto LBL_ERR; ++ } ++ } ++ ++ err = MP_OKAY; ++LBL_ERR: ++ MP_FREE_BUF(tmp, (size_t)bsize); ++ return err; ++} ++void s_mp_zero_buf(void *mem, size_t size) ++{ ++#ifdef MP_USE_MEMOPS ++ memset(mem, 0, size); ++#else ++ char *m = (char *)mem; ++ while (size-- > 0u) { ++ *m++ = '\0'; ++ } ++#endif ++} ++//=================================libtomath================================= ++ + namespace yacl::math { + + namespace { +@@ -165,7 +499,7 @@ void mpx_safe_prime_rand(mp_int *p, int t, int psize) { + + do { + /* read the bytes */ +- MPINT_ENFORCE_OK(s_mp_rand_source(tmp, (size_t)bsize)); ++ MPINT_ENFORCE_OK(s_mp_rand_platform(tmp, (size_t)bsize)); + + // clear bits in the first byte + tmp[0] &= maskAND; +@@ -234,7 +568,7 @@ void mpx_rand_bits(mp_int *out, int64_t bits) { + MPINT_ENFORCE_OK(mp_grow(out, digits)); + + MPINT_ENFORCE_OK( +- s_mp_rand_source(out->dp, (size_t)digits * sizeof(mp_digit))); ++ s_mp_rand_platform(out->dp, (size_t)digits * sizeof(mp_digit))); + + out->sign = MP_ZPOS; + out->used = digits; diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 3556474..4847cf5 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -18,7 +18,6 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") def algo_deps(): _rules_cc() - _com_github_libtom_libtommath() _build_bazel_apple_support() _heu() _spu() @@ -33,23 +32,6 @@ def _rules_cc(): url = "https://github.com/bazelbuild/rules_cc/releases/download/0.0.14/rules_cc-0.0.14.tar.gz", ) -def _com_github_libtom_libtommath(): - maybe( - http_archive, - name = "com_github_libtom_libtommath", - sha256 = "6c7a6732daeefda3826e6c5321d60d820655fb9f3f1a1f59049b0e7cab3c9079", - type = "tar.gz", - strip_prefix = "libtommath-2e03dfd64dd7ae6bf0d43b665036da82e87f3fb2", - patch_args = ["-p1"], - patches = [ - "//bazel:patches/libtommath.patch", - ], - urls = [ - "https://github.com/libtom/libtommath/archive/2e03dfd64dd7ae6bf0d43b665036da82e87f3fb2.tar.gz", - ], - build_file = "@yacl//bazel:libtommath.BUILD", - ) - def _build_bazel_apple_support(): maybe( http_archive, diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/heu/BUILD.bazel b/native/src/main/native/cn/cstn/algorithm/javacpp/heu/BUILD.bazel index 3abaf98..95c73ef 100644 --- a/native/src/main/native/cn/cstn/algorithm/javacpp/heu/BUILD.bazel +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/heu/BUILD.bazel @@ -27,9 +27,10 @@ algo_cc_library( cc_static_library( name = "phe_kit_all", - deps = [ - ":phe_kit", - ], + deps = select({ + "@platforms//os:macos": [":phe_kit"], + "//conditions:default": [":phe_kit", "//native/src/main/native/cn/cstn/algorithm/javacpp/libtommath:tommath"], + }), ) test_suite( diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/BUILD.bazel b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/BUILD.bazel new file mode 100644 index 0000000..ff0440e --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/BUILD.bazel @@ -0,0 +1,24 @@ +# Copyright 2024 dterazhao, Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:algo.bzl", "algo_cc_library") + +package(default_visibility = ["//visibility:public"]) + +algo_cc_library( + name = "tommath", + srcs = glob(["*.c"]), + hdrs = glob(["*.h"]), +) + diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/Package.swift b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/Package.swift new file mode 100644 index 0000000..54a195b --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/Package.swift @@ -0,0 +1,40 @@ +// swift-tools-version:5.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "tommath", + platforms: [ + .macOS(.v10_10), .iOS(.v9), .tvOS(.v9) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "libtommath", + targets: ["libtommath"]) + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "libtommath", + path: ".", + exclude: ["demo", "doc", "etc", "logs", "mtest"], + sources: ["."], + publicHeadersPath: "modulemap", + cSettings: [ + .unsafeFlags(["-flto=thin"]) // for Dead Code Elimination + ]), + .testTarget(name: "TommathTests", + dependencies: ["libtommath"], + path: "demo", + sources: ["tommath_tests.swift"]) + ], + cLanguageStandard: .gnu11, + cxxLanguageStandard: .gnucxx14 +) diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/README.md b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/README.md new file mode 100644 index 0000000..8ebdab7 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/README.md @@ -0,0 +1,70 @@ +# libtommath + +This is the git repository for [LibTomMath](http://www.libtom.net/LibTomMath/), a free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C. + +## Build Status + +### Travis CI + +master: [![Build Status](https://github.com/libtom/libtommath/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/libtom/libtommath/actions/workflows/main.yml?query=branch%3Amaster+++) + +develop: [![Build Status](https://github.com/libtom/libtommath/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/libtom/libtommath/actions/workflows/main.yml?query=branch%3Adevelop+++) + +### AppVeyor + +master: [![Build status](https://ci.appveyor.com/api/projects/status/b80lpolw3i8m6hsh/branch/master?svg=true)](https://ci.appveyor.com/project/libtom/libtommath/branch/master) + +develop: [![Build status](https://ci.appveyor.com/api/projects/status/b80lpolw3i8m6hsh/branch/develop?svg=true)](https://ci.appveyor.com/project/libtom/libtommath/branch/develop) + +### ABI Laboratory + +API/ABI changes: [check here](https://abi-laboratory.pro/tracker/timeline/libtommath/) + +### Pre-built packages + +We sometimes upload `deb` packages of the latest state from the develop branch to [packagecloud.io](https://packagecloud.io/libtom/packages). + +Use those packages with caution and at your own discretion. + +## Summary + +The `develop` branch contains the in-development version. Stable releases are tagged. + +Documentation is built from the LaTeX file `doc/bn.tex` and available as PDF for each release. +This PDF is also created as build artifact on each CI run. + +There is also limited documentation in `tommath.h`. + +Originally the library contained a document, `tommath.pdf`, which describes the goals of the project and many of the algorithms used at the time. +This document has been removed since it can't be built anymore and nobody spent the time to fix and update it. +The latest valid update to that document was done in version [`0.39`](https://github.com/libtom/libtommath/releases/tag/0.39) of the library and it is contained within that tarball. + +The project can be build by using `make`. Along with the usual `make`, `make clean` and `make install`, +there are several other build targets, see the makefile for details. +There are also makefiles for certain specific platforms. + +## Testing + +Tests are located in `demo/` and can be built in two flavors. +* `make test` creates a stand-alone test binary that executes several test routines. +* `make mtest_opponent` creates a test binary that is intended to be run against `mtest`. + `mtest` can be built with `make mtest` and test execution is done like `./mtest/mtest | ./mtest_opponent`. + `mtest` is creating test vectors using an alternative MPI library and `test` is consuming these vectors to verify correct behavior of ltm + +## Building and Installing + +Building is straightforward for GNU Linux only, the section "Building LibTomMath" in the documentation in `doc/bn.pdf` has the details. + +### CMake support + +The project provides support for the CMake build system. + +``` +git clone https://github.com/libtom/libtommath.git +mkdir -p libtommath/build +cd libtommath/build +cmake .. +make -j$(nproc) +``` + +A shared library build can be done by setting `-DBUILD_SHARED_LIBS=On` when invoking the `cmake` command. diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_2expt.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_2expt.c new file mode 100644 index 0000000..c11fe4c --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_2expt.c @@ -0,0 +1,35 @@ +#include "tommath_private.h" +#ifdef MP_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +mp_err mp_2expt(mp_int *a, int b) +{ + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + /* zero a as per default */ + mp_zero(a); + + /* grow a to accommodate the single bit */ + if ((err = mp_grow(a, (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + + /* set the used count of where the bit will go */ + a->used = (b / MP_DIGIT_BIT) + 1; + + /* put the single bit in its place */ + a->dp[b / MP_DIGIT_BIT] = (mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT); + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_abs.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_abs.c new file mode 100644 index 0000000..a87cc0c --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_abs.c @@ -0,0 +1,24 @@ +#include "tommath_private.h" +#ifdef MP_ABS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +mp_err mp_abs(const mp_int *a, mp_int *b) +{ + mp_err err; + + /* copy a to b */ + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add.c new file mode 100644 index 0000000..bf7a61e --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level addition (handles signs) */ +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) +{ + /* handle two cases, not four */ + if (a->sign == b->sign) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = a->sign; + return s_mp_add(a, b, c); + } + + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag(a, b) == MP_LT) { + MP_EXCH(const mp_int *, a, b); + } + + c->sign = a->sign; + return s_mp_sub(a, b, c); +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add_d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add_d.c new file mode 100644 index 0000000..c57a80d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_add_d.c @@ -0,0 +1,86 @@ +#include "tommath_private.h" +#ifdef MP_ADD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit addition */ +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_err err; + int oldused; + + /* fast path for a == c */ + if (a == c) { + if (!mp_isneg(c) && + !mp_iszero(c) && + ((c->dp[0] + b) < MP_DIGIT_MAX)) { + c->dp[0] += b; + return MP_OKAY; + } + if (mp_isneg(c) && + (c->dp[0] > b)) { + c->dp[0] -= b; + return MP_OKAY; + } + } + + /* grow c as required */ + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (mp_isneg(a) && ((a->used > 1) || (a->dp[0] >= b))) { + mp_int a_ = *a; + /* temporarily fix sign of a */ + a_.sign = MP_ZPOS; + + /* c = |a| - b */ + err = mp_sub_d(&a_, b, c); + + /* fix sign */ + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* if a is positive */ + if (!mp_isneg(a)) { + /* add digits, mu is carry */ + int i; + mp_digit mu = b; + for (i = 0; i < a->used; i++) { + c->dp[i] = a->dp[i] + mu; + mu = c->dp[i] >> MP_DIGIT_BIT; + c->dp[i] &= MP_MASK; + } + /* set final carry */ + c->dp[i] = mu; + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + c->dp[0] = (a->used == 1) ? b - a->dp[0] : b; + } + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* now zero to oldused */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + mp_clamp(c); + + return MP_OKAY; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_addmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_addmod.c new file mode 100644 index 0000000..91e2087 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_addmod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_ADDMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a + b (mod c) */ +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + if ((err = mp_add(a, b, d)) != MP_OKAY) { + return err; + } + return mp_mod(d, c, d); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_and.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_and.c new file mode 100644 index 0000000..b5230c4 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_and.c @@ -0,0 +1,54 @@ +#include "tommath_private.h" +#ifdef MP_AND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement and */ +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + bool neg = (mp_isneg(a) && mp_isneg(b)); + + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (mp_isneg(a)) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (mp_isneg(b)) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x & y; + + /* convert to to sign-magnitude if negative */ + if (neg) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = (neg ? MP_NEG : MP_ZPOS); + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clamp.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clamp.c new file mode 100644 index 0000000..463f22d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clamp.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef MP_CLAMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimmed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void mp_clamp(mp_int *a) +{ + /* decrease used while the most significant digit is + * zero. + */ + while ((a->used > 0) && (a->dp[a->used - 1] == 0u)) { + --(a->used); + } + + /* reset the sign flag if zero */ + if (mp_iszero(a)) { + a->sign = MP_ZPOS; + } +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear.c new file mode 100644 index 0000000..11094b2 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear.c @@ -0,0 +1,20 @@ +#include "tommath_private.h" +#ifdef MP_CLEAR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* clear one (frees) */ +void mp_clear(mp_int *a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + MP_FREE_DIGS(a->dp, a->alloc); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear_multi.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear_multi.c new file mode 100644 index 0000000..9c7aed8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_clear_multi.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef MP_CLEAR_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +void mp_clear_multi(mp_int *mp, ...) +{ + va_list args; + va_start(args, mp); + while (mp != NULL) { + mp_clear(mp); + mp = va_arg(args, mp_int *); + } + va_end(args); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp.c new file mode 100644 index 0000000..9f3847b --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_CMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare two ints (signed)*/ +mp_ord mp_cmp(const mp_int *a, const mp_int *b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + return mp_isneg(a) ? MP_LT : MP_GT; + } + + /* if negative compare opposite direction */ + if (mp_isneg(a)) { + MP_EXCH(const mp_int *, a, b); + } + + return mp_cmp_mag(a, b); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_d.c new file mode 100644 index 0000000..42f7b16 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_d.c @@ -0,0 +1,26 @@ +#include "tommath_private.h" +#ifdef MP_CMP_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare a digit */ +mp_ord mp_cmp_d(const mp_int *a, mp_digit b) +{ + /* compare based on sign */ + if (mp_isneg(a)) { + return MP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return MP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] != b) { + return a->dp[0] > b ? MP_GT : MP_LT; + } + + return MP_EQ; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_mag.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_mag.c new file mode 100644 index 0000000..06f22e7 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cmp_mag.c @@ -0,0 +1,25 @@ +#include "tommath_private.h" +#ifdef MP_CMP_MAG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare magnitude of two ints (unsigned) */ +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) +{ + int n; + + /* compare based on # of non-zero digits */ + if (a->used != b->used) { + return a->used > b->used ? MP_GT : MP_LT; + } + + /* compare based on digits */ + for (n = a->used; n --> 0;) { + if (a->dp[n] != b->dp[n]) { + return a->dp[n] > b->dp[n] ? MP_GT : MP_LT; + } + } + + return MP_EQ; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cnt_lsb.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cnt_lsb.c new file mode 100644 index 0000000..8519ad1 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cnt_lsb.c @@ -0,0 +1,38 @@ +#include "tommath_private.h" +#ifdef MP_CNT_LSB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static const char lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(const mp_int *a) +{ + int x; + mp_digit q; + + /* easy out */ + if (mp_iszero(a)) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; (x < a->used) && (a->dp[x] == 0u); x++) {} + q = a->dp[x]; + x *= MP_DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1u) == 0u) { + mp_digit p; + do { + p = q & 15u; + x += lnz[p]; + q >>= 4; + } while (p == 0u); + } + return x; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_complement.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_complement.c new file mode 100644 index 0000000..c16e25f --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_complement.c @@ -0,0 +1,13 @@ +#include "tommath_private.h" +#ifdef MP_COMPLEMENT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = ~a */ +mp_err mp_complement(const mp_int *a, mp_int *b) +{ + mp_int a_ = *a; + a_.sign = ((a_.sign == MP_ZPOS) && !mp_iszero(a)) ? MP_NEG : MP_ZPOS; + return mp_sub_d(&a_, 1uL, b); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_copy.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_copy.c new file mode 100644 index 0000000..d79e2b8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_copy.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* copy, b = a */ +mp_err mp_copy(const mp_int *a, mp_int *b) +{ + mp_err err; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + + /* copy everything over and zero high digits */ + s_mp_copy_digs(b->dp, a->dp, a->used); + s_mp_zero_digs(b->dp + a->used, b->used - a->used); + b->used = a->used; + b->sign = a->sign; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_count_bits.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_count_bits.c new file mode 100644 index 0000000..52b463d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_count_bits.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_COUNT_BITS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* returns the number of bits in an int */ +int mp_count_bits(const mp_int *a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (mp_iszero(a)) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * MP_DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > 0u) { + ++r; + q >>= 1u; + } + return r; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cutoffs.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cutoffs.c new file mode 100644 index 0000000..45b0bee --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_cutoffs.c @@ -0,0 +1,14 @@ +#include "tommath_private.h" +#ifdef MP_CUTOFFS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_FIXED_CUTOFFS +#include "tommath_cutoffs.h" +int MP_MUL_KARATSUBA_CUTOFF = MP_DEFAULT_MUL_KARATSUBA_CUTOFF, + MP_SQR_KARATSUBA_CUTOFF = MP_DEFAULT_SQR_KARATSUBA_CUTOFF, + MP_MUL_TOOM_CUTOFF = MP_DEFAULT_MUL_TOOM_CUTOFF, + MP_SQR_TOOM_CUTOFF = MP_DEFAULT_SQR_TOOM_CUTOFF; +#endif + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div.c new file mode 100644 index 0000000..b092d7b --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div.c @@ -0,0 +1,42 @@ +#include "tommath_private.h" +#ifdef MP_DIV_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_err err; + + /* is divisor zero ? */ + if (mp_iszero(b)) { + return MP_VAL; + } + + /* if a < b then q = 0, r = a */ + if (mp_cmp_mag(a, b) == MP_LT) { + if (d != NULL) { + if ((err = mp_copy(a, d)) != MP_OKAY) { + return err; + } + } + if (c != NULL) { + mp_zero(c); + } + return MP_OKAY; + } + + if (MP_HAS(S_MP_DIV_RECURSIVE) + && (b->used > (2 * MP_MUL_KARATSUBA_CUTOFF)) + && (b->used <= ((a->used/3)*2))) { + err = s_mp_div_recursive(a, b, c, d); + } else if (MP_HAS(S_MP_DIV_SCHOOL)) { + err = s_mp_div_school(a, b, c, d); + } else if (MP_HAS(S_MP_DIV_SMALL)) { + err = s_mp_div_small(a, b, c, d); + } else { + err = MP_VAL; + } + + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2.c new file mode 100644 index 0000000..8ab9bcb --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_DIV_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = a/2 */ +mp_err mp_div_2(const mp_int *a, mp_int *b) +{ + mp_err err; + int x, oldused; + mp_digit r; + + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + + oldused = b->used; + b->used = a->used; + + /* carry */ + r = 0; + for (x = b->used; x --> 0;) { + /* get the carry for the next iteration */ + mp_digit rr = a->dp[x] & 1u; + + /* shift the current digit, add in carry and store */ + b->dp[x] = (a->dp[x] >> 1) | (r << (MP_DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + s_mp_zero_digs(b->dp + b->used, oldused - b->used); + + b->sign = a->sign; + mp_clamp(b); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2d.c new file mode 100644 index 0000000..e523465 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_2d.c @@ -0,0 +1,61 @@ +#include "tommath_private.h" +#ifdef MP_DIV_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) +{ + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + /* 'a' should not be used after here - it might be the same as d */ + + /* get the remainder */ + if (d != NULL) { + if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) { + return err; + } + } + + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + mp_rshd(c, b / MP_DIGIT_BIT); + } + + /* shift any bit count < MP_DIGIT_BIT */ + b %= MP_DIGIT_BIT; + if (b != 0u) { + int x; + mp_digit r, mask, shift; + + /* mask */ + mask = ((mp_digit)1 << b) - 1uL; + + /* shift for lsb */ + shift = (mp_digit)(MP_DIGIT_BIT - b); + + /* carry */ + r = 0; + for (x = c->used; x --> 0;) { + /* get the lower bits of this word in a temp */ + mp_digit rr = c->dp[x] & mask; + + /* shift the current word and mix in the carry bits from the previous word */ + c->dp[x] = (c->dp[x] >> b) | (r << shift); + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_d.c new file mode 100644 index 0000000..5697e54 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_div_d.c @@ -0,0 +1,84 @@ +#include "tommath_private.h" +#ifdef MP_DIV_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit division (based on routine from MPI) */ +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w; + mp_err err; + int ix; + + /* cannot divide by zero */ + if (b == 0u) { + return MP_VAL; + } + + /* quick outs */ + if ((b == 1u) || mp_iszero(a)) { + if (d != NULL) { + *d = 0; + } + if (c != NULL) { + return mp_copy(a, c); + } + return MP_OKAY; + } + + /* power of two ? */ + if (MP_HAS(MP_DIV_2) && (b == 2u)) { + if (d != NULL) { + *d = mp_isodd(a) ? 1u : 0u; + } + return (c == NULL) ? MP_OKAY : mp_div_2(a, c); + } + if (MP_HAS(MP_DIV_2D) && MP_IS_2EXPT(b)) { + ix = 1; + while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL); + } + return (c == NULL) ? MP_OKAY : mp_div_2d(a, ix, c, NULL); + } + + /* three? */ + if (MP_HAS(S_MP_DIV_3) && (b == 3u)) { + return s_mp_div_3(a, c, d); + } + + /* no easy answer [c'est la vie]. Just division */ + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used; ix --> 0;) { + mp_digit t = 0; + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; + if (w >= b) { + t = (mp_digit)(w / b); + w -= (mp_word)t * (mp_word)b; + } + q.dp[ix] = t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return MP_OKAY; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_is_modulus.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_is_modulus.c new file mode 100644 index 0000000..72b3c96 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_is_modulus.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef MP_DR_IS_MODULUS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if a number is a valid DR modulus */ +bool mp_dr_is_modulus(const mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return false; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return false; + } + } + return true; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_reduce.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_reduce.c new file mode 100644 index 0000000..f0f6f35 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_reduce.c @@ -0,0 +1,68 @@ +#include "tommath_private.h" +#ifdef MP_DR_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Joong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + * + * Input x must be in the range 0 <= x <= (n-1)**2 + */ +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) +{ + mp_err err; + + /* m = digits in modulus */ + int m = n->used; + + /* ensure that "x" has at least 2m digits */ + if ((err = mp_grow(x, m + m)) != MP_OKAY) { + return err; + } + + /* top of loop, this is where the code resumes if + * another reduction pass is required. + */ + for (;;) { + int i; + mp_digit mu = 0; + + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + mp_word r = ((mp_word)x->dp[i + m] * (mp_word)k) + x->dp[i] + mu; + x->dp[i] = (mp_digit)(r & MP_MASK); + mu = (mp_digit)(r >> ((mp_word)MP_DIGIT_BIT)); + } + + /* set final carry */ + x->dp[i] = mu; + + /* zero words above m */ + s_mp_zero_digs(x->dp + m + 1, (x->used - m) - 1); + + /* clamp, sub and return */ + mp_clamp(x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag(x, n) == MP_LT) { + break; + } + + if ((err = s_mp_sub(x, n, x)) != MP_OKAY) { + return err; + } + } + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_setup.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_setup.c new file mode 100644 index 0000000..c5bb359 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_dr_setup.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_DR_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +void mp_dr_setup(const mp_int *a, mp_digit *d) +{ + /* the casts are required if MP_DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. MP_DIGIT_BIT==31] + */ + *d = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - (mp_word)a->dp[0]); +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_error_to_string.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_error_to_string.c new file mode 100644 index 0000000..39adcd1 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_error_to_string.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_ERROR_TO_STRING_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* return a char * string for a given code */ +const char *mp_error_to_string(mp_err code) +{ + switch (code) { + case MP_OKAY: + return "Successful"; + case MP_ERR: + return "Unknown error"; + case MP_MEM: + return "Out of heap"; + case MP_VAL: + return "Value out of range"; + case MP_ITER: + return "Max. iterations reached"; + case MP_BUF: + return "Buffer overflow"; + case MP_OVF: + return "Integer overflow"; + default: + return "Invalid error code"; + } +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exch.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exch.c new file mode 100644 index 0000000..50b97d9 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exch.c @@ -0,0 +1,13 @@ +#include "tommath_private.h" +#ifdef MP_EXCH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void mp_exch(mp_int *a, mp_int *b) +{ + MP_EXCH(mp_int, *a, *b); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_expt_n.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_expt_n.c new file mode 100644 index 0000000..93f9249 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_expt_n.c @@ -0,0 +1,43 @@ +#include "tommath_private.h" +#ifdef MP_EXPT_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calculate c = a**b using a square-multiply algorithm */ +mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + mp_int g; + + if ((err = mp_init_copy(&g, a)) != MP_OKAY) { + return err; + } + + /* set initial result */ + mp_set(c, 1uL); + + while (b > 0) { + /* if the bit is set multiply */ + if ((b & 1) != 0) { + if ((err = mp_mul(c, &g, c)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* square */ + if (b > 1) { + if ((err = mp_sqr(&g, &g)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* shift to next bit */ + b >>= 1; + } + +LBL_ERR: + mp_clear(&g); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exptmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exptmod.c new file mode 100644 index 0000000..eaab861 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exptmod.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted a lot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) +{ + int dr; + + /* modulus P must be positive */ + if (mp_isneg(P)) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (mp_isneg(X)) { + mp_int tmpG, tmpX; + mp_err err; + + if (!MP_HAS(MP_INVMOD)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) { + return err; + } + + /* first compute 1/G mod P */ + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + goto LBL_ERR; + } + + /* now get |X| */ + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + goto LBL_ERR; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); +LBL_ERR: + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* modified diminished radix reduction */ + if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) && + mp_reduce_is_2k_l(P)) { + return s_mp_exptmod(G, X, P, Y, 1); + } + + /* is it a DR modulus? default to no */ + dr = (MP_HAS(MP_DR_IS_MODULUS) && mp_dr_is_modulus(P)) ? 1 : 0; + + /* if not, is it a unrestricted DR modulus? */ + if (MP_HAS(MP_REDUCE_IS_2K) && (dr == 0)) { + dr = (mp_reduce_is_2k(P)) ? 2 : 0; + } + + /* if the modulus is odd or dr != 0 use the montgomery method */ + if (MP_HAS(S_MP_EXPTMOD_FAST) && (mp_isodd(P) || (dr != 0))) { + return s_mp_exptmod_fast(G, X, P, Y, dr); + } + + /* otherwise use the generic Barrett reduction technique */ + if (MP_HAS(S_MP_EXPTMOD)) { + return s_mp_exptmod(G, X, P, Y, 0); + } + + /* no exptmod for evens */ + return MP_VAL; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exteuclid.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exteuclid.c new file mode 100644 index 0000000..649c4ca --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_exteuclid.c @@ -0,0 +1,72 @@ +#include "tommath_private.h" +#ifdef MP_EXTEUCLID_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Extended euclidean algorithm of (a, b) produces + a*u1 + b*u2 = u3 + */ +mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) +{ + mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp; + mp_err err; + + if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { + return err; + } + + /* initialize, (u1,u2,u3) = (1,0,a) */ + mp_set(&u1, 1uL); + if ((err = mp_copy(a, &u3)) != MP_OKAY) goto LBL_ERR; + + /* initialize, (v1,v2,v3) = (0,1,b) */ + mp_set(&v2, 1uL); + if ((err = mp_copy(b, &v3)) != MP_OKAY) goto LBL_ERR; + + /* loop while v3 != 0 */ + while (!mp_iszero(&v3)) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) goto LBL_ERR; + + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) goto LBL_ERR; + + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) goto LBL_ERR; + + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) goto LBL_ERR; + } + + /* make sure U3 >= 0 */ + if (mp_isneg(&u3)) { + if ((err = mp_neg(&u1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u3, &u3)) != MP_OKAY) goto LBL_ERR; + } + + /* copy result out */ + if (U1 != NULL) { + mp_exch(U1, &u1); + } + if (U2 != NULL) { + mp_exch(U2, &u2); + } + if (U3 != NULL) { + mp_exch(U3, &u3); + } + +LBL_ERR: + mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fread.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fread.c new file mode 100644 index 0000000..53c35e8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fread.c @@ -0,0 +1,66 @@ +#include "tommath_private.h" +#ifdef MP_FREAD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_NO_FILE +/* read a bigint from a file stream in ASCII */ +mp_err mp_fread(mp_int *a, int radix, FILE *stream) +{ + mp_err err; + mp_sign sign = MP_ZPOS; + int ch; + + /* make sure the radix is ok */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == (int)'-') { + sign = MP_NEG; + ch = fgetc(stream); + } + + /* no digits, return error */ + if (ch == EOF) { + return MP_ERR; + } + + /* clear a */ + mp_zero(a); + + do { + uint8_t y; + unsigned pos; + ch = (radix <= 36) ? MP_TOUPPER(ch) : ch; + pos = (unsigned)(ch - (int)'+'); + if (MP_RADIX_MAP_REVERSE_SIZE <= pos) { + break; + } + + y = s_mp_radix_map_reverse[pos]; + + if (y >= radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + } while ((ch = fgetc(stream)) != EOF); + + if (!mp_iszero(a)) { + a->sign = sign; + } + + return MP_OKAY; +} +#endif + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_sbin.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_sbin.c new file mode 100644 index 0000000..26eb0f1 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_sbin.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_FROM_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +mp_err mp_from_sbin(mp_int *a, const uint8_t *buf, size_t size) +{ + mp_err err; + + /* read magnitude */ + if ((err = mp_from_ubin(a, buf + 1, size - 1u)) != MP_OKAY) { + return err; + } + + /* first byte is 0 for positive, non-zero for negative */ + a->sign = (buf[0] != (uint8_t)0) ? MP_NEG : MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_ubin.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_ubin.c new file mode 100644 index 0000000..8272185 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_from_ubin.c @@ -0,0 +1,30 @@ +#include "tommath_private.h" +#ifdef MP_FROM_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reads a uint8_t array, assumes the msb is stored first [big endian] */ +mp_err mp_from_ubin(mp_int *a, const uint8_t *buf, size_t size) +{ + mp_err err; + + /* make sure there are at least two digits */ + if ((err = mp_grow(a, 2)) != MP_OKAY) { + return err; + } + + /* zero the int */ + mp_zero(a); + + /* read the bytes in */ + while (size-- > 0u) { + if ((err = mp_mul_2d(a, 8, a)) != MP_OKAY) { + return err; + } + a->dp[0] |= *buf++; + a->used += 1; + } + mp_clamp(a); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fwrite.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fwrite.c new file mode 100644 index 0000000..8ea9d32 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_fwrite.c @@ -0,0 +1,34 @@ +#include "tommath_private.h" +#ifdef MP_FWRITE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_NO_FILE +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) +{ + char *buf; + mp_err err; + size_t size, written; + + if ((err = mp_radix_size_overestimate(a, radix, &size)) != MP_OKAY) { + return err; + } + + buf = (char *) MP_MALLOC(size); + if (buf == NULL) { + return MP_MEM; + } + + if ((err = mp_to_radix(a, buf, size, &written, radix)) == MP_OKAY) { + written--; + if (fwrite(buf, written, 1uL, stream) != 1uL) { + err = MP_ERR; + } + } + + MP_FREE_BUF(buf, size); + return err; +} +#endif + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_gcd.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_gcd.c new file mode 100644 index 0000000..4f6b6cc --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_gcd.c @@ -0,0 +1,92 @@ +#include "tommath_private.h" +#ifdef MP_GCD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Greatest Common Divisor using the binary method */ +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int u, v; + int k, u_lsb, v_lsb; + mp_err err; + + /* either zero than gcd is the largest */ + if (mp_iszero(a)) { + return mp_abs(b, c); + } + if (mp_iszero(b)) { + return mp_abs(a, c); + } + + /* get copies of a and b we can modify */ + if ((err = mp_init_copy(&u, a)) != MP_OKAY) { + return err; + } + + if ((err = mp_init_copy(&v, b)) != MP_OKAY) { + goto LBL_U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MP_MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((err = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + + if ((err = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((err = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + if (v_lsb != k) { + if ((err = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + while (!mp_iszero(&v)) { + /* make sure v is the largest */ + if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ + mp_exch(&u, &v); + } + + /* subtract smallest from largest */ + if ((err = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto LBL_V; + } + + /* Divide out all factors of two */ + if ((err = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* multiply by 2**k which we divided out at the beginning */ + if ((err = mp_mul_2d(&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + err = MP_OKAY; +LBL_V: + mp_clear(&u); +LBL_U: + mp_clear(&v); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_double.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_double.c new file mode 100644 index 0000000..f462eb8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_double.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef MP_GET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +double mp_get_double(const mp_int *a) +{ + int i; + double d = 0.0, fac = 1.0; + for (i = 0; i < MP_DIGIT_BIT; ++i) { + fac *= 2.0; + } + for (i = a->used; i --> 0;) { + d = (d * fac) + (double)a->dp[i]; + } + return mp_isneg(a) ? -d : d; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i32.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i32.c new file mode 100644 index 0000000..6b3b6ad --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i32, mp_get_mag_u32, int32_t, uint32_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i64.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i64.c new file mode 100644 index 0000000..8d38a1f --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i64, mp_get_mag_u64, int64_t, uint64_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_l.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_l.c new file mode 100644 index 0000000..3a1a2f7 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_l, mp_get_mag_ul, long, unsigned long) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u32.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u32.c new file mode 100644 index 0000000..acddc58 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_MAG_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u32, uint32_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u64.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u64.c new file mode 100644 index 0000000..f754639 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_MAG_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u64, uint64_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_ul.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_ul.c new file mode 100644 index 0000000..5c60430 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_get_mag_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_MAG_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_ul, unsigned long) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_grow.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_grow.c new file mode 100644 index 0000000..551d1a3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_grow.c @@ -0,0 +1,44 @@ +#include "tommath_private.h" +#ifdef MP_GROW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* grow as required */ +mp_err mp_grow(mp_int *a, int size) +{ + if (size < 0) { + return MP_VAL; + } + + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + mp_digit *dp; + + if (size > MP_MAX_DIGIT_COUNT) { + return MP_OVF; + } + + /* reallocate the array a->dp + * + * We store the return in a temporary variable + * in case the operation failed we don't want + * to overwrite the dp member of a. + */ + dp = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)size * sizeof(mp_digit)); + if (dp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } + + /* reallocation succeeded so set a->dp */ + a->dp = dp; + + /* zero excess digits */ + s_mp_zero_digs(a->dp + a->alloc, size - a->alloc); + a->alloc = size; + } + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_hash.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_hash.c new file mode 100644 index 0000000..9607c80 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_hash.c @@ -0,0 +1,36 @@ +#include "tommath_private.h" +#ifdef MP_HASH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if defined(MP_16BIT) +#define FNV_1A_INIT ((uint32_t)0x811c9dc5) +#define FNV_1A_PRIME ((uint32_t)0x01000193) +#else +#define FNV_1A_INIT ((uint64_t)0xcbf29ce484222325ULL) +#define FNV_1A_PRIME ((uint64_t)0x100000001b3ULL) +#endif + +/* computes hash of mp_int. */ +mp_err mp_hash(const mp_int *a, mp_hval *hash) +{ + int x; + mp_hval hval = FNV_1A_INIT; + mp_digit r, mask, shift; + + /* FNV-1a algorithm */ + mask = ((mp_digit)1 << 8) - 1uL; + shift = (mp_digit)(MP_DIGIT_BIT - 8); + r = 0; + for (x = a->used; x --> 0;) { + mp_digit rr = a->dp[x] & mask; + hval ^= (mp_hval)(a->dp[x] >> 8) | (r << shift); + hval *= FNV_1A_PRIME; + r = rr; + } + hval ^= mp_isneg(a) ? (mp_hval)1 : (mp_hval)0; + *hash = hval * FNV_1A_PRIME; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init.c new file mode 100644 index 0000000..af16744 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef MP_INIT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* init a new mp_int */ +mp_err mp_init(mp_int *a) +{ + /* allocate memory required and clear it */ + a->dp = (mp_digit *) MP_CALLOC((size_t)MP_DEFAULT_DIGIT_COUNT, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_DEFAULT_DIGIT_COUNT; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_copy.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_copy.c new file mode 100644 index 0000000..4d0773b --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_copy.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_INIT_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* creates "a" then copies b into it */ +mp_err mp_init_copy(mp_int *a, const mp_int *b) +{ + mp_err err; + + if ((err = mp_init_size(a, b->used)) != MP_OKAY) { + return err; + } + + if ((err = mp_copy(b, a)) != MP_OKAY) { + mp_clear(a); + } + + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i32.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i32.c new file mode 100644 index 0000000..434788f --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i32, mp_set_i32, int32_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i64.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i64.c new file mode 100644 index 0000000..7185678 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i64, mp_set_i64, int64_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_l.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_l.c new file mode 100644 index 0000000..16be8f6 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_l, mp_set_l, long) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_multi.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_multi.c new file mode 100644 index 0000000..908b4df --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_multi.c @@ -0,0 +1,41 @@ +#include "tommath_private.h" +#ifdef MP_INIT_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +mp_err mp_init_multi(mp_int *mp, ...) +{ + mp_err err = MP_OKAY; + int n = 0; /* Number of ok inits */ + mp_int *cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + err = mp_init(cur_arg); + if (err != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n-- != 0) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int *); + } + va_end(clean_args); + break; + } + n++; + cur_arg = va_arg(args, mp_int *); + } + va_end(args); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_set.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_set.c new file mode 100644 index 0000000..e1f2ee9 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_set.c @@ -0,0 +1,16 @@ +#include "tommath_private.h" +#ifdef MP_INIT_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* initialize and set a digit */ +mp_err mp_init_set(mp_int *a, mp_digit b) +{ + mp_err err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_size.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_size.c new file mode 100644 index 0000000..87a4256 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_size.c @@ -0,0 +1,32 @@ +#include "tommath_private.h" +#ifdef MP_INIT_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* init an mp_init for a given size */ +mp_err mp_init_size(mp_int *a, int size) +{ + if (size < 0) { + return MP_VAL; + } + + size = MP_MAX(MP_MIN_DIGIT_COUNT, size); + + if (size > MP_MAX_DIGIT_COUNT) { + return MP_OVF; + } + + /* alloc mem */ + a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u32.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u32.c new file mode 100644 index 0000000..d5a2b8f --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u32, mp_set_u32, uint32_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u64.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u64.c new file mode 100644 index 0000000..ca75084 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u64, mp_set_u64, uint64_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_ul.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_ul.c new file mode 100644 index 0000000..21ca3be --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_init_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ul, mp_set_ul, unsigned long) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_invmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_invmod.c new file mode 100644 index 0000000..2494acb --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_invmod.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + /* for all n in N and n > 0, n = 0 mod 1 */ + if (!mp_isneg(a) && mp_cmp_d(b, 1uL) == MP_EQ) { + mp_zero(c); + return MP_OKAY; + } + + /* b cannot be negative and has to be >1 */ + if (mp_isneg(b) || (mp_cmp_d(b, 1uL) != MP_GT)) { + return MP_VAL; + } + + /* if the modulus is odd we can use a faster routine instead */ + if (MP_HAS(S_MP_INVMOD_ODD) && mp_isodd(b)) { + return s_mp_invmod_odd(a, b, c); + } + + return MP_HAS(S_MP_INVMOD) + ? s_mp_invmod(a, b, c) + : MP_VAL; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_is_square.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_is_square.c new file mode 100644 index 0000000..d2856e2 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_is_square.c @@ -0,0 +1,94 @@ +#include "tommath_private.h" +#ifdef MP_IS_SQUARE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Check if remainders are possible squares - fast exclude non-squares */ +static const char rem_128[128] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 +}; + +static const char rem_105[105] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 +}; + +/* Store non-zero to ret if arg is square, and zero if not */ +mp_err mp_is_square(const mp_int *arg, bool *ret) +{ + mp_err err; + mp_digit c; + mp_int t; + uint32_t r; + + /* Default to Non-square :) */ + *ret = false; + + if (mp_isneg(arg)) { + return MP_VAL; + } + + if (mp_iszero(arg)) { + *ret = true; + return MP_OKAY; + } + + /* First check mod 128 (suppose that MP_DIGIT_BIT is at least 7) */ + if (rem_128[127u & arg->dp[0]] == (char)1) { + return MP_OKAY; + } + + /* Next check mod 105 (3*5*7) */ + if ((err = mp_mod_d(arg, 105uL, &c)) != MP_OKAY) { + return err; + } + if (rem_105[c] == (char)1) { + return MP_OKAY; + } + + + if ((err = mp_init_u32(&t, 11u*13u*17u*19u*23u*29u*31u)) != MP_OKAY) { + return err; + } + if ((err = mp_mod(arg, &t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + r = mp_get_u32(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto LBL_ERR. We know that err + * is already equal to MP_OKAY from the mp_mod call + */ + if (((1uL<<(r%11uL)) & 0x5C4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%13uL)) & 0x9E4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%17uL)) & 0x5CE8uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%19uL)) & 0x4F50CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%23uL)) & 0x7ACCA0uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%29uL)) & 0xC2EDD0CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%31uL)) & 0x6DE2B848uL) != 0uL) goto LBL_ERR; + + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((err = mp_sqrt(arg, &t)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sqr(&t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + + *ret = (mp_cmp_mag(&t, arg) == MP_EQ); +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_kronecker.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_kronecker.c new file mode 100644 index 0000000..e6bedc8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_kronecker.c @@ -0,0 +1,129 @@ +#include "tommath_private.h" +#ifdef MP_KRONECKER_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + Kronecker symbol (a|p) + Straightforward implementation of algorithm 1.4.10 in + Henri Cohen: "A Course in Computational Algebraic Number Theory" + + @book{cohen2013course, + title={A course in computational algebraic number theory}, + author={Cohen, Henri}, + volume={138}, + year={2013}, + publisher={Springer Science \& Business Media} + } + */ +mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c) +{ + mp_int a1, p1, r; + mp_err err; + int v, k; + + static const char table[] = {0, 1, 0, -1, 0, -1, 0, 1}; + + if (mp_iszero(p)) { + if ((a->used == 1) && (a->dp[0] == 1u)) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; + } + + if (mp_iseven(a) && mp_iseven(p)) { + *c = 0; + return MP_OKAY; + } + + if ((err = mp_init_copy(&a1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_init_copy(&p1, p)) != MP_OKAY) { + goto LBL_KRON_0; + } + + v = mp_cnt_lsb(&p1); + if ((err = mp_div_2d(&p1, v, &p1, NULL)) != MP_OKAY) { + goto LBL_KRON_1; + } + + if ((v & 1) == 0) { + k = 1; + } else { + k = table[a->dp[0] & 7u]; + } + + if (mp_isneg(&p1)) { + p1.sign = MP_ZPOS; + if (mp_isneg(&a1)) { + k = -k; + } + } + + if ((err = mp_init(&r)) != MP_OKAY) { + goto LBL_KRON_1; + } + + for (;;) { + if (mp_iszero(&a1)) { + if (mp_cmp_d(&p1, 1uL) == MP_EQ) { + *c = k; + goto LBL_KRON; + } else { + *c = 0; + goto LBL_KRON; + } + } + + v = mp_cnt_lsb(&a1); + if ((err = mp_div_2d(&a1, v, &a1, NULL)) != MP_OKAY) { + goto LBL_KRON; + } + + if ((v & 1) == 1) { + k = k * table[p1.dp[0] & 7u]; + } + + if (mp_isneg(&a1)) { + /* + * Compute k = (-1)^((a1)*(p1-1)/4) * k + * a1.dp[0] + 1 cannot overflow because the MSB + * of the type mp_digit is not set by definition + */ + if (((a1.dp[0] + 1u) & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } else { + /* compute k = (-1)^((a1-1)*(p1-1)/4) * k */ + if ((a1.dp[0] & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } + + if ((err = mp_copy(&a1, &r)) != MP_OKAY) { + goto LBL_KRON; + } + r.sign = MP_ZPOS; + if ((err = mp_mod(&p1, &r, &a1)) != MP_OKAY) { + goto LBL_KRON; + } + if ((err = mp_copy(&r, &p1)) != MP_OKAY) { + goto LBL_KRON; + } + } + +LBL_KRON: + mp_clear(&r); +LBL_KRON_1: + mp_clear(&p1); +LBL_KRON_0: + mp_clear(&a1); + + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lcm.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lcm.c new file mode 100644 index 0000000..f2044f0 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lcm.c @@ -0,0 +1,44 @@ +#include "tommath_private.h" +#ifdef MP_LCM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes least common multiple as |a*b|/(a, b) */ +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + mp_int t1, t2; + + + if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) { + return err; + } + + /* t1 = get the GCD of the two inputs */ + if ((err = mp_gcd(a, b, &t1)) != MP_OKAY) { + goto LBL_T; + } + + /* divide the smallest by the GCD */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* store quotient in t2 such that t2 * b is the LCM */ + if ((err = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((err = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(a, &t2, c); + } + + /* fix the sign to positive */ + c->sign = MP_ZPOS; + +LBL_T: + mp_clear_multi(&t1, &t2, NULL); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log.c new file mode 100644 index 0000000..0d5d893 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log.c @@ -0,0 +1,168 @@ +#include "tommath_private.h" +#ifdef MP_LOG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define MP_LOG2_EXPT(a,b) ((mp_count_bits((a)) - 1) / mp_cnt_lsb((b))) + +static mp_err s_approx_log_d(const mp_int *a, const mp_int *b, int *lb) +{ + mp_word La, Lb; + mp_err err; + + /* Approximation of the individual logarithms with low precision */ + if ((err = s_mp_fp_log_d(a, &La)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_fp_log_d(b, &Lb)) != MP_OKAY) goto LTM_ERR; + + /* Approximation of log_b(a) with low precision. */ + *lb = (int)(((La - (Lb + 1)/2) / Lb) + 1); + /* TODO: just floor it instead? Multiplication is cheaper than division. */ + /* *lb = (int)(la_word / lb_word); */ + err = MP_OKAY; +LTM_ERR: + return err; +} + +static mp_err s_approx_log(const mp_int *a, const mp_int *b, int *lb) +{ + mp_int La, Lb, t; + mp_err err; + + if ((err = mp_init_multi(&La, &Lb, &t, NULL)) != MP_OKAY) { + return err; + } + + if ((err = s_mp_fp_log(a, &La)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_fp_log(b, &Lb)) != MP_OKAY) goto LTM_ERR; + + if ((err = mp_add_d(&Lb, 1u, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2(&t, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_sub(&La, &t, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div(&t, &Lb, &t, NULL)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add_d(&t, 1u, &t)) != MP_OKAY) goto LTM_ERR; + + *lb = mp_get_i32(&t); + err = MP_OKAY; +LTM_ERR: + mp_clear_multi(&t, &Lb, &La, NULL); + return err; +} + +mp_err mp_log(const mp_int *a, const mp_int *b, int *lb) +{ + mp_int bn; + int n, fla, flb; + mp_err err; + mp_ord cmp; + + if (mp_isneg(a) || mp_iszero(a) || (mp_cmp_d(b, 2u) == MP_LT)) { + return MP_VAL; + } + + if (MP_IS_POWER_OF_TWO(b)) { + *lb = MP_LOG2_EXPT(a, b); + return MP_OKAY; + } + + /* floor(log_2(x)) for cut-off */ + fla = mp_count_bits(a) - 1; + flb = mp_count_bits(b) - 1; + + cmp = mp_cmp(a, b); + + /* "a < b -> 0" and "(b == a) -> 1" */ + if ((cmp == MP_LT) || (cmp == MP_EQ)) { + *lb = (cmp == MP_EQ); + return MP_OKAY; + } + + /* "a < b^2 -> 1" (bit-count is sufficient, doesn't need to be exact) */ + if (((2 * flb)-1) > fla) { + *lb = 1; + return MP_OKAY; + } + + if (MP_HAS(S_MP_WORD_TOO_SMALL)) { + err = s_approx_log(a, b, &n); + } else { + err = s_approx_log_d(a, b, &n); + } + if (err != MP_OKAY) { + return err; + } + + if ((err = mp_init(&bn)) != MP_OKAY) { + return err; + } + + /* Check result. Result is wrong by 2(two) at most. */ + if ((err = mp_expt_n(b, n, &bn)) != MP_OKAY) { + /* If the approximation overshot we can give it another try */ + if (err == MP_OVF) { + n--; + /* But only one */ + if ((err = mp_expt_n(b, n, &bn)) != MP_OKAY) goto LTM_ERR; + } else { + goto LTM_ERR; + } + } + + cmp = mp_cmp(&bn, a); + + /* The rare case of a perfect power makes a perfect shortcut, too. */ + if (cmp == MP_EQ) { + *lb = n; + goto LTM_OUT; + } + + /* We have to make at least one multiplication because it could still be a perfect power. */ + if (cmp == MP_LT) { + do { + /* Full big-integer operations are to be avoided if possible */ + if (b->used == 1) { + if ((err = mp_mul_d(&bn, b->dp[0], &bn)) != MP_OKAY) { + if (err == MP_OVF) { + goto LTM_OUT; + } + goto LTM_ERR; + } + } else { + if ((err = mp_mul(&bn, b, &bn)) != MP_OKAY) { + if (err == MP_OVF) { + goto LTM_OUT; + } + goto LTM_ERR; + } + } + n++; + } while ((cmp = mp_cmp(&bn, a)) == MP_LT); + /* Overshot, take it back. */ + if (cmp == MP_GT) { + n--; + } + goto LTM_OUT; + } + + /* But it can overestimate, too, for example if "a" is closely below some "b^k" */ + if (cmp == MP_GT) { + do { + if (b->used == 1) { + /* These are cheaper exact divisions, but that function is not available in LTM */ + if ((err = mp_div_d(&bn, b->dp[0], &bn, NULL)) != MP_OKAY) goto LTM_ERR; + + } else { + if ((err = mp_div(&bn, b, &bn, NULL)) != MP_OKAY) goto LTM_ERR; + } + n--; + } while ((cmp = mp_cmp(&bn, a)) == MP_GT); + } + +LTM_OUT: + *lb = n; + err = MP_OKAY; +LTM_ERR: + mp_clear(&bn); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log_n.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log_n.c new file mode 100644 index 0000000..364e28a --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_log_n.c @@ -0,0 +1,19 @@ +#include "tommath_private.h" +#ifdef MP_LOG_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_log_n(const mp_int *a, int base, int *c) +{ + mp_int b; + mp_err err; + + if ((err = mp_init_i32(&b, base)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_log(a, &b, c)) != MP_OKAY) goto LTM_ERR; + +LTM_ERR: + mp_clear(&b); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lshd.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lshd.c new file mode 100644 index 0000000..90014e4 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_lshd.c @@ -0,0 +1,42 @@ +#include "tommath_private.h" +#ifdef MP_LSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift left a certain amount of digits */ +mp_err mp_lshd(mp_int *a, int b) +{ + mp_err err; + int x; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + /* no need to shift 0 around */ + if (mp_iszero(a)) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if ((err = mp_grow(a, a->used + b)) != MP_OKAY) { + return err; + } + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the other way around. Copying from + * the bottom to the top. see mp_rshd.c for more info. + */ + for (x = a->used; x --> b;) { + a->dp[x] = a->dp[x - b]; + } + + /* zero the lower digits */ + s_mp_zero_digs(a->dp, b); + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod.c new file mode 100644 index 0000000..beae13e --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_MOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = a mod b, 0 <= c < b if b > 0, b < c <= 0 if b < 0 */ +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + if ((err = mp_div(a, b, NULL, c)) != MP_OKAY) { + return err; + } + return mp_iszero(c) || (c->sign == b->sign) ? MP_OKAY : mp_add(b, c, c); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod_2d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod_2d.c new file mode 100644 index 0000000..82c64f0 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mod_2d.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_MOD_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calc a value mod 2**b */ +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) +{ + int x; + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + if (b == 0) { + mp_zero(c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b >= (a->used * MP_DIGIT_BIT)) { + return mp_copy(a, c); + } + + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + /* zero digits above the last digit of the modulus */ + x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1); + s_mp_zero_digs(c->dp + x, c->used - x); + + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / MP_DIGIT_BIT] &= + ((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1; + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_calc_normalization.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_calc_normalization.c new file mode 100644 index 0000000..bbb3adb --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_calc_normalization.c @@ -0,0 +1,43 @@ +#include "tommath_private.h" +#ifdef MP_MONTGOMERY_CALC_NORMALIZATION_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves a lot of multiple precision shifting. + */ +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) +{ + int x, bits; + mp_err err; + + /* how many bits of last digit does b use */ + bits = mp_count_bits(b) % MP_DIGIT_BIT; + + if (b->used > 1) { + if ((err = mp_2expt(a, ((b->used - 1) * MP_DIGIT_BIT) + bits - 1)) != MP_OKAY) { + return err; + } + } else { + mp_set(a, 1uL); + bits = 1; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)MP_DIGIT_BIT; x++) { + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + return err; + } + if (mp_cmp_mag(a, b) != MP_LT) { + if ((err = s_mp_sub(a, b, a)) != MP_OKAY) { + return err; + } + } + } + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_reduce.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_reduce.c new file mode 100644 index 0000000..dbf45d3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_reduce.c @@ -0,0 +1,89 @@ +#include "tommath_private.h" +#ifdef MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) +{ + mp_err err; + int ix, digs; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = (n->used * 2) + 1; + if ((digs < MP_WARRAY) && + (x->used <= MP_WARRAY) && + (n->used < MP_MAX_COMBA)) { + return s_mp_montgomery_reduce_comba(x, n, rho); + } + + /* grow the input as required */ + if ((err = mp_grow(x, digs)) != MP_OKAY) { + return err; + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + int iy; + mp_digit u, mu; + + /* mu = ai * rho mod b + * + * The value of rho must be precalculated via + * montgomery_setup() such that + * it equals -1/n0 mod b this allows the + * following inner loop to reduce the + * input one digit at a time + */ + mu = (mp_digit)(((mp_word)x->dp[ix] * (mp_word)rho) & MP_MASK); + + /* a = a + mu * m * b**i */ + + /* Multiply and add in place */ + u = 0; + for (iy = 0; iy < n->used; iy++) { + /* compute product and sum */ + mp_word r = ((mp_word)mu * (mp_word)n->dp[iy]) + + (mp_word)u + (mp_word)x->dp[ix + iy]; + + /* get carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + + /* fix digit */ + x->dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + } + /* At this point the ix'th digit of x should be zero */ + + /* propagate carries upwards as required*/ + while (u != 0u) { + x->dp[ix + iy] += u; + u = x->dp[ix + iy] >> MP_DIGIT_BIT; + x->dp[ix + iy] &= MP_MASK; + ++iy; + } + } + + /* at this point the n.used'th least + * significant digits of x are all zero + * which means we can shift x to the + * right by n.used digits and the + * residue is unchanged. + */ + + /* x = x/b**n.used */ + mp_clamp(x); + mp_rshd(x, n->used); + + /* if x >= n then x = x - n */ + if (mp_cmp_mag(x, n) != MP_LT) { + return s_mp_sub(x, n, x); + } + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_setup.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_setup.c new file mode 100644 index 0000000..de57dc3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_montgomery_setup.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_MONTGOMERY_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* setups the montgomery reduction stuff */ +mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho) +{ + mp_digit x, b; + + /* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1u) == 0u) { + return MP_VAL; + } + + x = (((b + 2u) & 4u) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**8 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**16 */ +#if defined(MP_64BIT) || !(defined(MP_16BIT)) + x *= 2u - (b * x); /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2u - (b * x); /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - x) & MP_MASK; + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul.c new file mode 100644 index 0000000..8180740 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul.c @@ -0,0 +1,68 @@ +#include "tommath_private.h" +#ifdef MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level multiplication (handles sign) */ +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + int min = MP_MIN(a->used, b->used), + max = MP_MAX(a->used, b->used), + digs = a->used + b->used + 1; + bool neg = (a->sign != b->sign); + + if ((a == b) && + MP_HAS(S_MP_SQR_TOOM) && /* use Toom-Cook? */ + (a->used >= MP_SQR_TOOM_CUTOFF)) { + err = s_mp_sqr_toom(a, c); + } else if ((a == b) && + MP_HAS(S_MP_SQR_KARATSUBA) && /* Karatsuba? */ + (a->used >= MP_SQR_KARATSUBA_CUTOFF)) { + err = s_mp_sqr_karatsuba(a, c); + } else if ((a == b) && + MP_HAS(S_MP_SQR_COMBA) && /* can we use the fast comba multiplier? */ + (((a->used * 2) + 1) < MP_WARRAY) && + (a->used <= MP_MAX_COMBA)) { + err = s_mp_sqr_comba(a, c); + } else if ((a == b) && + MP_HAS(S_MP_SQR)) { + err = s_mp_sqr(a, c); + } else if (MP_HAS(S_MP_MUL_BALANCE) && + /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. + * The bigger one needs to be at least about one MP_MUL_KARATSUBA_CUTOFF bigger + * to make some sense, but it depends on architecture, OS, position of the + * stars... so YMMV. + * Using it to cut the input into slices small enough for s_mp_mul_comba + * was actually slower on the author's machine, but YMMV. + */ + (min >= MP_MUL_KARATSUBA_CUTOFF) && + ((max / 2) >= MP_MUL_KARATSUBA_CUTOFF) && + /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ + (max >= (2 * min))) { + err = s_mp_mul_balance(a,b,c); + } else if (MP_HAS(S_MP_MUL_TOOM) && + (min >= MP_MUL_TOOM_CUTOFF)) { + err = s_mp_mul_toom(a, b, c); + } else if (MP_HAS(S_MP_MUL_KARATSUBA) && + (min >= MP_MUL_KARATSUBA_CUTOFF)) { + err = s_mp_mul_karatsuba(a, b, c); + } else if (MP_HAS(S_MP_MUL_COMBA) && + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + (digs < MP_WARRAY) && + (min <= MP_MAX_COMBA)) { + err = s_mp_mul_comba(a, b, c, digs); + } else if (MP_HAS(S_MP_MUL)) { + err = s_mp_mul(a, b, c, digs); + } else { + err = MP_VAL; + } + c->sign = ((c->used > 0) && neg) ? MP_NEG : MP_ZPOS; + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2.c new file mode 100644 index 0000000..459fbd2 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2.c @@ -0,0 +1,53 @@ +#include "tommath_private.h" +#ifdef MP_MUL_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = a*2 */ +mp_err mp_mul_2(const mp_int *a, mp_int *b) +{ + mp_err err; + int x, oldused; + mp_digit r; + + /* grow to accommodate result */ + if ((err = mp_grow(b, a->used + 1)) != MP_OKAY) { + return err; + } + + oldused = b->used; + b->used = a->used; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + mp_digit rr = a->dp[x] >> (mp_digit)(MP_DIGIT_BIT - 1); + + /* now shift up this digit, add in the carry [from the previous] */ + b->dp[x] = ((a->dp[x] << 1uL) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0u) { + /* add a MSB which is always 1 at this point */ + b->dp[b->used++] = 1; + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + s_mp_zero_digs(b->dp + b->used, oldused - b->used); + + b->sign = a->sign; + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2d.c new file mode 100644 index 0000000..e458137 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_2d.c @@ -0,0 +1,63 @@ +#include "tommath_private.h" +#ifdef MP_MUL_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift left by a certain bit count */ +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + } + + /* shift any bit count < MP_DIGIT_BIT */ + b %= MP_DIGIT_BIT; + if (b != 0u) { + mp_digit shift, mask, r; + int x; + + /* bitmask for carries */ + mask = ((mp_digit)1 << b) - (mp_digit)1; + + /* shift for msbs */ + shift = (mp_digit)(MP_DIGIT_BIT - b); + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + mp_digit rr = (c->dp[x] >> shift) & mask; + + /* shift the current word and OR in the carry */ + c->dp[x] = ((c->dp[x] << b) | r) & MP_MASK; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + + /* set final carry */ + if (r != 0u) { + c->dp[(c->used)++] = r; + } + } + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_d.c new file mode 100644 index 0000000..2585055 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mul_d.c @@ -0,0 +1,68 @@ +#include "tommath_private.h" +#ifdef MP_MUL_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiply by a digit */ +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_digit u; + mp_err err; + int ix, oldused; + + if (b == 1u) { + return mp_copy(a, c); + } + + /* power of two ? */ + if (MP_HAS(MP_MUL_2) && (b == 2u)) { + return mp_mul_2(a, c); + } + if (MP_HAS(MP_MUL_2D) && MP_IS_2EXPT(b)) { + ix = 1; + while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<used + 1)) != MP_OKAY) { + return err; + } + + /* get the original destinations used count */ + oldused = c->used; + + /* set the sign */ + c->sign = a->sign; + + /* zero carry */ + u = 0; + + /* compute columns */ + for (ix = 0; ix < a->used; ix++) { + /* compute product and carry sum for this term */ + mp_word r = (mp_word)u + ((mp_word)a->dp[ix] * (mp_word)b); + + /* mask off higher bits to get a single digit */ + c->dp[ix] = (mp_digit)(r & (mp_word)MP_MASK); + + /* send carry into next iteration */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + + /* store final carry [if any] and increment ix offset */ + c->dp[ix] = u; + + /* set used count */ + c->used = a->used + 1; + + /* now zero digits above the top */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mulmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mulmod.c new file mode 100644 index 0000000..e158693 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_mulmod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_MULMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a * b (mod c) */ +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + if ((err = mp_mul(a, b, d)) != MP_OKAY) { + return err; + } + return mp_mod(d, c, d); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_neg.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_neg.c new file mode 100644 index 0000000..b445cd4 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_neg.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef MP_NEG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = -a */ +mp_err mp_neg(const mp_int *a, mp_int *b) +{ + mp_err err; + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + + b->sign = ((!mp_iszero(b) && !mp_isneg(b)) ? MP_NEG : MP_ZPOS); + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_or.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_or.c new file mode 100644 index 0000000..1595852 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_or.c @@ -0,0 +1,54 @@ +#include "tommath_private.h" +#ifdef MP_OR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement or */ +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + bool neg = (mp_isneg(a) || mp_isneg(b)); + + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (mp_isneg(a)) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (mp_isneg(b)) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x | y; + + /* convert to to sign-magnitude if negative */ + if (neg) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = (neg ? MP_NEG : MP_ZPOS); + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack.c new file mode 100644 index 0000000..447f1fd --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack.c @@ -0,0 +1,69 @@ +#include "tommath_private.h" +#ifdef MP_PACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_export. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j, count; + uint8_t odd_nail_mask; + + mp_int t; + + count = mp_pack_count(op, nails, size); + + if (count > maxcount) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, op)) != MP_OKAY) { + return err; + } + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0u; i < odd_nails; ++i) { + odd_nail_mask ^= (uint8_t)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0u; i < count; ++i) { + for (j = 0u; j < size; ++j) { + uint8_t *byte = (uint8_t *)rop + + (((order == MP_LSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_LITTLE_ENDIAN) ? j : ((size - 1u) - j)); + + if (j >= (size - nail_bytes)) { + *byte = 0; + continue; + } + + *byte = (uint8_t)((j == ((size - nail_bytes) - 1u)) ? (t.dp[0] & odd_nail_mask) : (t.dp[0] & 0xFFuL)); + + if ((err = mp_div_2d(&t, (j == ((size - nail_bytes) - 1u)) ? (int)(8u - odd_nails) : 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + } + } + + if (written != NULL) { + *written = count; + } + err = MP_OKAY; + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack_count.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack_count.c new file mode 100644 index 0000000..aa682ba --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_pack_count.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef MP_PACK_COUNT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) +{ + size_t bits = (size_t)mp_count_bits(a); + return ((bits / ((size * 8u) - nails)) + (((bits % ((size * 8u) - nails)) != 0u) ? 1u : 0u)); +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_fermat.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_fermat.c new file mode 100644 index 0000000..ac8116f --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_fermat.c @@ -0,0 +1,41 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_FERMAT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* performs one Fermat test. + * + * If "a" were prime then b**a == b (mod a) since the order of + * the multiplicative sub-group would be phi(a) = a-1. That means + * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a). + * + * Sets result to 1 if the congruence holds, or zero otherwise. + */ +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, bool *result) +{ + mp_int t; + mp_err err; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != MP_GT) { + return MP_VAL; + } + + /* init t */ + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + /* compute t = b**a mod a */ + if ((err = mp_exptmod(b, a, a, &t)) != MP_OKAY) { + goto LBL_ERR; + } + + /* is it equal to b? */ + *result = mp_cmp(&t, b) == MP_EQ; + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_frobenius_underwood.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_frobenius_underwood.c new file mode 100644 index 0000000..62d3476 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_frobenius_underwood.c @@ -0,0 +1,127 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_FROBENIUS_UNDERWOOD_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +/* + * floor of positive solution of + * (2^16)-1 = (a+4)*(2*a+5) + * TODO: Both values are smaller than N^(1/4), would have to use a bigint + * for a instead but any a biger than about 120 are already so rare that + * it is possible to ignore them and still get enough pseudoprimes. + * But it is still a restriction of the set of available pseudoprimes + * which makes this implementation less secure if used stand-alone. + */ +#define LTM_FROBENIUS_UNDERWOOD_A 32764 + +mp_err mp_prime_frobenius_underwood(const mp_int *N, bool *result) +{ + mp_int T1z, T2z, Np1z, sz, tz; + int a, ap2, i; + mp_err err; + + if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) { + return err; + } + + for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) { + int j; + + /* TODO: That's ugly! No, really, it is! */ + if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) || + (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) { + continue; + } + + mp_set_i32(&T1z, (int32_t)((a * a) - 4)); + + if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_END; + + if (j == -1) { + break; + } + + if (j == 0) { + /* composite */ + *result = false; + goto LBL_END; + } + } + /* Tell it a composite and set return value accordingly */ + if (a >= LTM_FROBENIUS_UNDERWOOD_A) { + err = MP_ITER; + goto LBL_END; + } + /* Composite if N and (a+4)*(2*a+5) are not coprime */ + mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5))); + + if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_END; + + if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) { + /* composite */ + *result = false; + goto LBL_END; + } + + ap2 = a + 2; + if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_END; + + mp_set(&sz, 1uL); + mp_set(&tz, 2uL); + + for (i = mp_count_bits(&Np1z) - 2; i >= 0; i--) { + /* + * temp = (sz*(a*sz+2*tz))%N; + * tz = ((tz-sz)*(tz+sz))%N; + * sz = temp; + */ + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_END; + + /* a = 0 at about 50% of the cases (non-square and odd input) */ + if (a != 0) { + if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_END; + if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_END; + } + + if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_END; + if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_END; + if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_END; + if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_END; + if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_END; + if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_END; + if (s_mp_get_bit(&Np1z, i)) { + /* + * temp = (a+2) * sz + tz + * tz = 2 * tz - sz + * sz = temp + */ + if (a == 0) { + if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_END; + } else { + if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_END; + } + if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_END; + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_END; + if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_END; + mp_exch(&sz, &T1z); + } + } + + mp_set_u32(&T1z, (uint32_t)((2 * a) + 5)); + if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_END; + + *result = mp_iszero(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ); + +LBL_END: + mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL); + return err; +} + +#endif +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_is_prime.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_is_prime.c new file mode 100644 index 0000000..bb24f59 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_is_prime.c @@ -0,0 +1,282 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_IS_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* portable integer log of two with small footprint */ +static unsigned int s_floor_ilog2(int value) +{ + unsigned int r = 0; + while ((value >>= 1) != 0) { + r++; + } + return r; +} + +mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) +{ + mp_int b; + int ix; + bool res; + mp_err err; + + /* default to no */ + *result = false; + + /* Some shortcuts */ + /* N > 3 */ + if (a->used == 1) { + if ((a->dp[0] == 0u) || (a->dp[0] == 1u)) { + *result = false; + return MP_OKAY; + } + if (a->dp[0] == 2u) { + *result = true; + return MP_OKAY; + } + } + + /* N must be odd */ + if (mp_iseven(a)) { + return MP_OKAY; + } + /* N is not a perfect square: floor(sqrt(N))^2 != N */ + if ((err = mp_is_square(a, &res)) != MP_OKAY) { + return err; + } + if (res) { + return MP_OKAY; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < MP_PRIME_TAB_SIZE; ix++) { + if (mp_cmp_d(a, s_mp_prime_tab[ix]) == MP_EQ) { + *result = true; + return MP_OKAY; + } + } + /* first perform trial division */ + if ((err = s_mp_prime_is_divisible(a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res) { + return MP_OKAY; + } + + /* + Run the Miller-Rabin test with base 2 for the BPSW test. + */ + if ((err = mp_init_set(&b, 2uL)) != MP_OKAY) { + return err; + } + + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + /* + Rumours have it that Mathematica does a second M-R test with base 3. + Other rumours have it that their strong L-S test is slightly different. + It does not hurt, though, beside a bit of extra runtime. + */ + b.dp[0]++; + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + + /* + * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite + * slow so if speed is an issue, define LTM_USE_ONLY_MR to use M-R tests with + * bases 2, 3 and t random bases. + */ +#ifndef LTM_USE_ONLY_MR + if (t >= 0) { +#ifdef LTM_USE_FROBENIUS_TEST + err = mp_prime_frobenius_underwood(a, &res); + if ((err != MP_OKAY) && (err != MP_ITER)) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } +#else + if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } +#endif + } +#endif + + /* run at least one Miller-Rabin test with a random base */ + if (t == 0) { + t = 1; + } + + /* + Only recommended if the input range is known to be < 3317044064679887385961981 + + It uses the bases necessary for a deterministic M-R test if the input is + smaller than 3317044064679887385961981 + The caller has to check the size. + TODO: can be made a bit finer grained but comparing is not free. + */ + if (t < 0) { + int p_max = 0; + + /* + Sorenson, Jonathan; Webster, Jonathan (2015). + "Strong Pseudoprimes to Twelve Prime Bases". + */ + /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */ + if ((err = mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 12; + } else { + /* 0x2be6951adc5b22410a5fd = 3317044064679887385961981 */ + if ((err = mp_read_radix(&b, "2be6951adc5b22410a5fd", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 13; + } else { + err = MP_VAL; + goto LBL_B; + } + } + + /* we did bases 2 and 3 already, skip them */ + for (ix = 2; ix < p_max; ix++) { + mp_set(&b, s_mp_prime_tab[ix]); + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + } + } + /* + Do "t" M-R tests with random bases between 3 and "a". + See Fips 186.4 p. 126ff + */ + else if (t > 0) { + unsigned int mask; + int size_a; + + /* + * The mp_digit's have a defined bit-size but the size of the + * array a.dp is a simple 'int' and this library can not assume full + * compliance to the current C-standard (ISO/IEC 9899:2011) because + * it gets used for small embedded processors, too. Some of those MCUs + * have compilers that one cannot call standard compliant by any means. + * Hence the ugly type-fiddling in the following code. + */ + size_a = mp_count_bits(a); + mask = (1u << s_floor_ilog2(size_a)) - 1u; + /* + Assuming the General Rieman hypothesis (never thought to write that in a + comment) the upper bound can be lowered to 2*(log a)^2. + E. Bach, "Explicit bounds for primality testing and related problems," + Math. Comp. 55 (1990), 355-380. + + size_a = (size_a/10) * 7; + len = 2 * (size_a * size_a); + + E.g.: a number of size 2^2048 would be reduced to the upper limit + + floor(2048/10)*7 = 1428 + 2 * 1428^2 = 4078368 + + (would have been ~4030331.9962 with floats and natural log instead) + That number is smaller than 2^28, the default bit-size of mp_digit. + */ + + /* + How many tests, you might ask? Dana Jacobsen of Math::Prime::Util fame + does exactly 1. In words: one. Look at the end of _GMP_is_prime() in + Math-Prime-Util-GMP-0.50/primality.c if you do not believe it. + + The function mp_rand() goes to some length to use a cryptographically + good PRNG. That also means that the chance to always get the same base + in the loop is non-zero, although very low. + If the BPSW test and/or the additional Frobenious test have been + performed instead of just the Miller-Rabin test with the bases 2 and 3, + a single extra test should suffice, so such a very unlikely event + will not do much harm. + + To preemptively answer the dangling question: no, a witness does not + need to be prime. + */ + for (ix = 0; ix < t; ix++) { + unsigned int fips_rand; + int len; + + /* mp_rand() guarantees the first digit to be non-zero */ + if ((err = mp_rand(&b, 1)) != MP_OKAY) { + goto LBL_B; + } + /* + * Reduce digit before casting because mp_digit might be bigger than + * an unsigned int and "mask" on the other side is most probably not. + */ + fips_rand = (unsigned int)(b.dp[0] & (mp_digit) mask); + if (fips_rand > (unsigned int)(INT_MAX - MP_DIGIT_BIT)) { + len = INT_MAX / MP_DIGIT_BIT; + } else { + len = (((int)fips_rand + MP_DIGIT_BIT) / MP_DIGIT_BIT); + } + /* Unlikely. */ + if (len < 0) { + ix--; + continue; + } + if ((err = mp_rand(&b, len)) != MP_OKAY) { + goto LBL_B; + } + /* + * That number might got too big and the witness has to be + * smaller than "a" + */ + len = mp_count_bits(&b); + if (len >= size_a) { + len = (len - size_a) + 1; + if ((err = mp_div_2d(&b, len, &b, NULL)) != MP_OKAY) { + goto LBL_B; + } + } + /* Although the chance for b <= 3 is miniscule, try again. */ + if (mp_cmp_d(&b, 3uL) != MP_GT) { + ix--; + continue; + } + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + } + } + + /* passed the test */ + *result = true; +LBL_B: + mp_clear(&b); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_miller_rabin.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_miller_rabin.c new file mode 100644 index 0000000..4c23a9f --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_miller_rabin.c @@ -0,0 +1,91 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_MILLER_RABIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, bool *result) +{ + mp_int n1, y, r; + mp_err err; + int s, j; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != MP_GT) { + return MP_VAL; + } + + /* get n1 = a - 1 */ + if ((err = mp_init_copy(&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d(&n1, 1uL, &n1)) != MP_OKAY) { + goto LBL_ERR1; + } + + /* set 2**s * r = n1 */ + if ((err = mp_init_copy(&r, &n1)) != MP_OKAY) { + goto LBL_ERR1; + } + + /* count the number of least significant bits + * which are zero + */ + s = mp_cnt_lsb(&r); + + /* now divide n - 1 by 2**s */ + if ((err = mp_div_2d(&r, s, &r, NULL)) != MP_OKAY) { + goto LBL_ERR2; + } + + /* compute y = b**r mod a */ + if ((err = mp_init(&y)) != MP_OKAY) { + goto LBL_ERR2; + } + if ((err = mp_exptmod(b, &r, a, &y)) != MP_OKAY) { + goto LBL_END; + } + + /* if y != 1 and y != n1 do */ + if ((mp_cmp_d(&y, 1uL) != MP_EQ) && (mp_cmp(&y, &n1) != MP_EQ)) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && (mp_cmp(&y, &n1) != MP_EQ)) { + if ((err = mp_sqrmod(&y, a, &y)) != MP_OKAY) { + goto LBL_END; + } + + /* if y == 1 then composite */ + if (mp_cmp_d(&y, 1uL) == MP_EQ) { + *result = false; + goto LBL_END; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp(&y, &n1) != MP_EQ) { + *result = false; + goto LBL_END; + } + } + + /* probably prime now */ + *result = true; + +LBL_END: + mp_clear(&y); +LBL_ERR2: + mp_clear(&r); +LBL_ERR1: + mp_clear(&n1); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_next_prime.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_next_prime.c new file mode 100644 index 0000000..6faa08d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_next_prime.c @@ -0,0 +1,127 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_NEXT_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = true means the prime must be congruent to 3 mod 4 + */ +mp_err mp_prime_next_prime(mp_int *a, int t, bool bbs_style) +{ + int x; + mp_err err; + bool res = false; + mp_digit res_tab[MP_PRIME_TAB_SIZE], kstep; + mp_int b; + + /* force positive */ + a->sign = MP_ZPOS; + + /* simple algo if a is less than the largest prime in the table */ + if (mp_cmp_d(a, s_mp_prime_tab[MP_PRIME_TAB_SIZE-1]) == MP_LT) { + /* find which prime it is bigger than "a" */ + for (x = 0; x < MP_PRIME_TAB_SIZE; x++) { + mp_ord cmp = mp_cmp_d(a, s_mp_prime_tab[x]); + if (cmp == MP_EQ) { + continue; + } + if (cmp != MP_GT) { + if ((bbs_style) && ((s_mp_prime_tab[x] & 3u) != 3u)) { + /* try again until we get a prime congruent to 3 mod 4 */ + continue; + } else { + mp_set(a, s_mp_prime_tab[x]); + return MP_OKAY; + } + } + } + /* fall through to the sieve */ + } + + /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ + kstep = bbs_style ? 4 : 2; + + /* at this point we will use a combination of a sieve and Miller-Rabin */ + + if (bbs_style) { + /* if a mod 4 != 3 subtract the correct value to make it so */ + if ((a->dp[0] & 3u) != 3u) { + if ((err = mp_sub_d(a, (a->dp[0] & 3u) + 1u, a)) != MP_OKAY) { + return err; + } + } + } else { + if (mp_iseven(a)) { + /* force odd */ + if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { + return err; + } + } + } + + /* generate the restable */ + for (x = 1; x < MP_PRIME_TAB_SIZE; x++) { + if ((err = mp_mod_d(a, s_mp_prime_tab[x], res_tab + x)) != MP_OKAY) { + return err; + } + } + + /* init temp used for Miller-Rabin Testing */ + if ((err = mp_init(&b)) != MP_OKAY) { + return err; + } + + for (;;) { + mp_digit step = 0; + bool y; + /* skip to the next non-trivially divisible candidate */ + do { + /* y == true if any residue was zero [e.g. cannot be prime] */ + y = false; + + /* increase step to next candidate */ + step += kstep; + + /* compute the new residue without using division */ + for (x = 1; x < MP_PRIME_TAB_SIZE; x++) { + /* add the step to each residue */ + res_tab[x] += kstep; + + /* subtract the modulus [instead of using division] */ + if (res_tab[x] >= s_mp_prime_tab[x]) { + res_tab[x] -= s_mp_prime_tab[x]; + } + + /* set flag if zero */ + if (res_tab[x] == 0u) { + y = true; + } + } + } while (y && (step < (((mp_digit)1 << MP_DIGIT_BIT) - kstep))); + + /* add the step */ + if ((err = mp_add_d(a, step, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* if didn't pass sieve and step == MP_MAX then skip test */ + if (y && (step >= (((mp_digit)1 << MP_DIGIT_BIT) - kstep))) { + continue; + } + + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + if (res) { + break; + } + } + +LBL_ERR: + mp_clear(&b); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rabin_miller_trials.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rabin_miller_trials.c new file mode 100644 index 0000000..9f66f8d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rabin_miller_trials.c @@ -0,0 +1,48 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_RABIN_MILLER_TRIALS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static const struct { + int k, t; +} sizes[] = { + { 80, -1 }, /* Use deterministic algorithm for size <= 80 bits */ + { 81, 37 }, /* max. error = 2^(-96)*/ + { 96, 32 }, /* max. error = 2^(-96)*/ + { 128, 40 }, /* max. error = 2^(-112)*/ + { 160, 35 }, /* max. error = 2^(-112)*/ + { 256, 27 }, /* max. error = 2^(-128)*/ + { 384, 16 }, /* max. error = 2^(-128)*/ + { 512, 18 }, /* max. error = 2^(-160)*/ + { 768, 11 }, /* max. error = 2^(-160)*/ + { 896, 10 }, /* max. error = 2^(-160)*/ + { 1024, 12 }, /* max. error = 2^(-192)*/ + { 1536, 8 }, /* max. error = 2^(-192)*/ + { 2048, 6 }, /* max. error = 2^(-192)*/ + { 3072, 4 }, /* max. error = 2^(-192)*/ + { 4096, 5 }, /* max. error = 2^(-256)*/ + { 5120, 4 }, /* max. error = 2^(-256)*/ + { 6144, 4 }, /* max. error = 2^(-256)*/ + { 8192, 3 }, /* max. error = 2^(-256)*/ + { 9216, 3 }, /* max. error = 2^(-256)*/ + { 10240, 2 } /* For bigger keysizes use always at least 2 Rounds */ +}; + +/* returns # of RM trials required for a given bit size */ +int mp_prime_rabin_miller_trials(int size) +{ + int x; + + for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { + if (sizes[x].k == size) { + return sizes[x].t; + } + if (sizes[x].k > size) { + return (x == 0) ? sizes[0].t : sizes[x - 1].t; + } + } + return sizes[x-1].t; +} + + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rand.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rand.c new file mode 100644 index 0000000..5351aef --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_rand.c @@ -0,0 +1,123 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ + +/* This is possibly the mother of all prime generation functions, muahahahahaha! */ +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) +{ + uint8_t *tmp, maskAND, maskOR_msb, maskOR_lsb; + int bsize, maskOR_msb_offset; + bool res; + mp_err err; + + /* sanity check the input */ + if (size <= 1) { + return MP_VAL; + } + + /* MP_PRIME_SAFE implies MP_PRIME_BBS */ + if ((flags & MP_PRIME_SAFE) != 0) { + flags |= MP_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3) + ((size&7)?1:0); + + /* we need a buffer of bsize bytes */ + tmp = (uint8_t *) MP_MALLOC((size_t)bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = ((size&7) == 0) ? 0xFFu : (uint8_t)(0xFFu >> (8 - (size & 7))); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; + if ((flags & MP_PRIME_2MSB_ON) != 0) { + maskOR_msb |= (uint8_t)(0x80 >> ((9 - size) & 7)); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 1u; + if ((flags & MP_PRIME_BBS) != 0) { + maskOR_lsb |= 3u; + } + + do { + /* read the bytes */ + if ((err = s_mp_rand_source(tmp, (size_t)bsize)) != MP_OKAY) { + goto LBL_ERR; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= (uint8_t)(1 << ((size - 1) & 7)); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/ + if ((err = mp_from_ubin(a, tmp, (size_t)bsize)) != MP_OKAY) { + goto LBL_ERR; + } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + if (!res) { + continue; + } + + if ((flags & MP_PRIME_SAFE) != 0) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2(a, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + } + } while (!res); + + if ((flags & MP_PRIME_SAFE) != 0) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) { + goto LBL_ERR; + } + } + + err = MP_OKAY; +LBL_ERR: + MP_FREE_BUF(tmp, (size_t)bsize); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_strong_lucas_selfridge.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_strong_lucas_selfridge.c new file mode 100644 index 0000000..ffbd9d3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_prime_strong_lucas_selfridge.c @@ -0,0 +1,281 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_STRONG_LUCAS_SELFRIDGE_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +/* + * multiply bigint a with int d and put the result in c + * Like mp_mul_d() but with a signed long as the small input + */ +static mp_err s_mul_si(const mp_int *a, int32_t d, mp_int *c) +{ + mp_int t; + mp_err err; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + /* + * mp_digit might be smaller than a long, which excludes + * the use of mp_mul_d() here. + */ + mp_set_i32(&t, d); + err = mp_mul(a, &t, c); + mp_clear(&t); + return err; +} +/* + Strong Lucas-Selfridge test. + returns true if it is a strong L-S prime, false if it is composite + + Code ported from Thomas Ray Nicely's implementation of the BPSW test + at http://www.trnicely.net/misc/bpsw.html + + Freeware copyright (C) 2016 Thomas R. Nicely . + Released into the public domain by the author, who disclaims any legal + liability arising from its use + + The multi-line comments are made by Thomas R. Nicely and are copied verbatim. + Additional comments marked "CZ" (without the quotes) are by the code-portist. + + (If that name sounds familiar, he is the guy who found the fdiv bug in the + Pentium (P5x, I think) Intel processor) +*/ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result) +{ + /* CZ TODO: choose better variable names! */ + mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz; + int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits; + mp_err err; + bool oddness; + + *result = false; + /* + Find the first element D in the sequence {5, -7, 9, -11, 13, ...} + such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory + indicates that, if N is not a perfect square, D will "nearly + always" be "small." Just in case, an overflow trap for D is + included. + */ + + if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz, + NULL)) != MP_OKAY) { + return err; + } + + D = 5; + sign = 1; + + for (;;) { + Ds = sign * D; + sign = -sign; + mp_set_u32(&Dz, (uint32_t)D); + if ((err = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) goto LBL_LS_ERR; + + /* if 1 < GCD < N then N is composite with factor "D", and + Jacobi(D,N) is technically undefined (but often returned + as zero). */ + if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) { + goto LBL_LS_ERR; + } + if (Ds < 0) { + Dz.sign = MP_NEG; + } + if ((err = mp_kronecker(&Dz, a, &J)) != MP_OKAY) goto LBL_LS_ERR; + + if (J == -1) { + break; + } + D += 2; + + if (D > (INT_MAX - 2)) { + err = MP_VAL; + goto LBL_LS_ERR; + } + } + + + + P = 1; /* Selfridge's choice */ + Q = (1 - Ds) / 4; /* Required so D = P*P - 4*Q */ + + /* NOTE: The conditions (a) N does not divide Q, and + (b) D is square-free or not a perfect square, are included by + some authors; e.g., "Prime numbers and computer methods for + factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston), + p. 130. For this particular application of Lucas sequences, + these conditions were found to be immaterial. */ + + /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the + odd positive integer d and positive integer s for which + N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test). + The strong Lucas-Selfridge test then returns N as a strong + Lucas probable prime (slprp) if any of the following + conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0, + V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0 + (all equalities mod N). Thus d is the highest index of U that + must be computed (since V_2m is independent of U), compared + to U_{N+1} for the standard Lucas-Selfridge test; and no + index of V beyond (N+1)/2 is required, just as in the + standard Lucas-Selfridge test. However, the quantity Q^d must + be computed for use (if necessary) in the latter stages of + the test. The result is that the strong Lucas-Selfridge test + has a running time only slightly greater (order of 10 %) than + that of the standard Lucas-Selfridge test, while producing + only (roughly) 30 % as many pseudoprimes (and every strong + Lucas pseudoprime is also a standard Lucas pseudoprime). Thus + the evidence indicates that the strong Lucas-Selfridge test is + more effective than the standard Lucas-Selfridge test, and a + Baillie-PSW test based on the strong Lucas-Selfridge test + should be more reliable. */ + + if ((err = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) goto LBL_LS_ERR; + s = mp_cnt_lsb(&Np1); + + /* CZ + * This should round towards zero because + * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp() + * and mp_div_2d() is equivalent. Additionally: + * dividing an even number by two does not produce + * any leftovers. + */ + if ((err = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) goto LBL_LS_ERR; + /* We must now compute U_d and V_d. Since d is odd, the accumulated + values U and V are initialized to U_1 and V_1 (if the target + index were even, U and V would be initialized instead to U_0=0 + and V_0=2). The values of U_2m and V_2m are also initialized to + U_1 and V_1; the FOR loop calculates in succession U_2 and V_2, + U_4 and V_4, U_8 and V_8, etc. If the corresponding bits + (1, 2, 3, ...) of t are on (the zero bit having been accounted + for in the initialization of U and V), these values are then + combined with the previous totals for U and V, using the + composition formulas for addition of indices. */ + + mp_set(&Uz, 1uL); /* U=U_1 */ + mp_set(&Vz, (mp_digit)P); /* V=V_1 */ + mp_set(&U2mz, 1uL); /* U_1 */ + mp_set(&V2mz, (mp_digit)P); /* V_1 */ + + mp_set_i32(&Qmz, Q); + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + /* Initializes calculation of Q^d */ + mp_set_i32(&Qkdz, Q); + + Nbits = mp_count_bits(&Dz); + + for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */ + /* Formulas for doubling of indices (carried out mod N). Note that + * the indices denoted as "2m" are actually powers of 2, specifically + * 2^(ul-1) beginning each loop and 2^ul ending each loop. + * + * U_2m = U_m*V_m + * V_2m = V_m*V_m - 2*Q^m + */ + + if ((err = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Must calculate powers of Q for use in V_2m, also for Q^d later */ + if ((err = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + + /* prevents overflow */ /* CZ still necessary without a fixed prealloc'd mem.? */ + if ((err = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + + if (s_mp_get_bit(&Dz, u)) { + /* Formulas for addition of indices (carried out mod N); + * + * U_(m+n) = (U_m*V_n + U_n*V_m)/2 + * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2 + * + * Be careful with division by 2 (mod N)! + */ + if ((err = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = s_mul_si(&T4z, Ds, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isodd(&Uz)) { + if ((err = mp_add(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + /* CZ + * This should round towards negative infinity because + * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp(). + * But mp_div_2() does not do so, it is truncating instead. + */ + oddness = mp_isodd(&Uz); + if ((err = mp_div_2(&Uz, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isneg(&Uz) && oddness) { + if ((err = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isodd(&Vz)) { + if ((err = mp_add(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + oddness = mp_isodd(&Vz); + if ((err = mp_div_2(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isneg(&Vz) && oddness) { + if ((err = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_mod(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Calculating Q^d for later use */ + if ((err = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } + + /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a + strong Lucas pseudoprime. */ + if (mp_iszero(&Uz) || mp_iszero(&Vz)) { + *result = true; + goto LBL_LS_ERR; + } + + /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed., + 1995/6) omits the condition V0 on p.142, but includes it on + p. 130. The condition is NECESSARY; otherwise the test will + return false negatives---e.g., the primes 29 and 2000029 will be + returned as composite. */ + + /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d} + by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of + these are congruent to 0 mod N, then N is a prime or a strong + Lucas pseudoprime. */ + + /* Initialize 2*Q^(d*2^r) for V_2m */ + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + + for (r = 1; r < s; r++) { + if ((err = mp_sqr(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_iszero(&Vz)) { + *result = true; + goto LBL_LS_ERR; + } + /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */ + if (r < (s - 1)) { + if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } +LBL_LS_ERR: + mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL); + return err; +} +#endif +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size.c new file mode 100644 index 0000000..ca08438 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size.c @@ -0,0 +1,34 @@ +#include "tommath_private.h" +#ifdef MP_RADIX_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* returns size of ASCII representation */ +mp_err mp_radix_size(const mp_int *a, int radix, size_t *size) +{ + mp_err err; + mp_int a_; + int b; + + /* make sure the radix is in range */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + if (mp_iszero(a)) { + *size = 2; + return MP_OKAY; + } + + a_ = *a; + a_.sign = MP_ZPOS; + if ((err = mp_log_n(&a_, radix, &b)) != MP_OKAY) { + return err; + } + + /* mp_ilogb truncates to zero, hence we need one extra put on top and one for `\0`. */ + *size = (size_t)b + 2U + (mp_isneg(a) ? 1U : 0U); + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size_overestimate.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size_overestimate.c new file mode 100644 index 0000000..3fe81d7 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_radix_size_overestimate.c @@ -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 diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand.c new file mode 100644 index 0000000..1936475 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand.c @@ -0,0 +1,39 @@ +#include "tommath_private.h" +#ifdef MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_rand(mp_int *a, int digits) +{ + int i; + mp_err err; + + mp_zero(a); + + if (digits <= 0) { + return MP_OKAY; + } + + if ((err = mp_grow(a, digits)) != MP_OKAY) { + return err; + } + + if ((err = s_mp_rand_source(a->dp, (size_t)digits * sizeof(mp_digit))) != MP_OKAY) { + return err; + } + + /* TODO: We ensure that the highest digit is nonzero. Should this be removed? */ + while ((a->dp[digits - 1] & MP_MASK) == 0u) { + if ((err = s_mp_rand_source(a->dp + digits - 1, sizeof(mp_digit))) != MP_OKAY) { + return err; + } + } + + a->used = digits; + for (i = 0; i < digits; ++i) { + a->dp[i] &= MP_MASK; + } + + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand_source.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand_source.c new file mode 100644 index 0000000..e9e8769 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rand_source.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform; + +void mp_rand_source(mp_err(*source)(void *out, size_t size)) +{ + s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_read_radix.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_read_radix.c new file mode 100644 index 0000000..28e6eb6 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_read_radix.c @@ -0,0 +1,69 @@ +#include "tommath_private.h" +#ifdef MP_READ_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* read a string [ASCII] in a given radix */ +mp_err mp_read_radix(mp_int *a, const char *str, int radix) +{ + mp_err err; + mp_sign sign = MP_ZPOS; + + /* make sure the radix is ok */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + sign = MP_NEG; + } + + /* set the integer to the default of zero */ + mp_zero(a); + + /* process each digit of the string */ + while (*str != '\0') { + /* if the radix <= 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + uint8_t y; + char ch = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str; + unsigned pos = (unsigned)(ch - '+'); + if (MP_RADIX_MAP_REVERSE_SIZE <= pos) { + break; + } + y = s_mp_radix_map_reverse[pos]; + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y >= radix) { + break; + } + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + ++str; + } + + /* if an illegal character was found, fail. */ + if ((*str != '\0') && (*str != '\r') && (*str != '\n')) { + return MP_VAL; + } + + /* set the sign only if a != 0 */ + if (!mp_iszero(a)) { + a->sign = sign; + } + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce.c new file mode 100644 index 0000000..b6fae55 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce.c @@ -0,0 +1,83 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) +{ + mp_int q; + mp_err err; + int um = m->used; + + /* q = x */ + if ((err = mp_init_copy(&q, x)) != MP_OKAY) { + return err; + } + + /* q1 = x / b**(k-1) */ + mp_rshd(&q, um - 1); + + /* according to HAC this optimization is ok */ + if ((mp_digit)um > ((mp_digit)1 << (MP_DIGIT_BIT - 1))) { + if ((err = mp_mul(&q, mu, &q)) != MP_OKAY) { + goto LBL_ERR; + } + } else if (MP_HAS(S_MP_MUL_HIGH)) { + if ((err = s_mp_mul_high(&q, mu, &q, um)) != MP_OKAY) { + goto LBL_ERR; + } + } else if (MP_HAS(S_MP_MUL_HIGH_COMBA)) { + if ((err = s_mp_mul_high_comba(&q, mu, &q, um)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + err = MP_VAL; + goto LBL_ERR; + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd(&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((err = mp_mod_2d(x, MP_DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((err = s_mp_mul(&q, m, &q, um + 1)) != MP_OKAY) { + goto LBL_ERR; + } + + /* x = x - q */ + if ((err = mp_sub(x, &q, x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d(x, 0uL) == MP_LT) { + mp_set(&q, 1uL); + if ((err = mp_lshd(&q, um + 1)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(x, &q, x)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* Back off if it's too big */ + while (mp_cmp(x, m) != MP_LT) { + if ((err = s_mp_sub(x, m, x)) != MP_OKAY) { + goto LBL_ERR; + } + } + +LBL_ERR: + mp_clear(&q); + + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k.c new file mode 100644 index 0000000..e635f5b --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k.c @@ -0,0 +1,49 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces a modulo n where n is of the form 2**p - d */ +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) +{ + mp_int q; + mp_err err; + int p; + + if ((err = mp_init(&q)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(n); + for (;;) { + /* q = a/2**p, a = a mod 2**p */ + if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (d != 1u) { + /* q = q * d */ + if ((err = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* a = a + q */ + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_cmp_mag(a, n) == MP_LT) { + break; + } + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } + } + +LBL_ERR: + mp_clear(&q); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_l.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_l.c new file mode 100644 index 0000000..31d9a18 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_l.c @@ -0,0 +1,52 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces a modulo n where n is of the form 2**p - d + This differs from reduce_2k since "d" can be larger + than a single digit. +*/ +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) +{ + mp_int q; + mp_err err; + int p; + + if ((err = mp_init(&q)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(n); + + for (;;) { + /* q = a/2**p, a = a mod 2**p */ + if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* q = q * d */ + if ((err = mp_mul(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; + } + + /* a = a + q */ + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_cmp_mag(a, n) == MP_LT) { + break; + } + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } + + } + +LBL_ERR: + mp_clear(&q); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup.c new file mode 100644 index 0000000..51f8841 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup.c @@ -0,0 +1,30 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) +{ + mp_err err; + mp_int tmp; + + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; + } + + if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + + *d = tmp.dp[0]; + +LBL_ERR: + mp_clear(&tmp); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup_l.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup_l.c new file mode 100644 index 0000000..b647c9d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_2k_setup_l.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_SETUP_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) +{ + mp_err err; + mp_int tmp; + + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; + } + + if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto LBL_ERR; + } + +LBL_ERR: + mp_clear(&tmp); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k.c new file mode 100644 index 0000000..d549633 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k.c @@ -0,0 +1,41 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_IS_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if mp_reduce_2k can be used */ +bool mp_reduce_is_2k(const mp_int *a) +{ + if (mp_iszero(a)) { + return false; + } else if (a->used == 1) { + return true; + } else if (a->used > 1) { + int ix, iy, iw = 1; + mp_digit iz; + /* Algorithm as implemented does not work if the least significant digit is zero */ + iz = a->dp[0] & MP_MASK; + if (iz == 0u) { + return false; + } + + iy = mp_count_bits(a); + iz = 1; + /* Test every bit from the second digit up, must be 1 */ + for (ix = MP_DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0u) { + return false; + } + iz <<= 1; + if (iz > MP_DIGIT_MAX) { + ++iw; + iz = 1; + } + } + return true; + } else { + return true; + } +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k_l.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k_l.c new file mode 100644 index 0000000..101b4a1 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_is_2k_l.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_IS_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if reduce_2k_l can be used */ +bool mp_reduce_is_2k_l(const mp_int *a) +{ + if (mp_iszero(a)) { + return false; + } else if (a->used == 1) { + return true; + } else if (a->used > 1) { + /* if more than half of the digits are -1 we're sold */ + int ix, iy; + for (iy = ix = 0; ix < a->used; ix++) { + if (a->dp[ix] == MP_DIGIT_MAX) { + ++iy; + } + } + return (iy >= (a->used/2)); + } else { + return false; + } +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_setup.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_setup.c new file mode 100644 index 0000000..2ce5b96 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_reduce_setup.c @@ -0,0 +1,17 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calculates the value required in "a" + */ +mp_err mp_reduce_setup(mp_int *a, const mp_int *b) +{ + mp_err err; + if ((err = mp_2expt(a, b->used * 2 * MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + return mp_div(a, b, a, NULL); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_root_n.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_root_n.c new file mode 100644 index 0000000..d904df8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_root_n.c @@ -0,0 +1,141 @@ +#include "tommath_private.h" +#ifdef MP_ROOT_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* find the n'th root of an integer + * + * Result found such that (c)**b <= a and (c+1)**b > a + * + * This algorithm uses Newton's approximation + * x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where + * each step involves a fair bit. + */ +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) +{ + mp_int t1, t2, t3, a_; + int ilog2; + mp_err err; + + if (b < 0 || (unsigned)b > (unsigned)MP_DIGIT_MAX) { + return MP_VAL; + } + + /* input must be positive if b is even */ + if (((b & 1) == 0) && mp_isneg(a)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { + return err; + } + + /* if a is negative fudge the sign but keep track */ + a_ = *a; + a_.sign = MP_ZPOS; + + /* Compute seed: 2^(log_2(n)/b + 2)*/ + ilog2 = mp_count_bits(a); + + /* + If "b" is larger than INT_MAX it is also larger than + log_2(n) because the bit-length of the "n" is measured + with an int and hence the root is always < 2 (two). + */ + if (b > INT_MAX/2) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + + /* "b" is smaller than INT_MAX, we can cast safely */ + if (ilog2 < b) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + ilog2 = ilog2 / b; + if (ilog2 == 0) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + /* Start value must be larger than root */ + ilog2 += 2; + if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR; + do { + /* t1 = t2 */ + if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((err = mp_expt_n(&t1, b - 1, &t3)) != MP_OKAY) goto LBL_ERR; + + /* numerator */ + /* t2 = t1**b */ + if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1**b - a */ + if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR; + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((err = mp_mul_d(&t3, (mp_digit)b, &t3)) != MP_OKAY) goto LBL_ERR; + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR; + + /* + Number of rounds is at most log_2(root). If it is more it + got stuck, so break out of the loop and do the rest manually. + */ + if (ilog2-- == 0) { + break; + } + } while (mp_cmp(&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + /* Loop beneath can overshoot by one if found root is smaller than actual root */ + for (;;) { + mp_ord cmp; + if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + cmp = mp_cmp(&t2, &a_); + if (cmp == MP_EQ) { + err = MP_OKAY; + goto LBL_ERR; + } + if (cmp == MP_LT) { + if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + /* correct overshoot from above or from recurrence */ + for (;;) { + if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + if (mp_cmp(&t2, &a_) == MP_GT) { + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + + /* set the result */ + mp_exch(&t1, c); + + /* set the sign of the result */ + c->sign = a->sign; + +LBL_ERR: + mp_clear_multi(&t1, &t2, &t3, NULL); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rshd.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rshd.c new file mode 100644 index 0000000..3f0a941 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_rshd.c @@ -0,0 +1,43 @@ +#include "tommath_private.h" +#ifdef MP_RSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right a certain amount of digits */ +void mp_rshd(mp_int *a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero(a); + return; + } + + /* shift the digits down. + * this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + a->dp[x] = a->dp[x + b]; + } + + /* zero the top digits */ + s_mp_zero_digs(a->dp + a->used - b, b); + + /* remove excess digits */ + a->used -= b; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sbin_size.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sbin_size.c new file mode 100644 index 0000000..2f40df3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sbin_size.c @@ -0,0 +1,11 @@ +#include "tommath_private.h" +#ifdef MP_SBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an signed equivalent */ +size_t mp_sbin_size(const mp_int *a) +{ + return 1u + mp_ubin_size(a); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set.c new file mode 100644 index 0000000..bc0c4da --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b) +{ + int oldused = a->used; + a->dp[0] = b & MP_MASK; + a->sign = MP_ZPOS; + a->used = (a->dp[0] != 0u) ? 1 : 0; + s_mp_zero_digs(a->dp + a->used, oldused - a->used); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_double.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_double.c new file mode 100644 index 0000000..0ede359 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_double.c @@ -0,0 +1,47 @@ +#include "tommath_private.h" +#ifdef MP_SET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if defined(MP_HAS_SET_DOUBLE) +mp_err mp_set_double(mp_int *a, double b) +{ + uint64_t frac; + int exp; + mp_err err; + union { + double dbl; + uint64_t bits; + } cast; + cast.dbl = b; + + exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu); + frac = (cast.bits & (((uint64_t)1 << 52) - (uint64_t)1)) | ((uint64_t)1 << 52); + + if (exp == 0x7FF) { /* +-inf, NaN */ + return MP_VAL; + } + exp -= 1023 + 52; + + mp_set_u64(a, frac); + + err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a); + if (err != MP_OKAY) { + return err; + } + + if (((cast.bits >> 63) != 0u) && !mp_iszero(a)) { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#else +/* pragma message() not supported by several compilers (in mostly older but still used versions) */ +# ifdef _MSC_VER +# pragma message("mp_set_double implementation is only available on platforms with IEEE754 floating point format") +# else +# warning "mp_set_double implementation is only available on platforms with IEEE754 floating point format" +# endif +#endif +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i32.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i32.c new file mode 100644 index 0000000..123613e --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i32, mp_set_u32, int32_t, uint32_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i64.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i64.c new file mode 100644 index 0000000..4635ca3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i64, mp_set_u64, int64_t, uint64_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_l.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_l.c new file mode 100644 index 0000000..411f6eb --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_l, mp_set_ul, long, unsigned long) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u32.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u32.c new file mode 100644 index 0000000..8ff84dc --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u32, uint32_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u64.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u64.c new file mode 100644 index 0000000..9acb1fe --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u64, uint64_t) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_ul.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_ul.c new file mode 100644 index 0000000..baf8e18 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_set_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_ul, unsigned long) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_shrink.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_shrink.c new file mode 100644 index 0000000..3d9b162 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_shrink.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef MP_SHRINK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shrink a bignum */ +mp_err mp_shrink(mp_int *a) +{ + int alloc = MP_MAX(MP_MIN_DIGIT_COUNT, a->used); + if (a->alloc != alloc) { + mp_digit *dp = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)alloc * sizeof(mp_digit)); + if (dp == NULL) { + return MP_MEM; + } + a->dp = dp; + a->alloc = alloc; + } + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_signed_rsh.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_signed_rsh.c new file mode 100644 index 0000000..3b7e232 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_signed_rsh.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_SIGNED_RSH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count with sign extension */ +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + if (!mp_isneg(a)) { + return mp_div_2d(a, b, c, NULL); + } + + if ((err = mp_add_d(a, 1uL, c)) != MP_OKAY) { + return err; + } + + err = mp_div_2d(c, b, c, NULL); + return (err == MP_OKAY) ? mp_sub_d(c, 1uL, c) : err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrmod.c new file mode 100644 index 0000000..bce2af0 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrmod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_SQRMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = a * a (mod b) */ +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + if ((err = mp_sqr(a, c)) != MP_OKAY) { + return err; + } + return mp_mod(c, b, c); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrt.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrt.c new file mode 100644 index 0000000..1a9dca7 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrt.c @@ -0,0 +1,67 @@ +#include "tommath_private.h" +#ifdef MP_SQRT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this function is less generic than mp_n_root, simpler and faster */ +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) +{ + mp_err err; + mp_int t1, t2; + + /* must be positive */ + if (mp_isneg(arg)) { + return MP_VAL; + } + + /* easy out */ + if (mp_iszero(arg)) { + mp_zero(ret); + return MP_OKAY; + } + + if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { + return err; + } + + if ((err = mp_init(&t2)) != MP_OKAY) { + goto LBL_ERR2; + } + + /* First approx. (not very bad for large arg) */ + mp_rshd(&t1, t1.used/2); + + /* t1 > 0 */ + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + /* And now t1 > sqrt(arg) */ + do { + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + /* t1 >= sqrt(arg) >= t2 at this point */ + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + mp_exch(&t1, ret); + +LBL_ERR1: + mp_clear(&t2); +LBL_ERR2: + mp_clear(&t1); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrtmod_prime.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrtmod_prime.c new file mode 100644 index 0000000..0fae1d0 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sqrtmod_prime.c @@ -0,0 +1,133 @@ +#include "tommath_private.h" +#ifdef MP_SQRTMOD_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Tonelli-Shanks algorithm + * https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm + * https://gmplib.org/list-archives/gmp-discuss/2013-April/005300.html + * + */ + +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) +{ + mp_err err; + int legendre; + /* The type is "int" because of the types in the mp_int struct. + Don't forget to change them here when you change them there! */ + int S, M, i; + mp_int t1, C, Q, Z, T, R, two; + + /* first handle the simple cases */ + if (mp_cmp_d(n, 0uL) == MP_EQ) { + mp_zero(ret); + return MP_OKAY; + } + /* "prime" must be odd and > 2 */ + if (mp_iseven(prime) || (mp_cmp_d(prime, 3uL) == MP_LT)) return MP_VAL; + if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err; + /* n \not\cong 0 (mod p) and n \cong r^2 (mod p) for some r \in N^+ */ + if (legendre != 1) return MP_VAL; + + if ((err = mp_init_multi(&t1, &C, &Q, &Z, &T, &R, &two, NULL)) != MP_OKAY) { + return err; + } + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: err = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + /* x%4 == x&3 for x in N and x>0 */ + if ((prime->dp[0] & 3u) == 3u) { + if ((err = mp_add_d(prime, 1uL, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_exptmod(n, &t1, prime, ret)) != MP_OKAY) goto LBL_END; + err = MP_OKAY; + goto LBL_END; + } + + /* NOW: Tonelli-Shanks algorithm */ + + /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ + if ((err = mp_copy(prime, &Q)) != MP_OKAY) goto LBL_END; + if ((err = mp_sub_d(&Q, 1uL, &Q)) != MP_OKAY) goto LBL_END; + /* Q = prime - 1 */ + S = 0; + /* S = 0 */ + while (mp_iseven(&Q)) { + if ((err = mp_div_2(&Q, &Q)) != MP_OKAY) goto LBL_END; + /* Q = Q / 2 */ + S++; + /* S = S + 1 */ + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + mp_set(&Z, 2uL); + /* Z = 2 */ + for (;;) { + if ((err = mp_kronecker(&Z, prime, &legendre)) != MP_OKAY) goto LBL_END; + /* If "prime" (p) is an odd prime Jacobi(k|p) = 0 for k \cong 0 (mod p) */ + /* but there is at least one non-quadratic residue before k>=p if p is an odd prime. */ + if (legendre == 0) { + err = MP_VAL; + goto LBL_END; + } + if (legendre == -1) break; + if ((err = mp_add_d(&Z, 1uL, &Z)) != MP_OKAY) goto LBL_END; + /* Z = Z + 1 */ + } + + if ((err = mp_exptmod(&Z, &Q, prime, &C)) != MP_OKAY) goto LBL_END; + /* C = Z ^ Q mod prime */ + if ((err = mp_add_d(&Q, 1uL, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto LBL_END; + /* t1 = (Q + 1) / 2 */ + if ((err = mp_exptmod(n, &t1, prime, &R)) != MP_OKAY) goto LBL_END; + /* R = n ^ ((Q + 1) / 2) mod prime */ + if ((err = mp_exptmod(n, &Q, prime, &T)) != MP_OKAY) goto LBL_END; + /* T = n ^ Q mod prime */ + M = S; + /* M = S */ + mp_set(&two, 2uL); + + for (;;) { + if ((err = mp_copy(&T, &t1)) != MP_OKAY) goto LBL_END; + i = 0; + for (;;) { + if (mp_cmp_d(&t1, 1uL) == MP_EQ) break; + /* No exponent in the range 0 < i < M found + (M is at least 1 in the first round because "prime" > 2) */ + if (M == i) { + err = MP_VAL; + goto LBL_END; + } + if ((err = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto LBL_END; + i++; + } + if (i == 0) { + if ((err = mp_copy(&R, ret)) != MP_OKAY) goto LBL_END; + err = MP_OKAY; + goto LBL_END; + } + mp_set_i32(&t1, M - i - 1); + if ((err = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY) goto LBL_END; + /* t1 = 2 ^ (M - i - 1) */ + if ((err = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY) goto LBL_END; + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + if ((err = mp_sqrmod(&t1, prime, &C)) != MP_OKAY) goto LBL_END; + /* C = (t1 * t1) mod prime */ + if ((err = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY) goto LBL_END; + /* R = (R * t1) mod prime */ + if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto LBL_END; + /* T = (T * C) mod prime */ + M = i; + /* M = i */ + } + +LBL_END: + mp_clear_multi(&t1, &C, &Q, &Z, &T, &R, &two, NULL); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub.c new file mode 100644 index 0000000..1c95ad5 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub.c @@ -0,0 +1,36 @@ +#include "tommath_private.h" +#ifdef MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level subtraction (handles signs) */ +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) +{ + if (a->sign != b->sign) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = a->sign; + return s_mp_add(a, b, c); + } + + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* The second has a larger magnitude */ + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (!mp_isneg(a) ? MP_NEG : MP_ZPOS); + MP_EXCH(const mp_int *, a, b); + } else { + /* The first has a larger or equal magnitude */ + /* Copy the sign from the first */ + c->sign = a->sign; + } + return s_mp_sub(a, b, c); +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub_d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub_d.c new file mode 100644 index 0000000..b2b4d72 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_sub_d.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef MP_SUB_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit subtraction */ +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_err err; + int oldused; + + /* fast path for a == c */ + if (a == c) { + if ((c->sign == MP_NEG) && + ((c->dp[0] + b) < MP_DIGIT_MAX)) { + c->dp[0] += b; + return MP_OKAY; + } + if ((c->sign == MP_ZPOS) && + (c->dp[0] > b)) { + c->dp[0] -= b; + return MP_OKAY; + } + } + + /* grow c as required */ + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + mp_int a_ = *a; + a_.sign = MP_ZPOS; + err = mp_add_d(&a_, b, c); + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + oldused = c->used; + + /* if a <= b simply fix the single digit */ + if (((a->used == 1) && (a->dp[0] <= b)) || mp_iszero(a)) { + c->dp[0] = (a->used == 1) ? b - a->dp[0] : b; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + int i; + mp_digit mu = b; + + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract digits, mu is carry */ + for (i = 0; i < a->used; i++) { + c->dp[i] = a->dp[i] - mu; + mu = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u); + c->dp[i] &= MP_MASK; + } + } + + /* zero excess digits */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_submod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_submod.c new file mode 100644 index 0000000..6e4d4f7 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_submod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_SUBMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a - b (mod c) */ +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + if ((err = mp_sub(a, b, d)) != MP_OKAY) { + return err; + } + return mp_mod(d, c, d); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_radix.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_radix.c new file mode 100644 index 0000000..1e5e671 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_radix.c @@ -0,0 +1,95 @@ +#include "tommath_private.h" +#ifdef MP_TO_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reverse an array, used for radix code */ +static void s_reverse(char *s, size_t len) +{ + size_t ix = 0, iy = len - 1u; + while (ix < iy) { + MP_EXCH(char, s[ix], s[iy]); + ++ix; + --iy; + } +} + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto "size - 1" chars and always a NULL byte, puts the number of characters + * written, including the '\0', in "written". + */ +mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) +{ + size_t digs; + mp_err err; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of radix and size*/ + if (maxlen < 2u) { + return MP_BUF; + } + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a)) { + *str++ = '0'; + *str = '\0'; + if (written != NULL) { + *written = 2u; + } + return MP_OKAY; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + /* if it is negative output a - */ + if (mp_isneg(&t)) { + /* we have to reverse our digits later... but not the - sign!! */ + ++_s; + + /* store the flag and mark the number as positive */ + *str++ = '-'; + t.sign = MP_ZPOS; + + /* subtract a char */ + --maxlen; + } + digs = 0u; + while (!mp_iszero(&t)) { + if (--maxlen < 1u) { + /* no more room */ + err = MP_BUF; + goto LBL_ERR; + } + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + goto LBL_ERR; + } + *str++ = s_mp_radix_map[d]; + ++digs; + } + /* reverse the digits of the string. In this case _s points + * to the first digit [excluding the sign] of the number + */ + s_reverse(_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + digs++; + + if (written != NULL) { + *written = mp_isneg(a) ? (digs + 1u): digs; + } + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_sbin.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_sbin.c new file mode 100644 index 0000000..00884c3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_sbin.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef MP_TO_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in signed [big endian] format */ +mp_err mp_to_sbin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) +{ + mp_err err; + if (maxlen == 0u) { + return MP_BUF; + } + if ((err = mp_to_ubin(a, buf + 1, maxlen - 1u, written)) != MP_OKAY) { + return err; + } + if (written != NULL) { + (*written)++; + } + buf[0] = mp_isneg(a) ? (uint8_t)1 : (uint8_t)0; + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_ubin.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_ubin.c new file mode 100644 index 0000000..e8643cc --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_to_ubin.c @@ -0,0 +1,37 @@ +#include "tommath_private.h" +#ifdef MP_TO_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in unsigned [big endian] format */ +mp_err mp_to_ubin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) +{ + size_t x, count; + mp_err err; + mp_int t; + + count = mp_ubin_size(a); + if (count > maxlen) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + for (x = count; x --> 0u;) { + buf[x] = (uint8_t)(t.dp[0] & 255u); + if ((err = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + } + + if (written != NULL) { + *written = count; + } + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_ubin_size.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_ubin_size.c new file mode 100644 index 0000000..4f16404 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_ubin_size.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef MP_UBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an unsigned equivalent */ +size_t mp_ubin_size(const mp_int *a) +{ + size_t size = (size_t)mp_count_bits(a); + return (size / 8u) + (((size & 7u) != 0u) ? 1u : 0u); +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_unpack.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_unpack.c new file mode 100644 index 0000000..f0127fa --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_unpack.c @@ -0,0 +1,49 @@ +#include "tommath_private.h" +#ifdef MP_UNPACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_import. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, + mp_endian endian, size_t nails, const void *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j; + uint8_t odd_nail_mask; + + mp_zero(rop); + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0; i < odd_nails; ++i) { + odd_nail_mask ^= (uint8_t)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0; i < count; ++i) { + for (j = 0; j < (size - nail_bytes); ++j) { + uint8_t byte = *((const uint8_t *)op + + (((order == MP_MSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_BIG_ENDIAN) ? (j + nail_bytes) : (((size - 1u) - j) - nail_bytes))); + + if ((err = mp_mul_2d(rop, (j == 0u) ? (int)(8u - odd_nails) : 8, rop)) != MP_OKAY) { + return err; + } + + rop->dp[0] |= (j == 0u) ? (mp_digit)(byte & odd_nail_mask) : (mp_digit)byte; + rop->used += 1; + } + } + + mp_clamp(rop); + + return MP_OKAY; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_warray_free.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_warray_free.c new file mode 100644 index 0000000..f7470f8 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_warray_free.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_WARRAY_FREE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* static check that the multiplication won't overflow */ +MP_STATIC_ASSERT(warray_free_sz_does_not_overflow, (sizeof(mp_word) * MP_WARRAY) >= MP_WARRAY) + +static int s_warray_free(void) +{ + int ret = 0; + if (s_mp_warray.w_used) + return -2; + if (s_mp_warray.w_free) { + s_mp_zero_buf(s_mp_warray.w_free, sizeof(mp_word) * MP_WARRAY); + MP_FREE(s_mp_warray.w_free, sizeof(mp_word) * MP_WARRAY); + s_mp_warray.w_free = NULL; + } + return ret; +} + +int mp_warray_free(void) +{ + if (MP_HAS(MP_SMALL_STACK_SIZE)) return s_warray_free(); + return -1; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_xor.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_xor.c new file mode 100644 index 0000000..ff26419 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_xor.c @@ -0,0 +1,54 @@ +#include "tommath_private.h" +#ifdef MP_XOR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement xor */ +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + bool neg = (a->sign != b->sign); + + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (mp_isneg(a)) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (mp_isneg(b)) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x ^ y; + + /* convert to to sign-magnitude if negative */ + if (neg) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = (neg ? MP_NEG : MP_ZPOS); + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_zero.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_zero.c new file mode 100644 index 0000000..48b60e4 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/mp_zero.c @@ -0,0 +1,13 @@ +#include "tommath_private.h" +#ifdef MP_ZERO_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* set to zero */ +void mp_zero(mp_int *a) +{ + a->sign = MP_ZPOS; + s_mp_zero_digs(a->dp, a->used); + a->used = 0; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_add.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_add.c new file mode 100644 index 0000000..2bda2fe --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_add.c @@ -0,0 +1,70 @@ +#include "tommath_private.h" +#ifdef S_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) +{ + int oldused, min, max, i; + mp_digit u; + mp_err err; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used < b->used) { + MP_EXCH(const mp_int *, a, b); + } + + min = b->used; + max = a->used; + + /* init result */ + if ((err = mp_grow(c, max + 1)) != MP_OKAY) { + return err; + } + + /* get old used digit count and set new one */ + oldused = c->used; + c->used = max + 1; + + /* zero the carry */ + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + c->dp[i] = a->dp[i] + b->dp[i] + u; + + /* U = carry bit of T[i] */ + u = c->dp[i] >> (mp_digit)MP_DIGIT_BIT; + + /* take away carry bit from T[i] */ + c->dp[i] &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = A[i] + U */ + c->dp[i] = a->dp[i] + u; + + /* U = carry bit of T[i] */ + u = c->dp[i] >> (mp_digit)MP_DIGIT_BIT; + + /* take away carry bit from T[i] */ + c->dp[i] &= MP_MASK; + } + } + + /* add carry */ + c->dp[i] = u; + + /* clear digits above oldused */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_copy_digs.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_copy_digs.c new file mode 100644 index 0000000..4079c33 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_copy_digs.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef S_MP_COPY_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_USE_MEMOPS +# include +#endif + +void s_mp_copy_digs(mp_digit *d, const mp_digit *s, int digits) +{ +#ifdef MP_USE_MEMOPS + if (digits > 0) { + memcpy(d, s, (size_t)digits * sizeof(mp_digit)); + } +#else + while (digits-- > 0) { + *d++ = *s++; + } +#endif +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_3.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_3.c new file mode 100644 index 0000000..1cc6d3d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_3.c @@ -0,0 +1,64 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_3_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* divide by three (based on routine from MPI and the GMP manual) */ +mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w; + mp_digit b; + mp_err err; + int ix; + + /* b = 2**MP_DIGIT_BIT / 3 */ + b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3; + + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used; ix --> 0;) { + mp_word t; + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; + + if (w >= 3u) { + /* multiply w by [1/3] */ + t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT; + + /* now subtract 3 * [w/3] from w, to get the remainder */ + w -= t+t+t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3u) { + t += 1u; + w -= 3u; + } + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + /* [optional] store the remainder */ + if (d != NULL) { + *d = (mp_digit)w; + } + + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return MP_OKAY; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_recursive.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_recursive.c new file mode 100644 index 0000000..d719c4e --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_recursive.c @@ -0,0 +1,159 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_RECURSIVE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + Direct implementation of algorithms 1.8 "RecursiveDivRem" and 1.9 "UnbalancedDivision" + from: + + Brent, Richard P., and Paul Zimmermann. "Modern computer arithmetic" + Vol. 18. Cambridge University Press, 2010 + Available online at https://arxiv.org/pdf/1004.4710 + + pages 19ff. in the above online document. +*/ + +static mp_err s_recursion(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) +{ + mp_err err; + mp_int A1, A2, B1, B0, Q1, Q0, R1, R0, t; + int m = a->used - b->used, k = m/2; + + if (m < (MP_MUL_KARATSUBA_CUTOFF)) { + return s_mp_div_school(a, b, q, r); + } + + if ((err = mp_init_multi(&A1, &A2, &B1, &B0, &Q1, &Q0, &R1, &R0, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + /* B1 = b / beta^k, B0 = b % beta^k*/ + if ((err = mp_div_2d(b, k * MP_DIGIT_BIT, &B1, &B0)) != MP_OKAY) goto LBL_ERR; + + /* (Q1, R1) = RecursiveDivRem(A / beta^(2k), B1) */ + if ((err = mp_div_2d(a, 2*k * MP_DIGIT_BIT, &A1, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = s_recursion(&A1, &B1, &Q1, &R1)) != MP_OKAY) goto LBL_ERR; + + /* A1 = (R1 * beta^(2k)) + (A % beta^(2k)) - (Q1 * B0 * beta^k) */ + if ((err = mp_lshd(&R1, 2*k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&R1, &t, &A1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&Q1, &B0, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&t, k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&A1, &t, &A1)) != MP_OKAY) goto LBL_ERR; + + /* while A1 < 0 do Q1 = Q1 - 1, A1 = A1 + (beta^k * B) */ + if (mp_cmp_d(&A1, 0uL) == MP_LT) { + if ((err = mp_mul_2d(b, k * MP_DIGIT_BIT, &t)) != MP_OKAY) goto LBL_ERR; + do { + if ((err = mp_decr(&Q1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&A1, &t, &A1)) != MP_OKAY) goto LBL_ERR; + } while (mp_cmp_d(&A1, 0uL) == MP_LT); + } + /* (Q0, R0) = RecursiveDivRem(A1 / beta^(k), B1) */ + if ((err = mp_div_2d(&A1, k * MP_DIGIT_BIT, &A1, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = s_recursion(&A1, &B1, &Q0, &R0)) != MP_OKAY) goto LBL_ERR; + + /* A2 = (R0*beta^k) + (A1 % beta^k) - (Q0*B0) */ + if ((err = mp_lshd(&R0, k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&R0, &t, &A2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&Q0, &B0, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&A2, &t, &A2)) != MP_OKAY) goto LBL_ERR; + + /* while A2 < 0 do Q0 = Q0 - 1, A2 = A2 + B */ + while (mp_cmp_d(&A2, 0uL) == MP_LT) { + if ((err = mp_decr(&Q0)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&A2, b, &A2)) != MP_OKAY) goto LBL_ERR; + } + /* return q = (Q1*beta^k) + Q0, r = A2 */ + if ((err = mp_lshd(&Q1, k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&Q1, &Q0, q)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_copy(&A2, r)) != MP_OKAY) goto LBL_ERR; + +LBL_ERR: + mp_clear_multi(&A1, &A2, &B1, &B0, &Q1, &Q0, &R1, &R0, &t, NULL); + return err; +} + + +mp_err s_mp_div_recursive(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) +{ + int j, m, n, sigma; + mp_err err; + bool neg; + mp_digit msb_b, msb; + mp_int A, B, Q, Q1, R, A_div, A_mod; + + if ((err = mp_init_multi(&A, &B, &Q, &Q1, &R, &A_div, &A_mod, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + /* most significant bit of a limb */ + /* assumes MP_DIGIT_MAX < (sizeof(mp_digit) * CHAR_BIT) */ + msb = (MP_DIGIT_MAX + (mp_digit)(1)) >> 1; + sigma = 0; + msb_b = b->dp[b->used - 1]; + while (msb_b < msb) { + sigma++; + msb_b <<= 1; + } + /* Use that sigma to normalize B */ + if ((err = mp_mul_2d(b, sigma, &B)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul_2d(a, sigma, &A)) != MP_OKAY) { + goto LBL_ERR; + } + + /* fix the sign */ + neg = (a->sign != b->sign); + A.sign = B.sign = MP_ZPOS; + + /* + If the magnitude of "A" is not more more than twice that of "B" we can work + on them directly, otherwise we need to work at "A" in chunks + */ + n = B.used; + m = A.used - B.used; + + /* Q = 0 */ + mp_zero(&Q); + while (m > n) { + /* (q, r) = RecursiveDivRem(A / (beta^(m-n)), B) */ + j = (m - n) * MP_DIGIT_BIT; + if ((err = mp_div_2d(&A, j, &A_div, &A_mod)) != MP_OKAY) goto LBL_ERR; + if ((err = s_recursion(&A_div, &B, &Q1, &R)) != MP_OKAY) goto LBL_ERR; + /* Q = (Q*beta!(n)) + q */ + if ((err = mp_mul_2d(&Q, n * MP_DIGIT_BIT, &Q)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&Q, &Q1, &Q)) != MP_OKAY) goto LBL_ERR; + /* A = (r * beta^(m-n)) + (A % beta^(m-n))*/ + if ((err = mp_mul_2d(&R, (m - n) * MP_DIGIT_BIT, &R)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&R, &A_mod, &A)) != MP_OKAY) goto LBL_ERR; + /* m = m - n */ + m = m - n; + } + /* (q, r) = RecursiveDivRem(A, B) */ + if ((err = s_recursion(&A, &B, &Q1, &R)) != MP_OKAY) goto LBL_ERR; + /* Q = (Q * beta^m) + q, R = r */ + if ((err = mp_mul_2d(&Q, m * MP_DIGIT_BIT, &Q)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&Q, &Q1, &Q)) != MP_OKAY) goto LBL_ERR; + + /* get sign before writing to c */ + R.sign = (mp_iszero(&Q) ? MP_ZPOS : a->sign); + + if (q != NULL) { + mp_exch(&Q, q); + q->sign = (neg ? MP_NEG : MP_ZPOS); + } + if (r != NULL) { + /* de-normalize the remainder */ + if ((err = mp_div_2d(&R, sigma, &R, NULL)) != MP_OKAY) goto LBL_ERR; + mp_exch(&R, r); + } +LBL_ERR: + mp_clear_multi(&A, &B, &Q, &Q1, &R, &A_div, &A_mod, NULL); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_school.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_school.c new file mode 100644 index 0000000..304c7a9 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_school.c @@ -0,0 +1,159 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_SCHOOL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* integer signed division. + * c*b + d == a [e.g. a/b, c=quotient, d=remainder] + * HAC pp.598 Algorithm 14.20 + * + * Note that the description in HAC is horribly + * incomplete. For example, it doesn't consider + * the case where digits are removed from 'x' in + * the inner loop. It also doesn't consider the + * case that y has fewer than three digits, etc.. + * + * The overall algorithm is as described as + * 14.20 from HAC but fixed to treat these cases. +*/ +mp_err s_mp_div_school(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_int q, x, y, t1, t2; + mp_digit xdpi; + int n, t, i, norm; + bool neg; + mp_err err; + + if ((err = mp_init_size(&q, a->used + 2)) != MP_OKAY) { + return err; + } + q.used = a->used + 2; + + if ((err = mp_init(&t1)) != MP_OKAY) goto LBL_Q; + if ((err = mp_init(&t2)) != MP_OKAY) goto LBL_T1; + if ((err = mp_init_copy(&x, a)) != MP_OKAY) goto LBL_T2; + if ((err = mp_init_copy(&y, b)) != MP_OKAY) goto LBL_X; + + /* fix the sign */ + neg = (a->sign != b->sign); + x.sign = y.sign = MP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */ + norm = mp_count_bits(&y) % MP_DIGIT_BIT; + if (norm < (MP_DIGIT_BIT - 1)) { + norm = (MP_DIGIT_BIT - 1) - norm; + if ((err = mp_mul_2d(&x, norm, &x)) != MP_OKAY) goto LBL_Y; + if ((err = mp_mul_2d(&y, norm, &y)) != MP_OKAY) goto LBL_Y; + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + /* y = y*b**{n-t} */ + if ((err = mp_lshd(&y, n - t)) != MP_OKAY) goto LBL_Y; + + while (mp_cmp(&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((err = mp_sub(&x, &y, &x)) != MP_OKAY) goto LBL_Y; + } + + /* reset y by shifting it back down */ + mp_rshd(&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + /* Do not assume that more than enough memory is automatically allocated and set to '0' */ + xdpi = (i == x.used) ? 0u : x.dp[i]; + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (xdpi == y.dp[t]) { + q.dp[(i - t) - 1] = ((mp_digit)1 << (mp_digit)MP_DIGIT_BIT) - (mp_digit)1; + } else { + mp_word tmp; + tmp = (mp_word)xdpi << (mp_word)MP_DIGIT_BIT; + tmp |= (mp_word)x.dp[i - 1]; + tmp /= (mp_word)y.dp[t]; + if (tmp > (mp_word)MP_MASK) { + tmp = MP_MASK; + } + q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)MP_MASK); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1uL) & (mp_digit)MP_MASK; + do { + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK; + + /* find left hand */ + mp_zero(&t1); + t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((err = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + + /* find right hand */ + t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2]; + t2.dp[1] = x.dp[i - 1]; /* i >= 1 always holds */ + t2.dp[2] = xdpi; + t2.used = 3; + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((err = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_sub(&x, &t1, &x)) != MP_OKAY) goto LBL_Y; + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (mp_isneg(&x)) { + if ((err = mp_copy(&y, &t1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_add(&x, &t1, &x)) != MP_OKAY) goto LBL_Y; + + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & MP_MASK; + } + } + + /* now q is the quotient and x is the remainder + * [which we have to normalize] + */ + + /* get sign before writing to c */ + x.sign = mp_iszero(&x) ? MP_ZPOS : a->sign; + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + c->sign = (neg ? MP_NEG : MP_ZPOS); + } + + if (d != NULL) { + if ((err = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) goto LBL_Y; + mp_exch(&x, d); + } + +LBL_Y: + mp_clear(&y); +LBL_X: + mp_clear(&x); +LBL_T2: + mp_clear(&t2); +LBL_T1: + mp_clear(&t1); +LBL_Q: + mp_clear(&q); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_small.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_small.c new file mode 100644 index 0000000..2d951be --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_div_small.c @@ -0,0 +1,51 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_SMALL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* slower bit-bang division... also smaller */ +mp_err s_mp_div_small(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_int ta, tb, tq, q; + int n; + bool neg; + mp_err err; + + /* init our temps */ + if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) { + return err; + } + + mp_set(&tq, 1uL); + n = mp_count_bits(a) - mp_count_bits(b); + if ((err = mp_abs(a, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_abs(b, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tq, n, &tq)) != MP_OKAY) goto LBL_ERR; + + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if ((err = mp_sub(&ta, &tb, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&q, &tq, &q)) != MP_OKAY) goto LBL_ERR; + } + if ((err = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY) goto LBL_ERR; + } + + /* now q == quotient and ta == remainder */ + + neg = (a->sign != b->sign); + if (c != NULL) { + mp_exch(c, &q); + c->sign = ((neg && !mp_iszero(c)) ? MP_NEG : MP_ZPOS); + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = (mp_iszero(d) ? MP_ZPOS : a->sign); + } +LBL_ERR: + mp_clear_multi(&ta, &tb, &tq, &q, NULL); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod.c new file mode 100644 index 0000000..2a89a2c --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod.c @@ -0,0 +1,198 @@ +#include "tommath_private.h" +#ifdef S_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_LOW_MEM +# define TAB_SIZE 32 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + mp_err err; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu); + + /* find window size */ + x = mp_count_bits(X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear(&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init(&mu)) != MP_OKAY) goto LBL_M; + + if (redmode == 0) { + if ((err = mp_reduce_setup(&mu, P)) != MP_OKAY) goto LBL_MU; + redux = mp_reduce; + } else { + if ((err = mp_reduce_2k_setup_l(P, &mu)) != MP_OKAY) goto LBL_MU; + redux = mp_reduce_2k_l; + } + + /* create M table + * + * The M table contains powers of the base, + * e.g. M[x] = G**x mod P + * + * The first half of the table is not + * computed though accept for M[0] and M[1] + */ + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_MU; + + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], + &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + /* reduce modulo P */ + if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, &mu)) != MP_OKAY) goto LBL_MU; + } + + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_MU; + if ((err = redux(&M[x], P, &mu)) != MP_OKAY) goto LBL_MU; + } + + /* setup result */ + if ((err = mp_init(&res)) != MP_OKAY) goto LBL_MU; + mp_set(&res, 1uL); + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ + if (digidx == -1) { + break; + } + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if ((mode == 0) && (y == 0)) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if ((mode == 1) && (y == 0)) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + } + + /* then multiply */ + if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if ((mode == 2) && (bitcpy > 0)) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + } + } + } + + mp_exch(&res, Y); + err = MP_OKAY; +LBL_RES: + mp_clear(&res); +LBL_MU: + mp_clear(&mu); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear(&M[x]); + } + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod_fast.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod_fast.c new file mode 100644 index 0000000..e7729f4 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_exptmod_fast.c @@ -0,0 +1,254 @@ +#include "tommath_private.h" +#ifdef S_MP_EXPTMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ + +#ifdef MP_LOW_MEM +# define TAB_SIZE 32 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res; + mp_digit buf, mp; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err err; + + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + mp_err(*redux)(mp_int *x, const mp_int *n, mp_digit rho); + + /* find window size */ + x = mp_count_bits(X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* init M array */ + /* init first cell */ + if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear(&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { + if (MP_HAS(MP_MONTGOMERY_SETUP)) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) goto LBL_M; + } else { + err = MP_VAL; + goto LBL_M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (MP_HAS(S_MP_MONTGOMERY_REDUCE_COMBA) && + (((P->used * 2) + 1) < MP_WARRAY) && + (P->used < MP_MAX_COMBA)) { + redux = s_mp_montgomery_reduce_comba; + } else if (MP_HAS(MP_MONTGOMERY_REDUCE)) { + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (redmode == 1) { + if (MP_HAS(MP_DR_SETUP) && MP_HAS(MP_DR_REDUCE)) { + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (MP_HAS(MP_REDUCE_2K_SETUP) && MP_HAS(MP_REDUCE_2K)) { + /* setup DR reduction for moduli of the form 2**k - b */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) goto LBL_M; + redux = mp_reduce_2k; + } else { + err = MP_VAL; + goto LBL_M; + } + + /* setup result */ + if ((err = mp_init_size(&res, P->alloc)) != MP_OKAY) goto LBL_M; + + /* create M table + * + + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { + if (MP_HAS(MP_MONTGOMERY_CALC_NORMALIZATION)) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) goto LBL_RES; + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) goto LBL_RES; + } else { + err = MP_VAL; + goto LBL_RES; + } + } else { + mp_set(&res, 1uL); + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_RES; + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_RES; + if ((err = redux(&M[x], P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (MP_DIGIT_BIT - 1)) & 1uL; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if ((mode == 0) && (y == 0)) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if ((mode == 1) && (y == 0)) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* then multiply */ + if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if ((mode == 2) && (bitcpy > 0)) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* swap res with Y */ + mp_exch(&res, Y); + err = MP_OKAY; +LBL_RES: + mp_clear(&res); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear(&M[x]); + } + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log.c new file mode 100644 index 0000000..90a89ab --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log.c @@ -0,0 +1,83 @@ +#include "tommath_private.h" +#ifdef S_MP_FP_LOG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Fixed point bitwise logarithm base two of "a" with precision "p", Big-integer version. */ +static mp_err s_mp_fp_log_fraction(const mp_int *a, int p, mp_int *c) +{ + mp_int b, L_out, twoep, a_bar; + int L, pmL; + int i; + mp_err err; + + if ((err = mp_init_multi(&b, &L_out, &twoep, &a_bar, NULL)) != MP_OKAY) { + return err; + } + + L = mp_count_bits(a) - 1; + pmL = (p < L) ? L - p: p - L; + if ((err = mp_mul_2d(a, pmL, &a_bar)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_2expt(&b, p - 1)) != MP_OKAY) goto LTM_ERR; + mp_set_i32(&L_out, L); + if ((err = mp_mul_2d(&L_out, p, &L_out)) != MP_OKAY) goto LTM_ERR; + + if ((err = mp_2expt(&twoep, p + 1)) != MP_OKAY) goto LTM_ERR; + + for (i = 0; i < p; i++) { + if ((err = mp_sqr(&a_bar, &a_bar)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2d(&a_bar, p, &a_bar, NULL)) != MP_OKAY) goto LTM_ERR; + if (mp_cmp(&a_bar, &twoep) != MP_LT) { + if ((err = mp_div_2(&a_bar, &a_bar)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add(&L_out, &b, &L_out)) != MP_OKAY) goto LTM_ERR; + } + if ((err = mp_div_2(&b, &b)) != MP_OKAY) goto LTM_ERR; + } + + mp_exch(c, &L_out); + +LTM_ERR: + mp_clear_multi(&b, &L_out, &twoep, &a_bar, NULL); + return err; +} + +mp_err s_mp_fp_log(const mp_int *a, mp_int *c) +{ + mp_int La, t; + mp_err err; + int fla; + /* + We have arbitrary precision here and could adapt "prec" to actual precision, + there is no need for lowering precision for small numbers. Some quick runtime + tests revealed a gain that can only be called marginally at best. + But: YMMV, as always. + */ + int prec = MP_PRECISION_FIXED_LOG; + + fla = mp_count_bits(a) - 1; + + if ((err = mp_init_multi(&La, &t, NULL)) != MP_OKAY) { + return err; + } + + if (fla > prec) { + if ((err = mp_div_2d(a, fla - prec, &t, NULL)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_fp_log_fraction(&t, prec, + &La)) != MP_OKAY) goto LTM_ERR; + mp_set_i32(&t,fla - prec); + if ((err = mp_mul_2d(&t,prec, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add(&La, &t, &La)) != MP_OKAY) goto LTM_ERR; + } else { + if ((err = s_mp_fp_log_fraction(a, prec, + &La)) != MP_OKAY) goto LTM_ERR; + } + + mp_exch(&La, c); + +LTM_ERR: + mp_clear_multi(&La, &t, NULL); + return err; +} + + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log_d.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log_d.c new file mode 100644 index 0000000..71d82dc --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_fp_log_d.c @@ -0,0 +1,83 @@ +#include "tommath_private.h" +#ifdef S_MP_FP_LOG_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static mp_word s_mp_flog2_mp_word_d(mp_word value) +{ + mp_word r = 0u; + while ((value >>= 1) != 0u) { + r++; + } + return r; +} + +/* Fixed point bitwise logarithm base two of "x" with precision "p" */ +static mp_err s_mp_fp_log_fraction_d(mp_word x, int p, mp_word *c) +{ + mp_word b, L_out, L, a_bar, twoep; + int i; + + L = s_mp_flog2_mp_word_d(x); + + if ((L + (mp_word)p) > MP_UPPER_LIMIT_FIXED_LOG) { + return MP_VAL; + } + + a_bar = ((mp_word)p < L) ? x << (L - (mp_word)p) : x << ((mp_word)p - L); + b = (mp_word)(1u) << (p - 1); + L_out = L << p; + + twoep = (mp_word)(1u) << (p + 1); + + for (i = 0; i < p; i++) { + a_bar = (a_bar * a_bar) >> p; + if (a_bar >= twoep) { + a_bar >>= 1u; + L_out += b; + } + b >>= 1u; + } + *c = L_out; + return MP_OKAY; +} + +/* Approximate the base two logarithm of "a" */ +mp_err s_mp_fp_log_d(const mp_int *a, mp_word *c) +{ + mp_err err; + int la; + int prec = MP_PRECISION_FIXED_LOG; + mp_word tmp, la_word; + mp_int t; + + la = mp_count_bits(a) - 1; + + /* We don't use the whole number, just the most significant "prec" bits */ + if (la > prec) { + if ((err = mp_init(&t)) != MP_OKAY) goto LTM_ERR; + /* Get enough msb-bits for the chosen precision */ + if ((err = mp_div_2d(a, la - prec, &t, NULL)) != MP_OKAY) goto LTM_ERR; + tmp = mp_get_u64(&t); + /* Compute the low precision approximation for the fractional part */ + if ((err = s_mp_fp_log_fraction_d(tmp, prec, &la_word)) != MP_OKAY) goto LTM_ERR; + /* Compute the integer part and add it */ + tmp = ((mp_word)(la - prec))<= a->used) { + return false; + } + + bit = (mp_digit)1 << (b % MP_DIGIT_BIT); + return ((a->dp[limb] & bit) != 0u); +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod.c new file mode 100644 index 0000000..b2fb21d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod.c @@ -0,0 +1,117 @@ +#include "tommath_private.h" +#ifdef S_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err s_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, A, B, C, D; + mp_err err; + + /* b cannot be negative */ + if ((b->sign == MP_NEG) || mp_iszero(b)) { + return MP_VAL; + } + + /* init temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x = a, y = b */ + if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR; + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven(&x) && mp_iseven(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&A, 1uL); + mp_set(&D, 1uL); + + do { + /* 4. while u is even do */ + while (mp_iseven(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if A or B is odd then */ + if (mp_isodd(&A) || mp_isodd(&B)) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((err = mp_add(&A, &y, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* A = A/2, B = B/2 */ + if ((err = mp_div_2(&A, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (mp_iseven(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if C or D is odd then */ + if (mp_isodd(&C) || mp_isodd(&D)) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((err = mp_add(&C, &y, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* C = C/2, D = D/2 */ + if ((err = mp_div_2(&C, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* 6. if u >= v then */ + if (mp_cmp(&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&A, &C, &A)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&C, &A, &C)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + } while (!mp_iszero(&u)); + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_isneg(&C)) { + if ((err = mp_add(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* C is now the inverse */ + mp_exch(&C, c); + +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod_odd.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod_odd.c new file mode 100644 index 0000000..11fc357 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_invmod_odd.c @@ -0,0 +1,113 @@ +#include "tommath_private.h" +#ifdef S_MP_INVMOD_ODD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on slow invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +mp_err s_mp_invmod_odd(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, B, D; + mp_err err; + + /* 2. [modified] b must be odd */ + if (mp_iseven(b)) { + return MP_VAL; + } + + /* init all our temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x == modulus, y == value to invert */ + if ((err = mp_copy(b, &x)) != MP_OKAY) goto LBL_ERR; + + /* y needs to be positive but the remainder d of mp_div(a,b,c,d) might be negative */ + if ((err = mp_mod(a, b, &y)) != MP_OKAY) goto LBL_ERR; + + /* if one of x,y is zero return an error! */ + if (mp_iszero(&x) || mp_iszero(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&D, 1uL); + + do { + /* 4. while u is even do */ + while (mp_iseven(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if B is odd then */ + if (mp_isodd(&B)) { + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* B = B/2 */ + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (mp_iseven(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if D is odd then */ + if (mp_isodd(&D)) { + /* D = (D-x)/2 */ + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* D = D/2 */ + if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* 6. if u >= v then */ + if (mp_cmp(&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + } while (!mp_iszero(&u)); + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + while (mp_isneg(&D)) { + if ((err = mp_add(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&D, b) != MP_LT) { + if ((err = mp_sub(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + mp_exch(&D, c); + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_log_2expt.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_log_2expt.c new file mode 100644 index 0000000..ec0fda3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_log_2expt.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef S_MP_LOG_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +int s_mp_log_2expt(const mp_int *a, mp_digit base) +{ + int y; + for (y = 0; (base & 1) == 0; y++, base >>= 1) {} + return (mp_count_bits(a) - 1) / y; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_montgomery_reduce_comba.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_montgomery_reduce_comba.c new file mode 100644 index 0000000..3858f75 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_montgomery_reduce_comba.c @@ -0,0 +1,124 @@ +#include "tommath_private.h" +#ifdef S_MP_MONTGOMERY_REDUCE_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) +{ + int ix, oldused; + mp_err err; + mp_word MP_ALLOC_WARRAY(W); + + MP_CHECK_WARRAY(W); + + if (x->used > MP_WARRAY) { + MP_FREE_WARRAY(W); + return MP_VAL; + } + + /* get old used count */ + oldused = x->used; + + /* grow a as required */ + if ((err = mp_grow(x, n->used + 1)) != MP_OKAY) { + MP_FREE_WARRAY(W); + return err; + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + W[ix] = x->dp[ix]; + } + + /* zero the high words of W[a->used..m->used*2] */ + if (ix < ((n->used * 2) + 1)) { + s_mp_zero_buf(W + x->used, sizeof(mp_word) * (size_t)(((n->used * 2) + 1) - ix)); + } + + /* now we proceed to zero successive digits + * from the least significant upwards + */ + for (ix = 0; ix < n->used; ix++) { + int iy; + mp_digit mu; + + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + mu = ((W[ix] & MP_MASK) * rho) & MP_MASK; + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offsetting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + for (iy = 0; iy < n->used; iy++) { + W[ix + iy] += (mp_word)mu * (mp_word)n->dp[iy]; + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> (mp_word)MP_DIGIT_BIT; + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + + for (; ix < (n->used * 2); ix++) { + W[ix + 1] += W[ix] >> (mp_word)MP_DIGIT_BIT; + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + + for (ix = 0; ix < (n->used + 1); ix++) { + x->dp[ix] = W[n->used + ix] & (mp_word)MP_MASK; + } + + /* set the max used */ + x->used = n->used + 1; + + /* zero oldused digits, if the input a was larger than + * m->used+1 we'll have to clear the digits + */ + s_mp_zero_digs(x->dp + x->used, oldused - x->used); + + mp_clamp(x); + + MP_FREE_WARRAY(W); + /* if A >= m then A = A - m */ + if (mp_cmp_mag(x, n) != MP_LT) { + return s_mp_sub(x, n, x); + } + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul.c new file mode 100644 index 0000000..3394c14 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul.c @@ -0,0 +1,65 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiplies |a| * |b| and only computes upto digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +mp_err s_mp_mul(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + mp_int t; + mp_err err; + int pa, ix; + + if (digs < 0) { + return MP_VAL; + } + + /* can we use the fast multiplier? */ + if ((digs < MP_WARRAY) && + (MP_MIN(a->used, b->used) < MP_MAX_COMBA)) { + return s_mp_mul_comba(a, b, c, digs); + } + + if ((err = mp_init_size(&t, digs)) != MP_OKAY) { + return err; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + int iy, pb; + mp_digit u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MP_MIN(b->used, digs - ix); + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + mp_word r = (mp_word)t.dp[ix + iy] + + ((mp_word)a->dp[ix] * (mp_word)b->dp[iy]) + + (mp_word)u; + + /* the new column is the lower part of the result */ + t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + + /* get the carry word from the result */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + /* set carry if it is placed below digs */ + if ((ix + iy) < digs) { + t.dp[ix + pb] = u; + } + } + + mp_clamp(&t); + mp_exch(&t, c); + + mp_clear(&t); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_balance.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_balance.c new file mode 100644 index 0000000..f36f0d3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_balance.c @@ -0,0 +1,71 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_BALANCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single-digit multiplication with the smaller number as the single-digit */ +mp_err s_mp_mul_balance(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int a0, tmp, r; + mp_err err; + int i, j, + nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used), + bsize = MP_MIN(a->used, b->used); + + if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) { + return err; + } + if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) { + mp_clear(&a0); + return err; + } + + /* Make sure that A is the larger one*/ + if (a->used < b->used) { + MP_EXCH(const mp_int *, a, b); + } + + for (i = 0, j=0; i < nblocks; i++) { + /* Cut a slice off of a */ + a0.used = bsize; + s_mp_copy_digs(a0.dp, a->dp + j, a0.used); + j += a0.used; + mp_clamp(&a0); + + /* Multiply with b */ + if ((err = mp_mul(&a0, b, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + /* Shift tmp to the correct position */ + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + /* Add to output. No carry needed */ + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* The left-overs; there are always left-overs */ + if (j < a->used) { + a0.used = a->used - j; + s_mp_copy_digs(a0.dp, a->dp + j, a0.used); + j += a0.used; + mp_clamp(&a0); + + if ((err = mp_mul(&a0, b, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + + mp_exch(&r,c); +LBL_ERR: + mp_clear_multi(&a0, &tmp, &r,NULL); + return err; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_comba.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_comba.c new file mode 100644 index 0000000..5b37035 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_comba.c @@ -0,0 +1,87 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +mp_err s_mp_mul_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int oldused, pa, ix; + mp_err err; + mp_digit MP_ALLOC_WARRAY(W); + mp_word _W; + + MP_CHECK_WARRAY(W); + + if (digs < 0) { + MP_FREE_WARRAY(W); + return MP_VAL; + } + + /* grow the destination as required */ + if ((err = mp_grow(c, digs)) != MP_OKAY) { + MP_FREE_WARRAY(W); + return err; + } + + /* number of output digits to produce */ + pa = MP_MIN(digs, a->used + b->used); + + /* clear the carry */ + _W = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy, iz; + + /* get offsets into the two bignums */ + ty = MP_MIN(b->used-1, ix); + tx = ix - ty; + + /* this is the number of times the loop will iterate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MP_MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; ++iz) { + _W += (mp_word)a->dp[tx + iz] * (mp_word)b->dp[ty - iz]; + } + + /* store term */ + W[ix] = (mp_digit)_W & MP_MASK; + + /* make next carry */ + _W = _W >> (mp_word)MP_DIGIT_BIT; + } + + /* setup dest */ + oldused = c->used; + c->used = pa; + + for (ix = 0; ix < pa; ix++) { + /* now extract the previous digit [below the carry] */ + c->dp[ix] = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + MP_FREE_WARRAY(W); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high.c new file mode 100644 index 0000000..fd532eb --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high.c @@ -0,0 +1,56 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_HIGH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +mp_err s_mp_mul_high(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + mp_int t; + int pa, pb, ix; + mp_err err; + + if (digs < 0) { + return MP_VAL; + } + + /* can we use the fast multiplier? */ + if (MP_HAS(S_MP_MUL_HIGH_COMBA) + && ((a->used + b->used + 1) < MP_WARRAY) + && (MP_MIN(a->used, b->used) < MP_MAX_COMBA)) { + return s_mp_mul_high_comba(a, b, c, digs); + } + + if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { + return err; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa; ix++) { + int iy; + mp_digit u = 0; + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + mp_word r = (mp_word)t.dp[ix + iy] + + ((mp_word)a->dp[ix] * (mp_word)b->dp[iy]) + + (mp_word)u; + + /* get the lower part */ + t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + + /* carry the carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + t.dp[ix + pb] = u; + } + mp_clamp(&t); + mp_exch(&t, c); + mp_clear(&t); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high_comba.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high_comba.c new file mode 100644 index 0000000..b0096d4 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_high_comba.c @@ -0,0 +1,79 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_HIGH_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this is a modified version of s_mp_mul_comba that only produces + * output digits *above* digs. See the comments for s_mp_mul_comba + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +mp_err s_mp_mul_high_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int oldused, pa, ix; + mp_err err; + mp_digit MP_ALLOC_WARRAY(W); + mp_word _W; + + MP_CHECK_WARRAY(W); + + if (digs < 0) { + MP_FREE_WARRAY(W); + return MP_VAL; + } + + /* grow the destination as required */ + pa = a->used + b->used; + if ((err = mp_grow(c, pa)) != MP_OKAY) { + MP_FREE_WARRAY(W); + return err; + } + + /* number of output digits to produce */ + pa = a->used + b->used; + _W = 0; + for (ix = digs; ix < pa; ix++) { + int tx, ty, iy, iz; + + /* get offsets into the two bignums */ + ty = MP_MIN(b->used-1, ix); + tx = ix - ty; + + /* this is the number of times the loop will iterate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MP_MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += (mp_word)a->dp[tx + iz] * (mp_word)b->dp[ty - iz]; + } + + /* store term */ + W[ix] = (mp_digit)_W & MP_MASK; + + /* make next carry */ + _W = _W >> (mp_word)MP_DIGIT_BIT; + } + + /* setup dest */ + oldused = c->used; + c->used = pa; + + for (ix = digs; ix < pa; ix++) { + /* now extract the previous digit [below the carry] */ + c->dp[ix] = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + MP_FREE_WARRAY(W); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_karatsuba.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_karatsuba.c new file mode 100644 index 0000000..b465298 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_mul_karatsuba.c @@ -0,0 +1,151 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_KARATSUBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**MP_DIGIT_BIT] and + * let n represent half of the number of digits in + * the min(a,b) + * + * a = a1 * B**n + a0 + * b = b1 * B**n + b0 + * + * Then, a * b => + a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0 + * + * Note that a1b1 and a0b0 are used twice and only need to be + * computed once. So in total three half size (half # of + * digit) multiplications are performed, a0b0, a1b1 and + * (a1+b1)(a0+b0) + * + * Note that a multiplication of half the digits requires + * 1/4th the number of single precision multiplications so in + * total after one call 25% of the single precision multiplications + * are saved. Note also that the call to mp_mul can end up back + * in this function if the a0, a1, b0, or b1 are above the threshold. + * This is known as divide-and-conquer and leads to the famous + * O(N**lg(3)) or O(N**1.584) work which is asymptotically lower than + * the standard O(N**2) that the baseline/comba methods use. + * Generally though the overhead of this method doesn't pay off + * until a certain size (N ~ 80) is reached. + */ +mp_err s_mp_mul_karatsuba(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B; + mp_err err; + + /* min # of digits */ + B = MP_MIN(a->used, b->used); + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if ((err = mp_init_size(&x0, B)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_init_size(&x1, a->used - B)) != MP_OKAY) { + goto X0; + } + if ((err = mp_init_size(&y0, B)) != MP_OKAY) { + goto X1; + } + if ((err = mp_init_size(&y1, b->used - B)) != MP_OKAY) { + goto Y0; + } + + /* init temps */ + if ((err = mp_init_size(&t1, B * 2)) != MP_OKAY) { + goto Y1; + } + if ((err = mp_init_size(&x0y0, B * 2)) != MP_OKAY) { + goto T1; + } + if ((err = mp_init_size(&x1y1, B * 2)) != MP_OKAY) { + goto X0Y0; + } + + /* now shift the digits */ + x0.used = y0.used = B; + x1.used = a->used - B; + y1.used = b->used - B; + + /* we copy the digits directly instead of using higher level functions + * since we also need to shift the digits + */ + s_mp_copy_digs(x0.dp, a->dp, x0.used); + s_mp_copy_digs(y0.dp, b->dp, y0.used); + s_mp_copy_digs(x1.dp, a->dp + B, x1.used); + s_mp_copy_digs(y1.dp, b->dp + B, y1.used); + + /* only need to clamp the lower words since by definition the + * upper words x1/y1 must have a known number of digits + */ + mp_clamp(&x0); + mp_clamp(&y0); + + /* now calc the products x0y0 and x1y1 */ + /* after this x0 is no longer required, free temp [x0==t2]! */ + if ((err = mp_mul(&x0, &y0, &x0y0)) != MP_OKAY) { + goto X1Y1; /* x0y0 = x0*y0 */ + } + if ((err = mp_mul(&x1, &y1, &x1y1)) != MP_OKAY) { + goto X1Y1; /* x1y1 = x1*y1 */ + } + + /* now calc x1+x0 and y1+y0 */ + if ((err = s_mp_add(&x1, &x0, &t1)) != MP_OKAY) { + goto X1Y1; /* t1 = x1 - x0 */ + } + if ((err = s_mp_add(&y1, &y0, &x0)) != MP_OKAY) { + goto X1Y1; /* t2 = y1 - y0 */ + } + if ((err = mp_mul(&t1, &x0, &t1)) != MP_OKAY) { + goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */ + } + + /* add x0y0 */ + if ((err = mp_add(&x0y0, &x1y1, &x0)) != MP_OKAY) { + goto X1Y1; /* t2 = x0y0 + x1y1 */ + } + if ((err = s_mp_sub(&t1, &x0, &t1)) != MP_OKAY) { + goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */ + } + + /* shift by B */ + if ((err = mp_lshd(&t1, B)) != MP_OKAY) { + goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<used, b->used) / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + if ((err = mp_init_size(&a2, a->used - 2 * B)) != MP_OKAY) goto LBL_ERRa2; + + a0.used = a1.used = B; + a2.used = a->used - 2 * B; + s_mp_copy_digs(a0.dp, a->dp, a0.used); + s_mp_copy_digs(a1.dp, a->dp + B, a1.used); + s_mp_copy_digs(a2.dp, a->dp + 2 * B, a2.used); + mp_clamp(&a0); + mp_clamp(&a1); + mp_clamp(&a2); + + /** b = b2 * x^2 + b1 * x + b0; */ + if ((err = mp_init_size(&b0, B)) != MP_OKAY) goto LBL_ERRb0; + if ((err = mp_init_size(&b1, B)) != MP_OKAY) goto LBL_ERRb1; + if ((err = mp_init_size(&b2, b->used - 2 * B)) != MP_OKAY) goto LBL_ERRb2; + + b0.used = b1.used = B; + b2.used = b->used - 2 * B; + s_mp_copy_digs(b0.dp, b->dp, b0.used); + s_mp_copy_digs(b1.dp, b->dp + B, b1.used); + s_mp_copy_digs(b2.dp, b->dp + 2 * B, b2.used); + mp_clamp(&b0); + mp_clamp(&b1); + mp_clamp(&b2); + + /** \\ S1 = (a2+a1+a0) * (b2+b1+b0); */ + /** T1 = a2 + a1; */ + if ((err = mp_add(&a2, &a1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &S2)) != MP_OKAY) goto LBL_ERR; + + /** c = b2 + b1; */ + if ((err = mp_add(&b2, &b1, c)) != MP_OKAY) goto LBL_ERR; + + /** S1 = c + b0; */ + if ((err = mp_add(c, &b0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 * S2; */ + if ((err = mp_mul(&S1, &S2, &S1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0); */ + /** T1 = T1 + a2; */ + if ((err = mp_add(&T1, &a2, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 << 1; */ + if ((err = mp_mul_2(&T1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &T1)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b2; */ + if ((err = mp_add(c, &b2, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c << 1; */ + if ((err = mp_mul_2(c, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b0; */ + if ((err = mp_add(c, &b0, c)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 * c; */ + if ((err = mp_mul(&T1, c, &S2)) != MP_OKAY) goto LBL_ERR; + + /** \\S3 = (a2-a1+a0) * (b2-b1+b0); */ + /** a1 = a2 - a1; */ + if ((err = mp_sub(&a2, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 + a0; */ + if ((err = mp_add(&a1, &a0, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b2 - b1; */ + if ((err = mp_sub(&b2, &b1, &b1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b1 + b0; */ + if ((err = mp_add(&b1, &b0, &b1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 * b1; */ + if ((err = mp_mul(&a1, &b1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = a2 * b2; */ + if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (S2 - S3)/3; */ + /** S2 = S2 - a1; */ + if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 / 3; \\ this is an exact division */ + if ((err = s_mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; + + /** a1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 >> 1; */ + if ((err = mp_div_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a0 = a0 * b0; */ + if ((err = mp_mul(&a0, &b0, &a0)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a0; */ + if ((err = mp_sub(&S1, &a0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - S1; */ + if ((err = mp_sub(&S2, &S1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 >> 1; */ + if ((err = mp_div_2(&S2, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - b1; */ + if ((err = mp_sub(&S1, &b1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = b1 << 1; */ + if ((err = mp_mul_2(&b1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - T1; */ + if ((err = mp_sub(&S2, &T1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 - S2; */ + if ((err = mp_sub(&a1, &S2, &a1)) != MP_OKAY) goto LBL_ERR; + + + /** P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0; */ + if ((err = mp_lshd(&b1, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S2, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S2, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S1, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a0, c)) != MP_OKAY) goto LBL_ERR; + + /** a * b - P */ + + +LBL_ERR: + mp_clear(&b2); +LBL_ERRb2: + mp_clear(&b1); +LBL_ERRb1: + mp_clear(&b0); +LBL_ERRb0: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear_multi(&S1, &S2, &T1, NULL); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_is_divisible.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_is_divisible.c new file mode 100644 index 0000000..63b2405 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_is_divisible.c @@ -0,0 +1,33 @@ +#include "tommath_private.h" +#ifdef S_MP_PRIME_IS_DIVISIBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if an integers is divisible by one + * of the first PRIME_SIZE primes or not + * + * sets result to 0 if not, 1 if yes + */ +mp_err s_mp_prime_is_divisible(const mp_int *a, bool *result) +{ + int i; + for (i = 0; i < MP_PRIME_TAB_SIZE; i++) { + /* what is a mod LBL_prime_tab[i] */ + mp_err err; + mp_digit res; + if ((err = mp_mod_d(a, s_mp_prime_tab[i], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0u) { + *result = true; + return MP_OKAY; + } + } + + /* default to not */ + *result = false; + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_tab.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_tab.c new file mode 100644 index 0000000..87c07fd --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_prime_tab.c @@ -0,0 +1,44 @@ +#include "tommath_private.h" +#ifdef S_MP_PRIME_TAB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +const mp_digit s_mp_prime_tab[] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +}; + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_map.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_map.c new file mode 100644 index 0000000..68e21f3 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_map.c @@ -0,0 +1,19 @@ +#include "tommath_private.h" +#ifdef S_MP_RADIX_MAP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* chars used in radix conversions */ +const char s_mp_radix_map[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +const uint8_t s_mp_radix_map_reverse[] = { + 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x01, 0x02, 0x03, 0x04, /* +,-./01234 */ + 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56789:;<=> */ + 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, /* ?@ABCDEFGH */ + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, /* IJKLMNOPQR */ + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff, 0xff, /* STUVWXYZ[\ */ + 0xff, 0xff, 0xff, 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* ]^_`abcdef */ + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, /* ghijklmnop */ + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d /* qrstuvwxyz */ +}; +MP_STATIC_ASSERT(correct_radix_map_reverse_size, sizeof(s_mp_radix_map_reverse) == MP_RADIX_MAP_REVERSE_SIZE) +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_size_overestimate.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_size_overestimate.c new file mode 100644 index 0000000..4f05997 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_radix_size_overestimate.c @@ -0,0 +1,82 @@ +#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) + 3); + 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 diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_rand_platform.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_rand_platform.c new file mode 100644 index 0000000..0a6982a --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_rand_platform.c @@ -0,0 +1,149 @@ +#include "tommath_private.h" +#ifdef S_MP_RAND_PLATFORM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* First the OS-specific special cases + * - *BSD + * - Windows + */ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +#define S_READ_ARC4RANDOM_C +static mp_err s_read_arc4random(void *p, size_t n) +{ + arc4random_buf(p, n); + return MP_OKAY; +} +#endif + +#if defined(_WIN32) +#define S_READ_WINCSP_C + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#ifndef WINVER +#define WINVER 0x0501 +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static mp_err s_read_wincsp(void *p, size_t n) +{ + static HCRYPTPROV hProv = 0; + if (hProv == 0) { + HCRYPTPROV h = 0; + if (!CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { + return MP_ERR; + } + hProv = h; + } + return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR; +} +#endif /* WIN32 */ + +#if !defined(S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 25) +#define S_READ_GETRANDOM_C +#include +#include + +static mp_err s_read_getrandom(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + ssize_t ret = getrandom(q, n, 0); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + return MP_OKAY; +} +#endif +#endif + +/* We assume all platforms besides windows provide "/dev/urandom". + * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time. + */ +#if !defined(S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM) +#define S_READ_URANDOM_C +#ifndef MP_DEV_URANDOM +#define MP_DEV_URANDOM "/dev/urandom" +#endif +#include +#include +#include + +static mp_err s_read_urandom(void *p, size_t n) +{ + int fd; + char *q = (char *)p; + + do { + fd = open(MP_DEV_URANDOM, O_RDONLY); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) return MP_ERR; + + while (n > 0u) { + ssize_t ret = read(fd, q, n); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + close(fd); + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + + close(fd); + return MP_OKAY; +} +#endif + +mp_err s_read_arc4random(void *p, size_t n); +mp_err s_read_wincsp(void *p, size_t n); +mp_err s_read_getrandom(void *p, size_t n); +mp_err s_read_urandom(void *p, size_t n); + +/* + * Note: libtommath relies on dead code elimination + * for the configuration system, i.e., the MP_HAS macro. + * + * If you observe linking errors in this functions, + * your compiler does not perform the dead code compilation + * such that the unused functions are still referenced. + * + * This happens for example for MSVC if the /Od compilation + * option is given. The option /Od instructs MSVC to + * not perform any "optimizations", not even removal of + * dead code wrapped in `if (0)` blocks. + * + * If you still insist on compiling with /Od, simply + * comment out the lines which result in linking errors. + * + * We intentionally don't fix this issue in order + * to have a single point of failure for misconfigured compilers. + */ +mp_err s_mp_rand_platform(void *p, size_t n) +{ + mp_err err = MP_ERR; + if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n); + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr.c new file mode 100644 index 0000000..da9aa69 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +mp_err s_mp_sqr(const mp_int *a, mp_int *b) +{ + mp_int t; + int ix, pa; + mp_err err; + + pa = a->used; + if ((err = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) { + return err; + } + + /* default used is maximum possible size */ + t.used = (2 * pa) + 1; + + for (ix = 0; ix < pa; ix++) { + mp_digit u; + int iy; + + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + mp_word r = (mp_word)t.dp[2*ix] + + ((mp_word)a->dp[ix] * (mp_word)a->dp[ix]); + + /* store lower part in result */ + t.dp[ix+ix] = (mp_digit)(r & (mp_word)MP_MASK); + + /* get the carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = (mp_word)a->dp[ix] * (mp_word)a->dp[iy]; + + /* now calculate the double precision result, note we use + * addition instead of *2 since it's easier to optimize. + */ + /* Some architectures and/or compilers seem to prefer a bit-shift nowadays */ + r = (mp_word)t.dp[ix + iy] + (r<<1) + (mp_word)u; + + /* store lower part */ + t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + + /* get carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + /* propagate upwards */ + while (u != 0uL) { + mp_digit tmp; + /* + "u" can get bigger than MP_DIGIT_MAX and would need a bigger type + for the sum (mp_word). That is costly if mp_word is not a native + integer but a bigint from the compiler library. We do a manual + multiword addition instead. + */ + /* t.dp[ix + iy] has been masked off by MP_MASK and is hence of the correct size + and we can just add the lower part of "u". Carry is guaranteed to fit into + the type used for mp_digit, too, so we can extract it later. */ + tmp = t.dp[ix + iy] + (u & MP_MASK); + /* t.dp[ix + iy] is set to the result minus the carry, carry is still in "tmp" */ + t.dp[ix + iy] = tmp & MP_MASK; + /* Add high part of "u" and the carry from "tmp" to get the next "u" */ + u = (u >> MP_DIGIT_BIT) + (tmp >> MP_DIGIT_BIT); + ++iy; + } + } + + mp_clamp(&t); + mp_exch(&t, b); + mp_clear(&t); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_comba.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_comba.c new file mode 100644 index 0000000..336a0a0 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_comba.c @@ -0,0 +1,91 @@ +#include "tommath_private.h" +#ifdef S_MP_SQR_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* the jist of squaring... + * you do like mult except the offset of the tmpx [one that + * starts closer to zero] can't equal the offset of tmpy. + * So basically you set up iy like before then you min it with + * (ty-tx) so that it never happens. You double all those + * you add in the inner loop + +After that loop you do the squares and add them in. +*/ + +mp_err s_mp_sqr_comba(const mp_int *a, mp_int *b) +{ + int oldused, pa, ix; + mp_digit MP_ALLOC_WARRAY(W); + mp_word W1; + mp_err err; + + MP_CHECK_WARRAY(W); + + /* grow the destination as required */ + pa = a->used + a->used; + if ((err = mp_grow(b, pa)) != MP_OKAY) { + MP_FREE_WARRAY(W); + return err; + } + + /* number of output digits to produce */ + W1 = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy, iz; + mp_word _W; + + /* clear counter */ + _W = 0; + + /* get offsets into the two bignums */ + ty = MP_MIN(a->used-1, ix); + tx = ix - ty; + + /* this is the number of times the loop will iterate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MP_MIN(a->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach at a rate of 2x + * and we have to round because odd cases need to be executed + */ + iy = MP_MIN(iy, ((ty-tx)+1)>>1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += (mp_word)a->dp[tx + iz] * (mp_word)a->dp[ty - iz]; + } + + /* double the inner product and add carry */ + _W = _W + _W + W1; + + /* even columns have the square term in them */ + if (((unsigned)ix & 1u) == 0u) { + _W += (mp_word)a->dp[ix>>1] * (mp_word)a->dp[ix>>1]; + } + + /* store it */ + W[ix] = (mp_digit)_W & MP_MASK; + + /* make next carry */ + W1 = _W >> (mp_word)MP_DIGIT_BIT; + } + + /* setup dest */ + oldused = b->used; + b->used = a->used+a->used; + + for (ix = 0; ix < pa; ix++) { + b->dp[ix] = W[ix] & MP_MASK; + } + + /* clear unused digits [that existed in the old copy of c] */ + s_mp_zero_digs(b->dp + b->used, oldused - b->used); + + mp_clamp(b); + MP_FREE_WARRAY(W); + return MP_OKAY; +} +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_karatsuba.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_karatsuba.c new file mode 100644 index 0000000..f064b46 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sqr_karatsuba.c @@ -0,0 +1,92 @@ +#include "tommath_private.h" +#ifdef S_MP_SQR_KARATSUBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Karatsuba squaring, computes b = a*a using three + * half size squarings + * + * See comments of mul_karatsuba for details. It + * is essentially the same algorithm but merely + * tuned to perform recursive squarings. + */ +mp_err s_mp_sqr_karatsuba(const mp_int *a, mp_int *b) +{ + mp_int x0, x1, t1, t2, x0x0, x1x1; + int B; + mp_err err; + + /* min # of digits */ + B = a->used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if ((err = mp_init_size(&x0, B)) != MP_OKAY) + goto LBL_ERR; + if ((err = mp_init_size(&x1, a->used - B)) != MP_OKAY) + goto X0; + + /* init temps */ + if ((err = mp_init_size(&t1, a->used * 2)) != MP_OKAY) + goto X1; + if ((err = mp_init_size(&t2, a->used * 2)) != MP_OKAY) + goto T1; + if ((err = mp_init_size(&x0x0, B * 2)) != MP_OKAY) + goto T2; + if ((err = mp_init_size(&x1x1, (a->used - B) * 2)) != MP_OKAY) + goto X0X0; + + /* now shift the digits */ + x0.used = B; + x1.used = a->used - B; + s_mp_copy_digs(x0.dp, a->dp, x0.used); + s_mp_copy_digs(x1.dp, a->dp + B, x1.used); + mp_clamp(&x0); + + /* now calc the products x0*x0 and x1*x1 */ + if ((err = mp_sqr(&x0, &x0x0)) != MP_OKAY) + goto X1X1; /* x0x0 = x0*x0 */ + if ((err = mp_sqr(&x1, &x1x1)) != MP_OKAY) + goto X1X1; /* x1x1 = x1*x1 */ + + /* now calc (x1+x0)**2 */ + if ((err = s_mp_add(&x1, &x0, &t1)) != MP_OKAY) + goto X1X1; /* t1 = x1 - x0 */ + if ((err = mp_sqr(&t1, &t1)) != MP_OKAY) + goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ + + /* add x0y0 */ + if ((err = s_mp_add(&x0x0, &x1x1, &t2)) != MP_OKAY) + goto X1X1; /* t2 = x0x0 + x1x1 */ + if ((err = s_mp_sub(&t1, &t2, &t1)) != MP_OKAY) + goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */ + + /* shift by B */ + if ((err = mp_lshd(&t1, B)) != MP_OKAY) + goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<used / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + if ((err = mp_init_size(&a2, a->used - (2 * B))) != MP_OKAY) goto LBL_ERRa2; + + a0.used = a1.used = B; + a2.used = a->used - 2 * B; + s_mp_copy_digs(a0.dp, a->dp, a0.used); + s_mp_copy_digs(a1.dp, a->dp + B, a1.used); + s_mp_copy_digs(a2.dp, a->dp + 2 * B, a2.used); + mp_clamp(&a0); + mp_clamp(&a1); + mp_clamp(&a2); + + /** S0 = a0^2; */ + if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR; + + /** \\S1 = (a2 + a1 + a0)^2 */ + /** \\S2 = (a2 - a1 + a0)^2 */ + /** \\S1 = a0 + a2; */ + /** a0 = a0 + a2; */ + if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S1 - a1; */ + /** b = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 + a1; */ + /** a0 = a0 + a1; */ + if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1^2; */ + /** a0 = a0^2; */ + if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2^2; */ + /** b = b^2; */ + if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S3 = 2 * a1 * a2 */ + /** \\S3 = a1 * a2; */ + /** a1 = a1 * a2; */ + if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR; + /** \\S3 = S3 << 1; */ + /** a1 = a1 << 1; */ + if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** \\S4 = a2^2; */ + /** a2 = a2^2; */ + if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR; + + /** \\ tmp = (S1 + S2)/2 */ + /** \\tmp = S1 + S2; */ + /** b = a0 + b; */ + if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR; + /** \\tmp = tmp >> 1; */ + /** b = b >> 1; */ + if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S1 = S1 - tmp - S3 */ + /** \\S1 = S1 - tmp; */ + /** a0 = a0 - b; */ + if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 - S3; */ + /** a0 = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = tmp - S4 -S0 */ + /** \\S2 = tmp - S4; */ + /** b = b - a2; */ + if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2 - S0; */ + /** b = b - S0; */ + if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + + + /** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */ + /** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */ + + if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + /** a^2 - P */ + + +LBL_ERR: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear(&S0); + + return err; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sub.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sub.c new file mode 100644 index 0000000..b1a749e --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_sub.c @@ -0,0 +1,56 @@ +#include "tommath_private.h" +#ifdef S_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) +{ + int oldused = c->used, min = b->used, max = a->used, i; + mp_digit u; + mp_err err; + + /* init result */ + if ((err = mp_grow(c, max)) != MP_OKAY) { + return err; + } + + c->used = max; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + c->dp[i] = (a->dp[i] - b->dp[i]) - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u); + + /* Clear carry from T[i] */ + c->dp[i] &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + c->dp[i] = a->dp[i] - u; + + /* U = carry bit of T[i] */ + u = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u); + + /* Clear carry from T[i] */ + c->dp[i] &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray.c new file mode 100644 index 0000000..1b8b068 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray.c @@ -0,0 +1,8 @@ +#include "tommath_private.h" +#ifdef S_MP_WARRAY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_thread st_warray s_mp_warray = { 0 }; + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_get.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_get.c new file mode 100644 index 0000000..26b0d7c --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_get.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef S_MP_WARRAY_GET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +void *s_mp_warray_get(void) +{ + if (s_mp_warray.w_used) + return NULL; + if (s_mp_warray.w_free == NULL) { + s_mp_warray.w_free = MP_CALLOC(MP_WARRAY, sizeof(mp_word)); + } + s_mp_warray.w_used = s_mp_warray.w_free; + s_mp_warray.w_free = NULL; + return s_mp_warray.w_used; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_put.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_put.c new file mode 100644 index 0000000..79e014a --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_warray_put.c @@ -0,0 +1,14 @@ +#include "tommath_private.h" +#ifdef S_MP_WARRAY_PUT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +void s_mp_warray_put(void *w) +{ + if (s_mp_warray.w_free || s_mp_warray.w_used != w) + return; + s_mp_warray.w_free = w; + s_mp_warray.w_used = NULL; +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_buf.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_buf.c new file mode 100644 index 0000000..23a458d --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_buf.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef S_MP_ZERO_BUF_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_USE_MEMOPS +# include +#endif + +void s_mp_zero_buf(void *mem, size_t size) +{ +#ifdef MP_USE_MEMOPS + memset(mem, 0, size); +#else + char *m = (char *)mem; + while (size-- > 0u) { + *m++ = '\0'; + } +#endif +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_digs.c b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_digs.c new file mode 100644 index 0000000..79e8377 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/s_mp_zero_digs.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef S_MP_ZERO_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_USE_MEMOPS +# include +#endif + +void s_mp_zero_digs(mp_digit *d, int digits) +{ +#ifdef MP_USE_MEMOPS + if (digits > 0) { + memset(d, 0, (size_t)digits * sizeof(mp_digit)); + } +#else + while (digits-- > 0) { + *d++ = 0; + } +#endif +} + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath.h b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath.h new file mode 100644 index 0000000..1820d24 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath.h @@ -0,0 +1,602 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMMATH_H_ +#define TOMMATH_H_ + +#include +#include +#include + +#ifndef MP_NO_FILE +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */ +#if (defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)) && !defined(MP_64BIT) +# define MP_32BIT +#endif + +/* detect 64-bit mode if possible */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ + defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ + defined(__LP64__) || defined(_LP64) || defined(__64BIT__) +# if !(defined(MP_64BIT) || defined(MP_32BIT) || defined(MP_16BIT)) +# if defined(__GNUC__) && defined(__SIZEOF_INT128__) && !defined(__hppa) +/* we support 128bit integers only via: __attribute__((mode(TI))) */ +# define MP_64BIT +# else +/* otherwise we fall back to MP_32BIT even on 64bit platforms */ +# define MP_32BIT +# endif +# endif +#endif + +#ifdef MP_DIGIT_BIT +# error Defining MP_DIGIT_BIT is disallowed, use MP_16/31/32/64BIT +#endif + +/* some default configurations. + * + * A "mp_digit" must be able to hold MP_DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*MP_DIGIT_BIT + 1 bits + * + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] + */ + +#if defined(MP_16BIT) +typedef uint16_t mp_digit; +# define MP_DIGIT_BIT 15 +#elif ((defined (MP_64BIT)) && !(defined(MP_31BIT)) ) +typedef uint64_t mp_digit; +# define MP_DIGIT_BIT 60 +#else +typedef uint32_t mp_digit; +# ifdef MP_31BIT +/* + * This is an extension that uses 31-bit digits. + * Please be aware that not all functions support this size, especially s_mp_mul_comba + * will be reduced to work on small numbers only: + * Up to 8 limbs, 248 bits instead of up to 512 limbs, 15872 bits with MP_28BIT. + */ +# define MP_DIGIT_BIT 31 +# else +/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ +# define MP_DIGIT_BIT 28 +# define MP_28BIT +# endif +#endif + +#define MP_MASK ((((mp_digit)1)<<((mp_digit)MP_DIGIT_BIT))-((mp_digit)1)) +#define MP_DIGIT_MAX MP_MASK + +/* Primality generation flags */ +#define MP_PRIME_BBS 0x0001 /* BBS style prime */ +#define MP_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define MP_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef enum { + MP_ZPOS = 0, /* positive */ + MP_NEG = 1 /* negative */ +} mp_sign; + +typedef enum { + MP_LT = -1, /* less than */ + MP_EQ = 0, /* equal */ + MP_GT = 1 /* greater than */ +} mp_ord; + +typedef enum { + MP_OKAY = 0, /* no error */ + MP_ERR = -1, /* unknown error */ + MP_MEM = -2, /* out of mem */ + MP_VAL = -3, /* invalid input */ + MP_ITER = -4, /* maximum iterations reached */ + MP_BUF = -5, /* buffer overflow, supplied buffer too small */ + MP_OVF = -6 /* mp_int overflow, too many digits */ +} mp_err; + +typedef enum { + MP_LSB_FIRST = -1, + MP_MSB_FIRST = 1 +} mp_order; + +typedef enum { + MP_LITTLE_ENDIAN = -1, + MP_NATIVE_ENDIAN = 0, + MP_BIG_ENDIAN = 1 +} mp_endian; + +/* tunable cutoffs */ +#ifndef MP_FIXED_CUTOFFS +extern int +MP_MUL_KARATSUBA_CUTOFF, +MP_SQR_KARATSUBA_CUTOFF, +MP_MUL_TOOM_CUTOFF, +MP_SQR_TOOM_CUTOFF; +#endif + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define MP_NULL_TERMINATED __attribute__((sentinel)) +#else +# define MP_NULL_TERMINATED +#endif + +/* + * MP_WUR - warn unused result + * --------------------------- + * + * The result of functions annotated with MP_WUR must be + * checked and cannot be ignored. + * + * Most functions in libtommath return an error code. + * This error code must be checked in order to prevent crashes or invalid + * results. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 +# define MP_WUR __attribute__((warn_unused_result)) +#else +# define MP_WUR +#endif + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) +# define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x))) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +# define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x)) +#else +# define MP_DEPRECATED(x) +#endif + +#ifndef MP_NO_DEPRECATED_PRAGMA +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) +# define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s) +# define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +# define MP_DEPRECATED_PRAGMA(s) __pragma(message(s)) +#endif +#endif + +#ifndef MP_DEPRECATED_PRAGMA +# define MP_DEPRECATED_PRAGMA(s) +#endif + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc; + mp_sign sign; + mp_digit *dp; +} mp_int; + +/* error code to char* string */ +const char *mp_error_to_string(mp_err code) MP_WUR; + +/* ---> init and deinit bignum functions <--- */ +/* init a bignum */ +mp_err mp_init(mp_int *a) MP_WUR; + +/* free a bignum */ +void mp_clear(mp_int *a); + +/* init a null terminated series of arguments */ +mp_err mp_init_multi(mp_int *mp, ...) MP_NULL_TERMINATED MP_WUR; + +/* clear a null terminated series of arguments */ +void mp_clear_multi(mp_int *mp, ...) MP_NULL_TERMINATED; + +/* exchange two ints */ +void mp_exch(mp_int *a, mp_int *b); + +/* shrink ram required for a bignum */ +mp_err mp_shrink(mp_int *a) MP_WUR; + +/* grow an int to a given size */ +mp_err mp_grow(mp_int *a, int size) MP_WUR; + +/* init to a given number of digits */ +mp_err mp_init_size(mp_int *a, int size) MP_WUR; + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) ((a)->used == 0) +#define mp_isone(a) ( ((a)->sign == MP_ZPOS) && ((a)->used == 1u) && ((a)->dp[0] == 1u) ) +#define mp_isneg(a) ((a)->sign == MP_NEG) +#define mp_iseven(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u)) +#define mp_isodd(a) (!mp_iseven(a)) + +/* set to zero */ +void mp_zero(mp_int *a); + +/* get and set doubles */ +double mp_get_double(const mp_int *a) MP_WUR; +mp_err mp_set_double(mp_int *a, double b) MP_WUR; + +/* get integer, set integer and init with integer (int32_t) */ +int32_t mp_get_i32(const mp_int *a) MP_WUR; +void mp_set_i32(mp_int *a, int32_t b); +mp_err mp_init_i32(mp_int *a, int32_t b) MP_WUR; + +/* get integer, set integer and init with integer, behaves like two complement for negative numbers (uint32_t) */ +#define mp_get_u32(a) ((uint32_t)mp_get_i32(a)) +void mp_set_u32(mp_int *a, uint32_t b); +mp_err mp_init_u32(mp_int *a, uint32_t b) MP_WUR; + +/* get integer, set integer and init with integer (int64_t) */ +int64_t mp_get_i64(const mp_int *a) MP_WUR; +void mp_set_i64(mp_int *a, int64_t b); +mp_err mp_init_i64(mp_int *a, int64_t b) MP_WUR; + +/* get integer, set integer and init with integer, behaves like two complement for negative numbers (uint64_t) */ +#define mp_get_u64(a) ((uint64_t)mp_get_i64(a)) +void mp_set_u64(mp_int *a, uint64_t b); +mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR; + +/* get magnitude */ +uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR; +uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR; +unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR; + +/* get integer, set integer (long) */ +long mp_get_l(const mp_int *a) MP_WUR; +void mp_set_l(mp_int *a, long b); +mp_err mp_init_l(mp_int *a, long b) MP_WUR; + +/* get integer, set integer (unsigned long) */ +#define mp_get_ul(a) ((unsigned long)mp_get_l(a)) +void mp_set_ul(mp_int *a, unsigned long b); +mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR; + +/* set to single unsigned digit, up to MP_DIGIT_MAX */ +void mp_set(mp_int *a, mp_digit b); +mp_err mp_init_set(mp_int *a, mp_digit b) MP_WUR; + +/* copy, b = a */ +mp_err mp_copy(const mp_int *a, mp_int *b) MP_WUR; + +/* inits and copies, a = b */ +mp_err mp_init_copy(mp_int *a, const mp_int *b) MP_WUR; + +/* trim unused digits */ +void mp_clamp(mp_int *a); + +/* unpack binary data */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, mp_endian endian, + size_t nails, const void *op) MP_WUR; + +/* pack binary data */ +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) MP_WUR; +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) MP_WUR; + +/* ---> digit manipulation <--- */ + +/* right shift by "b" digits */ +void mp_rshd(mp_int *a, int b); + +/* left shift by "b" digits */ +mp_err mp_lshd(mp_int *a, int b) MP_WUR; + +/* c = a / 2**b, implemented as c = a >> b */ +mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR; + +/* b = a/2 */ +mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR; + +/* c = a * 2**b, implemented as c = a << b */ +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* b = a*2 */ +mp_err mp_mul_2(const mp_int *a, mp_int *b) MP_WUR; + +/* c = a mod 2**b */ +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* computes a = 2**b */ +mp_err mp_2expt(mp_int *a, int b) MP_WUR; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(const mp_int *a) MP_WUR; + +/* I Love Earth! */ + +/* makes a pseudo-random mp_int of a given size */ +mp_err mp_rand(mp_int *a, int digits) MP_WUR; +/* use custom random data source instead of source provided the platform */ +void mp_rand_source(mp_err(*source)(void *out, size_t size)); + +/* ---> binary operations <--- */ + +/* c = a XOR b (two complement) */ +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a OR b (two complement) */ +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a AND b (two complement) */ +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* b = ~a (bitwise not, two complement) */ +mp_err mp_complement(const mp_int *a, mp_int *b) MP_WUR; + +/* right shift with sign extension */ +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* ---> Basic arithmetic <--- */ + +/* b = -a */ +mp_err mp_neg(const mp_int *a, mp_int *b) MP_WUR; + +/* b = |a| */ +mp_err mp_abs(const mp_int *a, mp_int *b) MP_WUR; + +/* compare a to b */ +mp_ord mp_cmp(const mp_int *a, const mp_int *b) MP_WUR; + +/* compare |a| to |b| */ +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) MP_WUR; + +/* c = a + b */ +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a - b */ +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a * b */ +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* b = a*a */ +#define mp_sqr(a, b) mp_mul((a), (a), (b)) + +/* a/b => cb + d == a */ +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; + +/* c = a mod b, 0 <= c < b */ +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* Increment "a" by one like "a++". Changes input! */ +#define mp_incr(a) mp_add_d((a), 1u, (a)) + +/* Decrement "a" by one like "a--". Changes input! */ +#define mp_decr(a) mp_sub_d((a), 1u, (a)) + +/* ---> single digit functions <--- */ + +/* compare against a single digit */ +mp_ord mp_cmp_d(const mp_int *a, mp_digit b) MP_WUR; + +/* c = a + b */ +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; + +/* c = a - b */ +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; + +/* c = a * b */ +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; + +/* a/b => cb + d == a */ +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) MP_WUR; + +/* c = a mod b, 0 <= c < b */ +#define mp_mod_d(a, b, c) mp_div_d((a), (b), NULL, (c)) + +/* ---> number theory <--- */ + +/* d = a + b (mod c) */ +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; + +/* d = a - b (mod c) */ +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; + +/* d = a * b (mod c) */ +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; + +/* c = a * a (mod b) */ +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = 1/a (mod b) */ +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = (a, b) */ +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* produces value such that U1*a + U2*b = U3 */ +mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) MP_WUR; + +/* c = [a, b] or (a*b)/(a, b) */ +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* Integer logarithm to integer base */ +mp_err mp_log_n(const mp_int *a, int base, int *c) MP_WUR; + +/* Integer logarithm to bigint base */ +mp_err mp_log(const mp_int *a, const mp_int *base, int *c) MP_WUR; + +/* c = a**b */ +mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* finds one of the b'th root of a, such that |c|**b <= |a| + * + * returns error if a < 0 and b is even + */ +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* special sqrt algo */ +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) MP_WUR; + +/* special sqrt (mod prime) */ +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) MP_WUR; + +/* is number a square? */ +mp_err mp_is_square(const mp_int *arg, bool *ret) MP_WUR; + +/* computes the Kronecker symbol c = (a | p) (like jacobi() but with {a,p} in Z */ +mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c) MP_WUR; + +/* used to setup the Barrett reduction for a given modulus b */ +mp_err mp_reduce_setup(mp_int *a, const mp_int *b) MP_WUR; + +/* Barrett Reduction, computes a (mod b) with a precomputed value c + * + * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely + * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code]. + */ +mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) MP_WUR; + +/* setups the montgomery reduction */ +mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho) MP_WUR; + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) MP_WUR; + +/* computes x/R == x (mod N) via Montgomery Reduction */ +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; + +/* returns 1 if a is a valid DR modulus */ +bool mp_dr_is_modulus(const mp_int *a) MP_WUR; + +/* sets the value of "d" required for mp_dr_reduce */ +void mp_dr_setup(const mp_int *a, mp_digit *d); + +/* reduces a modulo n using the Diminished Radix method */ +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) MP_WUR; + +/* returns true if a can be reduced with mp_reduce_2k */ +bool mp_reduce_is_2k(const mp_int *a) MP_WUR; + +/* determines k value for 2k reduction */ +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) MP_WUR; + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) MP_WUR; + +/* returns true if a can be reduced with mp_reduce_2k_l */ +bool mp_reduce_is_2k_l(const mp_int *a) MP_WUR; + +/* determines k value for 2k reduction */ +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) MP_WUR; + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) MP_WUR; + +/* Y = G**X (mod P) */ +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) MP_WUR; + +#if defined(MP_16BIT) +typedef uint32_t mp_hval; +#else +typedef uint64_t mp_hval; +#endif + +/* computes hash */ +mp_err mp_hash(const mp_int *a, mp_hval *hash) MP_WUR; + +/* ---> Primes <--- */ + +/* performs one Fermat test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, bool *result) MP_WUR; + +/* performs one Miller-Rabin test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, bool *result) MP_WUR; + +/* This gives [for a given bit size] the number of trials required + * such that Miller-Rabin gives a prob of failure lower than 2^-96 + */ +int mp_prime_rabin_miller_trials(int size) MP_WUR; + +/* performs one strong Lucas-Selfridge test of "a". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result) MP_WUR; + +/* performs one Frobenius test of "a" as described by Paul Underwood. + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_frobenius_underwood(const mp_int *N, bool *result) MP_WUR; + +/* performs t random rounds of Miller-Rabin on "a" additional to + * bases 2 and 3. Also performs an initial sieve of trial + * division. Determines if "a" is prime with probability + * of error no more than (1/4)**t. + * Both a strong Lucas-Selfridge to complete the BPSW test + * and a separate Frobenius test are available at compile time. + * With t<0 a deterministic test is run for primes up to + * 318665857834031151167461. With t<13 (abs(t)-13) additional + * tests with sequential small primes are run starting at 43. + * Is Fips 186.4 compliant if called with t as computed by + * mp_prime_rabin_miller_trials(); + * + * Sets result to 1 if probably prime, 0 otherwise + */ +mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) MP_WUR; + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = true means the prime must be congruent to 3 mod 4 + */ +mp_err mp_prime_next_prime(mp_int *a, int t, bool bbs_style) MP_WUR; + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR; + +/* ---> radix conversion <--- */ +int mp_count_bits(const mp_int *a) MP_WUR; + +size_t mp_ubin_size(const mp_int *a) MP_WUR; +mp_err mp_from_ubin(mp_int *a, const uint8_t *buf, size_t size) MP_WUR; +mp_err mp_to_ubin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) MP_WUR; + +size_t mp_sbin_size(const mp_int *a) MP_WUR; +mp_err mp_from_sbin(mp_int *a, const uint8_t *buf, size_t size) MP_WUR; +mp_err mp_to_sbin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) MP_WUR; + +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; +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; +#endif + +int mp_warray_free(void); + +#define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), NULL, 2) +#define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), NULL, 8) +#define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), NULL, 10) +#define mp_to_hex(M, S, N) mp_to_radix((M), (S), (N), NULL, 16) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_c89.h b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_c89.h new file mode 100644 index 0000000..2243636 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_c89.h @@ -0,0 +1,46 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * This header defines custom types which + * are used in c89 mode. + * + * By default, the source uses stdbool.h + * and stdint.h. The command `make c89` + * can be used to convert the source, + * such that this header is used instead. + * Use `make c99` to convert back. + * + * Please adapt the following definitions to your needs! + */ + +/* stdbool.h replacement types */ +typedef enum { MP_NO, MP_YES } mp_bool; + +/* stdint.h replacement types */ +typedef __INT8_TYPE__ mp_i8; +typedef __INT16_TYPE__ mp_i16; +typedef __INT32_TYPE__ mp_i32; +typedef __INT64_TYPE__ mp_i64; +typedef __UINT8_TYPE__ mp_u8; +typedef __UINT16_TYPE__ mp_u16; +typedef __UINT32_TYPE__ mp_u32; +typedef __UINT64_TYPE__ mp_u64; +# if __WORDSIZE == 64 +typedef __UINT64_TYPE__ mp_uintptr; +# else +typedef __UINT32_TYPE__ mp_uintptr; +# endif + +/* inttypes.h replacement, printf format specifier */ +# if __WORDSIZE == 64 +# define MP_PRI64_PREFIX "l" +# else +# define MP_PRI64_PREFIX "ll" +# endif +#define MP_PRIi64 MP_PRI64_PREFIX "i" +#define MP_PRIu64 MP_PRI64_PREFIX "u" +#define MP_PRIx64 MP_PRI64_PREFIX "x" +#define MP_PRIo64 MP_PRI64_PREFIX "o" + +#define MP_FUNCTION_NAME __func__ diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_class.h b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_class.h new file mode 100644 index 0000000..09bb3ea --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_class.h @@ -0,0 +1,1323 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#define LTM_INSIDE +#if defined(LTM2) +# define LTM3 +#endif +#if defined(LTM1) +# define LTM2 +#endif +#define LTM1 +#if defined(LTM_ALL) +# define MP_2EXPT_C +# define MP_ABS_C +# define MP_ADD_C +# define MP_ADD_D_C +# define MP_ADDMOD_C +# define MP_AND_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CMP_MAG_C +# define MP_CNT_LSB_C +# define MP_COMPLEMENT_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_CUTOFFS_C +# define MP_DIV_C +# define MP_DIV_2_C +# define MP_DIV_2D_C +# define MP_DIV_D_C +# define MP_DR_IS_MODULUS_C +# define MP_DR_REDUCE_C +# define MP_DR_SETUP_C +# define MP_ERROR_TO_STRING_C +# define MP_EXCH_C +# define MP_EXPT_N_C +# define MP_EXPTMOD_C +# define MP_EXTEUCLID_C +# define MP_FREAD_C +# define MP_FROM_SBIN_C +# define MP_FROM_UBIN_C +# define MP_FWRITE_C +# define MP_GCD_C +# define MP_GET_DOUBLE_C +# define MP_GET_I32_C +# define MP_GET_I64_C +# define MP_GET_L_C +# define MP_GET_MAG_U32_C +# define MP_GET_MAG_U64_C +# define MP_GET_MAG_UL_C +# define MP_GROW_C +# define MP_HASH_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_INIT_I32_C +# define MP_INIT_I64_C +# define MP_INIT_L_C +# define MP_INIT_MULTI_C +# define MP_INIT_SET_C +# define MP_INIT_SIZE_C +# define MP_INIT_U32_C +# define MP_INIT_U64_C +# define MP_INIT_UL_C +# define MP_INVMOD_C +# define MP_IS_SQUARE_C +# define MP_KRONECKER_C +# define MP_LCM_C +# define MP_LOG_C +# define MP_LOG_N_C +# define MP_LSHD_C +# define MP_MOD_C +# define MP_MOD_2D_C +# define MP_MONTGOMERY_CALC_NORMALIZATION_C +# define MP_MONTGOMERY_REDUCE_C +# define MP_MONTGOMERY_SETUP_C +# define MP_MUL_C +# define MP_MUL_2_C +# define MP_MUL_2D_C +# define MP_MUL_D_C +# define MP_MULMOD_C +# define MP_NEG_C +# define MP_OR_C +# define MP_PACK_C +# define MP_PACK_COUNT_C +# define MP_PRIME_FERMAT_C +# define MP_PRIME_FROBENIUS_UNDERWOOD_C +# define MP_PRIME_IS_PRIME_C +# define MP_PRIME_MILLER_RABIN_C +# define MP_PRIME_NEXT_PRIME_C +# define MP_PRIME_RABIN_MILLER_TRIALS_C +# 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_RAND_SOURCE_C +# define MP_READ_RADIX_C +# define MP_REDUCE_C +# define MP_REDUCE_2K_C +# define MP_REDUCE_2K_L_C +# define MP_REDUCE_2K_SETUP_C +# define MP_REDUCE_2K_SETUP_L_C +# define MP_REDUCE_IS_2K_C +# define MP_REDUCE_IS_2K_L_C +# define MP_REDUCE_SETUP_C +# define MP_ROOT_N_C +# define MP_RSHD_C +# define MP_SBIN_SIZE_C +# define MP_SET_C +# define MP_SET_DOUBLE_C +# define MP_SET_I32_C +# define MP_SET_I64_C +# define MP_SET_L_C +# define MP_SET_U32_C +# define MP_SET_U64_C +# define MP_SET_UL_C +# define MP_SHRINK_C +# define MP_SIGNED_RSH_C +# define MP_SQRMOD_C +# define MP_SQRT_C +# define MP_SQRTMOD_PRIME_C +# define MP_SUB_C +# define MP_SUB_D_C +# define MP_SUBMOD_C +# define MP_TO_RADIX_C +# define MP_TO_SBIN_C +# define MP_TO_UBIN_C +# define MP_UBIN_SIZE_C +# define MP_UNPACK_C +# define MP_WARRAY_FREE_C +# define MP_XOR_C +# define MP_ZERO_C +# define S_MP_ADD_C +# define S_MP_COPY_DIGS_C +# define S_MP_DIV_3_C +# define S_MP_DIV_RECURSIVE_C +# define S_MP_DIV_SCHOOL_C +# define S_MP_DIV_SMALL_C +# define S_MP_EXPTMOD_C +# define S_MP_EXPTMOD_FAST_C +# define S_MP_FP_LOG_C +# define S_MP_FP_LOG_D_C +# define S_MP_GET_BIT_C +# define S_MP_INVMOD_C +# define S_MP_INVMOD_ODD_C +# define S_MP_LOG_2EXPT_C +# define S_MP_MONTGOMERY_REDUCE_COMBA_C +# define S_MP_MUL_C +# define S_MP_MUL_BALANCE_C +# define S_MP_MUL_COMBA_C +# define S_MP_MUL_HIGH_C +# define S_MP_MUL_HIGH_COMBA_C +# define S_MP_MUL_KARATSUBA_C +# define S_MP_MUL_TOOM_C +# 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_PLATFORM_C +# define S_MP_SQR_C +# define S_MP_SQR_COMBA_C +# define S_MP_SQR_KARATSUBA_C +# define S_MP_SQR_TOOM_C +# define S_MP_SUB_C +# define S_MP_WARRAY_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C +# define S_MP_ZERO_BUF_C +# define S_MP_ZERO_DIGS_C +#endif +#endif +#if defined(MP_2EXPT_C) +# define MP_GROW_C +# define MP_ZERO_C +#endif + +#if defined(MP_ABS_C) +# define MP_COPY_C +#endif + +#if defined(MP_ADD_C) +# define MP_CMP_MAG_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_ADD_D_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define MP_SUB_D_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_ADDMOD_C) +# define MP_ADD_C +# define MP_MOD_C +#endif + +#if defined(MP_AND_C) +# define MP_CLAMP_C +# define MP_GROW_C +#endif + +#if defined(MP_CLAMP_C) +#endif + +#if defined(MP_CLEAR_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_CLEAR_MULTI_C) +# define MP_CLEAR_C +#endif + +#if defined(MP_CMP_C) +# define MP_CMP_MAG_C +#endif + +#if defined(MP_CMP_D_C) +#endif + +#if defined(MP_CMP_MAG_C) +#endif + +#if defined(MP_CNT_LSB_C) +#endif + +#if defined(MP_COMPLEMENT_C) +# define MP_SUB_D_C +#endif + +#if defined(MP_COPY_C) +# define MP_GROW_C +# define S_MP_COPY_DIGS_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_COUNT_BITS_C) +#endif + +#if defined(MP_CUTOFFS_C) +#endif + +#if defined(MP_DIV_C) +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_ZERO_C +# define S_MP_DIV_RECURSIVE_C +# define S_MP_DIV_SCHOOL_C +# define S_MP_DIV_SMALL_C +#endif + +#if defined(MP_DIV_2_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_DIV_2D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_MOD_2D_C +# define MP_RSHD_C +#endif + +#if defined(MP_DIV_D_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_DIV_2D_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define S_MP_DIV_3_C +#endif + +#if defined(MP_DR_IS_MODULUS_C) +#endif + +#if defined(MP_DR_REDUCE_C) +# define MP_CLAMP_C +# define MP_CMP_MAG_C +# define MP_GROW_C +# define S_MP_SUB_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_DR_SETUP_C) +#endif + +#if defined(MP_ERROR_TO_STRING_C) +#endif + +#if defined(MP_EXCH_C) +#endif + +#if defined(MP_EXPT_N_C) +# define MP_CLEAR_C +# define MP_INIT_COPY_C +# define MP_MUL_C +# define MP_SET_C +#endif + +#if defined(MP_EXPTMOD_C) +# define MP_ABS_C +# define MP_CLEAR_MULTI_C +# define MP_DR_IS_MODULUS_C +# define MP_INIT_MULTI_C +# define MP_INVMOD_C +# define MP_REDUCE_IS_2K_C +# define MP_REDUCE_IS_2K_L_C +# define S_MP_EXPTMOD_C +# define S_MP_EXPTMOD_FAST_C +#endif + +#if defined(MP_EXTEUCLID_C) +# define MP_CLEAR_MULTI_C +# define MP_COPY_C +# define MP_DIV_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_NEG_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(MP_FREAD_C) +# define MP_ADD_D_C +# define MP_MUL_D_C +# define MP_ZERO_C +#endif + +#if defined(MP_FROM_SBIN_C) +# define MP_FROM_UBIN_C +#endif + +#if defined(MP_FROM_UBIN_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define MP_MUL_2D_C +# define MP_ZERO_C +#endif + +#if defined(MP_FWRITE_C) +# define MP_RADIX_SIZE_OVERESTIMATE_C +# define MP_TO_RADIX_C +# define S_MP_ZERO_BUF_C +#endif + +#if defined(MP_GCD_C) +# define MP_ABS_C +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_CNT_LSB_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_COPY_C +# define MP_MUL_2D_C +# define S_MP_SUB_C +#endif + +#if defined(MP_GET_DOUBLE_C) +#endif + +#if defined(MP_GET_I32_C) +# define MP_GET_MAG_U32_C +#endif + +#if defined(MP_GET_I64_C) +# define MP_GET_MAG_U64_C +#endif + +#if defined(MP_GET_L_C) +# define MP_GET_MAG_UL_C +#endif + +#if defined(MP_GET_MAG_U32_C) +#endif + +#if defined(MP_GET_MAG_U64_C) +#endif + +#if defined(MP_GET_MAG_UL_C) +#endif + +#if defined(MP_GROW_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_HASH_C) +#endif + +#if defined(MP_INIT_C) +#endif + +#if defined(MP_INIT_COPY_C) +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_INIT_SIZE_C +#endif + +#if defined(MP_INIT_I32_C) +# define MP_INIT_C +# define MP_SET_I32_C +#endif + +#if defined(MP_INIT_I64_C) +# define MP_INIT_C +# define MP_SET_I64_C +#endif + +#if defined(MP_INIT_L_C) +# define MP_INIT_C +# define MP_SET_L_C +#endif + +#if defined(MP_INIT_MULTI_C) +# define MP_CLEAR_C +# define MP_INIT_C +#endif + +#if defined(MP_INIT_SET_C) +# define MP_INIT_C +# define MP_SET_C +#endif + +#if defined(MP_INIT_SIZE_C) +#endif + +#if defined(MP_INIT_U32_C) +# define MP_INIT_C +# define MP_SET_U32_C +#endif + +#if defined(MP_INIT_U64_C) +# define MP_INIT_C +# define MP_SET_U64_C +#endif + +#if defined(MP_INIT_UL_C) +# define MP_INIT_C +# define MP_SET_UL_C +#endif + +#if defined(MP_INVMOD_C) +# define MP_CMP_D_C +# define MP_ZERO_C +# define S_MP_INVMOD_C +# define S_MP_INVMOD_ODD_C +#endif + +#if defined(MP_IS_SQUARE_C) +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_DIV_D_C +# define MP_GET_I32_C +# define MP_INIT_U32_C +# define MP_MOD_C +# define MP_MUL_C +# define MP_SQRT_C +#endif + +#if defined(MP_KRONECKER_C) +# define MP_CLEAR_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_COPY_C +# define MP_DIV_2D_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_MOD_C +#endif + +#if defined(MP_LCM_C) +# define MP_CLEAR_MULTI_C +# define MP_CMP_MAG_C +# define MP_DIV_C +# define MP_GCD_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +#endif + +#if defined(MP_LOG_C) +# define MP_ADD_D_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_COUNT_BITS_C +# define MP_DIV_2_C +# define MP_DIV_C +# define MP_DIV_D_C +# define MP_EXPT_N_C +# define MP_GET_I32_C +# define MP_INIT_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_MUL_D_C +# define MP_SUB_C +# define S_MP_FP_LOG_C +# define S_MP_FP_LOG_D_C +#endif + +#if defined(MP_LOG_N_C) +# define MP_CLEAR_C +# define MP_INIT_I32_C +# define MP_LOG_C +#endif + +#if defined(MP_LSHD_C) +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MOD_C) +# define MP_ADD_C +# define MP_DIV_C +#endif + +#if defined(MP_MOD_2D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_ZERO_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MONTGOMERY_CALC_NORMALIZATION_C) +# define MP_2EXPT_C +# define MP_CMP_MAG_C +# define MP_COUNT_BITS_C +# define MP_MUL_2_C +# define MP_SET_C +# define S_MP_SUB_C +#endif + +#if defined(MP_MONTGOMERY_REDUCE_C) +# define MP_CLAMP_C +# define MP_CMP_MAG_C +# define MP_GROW_C +# define MP_RSHD_C +# define S_MP_MONTGOMERY_REDUCE_COMBA_C +# define S_MP_SUB_C +#endif + +#if defined(MP_MONTGOMERY_SETUP_C) +#endif + +#if defined(MP_MUL_C) +# define S_MP_MUL_BALANCE_C +# define S_MP_MUL_C +# define S_MP_MUL_COMBA_C +# define S_MP_MUL_KARATSUBA_C +# define S_MP_MUL_TOOM_C +# define S_MP_SQR_C +# define S_MP_SQR_COMBA_C +# define S_MP_SQR_KARATSUBA_C +# define S_MP_SQR_TOOM_C +#endif + +#if defined(MP_MUL_2_C) +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MUL_2D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_GROW_C +# define MP_LSHD_C +#endif + +#if defined(MP_MUL_D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_GROW_C +# define MP_MUL_2D_C +# define MP_MUL_2_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MULMOD_C) +# define MP_MOD_C +# define MP_MUL_C +#endif + +#if defined(MP_NEG_C) +# define MP_COPY_C +#endif + +#if defined(MP_OR_C) +# define MP_CLAMP_C +# define MP_GROW_C +#endif + +#if defined(MP_PACK_C) +# define MP_CLEAR_C +# define MP_DIV_2D_C +# define MP_INIT_COPY_C +# define MP_PACK_COUNT_C +#endif + +#if defined(MP_PACK_COUNT_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(MP_PRIME_FERMAT_C) +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_EXPTMOD_C +# define MP_INIT_C +#endif + +#if defined(MP_PRIME_FROBENIUS_UNDERWOOD_C) +# define MP_ADD_C +# define MP_ADD_D_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COUNT_BITS_C +# define MP_EXCH_C +# define MP_GCD_C +# define MP_INIT_MULTI_C +# define MP_KRONECKER_C +# define MP_MOD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_MUL_D_C +# define MP_SET_C +# define MP_SET_I32_C +# define MP_SET_U32_C +# define MP_SUB_C +# define S_MP_GET_BIT_C +#endif + +#if defined(MP_PRIME_IS_PRIME_C) +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_INIT_SET_C +# define MP_IS_SQUARE_C +# define MP_PRIME_MILLER_RABIN_C +# define MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define MP_RAND_C +# define MP_READ_RADIX_C +# define MP_SET_C +# define S_MP_PRIME_IS_DIVISIBLE_C +#endif + +#if defined(MP_PRIME_MILLER_RABIN_C) +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_DIV_2D_C +# define MP_EXPTMOD_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_SQRMOD_C +# define MP_SUB_D_C +#endif + +#if defined(MP_PRIME_NEXT_PRIME_C) +# define MP_ADD_D_C +# define MP_CLEAR_C +# define MP_CMP_D_C +# define MP_DIV_D_C +# define MP_INIT_C +# define MP_PRIME_IS_PRIME_C +# define MP_SET_C +# define MP_SUB_D_C +#endif + +#if defined(MP_PRIME_RABIN_MILLER_TRIALS_C) +#endif + +#if defined(MP_PRIME_RAND_C) +# define MP_ADD_D_C +# define MP_DIV_2_C +# define MP_FROM_UBIN_C +# define MP_MUL_2_C +# define MP_PRIME_IS_PRIME_C +# define MP_SUB_D_C +# define S_MP_RAND_SOURCE_C +# define S_MP_ZERO_BUF_C +#endif + +#if defined(MP_PRIME_STRONG_LUCAS_SELFRIDGE_C) +# define MP_ADD_C +# define MP_ADD_D_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_DIV_2_C +# define MP_GCD_C +# define MP_INIT_C +# define MP_INIT_MULTI_C +# define MP_KRONECKER_C +# define MP_MOD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_SET_C +# define MP_SET_I32_C +# define MP_SET_U32_C +# define MP_SUB_C +# define MP_SUB_D_C +# define S_MP_GET_BIT_C +#endif + +#if defined(MP_RADIX_SIZE_C) +# 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_ZERO_C +# define S_MP_RAND_SOURCE_C +#endif + +#if defined(MP_RAND_SOURCE_C) +# define S_MP_RAND_PLATFORM_C +#endif + +#if defined(MP_READ_RADIX_C) +# define MP_ADD_D_C +# define MP_MUL_D_C +# define MP_ZERO_C +#endif + +#if defined(MP_REDUCE_C) +# define MP_ADD_C +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_INIT_COPY_C +# define MP_LSHD_C +# define MP_MOD_2D_C +# define MP_MUL_C +# define MP_RSHD_C +# define MP_SET_C +# define MP_SUB_C +# define S_MP_MUL_C +# define S_MP_MUL_HIGH_C +# define S_MP_MUL_HIGH_COMBA_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_C) +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_INIT_C +# define MP_MUL_D_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_L_C) +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_INIT_C +# define MP_MUL_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_SETUP_C) +# define MP_2EXPT_C +# define MP_CLEAR_C +# define MP_COUNT_BITS_C +# define MP_INIT_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_SETUP_L_C) +# define MP_2EXPT_C +# define MP_CLEAR_C +# define MP_COUNT_BITS_C +# define MP_INIT_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_IS_2K_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(MP_REDUCE_IS_2K_L_C) +#endif + +#if defined(MP_REDUCE_SETUP_C) +# define MP_2EXPT_C +# define MP_DIV_C +#endif + +#if defined(MP_ROOT_N_C) +# define MP_2EXPT_C +# define MP_ADD_D_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_DIV_C +# define MP_EXCH_C +# define MP_EXPT_N_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_MUL_D_C +# define MP_SET_C +# define MP_SUB_C +# define MP_SUB_D_C +#endif + +#if defined(MP_RSHD_C) +# define MP_ZERO_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SBIN_SIZE_C) +# define MP_UBIN_SIZE_C +#endif + +#if defined(MP_SET_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SET_DOUBLE_C) +# define MP_DIV_2D_C +# define MP_MUL_2D_C +# define MP_SET_U64_C +#endif + +#if defined(MP_SET_I32_C) +# define MP_SET_U32_C +#endif + +#if defined(MP_SET_I64_C) +# define MP_SET_U64_C +#endif + +#if defined(MP_SET_L_C) +# define MP_SET_UL_C +#endif + +#if defined(MP_SET_U32_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SET_U64_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SET_UL_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SHRINK_C) +#endif + +#if defined(MP_SIGNED_RSH_C) +# define MP_ADD_D_C +# define MP_DIV_2D_C +# define MP_SUB_D_C +#endif + +#if defined(MP_SQRMOD_C) +# define MP_MOD_C +# define MP_MUL_C +#endif + +#if defined(MP_SQRT_C) +# define MP_ADD_C +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_DIV_2_C +# define MP_DIV_C +# define MP_EXCH_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_RSHD_C +# define MP_ZERO_C +#endif + +#if defined(MP_SQRTMOD_PRIME_C) +# define MP_ADD_D_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_D_C +# define MP_COPY_C +# define MP_DIV_2_C +# define MP_EXPTMOD_C +# define MP_INIT_MULTI_C +# define MP_KRONECKER_C +# define MP_MULMOD_C +# define MP_SET_C +# define MP_SET_I32_C +# define MP_SQRMOD_C +# define MP_SUB_D_C +# define MP_ZERO_C +#endif + +#if defined(MP_SUB_C) +# define MP_CMP_MAG_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_SUB_D_C) +# define MP_ADD_D_C +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SUBMOD_C) +# define MP_MOD_C +# define MP_SUB_C +#endif + +#if defined(MP_TO_RADIX_C) +# define MP_CLEAR_C +# define MP_DIV_D_C +# define MP_INIT_COPY_C +#endif + +#if defined(MP_TO_SBIN_C) +# define MP_TO_UBIN_C +#endif + +#if defined(MP_TO_UBIN_C) +# define MP_CLEAR_C +# define MP_DIV_2D_C +# define MP_INIT_COPY_C +# define MP_UBIN_SIZE_C +#endif + +#if defined(MP_UBIN_SIZE_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(MP_UNPACK_C) +# define MP_CLAMP_C +# define MP_MUL_2D_C +# define MP_ZERO_C +#endif + +#if defined(MP_WARRAY_FREE_C) +# define S_MP_ZERO_BUF_C +#endif + +#if defined(MP_XOR_C) +# define MP_CLAMP_C +# define MP_GROW_C +#endif + +#if defined(MP_ZERO_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_ADD_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_COPY_DIGS_C) +#endif + +#if defined(S_MP_DIV_3_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +#endif + +#if defined(S_MP_DIV_RECURSIVE_C) +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_D_C +# define MP_COPY_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_LSHD_C +# define MP_MUL_2D_C +# define MP_MUL_C +# define MP_SUB_C +# define MP_SUB_D_C +# define MP_ZERO_C +# define S_MP_DIV_SCHOOL_C +#endif + +#if defined(S_MP_DIV_SCHOOL_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_2D_C +# define MP_MUL_D_C +# define MP_RSHD_C +# define MP_SUB_C +# define MP_ZERO_C +#endif + +#if defined(S_MP_DIV_SMALL_C) +# define MP_ABS_C +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MUL_2D_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(S_MP_EXPTMOD_C) +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_EXCH_C +# define MP_INIT_C +# define MP_MOD_C +# define MP_MUL_C +# define MP_REDUCE_2K_L_C +# define MP_REDUCE_2K_SETUP_L_C +# define MP_REDUCE_C +# define MP_REDUCE_SETUP_C +# define MP_SET_C +#endif + +#if defined(S_MP_EXPTMOD_FAST_C) +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_DR_REDUCE_C +# define MP_DR_SETUP_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define MP_MOD_C +# define MP_MONTGOMERY_CALC_NORMALIZATION_C +# define MP_MONTGOMERY_REDUCE_C +# define MP_MONTGOMERY_SETUP_C +# define MP_MULMOD_C +# define MP_MUL_C +# define MP_REDUCE_2K_C +# define MP_REDUCE_2K_SETUP_C +# define MP_SET_C +# define S_MP_MONTGOMERY_REDUCE_COMBA_C +#endif + +#if defined(S_MP_FP_LOG_C) +# define MP_2EXPT_C +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MUL_2D_C +# define MP_MUL_C +# define MP_SET_I32_C +# define S_MP_FP_LOG_FRACTION_C +#endif + +#if defined(S_MP_FP_LOG_D_C) +# define MP_CLEAR_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_GET_I64_C +# define MP_INIT_C +# define S_MP_FLOG2_MP_WORD_D_C +# define S_MP_FP_LOG_FRACTION_D_C +#endif + +#if defined(S_MP_GET_BIT_C) +#endif + +#if defined(S_MP_INVMOD_C) +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MOD_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(S_MP_INVMOD_ODD_C) +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MOD_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(S_MP_LOG_2EXPT_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(S_MP_MONTGOMERY_REDUCE_COMBA_C) +# define MP_CLAMP_C +# define MP_CMP_MAG_C +# define MP_GROW_C +# define S_MP_SUB_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C +# define S_MP_ZERO_BUF_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_MUL_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define S_MP_MUL_COMBA_C +#endif + +#if defined(S_MP_MUL_BALANCE_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_C +# define S_MP_COPY_DIGS_C +#endif + +#if defined(S_MP_MUL_COMBA_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_MUL_HIGH_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define S_MP_MUL_HIGH_COMBA_C +#endif + +#if defined(S_MP_MUL_HIGH_COMBA_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_MUL_KARATSUBA_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_C +# define S_MP_ADD_C +# define S_MP_COPY_DIGS_C +# define S_MP_SUB_C +#endif + +#if defined(S_MP_MUL_TOOM_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_DIV_2_C +# define MP_INIT_MULTI_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_SUB_C +# define S_MP_COPY_DIGS_C +# define S_MP_DIV_3_C +#endif + +#if defined(S_MP_PRIME_IS_DIVISIBLE_C) +# define MP_DIV_D_C +#endif + +#if defined(S_MP_PRIME_TAB_C) +#endif + +#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_PLATFORM_C) +#endif + +#if defined(S_MP_SQR_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +#endif + +#if defined(S_MP_SQR_COMBA_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_WARRAY_GET_C +# define S_MP_WARRAY_PUT_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_SQR_KARATSUBA_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_C +# define S_MP_ADD_C +# define S_MP_COPY_DIGS_C +# define S_MP_SUB_C +#endif + +#if defined(S_MP_SQR_TOOM_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_DIV_2_C +# define MP_INIT_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_SUB_C +# define S_MP_COPY_DIGS_C +#endif + +#if defined(S_MP_SUB_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_WARRAY_C) +#endif + +#if defined(S_MP_WARRAY_GET_C) +#endif + +#if defined(S_MP_WARRAY_PUT_C) +#endif + +#if defined(S_MP_ZERO_BUF_C) +#endif + +#if defined(S_MP_ZERO_DIGS_C) +#endif + +#ifdef LTM_INSIDE +#undef LTM_INSIDE +#ifdef LTM3 +# define LTM_LAST +#endif + +#include "tommath_superclass.h" +#include "tommath_class.h" +#else +# define LTM_LAST +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_cutoffs.h b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_cutoffs.h new file mode 100644 index 0000000..fb84160 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_cutoffs.h @@ -0,0 +1,13 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* + Current values evaluated on an AMD A8-6600K (64-bit). + Type "make tune" to optimize them for your machine but + be aware that it may take a long time. It took 2:30 minutes + on the aforementioned machine for example. + */ + +#define MP_DEFAULT_MUL_KARATSUBA_CUTOFF 80 +#define MP_DEFAULT_SQR_KARATSUBA_CUTOFF 120 +#define MP_DEFAULT_MUL_TOOM_CUTOFF 350 +#define MP_DEFAULT_SQR_TOOM_CUTOFF 400 diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_private.h b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_private.h new file mode 100644 index 0000000..1cf3901 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_private.h @@ -0,0 +1,346 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMMATH_PRIVATE_H_ +#define TOMMATH_PRIVATE_H_ + +#include "tommath.h" +#include "tommath_class.h" +#include + +/* + * Private symbols + * --------------- + * + * On Unix symbols can be marked as hidden if libtommath is compiled + * as a shared object. By default, symbols are visible. + * On Win32 a .def file must be used to specify the exported symbols. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32) && !defined(__CYGWIN__) +# define MP_PRIVATE +#else +# define MP_PRIVATE +#endif + +/* Hardening libtommath + * -------------------- + * + * By default memory is zeroed before calling + * MP_FREE to avoid leaking data. This is good + * practice in cryptographical applications. + * + * Note however that memory allocators used + * in cryptographical applications can often + * be configured by itself to clear memory, + * rendering the clearing in tommath unnecessary. + * See for example https://github.com/GrapheneOS/hardened_malloc + * and the option CONFIG_ZERO_ON_FREE. + * + * Furthermore there are applications which + * value performance more and want this + * feature to be disabled. For such applications + * define MP_NO_ZERO_ON_FREE during compilation. + */ +#ifdef MP_NO_ZERO_ON_FREE +# define MP_FREE_BUF(mem, size) MP_FREE((mem), (size)) +# define MP_FREE_DIGS(mem, digits) MP_FREE((mem), sizeof (mp_digit) * (size_t)(digits)) +#else +# define MP_FREE_BUF(mem, size) \ +do { \ + size_t fs_ = (size); \ + void* fm_ = (mem); \ + if (fm_ != NULL) { \ + s_mp_zero_buf(fm_, fs_); \ + MP_FREE(fm_, fs_); \ + } \ +} while (0) +# define MP_FREE_DIGS(mem, digits) \ +do { \ + int fd_ = (digits); \ + mp_digit* fm_ = (mem); \ + if (fm_ != NULL) { \ + s_mp_zero_digs(fm_, fd_); \ + MP_FREE(fm_, sizeof (mp_digit) * (size_t)fd_); \ + } \ +} while (0) +#endif + +/* Tunable cutoffs + * --------------- + * + * - In the default settings, a cutoff X can be modified at runtime + * by adjusting the corresponding X_CUTOFF variable. + * + * - Tunability of the library can be disabled at compile time + * by defining the MP_FIXED_CUTOFFS macro. + * + * - There is an additional file tommath_cutoffs.h, which defines + * the default cutoffs. These can be adjusted manually or by the + * autotuner. + * + */ + +#ifdef MP_FIXED_CUTOFFS +# include "tommath_cutoffs.h" +# define MP_MUL_KARATSUBA_CUTOFF MP_DEFAULT_MUL_KARATSUBA_CUTOFF +# define MP_SQR_KARATSUBA_CUTOFF MP_DEFAULT_SQR_KARATSUBA_CUTOFF +# define MP_MUL_TOOM_CUTOFF MP_DEFAULT_MUL_TOOM_CUTOFF +# define MP_SQR_TOOM_CUTOFF MP_DEFAULT_SQR_TOOM_CUTOFF +#endif + +/* define heap macros */ +#ifndef MP_MALLOC +/* default to libc stuff */ +# include +# define MP_MALLOC(size) malloc(size) +# define MP_REALLOC(mem, oldsize, newsize) realloc((mem), (newsize)) +# define MP_CALLOC(nmemb, size) calloc((nmemb), (size)) +# define MP_FREE(mem, size) free(mem) +#else +/* prototypes for our heap functions */ +extern void *MP_MALLOC(size_t size); +extern void *MP_REALLOC(void *mem, size_t oldsize, size_t newsize); +extern void *MP_CALLOC(size_t nmemb, size_t size); +extern void MP_FREE(void *mem, size_t size); +#endif + +/* feature detection macro */ +#ifdef _MSC_VER +/* Prevent false positive: not enough arguments for function-like macro invocation */ +#pragma warning(disable: 4003) +#endif +#define MP_STRINGIZE(x) MP__STRINGIZE(x) +#define MP__STRINGIZE(x) ""#x"" +#define MP_HAS(x) (sizeof(MP_STRINGIZE(x##_C)) == 1u) + +#define MP_MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MP_MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c)) + +#define MP_EXCH(t, a, b) do { t _c = a; a = b; b = _c; } while (0) + +#define MP_IS_2EXPT(x) (((x) != 0u) && (((x) & ((x) - 1u)) == 0u)) + +/* TODO: same as above for bigint, merge (is it used elsewhere?) or change name */ +#define MP_IS_POWER_OF_TWO(a) (((mp_count_bits((a)) - 1) == mp_cnt_lsb((a))) ) + +/* Static assertion */ +#define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1]; + +#define MP_SIZEOF_BITS(type) ((size_t)CHAR_BIT * sizeof(type)) + +#define MP_MAX_COMBA (int)(1uL << (MP_SIZEOF_BITS(mp_word) - (2u * (size_t)MP_DIGIT_BIT))) +#define MP_WARRAY (int)(1uL << ((MP_SIZEOF_BITS(mp_word) - (2u * (size_t)MP_DIGIT_BIT)) + 1u)) + +#if defined(MP_16BIT) +typedef uint32_t mp_word; +#define MP_WORD_SIZE 4 +#elif ((defined (MP_64BIT)) && !(defined(MP_31BIT)) ) +typedef unsigned long mp_word __attribute__((mode(TI))); +#define MP_WORD_SIZE 16 +#else +typedef uint64_t mp_word; +#define MP_WORD_SIZE 8 +#endif + +MP_STATIC_ASSERT(correct_word_size, sizeof(mp_word) == (2u * sizeof(mp_digit))) + +/* default number of digits */ +#ifndef MP_DEFAULT_DIGIT_COUNT +# ifndef MP_LOW_MEM +# define MP_DEFAULT_DIGIT_COUNT 32 +# else +# define MP_DEFAULT_DIGIT_COUNT 8 +# endif +#endif + +/* Minimum number of available digits in mp_int, MP_DEFAULT_DIGIT_COUNT >= MP_MIN_DIGIT_COUNT + * - Must be at least 3 for s_mp_div_school. + * - Must be large enough such that the mp_set_u64 setter can + * store uint64_t in the mp_int without growing + */ +#ifndef MP_MIN_DIGIT_COUNT +# define MP_MIN_DIGIT_COUNT MP_MAX(3, (((int)MP_SIZEOF_BITS(uint64_t) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT) +#endif +MP_STATIC_ASSERT(prec_geq_min_prec, MP_DEFAULT_DIGIT_COUNT >= MP_MIN_DIGIT_COUNT) +MP_STATIC_ASSERT(min_prec_geq_3, MP_MIN_DIGIT_COUNT >= 3) +MP_STATIC_ASSERT(min_prec_geq_uint64size, + MP_MIN_DIGIT_COUNT >= ((((int)MP_SIZEOF_BITS(uint64_t) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT)) + +/* Maximum number of digits. + * - Must be small enough such that mp_bit_count does not overflow. + * - Must be small enough such that mp_radix_size for base 2 does not overflow. + * mp_radix_size needs two additional bytes for zero termination and sign. + */ +#define MP_MAX_DIGIT_COUNT ((INT_MAX - 2) / MP_DIGIT_BIT) + +#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) \ + || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) \ + || defined(__i386__) || defined(_M_X86) || defined(_M_IX86) \ + || defined(__aarch64__) || defined(__arm__) +#define MP_HAS_SET_DOUBLE +#endif + +/* + The mp_log functions rely on the size of mp_word being larger than INT_MAX and in case + there is a really weird architecture we try to check for it. Not a 100% reliable + test but it has a safe fallback. + */ +#if !(((UINT_MAX == UINT32_MAX) && (MP_WORD_SIZE > 4)) \ + || ((UINT_MAX == UINT16_MAX) && (MP_WORD_SIZE > 2))) +#define S_MP_WORD_TOO_SMALL_C +#endif + +/* random number source */ +extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size); + +/* lowlevel functions, do not call! */ +MP_PRIVATE bool s_mp_get_bit(const mp_int *a, int b) MP_WUR; +MP_PRIVATE int s_mp_log_2expt(const mp_int *a, mp_digit base) MP_WUR; + +MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; +MP_PRIVATE mp_err s_mp_div_recursive(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; +MP_PRIVATE mp_err s_mp_div_school(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; +MP_PRIVATE mp_err s_mp_div_small(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; +MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_invmod_odd(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +MP_PRIVATE mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; +MP_PRIVATE mp_err s_mp_mul(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_balance(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_high(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_high_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_karatsuba(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_toom(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, bool *result) MP_WUR; +MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_comba(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_karatsuba(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_toom(const mp_int *a, mp_int *b) MP_WUR; +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); + +#define MP_PRECISION_FIXED_LOG ( (int) (((sizeof(mp_word) * CHAR_BIT) / 2) - 1)) +#define MP_UPPER_LIMIT_FIXED_LOG ( (int) ( (sizeof(mp_word) * CHAR_BIT) - 1)) +MP_PRIVATE mp_err s_mp_fp_log(const mp_int *a, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_fp_log_d(const mp_int *a, mp_word *c) MP_WUR; + +#ifdef MP_SMALL_STACK_SIZE + +#if defined(__GNUC__) +/* We use TLS (Thread Local Storage) to manage the instance of the WARRAY + * per thread. + * The compilers we're usually looking at are GCC, Clang and MSVC. + * Both GCC and Clang are straight-forward with TLS, so it's enabled there. + * Using MSVC the tests were OK with the static library, but failed when + * the library was built as a DLL. As a result we completely disable + * support for MSVC. + * If your compiler can handle TLS properly without too much hocus pocus, + * feel free to open a PR to add support for it. + */ +#define mp_thread __thread +#else +#error "MP_SMALL_STACK_SIZE not supported with your compiler" +#endif + +#define MP_SMALL_STACK_SIZE_C +#define MP_ALLOC_WARRAY(name) *name = s_mp_warray_get() +#define MP_FREE_WARRAY(name) s_mp_warray_put(name) +#define MP_CHECK_WARRAY(name) do { if ((name) == NULL) { return MP_MEM; } } while(0) +#else +#define MP_ALLOC_WARRAY(name) name[MP_WARRAY] +#define MP_FREE_WARRAY(name) +#define MP_CHECK_WARRAY(name) +#endif + +#ifndef mp_thread +#define mp_thread +#endif + +typedef struct { + void *w_free, *w_used; +} st_warray; + +extern MP_PRIVATE mp_thread st_warray s_mp_warray; + +MP_PRIVATE void *s_mp_warray_get(void); +MP_PRIVATE void s_mp_warray_put(void *w); + +#define MP_RADIX_MAP_REVERSE_SIZE 80u +extern MP_PRIVATE const char s_mp_radix_map[]; +extern MP_PRIVATE const uint8_t s_mp_radix_map_reverse[]; +extern MP_PRIVATE const mp_digit s_mp_prime_tab[]; + +/* number of primes */ +#define MP_PRIME_TAB_SIZE 256 + +#define MP_GET_ENDIANNESS(x) \ + do{\ + int16_t n = 0x1; \ + char *p = (char *)&n; \ + x = (p[0] == '\x01') ? MP_LITTLE_ENDIAN : MP_BIG_ENDIAN; \ + } while (0) + +/* code-generating macros */ +#define MP_SET_UNSIGNED(name, type) \ + void name(mp_int * a, type b) \ + { \ + int i = 0; \ + while (b != 0u) { \ + a->dp[i++] = ((mp_digit)b & MP_MASK); \ + if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \ + b >>= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \ + } \ + a->used = i; \ + a->sign = MP_ZPOS; \ + s_mp_zero_digs(a->dp + a->used, a->alloc - a->used); \ + } + +#define MP_SET_SIGNED(name, uname, type, utype) \ + void name(mp_int * a, type b) \ + { \ + uname(a, (b < 0) ? -(utype)b : (utype)b); \ + if (b < 0) { a->sign = MP_NEG; } \ + } + +#define MP_INIT_INT(name , set, type) \ + mp_err name(mp_int * a, type b) \ + { \ + mp_err err; \ + if ((err = mp_init(a)) != MP_OKAY) { \ + return err; \ + } \ + set(a, b); \ + return MP_OKAY; \ + } + +#define MP_GET_MAG(name, type) \ + type name(const mp_int* a) \ + { \ + int i = MP_MIN(a->used, (int)((MP_SIZEOF_BITS(type) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT)); \ + type res = 0u; \ + while (i --> 0) { \ + res <<= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \ + res |= (type)a->dp[i]; \ + if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \ + } \ + return res; \ + } + +#define MP_GET_SIGNED(name, mag, type, utype) \ + type name(const mp_int* a) \ + { \ + utype res = mag(a); \ + return mp_isneg(a) ? (type)-res : (type)res; \ + } + +#endif diff --git a/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_superclass.h b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_superclass.h new file mode 100644 index 0000000..10c7f12 --- /dev/null +++ b/native/src/main/native/cn/cstn/algorithm/javacpp/libtommath/tommath_superclass.h @@ -0,0 +1,115 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* super class file for PK algos */ + +/* default ... include all MPI */ +#ifndef LTM_NOTHING +#define LTM_ALL +#endif + +/* RSA only (does not support DH/DSA/ECC) */ +/* #define SC_RSA_1 */ +/* #define SC_RSA_1_WITH_TESTS */ + +/* For reference.... On an Athlon64 optimizing for speed... + + LTM's mpi.o with all functions [striped] is 142KiB in size. + +*/ + +#ifdef SC_RSA_1_WITH_TESTS +# define MP_ERROR_TO_STRING_C +# define MP_FREAD_C +# define MP_FWRITE_C +# define MP_INCR_C +# define MP_ISEVEN_C +# define MP_ISODD_C +# 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 +# define MP_REDUCE_2K_L_C +# define MP_FROM_SBIN_C +# 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 +# define MP_WARRAY_FREE_C +# define MP_WARRAY_INIT_C +# define S_MP_RAND_JENKINS_C +# define S_MP_RAND_PLATFORM_C +#endif + +/* Works for RSA only, mpi.o is 68KiB */ +#if defined(SC_RSA_1) || defined (SC_RSA_1_WITH_TESTS) +# define MP_CUTOFFS_C +# define MP_ADDMOD_C +# define MP_CLEAR_MULTI_C +# define MP_EXPTMOD_C +# define MP_GCD_C +# define MP_INIT_MULTI_C +# define MP_INVMOD_C +# define MP_LCM_C +# define MP_MOD_C +# define MP_MOD_D_C +# define MP_MULMOD_C +# define MP_PRIME_IS_PRIME_C +# define MP_PRIME_RABIN_MILLER_TRIALS_C +# define MP_PRIME_RAND_C +# define MP_SET_INT_C +# define MP_SHRINK_C +# define MP_TO_UNSIGNED_BIN_C +# define MP_UNSIGNED_BIN_SIZE_C +# define S_MP_PRIME_TAB_C +# define S_MP_RADIX_MAP_C + +/* other modifiers */ + + + +/* here we are on the last pass so we turn things off. The functions classes are still there + * but we remove them specifically from the build. This also invokes tweaks in functions + * like removing support for even moduli, etc... + */ +# ifdef LTM_LAST +# undef MP_DR_IS_MODULUS_C +# undef MP_DR_REDUCE_C +# undef MP_DR_SETUP_C +# undef MP_REDUCE_2K_C +# undef MP_REDUCE_2K_SETUP_C +# undef MP_REDUCE_IS_2K_C +# undef MP_REDUCE_SETUP_C +# undef S_MP_DIV_3_C +# undef S_MP_EXPTMOD_C +# undef S_MP_INVMOD_ODD_C +# undef S_MP_MUL_BALANCE_C +# undef S_MP_MUL_HIGH_C +# undef S_MP_MUL_HIGH_COMBA_C +# undef S_MP_MUL_KARATSUBA_C +# undef S_MP_MUL_TOOM_C +# undef S_MP_SQR_KARATSUBA_C +# undef S_MP_SQR_TOOM_C + +# ifndef SC_RSA_1_WITH_TESTS +# undef MP_REDUCE_C +# endif + +/* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without + * trouble. + */ +# undef MP_MONTGOMERY_REDUCE_C +# undef S_MP_MUL_C +# undef S_MP_SQR_C +# endif + +#endif