Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -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.

View File

@@ -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.

File diff suppressed because it is too large Load Diff

View File

@@ -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__ */

View File

@@ -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);
}
}

View File

@@ -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__ */

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 *);

View File

@@ -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 ]

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 ();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 ();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 ();
}

View File

@@ -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 ();
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);