aboutsummaryrefslogtreecommitdiff
path: root/vendor/gmp-6.3.0/mini-gmp
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-21 23:36:36 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-21 23:42:26 +0200
commita89a14ef5da44684a16b204e7a70460cc8c4922a (patch)
treeb23b4c6b155977909ef508fdae2f48d33d802813 /vendor/gmp-6.3.0/mini-gmp
parent1db63fcedab0b288820d66e100b1877b1a5a8851 (diff)
Basic constant folding implementation
Diffstat (limited to 'vendor/gmp-6.3.0/mini-gmp')
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/ChangeLog768
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/README72
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/mini-gmp.c4627
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/mini-gmp.h310
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/mini-mpq.c556
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/mini-mpq.h114
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/Makefile65
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/hex-random.c573
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/hex-random.h55
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/mini-random.c160
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/mini-random.h35
-rwxr-xr-xvendor/gmp-6.3.0/mini-gmp/tests/run-tests143
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-add.c57
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-aorsmul.c77
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-bitops.c104
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-cmp_d.c283
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-comb.c175
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-cong.c212
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-div.c258
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-div_2exp.c82
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-double.c232
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-gcd.c178
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-import.c99
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-invert.c141
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-lcm.c73
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-limbs.c111
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-logops.c112
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-lucm.c98
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_addsub.c204
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_double.c211
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv.c176
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv_2exp.c138
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_str.c263
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-mul.c113
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-powm.c87
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-pprime_p.c183
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-reuse.c663
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-root.c95
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-scan.c90
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-signed.c348
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-sqrt.c181
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-str.c332
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/t-sub.c71
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/testutils.c196
-rw-r--r--vendor/gmp-6.3.0/mini-gmp/tests/testutils.h42
45 files changed, 13163 insertions, 0 deletions
diff --git a/vendor/gmp-6.3.0/mini-gmp/ChangeLog b/vendor/gmp-6.3.0/mini-gmp/ChangeLog
new file mode 100644
index 0000000..94b3738
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/ChangeLog
@@ -0,0 +1,768 @@
+2023-07-20 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (gmp_umullo_limb): New macro, to avoid unintended
+ promotion to signed int, in case mp_limb_t is a size smaller than
+ int. In particular, mp_limb_t configured to be a 16-bit unsigned
+ short, with 32-bit int, leads to undefined signed overflow.
+ Problem reported by Vincent Lefevre.
+ (gmp_udiv_qrnnd_preinv, gmp_udiv_qr_3by2): Use new macro.
+
+2022-09-08 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-powm.c: Test some corner cases (e.g. 1^0 mod 1).
+
+2022-09-05 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpz_powm): Fix case of x^0 (mod 1), should be 0.
+ Reported by Guido Vranken.
+
+2022-05-29 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-mpq.c (mpq_helper_2exp): New helper (internal) function.
+
+2022-04-18 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (gmp_assert_nocarry): Avoid warning about unused
+ variable in NDEBUG builds. Reported by Paul Egggert.
+
+2022-04-17 Marco Bodrato <bodrato@mail.dm.unipi.it>
+ * mini-mpq.c (mpq_helper_canonicalize): Remove tmp parameter.
+
+2022-03-19 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_swap): Use MPN_PTR_SWAP, tx Paul Eggert.
+
+2021-10-01 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Add asserts (removed at compile time) on limb size.
+ * mini-mpq.c: Add #defines needed if mini-gmp.h is not included.
+
+2021-08-02 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_rootrem): Better initial guess.
+ (gmp_stronglucas): Shortcut, mpn_common_scan instead of mpz_scan0.
+
+2021-05-13 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-reuse.c: Use numberof() to reduce the risk of typos.
+
+2021-04-16 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (gmp_millerrabin): Don't check unlikely 0 or 1.
+ * mini-gmp.h: Update FILE tests from gmp-h.
+
+2021-01-02 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_export): Correct error message (tx: Guillermo Monguia)
+
+2020-11-28 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_gcd): Support limbs larger than unsigned long.
+ * tests/t-invert.c: Likewise.
+
+2020-05-21 Torbjörn Granlund <tg@gmplib.org>
+
+ * tests/t-double.c: Provide default M_PI definition.
+
+2020-11-10 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/run-tests: Update WINEPATH, instead of overwriting it.
+
+2020-10-25 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-mpq.c (mpq_canonical_sign): Use the correct type for size.
+
+2020-10-18 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Use mpn_scan1 instead of mpz_scan1.
+ (mpn_set_str_bits): Reduce branches and writes.
+ (mpz_gcdext): Delay mpz_setbit (t0, ...).
+
+ * mini-mpq.c (mpq_out_str): Return 0 when base is out of range.
+ * mini-gmp.c (mpz_out_str): Likewise. (spotted by Paul Eggert)
+
+ * tests/t-str.c: Test out-of-range bases for mpz_out_str.
+ * tests/t-mpq_str.c: Likewise, for mpq_out_str.
+
+2020-10-06 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/run-tests: Better support for make check on wine or cygwin.
+
+2020-09-10 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-mpq_double.c (mpq_get_d_exact_p): Cleanup.
+
+ * mini-gmp.c (mpz_get_str): Explicit cast from void* to char*.
+
+ * mini-gmp.h: Update FILE tests from gmp-h (tx Vincent Lefèvre).
+
+2020-05-27 Minux Ma <minux.ma@gmail.com>
+
+ Pass correct old_size to custom free and reallocate functions.
+ * mini-gmp.c (gmp_alloc): Renamed macro from...
+ (gmp_xalloc): .. old name.
+ (gmp_realloc): New macro, with old_size argument.
+ (gmp_free): Take size argument, and pass on.
+ (gmp_realloc_limbs): Add old_size argument, and rename from
+ (gmp_xrealloc_limbs): ... old name..
+ (gmp_free_limbs): New function, with size argument. Lots of
+ updates, only non-trivial ones listed below.
+ (mpn_div_qr_1_preinv): Use gmp_free_limbs, simplify dealloc logic.
+ (mpz_get_str): Realloc result area when needed, to match final
+ digit count.
+ * mini-mpq.c (mpq_get_str, mpq_out_str, mpq_set_str): Pass correct
+ size to gmp_free_func.
+ * tests/testutils.c (tu_realloc, tu_free): Check that old_size
+ matches size in block header.
+ (testfree): Add size argument. Update all callers.
+
+2020-04-20 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpz_fits_slong_p): Simplify, by using mpz_cmp_si.
+ (mpz_fits_sint_p, mpz_fits_uint_p, mpz_fits_sshort_p)
+ (mpz_fits_ushort_p): New functions.
+ * mini-gmp.h: Declare new functions.
+ * tests/t-signed.c (try_fits_utype_p, try_fits_sint_p)
+ (try_fits_sshort_p): New tests.
+
+2020-02-02 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp/mini-gmp.c (gmp_jacobi_coprime): Exit condition on a.
+
+2019-12-04 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp/mini-gmp.c (mpn_invert_3by2): Remove shortcuts.
+
+2019-11-19 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp/mini-gmp.c (mpn_invert_3by2): Shortcut for short limbs.
+
+2019-11-09 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp/mini-gmp.c (gmp_clz, gmp_popcount_limb, mpz_export):
+ Avoid undefined behaviour with small limb sizes.
+
+2019-09-30 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-gcd.c (gcdext_valid_p): Stricter checks for gcdext
+ corner cases.
+
+2018-12-21 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp/mini-gmp.c: Support for micro-gmp.
+
+2018-11-07 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp/mini-gmp.c: Silence a couple of warnings.
+
+2018-10-30 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_probab_prime_p): BPSW test for primality.
+
+ * tests/hex-random.c (hex_random_lucm_op): New function.
+ * tests/hex-random.h: Declare it.
+ * tests/mini-random.c (mini_random_lucm_op): New function.
+ * tests/mini-random.h: Declare it.
+ * mini-gmp/tests/t-lucm.c: New test
+ * mini-gmp/tests/Makefile (CHECK_PROGRAMS): Add t-lucm.
+
+2018-09-07 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-div.c (testmain): Add missing const declarations.
+
+2018-05-20 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_get_d): Convert a fixed number of
+ bits (GMP_DBL_MANT_BITS) to avoid rounding.
+
+ * mini-mpq.c (mpq_mul): Use mpq_nan_init.
+
+ * tests/t-double.c (test_matissa): Tests converted bits.
+
+2018-04-26 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-mpq.c: New file, mini-implementation of mpq_t.
+ * mini-mpq.h: New file, definitions for mpq_t.
+ * tests/t-mpq_addsub: New tests for mpq_add and sub.
+ * tests/t-mpq_muldiv: New tests for mpq_mul and div.
+ * tests/t-mpq_muldiv_2exp: New tests for mpq_*_2exp.
+
+2018-03-11 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpn_div_qr_2_preinv): Drop separate rp argument.
+ Clobber input np, and store remainder in np[0] and np[1]. This is
+ all the current caller needs, and it eliminates one allocation in
+ the common case of un-normalized d.
+ (mpn_div_qr_2): Delete #if:ed out function.
+ (mpn_div_qr_preinv): Update the only call site for
+ mpn_div_qr_2_preinv.
+
+2018-02-10 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpn_div_qr_1_preinv): When qp is non-NULL, reuse
+ area for shifted input, to avoid an allocation.
+
+2018-01-15 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (gmp_popcount_limb): Micro-optimisations.
+ * tests/t-comb.c (checkWilson): Check also mpz_2fac_ui.
+
+2017-12-30 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_mfac_ui, mpz_2fac_ui): New functions.
+ * mini-gmp.h: Declare them.
+ * mini-gmp.c (mpz_fac_ui): Use mpz_mfac_ui.
+
+2017-07-23 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (GMP_MPN_OVERLAP_P): New macro, copy of
+ MPN_OVERLAP_P, from gmp-impl.h.
+ (mpn_mul): Assert that output area doesn't overlap with the input.
+
+2017-02-03 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_sizeinbase, mpz_get_str, mpz_set_str): Support
+ bases up to 62.
+ * tests/t-str.c: Update tests accordingly.
+
+2016-11-27 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_get_si): fewer branches, safer forumla for negatives.
+
+ * tests/t-signed.c: Removed a typo
+
+2016-11-24 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/hex-random.c (mkseed): Produce a 48-bit mpz_t value,
+ regardless of word size.
+ (hex_random_init): Use gmp_randseed instead of gmp_randseed_ui,
+ and support seeds exceeding an unsigned long.
+
+ * tests/hex-random.c (mkseed): New function, using /dev/urandom
+ for random seed when available.
+ (hex_random_init): Use it.
+
+2016-11-23 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (GMP_CMP): New macro.
+ (mpz_sgn, mpz_cmp_si, mpz_cmp_ui, mpz_cmpabs_ui): Use it.
+
+2016-11-22 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-invert.c (test_3by2, test_2by1): New functions,
+ extracted from testmain.
+ (testmain): Add test with inputs which triggered the
+ mpn_invert_3by2 bug (see 2016-11-16 entry).
+
+2016-11-21 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-signed.c: compare different signs, and after overflow.
+
+2016-11-20 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-signed.c: Reorganize testcase, to avoid undefined
+ behaviour with signed overflow.
+
+2016-11-19 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/run-tests: Set up LD_LIBRARY_PATH and DYLD_LIBRARY_PATH
+ for tests only, based on TEST_LIBRARY_PATH.
+
+ * tests/mini-random.h: Use name "../mini-gmp.h" for include, so we
+ don't need any -I options to the compiler.
+
+ * tests/Makefile: Pass CFLAGS to the linker, as
+ recommended by the GNU coding standard.
+ (CPPFLAGS): New variable, with empty default value.
+ (CFLAGS): Remove the -I flag involving MINI_GMP_DIR, to leave free
+ for overriding on make command line.
+ (EXTRA_CFLAGS): Deleted variable, no longer needed.
+
+2016-11-18 Torbjörn Granlund <tg@gmplib.org>
+
+ * tests/Makefile: Pass EXTRA_CFLAGS to linker as a intermediate fix.
+
+2016-11-17 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-str.c: free a pointer to avoid memory leaks.
+
+2016-11-16 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpn_invert_3by2): Fix arithmetic overflow
+ bug, and improve documentation of the algorithm.
+
+2016-11-15 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-limbs.c (testmain): Skip tests with zero product.
+
+ * tests/hex-random.c (hex_random_init): Added fflush call.
+
+2016-11-15 Torbjörn Granlund <tg@gmplib.org>
+
+ * tests/Makefile (TESTS): New variable, allowing separation of
+ compilation and running of tests.
+ * tests/run-tests: Allow empty tests list.
+
+2016-11-14 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-str.c: Some more test cases.
+ * tests/t-pprime_p.c: Use shorter operands, with different sizes.
+
+2016-11-01 Torbjörn Granlund <tg@gmplib.org>
+
+ * tests/hex-random.c: Reinstate gmp.h inclusion.
+
+2016-08-22 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpn_set_str_other): Always return size >= 1, with
+ unnormalized result in the case the input digits are all zero.
+ Fixes crash on a large number of leading zeros, reported by Axel
+ Miller.
+ (mpz_set_str): Normalize as needed, after above change. Return
+ failure for inputs string with no digits, i.e., empty except for
+ optional sign, base prefix and white space.
+
+2016-01-01 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Silence warnings due to (un)signed types.
+ * tests/testutils.c: Likewise.
+ * tests/t-logops.c: Likewise.
+ * tests/t-cmp_d.c: Likewise.
+ * tests/t-reuse.c: Likewise.
+ * tests/t-cong.c: Likewise.
+
+2015-11-13 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Lazy allocation for mpz_t.
+ (mpz_rootrem): Exploit lazy allocation to avoid init2.
+
+2015-11-06 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpn_com, mpn_neg): New functions.
+ * mini-gmp.h: Declare them.
+ * mini-gmp.c (mpz_div_r_2exp): Use mpn_neg.
+
+2015-10-29 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Removed a typo (spotted by Paul Zimmermann).
+
+2015-05-30 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.h: Declare mpn_zero_p.
+ * mini-gmp.c: Define mpn_zero_p as a function, not a macro.
+
+2014-08-27 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpz_abs_sub_bit): Do full normalization,
+ needed if mpz_clrbit clears the most significant one bit.
+
+2014-07-28 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Remove some useless variables.
+
+2014-05-20 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: +1 in the init2 argument before setbit.
+
+2014-05-15 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Micro-optimisations.
+
+2014-03-12 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_probab_prime_p): Micro-optimisation.
+
+2014-03-06 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (gmp_millerrabin): New internal function.
+ (mpz_probab_prime_p): New function.
+ * mini-gmp.h (mpz_probab_prime_p): Declare it.
+ * tests/t-pprime_p.c: New test program.
+ * tests/Makefile (CHECK_PROGRAMS): Added t-pprime_p.
+
+2014-03-03 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpz_congruent_p): New function.
+ * mini-gmp.h: Declare it.
+ * tests/t-cong.c: New file, based on tests/mpz/t-cong.c.
+ * tests/Makefile (CHECK_PROGRAMS): Added t-cong.
+
+ * tests/testutils.c (dump): New function. Deleted static
+ functions in other files.
+ (mpz_set_str_or_abort): Moved function here, from...
+ * tests/t-cmp_d.c: ... old location.
+
+ * tests/t-reuse.c (dump3): Renamed, from ...
+ (dump): ...old name.
+
+2014-02-21 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpn_sqrtrem): New function.
+ * mini-gmp.h: Declare it.
+ * tests/t-sqrt.c: Test it.
+
+2014-02-15 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_div_qr): init + set = init_set .
+
+2014-02-10 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-limbs.c: New test for mpz_limbs_*.
+ * tests/Makefile (CHECK_PROGRAMS): Add it.
+
+2014-02-08 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_realloc2, mpz_limbs_read, mpz_limbs_modify
+ mpz_limbs_write, mpz_limbs_finish, mpz_roinit_n): New functions.
+ (mpn_perfect_square_p): New function.
+ * mini-gmp.h: Declare them.
+
+ * tests/t-mul.c: Use roinit and limbs_read to test mpn.
+ * tests/t-sqrt.c: Test also mpn_perfect_square_p.
+
+2014-02-03 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpn_rootrem): Allow NULL argument.
+
+ * mini-gmp.c (mpn_zero): New function.
+ (mpz_perfect_square_p): New function.
+ * mini-gmp.h: Declare them.
+
+ * tests/t-sqrt.c: Test mpz_perfect_square_p.
+ * tests/t-root.c: Test also 1-th root, allow perfect powers.
+
+2014-01-23 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-aorsmul.c: New file, test for mpz_{add,sub}mul{,_ui}
+ * tests/Makefile: Add t-aorsmul.
+
+2014-01-19 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpn_popcount): New function.
+ (mpz_popcount): Use it.
+ (mpz_addmul_ui, mpz_addmul, mpz_submul_ui, mpz_submul): Added.
+ * mini-gmp.h: Declare them.
+
+2014-01-16 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mp_bits_per_limb): New const value.
+ * mini-gmp.h: Declare it.
+
+2013-03-13 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Write loops in a cleaner way.
+
+2013-02-27 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_div_q_2exp): Adjust only if needed.
+ (mpn_common_scan): New service function to unify scan loops.
+ (mpz_scan0, mpz_scan1): Simplify by using mpn_common_scan.
+ (mpz_make_odd): Simplify, assume in-place operation on positive.
+ (mpn_scan0, mpn_scan1): New functions.
+ * mini-gmp.h (mpn_scan0, mpn_scan1): New declarations.
+ * tests/t-scan.c: Test also mpn_scan0 and mpn_scan1.
+
+2013-02-25 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-double.c (testmain): Declare double variables as
+ volatile, to drop extended precision.
+
+ * tests/testutils.c (testfree): New function. Use it everywhere
+ where test programs deallocate storage allocated via the mini-gmp
+ allocation functions, including uses of mpz_get_str for various
+ test failure messages.
+
+2013-02-19 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: Move asserts to work-around a compiler bug.
+ (mpz_export): Reorder branches.
+ (mpz_mul_ui): Avoid temporary allocation (mpn_mul_1 can work in-place).
+
+ * tests/t-reuse.c: Fix typo causing the same negation condition to
+ be applied to all operands. (See 2013-02-03, Torbjorn)
+
+2013-02-17 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_mul): Read sizes just once.
+ (mpn_set_str_other): Remove a redundant variable.
+ (mpz_abs_add): Use SWAP once, to order sizes.
+ (mpz_mul_ui): Micro-optimisation.
+ (mpz_rootrem): Use _init2 before _setbit.
+ (mpz_set_str): Optimise-out a variable.
+ (mpz_import): Normalise only if needed.
+ (mpn_div_qr_1): Speed-up the d=1 case, delaying a branch.
+
+2013-02-12 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (fac_ui, bin_uiui): Use shorter and faster code.
+
+ * mini-gmp.c: Reduce branches.
+
+2013-01-23 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_cmpabs_d, mpz_cmp_d): Simplify.
+ (mpz_set_str): Behaviour more adherent to the real GMP.
+
+ * tests/t-str.c: Cast size_t to unsigned long, for printf.
+ * tests/t-import.c: Likewise.
+ * tests/t-comb.c: Remove an unused var.
+ * tests/t-div.c: Remove unused args passed to fprintf.
+ * tests/t-double.c: Use float immediates with float vars.
+
+2013-01-22 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp.c (mpz_cmp_d): Simplified, just sort out signs, then
+ call mpz_cmpabs_d.
+
+ * tests/testutils.h: Include stdio.h and stdlib.h.
+ (numberof): New define.
+
+ * tests/t-cmp_d.c: New file, copied from tests/mpz/t-cmp_d.c with
+ minor changes.
+ * tests/Makefile (CHECK_PROGRAMS): Added t-cmp_d,
+
+ * mini-gmp.c (mpz_cmpabs_d): New function.
+ * mini-gmp.h: Declare it.
+
+2013-01-21 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-str.c (testmain): Test mpz_out_str, using
+ the tmpfile function for i/o.
+
+2013-01-20 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/testutils.c (testhalves): New function, test default
+ memory functions.
+ * tests/testutils.h (testhalves): Declare it
+ * tests/t-logops.c: Use testhalves.
+
+ * mini-gmp.c (mpz_init_set_str): New function.
+ * mini-gmp.h (mpz_init_set_str): Declare it.
+ * tests/t-str.c: Test mpz_init_set_str.
+
+2013-01-19 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-double.c (testmain): Get the current free
+ function using mp_get_memory_functions.
+ * tests/t-str.c (testmain): Likewise.
+
+ * tests/testutils.h (tu_free): Remove declaration.
+
+ * tests/testutils.c (block_check, tu_free): Mark static.
+
+2013-01-18 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-str.c (test_small): New function, exercising
+ parsing of whitespace and base prefixes.
+ (testmain): Call it.
+
+ * tests/t-gcd.c (gcdext_valid_p): Fixed memory leak.
+
+ * tests/t-double.c (testmain): Call tu_free rather than
+ free, for storage allocated by mpz_get_str.
+ * tests/t-str.c (testmain): Likewise.
+
+ * tests/testutils.c (block_init, block_check): New functions.
+ (tu_alloc, tu_realloc, tu_free): New functions.
+ (main): Use mp_set_memory_functions.
+ * tests/testutils.h (tu_free): Declare.
+
+ * tests/testutils.h: New file, declarations for test programs.
+
+ * tests/testutils.c (main): New file, with shared main
+ function for all the test programs. Also includes mini-gmp.c.
+ Calls testmain after initialization. All other test programs
+ updated to define testmain rather than main.
+
+2013-01-18 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-signed.c: Slightly larger coverage.
+ * tests/t-double.c: Test also mpz_init_set_d.
+
+2013-01-18 Torbjorn Granlund <tege@gmplib.org>
+
+ * tests/t-div.c: Test mpz_divisible_p and mpz_divisible_ui_p.
+
+ * tests/t-div.c: Test also mpz_mod, mpz_mod_ui. Compare
+ mpz_divisible_p just to ceil, to save time.
+
+ * mini-gmp.c: Prefix some names with GMP_.
+
+2013-01-16 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-double.c: Test mpz_cmp_d.
+ * mini-gmp.c (mpz_cmp_d): Correct multiword comparison.
+
+ * mini-gmp.c (mpz_set_str): Handle the empty string.
+ * tests/t-str.c: Test base <= 0.
+
+2013-01-15 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-str.c (main): Use x->_mp_d rather than x[0]._mp_d.
+ * tests/t-invert.c (main): Likewise.
+
+ * tests/t-mul.c (main): Test mpn_mul_n and mpn_sqr.
+
+ * tests/hex-random.h (enum hex_random_op): New value OP_SQR.
+
+ * tests/mini-random.c (mini_random_op3): Renamed, from...
+ (mini_random_op): ... old name. Updated callers.
+ (mini_random_op2): New function.
+
+ * tests/hex-random.c (hex_random_op3): Renamed, from...
+ (hex_random_op): ... old name. Updated callers.
+ (hex_random_op2): New function.
+
+2013-01-15 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-logops.c: Improve popcount/hamdist testing.
+ * tests/t-signed.c: Test more cases.
+
+2013-01-14 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-str.c (main): Added tests for mpn_get_str and
+ mpn_set_str.
+
+2013-01-11 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-comb.c: New test program, testing both
+ mpz_fac_ui and mpz_bin_uiui.
+ * tests/Makefile (CHECK_PROGRAMS): Added t-comb.
+
+ * mini-gmp.c (mpz_mul_si): Simplify.
+ (mpz_mul_ui, mpz_mul, mpz_div_qr): Replace init+REALLOC with init2.
+
+ * mini-gmp.c (NEG_CAST): New macro.
+ (mpz_mul_si, mpz_set_si, mpz_cmp_si): Use NEG_CAST.
+
+ * mini-gmp.c (mpz_set_si, mpz_cmp_si): Simplify by using
+ the _ui variant.
+
+ * tests/t-root.c: Use mpz_ui_pow_ui, when base fits an ui.
+
+ * tests/t-mul.c: Test also mpz_mul_si.
+ * tests/t-sub.c: Test also mpz_ui_sub.
+
+ * mini-gmp.c (mpz_fits_slong_p): Correct range.
+ * tests/t-signed.c: New test program, for get/set/cmp_si.
+ * tests/Makefile (CHECK_PROGRAMS): Added t-signed.
+
+ * mini-gmp.c (mpz_hamdist): Handle different sizes.
+ * tests/t-logops.c: Test also popcount and hamdist.
+
+2013-01-10 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_export, mpz_import): Less restrictive ASSERTs.
+ * tests/t-import.c: Test also size=0 or count=0.
+
+2013-01-10 Torbjorn Granlund <tege@gmplib.org>
+
+ * tests/t-import.c (main): Don't drop off function end.
+
+2013-01-09 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_export): Support op=0 countp=NULL.
+
+2013-01-08 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/t-import.c: New test program, testing both
+ mpz_import and mpz_export.
+ * tests/Makefile (CHECK_PROGRAMS): Added t-import.
+
+ * tests/mini-random.c (mini_rrandomb_export): New function.
+ * tests/mini-random.h: Declare it.
+ * tests/hex-random.c (hex_rrandomb_export): New function.
+ * tests/hex-random.h: Declare it.
+
+ * mini-gmp.c (mpz_export): Compute accurate word count up
+ front, to avoid generating any high zero words.
+
+2013-01-07 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * README: Document base limitation for conversions.
+ * mini-gmp.c (mpz_set_str): Remove goto.
+ (mpz_import, mpz_export): Correctly use order/endianness.
+
+2013-01-04 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ From shuax:
+ * mini-gmp.c (mpz_import): Reset limb after storing it.
+
+2012-11-22 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/run-tests: Copied latest version from GNU Nettle.
+ Minor fix to the use of $EMULATOR, and proper copyright notice.
+
+2012-06-24 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_div_r_2exp, mpz_div_q_2exp): Improve
+ adjustment condition.
+
+2012-06-08 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_realloc): remove a branch.
+
+2012-05-25 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * tests/t-div.c: Test all _qr, _q, _r variants.
+ * tests/t-lcm.c: Test the _ui variant.
+
+ * mini-gmp.c (mpz_mod, mpz_mod_ui): New functions.
+ * mini-gmp.h (mpz_mod, mpz_mod_ui): Prototypes.
+
+2012-05-09 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c: merge mpz_rootrem and mpz_sqrtrem.
+
+2012-04-13 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.h (mpz_fac_ui, mpz_bin_uiui): New definitions.
+ * mini-gmp.c (mpz_fac_ui, mpz_bin_uiui): Trivial implementation.
+
+2012-04-11 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.h (mpz_root, mpz_rootrem): define (correctly).
+ * mini-gmp.c (mpz_rootrem): Extended code from _root.
+ (mpz_root): Use mpz_rootrem.
+ (mpz_mul_ui): Correctly handle negative operands.
+
+ * tests/Makefile (CHECK_PROGRAMS): add t-root.
+ * tests/t-root.c: New file.
+ * tests/t-reuse.c: Enable root{,rem} tests.
+
+2012-04-10 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_root): New, support negative operands.
+ * mini-gmp.h (mpz_root): define.
+ (mpz_out_str): Test also __STDIO_LOADED (for VMS).
+ * mpz/2fac_ui.c: Cosmetic change.
+
+ * tests/t-reuse.c: New test case, based on tests/mpz/reuse.c.
+
+ * mini-gmp.c (mpz_cdiv_r_ui): New function.
+ (mpz_fdiv_r_ui): New function.
+ (mpz_tdiv_r_ui): New function.
+ (mpz_powm_ui): New function.
+ (mpz_pow_ui): New function.
+ (mpz_ui_pow_ui): Use mpz_pow_ui.
+ (mpz_gcdext): Fixed input/output overlap, for the case of one
+ input being zero.
+ (mpz_sqrtrem): Fix for the case r NULL, U zero.
+
+2012-02-28 Niels Möller <nisse@lysator.liu.se>
+
+ * tests/Makefile (srcdir, MINI_GMP_DIR): New make variables. These
+ can be overridden when using a separate build directory.
+ (EXTRA_CFLAGS): Renamed, was OPTFLAGS.
+
+ * mini-gmp.c (mpz_abs_add): Don't cache limb pointers
+ over MPZ_REALLOC, since that breaks in-place operation. Bug
+ spotted by Torbjörn.
+ (mpz_and, mpz_ior, mpz_xor): Likewise.
+ (mpz_cmp): Fixed comparison of negative numbers.
+
+2012-02-26 Niels Möller <nisse@lysator.liu.se>
+
+ * mini-gmp: New subdirectory. For use by GMP bootstrap, and as a
+ fallback for applications needing bignums but not high
+ performance.
diff --git a/vendor/gmp-6.3.0/mini-gmp/README b/vendor/gmp-6.3.0/mini-gmp/README
new file mode 100644
index 0000000..fd54054
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/README
@@ -0,0 +1,72 @@
+Copyright 2011-2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/.
+
+
+This is "mini-gmp", a small implementation of a subset of GMP's mpn,
+mpz and mpq interfaces.
+
+It is intended for applications which need arithmetic on numbers
+larger than a machine word, but which don't need to handle very large
+numbers very efficiently. Those applications can include a copy of
+mini-gmp to get a GMP-compatible interface with small footprint. One
+can also arrange for optional linking with the real GMP library, using
+mini-gmp as a fallback when for some reason GMP is not available, or
+not desired as a dependency.
+
+The supported GMP subset of the mpn and mpz interfaces is declared in
+mini-gmp.h, and implemented in mini-gmp.c. The implemented
+functions are fully compatible with the corresponding GMP functions,
+as specified in the GMP manual, with a few exceptions:
+
+ mpz_export and mpz_import support only NAILS = 0.
+
+The performance target for mini-gmp is to be at most 10 times slower
+than the real GMP library, for numbers of size up to a few hundred
+bits. No asymptotically fast algorithms are included in mini-gmp, so
+it will be many orders of magnitude slower than GMP for very large
+numbers.
+
+The supported GMP subset of the mpq layer is declared in mini-mpq.h,
+and implemented in mini-mpq.c.
+
+You should never "install" mini-gmp. Applications can either just
+#include mini-gmp.c (but then, beware that it defines several macros
+and functions outside of the advertised interface), and if needed
+#include mini-mpq.c in a later line (order is important). Or compile
+mini-gmp.c and mini-mpq.c as separate compilation units, and use the
+declarations in mini-gmp.h and mini-mpq.h.
+
+The tests subdirectory contains a testsuite. To use it, you need GMP
+and GNU make. Just run make check in the tests directory. If the
+hard-coded compiler settings are not right, you have to either edit the
+Makefile or pass overriding values on the make command line (e.g.,
+make CC=cc check).
+
+The initial version of mini-gmp was put together by Niels Möller
+<nisse@lysator.liu.se>, with a fair amount of copy-and-paste from the
+GMP sources.
diff --git a/vendor/gmp-6.3.0/mini-gmp/mini-gmp.c b/vendor/gmp-6.3.0/mini-gmp/mini-gmp.c
new file mode 100644
index 0000000..69a72bf
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/mini-gmp.c
@@ -0,0 +1,4627 @@
+/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
+
+ Contributed to the GNU project by Niels Möller
+ Additional functionalities and improvements by Marco Bodrato.
+
+Copyright 1991-1997, 1999-2022 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+/* NOTE: All functions in this file which are not declared in
+ mini-gmp.h are internal, and are not intended to be compatible
+ with GMP or with future versions of mini-gmp. */
+
+/* Much of the material copied from GMP files, including: gmp-impl.h,
+ longlong.h, mpn/generic/add_n.c, mpn/generic/addmul_1.c,
+ mpn/generic/lshift.c, mpn/generic/mul_1.c,
+ mpn/generic/mul_basecase.c, mpn/generic/rshift.c,
+ mpn/generic/sbpi1_div_qr.c, mpn/generic/sub_n.c,
+ mpn/generic/submul_1.c. */
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mini-gmp.h"
+
+#if !defined(MINI_GMP_DONT_USE_FLOAT_H)
+#include <float.h>
+#endif
+
+
+/* Macros */
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+
+#define GMP_LIMB_MAX ((mp_limb_t) ~ (mp_limb_t) 0)
+#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1))
+
+#define GMP_HLIMB_BIT ((mp_limb_t) 1 << (GMP_LIMB_BITS / 2))
+#define GMP_LLIMB_MASK (GMP_HLIMB_BIT - 1)
+
+#define GMP_ULONG_BITS (sizeof(unsigned long) * CHAR_BIT)
+#define GMP_ULONG_HIGHBIT ((unsigned long) 1 << (GMP_ULONG_BITS - 1))
+
+#define GMP_ABS(x) ((x) >= 0 ? (x) : -(x))
+#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1))
+
+#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b))
+#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b)))
+
+#if defined(DBL_MANT_DIG) && FLT_RADIX == 2
+#define GMP_DBL_MANT_BITS DBL_MANT_DIG
+#else
+#define GMP_DBL_MANT_BITS (53)
+#endif
+
+/* Return non-zero if xp,xsize and yp,ysize overlap.
+ If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no
+ overlap. If both these are false, there's an overlap. */
+#define GMP_MPN_OVERLAP_P(xp, xsize, yp, ysize) \
+ ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp))
+
+#define gmp_assert_nocarry(x) do { \
+ mp_limb_t __cy = (x); \
+ assert (__cy == 0); \
+ (void) (__cy); \
+ } while (0)
+
+#define gmp_clz(count, x) do { \
+ mp_limb_t __clz_x = (x); \
+ unsigned __clz_c = 0; \
+ int LOCAL_SHIFT_BITS = 8; \
+ if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) \
+ for (; \
+ (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \
+ __clz_c += 8) \
+ { __clz_x <<= LOCAL_SHIFT_BITS; } \
+ for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++) \
+ __clz_x <<= 1; \
+ (count) = __clz_c; \
+ } while (0)
+
+#define gmp_ctz(count, x) do { \
+ mp_limb_t __ctz_x = (x); \
+ unsigned __ctz_c = 0; \
+ gmp_clz (__ctz_c, __ctz_x & - __ctz_x); \
+ (count) = GMP_LIMB_BITS - 1 - __ctz_c; \
+ } while (0)
+
+#define gmp_add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ mp_limb_t __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+
+#define gmp_sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ mp_limb_t __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - ((al) < (bl)); \
+ (sl) = __x; \
+ } while (0)
+
+#define gmp_umul_ppmm(w1, w0, u, v) \
+ do { \
+ int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; \
+ if (sizeof(unsigned int) * CHAR_BIT >= 2 * GMP_LIMB_BITS) \
+ { \
+ unsigned int __ww = (unsigned int) (u) * (v); \
+ w0 = (mp_limb_t) __ww; \
+ w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \
+ } \
+ else if (GMP_ULONG_BITS >= 2 * GMP_LIMB_BITS) \
+ { \
+ unsigned long int __ww = (unsigned long int) (u) * (v); \
+ w0 = (mp_limb_t) __ww; \
+ w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \
+ } \
+ else { \
+ mp_limb_t __x0, __x1, __x2, __x3; \
+ unsigned __ul, __vl, __uh, __vh; \
+ mp_limb_t __u = (u), __v = (v); \
+ assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); \
+ \
+ __ul = __u & GMP_LLIMB_MASK; \
+ __uh = __u >> (GMP_LIMB_BITS / 2); \
+ __vl = __v & GMP_LLIMB_MASK; \
+ __vh = __v >> (GMP_LIMB_BITS / 2); \
+ \
+ __x0 = (mp_limb_t) __ul * __vl; \
+ __x1 = (mp_limb_t) __ul * __vh; \
+ __x2 = (mp_limb_t) __uh * __vl; \
+ __x3 = (mp_limb_t) __uh * __vh; \
+ \
+ __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \
+ (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \
+ } \
+ } while (0)
+
+/* If mp_limb_t is of size smaller than int, plain u*v implies
+ automatic promotion to *signed* int, and then multiply may overflow
+ and cause undefined behavior. Explicitly cast to unsigned int for
+ that case. */
+#define gmp_umullo_limb(u, v) \
+ ((sizeof(mp_limb_t) >= sizeof(int)) ? (u)*(v) : (unsigned int)(u) * (v))
+
+#define gmp_udiv_qrnnd_preinv(q, r, nh, nl, d, di) \
+ do { \
+ mp_limb_t _qh, _ql, _r, _mask; \
+ gmp_umul_ppmm (_qh, _ql, (nh), (di)); \
+ gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \
+ _r = (nl) - gmp_umullo_limb (_qh, (d)); \
+ _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \
+ _qh += _mask; \
+ _r += _mask & (d); \
+ if (_r >= (d)) \
+ { \
+ _r -= (d); \
+ _qh++; \
+ } \
+ \
+ (r) = _r; \
+ (q) = _qh; \
+ } while (0)
+
+#define gmp_udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \
+ do { \
+ mp_limb_t _q0, _t1, _t0, _mask; \
+ gmp_umul_ppmm ((q), _q0, (n2), (dinv)); \
+ gmp_add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \
+ \
+ /* Compute the two most significant limbs of n - q'd */ \
+ (r1) = (n1) - gmp_umullo_limb ((d1), (q)); \
+ gmp_sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0)); \
+ gmp_umul_ppmm (_t1, _t0, (d0), (q)); \
+ gmp_sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \
+ (q)++; \
+ \
+ /* Conditionally adjust q and the remainders */ \
+ _mask = - (mp_limb_t) ((r1) >= _q0); \
+ (q) += _mask; \
+ gmp_add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \
+ if ((r1) >= (d1)) \
+ { \
+ if ((r1) > (d1) || (r0) >= (d0)) \
+ { \
+ (q)++; \
+ gmp_sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \
+ } \
+ } \
+ } while (0)
+
+/* Swap macros. */
+#define MP_LIMB_T_SWAP(x, y) \
+ do { \
+ mp_limb_t __mp_limb_t_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_limb_t_swap__tmp; \
+ } while (0)
+#define MP_SIZE_T_SWAP(x, y) \
+ do { \
+ mp_size_t __mp_size_t_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_size_t_swap__tmp; \
+ } while (0)
+#define MP_BITCNT_T_SWAP(x,y) \
+ do { \
+ mp_bitcnt_t __mp_bitcnt_t_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_bitcnt_t_swap__tmp; \
+ } while (0)
+#define MP_PTR_SWAP(x, y) \
+ do { \
+ mp_ptr __mp_ptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_ptr_swap__tmp; \
+ } while (0)
+#define MP_SRCPTR_SWAP(x, y) \
+ do { \
+ mp_srcptr __mp_srcptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_srcptr_swap__tmp; \
+ } while (0)
+
+#define MPN_PTR_SWAP(xp,xs, yp,ys) \
+ do { \
+ MP_PTR_SWAP (xp, yp); \
+ MP_SIZE_T_SWAP (xs, ys); \
+ } while(0)
+#define MPN_SRCPTR_SWAP(xp,xs, yp,ys) \
+ do { \
+ MP_SRCPTR_SWAP (xp, yp); \
+ MP_SIZE_T_SWAP (xs, ys); \
+ } while(0)
+
+#define MPZ_PTR_SWAP(x, y) \
+ do { \
+ mpz_ptr __mpz_ptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mpz_ptr_swap__tmp; \
+ } while (0)
+#define MPZ_SRCPTR_SWAP(x, y) \
+ do { \
+ mpz_srcptr __mpz_srcptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mpz_srcptr_swap__tmp; \
+ } while (0)
+
+const int mp_bits_per_limb = GMP_LIMB_BITS;
+
+
+/* Memory allocation and other helper functions. */
+static void
+gmp_die (const char *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+ abort();
+}
+
+static void *
+gmp_default_alloc (size_t size)
+{
+ void *p;
+
+ assert (size > 0);
+
+ p = malloc (size);
+ if (!p)
+ gmp_die("gmp_default_alloc: Virtual memory exhausted.");
+
+ return p;
+}
+
+static void *
+gmp_default_realloc (void *old, size_t unused_old_size, size_t new_size)
+{
+ void * p;
+
+ p = realloc (old, new_size);
+
+ if (!p)
+ gmp_die("gmp_default_realloc: Virtual memory exhausted.");
+
+ return p;
+}
+
+static void
+gmp_default_free (void *p, size_t unused_size)
+{
+ free (p);
+}
+
+static void * (*gmp_allocate_func) (size_t) = gmp_default_alloc;
+static void * (*gmp_reallocate_func) (void *, size_t, size_t) = gmp_default_realloc;
+static void (*gmp_free_func) (void *, size_t) = gmp_default_free;
+
+void
+mp_get_memory_functions (void *(**alloc_func) (size_t),
+ void *(**realloc_func) (void *, size_t, size_t),
+ void (**free_func) (void *, size_t))
+{
+ if (alloc_func)
+ *alloc_func = gmp_allocate_func;
+
+ if (realloc_func)
+ *realloc_func = gmp_reallocate_func;
+
+ if (free_func)
+ *free_func = gmp_free_func;
+}
+
+void
+mp_set_memory_functions (void *(*alloc_func) (size_t),
+ void *(*realloc_func) (void *, size_t, size_t),
+ void (*free_func) (void *, size_t))
+{
+ if (!alloc_func)
+ alloc_func = gmp_default_alloc;
+ if (!realloc_func)
+ realloc_func = gmp_default_realloc;
+ if (!free_func)
+ free_func = gmp_default_free;
+
+ gmp_allocate_func = alloc_func;
+ gmp_reallocate_func = realloc_func;
+ gmp_free_func = free_func;
+}
+
+#define gmp_alloc(size) ((*gmp_allocate_func)((size)))
+#define gmp_free(p, size) ((*gmp_free_func) ((p), (size)))
+#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, old_size, size))
+
+static mp_ptr
+gmp_alloc_limbs (mp_size_t size)
+{
+ return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t));
+}
+
+static mp_ptr
+gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size)
+{
+ assert (size > 0);
+ return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * sizeof (mp_limb_t));
+}
+
+static void
+gmp_free_limbs (mp_ptr old, mp_size_t size)
+{
+ gmp_free (old, size * sizeof (mp_limb_t));
+}
+
+
+/* MPN interface */
+
+void
+mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n)
+{
+ mp_size_t i;
+ for (i = 0; i < n; i++)
+ d[i] = s[i];
+}
+
+void
+mpn_copyd (mp_ptr d, mp_srcptr s, mp_size_t n)
+{
+ while (--n >= 0)
+ d[n] = s[n];
+}
+
+int
+mpn_cmp (mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ while (--n >= 0)
+ {
+ if (ap[n] != bp[n])
+ return ap[n] > bp[n] ? 1 : -1;
+ }
+ return 0;
+}
+
+static int
+mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
+{
+ if (an != bn)
+ return an < bn ? -1 : 1;
+ else
+ return mpn_cmp (ap, bp, an);
+}
+
+static mp_size_t
+mpn_normalized_size (mp_srcptr xp, mp_size_t n)
+{
+ while (n > 0 && xp[n-1] == 0)
+ --n;
+ return n;
+}
+
+int
+mpn_zero_p(mp_srcptr rp, mp_size_t n)
+{
+ return mpn_normalized_size (rp, n) == 0;
+}
+
+void
+mpn_zero (mp_ptr rp, mp_size_t n)
+{
+ while (--n >= 0)
+ rp[n] = 0;
+}
+
+mp_limb_t
+mpn_add_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
+{
+ mp_size_t i;
+
+ assert (n > 0);
+ i = 0;
+ do
+ {
+ mp_limb_t r = ap[i] + b;
+ /* Carry out */
+ b = (r < b);
+ rp[i] = r;
+ }
+ while (++i < n);
+
+ return b;
+}
+
+mp_limb_t
+mpn_add_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ mp_size_t i;
+ mp_limb_t cy;
+
+ for (i = 0, cy = 0; i < n; i++)
+ {
+ mp_limb_t a, b, r;
+ a = ap[i]; b = bp[i];
+ r = a + cy;
+ cy = (r < cy);
+ r += b;
+ cy += (r < b);
+ rp[i] = r;
+ }
+ return cy;
+}
+
+mp_limb_t
+mpn_add (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
+{
+ mp_limb_t cy;
+
+ assert (an >= bn);
+
+ cy = mpn_add_n (rp, ap, bp, bn);
+ if (an > bn)
+ cy = mpn_add_1 (rp + bn, ap + bn, an - bn, cy);
+ return cy;
+}
+
+mp_limb_t
+mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
+{
+ mp_size_t i;
+
+ assert (n > 0);
+
+ i = 0;
+ do
+ {
+ mp_limb_t a = ap[i];
+ /* Carry out */
+ mp_limb_t cy = a < b;
+ rp[i] = a - b;
+ b = cy;
+ }
+ while (++i < n);
+
+ return b;
+}
+
+mp_limb_t
+mpn_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ mp_size_t i;
+ mp_limb_t cy;
+
+ for (i = 0, cy = 0; i < n; i++)
+ {
+ mp_limb_t a, b;
+ a = ap[i]; b = bp[i];
+ b += cy;
+ cy = (b < cy);
+ cy += (a < b);
+ rp[i] = a - b;
+ }
+ return cy;
+}
+
+mp_limb_t
+mpn_sub (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
+{
+ mp_limb_t cy;
+
+ assert (an >= bn);
+
+ cy = mpn_sub_n (rp, ap, bp, bn);
+ if (an > bn)
+ cy = mpn_sub_1 (rp + bn, ap + bn, an - bn, cy);
+ return cy;
+}
+
+mp_limb_t
+mpn_mul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
+{
+ mp_limb_t ul, cl, hpl, lpl;
+
+ assert (n >= 1);
+
+ cl = 0;
+ do
+ {
+ ul = *up++;
+ gmp_umul_ppmm (hpl, lpl, ul, vl);
+
+ lpl += cl;
+ cl = (lpl < cl) + hpl;
+
+ *rp++ = lpl;
+ }
+ while (--n != 0);
+
+ return cl;
+}
+
+mp_limb_t
+mpn_addmul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
+{
+ mp_limb_t ul, cl, hpl, lpl, rl;
+
+ assert (n >= 1);
+
+ cl = 0;
+ do
+ {
+ ul = *up++;
+ gmp_umul_ppmm (hpl, lpl, ul, vl);
+
+ lpl += cl;
+ cl = (lpl < cl) + hpl;
+
+ rl = *rp;
+ lpl = rl + lpl;
+ cl += lpl < rl;
+ *rp++ = lpl;
+ }
+ while (--n != 0);
+
+ return cl;
+}
+
+mp_limb_t
+mpn_submul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
+{
+ mp_limb_t ul, cl, hpl, lpl, rl;
+
+ assert (n >= 1);
+
+ cl = 0;
+ do
+ {
+ ul = *up++;
+ gmp_umul_ppmm (hpl, lpl, ul, vl);
+
+ lpl += cl;
+ cl = (lpl < cl) + hpl;
+
+ rl = *rp;
+ lpl = rl - lpl;
+ cl += lpl > rl;
+ *rp++ = lpl;
+ }
+ while (--n != 0);
+
+ return cl;
+}
+
+mp_limb_t
+mpn_mul (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
+{
+ assert (un >= vn);
+ assert (vn >= 1);
+ assert (!GMP_MPN_OVERLAP_P(rp, un + vn, up, un));
+ assert (!GMP_MPN_OVERLAP_P(rp, un + vn, vp, vn));
+
+ /* We first multiply by the low order limb. This result can be
+ stored, not added, to rp. We also avoid a loop for zeroing this
+ way. */
+
+ rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
+
+ /* Now accumulate the product of up[] and the next higher limb from
+ vp[]. */
+
+ while (--vn >= 1)
+ {
+ rp += 1, vp += 1;
+ rp[un] = mpn_addmul_1 (rp, up, un, vp[0]);
+ }
+ return rp[un];
+}
+
+void
+mpn_mul_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ mpn_mul (rp, ap, n, bp, n);
+}
+
+void
+mpn_sqr (mp_ptr rp, mp_srcptr ap, mp_size_t n)
+{
+ mpn_mul (rp, ap, n, ap, n);
+}
+
+mp_limb_t
+mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
+{
+ mp_limb_t high_limb, low_limb;
+ unsigned int tnc;
+ mp_limb_t retval;
+
+ assert (n >= 1);
+ assert (cnt >= 1);
+ assert (cnt < GMP_LIMB_BITS);
+
+ up += n;
+ rp += n;
+
+ tnc = GMP_LIMB_BITS - cnt;
+ low_limb = *--up;
+ retval = low_limb >> tnc;
+ high_limb = (low_limb << cnt);
+
+ while (--n != 0)
+ {
+ low_limb = *--up;
+ *--rp = high_limb | (low_limb >> tnc);
+ high_limb = (low_limb << cnt);
+ }
+ *--rp = high_limb;
+
+ return retval;
+}
+
+mp_limb_t
+mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
+{
+ mp_limb_t high_limb, low_limb;
+ unsigned int tnc;
+ mp_limb_t retval;
+
+ assert (n >= 1);
+ assert (cnt >= 1);
+ assert (cnt < GMP_LIMB_BITS);
+
+ tnc = GMP_LIMB_BITS - cnt;
+ high_limb = *up++;
+ retval = (high_limb << tnc);
+ low_limb = high_limb >> cnt;
+
+ while (--n != 0)
+ {
+ high_limb = *up++;
+ *rp++ = low_limb | (high_limb << tnc);
+ low_limb = high_limb >> cnt;
+ }
+ *rp = low_limb;
+
+ return retval;
+}
+
+static mp_bitcnt_t
+mpn_common_scan (mp_limb_t limb, mp_size_t i, mp_srcptr up, mp_size_t un,
+ mp_limb_t ux)
+{
+ unsigned cnt;
+
+ assert (ux == 0 || ux == GMP_LIMB_MAX);
+ assert (0 <= i && i <= un );
+
+ while (limb == 0)
+ {
+ i++;
+ if (i == un)
+ return (ux == 0 ? ~(mp_bitcnt_t) 0 : un * GMP_LIMB_BITS);
+ limb = ux ^ up[i];
+ }
+ gmp_ctz (cnt, limb);
+ return (mp_bitcnt_t) i * GMP_LIMB_BITS + cnt;
+}
+
+mp_bitcnt_t
+mpn_scan1 (mp_srcptr ptr, mp_bitcnt_t bit)
+{
+ mp_size_t i;
+ i = bit / GMP_LIMB_BITS;
+
+ return mpn_common_scan ( ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)),
+ i, ptr, i, 0);
+}
+
+mp_bitcnt_t
+mpn_scan0 (mp_srcptr ptr, mp_bitcnt_t bit)
+{
+ mp_size_t i;
+ i = bit / GMP_LIMB_BITS;
+
+ return mpn_common_scan (~ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)),
+ i, ptr, i, GMP_LIMB_MAX);
+}
+
+void
+mpn_com (mp_ptr rp, mp_srcptr up, mp_size_t n)
+{
+ while (--n >= 0)
+ *rp++ = ~ *up++;
+}
+
+mp_limb_t
+mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n)
+{
+ while (*up == 0)
+ {
+ *rp = 0;
+ if (!--n)
+ return 0;
+ ++up; ++rp;
+ }
+ *rp = - *up;
+ mpn_com (++rp, ++up, --n);
+ return 1;
+}
+
+
+/* MPN division interface. */
+
+/* The 3/2 inverse is defined as
+
+ m = floor( (B^3-1) / (B u1 + u0)) - B
+*/
+mp_limb_t
+mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
+{
+ mp_limb_t r, m;
+
+ {
+ mp_limb_t p, ql;
+ unsigned ul, uh, qh;
+
+ assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t));
+ /* For notation, let b denote the half-limb base, so that B = b^2.
+ Split u1 = b uh + ul. */
+ ul = u1 & GMP_LLIMB_MASK;
+ uh = u1 >> (GMP_LIMB_BITS / 2);
+
+ /* Approximation of the high half of quotient. Differs from the 2/1
+ inverse of the half limb uh, since we have already subtracted
+ u0. */
+ qh = (u1 ^ GMP_LIMB_MAX) / uh;
+
+ /* Adjust to get a half-limb 3/2 inverse, i.e., we want
+
+ qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
+ = floor( (b (~u) + b-1) / u),
+
+ and the remainder
+
+ r = b (~u) + b-1 - qh (b uh + ul)
+ = b (~u - qh uh) + b-1 - qh ul
+
+ Subtraction of qh ul may underflow, which implies adjustments.
+ But by normalization, 2 u >= B > qh ul, so we need to adjust by
+ at most 2.
+ */
+
+ r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
+
+ p = (mp_limb_t) qh * ul;
+ /* Adjustment steps taken from udiv_qrnnd_c */
+ if (r < p)
+ {
+ qh--;
+ r += u1;
+ if (r >= u1) /* i.e. we didn't get carry when adding to r */
+ if (r < p)
+ {
+ qh--;
+ r += u1;
+ }
+ }
+ r -= p;
+
+ /* Low half of the quotient is
+
+ ql = floor ( (b r + b-1) / u1).
+
+ This is a 3/2 division (on half-limbs), for which qh is a
+ suitable inverse. */
+
+ p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
+ /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
+ work, it is essential that ql is a full mp_limb_t. */
+ ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
+
+ /* By the 3/2 trick, we don't need the high half limb. */
+ r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
+
+ if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2))))
+ {
+ ql--;
+ r += u1;
+ }
+ m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql;
+ if (r >= u1)
+ {
+ m++;
+ r -= u1;
+ }
+ }
+
+ /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
+ 3/2 inverse. */
+ if (u0 > 0)
+ {
+ mp_limb_t th, tl;
+ r = ~r;
+ r += u0;
+ if (r < u0)
+ {
+ m--;
+ if (r >= u1)
+ {
+ m--;
+ r -= u1;
+ }
+ r -= u1;
+ }
+ gmp_umul_ppmm (th, tl, u0, m);
+ r += th;
+ if (r < th)
+ {
+ m--;
+ m -= ((r > u1) | ((r == u1) & (tl > u0)));
+ }
+ }
+
+ return m;
+}
+
+struct gmp_div_inverse
+{
+ /* Normalization shift count. */
+ unsigned shift;
+ /* Normalized divisor (d0 unused for mpn_div_qr_1) */
+ mp_limb_t d1, d0;
+ /* Inverse, for 2/1 or 3/2. */
+ mp_limb_t di;
+};
+
+static void
+mpn_div_qr_1_invert (struct gmp_div_inverse *inv, mp_limb_t d)
+{
+ unsigned shift;
+
+ assert (d > 0);
+ gmp_clz (shift, d);
+ inv->shift = shift;
+ inv->d1 = d << shift;
+ inv->di = mpn_invert_limb (inv->d1);
+}
+
+static void
+mpn_div_qr_2_invert (struct gmp_div_inverse *inv,
+ mp_limb_t d1, mp_limb_t d0)
+{
+ unsigned shift;
+
+ assert (d1 > 0);
+ gmp_clz (shift, d1);
+ inv->shift = shift;
+ if (shift > 0)
+ {
+ d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift));
+ d0 <<= shift;
+ }
+ inv->d1 = d1;
+ inv->d0 = d0;
+ inv->di = mpn_invert_3by2 (d1, d0);
+}
+
+static void
+mpn_div_qr_invert (struct gmp_div_inverse *inv,
+ mp_srcptr dp, mp_size_t dn)
+{
+ assert (dn > 0);
+
+ if (dn == 1)
+ mpn_div_qr_1_invert (inv, dp[0]);
+ else if (dn == 2)
+ mpn_div_qr_2_invert (inv, dp[1], dp[0]);
+ else
+ {
+ unsigned shift;
+ mp_limb_t d1, d0;
+
+ d1 = dp[dn-1];
+ d0 = dp[dn-2];
+ assert (d1 > 0);
+ gmp_clz (shift, d1);
+ inv->shift = shift;
+ if (shift > 0)
+ {
+ d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift));
+ d0 = (d0 << shift) | (dp[dn-3] >> (GMP_LIMB_BITS - shift));
+ }
+ inv->d1 = d1;
+ inv->d0 = d0;
+ inv->di = mpn_invert_3by2 (d1, d0);
+ }
+}
+
+/* Not matching current public gmp interface, rather corresponding to
+ the sbpi1_div_* functions. */
+static mp_limb_t
+mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
+ const struct gmp_div_inverse *inv)
+{
+ mp_limb_t d, di;
+ mp_limb_t r;
+ mp_ptr tp = NULL;
+ mp_size_t tn = 0;
+
+ if (inv->shift > 0)
+ {
+ /* Shift, reusing qp area if possible. In-place shift if qp == np. */
+ tp = qp;
+ if (!tp)
+ {
+ tn = nn;
+ tp = gmp_alloc_limbs (tn);
+ }
+ r = mpn_lshift (tp, np, nn, inv->shift);
+ np = tp;
+ }
+ else
+ r = 0;
+
+ d = inv->d1;
+ di = inv->di;
+ while (--nn >= 0)
+ {
+ mp_limb_t q;
+
+ gmp_udiv_qrnnd_preinv (q, r, r, np[nn], d, di);
+ if (qp)
+ qp[nn] = q;
+ }
+ if (tn)
+ gmp_free_limbs (tp, tn);
+
+ return r >> inv->shift;
+}
+
+static void
+mpn_div_qr_2_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn,
+ const struct gmp_div_inverse *inv)
+{
+ unsigned shift;
+ mp_size_t i;
+ mp_limb_t d1, d0, di, r1, r0;
+
+ assert (nn >= 2);
+ shift = inv->shift;
+ d1 = inv->d1;
+ d0 = inv->d0;
+ di = inv->di;
+
+ if (shift > 0)
+ r1 = mpn_lshift (np, np, nn, shift);
+ else
+ r1 = 0;
+
+ r0 = np[nn - 1];
+
+ i = nn - 2;
+ do
+ {
+ mp_limb_t n0, q;
+ n0 = np[i];
+ gmp_udiv_qr_3by2 (q, r1, r0, r1, r0, n0, d1, d0, di);
+
+ if (qp)
+ qp[i] = q;
+ }
+ while (--i >= 0);
+
+ if (shift > 0)
+ {
+ assert ((r0 & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - shift))) == 0);
+ r0 = (r0 >> shift) | (r1 << (GMP_LIMB_BITS - shift));
+ r1 >>= shift;
+ }
+
+ np[1] = r1;
+ np[0] = r0;
+}
+
+static void
+mpn_div_qr_pi1 (mp_ptr qp,
+ mp_ptr np, mp_size_t nn, mp_limb_t n1,
+ mp_srcptr dp, mp_size_t dn,
+ mp_limb_t dinv)
+{
+ mp_size_t i;
+
+ mp_limb_t d1, d0;
+ mp_limb_t cy, cy1;
+ mp_limb_t q;
+
+ assert (dn > 2);
+ assert (nn >= dn);
+
+ d1 = dp[dn - 1];
+ d0 = dp[dn - 2];
+
+ assert ((d1 & GMP_LIMB_HIGHBIT) != 0);
+ /* Iteration variable is the index of the q limb.
+ *
+ * We divide <n1, np[dn-1+i], np[dn-2+i], np[dn-3+i],..., np[i]>
+ * by <d1, d0, dp[dn-3], ..., dp[0] >
+ */
+
+ i = nn - dn;
+ do
+ {
+ mp_limb_t n0 = np[dn-1+i];
+
+ if (n1 == d1 && n0 == d0)
+ {
+ q = GMP_LIMB_MAX;
+ mpn_submul_1 (np+i, dp, dn, q);
+ n1 = np[dn-1+i]; /* update n1, last loop's value will now be invalid */
+ }
+ else
+ {
+ gmp_udiv_qr_3by2 (q, n1, n0, n1, n0, np[dn-2+i], d1, d0, dinv);
+
+ cy = mpn_submul_1 (np + i, dp, dn-2, q);
+
+ cy1 = n0 < cy;
+ n0 = n0 - cy;
+ cy = n1 < cy1;
+ n1 = n1 - cy1;
+ np[dn-2+i] = n0;
+
+ if (cy != 0)
+ {
+ n1 += d1 + mpn_add_n (np + i, np + i, dp, dn - 1);
+ q--;
+ }
+ }
+
+ if (qp)
+ qp[i] = q;
+ }
+ while (--i >= 0);
+
+ np[dn - 1] = n1;
+}
+
+static void
+mpn_div_qr_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn,
+ mp_srcptr dp, mp_size_t dn,
+ const struct gmp_div_inverse *inv)
+{
+ assert (dn > 0);
+ assert (nn >= dn);
+
+ if (dn == 1)
+ np[0] = mpn_div_qr_1_preinv (qp, np, nn, inv);
+ else if (dn == 2)
+ mpn_div_qr_2_preinv (qp, np, nn, inv);
+ else
+ {
+ mp_limb_t nh;
+ unsigned shift;
+
+ assert (inv->d1 == dp[dn-1]);
+ assert (inv->d0 == dp[dn-2]);
+ assert ((inv->d1 & GMP_LIMB_HIGHBIT) != 0);
+
+ shift = inv->shift;
+ if (shift > 0)
+ nh = mpn_lshift (np, np, nn, shift);
+ else
+ nh = 0;
+
+ mpn_div_qr_pi1 (qp, np, nn, nh, dp, dn, inv->di);
+
+ if (shift > 0)
+ gmp_assert_nocarry (mpn_rshift (np, np, dn, shift));
+ }
+}
+
+static void
+mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
+{
+ struct gmp_div_inverse inv;
+ mp_ptr tp = NULL;
+
+ assert (dn > 0);
+ assert (nn >= dn);
+
+ mpn_div_qr_invert (&inv, dp, dn);
+ if (dn > 2 && inv.shift > 0)
+ {
+ tp = gmp_alloc_limbs (dn);
+ gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift));
+ dp = tp;
+ }
+ mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv);
+ if (tp)
+ gmp_free_limbs (tp, dn);
+}
+
+
+/* MPN base conversion. */
+static unsigned
+mpn_base_power_of_two_p (unsigned b)
+{
+ switch (b)
+ {
+ case 2: return 1;
+ case 4: return 2;
+ case 8: return 3;
+ case 16: return 4;
+ case 32: return 5;
+ case 64: return 6;
+ case 128: return 7;
+ case 256: return 8;
+ default: return 0;
+ }
+}
+
+struct mpn_base_info
+{
+ /* bb is the largest power of the base which fits in one limb, and
+ exp is the corresponding exponent. */
+ unsigned exp;
+ mp_limb_t bb;
+};
+
+static void
+mpn_get_base_info (struct mpn_base_info *info, mp_limb_t b)
+{
+ mp_limb_t m;
+ mp_limb_t p;
+ unsigned exp;
+
+ m = GMP_LIMB_MAX / b;
+ for (exp = 1, p = b; p <= m; exp++)
+ p *= b;
+
+ info->exp = exp;
+ info->bb = p;
+}
+
+static mp_bitcnt_t
+mpn_limb_size_in_base_2 (mp_limb_t u)
+{
+ unsigned shift;
+
+ assert (u > 0);
+ gmp_clz (shift, u);
+ return GMP_LIMB_BITS - shift;
+}
+
+static size_t
+mpn_get_str_bits (unsigned char *sp, unsigned bits, mp_srcptr up, mp_size_t un)
+{
+ unsigned char mask;
+ size_t sn, j;
+ mp_size_t i;
+ unsigned shift;
+
+ sn = ((un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1])
+ + bits - 1) / bits;
+
+ mask = (1U << bits) - 1;
+
+ for (i = 0, j = sn, shift = 0; j-- > 0;)
+ {
+ unsigned char digit = up[i] >> shift;
+
+ shift += bits;
+
+ if (shift >= GMP_LIMB_BITS && ++i < un)
+ {
+ shift -= GMP_LIMB_BITS;
+ digit |= up[i] << (bits - shift);
+ }
+ sp[j] = digit & mask;
+ }
+ return sn;
+}
+
+/* We generate digits from the least significant end, and reverse at
+ the end. */
+static size_t
+mpn_limb_get_str (unsigned char *sp, mp_limb_t w,
+ const struct gmp_div_inverse *binv)
+{
+ mp_size_t i;
+ for (i = 0; w > 0; i++)
+ {
+ mp_limb_t h, l, r;
+
+ h = w >> (GMP_LIMB_BITS - binv->shift);
+ l = w << binv->shift;
+
+ gmp_udiv_qrnnd_preinv (w, r, h, l, binv->d1, binv->di);
+ assert ((r & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - binv->shift))) == 0);
+ r >>= binv->shift;
+
+ sp[i] = r;
+ }
+ return i;
+}
+
+static size_t
+mpn_get_str_other (unsigned char *sp,
+ int base, const struct mpn_base_info *info,
+ mp_ptr up, mp_size_t un)
+{
+ struct gmp_div_inverse binv;
+ size_t sn;
+ size_t i;
+
+ mpn_div_qr_1_invert (&binv, base);
+
+ sn = 0;
+
+ if (un > 1)
+ {
+ struct gmp_div_inverse bbinv;
+ mpn_div_qr_1_invert (&bbinv, info->bb);
+
+ do
+ {
+ mp_limb_t w;
+ size_t done;
+ w = mpn_div_qr_1_preinv (up, up, un, &bbinv);
+ un -= (up[un-1] == 0);
+ done = mpn_limb_get_str (sp + sn, w, &binv);
+
+ for (sn += done; done < info->exp; done++)
+ sp[sn++] = 0;
+ }
+ while (un > 1);
+ }
+ sn += mpn_limb_get_str (sp + sn, up[0], &binv);
+
+ /* Reverse order */
+ for (i = 0; 2*i + 1 < sn; i++)
+ {
+ unsigned char t = sp[i];
+ sp[i] = sp[sn - i - 1];
+ sp[sn - i - 1] = t;
+ }
+
+ return sn;
+}
+
+size_t
+mpn_get_str (unsigned char *sp, int base, mp_ptr up, mp_size_t un)
+{
+ unsigned bits;
+
+ assert (un > 0);
+ assert (up[un-1] > 0);
+
+ bits = mpn_base_power_of_two_p (base);
+ if (bits)
+ return mpn_get_str_bits (sp, bits, up, un);
+ else
+ {
+ struct mpn_base_info info;
+
+ mpn_get_base_info (&info, base);
+ return mpn_get_str_other (sp, base, &info, up, un);
+ }
+}
+
+static mp_size_t
+mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
+ unsigned bits)
+{
+ mp_size_t rn;
+ mp_limb_t limb;
+ unsigned shift;
+
+ for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
+ {
+ limb |= (mp_limb_t) sp[sn] << shift;
+ shift += bits;
+ if (shift >= GMP_LIMB_BITS)
+ {
+ shift -= GMP_LIMB_BITS;
+ rp[rn++] = limb;
+ /* Next line is correct also if shift == 0,
+ bits == 8, and mp_limb_t == unsigned char. */
+ limb = (unsigned int) sp[sn] >> (bits - shift);
+ }
+ }
+ if (limb != 0)
+ rp[rn++] = limb;
+ else
+ rn = mpn_normalized_size (rp, rn);
+ return rn;
+}
+
+/* Result is usually normalized, except for all-zero input, in which
+ case a single zero limb is written at *RP, and 1 is returned. */
+static mp_size_t
+mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn,
+ mp_limb_t b, const struct mpn_base_info *info)
+{
+ mp_size_t rn;
+ mp_limb_t w;
+ unsigned k;
+ size_t j;
+
+ assert (sn > 0);
+
+ k = 1 + (sn - 1) % info->exp;
+
+ j = 0;
+ w = sp[j++];
+ while (--k != 0)
+ w = w * b + sp[j++];
+
+ rp[0] = w;
+
+ for (rn = 1; j < sn;)
+ {
+ mp_limb_t cy;
+
+ w = sp[j++];
+ for (k = 1; k < info->exp; k++)
+ w = w * b + sp[j++];
+
+ cy = mpn_mul_1 (rp, rp, rn, info->bb);
+ cy += mpn_add_1 (rp, rp, rn, w);
+ if (cy > 0)
+ rp[rn++] = cy;
+ }
+ assert (j == sn);
+
+ return rn;
+}
+
+mp_size_t
+mpn_set_str (mp_ptr rp, const unsigned char *sp, size_t sn, int base)
+{
+ unsigned bits;
+
+ if (sn == 0)
+ return 0;
+
+ bits = mpn_base_power_of_two_p (base);
+ if (bits)
+ return mpn_set_str_bits (rp, sp, sn, bits);
+ else
+ {
+ struct mpn_base_info info;
+
+ mpn_get_base_info (&info, base);
+ return mpn_set_str_other (rp, sp, sn, base, &info);
+ }
+}
+
+
+/* MPZ interface */
+void
+mpz_init (mpz_t r)
+{
+ static const mp_limb_t dummy_limb = GMP_LIMB_MAX & 0xc1a0;
+
+ r->_mp_alloc = 0;
+ r->_mp_size = 0;
+ r->_mp_d = (mp_ptr) &dummy_limb;
+}
+
+/* The utility of this function is a bit limited, since many functions
+ assigns the result variable using mpz_swap. */
+void
+mpz_init2 (mpz_t r, mp_bitcnt_t bits)
+{
+ mp_size_t rn;
+
+ bits -= (bits != 0); /* Round down, except if 0 */
+ rn = 1 + bits / GMP_LIMB_BITS;
+
+ r->_mp_alloc = rn;
+ r->_mp_size = 0;
+ r->_mp_d = gmp_alloc_limbs (rn);
+}
+
+void
+mpz_clear (mpz_t r)
+{
+ if (r->_mp_alloc)
+ gmp_free_limbs (r->_mp_d, r->_mp_alloc);
+}
+
+static mp_ptr
+mpz_realloc (mpz_t r, mp_size_t size)
+{
+ size = GMP_MAX (size, 1);
+
+ if (r->_mp_alloc)
+ r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size);
+ else
+ r->_mp_d = gmp_alloc_limbs (size);
+ r->_mp_alloc = size;
+
+ if (GMP_ABS (r->_mp_size) > size)
+ r->_mp_size = 0;
+
+ return r->_mp_d;
+}
+
+/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */
+#define MPZ_REALLOC(z,n) ((n) > (z)->_mp_alloc \
+ ? mpz_realloc(z,n) \
+ : (z)->_mp_d)
+
+/* MPZ assignment and basic conversions. */
+void
+mpz_set_si (mpz_t r, signed long int x)
+{
+ if (x >= 0)
+ mpz_set_ui (r, x);
+ else /* (x < 0) */
+ if (GMP_LIMB_BITS < GMP_ULONG_BITS)
+ {
+ mpz_set_ui (r, GMP_NEG_CAST (unsigned long int, x));
+ mpz_neg (r, r);
+ }
+ else
+ {
+ r->_mp_size = -1;
+ MPZ_REALLOC (r, 1)[0] = GMP_NEG_CAST (unsigned long int, x);
+ }
+}
+
+void
+mpz_set_ui (mpz_t r, unsigned long int x)
+{
+ if (x > 0)
+ {
+ r->_mp_size = 1;
+ MPZ_REALLOC (r, 1)[0] = x;
+ if (GMP_LIMB_BITS < GMP_ULONG_BITS)
+ {
+ int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS;
+ while (x >>= LOCAL_GMP_LIMB_BITS)
+ {
+ ++ r->_mp_size;
+ MPZ_REALLOC (r, r->_mp_size)[r->_mp_size - 1] = x;
+ }
+ }
+ }
+ else
+ r->_mp_size = 0;
+}
+
+void
+mpz_set (mpz_t r, const mpz_t x)
+{
+ /* Allow the NOP r == x */
+ if (r != x)
+ {
+ mp_size_t n;
+ mp_ptr rp;
+
+ n = GMP_ABS (x->_mp_size);
+ rp = MPZ_REALLOC (r, n);
+
+ mpn_copyi (rp, x->_mp_d, n);
+ r->_mp_size = x->_mp_size;
+ }
+}
+
+void
+mpz_init_set_si (mpz_t r, signed long int x)
+{
+ mpz_init (r);
+ mpz_set_si (r, x);
+}
+
+void
+mpz_init_set_ui (mpz_t r, unsigned long int x)
+{
+ mpz_init (r);
+ mpz_set_ui (r, x);
+}
+
+void
+mpz_init_set (mpz_t r, const mpz_t x)
+{
+ mpz_init (r);
+ mpz_set (r, x);
+}
+
+int
+mpz_fits_slong_p (const mpz_t u)
+{
+ return mpz_cmp_si (u, LONG_MAX) <= 0 && mpz_cmp_si (u, LONG_MIN) >= 0;
+}
+
+static int
+mpn_absfits_ulong_p (mp_srcptr up, mp_size_t un)
+{
+ int ulongsize = GMP_ULONG_BITS / GMP_LIMB_BITS;
+ mp_limb_t ulongrem = 0;
+
+ if (GMP_ULONG_BITS % GMP_LIMB_BITS != 0)
+ ulongrem = (mp_limb_t) (ULONG_MAX >> GMP_LIMB_BITS * ulongsize) + 1;
+
+ return un <= ulongsize || (up[ulongsize] < ulongrem && un == ulongsize + 1);
+}
+
+int
+mpz_fits_ulong_p (const mpz_t u)
+{
+ mp_size_t us = u->_mp_size;
+
+ return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us);
+}
+
+int
+mpz_fits_sint_p (const mpz_t u)
+{
+ return mpz_cmp_si (u, INT_MAX) <= 0 && mpz_cmp_si (u, INT_MIN) >= 0;
+}
+
+int
+mpz_fits_uint_p (const mpz_t u)
+{
+ return u->_mp_size >= 0 && mpz_cmpabs_ui (u, UINT_MAX) <= 0;
+}
+
+int
+mpz_fits_sshort_p (const mpz_t u)
+{
+ return mpz_cmp_si (u, SHRT_MAX) <= 0 && mpz_cmp_si (u, SHRT_MIN) >= 0;
+}
+
+int
+mpz_fits_ushort_p (const mpz_t u)
+{
+ return u->_mp_size >= 0 && mpz_cmpabs_ui (u, USHRT_MAX) <= 0;
+}
+
+long int
+mpz_get_si (const mpz_t u)
+{
+ unsigned long r = mpz_get_ui (u);
+ unsigned long c = -LONG_MAX - LONG_MIN;
+
+ if (u->_mp_size < 0)
+ /* This expression is necessary to properly handle -LONG_MIN */
+ return -(long) c - (long) ((r - c) & LONG_MAX);
+ else
+ return (long) (r & LONG_MAX);
+}
+
+unsigned long int
+mpz_get_ui (const mpz_t u)
+{
+ if (GMP_LIMB_BITS < GMP_ULONG_BITS)
+ {
+ int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS;
+ unsigned long r = 0;
+ mp_size_t n = GMP_ABS (u->_mp_size);
+ n = GMP_MIN (n, 1 + (mp_size_t) (GMP_ULONG_BITS - 1) / GMP_LIMB_BITS);
+ while (--n >= 0)
+ r = (r << LOCAL_GMP_LIMB_BITS) + u->_mp_d[n];
+ return r;
+ }
+
+ return u->_mp_size == 0 ? 0 : u->_mp_d[0];
+}
+
+size_t
+mpz_size (const mpz_t u)
+{
+ return GMP_ABS (u->_mp_size);
+}
+
+mp_limb_t
+mpz_getlimbn (const mpz_t u, mp_size_t n)
+{
+ if (n >= 0 && n < GMP_ABS (u->_mp_size))
+ return u->_mp_d[n];
+ else
+ return 0;
+}
+
+void
+mpz_realloc2 (mpz_t x, mp_bitcnt_t n)
+{
+ mpz_realloc (x, 1 + (n - (n != 0)) / GMP_LIMB_BITS);
+}
+
+mp_srcptr
+mpz_limbs_read (mpz_srcptr x)
+{
+ return x->_mp_d;
+}
+
+mp_ptr
+mpz_limbs_modify (mpz_t x, mp_size_t n)
+{
+ assert (n > 0);
+ return MPZ_REALLOC (x, n);
+}
+
+mp_ptr
+mpz_limbs_write (mpz_t x, mp_size_t n)
+{
+ return mpz_limbs_modify (x, n);
+}
+
+void
+mpz_limbs_finish (mpz_t x, mp_size_t xs)
+{
+ mp_size_t xn;
+ xn = mpn_normalized_size (x->_mp_d, GMP_ABS (xs));
+ x->_mp_size = xs < 0 ? -xn : xn;
+}
+
+static mpz_srcptr
+mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
+{
+ x->_mp_alloc = 0;
+ x->_mp_d = (mp_ptr) xp;
+ x->_mp_size = xs;
+ return x;
+}
+
+mpz_srcptr
+mpz_roinit_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
+{
+ mpz_roinit_normal_n (x, xp, xs);
+ mpz_limbs_finish (x, xs);
+ return x;
+}
+
+
+/* Conversions and comparison to double. */
+void
+mpz_set_d (mpz_t r, double x)
+{
+ int sign;
+ mp_ptr rp;
+ mp_size_t rn, i;
+ double B;
+ double Bi;
+ mp_limb_t f;
+
+ /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is
+ zero or infinity. */
+ if (x != x || x == x * 0.5)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ sign = x < 0.0 ;
+ if (sign)
+ x = - x;
+
+ if (x < 1.0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+ B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+ Bi = 1.0 / B;
+ for (rn = 1; x >= B; rn++)
+ x *= Bi;
+
+ rp = MPZ_REALLOC (r, rn);
+
+ f = (mp_limb_t) x;
+ x -= f;
+ assert (x < 1.0);
+ i = rn-1;
+ rp[i] = f;
+ while (--i >= 0)
+ {
+ x = B * x;
+ f = (mp_limb_t) x;
+ x -= f;
+ assert (x < 1.0);
+ rp[i] = f;
+ }
+
+ r->_mp_size = sign ? - rn : rn;
+}
+
+void
+mpz_init_set_d (mpz_t r, double x)
+{
+ mpz_init (r);
+ mpz_set_d (r, x);
+}
+
+double
+mpz_get_d (const mpz_t u)
+{
+ int m;
+ mp_limb_t l;
+ mp_size_t un;
+ double x;
+ double B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+
+ un = GMP_ABS (u->_mp_size);
+
+ if (un == 0)
+ return 0.0;
+
+ l = u->_mp_d[--un];
+ gmp_clz (m, l);
+ m = m + GMP_DBL_MANT_BITS - GMP_LIMB_BITS;
+ if (m < 0)
+ l &= GMP_LIMB_MAX << -m;
+
+ for (x = l; --un >= 0;)
+ {
+ x = B*x;
+ if (m > 0) {
+ l = u->_mp_d[un];
+ m -= GMP_LIMB_BITS;
+ if (m < 0)
+ l &= GMP_LIMB_MAX << -m;
+ x += l;
+ }
+ }
+
+ if (u->_mp_size < 0)
+ x = -x;
+
+ return x;
+}
+
+int
+mpz_cmpabs_d (const mpz_t x, double d)
+{
+ mp_size_t xn;
+ double B, Bi;
+ mp_size_t i;
+
+ xn = x->_mp_size;
+ d = GMP_ABS (d);
+
+ if (xn != 0)
+ {
+ xn = GMP_ABS (xn);
+
+ B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+ Bi = 1.0 / B;
+
+ /* Scale d so it can be compared with the top limb. */
+ for (i = 1; i < xn; i++)
+ d *= Bi;
+
+ if (d >= B)
+ return -1;
+
+ /* Compare floor(d) to top limb, subtract and cancel when equal. */
+ for (i = xn; i-- > 0;)
+ {
+ mp_limb_t f, xl;
+
+ f = (mp_limb_t) d;
+ xl = x->_mp_d[i];
+ if (xl > f)
+ return 1;
+ else if (xl < f)
+ return -1;
+ d = B * (d - f);
+ }
+ }
+ return - (d > 0.0);
+}
+
+int
+mpz_cmp_d (const mpz_t x, double d)
+{
+ if (x->_mp_size < 0)
+ {
+ if (d >= 0.0)
+ return -1;
+ else
+ return -mpz_cmpabs_d (x, d);
+ }
+ else
+ {
+ if (d < 0.0)
+ return 1;
+ else
+ return mpz_cmpabs_d (x, d);
+ }
+}
+
+
+/* MPZ comparisons and the like. */
+int
+mpz_sgn (const mpz_t u)
+{
+ return GMP_CMP (u->_mp_size, 0);
+}
+
+int
+mpz_cmp_si (const mpz_t u, long v)
+{
+ mp_size_t usize = u->_mp_size;
+
+ if (v >= 0)
+ return mpz_cmp_ui (u, v);
+ else if (usize >= 0)
+ return 1;
+ else
+ return - mpz_cmpabs_ui (u, GMP_NEG_CAST (unsigned long int, v));
+}
+
+int
+mpz_cmp_ui (const mpz_t u, unsigned long v)
+{
+ mp_size_t usize = u->_mp_size;
+
+ if (usize < 0)
+ return -1;
+ else
+ return mpz_cmpabs_ui (u, v);
+}
+
+int
+mpz_cmp (const mpz_t a, const mpz_t b)
+{
+ mp_size_t asize = a->_mp_size;
+ mp_size_t bsize = b->_mp_size;
+
+ if (asize != bsize)
+ return (asize < bsize) ? -1 : 1;
+ else if (asize >= 0)
+ return mpn_cmp (a->_mp_d, b->_mp_d, asize);
+ else
+ return mpn_cmp (b->_mp_d, a->_mp_d, -asize);
+}
+
+int
+mpz_cmpabs_ui (const mpz_t u, unsigned long v)
+{
+ mp_size_t un = GMP_ABS (u->_mp_size);
+
+ if (! mpn_absfits_ulong_p (u->_mp_d, un))
+ return 1;
+ else
+ {
+ unsigned long uu = mpz_get_ui (u);
+ return GMP_CMP(uu, v);
+ }
+}
+
+int
+mpz_cmpabs (const mpz_t u, const mpz_t v)
+{
+ return mpn_cmp4 (u->_mp_d, GMP_ABS (u->_mp_size),
+ v->_mp_d, GMP_ABS (v->_mp_size));
+}
+
+void
+mpz_abs (mpz_t r, const mpz_t u)
+{
+ mpz_set (r, u);
+ r->_mp_size = GMP_ABS (r->_mp_size);
+}
+
+void
+mpz_neg (mpz_t r, const mpz_t u)
+{
+ mpz_set (r, u);
+ r->_mp_size = -r->_mp_size;
+}
+
+void
+mpz_swap (mpz_t u, mpz_t v)
+{
+ MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc);
+ MPN_PTR_SWAP (u->_mp_d, u->_mp_size, v->_mp_d, v->_mp_size);
+}
+
+
+/* MPZ addition and subtraction */
+
+
+void
+mpz_add_ui (mpz_t r, const mpz_t a, unsigned long b)
+{
+ mpz_t bb;
+ mpz_init_set_ui (bb, b);
+ mpz_add (r, a, bb);
+ mpz_clear (bb);
+}
+
+void
+mpz_sub_ui (mpz_t r, const mpz_t a, unsigned long b)
+{
+ mpz_ui_sub (r, b, a);
+ mpz_neg (r, r);
+}
+
+void
+mpz_ui_sub (mpz_t r, unsigned long a, const mpz_t b)
+{
+ mpz_neg (r, b);
+ mpz_add_ui (r, r, a);
+}
+
+static mp_size_t
+mpz_abs_add (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t an = GMP_ABS (a->_mp_size);
+ mp_size_t bn = GMP_ABS (b->_mp_size);
+ mp_ptr rp;
+ mp_limb_t cy;
+
+ if (an < bn)
+ {
+ MPZ_SRCPTR_SWAP (a, b);
+ MP_SIZE_T_SWAP (an, bn);
+ }
+
+ rp = MPZ_REALLOC (r, an + 1);
+ cy = mpn_add (rp, a->_mp_d, an, b->_mp_d, bn);
+
+ rp[an] = cy;
+
+ return an + cy;
+}
+
+static mp_size_t
+mpz_abs_sub (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t an = GMP_ABS (a->_mp_size);
+ mp_size_t bn = GMP_ABS (b->_mp_size);
+ int cmp;
+ mp_ptr rp;
+
+ cmp = mpn_cmp4 (a->_mp_d, an, b->_mp_d, bn);
+ if (cmp > 0)
+ {
+ rp = MPZ_REALLOC (r, an);
+ gmp_assert_nocarry (mpn_sub (rp, a->_mp_d, an, b->_mp_d, bn));
+ return mpn_normalized_size (rp, an);
+ }
+ else if (cmp < 0)
+ {
+ rp = MPZ_REALLOC (r, bn);
+ gmp_assert_nocarry (mpn_sub (rp, b->_mp_d, bn, a->_mp_d, an));
+ return -mpn_normalized_size (rp, bn);
+ }
+ else
+ return 0;
+}
+
+void
+mpz_add (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t rn;
+
+ if ( (a->_mp_size ^ b->_mp_size) >= 0)
+ rn = mpz_abs_add (r, a, b);
+ else
+ rn = mpz_abs_sub (r, a, b);
+
+ r->_mp_size = a->_mp_size >= 0 ? rn : - rn;
+}
+
+void
+mpz_sub (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t rn;
+
+ if ( (a->_mp_size ^ b->_mp_size) >= 0)
+ rn = mpz_abs_sub (r, a, b);
+ else
+ rn = mpz_abs_add (r, a, b);
+
+ r->_mp_size = a->_mp_size >= 0 ? rn : - rn;
+}
+
+
+/* MPZ multiplication */
+void
+mpz_mul_si (mpz_t r, const mpz_t u, long int v)
+{
+ if (v < 0)
+ {
+ mpz_mul_ui (r, u, GMP_NEG_CAST (unsigned long int, v));
+ mpz_neg (r, r);
+ }
+ else
+ mpz_mul_ui (r, u, v);
+}
+
+void
+mpz_mul_ui (mpz_t r, const mpz_t u, unsigned long int v)
+{
+ mpz_t vv;
+ mpz_init_set_ui (vv, v);
+ mpz_mul (r, u, vv);
+ mpz_clear (vv);
+ return;
+}
+
+void
+mpz_mul (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ int sign;
+ mp_size_t un, vn, rn;
+ mpz_t t;
+ mp_ptr tp;
+
+ un = u->_mp_size;
+ vn = v->_mp_size;
+
+ if (un == 0 || vn == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ sign = (un ^ vn) < 0;
+
+ un = GMP_ABS (un);
+ vn = GMP_ABS (vn);
+
+ mpz_init2 (t, (un + vn) * GMP_LIMB_BITS);
+
+ tp = t->_mp_d;
+ if (un >= vn)
+ mpn_mul (tp, u->_mp_d, un, v->_mp_d, vn);
+ else
+ mpn_mul (tp, v->_mp_d, vn, u->_mp_d, un);
+
+ rn = un + vn;
+ rn -= tp[rn-1] == 0;
+
+ t->_mp_size = sign ? - rn : rn;
+ mpz_swap (r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_mul_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bits)
+{
+ mp_size_t un, rn;
+ mp_size_t limbs;
+ unsigned shift;
+ mp_ptr rp;
+
+ un = GMP_ABS (u->_mp_size);
+ if (un == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ limbs = bits / GMP_LIMB_BITS;
+ shift = bits % GMP_LIMB_BITS;
+
+ rn = un + limbs + (shift > 0);
+ rp = MPZ_REALLOC (r, rn);
+ if (shift > 0)
+ {
+ mp_limb_t cy = mpn_lshift (rp + limbs, u->_mp_d, un, shift);
+ rp[rn-1] = cy;
+ rn -= (cy == 0);
+ }
+ else
+ mpn_copyd (rp + limbs, u->_mp_d, un);
+
+ mpn_zero (rp, limbs);
+
+ r->_mp_size = (u->_mp_size < 0) ? - rn : rn;
+}
+
+void
+mpz_addmul_ui (mpz_t r, const mpz_t u, unsigned long int v)
+{
+ mpz_t t;
+ mpz_init_set_ui (t, v);
+ mpz_mul (t, u, t);
+ mpz_add (r, r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_submul_ui (mpz_t r, const mpz_t u, unsigned long int v)
+{
+ mpz_t t;
+ mpz_init_set_ui (t, v);
+ mpz_mul (t, u, t);
+ mpz_sub (r, r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_addmul (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mpz_t t;
+ mpz_init (t);
+ mpz_mul (t, u, v);
+ mpz_add (r, r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_submul (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mpz_t t;
+ mpz_init (t);
+ mpz_mul (t, u, v);
+ mpz_sub (r, r, t);
+ mpz_clear (t);
+}
+
+
+/* MPZ division */
+enum mpz_div_round_mode { GMP_DIV_FLOOR, GMP_DIV_CEIL, GMP_DIV_TRUNC };
+
+/* Allows q or r to be zero. Returns 1 iff remainder is non-zero. */
+static int
+mpz_div_qr (mpz_t q, mpz_t r,
+ const mpz_t n, const mpz_t d, enum mpz_div_round_mode mode)
+{
+ mp_size_t ns, ds, nn, dn, qs;
+ ns = n->_mp_size;
+ ds = d->_mp_size;
+
+ if (ds == 0)
+ gmp_die("mpz_div_qr: Divide by zero.");
+
+ if (ns == 0)
+ {
+ if (q)
+ q->_mp_size = 0;
+ if (r)
+ r->_mp_size = 0;
+ return 0;
+ }
+
+ nn = GMP_ABS (ns);
+ dn = GMP_ABS (ds);
+
+ qs = ds ^ ns;
+
+ if (nn < dn)
+ {
+ if (mode == GMP_DIV_CEIL && qs >= 0)
+ {
+ /* q = 1, r = n - d */
+ if (r)
+ mpz_sub (r, n, d);
+ if (q)
+ mpz_set_ui (q, 1);
+ }
+ else if (mode == GMP_DIV_FLOOR && qs < 0)
+ {
+ /* q = -1, r = n + d */
+ if (r)
+ mpz_add (r, n, d);
+ if (q)
+ mpz_set_si (q, -1);
+ }
+ else
+ {
+ /* q = 0, r = d */
+ if (r)
+ mpz_set (r, n);
+ if (q)
+ q->_mp_size = 0;
+ }
+ return 1;
+ }
+ else
+ {
+ mp_ptr np, qp;
+ mp_size_t qn, rn;
+ mpz_t tq, tr;
+
+ mpz_init_set (tr, n);
+ np = tr->_mp_d;
+
+ qn = nn - dn + 1;
+
+ if (q)
+ {
+ mpz_init2 (tq, qn * GMP_LIMB_BITS);
+ qp = tq->_mp_d;
+ }
+ else
+ qp = NULL;
+
+ mpn_div_qr (qp, np, nn, d->_mp_d, dn);
+
+ if (qp)
+ {
+ qn -= (qp[qn-1] == 0);
+
+ tq->_mp_size = qs < 0 ? -qn : qn;
+ }
+ rn = mpn_normalized_size (np, dn);
+ tr->_mp_size = ns < 0 ? - rn : rn;
+
+ if (mode == GMP_DIV_FLOOR && qs < 0 && rn != 0)
+ {
+ if (q)
+ mpz_sub_ui (tq, tq, 1);
+ if (r)
+ mpz_add (tr, tr, d);
+ }
+ else if (mode == GMP_DIV_CEIL && qs >= 0 && rn != 0)
+ {
+ if (q)
+ mpz_add_ui (tq, tq, 1);
+ if (r)
+ mpz_sub (tr, tr, d);
+ }
+
+ if (q)
+ {
+ mpz_swap (tq, q);
+ mpz_clear (tq);
+ }
+ if (r)
+ mpz_swap (tr, r);
+
+ mpz_clear (tr);
+
+ return rn != 0;
+ }
+}
+
+void
+mpz_cdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, r, n, d, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, r, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, r, n, d, GMP_DIV_TRUNC);
+}
+
+void
+mpz_cdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, NULL, n, d, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, NULL, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC);
+}
+
+void
+mpz_cdiv_r (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_r (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_r (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, GMP_DIV_TRUNC);
+}
+
+void
+mpz_mod (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, d->_mp_size >= 0 ? GMP_DIV_FLOOR : GMP_DIV_CEIL);
+}
+
+static void
+mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index,
+ enum mpz_div_round_mode mode)
+{
+ mp_size_t un, qn;
+ mp_size_t limb_cnt;
+ mp_ptr qp;
+ int adjust;
+
+ un = u->_mp_size;
+ if (un == 0)
+ {
+ q->_mp_size = 0;
+ return;
+ }
+ limb_cnt = bit_index / GMP_LIMB_BITS;
+ qn = GMP_ABS (un) - limb_cnt;
+ bit_index %= GMP_LIMB_BITS;
+
+ if (mode == ((un > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* un != 0 here. */
+ /* Note: Below, the final indexing at limb_cnt is valid because at
+ that point we have qn > 0. */
+ adjust = (qn <= 0
+ || !mpn_zero_p (u->_mp_d, limb_cnt)
+ || (u->_mp_d[limb_cnt]
+ & (((mp_limb_t) 1 << bit_index) - 1)));
+ else
+ adjust = 0;
+
+ if (qn <= 0)
+ qn = 0;
+ else
+ {
+ qp = MPZ_REALLOC (q, qn);
+
+ if (bit_index != 0)
+ {
+ mpn_rshift (qp, u->_mp_d + limb_cnt, qn, bit_index);
+ qn -= qp[qn - 1] == 0;
+ }
+ else
+ {
+ mpn_copyi (qp, u->_mp_d + limb_cnt, qn);
+ }
+ }
+
+ q->_mp_size = qn;
+
+ if (adjust)
+ mpz_add_ui (q, q, 1);
+ if (un < 0)
+ mpz_neg (q, q);
+}
+
+static void
+mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index,
+ enum mpz_div_round_mode mode)
+{
+ mp_size_t us, un, rn;
+ mp_ptr rp;
+ mp_limb_t mask;
+
+ us = u->_mp_size;
+ if (us == 0 || bit_index == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+ rn = (bit_index + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ assert (rn > 0);
+
+ rp = MPZ_REALLOC (r, rn);
+ un = GMP_ABS (us);
+
+ mask = GMP_LIMB_MAX >> (rn * GMP_LIMB_BITS - bit_index);
+
+ if (rn > un)
+ {
+ /* Quotient (with truncation) is zero, and remainder is
+ non-zero */
+ if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
+ {
+ /* Have to negate and sign extend. */
+ mp_size_t i;
+
+ gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un));
+ for (i = un; i < rn - 1; i++)
+ rp[i] = GMP_LIMB_MAX;
+
+ rp[rn-1] = mask;
+ us = -us;
+ }
+ else
+ {
+ /* Just copy */
+ if (r != u)
+ mpn_copyi (rp, u->_mp_d, un);
+
+ rn = un;
+ }
+ }
+ else
+ {
+ if (r != u)
+ mpn_copyi (rp, u->_mp_d, rn - 1);
+
+ rp[rn-1] = u->_mp_d[rn-1] & mask;
+
+ if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
+ {
+ /* If r != 0, compute 2^{bit_count} - r. */
+ mpn_neg (rp, rp, rn);
+
+ rp[rn-1] &= mask;
+
+ /* us is not used for anything else, so we can modify it
+ here to indicate flipped sign. */
+ us = -us;
+ }
+ }
+ rn = mpn_normalized_size (rp, rn);
+ r->_mp_size = us < 0 ? -rn : rn;
+}
+
+void
+mpz_cdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_q_2exp (r, u, cnt, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_q_2exp (r, u, cnt, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_q_2exp (r, u, cnt, GMP_DIV_TRUNC);
+}
+
+void
+mpz_cdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_r_2exp (r, u, cnt, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_r_2exp (r, u, cnt, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_r_2exp (r, u, cnt, GMP_DIV_TRUNC);
+}
+
+void
+mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ gmp_assert_nocarry (mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC));
+}
+
+int
+mpz_divisible_p (const mpz_t n, const mpz_t d)
+{
+ return mpz_div_qr (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0;
+}
+
+int
+mpz_congruent_p (const mpz_t a, const mpz_t b, const mpz_t m)
+{
+ mpz_t t;
+ int res;
+
+ /* a == b (mod 0) iff a == b */
+ if (mpz_sgn (m) == 0)
+ return (mpz_cmp (a, b) == 0);
+
+ mpz_init (t);
+ mpz_sub (t, a, b);
+ res = mpz_divisible_p (t, m);
+ mpz_clear (t);
+
+ return res;
+}
+
+static unsigned long
+mpz_div_qr_ui (mpz_t q, mpz_t r,
+ const mpz_t n, unsigned long d, enum mpz_div_round_mode mode)
+{
+ unsigned long ret;
+ mpz_t rr, dd;
+
+ mpz_init (rr);
+ mpz_init_set_ui (dd, d);
+ mpz_div_qr (q, rr, n, dd, mode);
+ mpz_clear (dd);
+ ret = mpz_get_ui (rr);
+
+ if (r)
+ mpz_swap (r, rr);
+ mpz_clear (rr);
+
+ return ret;
+}
+
+unsigned long
+mpz_cdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_CEIL);
+}
+
+unsigned long
+mpz_fdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_FLOOR);
+}
+
+unsigned long
+mpz_tdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_cdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_CEIL);
+}
+
+unsigned long
+mpz_fdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_FLOOR);
+}
+
+unsigned long
+mpz_tdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_cdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_CEIL);
+}
+unsigned long
+mpz_fdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR);
+}
+unsigned long
+mpz_tdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_cdiv_ui (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_CEIL);
+}
+
+unsigned long
+mpz_fdiv_ui (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_FLOOR);
+}
+
+unsigned long
+mpz_tdiv_ui (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_mod_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_divexact_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ gmp_assert_nocarry (mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC));
+}
+
+int
+mpz_divisible_ui_p (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0;
+}
+
+
+/* GCD */
+static mp_limb_t
+mpn_gcd_11 (mp_limb_t u, mp_limb_t v)
+{
+ unsigned shift;
+
+ assert ( (u | v) > 0);
+
+ if (u == 0)
+ return v;
+ else if (v == 0)
+ return u;
+
+ gmp_ctz (shift, u | v);
+
+ u >>= shift;
+ v >>= shift;
+
+ if ( (u & 1) == 0)
+ MP_LIMB_T_SWAP (u, v);
+
+ while ( (v & 1) == 0)
+ v >>= 1;
+
+ while (u != v)
+ {
+ if (u > v)
+ {
+ u -= v;
+ do
+ u >>= 1;
+ while ( (u & 1) == 0);
+ }
+ else
+ {
+ v -= u;
+ do
+ v >>= 1;
+ while ( (v & 1) == 0);
+ }
+ }
+ return u << shift;
+}
+
+unsigned long
+mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v)
+{
+ mpz_t t;
+ mpz_init_set_ui(t, v);
+ mpz_gcd (t, u, t);
+ if (v > 0)
+ v = mpz_get_ui (t);
+
+ if (g)
+ mpz_swap (t, g);
+
+ mpz_clear (t);
+
+ return v;
+}
+
+static mp_bitcnt_t
+mpz_make_odd (mpz_t r)
+{
+ mp_bitcnt_t shift;
+
+ assert (r->_mp_size > 0);
+ /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
+ shift = mpn_scan1 (r->_mp_d, 0);
+ mpz_tdiv_q_2exp (r, r, shift);
+
+ return shift;
+}
+
+void
+mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v)
+{
+ mpz_t tu, tv;
+ mp_bitcnt_t uz, vz, gz;
+
+ if (u->_mp_size == 0)
+ {
+ mpz_abs (g, v);
+ return;
+ }
+ if (v->_mp_size == 0)
+ {
+ mpz_abs (g, u);
+ return;
+ }
+
+ mpz_init (tu);
+ mpz_init (tv);
+
+ mpz_abs (tu, u);
+ uz = mpz_make_odd (tu);
+ mpz_abs (tv, v);
+ vz = mpz_make_odd (tv);
+ gz = GMP_MIN (uz, vz);
+
+ if (tu->_mp_size < tv->_mp_size)
+ mpz_swap (tu, tv);
+
+ mpz_tdiv_r (tu, tu, tv);
+ if (tu->_mp_size == 0)
+ {
+ mpz_swap (g, tv);
+ }
+ else
+ for (;;)
+ {
+ int c;
+
+ mpz_make_odd (tu);
+ c = mpz_cmp (tu, tv);
+ if (c == 0)
+ {
+ mpz_swap (g, tu);
+ break;
+ }
+ if (c < 0)
+ mpz_swap (tu, tv);
+
+ if (tv->_mp_size == 1)
+ {
+ mp_limb_t *gp;
+
+ mpz_tdiv_r (tu, tu, tv);
+ gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */
+ *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]);
+
+ g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */
+ break;
+ }
+ mpz_sub (tu, tu, tv);
+ }
+ mpz_clear (tu);
+ mpz_clear (tv);
+ mpz_mul_2exp (g, g, gz);
+}
+
+void
+mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v)
+{
+ mpz_t tu, tv, s0, s1, t0, t1;
+ mp_bitcnt_t uz, vz, gz;
+ mp_bitcnt_t power;
+
+ if (u->_mp_size == 0)
+ {
+ /* g = 0 u + sgn(v) v */
+ signed long sign = mpz_sgn (v);
+ mpz_abs (g, v);
+ if (s)
+ s->_mp_size = 0;
+ if (t)
+ mpz_set_si (t, sign);
+ return;
+ }
+
+ if (v->_mp_size == 0)
+ {
+ /* g = sgn(u) u + 0 v */
+ signed long sign = mpz_sgn (u);
+ mpz_abs (g, u);
+ if (s)
+ mpz_set_si (s, sign);
+ if (t)
+ t->_mp_size = 0;
+ return;
+ }
+
+ mpz_init (tu);
+ mpz_init (tv);
+ mpz_init (s0);
+ mpz_init (s1);
+ mpz_init (t0);
+ mpz_init (t1);
+
+ mpz_abs (tu, u);
+ uz = mpz_make_odd (tu);
+ mpz_abs (tv, v);
+ vz = mpz_make_odd (tv);
+ gz = GMP_MIN (uz, vz);
+
+ uz -= gz;
+ vz -= gz;
+
+ /* Cofactors corresponding to odd gcd. gz handled later. */
+ if (tu->_mp_size < tv->_mp_size)
+ {
+ mpz_swap (tu, tv);
+ MPZ_SRCPTR_SWAP (u, v);
+ MPZ_PTR_SWAP (s, t);
+ MP_BITCNT_T_SWAP (uz, vz);
+ }
+
+ /* Maintain
+ *
+ * u = t0 tu + t1 tv
+ * v = s0 tu + s1 tv
+ *
+ * where u and v denote the inputs with common factors of two
+ * eliminated, and det (s0, t0; s1, t1) = 2^p. Then
+ *
+ * 2^p tu = s1 u - t1 v
+ * 2^p tv = -s0 u + t0 v
+ */
+
+ /* After initial division, tu = q tv + tu', we have
+ *
+ * u = 2^uz (tu' + q tv)
+ * v = 2^vz tv
+ *
+ * or
+ *
+ * t0 = 2^uz, t1 = 2^uz q
+ * s0 = 0, s1 = 2^vz
+ */
+
+ mpz_tdiv_qr (t1, tu, tu, tv);
+ mpz_mul_2exp (t1, t1, uz);
+
+ mpz_setbit (s1, vz);
+ power = uz + vz;
+
+ if (tu->_mp_size > 0)
+ {
+ mp_bitcnt_t shift;
+ shift = mpz_make_odd (tu);
+ mpz_setbit (t0, uz + shift);
+ power += shift;
+
+ for (;;)
+ {
+ int c;
+ c = mpz_cmp (tu, tv);
+ if (c == 0)
+ break;
+
+ if (c < 0)
+ {
+ /* tv = tv' + tu
+ *
+ * u = t0 tu + t1 (tv' + tu) = (t0 + t1) tu + t1 tv'
+ * v = s0 tu + s1 (tv' + tu) = (s0 + s1) tu + s1 tv' */
+
+ mpz_sub (tv, tv, tu);
+ mpz_add (t0, t0, t1);
+ mpz_add (s0, s0, s1);
+
+ shift = mpz_make_odd (tv);
+ mpz_mul_2exp (t1, t1, shift);
+ mpz_mul_2exp (s1, s1, shift);
+ }
+ else
+ {
+ mpz_sub (tu, tu, tv);
+ mpz_add (t1, t0, t1);
+ mpz_add (s1, s0, s1);
+
+ shift = mpz_make_odd (tu);
+ mpz_mul_2exp (t0, t0, shift);
+ mpz_mul_2exp (s0, s0, shift);
+ }
+ power += shift;
+ }
+ }
+ else
+ mpz_setbit (t0, uz);
+
+ /* Now tv = odd part of gcd, and -s0 and t0 are corresponding
+ cofactors. */
+
+ mpz_mul_2exp (tv, tv, gz);
+ mpz_neg (s0, s0);
+
+ /* 2^p g = s0 u + t0 v. Eliminate one factor of two at a time. To
+ adjust cofactors, we need u / g and v / g */
+
+ mpz_divexact (s1, v, tv);
+ mpz_abs (s1, s1);
+ mpz_divexact (t1, u, tv);
+ mpz_abs (t1, t1);
+
+ while (power-- > 0)
+ {
+ /* s0 u + t0 v = (s0 - v/g) u - (t0 + u/g) v */
+ if (mpz_odd_p (s0) || mpz_odd_p (t0))
+ {
+ mpz_sub (s0, s0, s1);
+ mpz_add (t0, t0, t1);
+ }
+ assert (mpz_even_p (t0) && mpz_even_p (s0));
+ mpz_tdiv_q_2exp (s0, s0, 1);
+ mpz_tdiv_q_2exp (t0, t0, 1);
+ }
+
+ /* Arrange so that |s| < |u| / 2g */
+ mpz_add (s1, s0, s1);
+ if (mpz_cmpabs (s0, s1) > 0)
+ {
+ mpz_swap (s0, s1);
+ mpz_sub (t0, t0, t1);
+ }
+ if (u->_mp_size < 0)
+ mpz_neg (s0, s0);
+ if (v->_mp_size < 0)
+ mpz_neg (t0, t0);
+
+ mpz_swap (g, tv);
+ if (s)
+ mpz_swap (s, s0);
+ if (t)
+ mpz_swap (t, t0);
+
+ mpz_clear (tu);
+ mpz_clear (tv);
+ mpz_clear (s0);
+ mpz_clear (s1);
+ mpz_clear (t0);
+ mpz_clear (t1);
+}
+
+void
+mpz_lcm (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mpz_t g;
+
+ if (u->_mp_size == 0 || v->_mp_size == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ mpz_init (g);
+
+ mpz_gcd (g, u, v);
+ mpz_divexact (g, u, g);
+ mpz_mul (r, g, v);
+
+ mpz_clear (g);
+ mpz_abs (r, r);
+}
+
+void
+mpz_lcm_ui (mpz_t r, const mpz_t u, unsigned long v)
+{
+ if (v == 0 || u->_mp_size == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ v /= mpz_gcd_ui (NULL, u, v);
+ mpz_mul_ui (r, u, v);
+
+ mpz_abs (r, r);
+}
+
+int
+mpz_invert (mpz_t r, const mpz_t u, const mpz_t m)
+{
+ mpz_t g, tr;
+ int invertible;
+
+ if (u->_mp_size == 0 || mpz_cmpabs_ui (m, 1) <= 0)
+ return 0;
+
+ mpz_init (g);
+ mpz_init (tr);
+
+ mpz_gcdext (g, tr, NULL, u, m);
+ invertible = (mpz_cmp_ui (g, 1) == 0);
+
+ if (invertible)
+ {
+ if (tr->_mp_size < 0)
+ {
+ if (m->_mp_size >= 0)
+ mpz_add (tr, tr, m);
+ else
+ mpz_sub (tr, tr, m);
+ }
+ mpz_swap (r, tr);
+ }
+
+ mpz_clear (g);
+ mpz_clear (tr);
+ return invertible;
+}
+
+
+/* Higher level operations (sqrt, pow and root) */
+
+void
+mpz_pow_ui (mpz_t r, const mpz_t b, unsigned long e)
+{
+ unsigned long bit;
+ mpz_t tr;
+ mpz_init_set_ui (tr, 1);
+
+ bit = GMP_ULONG_HIGHBIT;
+ do
+ {
+ mpz_mul (tr, tr, tr);
+ if (e & bit)
+ mpz_mul (tr, tr, b);
+ bit >>= 1;
+ }
+ while (bit > 0);
+
+ mpz_swap (r, tr);
+ mpz_clear (tr);
+}
+
+void
+mpz_ui_pow_ui (mpz_t r, unsigned long blimb, unsigned long e)
+{
+ mpz_t b;
+
+ mpz_init_set_ui (b, blimb);
+ mpz_pow_ui (r, b, e);
+ mpz_clear (b);
+}
+
+void
+mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
+{
+ mpz_t tr;
+ mpz_t base;
+ mp_size_t en, mn;
+ mp_srcptr mp;
+ struct gmp_div_inverse minv;
+ unsigned shift;
+ mp_ptr tp = NULL;
+
+ en = GMP_ABS (e->_mp_size);
+ mn = GMP_ABS (m->_mp_size);
+ if (mn == 0)
+ gmp_die ("mpz_powm: Zero modulo.");
+
+ if (en == 0)
+ {
+ mpz_set_ui (r, mpz_cmpabs_ui (m, 1));
+ return;
+ }
+
+ mp = m->_mp_d;
+ mpn_div_qr_invert (&minv, mp, mn);
+ shift = minv.shift;
+
+ if (shift > 0)
+ {
+ /* To avoid shifts, we do all our reductions, except the final
+ one, using a *normalized* m. */
+ minv.shift = 0;
+
+ tp = gmp_alloc_limbs (mn);
+ gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift));
+ mp = tp;
+ }
+
+ mpz_init (base);
+
+ if (e->_mp_size < 0)
+ {
+ if (!mpz_invert (base, b, m))
+ gmp_die ("mpz_powm: Negative exponent and non-invertible base.");
+ }
+ else
+ {
+ mp_size_t bn;
+ mpz_abs (base, b);
+
+ bn = base->_mp_size;
+ if (bn >= mn)
+ {
+ mpn_div_qr_preinv (NULL, base->_mp_d, base->_mp_size, mp, mn, &minv);
+ bn = mn;
+ }
+
+ /* We have reduced the absolute value. Now take care of the
+ sign. Note that we get zero represented non-canonically as
+ m. */
+ if (b->_mp_size < 0)
+ {
+ mp_ptr bp = MPZ_REALLOC (base, mn);
+ gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn));
+ bn = mn;
+ }
+ base->_mp_size = mpn_normalized_size (base->_mp_d, bn);
+ }
+ mpz_init_set_ui (tr, 1);
+
+ while (--en >= 0)
+ {
+ mp_limb_t w = e->_mp_d[en];
+ mp_limb_t bit;
+
+ bit = GMP_LIMB_HIGHBIT;
+ do
+ {
+ mpz_mul (tr, tr, tr);
+ if (w & bit)
+ mpz_mul (tr, tr, base);
+ if (tr->_mp_size > mn)
+ {
+ mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
+ tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
+ }
+ bit >>= 1;
+ }
+ while (bit > 0);
+ }
+
+ /* Final reduction */
+ if (tr->_mp_size >= mn)
+ {
+ minv.shift = shift;
+ mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
+ tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
+ }
+ if (tp)
+ gmp_free_limbs (tp, mn);
+
+ mpz_swap (r, tr);
+ mpz_clear (tr);
+ mpz_clear (base);
+}
+
+void
+mpz_powm_ui (mpz_t r, const mpz_t b, unsigned long elimb, const mpz_t m)
+{
+ mpz_t e;
+
+ mpz_init_set_ui (e, elimb);
+ mpz_powm (r, b, e, m);
+ mpz_clear (e);
+}
+
+/* x=trunc(y^(1/z)), r=y-x^z */
+void
+mpz_rootrem (mpz_t x, mpz_t r, const mpz_t y, unsigned long z)
+{
+ int sgn;
+ mp_bitcnt_t bc;
+ mpz_t t, u;
+
+ sgn = y->_mp_size < 0;
+ if ((~z & sgn) != 0)
+ gmp_die ("mpz_rootrem: Negative argument, with even root.");
+ if (z == 0)
+ gmp_die ("mpz_rootrem: Zeroth root.");
+
+ if (mpz_cmpabs_ui (y, 1) <= 0) {
+ if (x)
+ mpz_set (x, y);
+ if (r)
+ r->_mp_size = 0;
+ return;
+ }
+
+ mpz_init (u);
+ mpz_init (t);
+ bc = (mpz_sizeinbase (y, 2) - 1) / z + 1;
+ mpz_setbit (t, bc);
+
+ if (z == 2) /* simplify sqrt loop: z-1 == 1 */
+ do {
+ mpz_swap (u, t); /* u = x */
+ mpz_tdiv_q (t, y, u); /* t = y/x */
+ mpz_add (t, t, u); /* t = y/x + x */
+ mpz_tdiv_q_2exp (t, t, 1); /* x'= (y/x + x)/2 */
+ } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */
+ else /* z != 2 */ {
+ mpz_t v;
+
+ mpz_init (v);
+ if (sgn)
+ mpz_neg (t, t);
+
+ do {
+ mpz_swap (u, t); /* u = x */
+ mpz_pow_ui (t, u, z - 1); /* t = x^(z-1) */
+ mpz_tdiv_q (t, y, t); /* t = y/x^(z-1) */
+ mpz_mul_ui (v, u, z - 1); /* v = x*(z-1) */
+ mpz_add (t, t, v); /* t = y/x^(z-1) + x*(z-1) */
+ mpz_tdiv_q_ui (t, t, z); /* x'=(y/x^(z-1) + x*(z-1))/z */
+ } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */
+
+ mpz_clear (v);
+ }
+
+ if (r) {
+ mpz_pow_ui (t, u, z);
+ mpz_sub (r, y, t);
+ }
+ if (x)
+ mpz_swap (x, u);
+ mpz_clear (u);
+ mpz_clear (t);
+}
+
+int
+mpz_root (mpz_t x, const mpz_t y, unsigned long z)
+{
+ int res;
+ mpz_t r;
+
+ mpz_init (r);
+ mpz_rootrem (x, r, y, z);
+ res = r->_mp_size == 0;
+ mpz_clear (r);
+
+ return res;
+}
+
+/* Compute s = floor(sqrt(u)) and r = u - s^2. Allows r == NULL */
+void
+mpz_sqrtrem (mpz_t s, mpz_t r, const mpz_t u)
+{
+ mpz_rootrem (s, r, u, 2);
+}
+
+void
+mpz_sqrt (mpz_t s, const mpz_t u)
+{
+ mpz_rootrem (s, NULL, u, 2);
+}
+
+int
+mpz_perfect_square_p (const mpz_t u)
+{
+ if (u->_mp_size <= 0)
+ return (u->_mp_size == 0);
+ else
+ return mpz_root (NULL, u, 2);
+}
+
+int
+mpn_perfect_square_p (mp_srcptr p, mp_size_t n)
+{
+ mpz_t t;
+
+ assert (n > 0);
+ assert (p [n-1] != 0);
+ return mpz_root (NULL, mpz_roinit_normal_n (t, p, n), 2);
+}
+
+mp_size_t
+mpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr p, mp_size_t n)
+{
+ mpz_t s, r, u;
+ mp_size_t res;
+
+ assert (n > 0);
+ assert (p [n-1] != 0);
+
+ mpz_init (r);
+ mpz_init (s);
+ mpz_rootrem (s, r, mpz_roinit_normal_n (u, p, n), 2);
+
+ assert (s->_mp_size == (n+1)/2);
+ mpn_copyd (sp, s->_mp_d, s->_mp_size);
+ mpz_clear (s);
+ res = r->_mp_size;
+ if (rp)
+ mpn_copyd (rp, r->_mp_d, res);
+ mpz_clear (r);
+ return res;
+}
+
+/* Combinatorics */
+
+void
+mpz_mfac_uiui (mpz_t x, unsigned long n, unsigned long m)
+{
+ mpz_set_ui (x, n + (n == 0));
+ if (m + 1 < 2) return;
+ while (n > m + 1)
+ mpz_mul_ui (x, x, n -= m);
+}
+
+void
+mpz_2fac_ui (mpz_t x, unsigned long n)
+{
+ mpz_mfac_uiui (x, n, 2);
+}
+
+void
+mpz_fac_ui (mpz_t x, unsigned long n)
+{
+ mpz_mfac_uiui (x, n, 1);
+}
+
+void
+mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k)
+{
+ mpz_t t;
+
+ mpz_set_ui (r, k <= n);
+
+ if (k > (n >> 1))
+ k = (k <= n) ? n - k : 0;
+
+ mpz_init (t);
+ mpz_fac_ui (t, k);
+
+ for (; k > 0; --k)
+ mpz_mul_ui (r, r, n--);
+
+ mpz_divexact (r, r, t);
+ mpz_clear (t);
+}
+
+
+/* Primality testing */
+
+/* Computes Kronecker (a/b) with odd b, a!=0 and GCD(a,b) = 1 */
+/* Adapted from JACOBI_BASE_METHOD==4 in mpn/generic/jacbase.c */
+static int
+gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
+{
+ int c, bit = 0;
+
+ assert (b & 1);
+ assert (a != 0);
+ /* assert (mpn_gcd_11 (a, b) == 1); */
+
+ /* Below, we represent a and b shifted right so that the least
+ significant one bit is implicit. */
+ b >>= 1;
+
+ gmp_ctz(c, a);
+ a >>= 1;
+
+ for (;;)
+ {
+ a >>= c;
+ /* (2/b) = -1 if b = 3 or 5 mod 8 */
+ bit ^= c & (b ^ (b >> 1));
+ if (a < b)
+ {
+ if (a == 0)
+ return bit & 1 ? -1 : 1;
+ bit ^= a & b;
+ a = b - a;
+ b -= a;
+ }
+ else
+ {
+ a -= b;
+ assert (a != 0);
+ }
+
+ gmp_ctz(c, a);
+ ++c;
+ }
+}
+
+static void
+gmp_lucas_step_k_2k (mpz_t V, mpz_t Qk, const mpz_t n)
+{
+ mpz_mod (Qk, Qk, n);
+ /* V_{2k} <- V_k ^ 2 - 2Q^k */
+ mpz_mul (V, V, V);
+ mpz_submul_ui (V, Qk, 2);
+ mpz_tdiv_r (V, V, n);
+ /* Q^{2k} = (Q^k)^2 */
+ mpz_mul (Qk, Qk, Qk);
+}
+
+/* Computes V_k, Q^k (mod n) for the Lucas' sequence */
+/* with P=1, Q=Q; k = (n>>b0)|1. */
+/* Requires an odd n > 4; b0 > 0; -2*Q must not overflow a long */
+/* Returns (U_k == 0) and sets V=V_k and Qk=Q^k. */
+static int
+gmp_lucas_mod (mpz_t V, mpz_t Qk, long Q,
+ mp_bitcnt_t b0, const mpz_t n)
+{
+ mp_bitcnt_t bs;
+ mpz_t U;
+ int res;
+
+ assert (b0 > 0);
+ assert (Q <= - (LONG_MIN / 2));
+ assert (Q >= - (LONG_MAX / 2));
+ assert (mpz_cmp_ui (n, 4) > 0);
+ assert (mpz_odd_p (n));
+
+ mpz_init_set_ui (U, 1); /* U1 = 1 */
+ mpz_set_ui (V, 1); /* V1 = 1 */
+ mpz_set_si (Qk, Q);
+
+ for (bs = mpz_sizeinbase (n, 2) - 1; --bs >= b0;)
+ {
+ /* U_{2k} <- U_k * V_k */
+ mpz_mul (U, U, V);
+ /* V_{2k} <- V_k ^ 2 - 2Q^k */
+ /* Q^{2k} = (Q^k)^2 */
+ gmp_lucas_step_k_2k (V, Qk, n);
+
+ /* A step k->k+1 is performed if the bit in $n$ is 1 */
+ /* mpz_tstbit(n,bs) or the bit is 0 in $n$ but */
+ /* should be 1 in $n+1$ (bs == b0) */
+ if (b0 == bs || mpz_tstbit (n, bs))
+ {
+ /* Q^{k+1} <- Q^k * Q */
+ mpz_mul_si (Qk, Qk, Q);
+ /* U_{k+1} <- (U_k + V_k) / 2 */
+ mpz_swap (U, V); /* Keep in V the old value of U_k */
+ mpz_add (U, U, V);
+ /* We have to compute U/2, so we need an even value, */
+ /* equivalent (mod n) */
+ if (mpz_odd_p (U))
+ mpz_add (U, U, n);
+ mpz_tdiv_q_2exp (U, U, 1);
+ /* V_{k+1} <-(D*U_k + V_k) / 2 =
+ U_{k+1} + (D-1)/2*U_k = U_{k+1} - 2Q*U_k */
+ mpz_mul_si (V, V, -2*Q);
+ mpz_add (V, U, V);
+ mpz_tdiv_r (V, V, n);
+ }
+ mpz_tdiv_r (U, U, n);
+ }
+
+ res = U->_mp_size == 0;
+ mpz_clear (U);
+ return res;
+}
+
+/* Performs strong Lucas' test on x, with parameters suggested */
+/* for the BPSW test. Qk is only passed to recycle a variable. */
+/* Requires GCD (x,6) = 1.*/
+static int
+gmp_stronglucas (const mpz_t x, mpz_t Qk)
+{
+ mp_bitcnt_t b0;
+ mpz_t V, n;
+ mp_limb_t maxD, D; /* The absolute value is stored. */
+ long Q;
+ mp_limb_t tl;
+
+ /* Test on the absolute value. */
+ mpz_roinit_normal_n (n, x->_mp_d, GMP_ABS (x->_mp_size));
+
+ assert (mpz_odd_p (n));
+ /* assert (mpz_gcd_ui (NULL, n, 6) == 1); */
+ if (mpz_root (Qk, n, 2))
+ return 0; /* A square is composite. */
+
+ /* Check Ds up to square root (in case, n is prime)
+ or avoid overflows */
+ maxD = (Qk->_mp_size == 1) ? Qk->_mp_d [0] - 1 : GMP_LIMB_MAX;
+
+ D = 3;
+ /* Search a D such that (D/n) = -1 in the sequence 5,-7,9,-11,.. */
+ /* For those Ds we have (D/n) = (n/|D|) */
+ do
+ {
+ if (D >= maxD)
+ return 1 + (D != GMP_LIMB_MAX); /* (1 + ! ~ D) */
+ D += 2;
+ tl = mpz_tdiv_ui (n, D);
+ if (tl == 0)
+ return 0;
+ }
+ while (gmp_jacobi_coprime (tl, D) == 1);
+
+ mpz_init (V);
+
+ /* n-(D/n) = n+1 = d*2^{b0}, with d = (n>>b0) | 1 */
+ b0 = mpn_common_scan (~ n->_mp_d[0], 0, n->_mp_d, n->_mp_size, GMP_LIMB_MAX);
+ /* b0 = mpz_scan0 (n, 0); */
+
+ /* D= P^2 - 4Q; P = 1; Q = (1-D)/4 */
+ Q = (D & 2) ? (long) (D >> 2) + 1 : -(long) (D >> 2);
+
+ if (! gmp_lucas_mod (V, Qk, Q, b0, n)) /* If Ud != 0 */
+ while (V->_mp_size != 0 && --b0 != 0) /* while Vk != 0 */
+ /* V <- V ^ 2 - 2Q^k */
+ /* Q^{2k} = (Q^k)^2 */
+ gmp_lucas_step_k_2k (V, Qk, n);
+
+ mpz_clear (V);
+ return (b0 != 0);
+}
+
+static int
+gmp_millerrabin (const mpz_t n, const mpz_t nm1, mpz_t y,
+ const mpz_t q, mp_bitcnt_t k)
+{
+ assert (k > 0);
+
+ /* Caller must initialize y to the base. */
+ mpz_powm (y, y, q, n);
+
+ if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0)
+ return 1;
+
+ while (--k > 0)
+ {
+ mpz_powm_ui (y, y, 2, n);
+ if (mpz_cmp (y, nm1) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* This product is 0xc0cfd797, and fits in 32 bits. */
+#define GMP_PRIME_PRODUCT \
+ (3UL*5UL*7UL*11UL*13UL*17UL*19UL*23UL*29UL)
+
+/* Bit (p+1)/2 is set, for each odd prime <= 61 */
+#define GMP_PRIME_MASK 0xc96996dcUL
+
+int
+mpz_probab_prime_p (const mpz_t n, int reps)
+{
+ mpz_t nm1;
+ mpz_t q;
+ mpz_t y;
+ mp_bitcnt_t k;
+ int is_prime;
+ int j;
+
+ /* Note that we use the absolute value of n only, for compatibility
+ with the real GMP. */
+ if (mpz_even_p (n))
+ return (mpz_cmpabs_ui (n, 2) == 0) ? 2 : 0;
+
+ /* Above test excludes n == 0 */
+ assert (n->_mp_size != 0);
+
+ if (mpz_cmpabs_ui (n, 64) < 0)
+ return (GMP_PRIME_MASK >> (n->_mp_d[0] >> 1)) & 2;
+
+ if (mpz_gcd_ui (NULL, n, GMP_PRIME_PRODUCT) != 1)
+ return 0;
+
+ /* All prime factors are >= 31. */
+ if (mpz_cmpabs_ui (n, 31*31) < 0)
+ return 2;
+
+ mpz_init (nm1);
+ mpz_init (q);
+
+ /* Find q and k, where q is odd and n = 1 + 2**k * q. */
+ mpz_abs (nm1, n);
+ nm1->_mp_d[0] -= 1;
+ /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
+ k = mpn_scan1 (nm1->_mp_d, 0);
+ mpz_tdiv_q_2exp (q, nm1, k);
+
+ /* BPSW test */
+ mpz_init_set_ui (y, 2);
+ is_prime = gmp_millerrabin (n, nm1, y, q, k) && gmp_stronglucas (n, y);
+ reps -= 24; /* skip the first 24 repetitions */
+
+ /* Use Miller-Rabin, with a deterministic sequence of bases, a[j] =
+ j^2 + j + 41 using Euler's polynomial. We potentially stop early,
+ if a[j] >= n - 1. Since n >= 31*31, this can happen only if reps >
+ 30 (a[30] == 971 > 31*31 == 961). */
+
+ for (j = 0; is_prime & (j < reps); j++)
+ {
+ mpz_set_ui (y, (unsigned long) j*j+j+41);
+ if (mpz_cmp (y, nm1) >= 0)
+ {
+ /* Don't try any further bases. This "early" break does not affect
+ the result for any reasonable reps value (<=5000 was tested) */
+ assert (j >= 30);
+ break;
+ }
+ is_prime = gmp_millerrabin (n, nm1, y, q, k);
+ }
+ mpz_clear (nm1);
+ mpz_clear (q);
+ mpz_clear (y);
+
+ return is_prime;
+}
+
+
+/* Logical operations and bit manipulation. */
+
+/* Numbers are treated as if represented in two's complement (and
+ infinitely sign extended). For a negative values we get the two's
+ complement from -x = ~x + 1, where ~ is bitwise complement.
+ Negation transforms
+
+ xxxx10...0
+
+ into
+
+ yyyy10...0
+
+ where yyyy is the bitwise complement of xxxx. So least significant
+ bits, up to and including the first one bit, are unchanged, and
+ the more significant bits are all complemented.
+
+ To change a bit from zero to one in a negative number, subtract the
+ corresponding power of two from the absolute value. This can never
+ underflow. To change a bit from one to zero, add the corresponding
+ power of two, and this might overflow. E.g., if x = -001111, the
+ two's complement is 110001. Clearing the least significant bit, we
+ get two's complement 110000, and -010000. */
+
+int
+mpz_tstbit (const mpz_t d, mp_bitcnt_t bit_index)
+{
+ mp_size_t limb_index;
+ unsigned shift;
+ mp_size_t ds;
+ mp_size_t dn;
+ mp_limb_t w;
+ int bit;
+
+ ds = d->_mp_size;
+ dn = GMP_ABS (ds);
+ limb_index = bit_index / GMP_LIMB_BITS;
+ if (limb_index >= dn)
+ return ds < 0;
+
+ shift = bit_index % GMP_LIMB_BITS;
+ w = d->_mp_d[limb_index];
+ bit = (w >> shift) & 1;
+
+ if (ds < 0)
+ {
+ /* d < 0. Check if any of the bits below is set: If so, our bit
+ must be complemented. */
+ if (shift > 0 && (mp_limb_t) (w << (GMP_LIMB_BITS - shift)) > 0)
+ return bit ^ 1;
+ while (--limb_index >= 0)
+ if (d->_mp_d[limb_index] > 0)
+ return bit ^ 1;
+ }
+ return bit;
+}
+
+static void
+mpz_abs_add_bit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ mp_size_t dn, limb_index;
+ mp_limb_t bit;
+ mp_ptr dp;
+
+ dn = GMP_ABS (d->_mp_size);
+
+ limb_index = bit_index / GMP_LIMB_BITS;
+ bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS);
+
+ if (limb_index >= dn)
+ {
+ mp_size_t i;
+ /* The bit should be set outside of the end of the number.
+ We have to increase the size of the number. */
+ dp = MPZ_REALLOC (d, limb_index + 1);
+
+ dp[limb_index] = bit;
+ for (i = dn; i < limb_index; i++)
+ dp[i] = 0;
+ dn = limb_index + 1;
+ }
+ else
+ {
+ mp_limb_t cy;
+
+ dp = d->_mp_d;
+
+ cy = mpn_add_1 (dp + limb_index, dp + limb_index, dn - limb_index, bit);
+ if (cy > 0)
+ {
+ dp = MPZ_REALLOC (d, dn + 1);
+ dp[dn++] = cy;
+ }
+ }
+
+ d->_mp_size = (d->_mp_size < 0) ? - dn : dn;
+}
+
+static void
+mpz_abs_sub_bit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ mp_size_t dn, limb_index;
+ mp_ptr dp;
+ mp_limb_t bit;
+
+ dn = GMP_ABS (d->_mp_size);
+ dp = d->_mp_d;
+
+ limb_index = bit_index / GMP_LIMB_BITS;
+ bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS);
+
+ assert (limb_index < dn);
+
+ gmp_assert_nocarry (mpn_sub_1 (dp + limb_index, dp + limb_index,
+ dn - limb_index, bit));
+ dn = mpn_normalized_size (dp, dn);
+ d->_mp_size = (d->_mp_size < 0) ? - dn : dn;
+}
+
+void
+mpz_setbit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ if (!mpz_tstbit (d, bit_index))
+ {
+ if (d->_mp_size >= 0)
+ mpz_abs_add_bit (d, bit_index);
+ else
+ mpz_abs_sub_bit (d, bit_index);
+ }
+}
+
+void
+mpz_clrbit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ if (mpz_tstbit (d, bit_index))
+ {
+ if (d->_mp_size >= 0)
+ mpz_abs_sub_bit (d, bit_index);
+ else
+ mpz_abs_add_bit (d, bit_index);
+ }
+}
+
+void
+mpz_combit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ if (mpz_tstbit (d, bit_index) ^ (d->_mp_size < 0))
+ mpz_abs_sub_bit (d, bit_index);
+ else
+ mpz_abs_add_bit (d, bit_index);
+}
+
+void
+mpz_com (mpz_t r, const mpz_t u)
+{
+ mpz_add_ui (r, u, 1);
+ mpz_neg (r, r);
+}
+
+void
+mpz_and (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, rn, i;
+ mp_ptr up, vp, rp;
+
+ mp_limb_t ux, vx, rx;
+ mp_limb_t uc, vc, rc;
+ mp_limb_t ul, vl, rl;
+
+ un = GMP_ABS (u->_mp_size);
+ vn = GMP_ABS (v->_mp_size);
+ if (un < vn)
+ {
+ MPZ_SRCPTR_SWAP (u, v);
+ MP_SIZE_T_SWAP (un, vn);
+ }
+ if (vn == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ uc = u->_mp_size < 0;
+ vc = v->_mp_size < 0;
+ rc = uc & vc;
+
+ ux = -uc;
+ vx = -vc;
+ rx = -rc;
+
+ /* If the smaller input is positive, higher limbs don't matter. */
+ rn = vx ? un : vn;
+
+ rp = MPZ_REALLOC (r, rn + (mp_size_t) rc);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ i = 0;
+ do
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ vx) + vc;
+ vc = vl < vc;
+
+ rl = ( (ul & vl) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ while (++i < vn);
+ assert (vc == 0);
+
+ for (; i < rn; i++)
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ rl = ( (ul & vx) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ if (rc)
+ rp[rn++] = rc;
+ else
+ rn = mpn_normalized_size (rp, rn);
+
+ r->_mp_size = rx ? -rn : rn;
+}
+
+void
+mpz_ior (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, rn, i;
+ mp_ptr up, vp, rp;
+
+ mp_limb_t ux, vx, rx;
+ mp_limb_t uc, vc, rc;
+ mp_limb_t ul, vl, rl;
+
+ un = GMP_ABS (u->_mp_size);
+ vn = GMP_ABS (v->_mp_size);
+ if (un < vn)
+ {
+ MPZ_SRCPTR_SWAP (u, v);
+ MP_SIZE_T_SWAP (un, vn);
+ }
+ if (vn == 0)
+ {
+ mpz_set (r, u);
+ return;
+ }
+
+ uc = u->_mp_size < 0;
+ vc = v->_mp_size < 0;
+ rc = uc | vc;
+
+ ux = -uc;
+ vx = -vc;
+ rx = -rc;
+
+ /* If the smaller input is negative, by sign extension higher limbs
+ don't matter. */
+ rn = vx ? vn : un;
+
+ rp = MPZ_REALLOC (r, rn + (mp_size_t) rc);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ i = 0;
+ do
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ vx) + vc;
+ vc = vl < vc;
+
+ rl = ( (ul | vl) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ while (++i < vn);
+ assert (vc == 0);
+
+ for (; i < rn; i++)
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ rl = ( (ul | vx) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ if (rc)
+ rp[rn++] = rc;
+ else
+ rn = mpn_normalized_size (rp, rn);
+
+ r->_mp_size = rx ? -rn : rn;
+}
+
+void
+mpz_xor (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, i;
+ mp_ptr up, vp, rp;
+
+ mp_limb_t ux, vx, rx;
+ mp_limb_t uc, vc, rc;
+ mp_limb_t ul, vl, rl;
+
+ un = GMP_ABS (u->_mp_size);
+ vn = GMP_ABS (v->_mp_size);
+ if (un < vn)
+ {
+ MPZ_SRCPTR_SWAP (u, v);
+ MP_SIZE_T_SWAP (un, vn);
+ }
+ if (vn == 0)
+ {
+ mpz_set (r, u);
+ return;
+ }
+
+ uc = u->_mp_size < 0;
+ vc = v->_mp_size < 0;
+ rc = uc ^ vc;
+
+ ux = -uc;
+ vx = -vc;
+ rx = -rc;
+
+ rp = MPZ_REALLOC (r, un + (mp_size_t) rc);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ i = 0;
+ do
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ vx) + vc;
+ vc = vl < vc;
+
+ rl = (ul ^ vl ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ while (++i < vn);
+ assert (vc == 0);
+
+ for (; i < un; i++)
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ rl = (ul ^ ux) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ if (rc)
+ rp[un++] = rc;
+ else
+ un = mpn_normalized_size (rp, un);
+
+ r->_mp_size = rx ? -un : un;
+}
+
+static unsigned
+gmp_popcount_limb (mp_limb_t x)
+{
+ unsigned c;
+
+ /* Do 16 bits at a time, to avoid limb-sized constants. */
+ int LOCAL_SHIFT_BITS = 16;
+ for (c = 0; x > 0;)
+ {
+ unsigned w = x - ((x >> 1) & 0x5555);
+ w = ((w >> 2) & 0x3333) + (w & 0x3333);
+ w = (w >> 4) + w;
+ w = ((w >> 8) & 0x000f) + (w & 0x000f);
+ c += w;
+ if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS)
+ x >>= LOCAL_SHIFT_BITS;
+ else
+ x = 0;
+ }
+ return c;
+}
+
+mp_bitcnt_t
+mpn_popcount (mp_srcptr p, mp_size_t n)
+{
+ mp_size_t i;
+ mp_bitcnt_t c;
+
+ for (c = 0, i = 0; i < n; i++)
+ c += gmp_popcount_limb (p[i]);
+
+ return c;
+}
+
+mp_bitcnt_t
+mpz_popcount (const mpz_t u)
+{
+ mp_size_t un;
+
+ un = u->_mp_size;
+
+ if (un < 0)
+ return ~(mp_bitcnt_t) 0;
+
+ return mpn_popcount (u->_mp_d, un);
+}
+
+mp_bitcnt_t
+mpz_hamdist (const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, i;
+ mp_limb_t uc, vc, ul, vl, comp;
+ mp_srcptr up, vp;
+ mp_bitcnt_t c;
+
+ un = u->_mp_size;
+ vn = v->_mp_size;
+
+ if ( (un ^ vn) < 0)
+ return ~(mp_bitcnt_t) 0;
+
+ comp = - (uc = vc = (un < 0));
+ if (uc)
+ {
+ assert (vn < 0);
+ un = -un;
+ vn = -vn;
+ }
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ if (un < vn)
+ MPN_SRCPTR_SWAP (up, un, vp, vn);
+
+ for (i = 0, c = 0; i < vn; i++)
+ {
+ ul = (up[i] ^ comp) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ comp) + vc;
+ vc = vl < vc;
+
+ c += gmp_popcount_limb (ul ^ vl);
+ }
+ assert (vc == 0);
+
+ for (; i < un; i++)
+ {
+ ul = (up[i] ^ comp) + uc;
+ uc = ul < uc;
+
+ c += gmp_popcount_limb (ul ^ comp);
+ }
+
+ return c;
+}
+
+mp_bitcnt_t
+mpz_scan1 (const mpz_t u, mp_bitcnt_t starting_bit)
+{
+ mp_ptr up;
+ mp_size_t us, un, i;
+ mp_limb_t limb, ux;
+
+ us = u->_mp_size;
+ un = GMP_ABS (us);
+ i = starting_bit / GMP_LIMB_BITS;
+
+ /* Past the end there's no 1 bits for u>=0, or an immediate 1 bit
+ for u<0. Notice this test picks up any u==0 too. */
+ if (i >= un)
+ return (us >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit);
+
+ up = u->_mp_d;
+ ux = 0;
+ limb = up[i];
+
+ if (starting_bit != 0)
+ {
+ if (us < 0)
+ {
+ ux = mpn_zero_p (up, i);
+ limb = ~ limb + ux;
+ ux = - (mp_limb_t) (limb >= ux);
+ }
+
+ /* Mask to 0 all bits before starting_bit, thus ignoring them. */
+ limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS);
+ }
+
+ return mpn_common_scan (limb, i, up, un, ux);
+}
+
+mp_bitcnt_t
+mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit)
+{
+ mp_ptr up;
+ mp_size_t us, un, i;
+ mp_limb_t limb, ux;
+
+ us = u->_mp_size;
+ ux = - (mp_limb_t) (us >= 0);
+ un = GMP_ABS (us);
+ i = starting_bit / GMP_LIMB_BITS;
+
+ /* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for
+ u<0. Notice this test picks up all cases of u==0 too. */
+ if (i >= un)
+ return (ux ? starting_bit : ~(mp_bitcnt_t) 0);
+
+ up = u->_mp_d;
+ limb = up[i] ^ ux;
+
+ if (ux == 0)
+ limb -= mpn_zero_p (up, i); /* limb = ~(~limb + zero_p) */
+
+ /* Mask all bits before starting_bit, thus ignoring them. */
+ limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS);
+
+ return mpn_common_scan (limb, i, up, un, ux);
+}
+
+
+/* MPZ base conversion. */
+
+size_t
+mpz_sizeinbase (const mpz_t u, int base)
+{
+ mp_size_t un, tn;
+ mp_srcptr up;
+ mp_ptr tp;
+ mp_bitcnt_t bits;
+ struct gmp_div_inverse bi;
+ size_t ndigits;
+
+ assert (base >= 2);
+ assert (base <= 62);
+
+ un = GMP_ABS (u->_mp_size);
+ if (un == 0)
+ return 1;
+
+ up = u->_mp_d;
+
+ bits = (un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]);
+ switch (base)
+ {
+ case 2:
+ return bits;
+ case 4:
+ return (bits + 1) / 2;
+ case 8:
+ return (bits + 2) / 3;
+ case 16:
+ return (bits + 3) / 4;
+ case 32:
+ return (bits + 4) / 5;
+ /* FIXME: Do something more clever for the common case of base
+ 10. */
+ }
+
+ tp = gmp_alloc_limbs (un);
+ mpn_copyi (tp, up, un);
+ mpn_div_qr_1_invert (&bi, base);
+
+ tn = un;
+ ndigits = 0;
+ do
+ {
+ ndigits++;
+ mpn_div_qr_1_preinv (tp, tp, tn, &bi);
+ tn -= (tp[tn-1] == 0);
+ }
+ while (tn > 0);
+
+ gmp_free_limbs (tp, un);
+ return ndigits;
+}
+
+char *
+mpz_get_str (char *sp, int base, const mpz_t u)
+{
+ unsigned bits;
+ const char *digits;
+ mp_size_t un;
+ size_t i, sn, osn;
+
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ if (base > 1)
+ {
+ if (base <= 36)
+ digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ else if (base > 62)
+ return NULL;
+ }
+ else if (base >= -1)
+ base = 10;
+ else
+ {
+ base = -base;
+ if (base > 36)
+ return NULL;
+ }
+
+ sn = 1 + mpz_sizeinbase (u, base);
+ if (!sp)
+ {
+ osn = 1 + sn;
+ sp = (char *) gmp_alloc (osn);
+ }
+ else
+ osn = 0;
+ un = GMP_ABS (u->_mp_size);
+
+ if (un == 0)
+ {
+ sp[0] = '0';
+ sn = 1;
+ goto ret;
+ }
+
+ i = 0;
+
+ if (u->_mp_size < 0)
+ sp[i++] = '-';
+
+ bits = mpn_base_power_of_two_p (base);
+
+ if (bits)
+ /* Not modified in this case. */
+ sn = i + mpn_get_str_bits ((unsigned char *) sp + i, bits, u->_mp_d, un);
+ else
+ {
+ struct mpn_base_info info;
+ mp_ptr tp;
+
+ mpn_get_base_info (&info, base);
+ tp = gmp_alloc_limbs (un);
+ mpn_copyi (tp, u->_mp_d, un);
+
+ sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, un);
+ gmp_free_limbs (tp, un);
+ }
+
+ for (; i < sn; i++)
+ sp[i] = digits[(unsigned char) sp[i]];
+
+ret:
+ sp[sn] = '\0';
+ if (osn && osn != sn + 1)
+ sp = (char*) gmp_realloc (sp, osn, sn + 1);
+ return sp;
+}
+
+int
+mpz_set_str (mpz_t r, const char *sp, int base)
+{
+ unsigned bits, value_of_a;
+ mp_size_t rn, alloc;
+ mp_ptr rp;
+ size_t dn, sn;
+ int sign;
+ unsigned char *dp;
+
+ assert (base == 0 || (base >= 2 && base <= 62));
+
+ while (isspace( (unsigned char) *sp))
+ sp++;
+
+ sign = (*sp == '-');
+ sp += sign;
+
+ if (base == 0)
+ {
+ if (sp[0] == '0')
+ {
+ if (sp[1] == 'x' || sp[1] == 'X')
+ {
+ base = 16;
+ sp += 2;
+ }
+ else if (sp[1] == 'b' || sp[1] == 'B')
+ {
+ base = 2;
+ sp += 2;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+
+ if (!*sp)
+ {
+ r->_mp_size = 0;
+ return -1;
+ }
+ sn = strlen(sp);
+ dp = (unsigned char *) gmp_alloc (sn);
+
+ value_of_a = (base > 36) ? 36 : 10;
+ for (dn = 0; *sp; sp++)
+ {
+ unsigned digit;
+
+ if (isspace ((unsigned char) *sp))
+ continue;
+ else if (*sp >= '0' && *sp <= '9')
+ digit = *sp - '0';
+ else if (*sp >= 'a' && *sp <= 'z')
+ digit = *sp - 'a' + value_of_a;
+ else if (*sp >= 'A' && *sp <= 'Z')
+ digit = *sp - 'A' + 10;
+ else
+ digit = base; /* fail */
+
+ if (digit >= (unsigned) base)
+ {
+ gmp_free (dp, sn);
+ r->_mp_size = 0;
+ return -1;
+ }
+
+ dp[dn++] = digit;
+ }
+
+ if (!dn)
+ {
+ gmp_free (dp, sn);
+ r->_mp_size = 0;
+ return -1;
+ }
+ bits = mpn_base_power_of_two_p (base);
+
+ if (bits > 0)
+ {
+ alloc = (dn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ rp = MPZ_REALLOC (r, alloc);
+ rn = mpn_set_str_bits (rp, dp, dn, bits);
+ }
+ else
+ {
+ struct mpn_base_info info;
+ mpn_get_base_info (&info, base);
+ alloc = (dn + info.exp - 1) / info.exp;
+ rp = MPZ_REALLOC (r, alloc);
+ rn = mpn_set_str_other (rp, dp, dn, base, &info);
+ /* Normalization, needed for all-zero input. */
+ assert (rn > 0);
+ rn -= rp[rn-1] == 0;
+ }
+ assert (rn <= alloc);
+ gmp_free (dp, sn);
+
+ r->_mp_size = sign ? - rn : rn;
+
+ return 0;
+}
+
+int
+mpz_init_set_str (mpz_t r, const char *sp, int base)
+{
+ mpz_init (r);
+ return mpz_set_str (r, sp, base);
+}
+
+size_t
+mpz_out_str (FILE *stream, int base, const mpz_t x)
+{
+ char *str;
+ size_t len, n;
+
+ str = mpz_get_str (NULL, base, x);
+ if (!str)
+ return 0;
+ len = strlen (str);
+ n = fwrite (str, 1, len, stream);
+ gmp_free (str, len + 1);
+ return n;
+}
+
+
+static int
+gmp_detect_endian (void)
+{
+ static const int i = 2;
+ const unsigned char *p = (const unsigned char *) &i;
+ return 1 - *p;
+}
+
+/* Import and export. Does not support nails. */
+void
+mpz_import (mpz_t r, size_t count, int order, size_t size, int endian,
+ size_t nails, const void *src)
+{
+ const unsigned char *p;
+ ptrdiff_t word_step;
+ mp_ptr rp;
+ mp_size_t rn;
+
+ /* The current (partial) limb. */
+ mp_limb_t limb;
+ /* The number of bytes already copied to this limb (starting from
+ the low end). */
+ size_t bytes;
+ /* The index where the limb should be stored, when completed. */
+ mp_size_t i;
+
+ if (nails != 0)
+ gmp_die ("mpz_import: Nails not supported.");
+
+ assert (order == 1 || order == -1);
+ assert (endian >= -1 && endian <= 1);
+
+ if (endian == 0)
+ endian = gmp_detect_endian ();
+
+ p = (unsigned char *) src;
+
+ word_step = (order != endian) ? 2 * size : 0;
+
+ /* Process bytes from the least significant end, so point p at the
+ least significant word. */
+ if (order == 1)
+ {
+ p += size * (count - 1);
+ word_step = - word_step;
+ }
+
+ /* And at least significant byte of that word. */
+ if (endian == 1)
+ p += (size - 1);
+
+ rn = (size * count + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t);
+ rp = MPZ_REALLOC (r, rn);
+
+ for (limb = 0, bytes = 0, i = 0; count > 0; count--, p += word_step)
+ {
+ size_t j;
+ for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
+ {
+ limb |= (mp_limb_t) *p << (bytes++ * CHAR_BIT);
+ if (bytes == sizeof(mp_limb_t))
+ {
+ rp[i++] = limb;
+ bytes = 0;
+ limb = 0;
+ }
+ }
+ }
+ assert (i + (bytes > 0) == rn);
+ if (limb != 0)
+ rp[i++] = limb;
+ else
+ i = mpn_normalized_size (rp, i);
+
+ r->_mp_size = i;
+}
+
+void *
+mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
+ size_t nails, const mpz_t u)
+{
+ size_t count;
+ mp_size_t un;
+
+ if (nails != 0)
+ gmp_die ("mpz_export: Nails not supported.");
+
+ assert (order == 1 || order == -1);
+ assert (endian >= -1 && endian <= 1);
+ assert (size > 0 || u->_mp_size == 0);
+
+ un = u->_mp_size;
+ count = 0;
+ if (un != 0)
+ {
+ size_t k;
+ unsigned char *p;
+ ptrdiff_t word_step;
+ /* The current (partial) limb. */
+ mp_limb_t limb;
+ /* The number of bytes left to do in this limb. */
+ size_t bytes;
+ /* The index where the limb was read. */
+ mp_size_t i;
+
+ un = GMP_ABS (un);
+
+ /* Count bytes in top limb. */
+ limb = u->_mp_d[un-1];
+ assert (limb != 0);
+
+ k = (GMP_LIMB_BITS <= CHAR_BIT);
+ if (!k)
+ {
+ do {
+ int LOCAL_CHAR_BIT = CHAR_BIT;
+ k++; limb >>= LOCAL_CHAR_BIT;
+ } while (limb != 0);
+ }
+ /* else limb = 0; */
+
+ count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
+
+ if (!r)
+ r = gmp_alloc (count * size);
+
+ if (endian == 0)
+ endian = gmp_detect_endian ();
+
+ p = (unsigned char *) r;
+
+ word_step = (order != endian) ? 2 * size : 0;
+
+ /* Process bytes from the least significant end, so point p at the
+ least significant word. */
+ if (order == 1)
+ {
+ p += size * (count - 1);
+ word_step = - word_step;
+ }
+
+ /* And at least significant byte of that word. */
+ if (endian == 1)
+ p += (size - 1);
+
+ for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
+ {
+ size_t j;
+ for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian)
+ {
+ if (sizeof (mp_limb_t) == 1)
+ {
+ if (i < un)
+ *p = u->_mp_d[i++];
+ else
+ *p = 0;
+ }
+ else
+ {
+ int LOCAL_CHAR_BIT = CHAR_BIT;
+ if (bytes == 0)
+ {
+ if (i < un)
+ limb = u->_mp_d[i++];
+ bytes = sizeof (mp_limb_t);
+ }
+ *p = limb;
+ limb >>= LOCAL_CHAR_BIT;
+ bytes--;
+ }
+ }
+ }
+ assert (i == un);
+ assert (k == count);
+ }
+
+ if (countp)
+ *countp = count;
+
+ return r;
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/mini-gmp.h b/vendor/gmp-6.3.0/mini-gmp/mini-gmp.h
new file mode 100644
index 0000000..59c24cf
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/mini-gmp.h
@@ -0,0 +1,310 @@
+/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
+
+Copyright 2011-2015, 2017, 2019-2021 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+/* About mini-gmp: This is a minimal implementation of a subset of the
+ GMP interface. It is intended for inclusion into applications which
+ have modest bignums needs, as a fallback when the real GMP library
+ is not installed.
+
+ This file defines the public interface. */
+
+#ifndef __MINI_GMP_H__
+#define __MINI_GMP_H__
+
+/* For size_t */
+#include <stddef.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void mp_set_memory_functions (void *(*) (size_t),
+ void *(*) (void *, size_t, size_t),
+ void (*) (void *, size_t));
+
+void mp_get_memory_functions (void *(**) (size_t),
+ void *(**) (void *, size_t, size_t),
+ void (**) (void *, size_t));
+
+#ifndef MINI_GMP_LIMB_TYPE
+#define MINI_GMP_LIMB_TYPE long
+#endif
+
+typedef unsigned MINI_GMP_LIMB_TYPE mp_limb_t;
+typedef long mp_size_t;
+typedef unsigned long mp_bitcnt_t;
+
+typedef mp_limb_t *mp_ptr;
+typedef const mp_limb_t *mp_srcptr;
+
+typedef struct
+{
+ int _mp_alloc; /* Number of *limbs* allocated and pointed
+ to by the _mp_d field. */
+ int _mp_size; /* abs(_mp_size) is the number of limbs the
+ last field points to. If _mp_size is
+ negative this is a negative number. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpz_struct;
+
+typedef __mpz_struct mpz_t[1];
+
+typedef __mpz_struct *mpz_ptr;
+typedef const __mpz_struct *mpz_srcptr;
+
+extern const int mp_bits_per_limb;
+
+void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t);
+void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t);
+void mpn_zero (mp_ptr, mp_size_t);
+
+int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t);
+int mpn_zero_p (mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+
+mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
+void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
+void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
+int mpn_perfect_square_p (mp_srcptr, mp_size_t);
+mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
+mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
+
+mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t);
+mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t);
+
+void mpn_com (mp_ptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t);
+
+mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t);
+#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0)
+
+size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t);
+mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int);
+
+void mpz_init (mpz_t);
+void mpz_init2 (mpz_t, mp_bitcnt_t);
+void mpz_clear (mpz_t);
+
+#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0])
+#define mpz_even_p(z) (! mpz_odd_p (z))
+
+int mpz_sgn (const mpz_t);
+int mpz_cmp_si (const mpz_t, long);
+int mpz_cmp_ui (const mpz_t, unsigned long);
+int mpz_cmp (const mpz_t, const mpz_t);
+int mpz_cmpabs_ui (const mpz_t, unsigned long);
+int mpz_cmpabs (const mpz_t, const mpz_t);
+int mpz_cmp_d (const mpz_t, double);
+int mpz_cmpabs_d (const mpz_t, double);
+
+void mpz_abs (mpz_t, const mpz_t);
+void mpz_neg (mpz_t, const mpz_t);
+void mpz_swap (mpz_t, mpz_t);
+
+void mpz_add_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_add (mpz_t, const mpz_t, const mpz_t);
+void mpz_sub_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_ui_sub (mpz_t, unsigned long, const mpz_t);
+void mpz_sub (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_mul_si (mpz_t, const mpz_t, long int);
+void mpz_mul_ui (mpz_t, const mpz_t, unsigned long int);
+void mpz_mul (mpz_t, const mpz_t, const mpz_t);
+void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_addmul_ui (mpz_t, const mpz_t, unsigned long int);
+void mpz_addmul (mpz_t, const mpz_t, const mpz_t);
+void mpz_submul_ui (mpz_t, const mpz_t, unsigned long int);
+void mpz_submul (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t);
+void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t);
+void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t);
+void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t);
+void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t);
+void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+
+void mpz_mod (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_divexact (mpz_t, const mpz_t, const mpz_t);
+
+int mpz_divisible_p (const mpz_t, const mpz_t);
+int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t);
+
+unsigned long mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_cdiv_q_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_fdiv_q_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_tdiv_q_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_cdiv_r_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_fdiv_r_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_tdiv_r_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_cdiv_ui (const mpz_t, unsigned long);
+unsigned long mpz_fdiv_ui (const mpz_t, unsigned long);
+unsigned long mpz_tdiv_ui (const mpz_t, unsigned long);
+
+unsigned long mpz_mod_ui (mpz_t, const mpz_t, unsigned long);
+
+void mpz_divexact_ui (mpz_t, const mpz_t, unsigned long);
+
+int mpz_divisible_ui_p (const mpz_t, unsigned long);
+
+unsigned long mpz_gcd_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_gcd (mpz_t, const mpz_t, const mpz_t);
+void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_lcm_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_lcm (mpz_t, const mpz_t, const mpz_t);
+int mpz_invert (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t);
+void mpz_sqrt (mpz_t, const mpz_t);
+int mpz_perfect_square_p (const mpz_t);
+
+void mpz_pow_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_ui_pow_ui (mpz_t, unsigned long, unsigned long);
+void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t);
+void mpz_powm_ui (mpz_t, const mpz_t, unsigned long, const mpz_t);
+
+void mpz_rootrem (mpz_t, mpz_t, const mpz_t, unsigned long);
+int mpz_root (mpz_t, const mpz_t, unsigned long);
+
+void mpz_fac_ui (mpz_t, unsigned long);
+void mpz_2fac_ui (mpz_t, unsigned long);
+void mpz_mfac_uiui (mpz_t, unsigned long, unsigned long);
+void mpz_bin_uiui (mpz_t, unsigned long, unsigned long);
+
+int mpz_probab_prime_p (const mpz_t, int);
+
+int mpz_tstbit (const mpz_t, mp_bitcnt_t);
+void mpz_setbit (mpz_t, mp_bitcnt_t);
+void mpz_clrbit (mpz_t, mp_bitcnt_t);
+void mpz_combit (mpz_t, mp_bitcnt_t);
+
+void mpz_com (mpz_t, const mpz_t);
+void mpz_and (mpz_t, const mpz_t, const mpz_t);
+void mpz_ior (mpz_t, const mpz_t, const mpz_t);
+void mpz_xor (mpz_t, const mpz_t, const mpz_t);
+
+mp_bitcnt_t mpz_popcount (const mpz_t);
+mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t);
+mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t);
+mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t);
+
+int mpz_fits_slong_p (const mpz_t);
+int mpz_fits_ulong_p (const mpz_t);
+int mpz_fits_sint_p (const mpz_t);
+int mpz_fits_uint_p (const mpz_t);
+int mpz_fits_sshort_p (const mpz_t);
+int mpz_fits_ushort_p (const mpz_t);
+long int mpz_get_si (const mpz_t);
+unsigned long int mpz_get_ui (const mpz_t);
+double mpz_get_d (const mpz_t);
+size_t mpz_size (const mpz_t);
+mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t);
+
+void mpz_realloc2 (mpz_t, mp_bitcnt_t);
+mp_srcptr mpz_limbs_read (mpz_srcptr);
+mp_ptr mpz_limbs_modify (mpz_t, mp_size_t);
+mp_ptr mpz_limbs_write (mpz_t, mp_size_t);
+void mpz_limbs_finish (mpz_t, mp_size_t);
+mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t);
+
+#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }}
+
+void mpz_set_si (mpz_t, signed long int);
+void mpz_set_ui (mpz_t, unsigned long int);
+void mpz_set (mpz_t, const mpz_t);
+void mpz_set_d (mpz_t, double);
+
+void mpz_init_set_si (mpz_t, signed long int);
+void mpz_init_set_ui (mpz_t, unsigned long int);
+void mpz_init_set (mpz_t, const mpz_t);
+void mpz_init_set_d (mpz_t, double);
+
+size_t mpz_sizeinbase (const mpz_t, int);
+char *mpz_get_str (char *, int, const mpz_t);
+int mpz_set_str (mpz_t, const char *, int);
+int mpz_init_set_str (mpz_t, const char *, int);
+
+/* This long list taken from gmp.h. */
+/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4,
+ <iostream> defines EOF but not FILE. */
+#if defined (FILE) \
+ || defined (H_STDIO) \
+ || defined (_H_STDIO) /* AIX */ \
+ || defined (_STDIO_H) /* glibc, Sun, SCO */ \
+ || defined (_STDIO_H_) /* BSD, OSF */ \
+ || defined (__STDIO_H) /* Borland */ \
+ || defined (__STDIO_H__) /* IRIX */ \
+ || defined (_STDIO_INCLUDED) /* HPUX */ \
+ || defined (__dj_include_stdio_h_) /* DJGPP */ \
+ || defined (_FILE_DEFINED) /* Microsoft */ \
+ || defined (__STDIO__) /* Apple MPW MrC */ \
+ || defined (_MSL_STDIO_H) /* Metrowerks */ \
+ || defined (_STDIO_H_INCLUDED) /* QNX4 */ \
+ || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
+ || defined (__STDIO_LOADED) /* VMS */ \
+ || defined (_STDIO) /* HPE NonStop */ \
+ || defined (__DEFINED_FILE) /* musl */
+size_t mpz_out_str (FILE *, int, const mpz_t);
+#endif
+
+void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *);
+void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __MINI_GMP_H__ */
diff --git a/vendor/gmp-6.3.0/mini-gmp/mini-mpq.c b/vendor/gmp-6.3.0/mini-gmp/mini-mpq.c
new file mode 100644
index 0000000..58ce37f
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/mini-mpq.c
@@ -0,0 +1,556 @@
+/* mini-mpq, a minimalistic implementation of a GNU GMP subset.
+
+ Contributed to the GNU project by Marco Bodrato
+
+ Acknowledgment: special thanks to Bradley Lucier for his comments
+ to the preliminary version of this code.
+
+Copyright 2018-2022 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mini-mpq.h"
+
+#ifndef GMP_LIMB_HIGHBIT
+/* Define macros and static functions already defined by mini-gmp.c */
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1))
+#define GMP_LIMB_MAX ((mp_limb_t) ~ (mp_limb_t) 0)
+#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1))
+#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static mpz_srcptr
+mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
+{
+ x->_mp_alloc = 0;
+ x->_mp_d = (mp_ptr) xp;
+ x->_mp_size = xs;
+ return x;
+}
+
+static void
+gmp_die (const char *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+ abort();
+}
+#endif
+
+
+/* MPQ helper functions */
+static mpq_srcptr
+mpq_roinit_normal_nn (mpq_t x, mp_srcptr np, mp_size_t ns,
+ mp_srcptr dp, mp_size_t ds)
+{
+ mpz_roinit_normal_n (mpq_numref(x), np, ns);
+ mpz_roinit_normal_n (mpq_denref(x), dp, ds);
+ return x;
+}
+
+static mpq_srcptr
+mpq_roinit_zz (mpq_t x, mpz_srcptr n, mpz_srcptr d)
+{
+ return mpq_roinit_normal_nn (x, n->_mp_d, n->_mp_size,
+ d->_mp_d, d->_mp_size);
+}
+
+static void
+mpq_nan_init (mpq_t x)
+{
+ mpz_init (mpq_numref (x));
+ mpz_init (mpq_denref (x));
+}
+
+void
+mpq_init (mpq_t x)
+{
+ mpz_init (mpq_numref (x));
+ mpz_init_set_ui (mpq_denref (x), 1);
+}
+
+void
+mpq_clear (mpq_t x)
+{
+ mpz_clear (mpq_numref (x));
+ mpz_clear (mpq_denref (x));
+}
+
+static void
+mpq_canonical_sign (mpq_t r)
+{
+ mp_size_t ds = mpq_denref (r)->_mp_size;
+ if (ds <= 0)
+ {
+ if (ds == 0)
+ gmp_die("mpq: Fraction with zero denominator.");
+ mpz_neg (mpq_denref (r), mpq_denref (r));
+ mpz_neg (mpq_numref (r), mpq_numref (r));
+ }
+}
+
+static void
+mpq_helper_canonicalize (mpq_t r, const mpz_t num, const mpz_t den)
+{
+ if (num->_mp_size == 0)
+ mpq_set_ui (r, 0, 1);
+ else
+ {
+ mpz_t g;
+
+ mpz_init (g);
+ mpz_gcd (g, num, den);
+ mpz_tdiv_q (mpq_numref (r), num, g);
+ mpz_tdiv_q (mpq_denref (r), den, g);
+ mpz_clear (g);
+ mpq_canonical_sign (r);
+ }
+}
+
+void
+mpq_canonicalize (mpq_t r)
+{
+ mpq_helper_canonicalize (r, mpq_numref (r), mpq_denref (r));
+}
+
+void
+mpq_swap (mpq_t a, mpq_t b)
+{
+ mpz_swap (mpq_numref (a), mpq_numref (b));
+ mpz_swap (mpq_denref (a), mpq_denref (b));
+}
+
+
+/* MPQ assignment and conversions. */
+void
+mpz_set_q (mpz_t r, const mpq_t q)
+{
+ mpz_tdiv_q (r, mpq_numref (q), mpq_denref (q));
+}
+
+void
+mpq_set (mpq_t r, const mpq_t q)
+{
+ mpz_set (mpq_numref (r), mpq_numref (q));
+ mpz_set (mpq_denref (r), mpq_denref (q));
+}
+
+void
+mpq_set_ui (mpq_t r, unsigned long n, unsigned long d)
+{
+ mpz_set_ui (mpq_numref (r), n);
+ mpz_set_ui (mpq_denref (r), d);
+}
+
+void
+mpq_set_si (mpq_t r, signed long n, unsigned long d)
+{
+ mpz_set_si (mpq_numref (r), n);
+ mpz_set_ui (mpq_denref (r), d);
+}
+
+void
+mpq_set_z (mpq_t r, const mpz_t n)
+{
+ mpz_set_ui (mpq_denref (r), 1);
+ mpz_set (mpq_numref (r), n);
+}
+
+void
+mpq_set_num (mpq_t r, const mpz_t z)
+{
+ mpz_set (mpq_numref (r), z);
+}
+
+void
+mpq_set_den (mpq_t r, const mpz_t z)
+{
+ mpz_set (mpq_denref (r), z);
+}
+
+void
+mpq_get_num (mpz_t r, const mpq_t q)
+{
+ mpz_set (r, mpq_numref (q));
+}
+
+void
+mpq_get_den (mpz_t r, const mpq_t q)
+{
+ mpz_set (r, mpq_denref (q));
+}
+
+
+/* MPQ comparisons and the like. */
+int
+mpq_cmp (const mpq_t a, const mpq_t b)
+{
+ mpz_t t1, t2;
+ int res;
+
+ mpz_init (t1);
+ mpz_init (t2);
+ mpz_mul (t1, mpq_numref (a), mpq_denref (b));
+ mpz_mul (t2, mpq_numref (b), mpq_denref (a));
+ res = mpz_cmp (t1, t2);
+ mpz_clear (t1);
+ mpz_clear (t2);
+
+ return res;
+}
+
+int
+mpq_cmp_z (const mpq_t a, const mpz_t b)
+{
+ mpz_t t;
+ int res;
+
+ mpz_init (t);
+ mpz_mul (t, b, mpq_denref (a));
+ res = mpz_cmp (mpq_numref (a), t);
+ mpz_clear (t);
+
+ return res;
+}
+
+int
+mpq_equal (const mpq_t a, const mpq_t b)
+{
+ return (mpz_cmp (mpq_numref (a), mpq_numref (b)) == 0) &&
+ (mpz_cmp (mpq_denref (a), mpq_denref (b)) == 0);
+}
+
+int
+mpq_cmp_ui (const mpq_t q, unsigned long n, unsigned long d)
+{
+ mpq_t t;
+ assert (d != 0);
+ if (ULONG_MAX <= GMP_LIMB_MAX) {
+ mp_limb_t nl = n, dl = d;
+ return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, n != 0, &dl, 1));
+ } else {
+ int ret;
+
+ mpq_nan_init (t);
+ mpq_set_ui (t, n, d);
+ ret = mpq_cmp (q, t);
+ mpq_clear (t);
+
+ return ret;
+ }
+}
+
+int
+mpq_cmp_si (const mpq_t q, signed long n, unsigned long d)
+{
+ assert (d != 0);
+
+ if (n >= 0)
+ return mpq_cmp_ui (q, n, d);
+ else
+ {
+ mpq_t t;
+
+ if (ULONG_MAX <= GMP_LIMB_MAX)
+ {
+ mp_limb_t nl = GMP_NEG_CAST (unsigned long, n), dl = d;
+ return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, -1, &dl, 1));
+ }
+ else
+ {
+ unsigned long l_n = GMP_NEG_CAST (unsigned long, n);
+
+ mpq_roinit_normal_nn (t, mpq_numref (q)->_mp_d, - mpq_numref (q)->_mp_size,
+ mpq_denref (q)->_mp_d, mpq_denref (q)->_mp_size);
+ return - mpq_cmp_ui (t, l_n, d);
+ }
+ }
+}
+
+int
+mpq_sgn (const mpq_t a)
+{
+ return mpz_sgn (mpq_numref (a));
+}
+
+
+/* MPQ arithmetic. */
+void
+mpq_abs (mpq_t r, const mpq_t q)
+{
+ mpz_abs (mpq_numref (r), mpq_numref (q));
+ mpz_set (mpq_denref (r), mpq_denref (q));
+}
+
+void
+mpq_neg (mpq_t r, const mpq_t q)
+{
+ mpz_neg (mpq_numref (r), mpq_numref (q));
+ mpz_set (mpq_denref (r), mpq_denref (q));
+}
+
+void
+mpq_add (mpq_t r, const mpq_t a, const mpq_t b)
+{
+ mpz_t t;
+
+ mpz_init (t);
+ mpz_gcd (t, mpq_denref (a), mpq_denref (b));
+ if (mpz_cmp_ui (t, 1) == 0)
+ {
+ mpz_mul (t, mpq_numref (a), mpq_denref (b));
+ mpz_addmul (t, mpq_numref (b), mpq_denref (a));
+ mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b));
+ mpz_swap (mpq_numref (r), t);
+ }
+ else
+ {
+ mpz_t x, y;
+ mpz_init (x);
+ mpz_init (y);
+
+ mpz_tdiv_q (x, mpq_denref (b), t);
+ mpz_tdiv_q (y, mpq_denref (a), t);
+ mpz_mul (x, mpq_numref (a), x);
+ mpz_addmul (x, mpq_numref (b), y);
+
+ mpz_gcd (t, x, t);
+ mpz_tdiv_q (mpq_numref (r), x, t);
+ mpz_tdiv_q (x, mpq_denref (b), t);
+ mpz_mul (mpq_denref (r), x, y);
+
+ mpz_clear (x);
+ mpz_clear (y);
+ }
+ mpz_clear (t);
+}
+
+void
+mpq_sub (mpq_t r, const mpq_t a, const mpq_t b)
+{
+ mpq_t t;
+
+ mpq_roinit_normal_nn (t, mpq_numref (b)->_mp_d, - mpq_numref (b)->_mp_size,
+ mpq_denref (b)->_mp_d, mpq_denref (b)->_mp_size);
+ mpq_add (r, a, t);
+}
+
+void
+mpq_div (mpq_t r, const mpq_t a, const mpq_t b)
+{
+ mpq_t t;
+ mpq_mul (r, a, mpq_roinit_zz (t, mpq_denref (b), mpq_numref (b)));
+}
+
+void
+mpq_mul (mpq_t r, const mpq_t a, const mpq_t b)
+{
+ mpq_t t;
+ mpq_nan_init (t);
+
+ if (a != b) {
+ mpq_helper_canonicalize (t, mpq_numref (a), mpq_denref (b));
+ mpq_helper_canonicalize (r, mpq_numref (b), mpq_denref (a));
+
+ a = r;
+ b = t;
+ }
+
+ mpz_mul (mpq_numref (r), mpq_numref (a), mpq_numref (b));
+ mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b));
+ mpq_clear (t);
+}
+
+static void
+mpq_helper_2exp (mpz_t rn, mpz_t rd, const mpz_t qn, const mpz_t qd, mp_bitcnt_t e)
+{
+ mp_bitcnt_t z = mpz_scan1 (qd, 0);
+ z = GMP_MIN (z, e);
+ mpz_mul_2exp (rn, qn, e - z);
+ mpz_tdiv_q_2exp (rd, qd, z);
+}
+
+void
+mpq_div_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e)
+{
+ mpq_helper_2exp (mpq_denref (r), mpq_numref (r), mpq_denref (q), mpq_numref (q), e);
+}
+
+void
+mpq_mul_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e)
+{
+ mpq_helper_2exp (mpq_numref (r), mpq_denref (r), mpq_numref (q), mpq_denref (q), e);
+}
+
+void
+mpq_inv (mpq_t r, const mpq_t q)
+{
+ mpq_set (r, q);
+ mpz_swap (mpq_denref (r), mpq_numref (r));
+ mpq_canonical_sign (r);
+}
+
+
+/* MPQ to/from double. */
+void
+mpq_set_d (mpq_t r, double x)
+{
+ mpz_set_ui (mpq_denref (r), 1);
+
+ /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is
+ zero or infinity. */
+ if (x == x * 0.5 || x != x)
+ mpq_numref (r)->_mp_size = 0;
+ else
+ {
+ double B;
+ mp_bitcnt_t e;
+
+ B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+ for (e = 0; x != x + 0.5; e += GMP_LIMB_BITS)
+ x *= B;
+
+ mpz_set_d (mpq_numref (r), x);
+ mpq_div_2exp (r, r, e);
+ }
+}
+
+double
+mpq_get_d (const mpq_t u)
+{
+ mp_bitcnt_t ne, de, ee;
+ mpz_t z;
+ double B, ret;
+
+ ne = mpz_sizeinbase (mpq_numref (u), 2);
+ de = mpz_sizeinbase (mpq_denref (u), 2);
+
+ ee = CHAR_BIT * sizeof (double);
+ if (de == 1 || ne > de + ee)
+ ee = 0;
+ else
+ ee = (ee + de - ne) / GMP_LIMB_BITS + 1;
+
+ mpz_init (z);
+ mpz_mul_2exp (z, mpq_numref (u), ee * GMP_LIMB_BITS);
+ mpz_tdiv_q (z, z, mpq_denref (u));
+ ret = mpz_get_d (z);
+ mpz_clear (z);
+
+ B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+ for (B = 1 / B; ee != 0; --ee)
+ ret *= B;
+
+ return ret;
+}
+
+
+/* MPQ and strings/streams. */
+char *
+mpq_get_str (char *sp, int base, const mpq_t q)
+{
+ char *res;
+ char *rden;
+ size_t len;
+
+ res = mpz_get_str (sp, base, mpq_numref (q));
+ if (res == NULL || mpz_cmp_ui (mpq_denref (q), 1) == 0)
+ return res;
+
+ len = strlen (res) + 1;
+ rden = sp ? sp + len : NULL;
+ rden = mpz_get_str (rden, base, mpq_denref (q));
+ assert (rden != NULL);
+
+ if (sp == NULL) {
+ void * (*gmp_reallocate_func) (void *, size_t, size_t);
+ void (*gmp_free_func) (void *, size_t);
+ size_t lden;
+
+ mp_get_memory_functions (NULL, &gmp_reallocate_func, &gmp_free_func);
+ lden = strlen (rden) + 1;
+ res = (char *) gmp_reallocate_func (res, len, (lden + len) * sizeof (char));
+ memcpy (res + len, rden, lden);
+ gmp_free_func (rden, lden);
+ }
+
+ res [len - 1] = '/';
+ return res;
+}
+
+size_t
+mpq_out_str (FILE *stream, int base, const mpq_t x)
+{
+ char * str;
+ size_t len, n;
+ void (*gmp_free_func) (void *, size_t);
+
+ str = mpq_get_str (NULL, base, x);
+ if (!str)
+ return 0;
+ len = strlen (str);
+ n = fwrite (str, 1, len, stream);
+ mp_get_memory_functions (NULL, NULL, &gmp_free_func);
+ gmp_free_func (str, len + 1);
+ return n;
+}
+
+int
+mpq_set_str (mpq_t r, const char *sp, int base)
+{
+ const char *slash;
+
+ slash = strchr (sp, '/');
+ if (slash == NULL) {
+ mpz_set_ui (mpq_denref(r), 1);
+ return mpz_set_str (mpq_numref(r), sp, base);
+ } else {
+ char *num;
+ size_t numlen;
+ int ret;
+ void * (*gmp_allocate_func) (size_t);
+ void (*gmp_free_func) (void *, size_t);
+
+ mp_get_memory_functions (&gmp_allocate_func, NULL, &gmp_free_func);
+ numlen = slash - sp;
+ num = (char *) gmp_allocate_func (numlen + 1);
+ memcpy (num, sp, numlen);
+ num[numlen] = '\0';
+ ret = mpz_set_str (mpq_numref(r), num, base);
+ gmp_free_func (num, numlen + 1);
+
+ if (ret != 0)
+ return ret;
+
+ return mpz_set_str (mpq_denref(r), slash + 1, base);
+ }
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/mini-mpq.h b/vendor/gmp-6.3.0/mini-gmp/mini-mpq.h
new file mode 100644
index 0000000..8eabcec
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/mini-mpq.h
@@ -0,0 +1,114 @@
+/* mini-mpq, a minimalistic implementation of a GNU GMP subset.
+
+Copyright 2018, 2019 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+/* Header */
+
+#ifndef __MINI_MPQ_H__
+#define __MINI_MPQ_H__
+
+#include "mini-gmp.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct
+{
+ __mpz_struct _mp_num;
+ __mpz_struct _mp_den;
+} __mpq_struct;
+
+typedef __mpq_struct mpq_t[1];
+
+typedef const __mpq_struct *mpq_srcptr;
+typedef __mpq_struct *mpq_ptr;
+
+#define mpq_numref(Q) (&((Q)->_mp_num))
+#define mpq_denref(Q) (&((Q)->_mp_den))
+
+void mpq_abs (mpq_t, const mpq_t);
+void mpq_add (mpq_t, const mpq_t, const mpq_t);
+void mpq_canonicalize (mpq_t);
+void mpq_clear (mpq_t);
+int mpq_cmp (const mpq_t, const mpq_t);
+int mpq_cmp_si (const mpq_t, signed long, unsigned long);
+int mpq_cmp_ui (const mpq_t, unsigned long, unsigned long);
+int mpq_cmp_z (const mpq_t, const mpz_t);
+void mpq_div (mpq_t, const mpq_t, const mpq_t);
+void mpq_div_2exp (mpq_t, const mpq_t, mp_bitcnt_t);
+int mpq_equal (const mpq_t, const mpq_t);
+double mpq_get_d (const mpq_t);
+void mpq_get_den (mpz_t, const mpq_t);
+void mpq_get_num (mpz_t, const mpq_t);
+char * mpq_get_str (char *, int, const mpq_t q);
+void mpq_init (mpq_t);
+void mpq_inv (mpq_t, const mpq_t);
+void mpq_mul (mpq_t, const mpq_t, const mpq_t);
+void mpq_mul_2exp (mpq_t, const mpq_t, mp_bitcnt_t);
+void mpq_neg (mpq_t, const mpq_t);
+void mpq_set (mpq_t, const mpq_t);
+void mpq_set_d (mpq_t, double);
+void mpq_set_den (mpq_t, const mpz_t);
+void mpq_set_num (mpq_t, const mpz_t);
+void mpq_set_si (mpq_t, signed long, unsigned long);
+int mpq_set_str (mpq_t, const char *, int);
+void mpq_set_ui (mpq_t, unsigned long, unsigned long);
+void mpq_set_z (mpq_t, const mpz_t);
+int mpq_sgn (const mpq_t);
+void mpq_sub (mpq_t, const mpq_t, const mpq_t);
+void mpq_swap (mpq_t, mpq_t);
+
+/* This long list taken from gmp.h. */
+/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4,
+ <iostream> defines EOF but not FILE. */
+#if defined (FILE) \
+ || defined (H_STDIO) \
+ || defined (_H_STDIO) /* AIX */ \
+ || defined (_STDIO_H) /* glibc, Sun, SCO */ \
+ || defined (_STDIO_H_) /* BSD, OSF */ \
+ || defined (__STDIO_H) /* Borland */ \
+ || defined (__STDIO_H__) /* IRIX */ \
+ || defined (_STDIO_INCLUDED) /* HPUX */ \
+ || defined (__dj_include_stdio_h_) /* DJGPP */ \
+ || defined (_FILE_DEFINED) /* Microsoft */ \
+ || defined (__STDIO__) /* Apple MPW MrC */ \
+ || defined (_MSL_STDIO_H) /* Metrowerks */ \
+ || defined (_STDIO_H_INCLUDED) /* QNX4 */ \
+ || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
+ || defined (__STDIO_LOADED) /* VMS */
+size_t mpq_out_str (FILE *, int, const mpq_t);
+#endif
+
+void mpz_set_q (mpz_t, const mpq_t);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __MINI_MPQ_H__ */
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/Makefile b/vendor/gmp-6.3.0/mini-gmp/tests/Makefile
new file mode 100644
index 0000000..7cc4485
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/Makefile
@@ -0,0 +1,65 @@
+# Note: Requires GNU make
+
+# Copyright 2011, 2012, 2014, 2016, 2018 Free Software Foundation, Inc.
+#
+# This file is part of the GNU MP Library test suite.
+#
+# The GNU MP Library test suite is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the License,
+# or (at your option) any later version.
+#
+# The GNU MP Library test suite is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/.
+
+srcdir=.
+MINI_GMP_DIR=..
+
+CC = gcc
+CFLAGS = -O -Wall -g
+CPPFLAGS =
+LDFLAGS =
+
+LIBS = -lgmp -lm -lmcheck
+
+CHECK_PROGRAMS = t-add t-sub t-mul t-invert t-div t-div_2exp \
+ t-double t-cmp_d t-gcd t-lcm t-import t-comb t-signed \
+ t-sqrt t-root t-powm t-logops t-bitops t-scan t-str \
+ t-reuse t-aorsmul t-limbs t-cong t-pprime_p t-lucm \
+ t-mpq_addsub t-mpq_muldiv t-mpq_muldiv_2exp t-mpq_str \
+ t-mpq_double
+# Default TESTS to all tests, allowing overriding TESTS for building tests
+# without running them.
+TESTS = $(CHECK_PROGRAMS)
+
+MISC_OBJS = hex-random.o mini-random.o testutils.o
+
+all:
+
+clean:
+ rm -f *.o $(CHECK_PROGRAMS)
+
+%: %.c
+.c:
+
+# Keep object files
+.PRECIOUS: %.o
+
+%.o: %.c $(MINI_GMP_DIR)/mini-gmp.h $(MINI_GMP_DIR)/mini-mpq.h hex-random.h mini-random.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+testutils.o: $(MINI_GMP_DIR)/mini-gmp.c $(MINI_GMP_DIR)/mini-mpq.c
+
+%: %.o $(MISC_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@
+
+# Missing tests include:
+# mpz_cmp_d, mpz_popcount, mpz_hamdist, mpz_ui_pow_ui
+
+check: $(CHECK_PROGRAMS)
+ $(srcdir)/run-tests $(TESTS)
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/hex-random.c b/vendor/gmp-6.3.0/mini-gmp/tests/hex-random.c
new file mode 100644
index 0000000..a5b405b
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/hex-random.c
@@ -0,0 +1,573 @@
+/*
+
+Copyright 2011, 2016, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <time.h>
+
+#ifdef __unix__
+# include <unistd.h>
+# include <sys/time.h>
+#endif
+
+#include "gmp.h"
+
+#include "hex-random.h"
+
+/* FIXME: gmp-impl.h included only for mpz_lucas_mod */
+/* #include "gmp-impl.h" */
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define mpz_lucas_mod __gmpz_lucas_mod
+__GMP_DECLSPEC int mpz_lucas_mod (mpz_ptr, mpz_ptr, long, mp_bitcnt_t, mpz_srcptr, mpz_ptr, mpz_ptr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+static gmp_randstate_t state;
+
+static void
+mkseed (mpz_t seed)
+{
+ FILE *f = fopen ("/dev/urandom", "rb");
+ if (f)
+ {
+ unsigned char buf[6];
+ size_t res;
+
+ setbuf (f, NULL);
+ res = fread (buf, sizeof(buf), 1, f);
+ fclose (f);
+
+ if (res == 1)
+ {
+ mpz_import (seed, sizeof(buf), 1, 1, 0, 0, buf);
+ return;
+ }
+ }
+
+#ifdef __unix__
+ {
+ struct timeval tv;
+ mpz_t usec;
+ mpz_init (usec);
+
+ gettimeofday (&tv, NULL);
+ mpz_set_ui (seed, tv.tv_sec);
+ mpz_set_ui (usec, tv.tv_usec);
+ /* usec fits in 20 bits, shift left to make it 48 bits. */
+ mpz_mul_2exp (usec, usec, 28);
+ mpz_xor (seed, seed, usec);
+
+ mpz_clear (usec);
+ }
+#else
+ mpz_set_ui (seed, time (NULL));
+#endif
+}
+
+void
+hex_random_init (void)
+{
+ mpz_t seed;
+ char *env_seed;
+
+ mpz_init (seed);
+
+ env_seed = getenv ("GMP_CHECK_RANDOMIZE");
+ if (env_seed && env_seed[0])
+ {
+ mpz_set_str (seed, env_seed, 0);
+ if (mpz_cmp_ui (seed, 0) != 0)
+ gmp_printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%Zd\n", seed);
+ else
+ {
+ mkseed (seed);
+ gmp_printf ("Seed GMP_CHECK_RANDOMIZE=%Zd (include this in bug reports)\n", seed);
+ }
+ fflush (stdout);
+ }
+ else
+ mpz_set_ui (seed, 4711);
+
+ gmp_randinit_default (state);
+ gmp_randseed (state, seed);
+
+ mpz_clear (seed);
+}
+
+char *
+hex_urandomb (unsigned long bits)
+{
+ char *res;
+ mpz_t x;
+
+ mpz_init (x);
+ mpz_urandomb (x, state, bits);
+ gmp_asprintf (&res, "%Zx", x);
+ mpz_clear (x);
+ return res;
+}
+
+char *
+hex_rrandomb (unsigned long bits)
+{
+ char *res;
+ mpz_t x;
+
+ mpz_init (x);
+ mpz_rrandomb (x, state, bits);
+ gmp_asprintf (&res, "%Zx", x);
+ mpz_clear (x);
+ return res;
+}
+
+char *
+hex_rrandomb_export (void *dst, size_t *countp,
+ int order, size_t size, int endian, unsigned long bits)
+{
+ char *res;
+ mpz_t x;
+ mpz_init (x);
+ mpz_rrandomb (x, state, bits);
+ gmp_asprintf (&res, "%Zx", x);
+ mpz_export (dst, countp, order, size, endian, 0, x);
+ mpz_clear (x);
+ return res;
+}
+
+void hex_random_op2 (enum hex_random_op op, unsigned long maxbits,
+ char **ap, char **rp)
+{
+ mpz_t a, r;
+ unsigned long abits;
+ unsigned signs;
+
+ mpz_init (a);
+ mpz_init (r);
+
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+
+ mpz_rrandomb (a, state, abits);
+
+ signs = gmp_urandomb_ui (state, 1);
+ if (signs & 1)
+ mpz_neg (a, a);
+
+ switch (op)
+ {
+ default:
+ abort ();
+ case OP_SQR:
+ mpz_mul (r, a, a);
+ break;
+ }
+
+ gmp_asprintf (ap, "%Zx", a);
+ gmp_asprintf (rp, "%Zx", r);
+
+ mpz_clear (a);
+ mpz_clear (r);
+}
+
+void
+hex_random_op3 (enum hex_random_op op, unsigned long maxbits,
+ char **ap, char **bp, char **rp)
+{
+ mpz_t a, b, r;
+ unsigned long abits, bbits;
+ unsigned signs;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (r);
+
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+ bbits = gmp_urandomb_ui (state, 32) % maxbits;
+
+ mpz_rrandomb (a, state, abits);
+ mpz_rrandomb (b, state, bbits);
+
+ signs = gmp_urandomb_ui (state, 3);
+ if (signs & 1)
+ mpz_neg (a, a);
+ if (signs & 2)
+ mpz_neg (b, b);
+
+ switch (op)
+ {
+ default:
+ abort ();
+ case OP_ADD:
+ mpz_add (r, a, b);
+ break;
+ case OP_SUB:
+ mpz_sub (r, a, b);
+ break;
+ case OP_MUL:
+ mpz_mul (r, a, b);
+ break;
+ case OP_GCD:
+ if (signs & 4)
+ {
+ /* Produce a large gcd */
+ unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
+ mpz_rrandomb (r, state, gbits);
+ mpz_mul (a, a, r);
+ mpz_mul (b, b, r);
+ }
+ mpz_gcd (r, a, b);
+ break;
+ case OP_LCM:
+ if (signs & 4)
+ {
+ /* Produce a large gcd */
+ unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
+ mpz_rrandomb (r, state, gbits);
+ mpz_mul (a, a, r);
+ mpz_mul (b, b, r);
+ }
+ mpz_lcm (r, a, b);
+ break;
+ case OP_AND:
+ mpz_and (r, a, b);
+ break;
+ case OP_IOR:
+ mpz_ior (r, a, b);
+ break;
+ case OP_XOR:
+ mpz_xor (r, a, b);
+ break;
+ }
+
+ gmp_asprintf (ap, "%Zx", a);
+ gmp_asprintf (bp, "%Zx", b);
+ gmp_asprintf (rp, "%Zx", r);
+
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (r);
+}
+
+void
+hex_random_op4 (enum hex_random_op op, unsigned long maxbits,
+ char **ap, char **bp, char **cp, char **dp)
+{
+ mpz_t a, b, c, d;
+ unsigned long abits, bbits;
+ unsigned signs;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (c);
+ mpz_init (d);
+
+ if (op == OP_POWM)
+ {
+ unsigned long cbits;
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+ bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
+ cbits = 2 + gmp_urandomb_ui (state, 32) % maxbits;
+
+ mpz_rrandomb (a, state, abits);
+ mpz_rrandomb (b, state, bbits);
+ mpz_rrandomb (c, state, cbits);
+
+ signs = gmp_urandomb_ui (state, 3);
+ if (signs & 1)
+ mpz_neg (a, a);
+ if (signs & 2)
+ {
+ mpz_t g;
+
+ /* If we negate the exponent, must make sure that gcd(a, c) = 1 */
+ if (mpz_sgn (a) == 0)
+ mpz_set_ui (a, 1);
+ else
+ {
+ mpz_init (g);
+
+ for (;;)
+ {
+ mpz_gcd (g, a, c);
+ if (mpz_cmp_ui (g, 1) == 0)
+ break;
+ mpz_divexact (a, a, g);
+ }
+ mpz_clear (g);
+ }
+ mpz_neg (b, b);
+ }
+ if (signs & 4)
+ mpz_neg (c, c);
+
+ mpz_powm (d, a, b, c);
+ }
+ else
+ {
+ unsigned long qbits;
+ bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
+ qbits = gmp_urandomb_ui (state, 32) % maxbits;
+ abits = bbits + qbits;
+ if (abits > 30)
+ abits -= 30;
+ else
+ abits = 0;
+
+ mpz_rrandomb (a, state, abits);
+ mpz_rrandomb (b, state, bbits);
+
+ signs = gmp_urandomb_ui (state, 2);
+ if (signs & 1)
+ mpz_neg (a, a);
+ if (signs & 2)
+ mpz_neg (b, b);
+
+ switch (op)
+ {
+ default:
+ abort ();
+ case OP_CDIV:
+ mpz_cdiv_qr (c, d, a, b);
+ break;
+ case OP_FDIV:
+ mpz_fdiv_qr (c, d, a, b);
+ break;
+ case OP_TDIV:
+ mpz_tdiv_qr (c, d, a, b);
+ break;
+ }
+ }
+ gmp_asprintf (ap, "%Zx", a);
+ gmp_asprintf (bp, "%Zx", b);
+ gmp_asprintf (cp, "%Zx", c);
+ gmp_asprintf (dp, "%Zx", d);
+
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (c);
+ mpz_clear (d);
+}
+
+void
+hex_random_bit_op (enum hex_random_op op, unsigned long maxbits,
+ char **ap, unsigned long *b, char **rp)
+{
+ mpz_t a, r;
+ unsigned long abits, bbits;
+ unsigned signs;
+
+ mpz_init (a);
+ mpz_init (r);
+
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+ bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
+
+ mpz_rrandomb (a, state, abits);
+
+ signs = gmp_urandomb_ui (state, 1);
+ if (signs & 1)
+ mpz_neg (a, a);
+
+ switch (op)
+ {
+ default:
+ abort ();
+
+ case OP_SETBIT:
+ mpz_set (r, a);
+ mpz_setbit (r, bbits);
+ break;
+ case OP_CLRBIT:
+ mpz_set (r, a);
+ mpz_clrbit (r, bbits);
+ break;
+ case OP_COMBIT:
+ mpz_set (r, a);
+ mpz_combit (r, bbits);
+ break;
+ case OP_CDIV_Q_2:
+ mpz_cdiv_q_2exp (r, a, bbits);
+ break;
+ case OP_CDIV_R_2:
+ mpz_cdiv_r_2exp (r, a, bbits);
+ break;
+ case OP_FDIV_Q_2:
+ mpz_fdiv_q_2exp (r, a, bbits);
+ break;
+ case OP_FDIV_R_2:
+ mpz_fdiv_r_2exp (r, a, bbits);
+ break;
+ case OP_TDIV_Q_2:
+ mpz_tdiv_q_2exp (r, a, bbits);
+ break;
+ case OP_TDIV_R_2:
+ mpz_tdiv_r_2exp (r, a, bbits);
+ break;
+ }
+
+ gmp_asprintf (ap, "%Zx", a);
+ *b = bbits;
+ gmp_asprintf (rp, "%Zx", r);
+
+ mpz_clear (a);
+ mpz_clear (r);
+}
+
+void
+hex_random_scan_op (enum hex_random_op op, unsigned long maxbits,
+ char **ap, unsigned long *b, unsigned long *r)
+{
+ mpz_t a;
+ unsigned long abits, bbits;
+ unsigned signs;
+
+ mpz_init (a);
+
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+ bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
+
+ mpz_rrandomb (a, state, abits);
+
+ signs = gmp_urandomb_ui (state, 1);
+ if (signs & 1)
+ mpz_neg (a, a);
+
+ switch (op)
+ {
+ default:
+ abort ();
+
+ case OP_SCAN0:
+ *r = mpz_scan0 (a, bbits);
+ break;
+ case OP_SCAN1:
+ *r = mpz_scan1 (a, bbits);
+ break;
+ }
+ gmp_asprintf (ap, "%Zx", a);
+ *b = bbits;
+
+ mpz_clear (a);
+}
+
+void
+hex_random_str_op (unsigned long maxbits,
+ int base, char **ap, char **rp)
+{
+ mpz_t a;
+ unsigned long abits;
+ unsigned signs;
+
+ mpz_init (a);
+
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+
+ mpz_rrandomb (a, state, abits);
+
+ signs = gmp_urandomb_ui (state, 2);
+ if (signs & 1)
+ mpz_neg (a, a);
+
+ *ap = mpz_get_str (NULL, 16, a);
+ *rp = mpz_get_str (NULL, base, a);
+
+ mpz_clear (a);
+}
+
+void hex_random_lucm_op (unsigned long maxbits,
+ char **vp, char **qp, char **mp,
+ long *Q, unsigned long *b0, int *res)
+{
+ mpz_t m, v, q, t1, t2;
+ unsigned long mbits;
+
+ mpz_init (m);
+ mpz_init (v);
+ mpz_init (q);
+ mpz_init (t1);
+ mpz_init (t2);
+
+ *Q = gmp_urandomb_ui (state, 14) + 1;
+
+ do
+ {
+ mbits = gmp_urandomb_ui (state, 32) % maxbits + 5;
+
+ mpz_rrandomb (m, state, mbits);
+ *b0 = gmp_urandomb_ui (state, 32) % (mbits - 3) + 2;
+ /* The GMP implementation uses the exponent (m >> b0) + 1. */
+ /* mini-gmp implementation uses the exponent (m >> b0) | 1. */
+ /* They are the same (and are used) only when (m >> b0) is even */
+ mpz_clrbit (m, *b0);
+ /* mini-gmp implementation only works if the modulus is odd. */
+ mpz_setbit (m, 0);
+ }
+ while (mpz_gcd_ui (NULL, m, *Q) != 1);
+
+ if (*Q == 1 || gmp_urandomb_ui (state, 1))
+ *Q = - *Q;
+
+#if (__GNU_MP_VERSION == 6 && (__GNU_MP_VERSION_MINOR > 1 || __GNU_MP_VERSION_PATCHLEVEL > 9))
+ *res = mpz_lucas_mod (v, q, *Q, *b0, m, t1, t2);
+#else
+ *b0 = 0;
+#endif
+
+ gmp_asprintf (vp, "%Zx", v);
+ gmp_asprintf (qp, "%Zx", q);
+ gmp_asprintf (mp, "%Zx", m);
+
+ mpz_clear (m);
+ mpz_clear (v);
+ mpz_clear (q);
+ mpz_clear (t1);
+ mpz_clear (t2);
+}
+
+void
+hex_mpq_random_str_op (unsigned long maxbits,
+ int base, char **ap, char **rp)
+{
+ mpq_t a;
+ unsigned long abits;
+ unsigned signs;
+
+ mpq_init (a);
+
+ abits = gmp_urandomb_ui (state, 32) % maxbits;
+
+ mpz_rrandomb (mpq_numref (a), state, abits);
+ mpz_rrandomb (mpq_denref (a), state, abits);
+ mpz_add_ui (mpq_denref (a), mpq_denref (a), 1);
+
+ mpq_canonicalize (a);
+ signs = gmp_urandomb_ui (state, 2);
+ if (signs & 1)
+ mpq_neg (a, a);
+
+ *ap = mpq_get_str (NULL, 16, a);
+ *rp = mpq_get_str (NULL, base, a);
+
+ mpq_clear (a);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/hex-random.h b/vendor/gmp-6.3.0/mini-gmp/tests/hex-random.h
new file mode 100644
index 0000000..da44347
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/hex-random.h
@@ -0,0 +1,55 @@
+/*
+
+Copyright 2011, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+enum hex_random_op
+ {
+ OP_ADD, OP_SUB, OP_MUL, OP_SQR,
+ OP_CDIV, OP_FDIV, OP_TDIV,
+ OP_CDIV_Q_2, OP_CDIV_R_2,
+ OP_FDIV_Q_2, OP_FDIV_R_2,
+ OP_TDIV_Q_2, OP_TDIV_R_2,
+ OP_GCD, OP_LCM, OP_POWM, OP_AND, OP_IOR, OP_XOR,
+ OP_SETBIT, OP_CLRBIT, OP_COMBIT,
+ OP_SCAN0, OP_SCAN1,
+ };
+
+void hex_random_init (void);
+char *hex_urandomb (unsigned long bits);
+char *hex_rrandomb (unsigned long bits);
+char *hex_rrandomb_export (void *dst, size_t *countp,
+ int order, size_t size, int endian,
+ unsigned long bits);
+
+void hex_random_op2 (enum hex_random_op op, unsigned long maxbits,
+ char **ap, char **rp);
+void hex_random_op3 (enum hex_random_op op, unsigned long maxbits,
+ char **ap, char **bp, char **rp);
+void hex_random_op4 (enum hex_random_op op, unsigned long maxbits,
+ char **ap, char **bp, char **rp, char **qp);
+void hex_random_bit_op (enum hex_random_op op, unsigned long maxbits,
+ char **ap, unsigned long *b, char **rp);
+void hex_random_scan_op (enum hex_random_op op, unsigned long maxbits,
+ char **ap, unsigned long *b, unsigned long *r);
+void hex_random_str_op (unsigned long maxbits,
+ int base, char **ap, char **rp);
+void hex_random_lucm_op (unsigned long maxbits,
+ char **vp, char **qp, char **mp,
+ long *Q, unsigned long *b0, int *res);
+void hex_mpq_random_str_op (unsigned long maxbits,
+ int base, char **ap, char **rp);
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/mini-random.c b/vendor/gmp-6.3.0/mini-gmp/tests/mini-random.c
new file mode 100644
index 0000000..7504af3
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/mini-random.c
@@ -0,0 +1,160 @@
+/*
+
+Copyright 2011, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mini-random.h"
+
+static void
+set_str (mpz_t r, const char *s)
+{
+ if (mpz_set_str (r, s, 16) != 0)
+ {
+ fprintf (stderr, "mpz_set_str failed on input %s\n", s);
+ abort ();
+ }
+}
+
+void
+mini_urandomb (mpz_t r, unsigned long bits)
+{
+ char *s;
+ s = hex_urandomb (bits);
+ set_str (r, s);
+ free (s);
+}
+
+void
+mini_rrandomb (mpz_t r, unsigned long bits)
+{
+ char *s;
+ s = hex_rrandomb (bits);
+ set_str (r, s);
+ free (s);
+}
+
+void
+mini_rrandomb_export (mpz_t r, void *dst, size_t *countp,
+ int order, size_t size, int endian, unsigned long bits)
+{
+ char *s;
+ s = hex_rrandomb_export (dst, countp, order, size, endian, bits);
+ set_str (r, s);
+ free (s);
+}
+
+void
+mini_random_op2 (enum hex_random_op op, unsigned long maxbits,
+ mpz_t a, mpz_t r)
+{
+ char *ap;
+ char *rp;
+
+ hex_random_op2 (op, maxbits, &ap, &rp);
+ set_str (a, ap);
+ set_str (r, rp);
+
+ free (ap);
+ free (rp);
+}
+
+void
+mini_random_op3 (enum hex_random_op op, unsigned long maxbits,
+ mpz_t a, mpz_t b, mpz_t r)
+{
+ char *ap;
+ char *bp;
+ char *rp;
+
+ hex_random_op3 (op, maxbits, &ap, &bp, &rp);
+ set_str (a, ap);
+ set_str (b, bp);
+ set_str (r, rp);
+
+ free (ap);
+ free (bp);
+ free (rp);
+}
+
+void
+mini_random_op4 (enum hex_random_op op, unsigned long maxbits,
+ mpz_t a, mpz_t b, mpz_t c, mpz_t d)
+{
+ char *ap;
+ char *bp;
+ char *cp;
+ char *dp;
+
+ hex_random_op4 (op, maxbits, &ap, &bp, &cp, &dp);
+ set_str (a, ap);
+ set_str (b, bp);
+ set_str (c, cp);
+ set_str (d, dp);
+
+ free (ap);
+ free (bp);
+ free (cp);
+ free (dp);
+}
+
+void
+mini_random_bit_op (enum hex_random_op op, unsigned long maxbits,
+ mpz_t a, mp_bitcnt_t *b, mpz_t r)
+{
+ char *ap;
+ char *rp;
+
+ hex_random_bit_op (op, maxbits, &ap, b, &rp);
+ set_str (a, ap);
+ set_str (r, rp);
+
+ free (ap);
+ free (rp);
+}
+
+void
+mini_random_scan_op (enum hex_random_op op, unsigned long maxbits,
+ mpz_t a, mp_bitcnt_t *b, mp_bitcnt_t *r)
+{
+ char *ap;
+
+ hex_random_scan_op (op, maxbits, &ap, b, r);
+ set_str (a, ap);
+
+ free (ap);
+}
+
+void
+mini_random_lucm_op (unsigned long maxbits, mpz_t v, mpz_t q, mpz_t m,
+ long *Q, unsigned long *b0, int *res)
+{
+ char *vp;
+ char *qp;
+ char *mp;
+
+ hex_random_lucm_op (maxbits, &vp, &qp, &mp, Q, b0, res);
+ set_str (v, vp);
+ set_str (q, qp);
+ set_str (m, mp);
+
+ free (vp);
+ free (qp);
+ free (mp);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/mini-random.h b/vendor/gmp-6.3.0/mini-gmp/tests/mini-random.h
new file mode 100644
index 0000000..2f54749
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/mini-random.h
@@ -0,0 +1,35 @@
+/*
+
+Copyright 2011, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include "../mini-gmp.h"
+#include "hex-random.h"
+
+void mini_urandomb (mpz_t, unsigned long);
+void mini_rrandomb (mpz_t, unsigned long);
+void mini_rrandomb_export (mpz_t r, void *dst, size_t *countp,
+ int order, size_t size, int endian,
+ unsigned long bits);
+
+void mini_random_op2 (enum hex_random_op, unsigned long, mpz_t, mpz_t);
+void mini_random_op3 (enum hex_random_op, unsigned long, mpz_t, mpz_t, mpz_t);
+void mini_random_op4 (enum hex_random_op, unsigned long, mpz_t, mpz_t, mpz_t, mpz_t);
+void mini_random_scan_op (enum hex_random_op, unsigned long, mpz_t, mp_bitcnt_t *, mp_bitcnt_t *);
+void mini_random_bit_op (enum hex_random_op, unsigned long, mpz_t, mp_bitcnt_t *, mpz_t);
+void mini_random_lucm_op (unsigned long, mpz_t, mpz_t, mpz_t,
+ long *, unsigned long *, int *);
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/run-tests b/vendor/gmp-6.3.0/mini-gmp/tests/run-tests
new file mode 100755
index 0000000..3ebc4ae
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/run-tests
@@ -0,0 +1,143 @@
+#! /bin/sh
+
+# Copyright (C) 2000-2002, 2004, 2005, 2011, 2012, 2016, 2020 Niels Möller
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+failed=0
+all=0
+
+debug='no'
+testflags=''
+
+if [ -z "$srcdir" ] ; then
+ srcdir=`pwd`
+fi
+
+export srcdir
+
+if [ -n "$TEST_SHLIB_DIR" ] ; then
+ # Prepend to LD_LIBRARY_PATH, if it is alredy set.
+ LD_LIBRARY_PATH="${TEST_SHLIB_DIR}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+ # For MACOS
+ DYLD_LIBRARY_PATH="$TEST_SHLIB_DIR"
+ # For Windows
+ PATH="${TEST_SHLIB_DIR}:${PATH}"
+ # For Wine
+ WINEPATH="${TEST_SHLIB_DIR}${WINEPATH:+;$WINEPATH}"
+
+ export LD_LIBRARY_PATH
+ export DYLD_LIBRARY_PATH
+ export PATH
+ export WINEPATH
+fi
+
+# When used in make rules, we sometimes get the filenames VPATH
+# expanded, but usually not.
+find_program () {
+ case "$1" in
+ */*)
+ echo "$1"
+ ;;
+ *)
+ if [ -x "$1" ] ; then
+ echo "./$1"
+ elif [ -x "$1.exe" ] ; then
+ echo "./$1.exe"
+ else
+ echo "$srcdir/$1"
+ fi
+ ;;
+ esac
+}
+
+env_program () {
+ if [ -x "$1" ] ; then
+ if "$1"; then : ; else
+ echo FAIL: $1
+ exit 1
+ fi
+ fi
+}
+
+test_program () {
+ testname=`basename "$1" .exe`
+ testname=`basename "$testname" -test`
+ if [ -z "$EMULATOR" ] || head -1 "$1" | grep '^#!' > /dev/null; then
+ "$1" $testflags
+ else
+ $EMULATOR "$1" $testflags
+ fi
+ case "$?" in
+ 0)
+ echo PASS: $testname
+ all=`expr $all + 1`
+ ;;
+ 77)
+ echo SKIP: $testname
+ ;;
+ *)
+ echo FAIL: $testname
+ failed=`expr $failed + 1`
+ all=`expr $all + 1`
+ ;;
+ esac
+}
+
+env_program `find_program setup-env`
+
+while test $# != 0
+do
+ case "$1" in
+ --debug)
+ debug=yes
+ ;;
+ -v)
+ testflags='-v'
+ ;;
+ -*)
+ echo >&2 'Unknown option `'"$1'"
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+# Comment out special handling for zero arguments to support separate
+# tests-build/tests-run.
+#if [ $# -eq 0 ] ; then
+# for f in *-test; do test_program "./$f"; done
+#else
+ for f in "$@" ; do test_program `find_program "$f"`; done
+#fi
+
+if [ $failed -eq 0 ] ; then
+ banner="All $all tests passed"
+else
+ banner="$failed of $all tests failed"
+fi
+dashes=`echo "$banner" | sed s/./=/g`
+echo "$dashes"
+echo "$banner"
+echo "$dashes"
+
+if [ "x$debug" = xno ] ; then
+ env_program `find_program teardown-env`
+fi
+
+[ "$failed" -eq 0 ]
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-add.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-add.c
new file mode 100644
index 0000000..0a093ef
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-add.c
@@ -0,0 +1,57 @@
+/*
+
+Copyright 2012, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, res, ref;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (res);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_ADD, MAXBITS, a, b, ref);
+ mpz_add (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_add failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-aorsmul.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-aorsmul.c
new file mode 100644
index 0000000..eb275a8
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-aorsmul.c
@@ -0,0 +1,77 @@
+/*
+
+Copyright 2012, 2014, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+#define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, res, ref;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init_set_ui (res, 5);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_MUL, MAXBITS, a, b, ref);
+ if (i & 1) {
+ mpz_add (ref, ref, res);
+ if (mpz_fits_ulong_p (b))
+ mpz_addmul_ui (res, a, mpz_get_ui (b));
+ else
+ mpz_addmul (res, a, b);
+ } else {
+ mpz_sub (ref, res, ref);
+ if (mpz_fits_ulong_p (b))
+ mpz_submul_ui (res, a, mpz_get_ui (b));
+ else
+ mpz_submul (res, a, b);
+ }
+ if (mpz_cmp (res, ref))
+ {
+ if (i & 1)
+ fprintf (stderr, "mpz_addmul failed:\n");
+ else
+ fprintf (stderr, "mpz_submul failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-bitops.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-bitops.c
new file mode 100644
index 0000000..27d87ca
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-bitops.c
@@ -0,0 +1,104 @@
+/*
+
+Copyright 2012, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, res, ref;
+ mp_bitcnt_t b;
+
+ mpz_init (a);
+ mpz_init (res);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_bit_op (OP_SETBIT, MAXBITS, a, &b, ref);
+ mpz_set (res, a);
+ mpz_setbit (res, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_setbit failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ if (!mpz_tstbit (res, b))
+ {
+ fprintf (stderr, "mpz_tstbit failed (after mpz_setbit):\n");
+ dump ("res", a);
+ fprintf (stderr, "b: %lu\n", b);
+ abort ();
+ }
+ mini_random_bit_op (OP_CLRBIT, MAXBITS, a, &b, ref);
+ mpz_set (res, a);
+ mpz_clrbit (res, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_clrbit failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ if (mpz_tstbit (res, b))
+ {
+ fprintf (stderr, "mpz_tstbit failed (after mpz_clrbit):\n");
+ dump ("res", a);
+ fprintf (stderr, "b: %lu\n", b);
+ abort ();
+ }
+ mini_random_bit_op (OP_COMBIT, MAXBITS, a, &b, ref);
+ mpz_set (res, a);
+ mpz_com (a, a);
+ mpz_combit (res, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_combit failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ if (mpz_tstbit (res, b) != mpz_tstbit (a, b))
+ {
+ fprintf (stderr, "mpz_tstbit failed (after mpz_combit):\n");
+ dump ("res", a);
+ fprintf (stderr, "b: %lu\n", b);
+ abort ();
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-cmp_d.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-cmp_d.c
new file mode 100644
index 0000000..09ca810
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-cmp_d.c
@@ -0,0 +1,283 @@
+/* Test mpz_cmp_d and mpz_cmpabs_d.
+
+Copyright 2001-2003, 2005, 2013 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <math.h>
+
+#include "testutils.h"
+
+/* FIXME: Not sure if the tests here are exhaustive. Ought to try to get
+ each possible exit from mpz_cmp_d (and mpz_cmpabs_d) exercised. */
+
+
+#define SGN(n) ((n) > 0 ? 1 : (n) < 0 ? -1 : 0)
+
+
+void
+check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
+{
+ int got;
+
+ got = mpz_cmp_d (x, y);
+ if (SGN(got) != cmp)
+ {
+ unsigned i;
+ printf ("mpz_cmp_d wrong (from %s)\n", name);
+ printf (" got %d\n", got);
+ printf (" want %d\n", cmp);
+ fail:
+ printf (" x=");
+ mpz_out_str (stdout, 10, x);
+ printf ("\n y %g\n", y);
+ printf (" x=0x");
+ mpz_out_str (stdout, -16, x);
+ printf ("\n y %g\n", y);
+ printf (" y");
+ for (i = 0; i < sizeof(y); i++)
+ printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
+ printf ("\n");
+ abort ();
+ }
+
+ got = mpz_cmpabs_d (x, y);
+ if (SGN(got) != cmpabs)
+ {
+ printf ("mpz_cmpabs_d wrong\n");
+ printf (" got %d\n", got);
+ printf (" want %d\n", cmpabs);
+ goto fail;
+ }
+}
+
+void
+check_data (void)
+{
+ static const struct {
+ const char *x;
+ double y;
+ int cmp, cmpabs;
+
+ } data[] = {
+
+ { "0", 0.0, 0, 0 },
+
+ { "1", 0.0, 1, 1 },
+ { "-1", 0.0, -1, 1 },
+
+ { "1", 0.5, 1, 1 },
+ { "-1", -0.5, -1, 1 },
+
+ { "0", 1.0, -1, -1 },
+ { "0", -1.0, 1, -1 },
+
+ { "0x1000000000000000000000000000000000000000000000000", 1.0, 1, 1 },
+ { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
+
+ { "0", 1e100, -1, -1 },
+ { "0", -1e100, 1, -1 },
+
+ { "2", 1.5, 1, 1 },
+ { "2", -1.5, 1, 1 },
+ { "-2", 1.5, -1, 1 },
+ { "-2", -1.5, -1, 1 },
+ };
+
+ mpz_t x;
+ unsigned i;
+
+ mpz_init (x);
+
+ for (i = 0; i < numberof (data); i++)
+ {
+ mpz_set_str_or_abort (x, data[i].x, 0);
+ check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
+ }
+
+ mpz_clear (x);
+}
+
+
+/* Equality of integers with up to 53 bits */
+void
+check_onebits (void)
+{
+ mpz_t x, x2;
+ double y;
+ int i;
+
+ mpz_init_set_ui (x, 0L);
+ mpz_init (x2);
+
+ for (i = 0; i < 512; i++)
+ {
+ mpz_mul_2exp (x, x, 1);
+ mpz_add_ui (x, x, 1L);
+
+ y = mpz_get_d (x);
+ mpz_set_d (x2, y);
+
+ /* stop if any truncation is occurring */
+ if (mpz_cmp (x, x2) != 0)
+ break;
+
+ check_one ("check_onebits", x, y, 0, 0);
+ check_one ("check_onebits", x, -y, 1, 0);
+ mpz_neg (x, x);
+ check_one ("check_onebits", x, y, -1, 0);
+ check_one ("check_onebits", x, -y, 0, 0);
+ mpz_neg (x, x);
+ }
+
+ mpz_clear (x);
+ mpz_clear (x2);
+}
+
+
+/* With the mpz differing by 1, in a limb position possibly below the double */
+void
+check_low_z_one (void)
+{
+ mpz_t x;
+ double y;
+ unsigned long i;
+
+ mpz_init (x);
+
+ /* FIXME: It'd be better to base this on the float format. */
+#if defined (__vax) || defined (__vax__)
+#define LIM 127 /* vax fp numbers have limited range */
+#else
+#define LIM 512
+#endif
+
+ for (i = 1; i < LIM; i++)
+ {
+ mpz_set_ui (x, 1L);
+ mpz_mul_2exp (x, x, i);
+ y = mpz_get_d (x);
+
+ check_one ("check_low_z_one", x, y, 0, 0);
+ check_one ("check_low_z_one", x, -y, 1, 0);
+ mpz_neg (x, x);
+ check_one ("check_low_z_one", x, y, -1, 0);
+ check_one ("check_low_z_one", x, -y, 0, 0);
+ mpz_neg (x, x);
+
+ mpz_sub_ui (x, x, 1);
+
+ check_one ("check_low_z_one", x, y, -1, -1);
+ check_one ("check_low_z_one", x, -y, 1, -1);
+ mpz_neg (x, x);
+ check_one ("check_low_z_one", x, y, -1, -1);
+ check_one ("check_low_z_one", x, -y, 1, -1);
+ mpz_neg (x, x);
+
+ mpz_add_ui (x, x, 2);
+
+ check_one ("check_low_z_one", x, y, 1, 1);
+ check_one ("check_low_z_one", x, -y, 1, 1);
+ mpz_neg (x, x);
+ check_one ("check_low_z_one", x, y, -1, 1);
+ check_one ("check_low_z_one", x, -y, -1, 1);
+ mpz_neg (x, x);
+ }
+
+ mpz_clear (x);
+}
+
+/* Comparing 1 and 1+2^-n. "y" is volatile to make gcc store and fetch it,
+ which forces it to a 64-bit double, whereas on x86 it would otherwise
+ remain on the float stack as an 80-bit long double. */
+void
+check_one_2exp (void)
+{
+ double e;
+ mpz_t x;
+ volatile double y;
+ int i;
+
+ mpz_init (x);
+
+ e = 1.0;
+ for (i = 0; i < 128; i++)
+ {
+ e /= 2.0;
+ y = 1.0 + e;
+ if (y == 1.0)
+ break;
+
+ mpz_set_ui (x, 1L);
+ check_one ("check_one_2exp", x, y, -1, -1);
+ check_one ("check_one_2exp", x, -y, 1, -1);
+
+ mpz_set_si (x, -1L);
+ check_one ("check_one_2exp", x, y, -1, -1);
+ check_one ("check_one_2exp", x, -y, 1, -1);
+ }
+
+ mpz_clear (x);
+}
+
+void
+check_infinity (void)
+{
+ mpz_t x;
+ double y = HUGE_VAL;
+ if (y != 2*y)
+ return;
+
+ mpz_init (x);
+
+ /* 0 cmp inf */
+ mpz_set_ui (x, 0L);
+ check_one ("check_infinity", x, y, -1, -1);
+ check_one ("check_infinity", x, -y, 1, -1);
+
+ /* 123 cmp inf */
+ mpz_set_ui (x, 123L);
+ check_one ("check_infinity", x, y, -1, -1);
+ check_one ("check_infinity", x, -y, 1, -1);
+
+ /* -123 cmp inf */
+ mpz_set_si (x, -123L);
+ check_one ("check_infinity", x, y, -1, -1);
+ check_one ("check_infinity", x, -y, 1, -1);
+
+ /* 2^5000 cmp inf */
+ mpz_set_ui (x, 1L);
+ mpz_mul_2exp (x, x, 5000L);
+ check_one ("check_infinity", x, y, -1, -1);
+ check_one ("check_infinity", x, -y, 1, -1);
+
+ /* -2^5000 cmp inf */
+ mpz_neg (x, x);
+ check_one ("check_infinity", x, y, -1, -1);
+ check_one ("check_infinity", x, -y, 1, -1);
+
+ mpz_clear (x);
+}
+
+void
+testmain (int argc, char *argv[])
+{
+ check_data ();
+ check_onebits ();
+ check_low_z_one ();
+ check_one_2exp ();
+ check_infinity ();
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-comb.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-comb.c
new file mode 100644
index 0000000..652bfcb
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-comb.c
@@ -0,0 +1,175 @@
+/* Exercise mpz_fac_ui and mpz_bin_uiui.
+
+Copyright 2000-2002, 2012, 2013, 2017-2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testutils.h"
+
+/* Usage: t-fac_ui [x|num]
+
+ With no arguments testing goes up to the initial value of "limit" below.
+ With a number argument tests are carried that far, or with a literal "x"
+ tests are continued without limit (this being meant only for development
+ purposes). */
+
+void
+try_mpz_bin_uiui (mpz_srcptr want, unsigned long n, unsigned long k)
+{
+ mpz_t got;
+
+ mpz_init (got);
+ mpz_bin_uiui (got, n, k);
+ if (mpz_cmp (got, want) != 0)
+ {
+ printf ("mpz_bin_uiui wrong\n");
+ printf (" n=%lu\n", n);
+ printf (" k=%lu\n", k);
+ printf (" got="); mpz_out_str (stdout, 10, got); printf ("\n");
+ printf (" want="); mpz_out_str (stdout, 10, want); printf ("\n");
+ abort();
+ }
+ mpz_clear (got);
+}
+
+/* Test all bin(n,k) cases, with 0 <= k <= n + 1 <= count. */
+void
+bin_smallexaustive (unsigned int count)
+{
+ mpz_t want;
+ unsigned long n, k;
+
+ mpz_init (want);
+
+ for (n = 0; n < count; n++)
+ {
+ mpz_set_ui (want, 1);
+ for (k = 0; k <= n; k++)
+ {
+ try_mpz_bin_uiui (want, n, k);
+ mpz_mul_ui (want, want, n - k);
+ mpz_fdiv_q_ui (want, want, k + 1);
+ }
+ try_mpz_bin_uiui (want, n, k);
+ }
+
+ mpz_clear (want);
+}
+
+/* Test all fac(n) cases, with 0 <= n <= limit. */
+void
+fac_smallexaustive (unsigned int limit)
+{
+ mpz_t f, r;
+ unsigned long n;
+ mpz_init_set_si (f, 1); /* 0! = 1 */
+ mpz_init (r);
+
+ for (n = 0; n < limit; n++)
+ {
+ mpz_fac_ui (r, n);
+
+ if (mpz_cmp (f, r) != 0)
+ {
+ printf ("mpz_fac_ui(%lu) wrong\n", n);
+ printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
+ printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
+ abort ();
+ }
+
+ mpz_mul_ui (f, f, n+1); /* (n+1)! = n! * (n+1) */
+ }
+
+ mpz_clear (f);
+ mpz_clear (r);
+}
+
+void checkWilson (mpz_t f, unsigned long n)
+{
+ unsigned long m, a;
+
+ mpz_2fac_ui (f, 2 * n - 1);
+
+ a = mpz_fdiv_q_ui (f, f, n);
+ m = mpz_fdiv_ui (f, n);
+ if ((m != n - 1) || (a != 0))
+ {
+ printf ("mpz_2fac_ui(%lu) wrong\n", 2 * n - 1);
+ printf (" Wilson's theorem not verified: got (%lu, %lu), expected (0, %lu).\n", a, m, n - 1);
+ abort ();
+ }
+
+ mpz_fac_ui (f, n - 1);
+ m = mpz_fdiv_ui (f, n);
+ if ( m != n - 1)
+ {
+ printf ("mpz_fac_ui(%lu) wrong\n", n - 1);
+ printf (" Wilson's theorem not verified: got %lu, expected %lu.\n",m ,n - 1);
+ abort ();
+ }
+}
+
+void
+checkprimes (unsigned long p1, unsigned long p2, unsigned long p3)
+{
+ mpz_t b, f;
+
+ if (p1 - 1 != p2 - 1 + p3 - 1)
+ {
+ printf ("checkprimes(%lu, %lu, %lu) wrong\n", p1, p2, p3);
+ printf (" %lu - 1 != %lu - 1 + %lu - 1 \n", p1, p2, p3);
+ abort ();
+ }
+
+ mpz_init (b);
+ mpz_init (f);
+
+ checkWilson (b, p1); /* b = (p1-1)! */
+ checkWilson (f, p2); /* f = (p2-1)! */
+ mpz_divexact (b, b, f);
+ checkWilson (f, p3); /* f = (p3-1)! */
+ mpz_divexact (b, b, f); /* b = (p1-1)!/((p2-1)!(p3-1)!) */
+ mpz_bin_uiui (f, p1 - 1, p2 - 1);
+ if (mpz_cmp (f, b) != 0)
+ {
+ printf ("checkprimes(%lu, %lu, %lu) wrong\n", p1, p2, p3);
+ printf (" got "); mpz_out_str (stdout, 10, b); printf("\n");
+ printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
+ abort ();
+ }
+
+ mpz_clear (b);
+ mpz_clear (f);
+
+}
+
+void
+testmain (int argc, char *argv[])
+{
+ unsigned long limit = 128;
+
+ if (argc > 1 && argv[1][0] == 'x')
+ limit = ~ limit;
+ else if (argc > 1)
+ limit = atoi (argv[1]);
+
+ checkprimes(1009, 733, 277);
+ fac_smallexaustive (limit);
+ bin_smallexaustive (limit);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-cong.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-cong.c
new file mode 100644
index 0000000..92b6930
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-cong.c
@@ -0,0 +1,212 @@
+/* test mpz_congruent_p
+
+Copyright 2001, 2002, 2012, 2014 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include "testutils.h"
+
+#define MPZ_SRCPTR_SWAP(x, y) \
+ do { \
+ mpz_srcptr __mpz_srcptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mpz_srcptr_swap__tmp; \
+ } while (0)
+
+void
+check_one (mpz_srcptr a, mpz_srcptr c, mpz_srcptr d, int want)
+{
+ int got;
+ int swap;
+
+ for (swap = 0; swap <= 1; swap++)
+ {
+ got = (mpz_congruent_p (a, c, d) != 0);
+ if (want != got)
+ {
+ printf ("mpz_congruent_p wrong\n");
+ printf (" expected %d got %d\n", want, got);
+ dump (" a", a);
+ dump (" c", c);
+ dump (" d", d);
+ abort ();
+ }
+
+#if 0
+ if (mpz_fits_ulong_p (c) && mpz_fits_ulong_p (d))
+ {
+ unsigned long uc = mpz_get_ui (c);
+ unsigned long ud = mpz_get_ui (d);
+ got = (mpz_congruent_ui_p (a, uc, ud) != 0);
+ if (want != got)
+ {
+ printf ("mpz_congruent_ui_p wrong\n");
+ printf (" expected %d got %d\n", want, got);
+ dump (" a", a);
+ printf (" c=%lu\n", uc);
+ printf (" d=%lu\n", ud);
+ abort ();
+ }
+ }
+#endif
+ MPZ_SRCPTR_SWAP (a, c);
+ }
+}
+
+
+void
+check_data (void)
+{
+ static const struct {
+ const char *a;
+ const char *c;
+ const char *d;
+ int want;
+
+ } data[] = {
+
+ /* strict equality mod 0 */
+ { "0", "0", "0", 1 },
+ { "11", "11", "0", 1 },
+ { "3", "11", "0", 0 },
+
+ /* anything congruent mod 1 */
+ { "0", "0", "1", 1 },
+ { "1", "0", "1", 1 },
+ { "0", "1", "1", 1 },
+ { "123", "456", "1", 1 },
+ { "0x123456789123456789", "0x987654321987654321", "1", 1 },
+
+ /* csize==1, dsize==2 changing to 1 after stripping 2s */
+ { "0x3333333333333333", "0x33333333",
+ "0x180000000", 1 },
+ { "0x33333333333333333333333333333333", "0x3333333333333333",
+ "0x18000000000000000", 1 },
+
+ /* another dsize==2 becoming 1, with opposite signs this time */
+ { "0x444444441",
+ "-0x22222221F",
+ "0x333333330", 1 },
+ { "0x44444444444444441",
+ "-0x2222222222222221F",
+ "0x33333333333333330", 1 },
+ };
+
+ mpz_t a, c, d;
+ unsigned i;
+
+ mpz_init (a);
+ mpz_init (c);
+ mpz_init (d);
+
+ for (i = 0; i < numberof (data); i++)
+ {
+ mpz_set_str_or_abort (a, data[i].a, 0);
+ mpz_set_str_or_abort (c, data[i].c, 0);
+ mpz_set_str_or_abort (d, data[i].d, 0);
+ check_one (a, c, d, data[i].want);
+ }
+
+ mpz_clear (a);
+ mpz_clear (c);
+ mpz_clear (d);
+}
+
+
+void
+check_random (int argc, char *argv[])
+{
+ mpz_t a, c, d, ra, rc;
+ int i;
+ int want;
+ int reps = 10000;
+ mpz_t bs;
+ unsigned long size_range, size;
+
+ if (argc >= 2)
+ reps = atoi (argv[1]);
+
+ mpz_init (bs);
+
+ mpz_init (a);
+ mpz_init (c);
+ mpz_init (d);
+ mpz_init (ra);
+ mpz_init (rc);
+
+ for (i = 0; i < reps; i++)
+ {
+ mini_urandomb (bs, 32);
+ size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (a, size);
+
+ mini_urandomb (bs, 32);
+ size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (c, size);
+
+ do
+ {
+ mini_urandomb (bs, 32);
+ size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (d, size);
+ }
+ while (mpz_sgn(d) == 0);
+
+ mini_urandomb (bs, 3);
+ if (mpz_tstbit (bs, 0))
+ mpz_neg (a, a);
+ if (mpz_tstbit (bs, 1))
+ mpz_neg (c, c);
+ if (mpz_tstbit (bs, 2))
+ mpz_neg (d, d);
+
+ mpz_fdiv_r (ra, a, d);
+ mpz_fdiv_r (rc, c, d);
+
+ want = (mpz_cmp (ra, rc) == 0);
+ check_one (a, c, d, want);
+
+ mpz_sub (ra, ra, rc);
+ mpz_sub (a, a, ra);
+ check_one (a, c, d, 1);
+
+ }
+
+ mpz_clear (bs);
+
+ mpz_clear (a);
+ mpz_clear (c);
+ mpz_clear (d);
+ mpz_clear (ra);
+ mpz_clear (rc);
+}
+
+
+void
+testmain (int argc, char *argv[])
+{
+ check_data ();
+ check_random (argc, argv);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-div.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-div.c
new file mode 100644
index 0000000..be2f6b1
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-div.c
@@ -0,0 +1,258 @@
+/*
+
+Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+typedef void div_qr_func (mpz_t, mpz_t, const mpz_t, const mpz_t);
+typedef unsigned long div_qr_ui_func (mpz_t, mpz_t, const mpz_t, unsigned long);
+typedef void div_func (mpz_t, const mpz_t, const mpz_t);
+typedef unsigned long div_x_ui_func (mpz_t, const mpz_t, unsigned long);
+typedef unsigned long div_ui_func (const mpz_t, unsigned long);
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, q, r, rq, rr;
+ int div_p;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (r);
+ mpz_init (q);
+ mpz_init (rr);
+ mpz_init (rq);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ unsigned j;
+ for (j = 0; j < 3; j++)
+ {
+ static const enum hex_random_op ops[3] = { OP_CDIV, OP_FDIV, OP_TDIV };
+ static const char name[3] = { 'c', 'f', 't'};
+ static div_qr_func * const div_qr [3] =
+ {
+ mpz_cdiv_qr, mpz_fdiv_qr, mpz_tdiv_qr
+ };
+ static div_qr_ui_func * const div_qr_ui[3] =
+ {
+ mpz_cdiv_qr_ui, mpz_fdiv_qr_ui, mpz_tdiv_qr_ui
+ };
+ static div_func * const div_q [3] =
+ {
+ mpz_cdiv_q, mpz_fdiv_q, mpz_tdiv_q
+ };
+ static div_x_ui_func * const div_q_ui[3] =
+ {
+ mpz_cdiv_q_ui, mpz_fdiv_q_ui, mpz_tdiv_q_ui
+ };
+ static div_func * const div_r [3] =
+ {
+ mpz_cdiv_r, mpz_fdiv_r, mpz_tdiv_r
+ };
+ static div_x_ui_func * const div_r_ui[3] =
+ {
+ mpz_cdiv_r_ui, mpz_fdiv_r_ui, mpz_tdiv_r_ui
+ };
+ static div_ui_func * const div_ui[3] =
+ {
+ mpz_cdiv_ui, mpz_fdiv_ui, mpz_tdiv_ui
+ };
+
+ mini_random_op4 (ops[j], MAXBITS, a, b, rq, rr);
+ div_qr[j] (q, r, a, b);
+ if (mpz_cmp (r, rr) || mpz_cmp (q, rq))
+ {
+ fprintf (stderr, "mpz_%cdiv_qr failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ dump ("rref", rr);
+ dump ("q ", q);
+ dump ("qref", rq);
+ abort ();
+ }
+ mpz_set_si (q, -5);
+ div_q[j] (q, a, b);
+ if (mpz_cmp (q, rq))
+ {
+ fprintf (stderr, "mpz_%cdiv_q failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ dump ("q ", q);
+ dump ("qref", rq);
+ abort ();
+ }
+ mpz_set_ui (r, ~5);
+ div_r[j] (r, a, b);
+ if (mpz_cmp (r, rr))
+ {
+ fprintf (stderr, "mpz_%cdiv_r failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ dump ("rref", rr);
+ abort ();
+ }
+
+ if (j == 0) /* do this once, not for all roundings */
+ {
+ div_p = mpz_divisible_p (a, b);
+ if ((mpz_sgn (r) == 0) ^ (div_p != 0))
+ {
+ fprintf (stderr, "mpz_divisible_p failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ abort ();
+ }
+ }
+
+ mpz_set_si (r, -6);
+ if (j == 0 && mpz_sgn (b) < 0) /* ceil, negative divisor */
+ {
+ mpz_mod (r, a, b);
+ if (mpz_cmp (r, rr))
+ {
+ fprintf (stderr, "mpz_mod failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ dump ("rref", rr);
+ abort ();
+ }
+ }
+
+ if (j == 1 && mpz_sgn (b) > 0) /* floor, positive divisor */
+ {
+ mpz_mod (r, a, b);
+ if (mpz_cmp (r, rr))
+ {
+ fprintf (stderr, "mpz_mod failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ dump ("rref", rr);
+ abort ();
+ }
+ }
+
+ if (mpz_fits_ulong_p (b))
+ {
+ unsigned long rl;
+
+ mpz_set_si (r, -7);
+ mpz_set_ui (q, ~7);
+ rl = div_qr_ui[j] (q, r, a, mpz_get_ui (b));
+ if (rl != mpz_get_ui (rr)
+ || mpz_cmp (r, rr) || mpz_cmp (q, rq))
+ {
+ fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ fprintf(stderr, "rl = %lx\n", rl);
+ dump ("r ", r);
+ dump ("rref", rr);
+ dump ("q ", q);
+ dump ("qref", rq);
+ abort ();
+ }
+
+ mpz_set_si (q, 3);
+ rl = div_q_ui[j] (q, a, mpz_get_ui (b));
+ if (rl != mpz_get_ui (rr) || mpz_cmp (q, rq))
+ {
+ fprintf (stderr, "mpz_%cdiv_q_ui failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ fprintf(stderr, "rl = %lx\n", rl);
+ dump ("rref", rr);
+ dump ("q ", q);
+ dump ("qref", rq);
+ abort ();
+ }
+
+ mpz_set_ui (r, 7);
+ rl = div_r_ui[j] (r, a, mpz_get_ui (b));
+ if (rl != mpz_get_ui (rr) || mpz_cmp (r, rr))
+ {
+ fprintf (stderr, "mpz_%cdiv_r_ui failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ fprintf(stderr, "rl = %lx\n", rl);
+ dump ("r ", r);
+ dump ("rref", rr);
+ abort ();
+ }
+
+ rl = div_ui[j] (a, mpz_get_ui (b));
+ if (rl != mpz_get_ui (rr))
+ {
+ fprintf (stderr, "mpz_%cdiv_ui failed:\n", name[j]);
+ dump ("a", a);
+ dump ("b", b);
+ fprintf(stderr, "rl = %lx\n", rl);
+ dump ("rref", rr);
+ abort ();
+ }
+
+ if (j == 0) /* do this once, not for all roundings */
+ {
+ div_p = mpz_divisible_ui_p (a, mpz_get_ui (b));
+ if ((mpz_sgn (r) == 0) ^ (div_p != 0))
+ {
+ fprintf (stderr, "mpz_divisible_ui_p failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ abort ();
+ }
+ }
+
+ if (j == 1) /* floor */
+ {
+ mpz_set_si (r, -2);
+ mpz_mod_ui (r, a, mpz_get_ui (b));
+ if (mpz_cmp (r, rr))
+ {
+ fprintf (stderr, "mpz_mod failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r ", r);
+ dump ("rref", rr);
+ abort ();
+ }
+ }
+ }
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (r);
+ mpz_clear (q);
+ mpz_clear (rr);
+ mpz_clear (rq);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-div_2exp.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-div_2exp.c
new file mode 100644
index 0000000..53d3f2b
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-div_2exp.c
@@ -0,0 +1,82 @@
+/*
+
+Copyright 2012, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+typedef void div_func (mpz_t, const mpz_t, mp_bitcnt_t);
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, res, ref;
+ mp_bitcnt_t b;
+
+ mpz_init (a);
+ mpz_init (res);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ unsigned j;
+ for (j = 0; j < 6; j++)
+ {
+ static const enum hex_random_op ops[6] =
+ {
+ OP_CDIV_Q_2, OP_CDIV_R_2,
+ OP_FDIV_Q_2, OP_FDIV_R_2,
+ OP_TDIV_Q_2, OP_TDIV_R_2
+ };
+ static const char *name[6] =
+ {
+ "cdiv_q", "cdiv_r",
+ "fdiv_q", "fdiv_r",
+ "tdiv_q", "tdiv_r"
+ };
+ static div_func * const div [6] =
+ {
+ mpz_cdiv_q_2exp, mpz_cdiv_r_2exp,
+ mpz_fdiv_q_2exp, mpz_fdiv_r_2exp,
+ mpz_tdiv_q_2exp, mpz_tdiv_r_2exp
+ };
+
+ mini_random_bit_op (ops[j], MAXBITS, a, &b, ref);
+ div[j] (res, a, b);
+ if (mpz_cmp (ref, res))
+ {
+ fprintf (stderr, "mpz_%s_2exp failed:\n", name[j]);
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-double.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-double.c
new file mode 100644
index 0000000..48774b3
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-double.c
@@ -0,0 +1,232 @@
+/*
+
+Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+
+#include "testutils.h"
+
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+
+mp_bitcnt_t
+mpz_mantissasizeinbits (const mpz_t z)
+{
+ return ! mpz_cmp_ui (z, 0) ? 0 :
+ mpz_sizeinbase (z, 2) - mpz_scan1 (z, 0);
+}
+
+#if defined(DBL_MANT_DIG) && FLT_RADIX == 2
+int
+mpz_get_d_exact_p (const mpz_t z)
+{
+ return mpz_mantissasizeinbits (z) <= DBL_MANT_DIG;
+}
+#define HAVE_EXACT_P 1
+#endif
+
+#define COUNT 10000
+
+void
+test_matissa (void)
+{
+ mpz_t x, y;
+ int i, c;
+
+ mpz_init (x);
+ mpz_init (y);
+
+ mini_urandomb (y, 4);
+ c = i = mpz_get_ui (y);
+
+ do {
+ double d;
+ int cmp;
+
+ mpz_setbit (x, c);
+ d = mpz_get_d (x);
+ mpz_set_d (y, d);
+ if (mpz_cmp_d (y, d) != 0)
+ {
+ fprintf (stderr, "mpz_cmp_d (y, d) failed:\n"
+ "d = %.20g\n"
+ "i = %i\n"
+ "c = %i\n",
+ d, i, c);
+ abort ();
+ }
+
+ cmp = mpz_cmp (x, y);
+
+#if defined(HAVE_EXACT_P)
+ if ((mpz_get_d_exact_p (x) != 0) != (cmp == 0))
+ {
+ fprintf (stderr, "Not all bits converted:\n"
+ "d = %.20g\n"
+ "i = %i\n"
+ "c = %i\n",
+ d, i, c);
+ abort ();
+ }
+#endif
+
+ if (cmp < 0)
+ {
+ fprintf (stderr, "mpz_get_d failed:\n"
+ "d = %.20g\n"
+ "i = %i\n"
+ "c = %i\n",
+ d, i, c);
+ abort ();
+ }
+ else if (cmp > 0)
+ {
+ if (mpz_cmp_d (x, d) <= 0)
+ {
+ fprintf (stderr, "mpz_cmp_d (x, d) failed:\n"
+ "d = %.20g\n"
+ "i = %i\n"
+ "c = %i\n",
+ d, i, c);
+ abort ();
+ }
+ break;
+ }
+ ++c;
+ } while (1);
+
+ mpz_clear (x);
+ mpz_clear (y);
+}
+
+#ifndef M_PI
+#define M_PI 3.141592653589793238462643383279502884
+#endif
+
+static const struct
+{
+ double d;
+ const char *s;
+} values[] = {
+ { 0.0, "0" },
+ { 0.3, "0" },
+ { -0.3, "0" },
+ { M_PI, "3" },
+ { M_PI*1e15, "b29430a256d21" },
+ { -M_PI*1e15, "-b29430a256d21" },
+ /* 17 * 2^{200} =
+ 27317946752402834684213355569799764242877450894307478200123392 */
+ {0.2731794675240283468421335556979976424288e62,
+ "1100000000000000000000000000000000000000000000000000" },
+ { 0.0, NULL }
+};
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t x;
+
+ for (i = 0; values[i].s; i++)
+ {
+ char *s;
+ mpz_init_set_d (x, values[i].d);
+ s = mpz_get_str (NULL, 16, x);
+ if (strcmp (s, values[i].s) != 0)
+ {
+ fprintf (stderr, "mpz_set_d failed:\n"
+ "d = %.20g\n"
+ "s = %s\n"
+ "r = %s\n",
+ values[i].d, s, values[i].s);
+ abort ();
+ }
+ testfree (s, strlen(s) + 1);
+ mpz_clear (x);
+ }
+
+ mpz_init (x);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ /* Use volatile, to avoid extended precision in floating point
+ registers, e.g., on m68k and 80387. */
+ volatile double d, f;
+ unsigned long m;
+ int e;
+
+ mini_rrandomb (x, GMP_LIMB_BITS);
+ m = mpz_get_ui (x);
+ mini_urandomb (x, 8);
+ e = mpz_get_ui (x) - 100;
+
+ d = ldexp ((double) m, e);
+ mpz_set_d (x, d);
+ f = mpz_get_d (x);
+ if (f != floor (d))
+ {
+ fprintf (stderr, "mpz_set_d/mpz_get_d failed:\n");
+ goto dumperror;
+ }
+ if ((f == d) ? (mpz_cmp_d (x, d) != 0) : (mpz_cmp_d (x, d) >= 0))
+ {
+ fprintf (stderr, "mpz_cmp_d (x, d) failed:\n");
+ goto dumperror;
+ }
+ f = d + 1.0;
+ if (f > d && ! (mpz_cmp_d (x, f) < 0))
+ {
+ fprintf (stderr, "mpz_cmp_d (x, f) failed:\n");
+ goto dumperror;
+ }
+
+ d = - d;
+
+ mpz_set_d (x, d);
+ f = mpz_get_d (x);
+ if (f != ceil (d))
+ {
+ fprintf (stderr, "mpz_set_d/mpz_get_d failed:\n");
+ dumperror:
+ dump ("x", x);
+ fprintf (stderr, "m = %lx, e = %i\n", m, e);
+ fprintf (stderr, "d = %.15g\n", d);
+ fprintf (stderr, "f = %.15g\n", f);
+ fprintf (stderr, "f - d = %.5g\n", f - d);
+ abort ();
+ }
+ if ((f == d) ? (mpz_cmp_d (x, d) != 0) : (mpz_cmp_d (x, d) <= 0))
+ {
+ fprintf (stderr, "mpz_cmp_d (x, d) failed:\n");
+ goto dumperror;
+ }
+ f = d - 1.0;
+ if (f < d && ! (mpz_cmp_d (x, f) > 0))
+ {
+ fprintf (stderr, "mpz_cmp_d (x, f) failed:\n");
+ goto dumperror;
+ }
+ }
+
+ mpz_clear (x);
+ test_matissa();
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-gcd.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-gcd.c
new file mode 100644
index 0000000..64f90f4
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-gcd.c
@@ -0,0 +1,178 @@
+/*
+
+Copyright 2012, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+/* Called when g is supposed to be gcd(a,b), and g = s a + t b. */
+static int
+gcdext_valid_p (const mpz_t a, const mpz_t b,
+ const mpz_t g, const mpz_t s, const mpz_t t)
+{
+ mpz_t ta, tb, r;
+
+ /* It's not clear that gcd(0,0) is well defined, but we allow it and
+ require that gcd(0,0) = 0. */
+ if (mpz_sgn (g) < 0)
+ return 0;
+
+ if (mpz_sgn (a) == 0)
+ {
+ /* Must have g == abs (b). Any value for s is in some sense "correct",
+ but it makes sense to require that s == 0, t = sgn (b)*/
+ return mpz_cmpabs (g, b) == 0
+ && mpz_sgn (s) == 0 && mpz_cmp_si (t, mpz_sgn (b)) == 0;
+ }
+ else if (mpz_sgn (b) == 0)
+ {
+ /* Must have g == abs (a), s == sign (a), t = 0 */
+ return mpz_cmpabs (g, a) == 0
+ && mpz_cmp_si (s, mpz_sgn (a)) == 0 && mpz_sgn (t) == 0;
+ }
+
+ if (mpz_sgn (g) <= 0)
+ return 0;
+
+ mpz_init (ta);
+ mpz_init (tb);
+ mpz_init (r);
+
+ mpz_mul (ta, s, a);
+ mpz_mul (tb, t, b);
+ mpz_add (ta, ta, tb);
+
+ if (mpz_cmp (ta, g) != 0)
+ {
+ fail:
+ mpz_clear (ta);
+ mpz_clear (tb);
+ mpz_clear (r);
+ return 0;
+ }
+ mpz_tdiv_qr (ta, r, a, g);
+ if (mpz_sgn (r) != 0)
+ goto fail;
+
+ mpz_tdiv_qr (tb, r, b, g);
+ if (mpz_sgn (r) != 0)
+ goto fail;
+
+ /* Require that 2 |s| < |b/g|, or |s| == 1. */
+ if (mpz_cmpabs_ui (s, 1) > 0)
+ {
+ mpz_mul_2exp (r, s, 1);
+ if (mpz_cmpabs (r, tb) > 0)
+ goto fail;
+ }
+
+ /* Require that 2 |t| < |a/g| or |t| == 1*/
+ if (mpz_cmpabs_ui (t, 1) > 0)
+ {
+ mpz_mul_2exp (r, t, 1);
+ if (mpz_cmpabs (r, ta) > 0)
+ return 0;
+ }
+
+ mpz_clear (ta);
+ mpz_clear (tb);
+ mpz_clear (r);
+
+ return 1;
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, g, s, t;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (g);
+ mpz_init (s);
+ mpz_init (t);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_GCD, MAXBITS, a, b, s);
+ mpz_gcd (g, a, b);
+ if (mpz_cmp (g, s))
+ {
+ fprintf (stderr, "mpz_gcd failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", g);
+ dump ("ref", s);
+ abort ();
+ }
+ }
+
+ for (i = 0; i < COUNT; i++)
+ {
+ unsigned flags;
+ mini_urandomb (a, 32);
+ flags = mpz_get_ui (a);
+ mini_rrandomb (a, MAXBITS);
+ mini_rrandomb (b, MAXBITS);
+
+ if (flags % 37 == 0)
+ mpz_mul (a, a, b);
+ if (flags % 37 == 1)
+ mpz_mul (b, a, b);
+
+ if (flags & 1)
+ mpz_neg (a, a);
+ if (flags & 2)
+ mpz_neg (b, b);
+
+ mpz_gcdext (g, s, t, a, b);
+ if (!gcdext_valid_p (a, b, g, s, t))
+ {
+ fprintf (stderr, "mpz_gcdext failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("g", g);
+ dump ("s", s);
+ dump ("t", t);
+ abort ();
+ }
+
+ mpz_gcd (s, a, b);
+ if (mpz_cmp (g, s))
+ {
+ fprintf (stderr, "mpz_gcd failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", g);
+ dump ("ref", s);
+ abort ();
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (g);
+ mpz_clear (s);
+ mpz_clear (t);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-import.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-import.c
new file mode 100644
index 0000000..66c9d5e
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-import.c
@@ -0,0 +1,99 @@
+/*
+
+Copyright 2013 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define MAX_WORDS 20
+#define MAX_WORD_SIZE 10
+
+static void
+dump_bytes (const char *label, const unsigned char *s, size_t n)
+{
+ size_t i;
+ fprintf (stderr, "%s:", label);
+ for (i = 0; i < n; i++)
+ {
+ if (i && (i % 16) == 0)
+ fprintf (stderr, "\n");
+ fprintf (stderr, " %02x", s[i]);
+ }
+ fprintf (stderr, "\n");
+}
+
+/* Tests both mpz_import and mpz_export. */
+void
+testmain (int argc, char **argv)
+{
+ unsigned char input[MAX_WORDS * MAX_WORD_SIZE];
+ unsigned char output[MAX_WORDS * MAX_WORD_SIZE + 2];
+ size_t count, in_count, out_count, size;
+ int endian, order;
+
+ mpz_t a, res;
+
+ mpz_init (a);
+ mpz_init (res);
+
+ for (size = 0; size <= MAX_WORD_SIZE; size++)
+ for (count = 0; count <= MAX_WORDS; count++)
+ for (endian = -1; endian <= 1; endian++)
+ for (order = -1; order <= 1; order += 2)
+ {
+ mini_rrandomb_export (a, input, &in_count,
+ order, size, endian, size*count * 8);
+ mpz_import (res, in_count, order, size, endian, 0, input);
+ if (mpz_cmp (a, res))
+ {
+ fprintf (stderr, "mpz_import failed:\n"
+ "in_count %lu, out_count %lu, endian = %d, order = %d\n",
+ (unsigned long) in_count, (unsigned long) out_count, endian, order);
+ dump ("a", a);
+ dump ("res", res);
+ abort ();
+ }
+ output[0] = 17;
+ output[1+in_count*size] = 17;
+
+ mpz_export (output+1, &out_count, order, size, endian, 0, a);
+ if (out_count != in_count
+ || memcmp (output+1, input, in_count * size)
+ || output[0] != 17
+ || output[1+in_count*size] != 17)
+ {
+ fprintf (stderr, "mpz_export failed:\n"
+ "in_count %lu, out_count %lu, endian = %d, order = %d\n",
+ (unsigned long) in_count, (unsigned long) out_count, endian, order);
+ dump_bytes ("input", input, in_count * size);
+ dump_bytes ("output", output+1, out_count * size);
+ if (output[0] != 17)
+ fprintf (stderr, "Overwrite at -1, value %02x\n", output[0]);
+ if (output[1+in_count*size] != 17)
+ fprintf (stderr, "Overwrite at %lu, value %02x\n",
+ (unsigned long) (in_count*size), output[1+in_count*size]);
+
+ abort ();
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (res);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-invert.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-invert.c
new file mode 100644
index 0000000..02e1731
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-invert.c
@@ -0,0 +1,141 @@
+/*
+
+Copyright 2012, 2016 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+
+#define COUNT 10000
+
+static void
+test_2by1(const mpz_t u)
+{
+ mpz_t m, p, t;
+ mp_limb_t tl;
+
+ mpz_init (p);
+
+ assert (mpz_size (u) == 1);
+
+ tl = mpn_invert_limb (u->_mp_d[0]);
+ mpz_roinit_n (t, &tl, 1);
+ mpz_init_set (m, t);
+ mpz_setbit (m, GMP_LIMB_BITS);
+
+ mpz_mul (p, m, u);
+
+ mpz_init (t);
+ mpz_setbit (t, 2* GMP_LIMB_BITS);
+ mpz_sub (t, t, p);
+
+ /* Should have 0 < B^2 - m u <= u */
+ if (mpz_sgn (t) <= 0 || mpz_cmp (t, u) > 0)
+ {
+ fprintf (stderr, "mpn_invert_limb failed:\n");
+ dump ("u", u);
+ dump ("m", m);
+ dump ("p", p);
+ dump ("t", t);
+ abort ();
+ }
+ mpz_clear (m);
+ mpz_clear (p);
+ mpz_clear (t);
+}
+
+static void
+test_3by2(const mpz_t u)
+{
+ mpz_t m, p, t;
+ mp_limb_t tl;
+
+ mpz_init (p);
+
+ assert (mpz_size (u) == 2);
+
+ tl = mpn_invert_3by2 (u->_mp_d[1], u->_mp_d[0]);
+ mpz_roinit_n (t, &tl, 1);
+ mpz_init_set (m, t);
+
+ mpz_setbit (m, GMP_LIMB_BITS);
+
+ mpz_mul (p, m, u);
+
+ mpz_init (t);
+ mpz_setbit (t, 3 * GMP_LIMB_BITS);
+ mpz_sub (t, t, p);
+
+ /* Should have 0 < B^3 - m u <= u */
+ if (mpz_sgn (t) <= 0 || mpz_cmp (t, u) > 0)
+ {
+ fprintf (stderr, "mpn_invert_3by2 failed:\n");
+ dump ("u", u);
+ dump ("m", m);
+ dump ("p", p);
+ dump ("t", t);
+ abort ();
+ }
+ mpz_clear (m);
+ mpz_clear (p);
+ mpz_clear (t);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t u, m, p, t;
+
+ mpz_init (u);
+ mpz_init (m);
+ mpz_init (p);
+ mpz_init (t);
+
+ /* These values trigger 32-bit overflow of ql in mpn_invert_3by2. */
+ if (GMP_LIMB_BITS == 64)
+ {
+ mpz_set_str (u, "80007fff3ffe0000", 16);
+ test_2by1 (u);
+ mpz_set_str (u, "80007fff3ffe000000000000000003ff", 16);
+ test_3by2 (u);
+ }
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_urandomb (u, GMP_LIMB_BITS);
+ mpz_setbit (u, GMP_LIMB_BITS -1);
+
+ test_2by1 (u);
+ }
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_urandomb (u, 2*GMP_LIMB_BITS);
+ mpz_setbit (u, 2*GMP_LIMB_BITS -1);
+
+ test_3by2 (u);
+ }
+
+ mpz_clear (u);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-lcm.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-lcm.c
new file mode 100644
index 0000000..f21a39a
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-lcm.c
@@ -0,0 +1,73 @@
+/*
+
+Copyright 2012, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, g, s;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (g);
+ mpz_init (s);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_LCM, MAXBITS, a, b, s);
+ mpz_lcm (g, a, b);
+ if (mpz_cmp (g, s))
+ {
+ fprintf (stderr, "mpz_lcm failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", g);
+ dump ("ref", s);
+ abort ();
+ }
+ if (mpz_fits_ulong_p (b))
+ {
+ mpz_set_si (g, 0);
+ mpz_lcm_ui (g, a, mpz_get_ui (b));
+ if (mpz_cmp (g, s))
+ {
+ fprintf (stderr, "mpz_lcm_ui failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", g);
+ dump ("ref", s);
+ abort ();
+ }
+ }
+ }
+
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (g);
+ mpz_clear (s);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-limbs.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-limbs.c
new file mode 100644
index 0000000..f4e57dd
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-limbs.c
@@ -0,0 +1,111 @@
+/*
+
+Copyright 2012, 2014, 2016, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 100
+
+void
+my_mpz_mul (mpz_t r, mpz_srcptr a, mpz_srcptr b)
+{
+ mp_limb_t *tp;
+ mp_size_t tn, an, bn;
+
+ an = mpz_size (a);
+ bn = mpz_size (b);
+
+ assert (an > 0);
+ assert (bn > 0);
+
+ tn = an + bn;
+ tp = mpz_limbs_write (r, tn);
+ if (an > bn)
+ mpn_mul (tp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn);
+ else
+ mpn_mul (tp, mpz_limbs_read (b), bn, mpz_limbs_read (a), an);
+
+ if (mpz_sgn (a) != mpz_sgn(b))
+ tn = - tn;
+
+ mpz_limbs_finish (r, tn);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, res, ref;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (res);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_MUL, MAXBITS, a, b, ref);
+ if (mpz_sgn(ref) == 0)
+ /* my_mpz_mul requires a != 0, b != 0 */
+ continue;
+ my_mpz_mul (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "my_mpz_mul failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ /* The following test exploits a side-effect of my_mpz_mul: res
+ points to a buffer with at least an+bn limbs, and the limbs
+ above the result are zeroed. */
+ if (mpz_size (b) > 0 && mpz_getlimbn (res, mpz_size(a)) != mpz_limbs_read (res) [mpz_size(a)])
+ {
+ fprintf (stderr, "getlimbn - limbs_read differ.\n");
+ abort ();
+ }
+ if ((i % 4 == 0) && mpz_size (res) > 1)
+ {
+ mpz_realloc2 (res, 1);
+ if (mpz_cmp_ui (res, 0))
+ {
+ fprintf (stderr, "mpz_realloc2 did not clear res.\n");
+ abort ();
+ }
+ mpz_limbs_finish (ref, 0);
+ if (mpz_cmp_d (ref, 0))
+ {
+ fprintf (stderr, "mpz_limbs_finish did not clear res.\n");
+ abort ();
+ }
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-logops.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-logops.c
new file mode 100644
index 0000000..b4e0239
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-logops.c
@@ -0,0 +1,112 @@
+/*
+
+Copyright 2012, 2013 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+void
+testlogops (int count)
+{
+ int i;
+ mpz_t a, b, res, ref;
+ mp_bitcnt_t c;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (res);
+ mpz_init (ref);
+
+ for (i = 0; i < count; i++)
+ {
+ mini_random_op3 (OP_AND, MAXBITS, a, b, ref);
+ mpz_and (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_and failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+
+ mini_random_op3 (OP_IOR, MAXBITS, a, b, ref);
+ mpz_ior (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_ior failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+
+ mini_random_op3 (OP_XOR, MAXBITS, a, b, ref);
+ mpz_xor (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_xor failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+
+ if (i % 8) {
+ c = 0;
+ mpz_mul_2exp (res, res, i % 8);
+ } else if (mpz_sgn (res) >= 0) {
+ c = mpz_odd_p (res) != 0;
+ mpz_tdiv_q_2exp (res, res, 1);
+ } else {
+ c = (~ (mp_bitcnt_t) 0) - 3;
+ mpz_set_ui (res, 11 << ((i >> 3)%4)); /* set 3 bits */
+ }
+
+ if (mpz_popcount (res) + c != mpz_hamdist (a, b))
+ {
+ fprintf (stderr, "mpz_popcount(r) + %lu and mpz_hamdist(a,b) differ:\n", c);
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ fprintf (stderr, "mpz_popcount(r) = %lu:\n", mpz_popcount (res));
+ fprintf (stderr, "mpz_hamdist(a,b) = %lu:\n", mpz_hamdist (a, b));
+ abort ();
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ testhalves (COUNT*2/3, testlogops);
+ testlogops (COUNT/3);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-lucm.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-lucm.c
new file mode 100644
index 0000000..22ad575
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-lucm.c
@@ -0,0 +1,98 @@
+/* Tests the (internal) function mpz_lucas_mod
+
+Copyright 2018, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define MAXBITS 100
+#define COUNT 1000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t m, vr, qr, vm, qm, vt;
+ int resm, resr;
+ long Q;
+ unsigned long b0;
+
+ mpz_init (m);
+ mpz_init (vr);
+ mpz_init (qr);
+ mpz_init (vm);
+ mpz_init (qm);
+ mpz_init (vt);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_lucm_op (MAXBITS, vr, qr, m, &Q, &b0, &resr);
+ if (b0 == 0)
+ {
+ fprintf (stderr, "lucas_mod: test disabled (%u tests done).\n", i);
+ break;
+ }
+ resm = mpz_lucas_mod (vm, qm, Q, b0, m);
+
+ if (resr != resm)
+ {
+ if (resm != 0 || mpz_cmp_ui (vm, 0) != 0)
+ {
+ fprintf (stderr, "mpz_lucas_mod wrong return value (%d != %d):\n", resr, resm);
+ fprintf (stderr, "Q = %ld , b0 = %lu\n", Q, b0);
+ dump ("m", m);
+ dump ("vm", vm);
+ dump ("qm", qm);
+ abort ();
+ }
+ }
+ else if (resm == 0)
+ {
+ mpz_abs (vr, vr);
+ mpz_sub (vt, m, vr);
+ mpz_abs (vm, vm);
+ mpz_mod (qm, qm, m);
+ if (mpz_cmp_ui (qr, 0) < 0)
+ mpz_add (qr, qr, m);
+ if (mpz_cmp (qm, qr) != 0 ||
+ (mpz_cmp (vm, vr) != 0 && mpz_cmp (vm, vt) != 0))
+ {
+ fprintf (stderr, "mpz_lucas_mod error:\n");
+ fprintf (stderr, "Q = %ld , b0 = %lu\n", Q, b0);
+ dump ("m", m);
+ dump ("vm", vm);
+ dump ("vr", vr);
+ dump ("vt", vt);
+ dump ("qm", qm);
+ dump ("qr", qr);
+ abort ();
+ }
+
+ }
+ }
+ mpz_clear (m);
+ mpz_clear (vr);
+ mpz_clear (qr);
+ mpz_clear (vm);
+ mpz_clear (qm);
+ mpz_clear (vt);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_addsub.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_addsub.c
new file mode 100644
index 0000000..de1461f
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_addsub.c
@@ -0,0 +1,204 @@
+/*
+
+Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+#include "../mini-mpq.h"
+
+#define MAXBITS 300
+#define COUNT 10000
+
+static void
+_mpq_set_zz (mpq_t q, mpz_t n, mpz_t d)
+{
+ if (mpz_fits_ulong_p (d) && mpz_fits_slong_p (n))
+ {
+ mpq_set_si (q, mpz_get_si (n), mpz_get_ui (d));
+ }
+ else if (mpz_fits_ulong_p (d) && mpz_fits_ulong_p (n))
+ {
+ mpq_set_ui (q, mpz_get_ui (n), mpz_get_ui (d));
+ }
+ else
+ {
+ mpq_set_num (q, n);
+ mpq_set_den (q, d);
+ }
+ mpq_canonicalize (q);
+}
+
+void
+testcmpui ()
+{
+ unsigned d1, d2, n1, n2;
+ mpq_t q1, q2;
+
+ mpq_init (q1);
+ mpq_init (q2);
+
+ for (d1 = 1; d1 < 6; d1 += 2)
+ for (n1 = 1; n1 < 6; n1 *= 2)
+ {
+ mpq_set_ui (q1, n1, d1);
+ for (d2 = 1; d2 < 6; d2 += 2)
+ for (n2 = 1; n2 < 6; n2 *= 2)
+ {
+ int fres = mpq_cmp_ui (q1, n2, d2);
+ int ref = (d1*n2 < d2*n1) - (d1*n2 > d2*n1);
+
+ mpq_set_ui (q2, n2, d2);
+
+ if ((!ref) != mpq_equal (q1, q2))
+ {
+ fprintf (stderr, "mpz_equal failed: %i / %i = %i / %i ? %i\n", n1, d1, n2, d2, ref);
+ abort ();
+ }
+
+ if (ref != fres)
+ {
+ fprintf (stderr, "mpz_cmp_ui failed: %i / %i = %i / %i ? %i != %i\n", n1, d1, n2, d2, ref, fres);
+ abort ();
+ }
+ }
+ }
+
+ mpq_clear (q1);
+ mpq_clear (q2);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, q, r, c;
+ mpq_t rr, ii, ff;
+ int tst;
+
+ testcmpui ();
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (r);
+ mpz_init (q);
+ mpz_init (c);
+ mpq_init (rr);
+ mpq_init (ff);
+ mpq_init (ii);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op4 (OP_TDIV, MAXBITS, a, b, q, r);
+
+ _mpq_set_zz (rr, a, b);
+ _mpq_set_zz (ff, r, b);
+
+ mpq_set_z (ii, q);
+
+ mpz_set_q (c, rr);
+ if (mpz_cmp (c, q))
+ {
+ fprintf (stderr, "mpz_set_q failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("c", c);
+ dump ("q", q);
+ abort ();
+ }
+
+ if ((mpz_sgn (r) != 0) ^ (mpz_cmp_ui (mpq_denref (rr), 1) != 0))
+ {
+ fprintf (stderr, "mpq_canonicalize failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", r);
+ dump ("D", mpq_denref (rr));
+ abort ();
+ }
+
+ if (i & 1)
+ {
+ if (mpz_fits_slong_p (q))
+ tst = mpq_cmp_si (rr, mpz_get_si (q), 1);
+ else if (mpz_fits_ulong_p (q))
+ tst = mpq_cmp_ui (rr, mpz_get_ui (q), 1);
+ else
+ tst = mpq_cmp_z (rr, q);
+ if (mpz_sgn (b) < 0)
+ tst = - tst;
+ if ((tst != mpz_sgn (r)) && ((tst < 0 && mpz_sgn (r) >= 0) || (tst > 0 && mpz_sgn (r) <= 0)))
+ {
+ fprintf (stderr, "mpq_cmp ii failed: %i %i\n", tst, mpz_sgn (r));
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", r);
+ dump ("q", q);
+ abort ();
+ }
+ }
+ else
+ {
+ if (mpz_fits_ulong_p (b) && mpz_fits_slong_p (r))
+ tst = mpq_cmp_si (rr, mpz_get_si (r), mpz_get_ui (b));
+ else if (mpz_fits_ulong_p (b) && mpz_fits_ulong_p (r))
+ tst = mpq_cmp_ui (rr, mpz_get_ui (r), mpz_get_ui (b));
+ else
+ tst = mpq_cmp (rr, ff);
+ if ((tst != mpz_sgn (q)) && ((tst < 0 && mpz_sgn (q) >= 0) || (tst > 0 && mpz_sgn (q) <= 0)))
+ {
+ fprintf (stderr, "mpq_cmp ff failed: %i %i\n", tst, mpz_sgn (q));
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", r);
+ dump ("q", q);
+ abort ();
+ }
+ }
+
+ if (i & 1)
+ {
+ mpq_sub (rr, rr, ff);
+ }
+ else
+ {
+ mpq_neg (ff, ff);
+ mpq_add (rr, ff, rr);
+ }
+
+ if (!mpq_equal (ii, rr))
+ {
+ fprintf (stderr, "mpq_%s failed:\n", (i & 1) ? "sub" : "add");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", r);
+ dump ("q", q);
+ abort ();
+ }
+ }
+
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (r);
+ mpz_clear (q);
+ mpz_clear (c);
+ mpq_clear (rr);
+ mpq_clear (ff);
+ mpq_clear (ii);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_double.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_double.c
new file mode 100644
index 0000000..3cfba60
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_double.c
@@ -0,0 +1,211 @@
+/* Test mpq_set_d.
+
+Copyright 2001-2003, 2005, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+
+#include "testutils.h"
+#include "../mini-mpq.h"
+
+#define COUNT 2000
+
+mp_bitcnt_t
+mpz_mantissasizeinbits (const mpz_t z)
+{
+ return ! mpz_cmp_ui (z, 0) ? 0 :
+ mpz_sizeinbase (z, 2) - mpz_scan1 (z, 0);
+}
+
+int
+mpz_abspow2_p (const mpz_t z)
+{
+ return mpz_mantissasizeinbits (z) == 1;
+}
+
+mp_bitcnt_t
+mpq_mantissasizeinbits (const mpq_t q)
+{
+ if (! mpz_abspow2_p (mpq_denref (q)))
+ return ~ (mp_bitcnt_t) 0;
+
+ return mpz_mantissasizeinbits (mpq_numref (q));
+}
+
+#if defined(DBL_MANT_DIG) && FLT_RADIX == 2
+int
+mpz_get_d_exact_p (const mpz_t z)
+{
+ return mpz_mantissasizeinbits (z) <= DBL_MANT_DIG;
+}
+
+int
+mpq_get_d_exact_p (const mpq_t q)
+{
+ return mpq_mantissasizeinbits (q) <= DBL_MANT_DIG;
+}
+#define HAVE_EXACT_P 1
+#endif
+
+void
+check_random (void)
+{
+ unsigned i;
+ mpz_t x;
+ mpq_t y, z;
+
+ mpz_init (x);
+ mpq_init (y);
+ mpq_init (z);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ /* Use volatile, to avoid extended precision in floating point
+ registers, e.g., on m68k and 80387. */
+ volatile double d, f;
+ unsigned long m;
+ int e, c;
+
+ mini_rrandomb (x, CHAR_BIT * sizeof (unsigned long));
+ m = mpz_get_ui (x);
+ mini_urandomb (x, 8);
+ e = mpz_get_ui (x) - 128;
+
+ d = ldexp ((double) m, e);
+ mpq_set_d (y, d);
+ f = mpq_get_d (y);
+ if (f != d)
+ {
+ fprintf (stderr, "mpq_set_d/mpq_get_d failed:\n");
+ goto dumperror;
+ }
+
+ d = - d;
+ mpq_neg (y, y);
+
+ mpq_set_d (z, d);
+ f = mpq_get_d (z);
+ if (f != d || !mpq_equal (y, z))
+ {
+ fprintf (stderr, "mpq_set_d/mpq_get_d failed:\n");
+ dumperror:
+ dump ("ny", mpq_numref (y));
+ dump ("dy", mpq_denref (y));
+ fprintf (stderr, "m = %lx, e = %i\n", m, e);
+ fprintf (stderr, "d = %.35g\n", d);
+ fprintf (stderr, "f = %.35g\n", f);
+ fprintf (stderr, "f - d = %.35g\n", f - d);
+ abort ();
+ }
+
+ mini_rrandomb (x, CHAR_BIT * sizeof (unsigned long));
+ m = mpz_get_ui (x);
+ mini_urandomb (x, 8);
+ e = mpz_get_ui (x) - 128;
+
+ d = ldexp ((double) m, e);
+ mpq_set_d (y, d);
+
+ if (i == 0)
+ mpq_neg (z, y);
+
+ mpq_add (y, y, z);
+ mpq_set_d (z, mpq_get_d (y));
+ f = mpq_get_d (z);
+ c = mpq_cmp (y, z);
+
+#if defined(HAVE_EXACT_P)
+ if (mpq_get_d_exact_p (y) ? c != 0 : (f > 0 ? c <= 0 : c >= 0))
+#else
+ if (f > 0 ? c < 0 : c > 0)
+#endif
+ {
+ fprintf (stderr, "mpq_get_d/mpq_set_d failed: %i %i\n", i, c);
+ goto dumperror;
+ }
+ }
+
+ mpz_clear (x);
+ mpq_clear (y);
+ mpq_clear (z);
+}
+
+
+void
+check_data (void)
+{
+ static const struct {
+ double y;
+ long int n;
+ unsigned long d;
+ } data[] = {
+ { 0.0, 0, 1 },
+ { 1.0, 1, 1 },
+ { -1.0, -1, 1 },
+ { -1.5, -3, 2 },
+ {-1.25, -5, 4 },
+ {0.125, 1, 8 },
+
+ {24685,24685,1},
+ {-9876,-9876,1},
+ {463.5, 927,2},
+
+ {1234.5/8192, 2469, 16384 },
+ {-543.0/1024, -543, 1024 },
+ {9876.5/ 512, 19753, 1024 },
+ {9753.0/ 128, 9753, 128 },
+ {-789.0/ 32, -789, 32 },
+ {4.580078125, 2345, 512 },
+ };
+
+ mpq_t x, r;
+ unsigned i;
+ double d;
+
+ mpq_init (x);
+ mpq_init (r);
+
+ for (i = 0; i < numberof (data); i++)
+ {
+ mpq_set_d (x, data[i].y);
+ mpq_set_si (r, data[i].n, data[i].d);
+ mpq_canonicalize (r);
+ if (!mpq_equal (x, r))
+ {
+ fprintf (stderr, "mpq_set_d failed: %li / %lu != %g\n", data[i].n, data[i].d, data[i].y);
+ abort ();
+ }
+ d = mpq_get_d (r);
+ if (d != data[i].y)
+ {
+ fprintf (stderr, "mpq_get_d failed: %li / %lu != %g\n", data[i].n, data[i].d, data[i].y);
+ abort ();
+ }
+ }
+
+ mpq_clear (x);
+ mpq_clear (r);
+}
+
+void
+testmain (int argc, char *argv[])
+{
+ check_data ();
+ check_random ();
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv.c
new file mode 100644
index 0000000..8e7de8b
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv.c
@@ -0,0 +1,176 @@
+/*
+
+Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+#include "../mini-mpq.h"
+
+#define MAXBITS 300
+#define COUNT 10000
+
+static void
+_mpq_set_zz (mpq_t q, mpz_t n, mpz_t d)
+{
+ if (mpz_fits_ulong_p (d) && mpz_fits_slong_p (n))
+ {
+ mpq_set_si (q, mpz_get_si (n), mpz_get_ui (d));
+ }
+ else if (mpz_fits_ulong_p (d) && mpz_fits_ulong_p (n))
+ {
+ mpq_set_ui (q, mpz_get_ui (n), mpz_get_ui (d));
+ }
+ else
+ {
+ mpq_set_num (q, n);
+ mpq_set_den (q, d);
+ }
+ mpq_canonicalize (q);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t an, bn, rn, ad, bd, rd;
+ mpq_t aq, bq, refq, resq;
+
+ mpz_init (an);
+ mpz_init (bn);
+ mpz_init (rn);
+ mpz_init (ad);
+ mpz_init (bd);
+ mpz_init (rd);
+ mpq_init (aq);
+ mpq_init (bq);
+ mpq_init (refq);
+ mpq_init (resq);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_MUL, MAXBITS, an, bn, rn);
+ do {
+ mini_random_op3 (OP_MUL, MAXBITS, ad, bd, rd);
+ } while (mpz_sgn (rd) == 0);
+
+ _mpq_set_zz (aq, an, ad);
+ _mpq_set_zz (bq, bn, bd);
+ _mpq_set_zz (refq, rn, rd);
+
+ mpq_mul (resq, aq, bq);
+ if (!mpq_equal (resq, refq))
+ {
+ fprintf (stderr, "mpq_mul failed [%i]:\n", i);
+ dump ("an", an);
+ dump ("ad", ad);
+ dump ("bn", bn);
+ dump ("bd", bd);
+ dump ("refn", rn);
+ dump ("refd", rd);
+ dump ("resn", mpq_numref (resq));
+ dump ("resd", mpq_denref (resq));
+ abort ();
+ }
+
+ if (mpq_sgn (refq) != 0)
+ {
+ mpq_set_ui (resq, ~6, 8);
+ mpq_inv (aq, aq);
+ mpq_div (resq, aq, bq);
+ mpq_inv (resq, resq);
+ if (!mpq_equal (resq, refq))
+ {
+ fprintf (stderr, "mpq_div failed [%i]:\n", i);
+ dump ("an", an);
+ dump ("ad", ad);
+ dump ("bn", bn);
+ dump ("bd", bd);
+ dump ("refn", rn);
+ dump ("refd", rd);
+ dump ("resn", mpq_numref (resq));
+ dump ("resd", mpq_denref (resq));
+ abort ();
+ }
+
+ mpq_swap (bq, aq);
+ mpq_div (resq, aq, bq);
+ if (!mpq_equal (resq, refq))
+ {
+ fprintf (stderr, "mpq_swap failed [%i]:\n", i);
+ dump ("an", an);
+ dump ("ad", ad);
+ dump ("bn", bn);
+ dump ("bd", bd);
+ dump ("refn", rn);
+ dump ("refd", rd);
+ dump ("resn", mpq_numref (resq));
+ dump ("resd", mpq_denref (resq));
+ abort ();
+ }
+ }
+
+ mpq_set (resq, aq);
+ mpq_neg (bq, aq);
+ mpq_abs (refq, aq);
+ if (mpq_equal (refq, resq))
+ mpq_add (resq, refq, bq);
+ else
+ mpq_add (resq, refq, resq);
+ mpq_set_ui (refq, 0, 1);
+ if (!mpq_equal (resq, refq))
+ {
+ fprintf (stderr, "mpq_abs failed [%i]:\n", i);
+ dump ("an", an);
+ dump ("ad", ad);
+ dump ("resn", mpq_numref (resq));
+ dump ("resd", mpq_denref (resq));
+ abort ();
+ }
+
+ mpq_mul (resq, aq, aq);
+ mpq_mul (refq, aq, bq); /* now bq = - aq */
+ mpq_neg (refq, refq);
+ if (!mpq_equal (resq, refq))
+ {
+ fprintf (stderr, "mpq_mul(sqr) failed [%i]:\n", i);
+ dump ("an", an);
+ dump ("ad", ad);
+ dump ("bn", bn);
+ dump ("bd", bd);
+ dump ("refn", rn);
+ dump ("refd", rd);
+ dump ("resn", mpq_numref (resq));
+ dump ("resd", mpq_denref (resq));
+ abort ();
+ }
+ }
+
+ mpz_clear (an);
+ mpz_clear (bn);
+ mpz_clear (rn);
+ mpz_clear (ad);
+ mpz_clear (bd);
+ mpz_clear (rd);
+ mpq_clear (aq);
+ mpq_clear (bq);
+ mpq_clear (refq);
+ mpq_clear (resq);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv_2exp.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv_2exp.c
new file mode 100644
index 0000000..46b2c0c
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_muldiv_2exp.c
@@ -0,0 +1,138 @@
+/*
+
+Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+#include "../mini-mpq.h"
+
+#define MAXBITS 300
+#define COUNT 10000
+
+static void
+_mpq_set_zz (mpq_t q, mpz_t n, mpz_t d)
+{
+ if (mpz_fits_ulong_p (d) && mpz_fits_slong_p (n))
+ {
+ mpq_set_si (q, mpz_get_si (n), mpz_get_ui (d));
+ }
+ else if (mpz_fits_ulong_p (d) && mpz_fits_ulong_p (n))
+ {
+ mpq_set_ui (q, mpz_get_ui (n), mpz_get_ui (d));
+ }
+ else
+ {
+ mpq_set_num (q, n);
+ mpq_set_den (q, d);
+ }
+ mpq_canonicalize (q);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, t;
+ mpq_t aq, rq, tq;
+ mp_bitcnt_t e;
+ long int e2, t1, t2;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (t);
+ mpq_init (aq);
+ mpq_init (rq);
+ mpq_init (tq);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ do {
+ mini_random_bit_op (OP_COMBIT, MAXBITS, a, &e, b);
+ } while (mpz_sgn (a) == 0 || mpz_sgn (b) == 0);
+
+ _mpq_set_zz (aq, a, b);
+ e2 = mpz_scan1 (a, 0);
+ e2-= mpz_scan1 (b, 0);
+
+ mpq_mul_2exp (rq, aq, e);
+ t1 = mpz_scan1 (mpq_numref (rq), 0);
+ t2 = mpz_scan1 (mpq_denref (rq), 0);
+ mpq_neg (tq, rq);
+ mpq_div (tq, aq, tq);
+ mpq_get_den (t, tq);
+
+ if (e2 + e != t1 - t2 || (t2 != 0 && t1 != 0) || mpz_scan1 (t, 0) != e
+ || mpz_sizeinbase (t, 2) - 1 != e || mpz_cmp_si (mpq_numref (tq), -1) != 0)
+ {
+ fprintf (stderr, "mpq_mul_2exp failed: %lu\n", e);
+ dump ("na", a);
+ dump ("da", b);
+ dump ("nr", mpq_numref (rq));
+ dump ("dr", mpq_denref (rq));
+ abort ();
+ }
+
+ mpq_div_2exp (rq, aq, e);
+ t1 = mpz_scan1 (mpq_numref (rq), 0);
+ t2 = mpz_scan1 (mpq_denref (rq), 0);
+ mpq_div (aq, aq, rq);
+ mpq_get_num (t, aq);
+
+ if (e2 != t1 - t2 + e || (t2 != 0 && t1 != 0) || mpz_scan1 (t, 0) != e
+ || mpz_sizeinbase (t, 2) - 1 != e || mpz_cmp_ui (mpq_denref (aq), 1) != 0)
+ {
+ fprintf (stderr, "mpq_div_2exp failed: %lu\n", e);
+ fprintf (stderr, "%li %li %lu %zu\n", e2, t2, mpz_scan1 (t, 0), mpz_sizeinbase (t, 2));
+ dump ("na", a);
+ dump ("da", b);
+ dump ("nr", mpq_numref (rq));
+ dump ("dr", mpq_denref (rq));
+ abort ();
+ }
+
+ mpq_set_ui (aq, 0, 1);
+ mpq_set_ui (rq, 6, 7);
+ mpq_set (tq, aq);
+ mpq_div_2exp (rq, aq, e);
+
+ if (!mpq_equal (tq, rq))
+ {
+ fprintf (stderr, "mpq_div_2exp failed on zero: %lu\n", e);
+ abort ();
+ }
+
+ mpq_set_ui (rq, 7, 6);
+ mpq_mul_2exp (rq, aq, e);
+
+ if (!mpq_equal (rq, tq))
+ {
+ fprintf (stderr, "mpq_mul_2exp failed on zero: %lu\n", e);
+ abort ();
+ }
+ }
+
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (t);
+ mpq_clear (aq);
+ mpq_clear (rq);
+ mpq_clear (tq);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_str.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_str.c
new file mode 100644
index 0000000..e2b740a
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-mpq_str.c
@@ -0,0 +1,263 @@
+/*
+
+Copyright 2012-2014, 2016, 2018, 2020 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+#include "../mini-mpq.h"
+
+#define MAXBITS 400
+#define COUNT 2000
+
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+#define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
+
+static void
+test_small (void)
+{
+ struct {
+ const char *input;
+ const char *decimal;
+ } data[] = {
+ { "1832407/3", "1832407/3" },
+ { " 2763959/6", "2763959/6 " },
+ { "4 981 999 / 1 8", "4981999/18" },
+ { "10\t73981/30 ", "1073981/30" },
+ { "958 544 /1", "00958544/01" },
+ { "-0", "0000" },
+ { " -000 ", "0/ 1" },
+ { "0704436/011", "231710/9" },
+ /* Check the case of large number of leading zeros. */
+ { "0000000000000000000000000/1", "0/0000000000000000000000001" },
+ { "000000000000000704436/000011", "0000000000000000231710/00009" },
+ { " 012/ 02503517", "10/689999" },
+ { "0b 10/0 1312143", "2/365667" },
+ { "-03 274062/0x1", "-882738/1" },
+ { "012\t242", "005282" },
+ { "9/0b11010111110010001111", "9/883855" },
+ { "022/ 0b11001010010100001", "18/103585" },
+ { "-0b101010110011101111/0x12", "-175343/18" },
+ { "-05/0b 111 1111 0110 1110 0110", "-5/521958" },
+ { "0b 011 111 110 111 001 000 011/0b00110", "1044035/6" },
+ { " 0x53dfc", "343548" },
+ { "-0x00012/0x000fA019", "-18/1024025" },
+ { "0x 642d1", "410321" },
+ { "0x5 8067/0Xa", "360551/10" },
+ { "-0xd6Be6/3", "-879590/3" },
+ { "\t0B1110000100000000011", "460803" },
+ { "0B\t1111110010010100101", "517285" },
+ { "-0x 00 2d/0B1\t010111101101110100", "-45/359284" },
+ { "-0B101\t1001101111111001", "-367609" },
+ { "0B10001001010111110000/0xf", "562672/15" },
+ { "0Xe4B7e/1", "936830" },
+ { "0X1E4bf/0X1", "124095" },
+ { "-0Xfdb90/05", "-1039248/5" },
+ { "0b010/0X7fc47", "2/523335" },
+ { "15/0X8167c", "15/530044" },
+ /* Some invalid inputs */
+ { "", NULL },
+ { "0x", NULL },
+ { "0b", NULL },
+ { "0z", NULL },
+ { "-", NULL },
+ { "/0x ", NULL },
+ { "0|1", NULL },
+ { "/", NULL },
+ { "0ab", NULL },
+ { "10x0", NULL },
+ { "1/0xxab", NULL },
+ { "0/ab", NULL },
+ { "0/#", NULL },
+ { "$foo/1", NULL },
+ { NULL, NULL }
+ };
+ unsigned i;
+ mpq_t a, b;
+ mpq_init (a);
+ mpq_init (b);
+
+ for (i = 0; data[i].input; i++)
+ {
+ int res = mpq_set_str (a, data[i].input, 0);
+ if (data[i].decimal)
+ {
+ if (res != 0)
+ {
+ fprintf (stderr, "mpq_set_str returned -1, input: %s\n",
+ data[i].input);
+ abort ();
+ }
+ if (mpq_set_str (b, data[i].decimal, 10) != 0)
+ {
+ fprintf (stderr, "mpq_set_str returned -1, decimal input: %s\n",
+ data[i].input);
+ abort ();
+ }
+ if (!mpq_equal (a, b))
+ {
+ fprintf (stderr, "mpq_set_str failed for input: %s\n",
+ data[i].input);
+
+ dump ("got_num", mpq_numref (a));
+ dump ("got_den", mpq_denref (a));
+ dump ("ref_num", mpq_numref (b));
+ dump ("ref_den", mpq_denref (b));
+ abort ();
+ }
+ }
+ else if (res != -1)
+ {
+ fprintf (stderr, "mpq_set_str returned %d, invalid input: %s\n",
+ res, data[i].input);
+ abort ();
+ }
+ }
+
+ mpq_clear (a);
+ mpq_clear (b);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ char *ap;
+ char *bp;
+ char *rp;
+ size_t rn;
+
+ mpq_t a, b;
+
+ FILE *tmp;
+
+ test_small ();
+
+ mpq_init (a);
+ mpq_init (b);
+
+ tmp = tmpfile ();
+ if (!tmp)
+ fprintf (stderr,
+ "Failed to create temporary file. Skipping mpq_out_str tests.\n");
+
+ if (mpq_out_str (tmp, 63, a) != 0)
+ {
+ printf ("mpq_out_str did not return 0 (error) with base > 62\n");
+ abort ();
+ }
+
+ if (mpq_out_str (tmp, -37, a) != 0)
+ {
+ printf ("mpq_out_str did not return 0 (error) with base < -37\n");
+ abort ();
+ }
+
+ for (i = 0; i < COUNT/60; i++)
+ {
+ int base;
+ for (base = 2; base <= 62; ++base)
+ {
+ hex_mpq_random_str_op (MAXBITS, (i&1 || base > 36) ? base: -base, &ap, &rp);
+ if (mpq_set_str (a, ap, 16) != 0)
+ {
+ fprintf (stderr, "mpq_set_str failed on input %s\n", ap);
+ abort ();
+ }
+
+ rn = strlen (rp);
+
+ bp = mpq_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
+ if (strcmp (bp, rp))
+ {
+ fprintf (stderr, "mpz_get_str failed:\n");
+ dump ("a_num", mpq_numref (a));
+ dump ("a_den", mpq_denref (a));
+ fprintf (stderr, "b = %s\n", bp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", rp);
+ abort ();
+ }
+
+ /* Just a few tests with file i/o. */
+ if (tmp && i < 20)
+ {
+ size_t tn;
+ rewind (tmp);
+ tn = mpq_out_str (tmp, (i&1 || base > 36) ? base: -base, a);
+ if (tn != rn)
+ {
+ fprintf (stderr, "mpq_out_str, bad return value:\n");
+ dump ("a_num", mpq_numref (a));
+ dump ("a_den", mpq_denref (a));
+ fprintf (stderr, "r = %s\n", rp);
+ fprintf (stderr, " base %d, correct size %u, got %u\n",
+ base, (unsigned) rn, (unsigned)tn);
+ abort ();
+ }
+ rewind (tmp);
+ memset (bp, 0, rn);
+ tn = fread (bp, 1, rn, tmp);
+ if (tn != rn)
+ {
+ fprintf (stderr,
+ "fread failed, expected %lu bytes, got only %lu.\n",
+ (unsigned long) rn, (unsigned long) tn);
+ abort ();
+ }
+
+ if (memcmp (bp, rp, rn) != 0)
+ {
+ fprintf (stderr, "mpq_out_str failed:\n");
+ dump ("a_num", mpq_numref (a));
+ dump ("a_den", mpq_denref (a));
+ fprintf (stderr, "b = %s\n", bp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", rp);
+ abort ();
+ }
+ }
+
+ mpq_set_str (b, rp, base);
+
+ if (!mpq_equal (a, b))
+ {
+ fprintf (stderr, "mpq_set_str failed:\n");
+ fprintf (stderr, "r = %s\n", rp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", ap);
+ fprintf (stderr, " base = 16\n");
+ dump ("b_num", mpq_numref (b));
+ dump ("b_den", mpq_denref (b));
+ dump ("r_num", mpq_numref (a));
+ dump ("r_den", mpq_denref (a));
+ abort ();
+ }
+
+ free (ap);
+ free (rp);
+ testfree (bp, strlen(bp) + 1);
+ }
+ }
+ mpq_clear (a);
+ mpq_clear (b);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-mul.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-mul.c
new file mode 100644
index 0000000..57ec4ed
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-mul.c
@@ -0,0 +1,113 @@
+/*
+
+Copyright 2012, 2014, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+#define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, res, res_ui, ref, tz;
+ mp_limb_t t[2*MAXLIMBS];
+ mp_size_t an;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (res);
+ mpz_init (res_ui);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_MUL, MAXBITS, a, b, ref);
+ mpz_mul (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_mul failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ if (mpz_size (a) == mpz_size (b))
+ {
+ memset (t, 0x55, sizeof(t));
+ an = mpz_size (a);
+ if (an > 0)
+ {
+ mpn_mul_n (t, a->_mp_d, b->_mp_d, an);
+
+ mpz_roinit_n (tz, t, 2*an);
+ if (mpz_cmpabs (tz, ref))
+ {
+ fprintf (stderr, "mpn_mul_n failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ }
+ if (mpz_fits_slong_p (b)) {
+ mpz_mul_si (res_ui, a, mpz_get_si (b));
+ if (mpz_cmp (res_ui, ref))
+ {
+ fprintf (stderr, "mpz_mul_si failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res_ui);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ mini_random_op2 (OP_SQR, MAXBITS, a, ref);
+ an = mpz_size (a);
+ if (an > 0)
+ {
+ memset (t, 0x33, sizeof(t));
+ mpn_sqr (t, mpz_limbs_read (a), an);
+
+ mpz_roinit_n (tz, t, 2*an);
+ if (mpz_cmp (tz, ref))
+ {
+ fprintf (stderr, "mpn (squaring) failed:\n");
+ dump ("a", a);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (res);
+ mpz_clear (res_ui);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-powm.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-powm.c
new file mode 100644
index 0000000..1cce9b5
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-powm.c
@@ -0,0 +1,87 @@
+/*
+
+Copyright 2012, 2022, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 1000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t b, e, m, res, ref;
+
+ mpz_init (b);
+ mpz_init (e);
+ mpz_init (m);
+ mpz_init (res);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op4 (OP_POWM, MAXBITS, b, e, m, ref);
+ mpz_powm (res, b, e, m);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_powm failed:\n");
+ dump ("b", b);
+ dump ("e", e);
+ dump ("m", m);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+
+ /* res >= 0, come from the random choices above, */
+ if (mpz_cmp_ui (res, 1) <= 0) /* if too small, */
+ mpz_add_ui (res, res, 9); /* add an arbitrary value. */
+
+ mpz_set_ui (e, 0);
+ /* Test the case m^0 (mod m), expect 1 (m is greater than 1). */
+ mpz_powm (res, res, e, res);
+ if (mpz_cmp_ui (res, 1) != 0)
+ {
+ fprintf (stderr, "mpz_powm failed: b=m, e=0; 1 expected,\n");
+ dump ("m", res);
+ dump ("r", res);
+ abort ();
+ }
+
+ /* Now res is 1. */
+ /* Test the case 1^0 (mod 1), expect 0. */
+ mpz_powm (res, res, e, res);
+ if (mpz_size (res))
+ {
+ fprintf (stderr, "mpz_powm failed: b=1, e=0, m=1; 0 expected,\n");
+ dump ("r", res);
+ abort ();
+ }
+
+ mpz_clear (b);
+ mpz_clear (e);
+ mpz_clear (m);
+ mpz_clear (res);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-pprime_p.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-pprime_p.c
new file mode 100644
index 0000000..6cf9b18
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-pprime_p.c
@@ -0,0 +1,183 @@
+/* test mpz_probab_prime_p
+
+Copyright 2001, 2002, 2004, 2011, 2012, 2014, 2016 Free Software
+Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include "testutils.h"
+
+static int
+isprime (unsigned long int t)
+{
+ unsigned long int q, r, d;
+
+ if (t < 32)
+ return (0xa08a28acUL >> t) & 1;
+ if ((t & 1) == 0)
+ return 0;
+
+ if (t % 3 == 0)
+ return 0;
+ if (t % 5 == 0)
+ return 0;
+ if (t % 7 == 0)
+ return 0;
+
+ for (d = 11;;)
+ {
+ q = t / d;
+ r = t - q * d;
+ if (q < d)
+ return 1;
+ if (r == 0)
+ break;
+ d += 2;
+ q = t / d;
+ r = t - q * d;
+ if (q < d)
+ return 1;
+ if (r == 0)
+ break;
+ d += 4;
+ }
+ return 0;
+}
+
+static void
+check_one (mpz_srcptr n, int want)
+{
+ int got;
+
+ got = mpz_probab_prime_p (n, 25);
+
+ /* "definitely prime" is fine if we only wanted "probably prime" */
+ if (got == 2 && want == 1)
+ want = 2;
+
+ if (got != want)
+ {
+ printf ("mpz_probab_prime_p\n");
+ dump (" n ", n);
+ printf (" got =%d", got);
+ printf (" want=%d\n", want);
+ abort ();
+ }
+}
+
+static void
+check_pn (mpz_ptr n, int want)
+{
+ check_one (n, want);
+ mpz_neg (n, n);
+ check_one (n, want);
+}
+
+static void
+check_small (void)
+{
+ mpz_t n;
+ long i;
+
+ mpz_init (n);
+
+ for (i = 0; i < 1700; i++)
+ {
+ mpz_set_si (n, i);
+ check_pn (n, isprime (i));
+ }
+
+ mpz_clear (n);
+}
+
+void
+check_composites (void)
+{
+ int i;
+ int reps = 1000;
+ mpz_t a, b, n, bs;
+ unsigned long size_range, size;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (n);
+ mpz_init (bs);
+
+ for (i = 0; i < reps; i++)
+ {
+ mini_urandomb (bs, 16);
+ size_range = mpz_get_ui (bs) % 10 + 1; /* 0..1024 bit operands */
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (a, size);
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (b, size);
+
+ /* Exclude trivial factors */
+ if (mpz_cmp_ui (a, 1) == 0)
+ mpz_set_ui (a, 2);
+ if (mpz_cmp_ui (b, 1) == 0)
+ mpz_set_ui (b, 2);
+
+ mpz_mul (n, a, b);
+
+ check_pn (n, 0);
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (n);
+ mpz_clear (bs);
+}
+
+static void
+check_primes (void)
+{
+ static const char * const primes[] = {
+ "2", "17", "65537",
+ /* diffie-hellman-group1-sha1, also "Well known group 2" in RFC
+ 2412, 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */
+ "0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
+ "FFFFFFFFFFFFFFFF",
+ NULL
+ };
+
+ mpz_t n;
+ int i;
+
+ mpz_init (n);
+
+ for (i = 0; primes[i]; i++)
+ {
+ mpz_set_str_or_abort (n, primes[i], 0);
+ check_one (n, 1);
+ }
+ mpz_clear (n);
+}
+
+void
+testmain (int argc, char *argv[])
+{
+ check_small ();
+ check_composites ();
+ check_primes ();
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-reuse.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-reuse.c
new file mode 100644
index 0000000..09a5440
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-reuse.c
@@ -0,0 +1,663 @@
+/* Test that routines allow reusing a source variable as destination.
+
+Copyright 1996, 1999-2002, 2009, 2012 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define COUNT 100
+
+void dump3 (const char *, mpz_t, mpz_t, mpz_t);
+void mpz_check_format (const mpz_t);
+
+typedef void (*dss_func) (mpz_t, const mpz_t, const mpz_t);
+typedef void (*dsi_func) (mpz_t, const mpz_t, unsigned long int);
+typedef unsigned long int (*dsi_div_func) (mpz_t, const mpz_t, unsigned long int);
+typedef unsigned long int (*ddsi_div_func) (mpz_t, mpz_t, const mpz_t, unsigned long int);
+typedef void (*ddss_div_func) (mpz_t, mpz_t, const mpz_t, const mpz_t);
+typedef void (*ds_func) (mpz_t, const mpz_t);
+
+
+void
+mpz_xinvert (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ int res;
+ res = mpz_invert (r, a, b);
+ if (res == 0)
+ mpz_set_ui (r, 0);
+}
+
+dss_func dss_funcs[] =
+{
+ mpz_add, mpz_sub, mpz_mul,
+ mpz_cdiv_q, mpz_cdiv_r, mpz_fdiv_q, mpz_fdiv_r, mpz_tdiv_q, mpz_tdiv_r,
+ mpz_xinvert,
+ mpz_gcd, mpz_lcm, mpz_and, mpz_ior, mpz_xor
+};
+const char *dss_func_names[] =
+{
+ "mpz_add", "mpz_sub", "mpz_mul",
+ "mpz_cdiv_q", "mpz_cdiv_r", "mpz_fdiv_q", "mpz_fdiv_r", "mpz_tdiv_q", "mpz_tdiv_r",
+ "mpz_xinvert",
+ "mpz_gcd", "mpz_lcm", "mpz_and", "mpz_ior", "mpz_xor"
+};
+char dss_func_division[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
+
+dsi_func dsi_funcs[] =
+{
+ /* Don't change order here without changing the code in main(). */
+ mpz_add_ui, mpz_mul_ui, mpz_sub_ui,
+ mpz_fdiv_q_2exp, mpz_fdiv_r_2exp,
+ mpz_cdiv_q_2exp, mpz_cdiv_r_2exp,
+ mpz_tdiv_q_2exp, mpz_tdiv_r_2exp,
+ mpz_mul_2exp,
+ mpz_pow_ui
+};
+const char *dsi_func_names[] =
+{
+ "mpz_add_ui", "mpz_mul_ui", "mpz_sub_ui",
+ "mpz_fdiv_q_2exp", "mpz_fdiv_r_2exp",
+ "mpz_cdiv_q_2exp", "mpz_cdiv_r_2exp",
+ "mpz_tdiv_q_2exp", "mpz_tdiv_r_2exp",
+ "mpz_mul_2exp",
+ "mpz_pow_ui"
+};
+
+dsi_div_func dsi_div_funcs[] =
+{
+ mpz_cdiv_q_ui, mpz_cdiv_r_ui,
+ mpz_fdiv_q_ui, mpz_fdiv_r_ui,
+ mpz_tdiv_q_ui, mpz_tdiv_r_ui
+};
+const char *dsi_div_func_names[] =
+{
+ "mpz_cdiv_q_ui", "mpz_cdiv_r_ui",
+ "mpz_fdiv_q_ui", "mpz_fdiv_r_ui",
+ "mpz_tdiv_q_ui", "mpz_tdiv_r_ui"
+};
+
+ddsi_div_func ddsi_div_funcs[] =
+{
+ mpz_cdiv_qr_ui,
+ mpz_fdiv_qr_ui,
+ mpz_tdiv_qr_ui
+};
+const char *ddsi_div_func_names[] =
+{
+ "mpz_cdiv_qr_ui",
+ "mpz_fdiv_qr_ui",
+ "mpz_tdiv_qr_ui"
+};
+
+ddss_div_func ddss_div_funcs[] =
+{
+ mpz_cdiv_qr,
+ mpz_fdiv_qr,
+ mpz_tdiv_qr
+};
+const char *ddss_div_func_names[] =
+{
+ "mpz_cdiv_qr",
+ "mpz_fdiv_qr",
+ "mpz_tdiv_qr"
+};
+
+ds_func ds_funcs[] =
+{
+ mpz_abs, mpz_com, mpz_neg, mpz_sqrt
+};
+const char *ds_func_names[] =
+{
+ "mpz_abs", "mpz_com", "mpz_neg", "mpz_sqrt"
+};
+
+
+#define FAIL(class,indx,op1,op2,op3) \
+ do { \
+ class##_funcs[indx] = 0; \
+ dump3 (class##_func_names[indx], op1, op2, op3); \
+ failures++; \
+ } while (0)
+#define FAIL2(fname,op1,op2,op3) \
+ do { \
+ dump3 (#fname, op1, op2, op3); \
+ failures++; \
+ } while (0)
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ int pass, reps = COUNT;
+ mpz_t in1, in2, in3;
+ unsigned long int in2i;
+ mp_size_t size;
+ mpz_t res1, res2, res3;
+ mpz_t ref1, ref2, ref3;
+ mpz_t t;
+ unsigned long int r1, r2;
+ long failures = 0;
+ mpz_t bs;
+ unsigned long bsi, size_range;
+
+ mpz_init (bs);
+
+ mpz_init (in1);
+ mpz_init (in2);
+ mpz_init (in3);
+ mpz_init (ref1);
+ mpz_init (ref2);
+ mpz_init (ref3);
+ mpz_init (res1);
+ mpz_init (res2);
+ mpz_init (res3);
+ mpz_init (t);
+
+ for (pass = 1; pass <= reps; pass++)
+ {
+ mini_urandomb (bs, 32);
+ size_range = mpz_get_ui (bs) % 12 + 2;
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (in1, size);
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (in2, size);
+
+ mini_urandomb (bs, size_range);
+ size = mpz_get_ui (bs);
+ mini_rrandomb (in3, size);
+
+ mini_urandomb (bs, 3);
+ bsi = mpz_get_ui (bs);
+ if ((bsi & 1) != 0)
+ mpz_neg (in1, in1);
+ if ((bsi & 2) != 0)
+ mpz_neg (in2, in2);
+ if ((bsi & 4) != 0)
+ mpz_neg (in3, in3);
+
+ for (i = 0; i < numberof (dss_funcs); i++)
+ {
+ if (dss_funcs[i] == 0)
+ continue;
+ if (dss_func_division[i] && mpz_sgn (in2) == 0)
+ continue;
+
+ (dss_funcs[i]) (ref1, in1, in2);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ (dss_funcs[i]) (res1, res1, in2);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL (dss, i, in1, in2, NULL);
+
+ mpz_set (res1, in2);
+ (dss_funcs[i]) (res1, in1, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL (dss, i, in1, in2, NULL);
+ }
+
+ for (i = 0; i < numberof (ddss_div_funcs); i++)
+ {
+ if (ddss_div_funcs[i] == 0)
+ continue;
+ if (mpz_sgn (in2) == 0)
+ continue;
+
+ (ddss_div_funcs[i]) (ref1, ref2, in1, in2);
+ mpz_check_format (ref1);
+ mpz_check_format (ref2);
+
+ mpz_set (res1, in1);
+ (ddss_div_funcs[i]) (res1, res2, res1, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL (ddss_div, i, in1, in2, NULL);
+
+ mpz_set (res2, in1);
+ (ddss_div_funcs[i]) (res1, res2, res2, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL (ddss_div, i, in1, in2, NULL);
+
+ mpz_set (res1, in2);
+ (ddss_div_funcs[i]) (res1, res2, in1, res1);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL (ddss_div, i, in1, in2, NULL);
+
+ mpz_set (res2, in2);
+ (ddss_div_funcs[i]) (res1, res2, in1, res2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL (ddss_div, i, in1, in2, NULL);
+ }
+
+ for (i = 0; i < numberof (ds_funcs); i++)
+ {
+ if (ds_funcs[i] == 0)
+ continue;
+ if (strcmp (ds_func_names[i], "mpz_sqrt") == 0
+ && mpz_sgn (in1) < 0)
+ continue;
+
+ (ds_funcs[i]) (ref1, in1);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ (ds_funcs[i]) (res1, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL (ds, i, in1, in2, NULL);
+ }
+
+ in2i = mpz_get_ui (in2);
+
+ for (i = 0; i < numberof (dsi_funcs); i++)
+ {
+ if (dsi_funcs[i] == 0)
+ continue;
+ if (strcmp (dsi_func_names[i], "mpz_fdiv_q_2exp") == 0)
+ /* Limit exponent to something reasonable for the division
+ functions. Without this, we'd normally shift things off
+ the end and just generate the trivial values 1, 0, -1. */
+ in2i %= 0x1000;
+ if (strcmp (dsi_func_names[i], "mpz_mul_2exp") == 0)
+ /* Limit exponent more for mpz_mul_2exp to save time. */
+ in2i %= 0x100;
+ if (strcmp (dsi_func_names[i], "mpz_pow_ui") == 0)
+ /* Limit exponent yet more for mpz_pow_ui to save time. */
+ in2i %= 0x10;
+
+ (dsi_funcs[i]) (ref1, in1, in2i);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ (dsi_funcs[i]) (res1, res1, in2i);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL (dsi, i, in1, in2, NULL);
+ }
+
+ if (in2i != 0) /* Don't divide by 0. */
+ {
+ for (i = 0; i < numberof (dsi_div_funcs); i++)
+ {
+ r1 = (dsi_div_funcs[i]) (ref1, in1, in2i);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ r2 = (dsi_div_funcs[i]) (res1, res1, in2i);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
+ FAIL (dsi_div, i, in1, in2, NULL);
+ }
+
+ for (i = 0; i < numberof (ddsi_div_funcs); i++)
+ {
+ r1 = (ddsi_div_funcs[i]) (ref1, ref2, in1, in2i);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ r2 = (ddsi_div_funcs[i]) (res1, res2, res1, in2i);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
+ FAIL (ddsi_div, i, in1, in2, NULL);
+
+ mpz_set (res2, in1);
+ (ddsi_div_funcs[i]) (res1, res2, res2, in2i);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
+ FAIL (ddsi_div, i, in1, in2, NULL);
+ }
+ }
+
+ if (mpz_sgn (in1) >= 0)
+ {
+ mpz_sqrtrem (ref1, ref2, in1);
+ mpz_check_format (ref1);
+ mpz_check_format (ref2);
+
+ mpz_set (res1, in1);
+ mpz_sqrtrem (res1, res2, res1);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
+
+ mpz_set (res2, in1);
+ mpz_sqrtrem (res1, res2, res2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
+ }
+
+ if (mpz_sgn (in1) >= 0)
+ {
+ mpz_root (ref1, in1, in2i % 0x1000 + 1);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ mpz_root (res1, res1, in2i % 0x1000 + 1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_root, in1, in2, NULL);
+ }
+
+ if (mpz_sgn (in1) >= 0)
+ {
+ mpz_rootrem (ref1, ref2, in1, in2i % 0x1000 + 1);
+ mpz_check_format (ref1);
+ mpz_check_format (ref2);
+
+ mpz_set (res1, in1);
+ mpz_rootrem (res1, res2, res1, in2i % 0x1000 + 1);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL2 (mpz_rootrem, in1, in2, NULL);
+
+ mpz_set (res2, in1);
+ mpz_rootrem (res1, res2, res2, in2i % 0x1000 + 1);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
+ FAIL2 (mpz_rootrem, in1, in2, NULL);
+ }
+
+ if (pass < reps / 2) /* run fewer tests since gcdext lots of time */
+ {
+ mpz_gcdext (ref1, ref2, ref3, in1, in2);
+ mpz_check_format (ref1);
+ mpz_check_format (ref2);
+ mpz_check_format (ref3);
+
+ mpz_set (res1, in1);
+ mpz_gcdext (res1, res2, res3, res1, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ mpz_check_format (res3);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res2, in1);
+ mpz_gcdext (res1, res2, res3, res2, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ mpz_check_format (res3);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res3, in1);
+ mpz_gcdext (res1, res2, res3, res3, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ mpz_check_format (res3);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res1, in2);
+ mpz_gcdext (res1, res2, res3, in1, res1);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ mpz_check_format (res3);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res2, in2);
+ mpz_gcdext (res1, res2, res3, in1, res2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ mpz_check_format (res3);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res3, in2);
+ mpz_gcdext (res1, res2, res3, in1, res3);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ mpz_check_format (res3);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res1, in1);
+ mpz_gcdext (res1, res2, NULL, res1, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res2, in1);
+ mpz_gcdext (res1, res2, NULL, res2, in2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res1, in2);
+ mpz_gcdext (res1, res2, NULL, in1, res1);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+
+ mpz_set (res2, in2);
+ mpz_gcdext (res1, res2, NULL, in1, res2);
+ mpz_check_format (res1);
+ mpz_check_format (res2);
+ if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
+ || mpz_cmp (ref3, res3) != 0)
+ FAIL2 (mpz_gcdext, in1, in2, NULL);
+ }
+
+ /* Don't run mpz_powm for huge exponents or when undefined. */
+ if (mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
+ && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
+ {
+ mpz_powm (ref1, in1, in2, in3);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ mpz_powm (res1, res1, in2, in3);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_powm, in1, in2, in3);
+
+ mpz_set (res1, in2);
+ mpz_powm (res1, in1, res1, in3);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_powm, in1, in2, in3);
+
+ mpz_set (res1, in3);
+ mpz_powm (res1, in1, in2, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_powm, in1, in2, in3);
+ }
+
+ /* Don't run mpz_powm_ui when undefined. */
+ if (mpz_sgn (in3) != 0)
+ {
+ mpz_powm_ui (ref1, in1, in2i, in3);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ mpz_powm_ui (res1, res1, in2i, in3);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_powm_ui, in1, in2, in3);
+
+ mpz_set (res1, in3);
+ mpz_powm_ui (res1, in1, in2i, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_powm_ui, in1, in2, in3);
+ }
+
+ {
+ r1 = mpz_gcd_ui (ref1, in1, in2i);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ r2 = mpz_gcd_ui (res1, res1, in2i);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_gcd_ui, in1, in2, NULL);
+ }
+#if 0
+ if (mpz_cmp_ui (in2, 1L) > 0 && mpz_sgn (in1) != 0)
+ {
+ /* Test mpz_remove */
+ mpz_remove (ref1, in1, in2);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, in1);
+ mpz_remove (res1, res1, in2);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_remove, in1, in2, NULL);
+
+ mpz_set (res1, in2);
+ mpz_remove (res1, in1, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_remove, in1, in2, NULL);
+ }
+#endif
+ if (mpz_sgn (in2) != 0)
+ {
+ /* Test mpz_divexact */
+ mpz_mul (t, in1, in2);
+ mpz_divexact (ref1, t, in2);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, t);
+ mpz_divexact (res1, res1, in2);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_divexact, t, in2, NULL);
+
+ mpz_set (res1, in2);
+ mpz_divexact (res1, t, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_divexact, t, in2, NULL);
+ }
+
+#if 0
+ if (mpz_sgn (in2) > 0)
+ {
+ /* Test mpz_divexact_gcd, same as mpz_divexact */
+ mpz_mul (t, in1, in2);
+ mpz_divexact_gcd (ref1, t, in2);
+ mpz_check_format (ref1);
+
+ mpz_set (res1, t);
+ mpz_divexact_gcd (res1, res1, in2);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_divexact_gcd, t, in2, NULL);
+
+ mpz_set (res1, in2);
+ mpz_divexact_gcd (res1, t, res1);
+ mpz_check_format (res1);
+ if (mpz_cmp (ref1, res1) != 0)
+ FAIL2 (mpz_divexact_gcd, t, in2, NULL);
+ }
+#endif
+ }
+
+ if (failures != 0)
+ {
+ fprintf (stderr, "mpz/reuse: %ld error%s\n", failures, "s" + (failures == 1));
+ exit (1);
+ }
+
+ mpz_clear (bs);
+ mpz_clear (in1);
+ mpz_clear (in2);
+ mpz_clear (in3);
+ mpz_clear (ref1);
+ mpz_clear (ref2);
+ mpz_clear (ref3);
+ mpz_clear (res1);
+ mpz_clear (res2);
+ mpz_clear (res3);
+ mpz_clear (t);
+}
+
+void
+dump3 (const char *name, mpz_t in1, mpz_t in2, mpz_t in3)
+{
+ printf ("failure in %s (", name);
+ mpz_out_str (stdout, -16, in1);
+ if (in2 != NULL)
+ {
+ printf (" ");
+ mpz_out_str (stdout, -16, in2);
+ }
+ if (in3 != NULL)
+ {
+ printf (" ");
+ mpz_out_str (stdout, -16, in3);
+ }
+ printf (")\n");
+}
+
+void
+mpz_check_format (const mpz_t x)
+{
+ mp_size_t n = x ->_mp_size;
+ if (n < 0)
+ n = - n;
+
+ if (n > x->_mp_alloc)
+ {
+ fprintf (stderr, "mpz_t size exceeds allocation!\n");
+ abort ();
+ }
+
+ if (n > 0 && x->_mp_d[n-1] == 0)
+ {
+ fprintf (stderr, "Unnormalized mpz_t!\n");
+ abort ();
+ }
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-root.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-root.c
new file mode 100644
index 0000000..1f46c43
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-root.c
@@ -0,0 +1,95 @@
+/*
+
+Copyright 2012, 2013 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+/* Called when s is supposed to be floor(root(u,z)), and r = u - s^z */
+static int
+rootrem_valid_p (const mpz_t u, const mpz_t s, const mpz_t r, unsigned long z)
+{
+ mpz_t t;
+
+ mpz_init (t);
+ if (mpz_fits_ulong_p (s))
+ mpz_ui_pow_ui (t, mpz_get_ui (s), z);
+ else
+ mpz_pow_ui (t, s, z);
+ mpz_sub (t, u, t);
+ if ((mpz_sgn (t) != mpz_sgn(u) && mpz_sgn (t) != 0) || mpz_cmp (t, r) != 0)
+ {
+ mpz_clear (t);
+ return 0;
+ }
+ if (mpz_sgn (s) > 0)
+ mpz_add_ui (t, s, 1);
+ else
+ mpz_sub_ui (t, s, 1);
+ mpz_pow_ui (t, t, z);
+ if (mpz_cmpabs (t, u) <= 0)
+ {
+ mpz_clear (t);
+ return 0;
+ }
+
+ mpz_clear (t);
+ return 1;
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ unsigned long e;
+ mpz_t u, s, r, bs;
+
+ mpz_init (u);
+ mpz_init (s);
+ mpz_init (r);
+ mpz_init (bs);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_rrandomb (u, MAXBITS);
+ mini_rrandomb (bs, 12);
+ e = mpz_getlimbn (bs, 0) % mpz_sizeinbase (u, 2) + 1;
+ if ((e & 1) && (mpz_getlimbn (bs, 0) & (1L<<10)))
+ mpz_neg (u, u);
+ mpz_rootrem (s, r, u, e);
+
+ if (!rootrem_valid_p (u, s, r, e))
+ {
+ fprintf (stderr, "mpz_rootrem(%lu-th) failed:\n", e);
+ dump ("u", u);
+ dump ("root", s);
+ dump ("rem", r);
+ abort ();
+ }
+ }
+ mpz_clear (bs);
+ mpz_clear (u);
+ mpz_clear (s);
+ mpz_clear (r);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-scan.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-scan.c
new file mode 100644
index 0000000..39b1f35
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-scan.c
@@ -0,0 +1,90 @@
+/*
+
+Copyright 2012, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a;
+ mp_bitcnt_t b, res, ref;
+
+ mpz_init (a);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_scan_op (OP_SCAN0, MAXBITS, a, &b, &ref);
+ res = mpz_scan0 (a, b);
+ if (res != ref)
+ {
+ fprintf (stderr, "mpz_scan0 failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ fprintf (stderr, "r: %lu\n", res);
+ fprintf (stderr, "ref: %lu\n", ref);
+ abort ();
+ }
+ if (mpz_sgn (a) > 0 && ref < mpz_sizeinbase (a, 2))
+ {
+ res = mpn_scan0 (a->_mp_d, b);
+ if (res != ref)
+ {
+ fprintf (stderr, "mpn_scan0 failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ fprintf (stderr, "r: %lu\n", res);
+ fprintf (stderr, "ref: %lu\n", ref);
+ abort ();
+ }
+ }
+ mini_random_scan_op (OP_SCAN1, MAXBITS, a, &b, &ref);
+ res = mpz_scan1 (a, b);
+ if (res != ref)
+ {
+ fprintf (stderr, "mpz_scan1 failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ fprintf (stderr, "r: %lu\n", res);
+ fprintf (stderr, "ref: %lu\n", ref);
+ abort ();
+ }
+ if (mpz_sgn (a) > 0 && ref != ~ (mp_bitcnt_t) 0)
+ {
+ res = mpn_scan1 (a->_mp_d, b);
+ if (res != ref)
+ {
+ fprintf (stderr, "mpn_scan1 failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b: %lu\n", b);
+ fprintf (stderr, "r: %lu\n", res);
+ fprintf (stderr, "ref: %lu\n", ref);
+ abort ();
+ }
+ }
+ }
+ mpz_clear (a);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-signed.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-signed.c
new file mode 100644
index 0000000..cfa40d7
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-signed.c
@@ -0,0 +1,348 @@
+/* Exercise some mpz_..._si functions.
+
+Copyright 2013, 2016, 2020 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testutils.h"
+
+/* Always called with sz fitting in a signed long, and si is the
+ corresponding value. */
+int
+check_si (const mpz_t sz, long si)
+{
+ mpz_t t;
+
+ /* Checks on sz/si */
+ if ((mpz_cmp_si (sz, si)) != 0)
+ {
+ printf ("mpz_cmp_si (sz, %ld) != 0.\n", si);
+ return 0;
+ }
+ if (mpz_get_si (sz) != si)
+ {
+ printf ("mpz_get_si (sz) != %ld.\n", si);
+ return 0;
+ }
+
+ mpz_init_set_si (t, si);
+
+ if (mpz_cmp (t, sz) != 0)
+ {
+ printf ("mpz_init_set_si (%ld) failed.\n", si);
+ printf (" got="); mpz_out_str (stdout, 10, t); printf ("\n");
+ return 0;
+ }
+
+ mpz_clear (t);
+ return 1;
+}
+
+/* Called with mpz_cmp (sz, oz) == c. If sz fits in a signed long,
+ si is the coresponding value, and similarly for oz and oi. */
+void
+check_si_cmp (const mpz_t sz, const mpz_t oz, long si, long oi, int c)
+{
+ if (mpz_cmp (sz, oz) != c)
+ {
+ printf ("mpz_cmp (sz, oz) != %i.\n", c);
+ goto fail;
+ }
+
+ if (mpz_fits_slong_p (sz))
+ {
+ if (!check_si (sz, si))
+ goto fail;
+ if (mpz_cmp_si (oz, si) != -c)
+ {
+ printf ("mpz_cmp_si (oz, %ld) != %i.\n", si, -c);
+ goto fail;
+ }
+ }
+ else
+ {
+ if (mpz_cmp_si (sz, si) != c)
+ {
+ printf ("mpz_cmp_si (sz, %ld) != %i.\n", si, c);
+ goto fail;
+ }
+ if (mpz_cmp_si (sz, -c) != c)
+ {
+ printf ("mpz_cmp_si (sz, %i) != %i.\n", -c, c);
+ goto fail;
+ }
+ }
+ if (mpz_fits_slong_p (oz))
+ {
+ if (!check_si (oz, oi))
+ goto fail;
+ if (mpz_cmp_si (sz, oi) != c)
+ {
+ printf ("mpz_cmp_si (sz, %ld) != %i.\n", oi, c);
+ goto fail;
+ }
+ }
+ return;
+
+ fail:
+ printf (" sz="); mpz_out_str (stdout, 10, sz); printf ("\n");
+ printf (" si=%ld\n", si);
+ printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
+ printf (" oi=%ld\n", si);
+ abort ();
+}
+
+void
+try_op_si (int c)
+{
+ long si, oi;
+ mpz_t sz, oz;
+ unsigned overflow_count;
+
+ si = c;
+ mpz_init_set_si (sz, si);
+
+ oi = si;
+ mpz_init_set (oz, sz);
+
+ /* To get a few tests with operands straddling the border, don't
+ stop at the very first operand exceeding a signed long. */
+ for (overflow_count = 0; overflow_count < 10; )
+ {
+ /* c * 2^k */
+ mpz_mul_2exp (sz, sz, 1);
+ if (mpz_fits_slong_p (sz))
+ si *= 2;
+ else
+ overflow_count++;
+
+ check_si_cmp (sz, oz, si, oi, c);
+
+ /* c * (2^k + 1) */
+ if (c == -1)
+ mpz_sub_ui (oz, sz, 1);
+ else
+ mpz_add_ui (oz, sz, 1);
+ if (mpz_fits_slong_p (oz))
+ oi = si + c;
+ else
+ overflow_count++;
+ check_si_cmp (oz, sz, oi, si, c);
+
+ /* c * (2^K - 1) */
+ mpz_mul_si (oz, sz, 2*c);
+ if (c == -1)
+ mpz_ui_sub (oz, 1, oz); /* oz = sz * 2 + 1 */
+ else
+ mpz_sub_ui (oz, oz, 1); /* oz = sz * 2 - 1 */
+ if (mpz_fits_slong_p (oz))
+ oi = (si - c) * 2 + c;
+ else
+ overflow_count++;
+
+ check_si_cmp (oz, sz, oi, si, c);
+ };
+
+ mpz_clear (sz);
+ mpz_clear (oz);
+}
+
+void
+try_fits_slong_p (void)
+{
+ mpz_t x;
+ mpz_init_set_si (x, LONG_MAX);
+ if (!mpz_fits_slong_p (x))
+ {
+ printf ("mpz_fits_slong_p (LONG_MAX) false!\n");
+ abort ();
+ }
+ mpz_add_ui (x, x, 1);
+ if (mpz_fits_slong_p (x))
+ {
+ printf ("mpz_fits_slong_p (LONG_MAX + 1) true!\n");
+ abort ();
+ }
+ mpz_set_si (x, LONG_MIN);
+ if (!mpz_fits_slong_p (x))
+ {
+ printf ("mpz_fits_slong_p (LONG_MIN) false!\n");
+ abort ();
+ }
+ mpz_sub_ui (x, x, 1);
+ if (mpz_fits_slong_p (x))
+ {
+ printf ("mpz_fits_slong_p (LONG_MIN - 1) true!\n");
+ abort ();
+ }
+
+ mpz_clear (x);
+}
+
+void
+try_fits_utype_p (void)
+{
+ mpz_t x;
+ mpz_init (x);
+ if (!mpz_fits_ulong_p (x))
+ {
+ printf ("mpz_fits_ulong_p (0) false!\n");
+ abort ();
+ }
+ if (!mpz_fits_uint_p (x))
+ {
+ printf ("mpz_fits_uint_p (0) false!\n");
+ abort ();
+ }
+ if (!mpz_fits_ushort_p (x))
+ {
+ printf ("mpz_fits_udhort_p (0) false!\n");
+ abort ();
+ }
+ mpz_set_si (x, -1);
+ if (mpz_fits_ulong_p (x))
+ {
+ printf ("mpz_fits_ulong_p (- 1) true!\n");
+ abort ();
+ }
+ if (mpz_fits_uint_p (x))
+ {
+ printf ("mpz_fits_uint_p (- 1) true!\n");
+ abort ();
+ }
+ if (mpz_fits_ushort_p (x))
+ {
+ printf ("mpz_fits_ushort_p (- 1) true!\n");
+ abort ();
+ }
+ mpz_set_ui (x, ULONG_MAX);
+ if (!mpz_fits_ulong_p (x))
+ {
+ printf ("mpz_fits_ulong_p (ULONG_MAX) false!\n");
+ abort ();
+ }
+ mpz_add_ui (x, x, 1);
+ if (mpz_fits_ulong_p (x))
+ {
+ printf ("mpz_fits_ulong_p (ULONG_MAX + 1) true!\n");
+ abort ();
+ }
+ mpz_set_ui (x, UINT_MAX);
+ if (!mpz_fits_uint_p (x))
+ {
+ printf ("mpz_fits_uint_p (UINT_MAX) false!\n");
+ abort ();
+ }
+ mpz_add_ui (x, x, 1);
+ if (mpz_fits_uint_p (x))
+ {
+ printf ("mpz_fits_uint_p (UINT_MAX + 1) true!\n");
+ abort ();
+ }
+ mpz_set_ui (x, USHRT_MAX);
+ if (!mpz_fits_ushort_p (x))
+ {
+ printf ("mpz_fits_ushort_p (USHRT_MAX) false!\n");
+ abort ();
+ }
+ mpz_add_ui (x, x, 1);
+ if (mpz_fits_ushort_p (x))
+ {
+ printf ("mpz_fits_ushort_p (USHRT_MAX + 1) true!\n");
+ abort ();
+ }
+
+ mpz_clear (x);
+}
+
+void
+try_fits_sint_p (void)
+{
+ mpz_t x;
+ mpz_init_set_si (x, INT_MAX);
+ if (!mpz_fits_sint_p (x))
+ {
+ printf ("mpz_fits_sint_p (INT_MAX) false!\n");
+ abort ();
+ }
+ mpz_add_ui (x, x, 1);
+ if (mpz_fits_sint_p (x))
+ {
+ printf ("mpz_fits_sint_p (INT_MAX + 1) true!\n");
+ abort ();
+ }
+ mpz_set_si (x, INT_MIN);
+ if (!mpz_fits_sint_p (x))
+ {
+ printf ("mpz_fits_sint_p (INT_MIN) false!\n");
+ abort ();
+ }
+ mpz_sub_ui (x, x, 1);
+ if (mpz_fits_sint_p (x))
+ {
+ printf ("mpz_fits_sint_p (INT_MIN - 1) true!\n");
+ abort ();
+ }
+
+ mpz_clear (x);
+}
+
+void
+try_fits_sshort_p (void)
+{
+ mpz_t x;
+ mpz_init_set_si (x, SHRT_MAX);
+ if (!mpz_fits_sshort_p (x))
+ {
+ printf ("mpz_fits_sshort_p (SHRT_MAX) false!\n");
+ abort ();
+ }
+ mpz_add_ui (x, x, 1);
+ if (mpz_fits_sshort_p (x))
+ {
+ printf ("mpz_fits_sshort_p (SHRT_MAX + 1) true!\n");
+ abort ();
+ }
+ mpz_set_si (x, SHRT_MIN);
+ if (!mpz_fits_sshort_p (x))
+ {
+ printf ("mpz_fits_sshort_p (SHRT_MIN) false!\n");
+ abort ();
+ }
+ mpz_sub_ui (x, x, 1);
+ if (mpz_fits_sshort_p (x))
+ {
+ printf ("mpz_fits_sshort_p (SHRT_MIN - 1) true!\n");
+ abort ();
+ }
+
+ mpz_clear (x);
+}
+
+void
+testmain (int argc, char *argv[])
+{
+ try_fits_slong_p ();
+ try_fits_sint_p ();
+ try_fits_sshort_p ();
+ try_fits_utype_p ();
+ try_op_si (-1);
+ try_op_si (1);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-sqrt.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-sqrt.c
new file mode 100644
index 0000000..dd4c83a
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-sqrt.c
@@ -0,0 +1,181 @@
+/*
+
+Copyright 2012, 2014, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 9000
+
+/* Called when s is supposed to be floor(sqrt(u)), and r = u - s^2 */
+static int
+sqrtrem_valid_p (const mpz_t u, const mpz_t s, const mpz_t r)
+{
+ mpz_t t;
+
+ mpz_init (t);
+ mpz_mul (t, s, s);
+ mpz_sub (t, u, t);
+ if (mpz_sgn (t) < 0 || mpz_cmp (t, r) != 0)
+ {
+ mpz_clear (t);
+ return 0;
+ }
+ mpz_add_ui (t, s, 1);
+ mpz_mul (t, t, t);
+ if (mpz_cmp (t, u) <= 0)
+ {
+ mpz_clear (t);
+ return 0;
+ }
+
+ mpz_clear (t);
+ return 1;
+}
+
+void
+mpz_mpn_sqrtrem (mpz_t s, mpz_t r, const mpz_t u)
+{
+ mp_limb_t *sp, *rp;
+ mp_size_t un, sn, ret;
+
+ un = mpz_size (u);
+
+ mpz_xor (s, s, u);
+ sn = (un + 1) / 2;
+ sp = mpz_limbs_write (s, sn + 1);
+ sp [sn] = 11;
+
+ if (un & 1)
+ rp = NULL; /* Exploits the fact that r already is correct. */
+ else {
+ mpz_add (r, u, s);
+ rp = mpz_limbs_write (r, un + 1);
+ rp [un] = 19;
+ }
+
+ ret = mpn_sqrtrem (sp, rp, mpz_limbs_read (u), un);
+
+ if (sp [sn] != 11)
+ {
+ fprintf (stderr, "mpn_sqrtrem buffer overrun on sp.\n");
+ abort ();
+ }
+ if (un & 1) {
+ if ((ret != 0) != (mpz_size (r) != 0)) {
+ fprintf (stderr, "mpn_sqrtrem wrong return value with NULL.\n");
+ abort ();
+ }
+ } else {
+ mpz_limbs_finish (r, ret);
+ if ((size_t) ret != mpz_size (r)) {
+ fprintf (stderr, "mpn_sqrtrem wrong return value.\n");
+ abort ();
+ }
+ if (rp [un] != 19)
+ {
+ fprintf (stderr, "mpn_sqrtrem buffer overrun on rp.\n");
+ abort ();
+ }
+ }
+
+ mpz_limbs_finish (s, (un + 1) / 2);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t u, s, r;
+
+ mpz_init (s);
+ mpz_init (r);
+
+ mpz_init_set_si (u, -1);
+ if (mpz_perfect_square_p (u))
+ {
+ fprintf (stderr, "mpz_perfect_square_p failed on -1.\n");
+ abort ();
+ }
+
+ if (!mpz_perfect_square_p (s))
+ {
+ fprintf (stderr, "mpz_perfect_square_p failed on 0.\n");
+ abort ();
+ }
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_rrandomb (u, MAXBITS - (i & 0xFF));
+ mpz_sqrtrem (s, r, u);
+
+ if (!sqrtrem_valid_p (u, s, r))
+ {
+ fprintf (stderr, "mpz_sqrtrem failed:\n");
+ dump ("u", u);
+ dump ("sqrt", s);
+ dump ("rem", r);
+ abort ();
+ }
+
+ mpz_mpn_sqrtrem (s, r, u);
+
+ if (!sqrtrem_valid_p (u, s, r))
+ {
+ fprintf (stderr, "mpn_sqrtrem failed:\n");
+ dump ("u", u);
+ dump ("sqrt", s);
+ dump ("rem", r);
+ abort ();
+ }
+
+ if (mpz_sgn (r) == 0) {
+ mpz_neg (u, u);
+ mpz_sub_ui (u, u, 1);
+ }
+
+ if ((mpz_sgn (u) <= 0 || (i & 1)) ?
+ mpz_perfect_square_p (u) :
+ mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u)))
+ {
+ fprintf (stderr, "mp%s_perfect_square_p failed on non square:\n",
+ (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
+ dump ("u", u);
+ abort ();
+ }
+
+ mpz_mul (u, s, s);
+ if (!((mpz_sgn (u) <= 0 || (i & 1)) ?
+ mpz_perfect_square_p (u) :
+ mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u))))
+ {
+ fprintf (stderr, "mp%s_perfect_square_p failed on square:\n",
+ (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
+ dump ("u", u);
+ abort ();
+ }
+
+ }
+ mpz_clear (u);
+ mpz_clear (s);
+ mpz_clear (r);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-str.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-str.c
new file mode 100644
index 0000000..d4dce1e
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-str.c
@@ -0,0 +1,332 @@
+/*
+
+Copyright 2012-2014, 2016 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 2000
+
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+#define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
+
+static void
+test_small (void)
+{
+ struct {
+ const char *input;
+ const char *decimal;
+ } data[] = {
+ { "183407", "183407" },
+ { " 763959", "763959 " },
+ { "9 81999", "981999" },
+ { "10\t7398 ", "107398" },
+ { "-9585 44", "-00958544" },
+ { "-0", "0000" },
+ { " -000 ", "0" },
+ { "0704436", "231710" },
+ /* Check the case of large number of leading zeros. */
+ { "0000000000000000000000000", "0000000000000000000000000" },
+ { "000000000000000000000000704436", "000000000000000000000000231710" },
+ { " 02503517", "689999" },
+ { "0 1312143", "365667" },
+ { "-03 274062", "-882738" },
+ { "012\t242", "005282" },
+ { "0b11010111110010001111", "883855" },
+ { " 0b11001010010100001", "103585" },
+ { "-0b101010110011101111", "-175343" },
+ { "0b 1111111011011100110", "521958" },
+ { "0b1 1111110111001000011", "1044035" },
+ { " 0x53dfc", "343548" },
+ { "0xfA019", "1024025" },
+ { "0x 642d1", "410321" },
+ { "0x5 8067", "360551" },
+ { "-0xd6Be6", "-879590" },
+ { "\t0B1110000100000000011", "460803" },
+ { "0B\t1111110010010100101", "517285" },
+ { "0B1\t010111101101110100", "359284" },
+ { "-0B101\t1001101111111001", "-367609" },
+ { "0B10001001010111110000", "562672" },
+ { "0Xe4B7e", "936830" },
+ { "0X1E4bf", "124095" },
+ { "-0Xfdb90", "-1039248" },
+ { "0X7fc47", "523335" },
+ { "0X8167c", "530044" },
+ /* Some invalid inputs */
+ { "", NULL },
+ { "0x", NULL },
+ { "0b", NULL },
+ { "0z", NULL },
+ { "-", NULL },
+ { "-0x ", NULL },
+ { "0|1", NULL },
+ { "4+4", NULL },
+ { "0ab", NULL },
+ { "10x0", NULL },
+ { "0xxab", NULL },
+ { "ab", NULL },
+ { "0%#", NULL },
+ { "$foo", NULL },
+ { NULL, NULL }
+ };
+ unsigned i;
+ mpz_t a, b;
+ mpz_init (b);
+
+ for (i = 0; data[i].input; i++)
+ {
+ int res = mpz_init_set_str (a, data[i].input, 0);
+ if (data[i].decimal)
+ {
+ if (res != 0)
+ {
+ fprintf (stderr, "mpz_set_str returned -1, input: %s\n",
+ data[i].input);
+ abort ();
+ }
+ if (mpz_set_str (b, data[i].decimal, 10) != 0)
+ {
+ fprintf (stderr, "mpz_set_str returned -1, decimal input: %s\n",
+ data[i].input);
+ abort ();
+ }
+ if (mpz_cmp (a, b) != 0)
+ {
+ fprintf (stderr, "mpz_set_str failed for input: %s\n",
+ data[i].input);
+
+ dump ("got", a);
+ dump ("ref", b);
+ abort ();
+ }
+ }
+ else if (res != -1)
+ {
+ fprintf (stderr, "mpz_set_str returned %d, invalid input: %s\n",
+ res, data[i].input);
+ abort ();
+ }
+ mpz_clear (a);
+ }
+
+ mpz_clear (b);
+}
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ char *ap;
+ char *bp;
+ char *rp;
+ size_t bn, rn, arn, bps;
+
+ mpz_t a, b;
+
+ FILE *tmp;
+
+ test_small ();
+
+ mpz_init (a);
+ mpz_init (b);
+
+ tmp = tmpfile ();
+ if (!tmp)
+ fprintf (stderr,
+ "Failed to create temporary file. Skipping mpz_out_str tests.\n");
+
+ if (mpz_out_str (tmp, 63, a) != 0)
+ {
+ printf ("mpz_out_str did not return 0 (error) with base > 62\n");
+ abort ();
+ }
+
+ if (mpz_out_str (tmp, -37, a) != 0)
+ {
+ printf ("mpz_out_str did not return 0 (error) with base < -37\n");
+ abort ();
+ }
+
+ for (i = 0; i < COUNT; i++)
+ {
+ int base;
+ for (base = 0; base <= 62; base += 1 + (base == 0))
+ {
+ hex_random_str_op (MAXBITS, (i&1 || base > 36) ? base: -base, &ap, &rp);
+ if (mpz_set_str (a, ap, 16) != 0)
+ {
+ fprintf (stderr, "mpz_set_str failed on input %s\n", ap);
+ abort ();
+ }
+
+ rn = strlen (rp);
+ arn = rn - (rp[0] == '-');
+
+ bn = mpz_sizeinbase (a, base ? base : 10);
+ if (bn < arn || bn > (arn + 1))
+ {
+ fprintf (stderr, "mpz_sizeinbase failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "r = %s\n", rp);
+ fprintf (stderr, " base %d, correct size %u, got %u\n",
+ base, (unsigned) arn, (unsigned)bn);
+ abort ();
+ }
+ bp = mpz_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
+ bps = strlen(bp) + 1;
+ if (strcmp (bp, rp))
+ {
+ fprintf (stderr, "mpz_get_str failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b = %s\n", bp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", rp);
+ abort ();
+ }
+
+ /* Just a few tests with file i/o. */
+ if (tmp && i < 20)
+ {
+ size_t tn;
+ rewind (tmp);
+ tn = mpz_out_str (tmp, (i&1 || base > 36) ? base: -base, a);
+ if (tn != rn)
+ {
+ fprintf (stderr, "mpz_out_str, bad return value:\n");
+ dump ("a", a);
+ fprintf (stderr, "r = %s\n", rp);
+ fprintf (stderr, " base %d, correct size %u, got %u\n",
+ base, (unsigned) rn, (unsigned)tn);
+ abort ();
+ }
+ rewind (tmp);
+ memset (bp, 0, rn);
+ tn = fread (bp, 1, rn, tmp);
+ if (tn != rn)
+ {
+ fprintf (stderr,
+ "fread failed, expected %lu bytes, got only %lu.\n",
+ (unsigned long) rn, (unsigned long) tn);
+ abort ();
+ }
+
+ if (memcmp (bp, rp, rn) != 0)
+ {
+ fprintf (stderr, "mpz_out_str failed:\n");
+ dump ("a", a);
+ fprintf (stderr, "b = %s\n", bp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", rp);
+ abort ();
+ }
+ }
+
+ mpz_set_str (b, rp, base);
+
+ if (mpz_cmp (a, b))
+ {
+ fprintf (stderr, "mpz_set_str failed:\n");
+ fprintf (stderr, "r = %s\n", rp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", ap);
+ fprintf (stderr, " base = 16\n");
+ dump ("b", b);
+ dump ("r", a);
+ abort ();
+ }
+
+ /* Test mpn interface */
+ if (base && mpz_sgn (a))
+ {
+ size_t i;
+ const char *absr;
+ mp_limb_t t[MAXLIMBS];
+ size_t tn = mpz_size (a);
+
+ assert (tn <= MAXLIMBS);
+ mpn_copyi (t, a->_mp_d, tn);
+
+ bn = mpn_get_str ((unsigned char *) bp, base, t, tn);
+ if (bn != arn)
+ {
+ fprintf (stderr, "mpn_get_str failed:\n");
+ fprintf (stderr, "returned length: %lu (bad)\n", (unsigned long) bn);
+ fprintf (stderr, "expected: %lu\n", (unsigned long) arn);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", ap);
+ fprintf (stderr, " base = 16\n");
+ dump ("b", b);
+ dump ("r", a);
+ abort ();
+ }
+ absr = rp + (rp[0] == '-');
+
+ for (i = 0; i < bn; i++)
+ {
+ unsigned char digit = absr[i];
+ char value;
+ if (digit >= '0' && digit <= '9')
+ value = digit - '0';
+ else if (digit >= 'a' && digit <= 'z')
+ value = digit - 'a' + ((base > 36) ? 36 : 10);
+ else if (digit >= 'A' && digit <= 'Z')
+ value = digit - 'A' + 10;
+ else
+ {
+ fprintf (stderr, "Internal error in test.\n");
+ abort();
+ }
+ if (bp[i] != value)
+ {
+ fprintf (stderr, "mpn_get_str failed:\n");
+ fprintf (stderr, "digit %lu: %d (bad)\n", (unsigned long) i, bp[i]);
+ fprintf (stderr, "expected: %d\n", value);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", ap);
+ fprintf (stderr, " base = 16\n");
+ dump ("b", b);
+ dump ("r", a);
+ abort ();
+ }
+ }
+ tn = mpn_set_str (t, (unsigned char *) bp, bn, base);
+ if (tn != mpz_size (a) || mpn_cmp (t, a->_mp_d, tn))
+ {
+ fprintf (stderr, "mpn_set_str failed:\n");
+ fprintf (stderr, "r = %s\n", rp);
+ fprintf (stderr, " base = %d\n", base);
+ fprintf (stderr, "r = %s\n", ap);
+ fprintf (stderr, " base = 16\n");
+ dump ("r", a);
+ abort ();
+ }
+ }
+ free (ap);
+ free (rp);
+ testfree (bp, bps);
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/t-sub.c b/vendor/gmp-6.3.0/mini-gmp/tests/t-sub.c
new file mode 100644
index 0000000..e230fda
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/t-sub.c
@@ -0,0 +1,71 @@
+/*
+
+Copyright 2012, 2013 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "testutils.h"
+
+#define MAXBITS 400
+#define COUNT 10000
+
+void
+testmain (int argc, char **argv)
+{
+ unsigned i;
+ mpz_t a, b, res, res_ui, ref;
+
+ mpz_init (a);
+ mpz_init (b);
+ mpz_init (res);
+ mpz_init (res_ui);
+ mpz_init (ref);
+
+ for (i = 0; i < COUNT; i++)
+ {
+ mini_random_op3 (OP_SUB, MAXBITS, a, b, ref);
+ mpz_sub (res, a, b);
+ if (mpz_cmp (res, ref))
+ {
+ fprintf (stderr, "mpz_sub failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res);
+ dump ("ref", ref);
+ abort ();
+ }
+ if (mpz_fits_ulong_p (a)) {
+ mpz_ui_sub (res_ui, mpz_get_ui (a), b);
+ if (mpz_cmp (res_ui, ref))
+ {
+ fprintf (stderr, "mpz_ui_sub failed:\n");
+ dump ("a", a);
+ dump ("b", b);
+ dump ("r", res_ui);
+ dump ("ref", ref);
+ abort ();
+ }
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (res);
+ mpz_clear (res_ui);
+ mpz_clear (ref);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/testutils.c b/vendor/gmp-6.3.0/mini-gmp/tests/testutils.c
new file mode 100644
index 0000000..46e368a
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/testutils.c
@@ -0,0 +1,196 @@
+/*
+
+Copyright 2013-2015, 2018 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include "testutils.h"
+
+/* Include it here, so we we could tweak, e.g., how MPZ_REALLOC
+ works. */
+#include "../mini-gmp.c"
+#include "../mini-mpq.c"
+
+static size_t total_alloc = 0;
+
+/* Custom memory allocation to track memory usage, and add a small red
+ zone.
+
+ About alignment: In general, getting a block from malloc, and
+ incrementing it by sizeof(size_t), like we do here, might give a
+ pointer which is not properly aligned for all types. But the
+ largest type we allocate space for is unsigned long (mp_limb_t),
+ which shouldn't have stricter alignment requirements than
+ size_t. */
+
+static unsigned char block_end[8] =
+ { 0x7c, 0x37, 0xd6, 0x12, 0xa8, 0x6c, 0x01, 0xd1 };
+
+static void *
+block_init (size_t *block, size_t size)
+{
+ char *p;
+ *block++ = size;
+
+ p = (char *) block;
+ memcpy (p + size, block_end, sizeof(block_end));
+
+ total_alloc += size;
+ return p;
+}
+
+/* Check small redzone, return pointer to malloced block. */
+static size_t *
+block_check (void *p)
+{
+ size_t *block = (size_t *) p - 1;
+ size_t size = block[0];
+
+ if (memcmp ((char *)p + size, block_end, sizeof(block_end)) != 0)
+ {
+ fprintf (stderr, "red zone overwritten.\n");
+ abort ();
+ }
+ total_alloc -= size;
+ return block;
+}
+
+static void *
+tu_alloc (size_t size)
+{
+ size_t *block = (size_t *) malloc (sizeof(size_t) + size + sizeof(block_end));
+ if (!block)
+ {
+ fprintf (stderr, "Virtual memory exhausted.\n");
+ abort ();
+ }
+
+ return block_init (block, size);
+}
+
+static void *
+tu_realloc (void *p, size_t old_size, size_t new_size)
+{
+ size_t *block;
+ size_t *old_block = block_check (p);
+ if (old_block[0] != old_size)
+ {
+ fprintf (stderr, "%s:%d: bad old_size: want %ld, got %ld.\n", __FILE__, __LINE__,
+ (long)old_block[0], (long)old_size);
+ abort ();
+ }
+
+ block = (size_t *) realloc (old_block, sizeof(size_t) + new_size + sizeof(block_end));
+ if (!block)
+ {
+ fprintf (stderr, "Virtual memory exhausted.\n");
+ abort ();
+ }
+
+ return block_init (block, new_size);
+}
+
+static void
+tu_free (void *p, size_t old_size)
+{
+ size_t *old_block = block_check (p);
+ if (old_block[0] != old_size && old_size != 0)
+ {
+ fprintf (stderr, "%s:%d: bad old_size: want %ld, got %ld.\n", __FILE__, __LINE__,
+ (long)old_block[0], (long)old_size);
+ abort ();
+ }
+ free (old_block);
+}
+
+/* Free memory allocated via mini-gmp allocation function. */
+void
+testfree (void *p, size_t size)
+{
+ void (*freefunc) (void *, size_t);
+ mp_get_memory_functions (NULL, NULL, &freefunc);
+
+ freefunc (p, size);
+}
+
+int
+main (int argc, char **argv)
+{
+ hex_random_init ();
+
+ mp_set_memory_functions (tu_alloc, tu_realloc, tu_free);
+
+ /* Currently, t-comb seems to be the only program accepting any
+ arguments. It might make sense to parse common arguments here. */
+ testmain (argc, argv);
+
+ if (total_alloc != 0)
+ {
+ fprintf (stderr, "Memory leaked: %lu bytes.\n",
+ (unsigned long) total_alloc);
+ abort ();
+ }
+ return 0;
+}
+
+void
+testhalves (int count, void (*tested_fun) (int))
+{
+ void (*freefunc) (void *, size_t);
+ void *(*reallocfunc) (void *, size_t, size_t);
+ void *(*allocfunc) (size_t);
+ size_t initial_alloc;
+
+ mp_get_memory_functions (&allocfunc, &reallocfunc, &freefunc);
+ initial_alloc = total_alloc;
+ (*tested_fun) (count / 2);
+ if (initial_alloc != total_alloc)
+ {
+ fprintf (stderr, "First half, memory leaked: %lu bytes.\n",
+ (unsigned long) total_alloc - initial_alloc);
+ abort ();
+ }
+ mp_set_memory_functions (NULL, NULL, NULL);
+ (*tested_fun) (count / 2);
+ mp_set_memory_functions (allocfunc, reallocfunc, freefunc);
+}
+
+void
+dump (const char *label, const mpz_t x)
+{
+ char *buf = mpz_get_str (NULL, 16, x);
+ fprintf (stderr, "%s: %s\n", label, buf);
+ testfree (buf, strlen(buf) + 1);
+}
+
+void
+mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
+{
+ if (mpz_set_str (z, str, base) != 0)
+ {
+ fprintf (stderr, "ERROR: mpz_set_str failed\n");
+ fprintf (stderr, " str = \"%s\"\n", str);
+ fprintf (stderr, " base = %d\n", base);
+ abort();
+ }
+}
+
+int
+mpz_lucas_mod (mpz_t V, mpz_t Qk, long Q,
+ mp_bitcnt_t b0, const mpz_t n)
+{
+ return gmp_lucas_mod (V, Qk, Q, b0, n);
+}
diff --git a/vendor/gmp-6.3.0/mini-gmp/tests/testutils.h b/vendor/gmp-6.3.0/mini-gmp/tests/testutils.h
new file mode 100644
index 0000000..bcc08c5
--- /dev/null
+++ b/vendor/gmp-6.3.0/mini-gmp/tests/testutils.h
@@ -0,0 +1,42 @@
+/*
+
+Copyright 2013, 2014, 2018, Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mini-random.h"
+
+#define numberof(x) (sizeof (x) / sizeof ((x)[0]))
+
+void testmain (int argc, char **argv);
+
+void testhalves (int count, void (*tested_fun) (int));
+
+void testfree (void *p, size_t size);
+
+void
+dump (const char *label, const mpz_t x);
+
+void
+mpz_set_str_or_abort (mpz_ptr z, const char *str, int base);
+
+/* Prototype for wrappers to internal functions to be tested. */
+int
+mpz_lucas_mod (mpz_t V, mpz_t Qk, long Q,
+ mp_bitcnt_t b0, const mpz_t n);