diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-04-11 13:54:39 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-04-11 13:54:39 +0000 |
commit | 985398b4b9dadafbdc1600e12707dee74cab4cd8 (patch) | |
tree | fffa9d39f59c68d812ee9e20deba3e565b1f7c19 | |
parent | e9dc7e9f72cc13e5dfdd3cca1a56b2d4cc823e95 (diff) | |
download | mpfr-985398b4b9dadafbdc1600e12707dee74cab4cd8.tar.gz |
Merged recent tests from the trunk (r12288-12347).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/4.0@12579 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | tests/tagm.c | 1 | ||||
-rw-r--r-- | tests/tai.c | 94 | ||||
-rw-r--r-- | tests/tdiv.c | 122 | ||||
-rw-r--r-- | tests/tgmpop.c | 39 | ||||
-rw-r--r-- | tests/tmul.c | 164 | ||||
-rw-r--r-- | tests/tmul_2exp.c | 38 | ||||
-rw-r--r-- | tests/tsqrt.c | 228 | ||||
-rw-r--r-- | tests/tsub.c | 13 | ||||
-rw-r--r-- | tests/tzeta.c | 20 |
9 files changed, 699 insertions, 20 deletions
diff --git a/tests/tagm.c b/tests/tagm.c index ac314ef73..9627ab5a8 100644 --- a/tests/tagm.c +++ b/tests/tagm.c @@ -354,7 +354,6 @@ main (int argc, char* argv[]) tests_start_mpfr (); check_special (); - check_large (); check_eq (); check4 ("2.0", "1.0", MPFR_RNDN, "1.456791031046906869", -1); diff --git a/tests/tai.c b/tests/tai.c index c6b82b20c..f15eea86a 100644 --- a/tests/tai.c +++ b/tests/tai.c @@ -133,11 +133,105 @@ bug20180107 (void) mpfr_clear (z); } +/* exercise mpfr_ai near m*2^e, for precision p */ +static void +test_near_m2e (long m, mpfr_exp_t e, mpfr_prec_t pmax) +{ + mpfr_t x, xx, y, yy; + mpfr_prec_t p; + int inex; + + mpfr_clear_flags (); + + /* first determine the smallest precision for which m*2^e is exact */ + for (p = MPFR_PREC_MIN; p <= pmax; p++) + { + mpfr_init2 (x, p); + inex = mpfr_set_si_2exp (x, m, e, MPFR_RNDN); + mpfr_clear (x); + if (inex == 0) + break; + } + + mpfr_init2 (x, p); + inex = mpfr_set_si_2exp (x, m, e, MPFR_RNDN); + MPFR_ASSERTN(inex == 0); + + for (; p <= pmax; p++) + { + mpfr_init2 (y, p); + mpfr_init2 (xx, p); + mpfr_init2 (yy, p); + mpfr_prec_round (x, p, MPFR_RNDN); + mpfr_ai (y, x, MPFR_RNDN); + while (1) + { + mpfr_set (xx, x, MPFR_RNDN); + mpfr_nextbelow (xx); + mpfr_ai (yy, xx, MPFR_RNDN); + if (mpfr_cmpabs (yy, y) >= 0) + break; + else + { + mpfr_set (x, xx, MPFR_RNDN); + mpfr_set (y, yy, MPFR_RNDN); + } + } + while (1) + { + mpfr_set (xx, x, MPFR_RNDN); + mpfr_nextabove (xx); + mpfr_ai (yy, xx, MPFR_RNDN); + if (mpfr_cmpabs (yy, y) >= 0) + break; + else + { + mpfr_set (x, xx, MPFR_RNDN); + mpfr_set (y, yy, MPFR_RNDN); + } + } + mpfr_clear (y); + mpfr_clear (xx); + mpfr_clear (yy); + } + + mpfr_clear (x); + + /* Since some tests don't really check that the result is not NaN... */ + MPFR_ASSERTN (! mpfr_nanflag_p ()); +} + +/* example provided by Sylvain Chevillard, which exercises the case + wprec < err + 1, and thus correct_bits = 0, in src/ai.c */ +static void +coverage (void) +{ + mpfr_t x, y; + int inex; + + mpfr_init2 (x, 800); + mpfr_init2 (y, 20); + mpfr_set_str (x, "-2.3381074104597670384891972524467354406385401456723878524838544372136680027002836477821640417313293202847600938532659527752254668583598667448688987168197275409731526749911127480659996456283534915503672", 10, MPFR_RNDN); + inex = mpfr_ai (y, x, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 593131, -682) == 0); + + mpfr_clear (x); + mpfr_clear (y); +} + int main (int argc, char *argv[]) { tests_start_mpfr (); + coverage (); + test_near_m2e (-5, -1, 100); /* exercise near -2.5 */ + test_near_m2e (-4, 0, 100); /* exercise near -4 */ + test_near_m2e (-11, -1, 100); /* exercise near -5.5 */ + test_near_m2e (-27, -2, 100); /* exercise near -6.75 */ + test_near_m2e (-31, -2, 100); /* exercise near -7.75 */ + test_near_m2e (-15, -1, 100); /* exercise near -7.5 */ bug20180107 (); check_large (); check_zero (); diff --git a/tests/tdiv.c b/tests/tdiv.c index 6bfec0b18..2b328c5f3 100644 --- a/tests/tdiv.c +++ b/tests/tdiv.c @@ -1597,11 +1597,133 @@ bug20180126 (void) } /* j */ } +static void +coverage (mpfr_prec_t pmax) +{ + mpfr_prec_t p; + + for (p = MPFR_PREC_MIN; p <= pmax; p++) + { + int inex; + mpfr_t q, u, v; + + mpfr_init2 (q, p); + mpfr_init2 (u, p); + mpfr_init2 (v, p); + + /* exercise case qx < emin */ + mpfr_set_ui_2exp (u, 1, mpfr_get_emin (), MPFR_RNDN); + mpfr_set_ui (v, 4, MPFR_RNDN); + + mpfr_clear_flags (); + /* u/v = 2^(emin-2), should be rounded to +0 for RNDN */ + inex = mpfr_div (q, u, v, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (q) && mpfr_signbit (q) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_clear_flags (); + /* u/v = 2^(emin-2), should be rounded to 2^(emin-1) for RNDU */ + inex = mpfr_div (q, u, v, MPFR_RNDU); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (q, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_clear_flags (); + /* u/v = 2^(emin-2), should be rounded to +0 for RNDZ */ + inex = mpfr_div (q, u, v, MPFR_RNDZ); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (q) && mpfr_signbit (q) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + if (p == 1) + goto end_of_loop; + + mpfr_set_ui_2exp (u, 1, mpfr_get_emin (), MPFR_RNDN); + mpfr_nextbelow (u); /* u = (1-2^(-p))*2^emin */ + mpfr_set_ui (v, 2, MPFR_RNDN); + + mpfr_clear_flags (); + /* u/v = (1-2^(-p))*2^(emin-1), will round to 2^(emin-1) for RNDN */ + inex = mpfr_div (q, u, v, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (q, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_clear_flags (); + /* u/v should round to 2^(emin-1) for RNDU */ + inex = mpfr_div (q, u, v, MPFR_RNDU); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (q, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_clear_flags (); + /* u/v should round to +0 for RNDZ */ + inex = mpfr_div (q, u, v, MPFR_RNDZ); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (q) && mpfr_signbit (q) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + end_of_loop: + mpfr_clear (q); + mpfr_clear (u); + mpfr_clear (v); + } +} + +/* coverage for case usize >= n + n in Mulders' algorithm */ +static void +coverage2 (void) +{ + mpfr_prec_t p; + mpfr_t q, u, v, t, w; + int inex, inex2; + + p = MPFR_DIV_THRESHOLD * GMP_NUMB_BITS; + mpfr_init2 (q, p); + mpfr_init2 (u, 2 * p + 3 * GMP_NUMB_BITS); + mpfr_init2 (v, p); + do mpfr_urandomb (u, RANDS); while (mpfr_zero_p (u)); + do mpfr_urandomb (v, RANDS); while (mpfr_zero_p (v)); + inex = mpfr_div (q, u, v, MPFR_RNDN); + mpfr_init2 (t, mpfr_get_prec (u)); + mpfr_init2 (w, mpfr_get_prec (u)); + inex2 = mpfr_mul (t, q, v, MPFR_RNDN); + MPFR_ASSERTN(inex2 == 0); + if (inex == 0) /* check q*v = u */ + MPFR_ASSERTN(mpfr_equal_p (u, t)); + else + { + if (inex > 0) + mpfr_nextbelow (q); + else + mpfr_nextabove (q); + inex2 = mpfr_mul (w, q, v, MPFR_RNDN); + MPFR_ASSERTN(inex2 == 0); + inex2 = mpfr_sub (t, t, u, MPFR_RNDN); + MPFR_ASSERTN(inex2 == 0); + inex2 = mpfr_sub (w, w, u, MPFR_RNDN); + MPFR_ASSERTN(inex2 == 0); + MPFR_ASSERTN(mpfr_cmpabs (t, w) <= 0); + if (mpfr_cmpabs (t, w) == 0) /* even rule: significand of q should now + be odd */ + MPFR_ASSERTN(mpfr_min_prec (q) == mpfr_get_prec (q)); + } + + mpfr_clear (q); + mpfr_clear (u); + mpfr_clear (v); + mpfr_clear (t); + mpfr_clear (w); +} + int main (int argc, char *argv[]) { tests_start_mpfr (); + coverage (1024); + coverage2 (); bug20180126 (); bug20171218 (); testall_rndf (9); diff --git a/tests/tgmpop.c b/tests/tgmpop.c index ae3afcb4c..e5cf87619 100644 --- a/tests/tgmpop.c +++ b/tests/tgmpop.c @@ -1216,11 +1216,50 @@ coverage_mpfr_mul_q_20110218 (void) mpfr_clear (cmp); } +static void +coverage (void) +{ + mpfr_exp_t emax, emin; + mpz_t z; + mpfr_t x; + int cmp; + + mpz_init (z); + mpfr_init2 (x, 5); + + /* coverage for mpfr_cmp_z in case of overflow */ + emax = mpfr_get_emax (); + mpfr_set_emax (63); + mpz_set_str (z, "9223372036854775808", 10); /* 2^63 */ + mpfr_set_ui_2exp (x, 1, mpfr_get_emax (), MPFR_RNDZ); + /* x = (1-2^(-p))*2^emax */ + mpfr_clear_flags (); + cmp = mpfr_cmp_z (x, z); + MPFR_ASSERTN(cmp < 0); + MPFR_ASSERTN(!mpfr_overflow_p ()); + mpfr_set_emax (emax); + + /* coverage for mpfr_cmp_z in case of underflow */ + mpz_set_str (z, "18446744073709551615", 10); /* 2^64-1 */ + emin = mpfr_get_emin (); + mpfr_set_emin (65); /* xmin = 2^64 */ + mpfr_set_ui_2exp (x, 1, 64, MPFR_RNDN); + mpfr_clear_flags (); + cmp = mpfr_cmp_z (x, z); + MPFR_ASSERTN(cmp > 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_set_emin (emin); + + mpfr_clear (x); + mpz_clear (z); +} + int main (int argc, char *argv[]) { tests_start_mpfr (); + coverage (); special (); test_specialz (mpfr_add_z, mpz_add, "add"); diff --git a/tests/tmul.c b/tests/tmul.c index 289825c75..7448e0c80 100644 --- a/tests/tmul.c +++ b/tests/tmul.c @@ -1087,11 +1087,175 @@ test_underflow2 (void) mpfr_set_emin (emin); } +static void +coverage (mpfr_prec_t pmax) +{ + mpfr_t a, b, c; + mpfr_prec_t p; + int inex; + + for (p = MPFR_PREC_MIN; p <= pmax; p++) + { + mpfr_init2 (a, p); + mpfr_init2 (b, p); + mpfr_init2 (c, p); + + /* exercise case b*c = 2^(emin-2), which is just in the middle + between 0 and the smallest positive number 0.5*2^emin */ + mpfr_set_ui_2exp (b, 1, mpfr_get_emin (), MPFR_RNDN); + mpfr_set_ui_2exp (c, 1, -2, MPFR_RNDN); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + if (p == 1) + goto end_of_loop; + + /* case b*c > 2^(emin-2): b = (1-2^(-p))*2^emin, + c = 0.25*(1+2^(1-p)), thus b*c = (1+2^(-p)-2^(1-2p))*2^(emin-2) + should be rounded to 2^(emin-1) for RNDN */ + mpfr_nextbelow (b); + mpfr_nextabove (c); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + /* b = (1-2^(1-p))*2^emin, c = 0.25*(1+2^(1-p)), + thus b*c = (1-2^(2-2p))*2^(emin-2) should be rounded to 0 */ + mpfr_nextbelow (b); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + /* special case where b*c is in [nextbelow(0.5*2^emin),0.5*2^emin[ */ + if ((p % 2) == 0) + { + /* the middle of the interval [nextbelow(0.5*2^emin),0.5*2^emin[ + is (1-2^(-p-1))*2^(emin-1) + = (1-2^(-p/2))*(1+2^(-p/2))*2^(emin-1) */ + mpfr_set_si_2exp (b, -1, -p/2, MPFR_RNDN); + mpfr_add_ui (b, b, 1, MPFR_RNDN); + mpfr_set_si_2exp (c, 1, -p/2, MPFR_RNDN); + mpfr_add_ui (c, c, 1, MPFR_RNDN); + MPFR_ASSERTN(mpfr_get_emin () < 0); + mpfr_mul_2si (b, b, (mpfr_get_emin () - 1) / 2, MPFR_RNDN); + mpfr_mul_2si (c, c, (mpfr_get_emin () - 2) / 2, MPFR_RNDN); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDU); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDD); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + } + else /* p is odd: + b = (1-2^(-(p+1)/2))*2^... + c = (1+2^(-(p+1)/2))*2^... */ + { + mpfr_set_si_2exp (b, -1, -(p+1)/2, MPFR_RNDN); + mpfr_add_ui (b, b, 1, MPFR_RNDN); + mpfr_set_si_2exp (c, 1, -(p+1)/2, MPFR_RNDN); + mpfr_add_ui (c, c, 1, MPFR_RNDN); + MPFR_ASSERTN(mpfr_get_emin () < 0); + mpfr_mul_2si (b, b, (mpfr_get_emin () - 1) / 2, MPFR_RNDN); + mpfr_mul_2si (c, c, (mpfr_get_emin () - 2) / 2, MPFR_RNDN); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDU); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDD); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + } + + if (p <= 2) /* for p=2, 1+2^(-ceil((p+1)/2)) = 1 + 2^(-2) is not + exactly representable */ + goto end_of_loop; + + /* b = 1-2^(-ceil((p+1)/2)) + c = 1+2^(-ceil((p+1)/2)) + For p odd, b*c = 1-2^(p+1) should round to 1; + for p even, b*c = 1-2^(p+2) should round to 1 too. */ + mpfr_set_si_2exp (b, -1, -(p+2)/2, MPFR_RNDN); + mpfr_add_ui (b, b, 1, MPFR_RNDN); + mpfr_set_si_2exp (c, 1, -(p+2)/2, MPFR_RNDN); + mpfr_add_ui (c, c, 1, MPFR_RNDN); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); + /* For RNDU, b*c should round to 1 */ + inex = mpfr_mul (a, b, c, MPFR_RNDU); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); + /* For RNDD, b*c should round to 1-2^(-p) */ + inex = mpfr_mul (a, b, c, MPFR_RNDD); + MPFR_ASSERTN(inex < 0); + mpfr_nextabove (a); + MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); + + /* same as above, but near emax, to exercise the case where a carry + produces an overflow */ + mpfr_set_si_2exp (b, -1, -(p+2)/2, MPFR_RNDN); + mpfr_add_ui (b, b, 1, MPFR_RNDN); + mpfr_mul_2si (b, b, mpfr_get_emax (), MPFR_RNDN); + mpfr_set_si_2exp (c, 1, -(p+2)/2, MPFR_RNDN); + mpfr_add_ui (c, c, 1, MPFR_RNDN); + /* b*c should round to 2^emax */ + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); + MPFR_ASSERTN(mpfr_overflow_p ()); + /* idem for RNDU */ + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDU); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); + MPFR_ASSERTN(mpfr_overflow_p ()); + /* For RNDD, b*c should round to (1-2^(-p))*2^emax */ + mpfr_clear_flags (); + inex = mpfr_mul (a, b, c, MPFR_RNDD); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(!mpfr_inf_p (a)); + MPFR_ASSERTN(!mpfr_overflow_p ()); + mpfr_nextabove (a); + MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); + + end_of_loop: + mpfr_clear (a); + mpfr_clear (b); + mpfr_clear (c); + } +} + int main (int argc, char *argv[]) { tests_start_mpfr (); + coverage (1024); testall_rndf (9); check_nans (); check_exact (); diff --git a/tests/tmul_2exp.c b/tests/tmul_2exp.c index c6ddbbf8d..1a4a1e3b0 100644 --- a/tests/tmul_2exp.c +++ b/tests/tmul_2exp.c @@ -101,10 +101,8 @@ underflow (mpfr_exp_t e) printf ("MPFR_EMIN_MIN"); else if (e == emin) printf ("default emin"); - else if (e >= LONG_MIN) - printf ("%ld", (long) e); else - printf ("<LONG_MIN"); + printf ("%" MPFR_EXP_FSPEC "d", (mpfr_eexp_t) e); printf (") with mpfr_%s,\nx = %d/16, prec = %d, k = %d," " %s\n", div == 0 ? "mul_2si" : div == 1 ? "div_2si" : "div_2ui", s * i, prec, k, @@ -167,10 +165,8 @@ large (mpfr_exp_t e) printf ("MPFR_EMAX_MAX"); else if (e == emax) printf ("default emax"); - else if (e <= LONG_MAX) - printf ("%ld", (long) e); else - printf (">LONG_MAX"); + printf ("%" MPFR_EXP_FSPEC "d", (mpfr_eexp_t) e); printf (") for mpfr_mul_2si\n"); printf ("Expected inex > 0, flags = %u,\n y = ", (unsigned int) MPFR_FLAGS_INEXACT); @@ -192,10 +188,8 @@ large (mpfr_exp_t e) printf ("MPFR_EMAX_MAX"); else if (e == emax) printf ("default emax"); - else if (e <= LONG_MAX) - printf ("%ld", (long) e); else - printf (">LONG_MAX"); + printf ("%" MPFR_EXP_FSPEC "d", (mpfr_eexp_t) e); printf (") for mpfr_div_2si\n"); printf ("Expected inex > 0, flags = %u,\n y = ", (unsigned int) MPFR_FLAGS_INEXACT); @@ -217,10 +211,8 @@ large (mpfr_exp_t e) printf ("MPFR_EMAX_MAX"); else if (e == emax) printf ("default emax"); - else if (e <= LONG_MAX) - printf ("%ld", (long) e); else - printf (">LONG_MAX"); + printf ("%" MPFR_EXP_FSPEC "d", (mpfr_eexp_t) e); printf (") for mpfr_div_2ui\n"); printf ("Expected inex > 0, flags = %u,\n y = ", (unsigned int) MPFR_FLAGS_INEXACT); @@ -238,10 +230,24 @@ large (mpfr_exp_t e) static void large0 (void) { - large (256); - if (mpfr_get_emax () != MPFR_EMAX_MAX) - large (mpfr_get_emax ()); - large (MPFR_EMAX_MAX); + mpfr_exp_t emin; + + emin = mpfr_get_emin (); + + while (1) + { + large (256); + if (mpfr_get_emax () != MPFR_EMAX_MAX) + large (mpfr_get_emax ()); + large (MPFR_EMAX_MAX); + if (mpfr_get_emin () == MPFR_EMIN_MIN) + break; + /* Redo the test with __gmpfr_emin set to MPFR_EMIN_MIN, which can + be useful to trigger integer overflows as in div_2ui.c r12272. */ + set_emin (MPFR_EMIN_MIN); + } + + set_emin (emin); } /* Cases where the function overflows on n = 0 when rounding is like diff --git a/tests/tsqrt.c b/tests/tsqrt.c index 8136ad681..6cf0cbee5 100644 --- a/tests/tsqrt.c +++ b/tests/tsqrt.c @@ -689,6 +689,231 @@ test_sqrt1n (void) mpfr_clear (u); } +static void +check_overflow (void) +{ + mpfr_t r, u; + mpfr_prec_t p; + mpfr_exp_t emax; + int inex; + + emax = mpfr_get_emax (); + for (p = MPFR_PREC_MIN; p <= 1024; p++) + { + mpfr_init2 (r, p); + mpfr_init2 (u, p); + + mpfr_set_emax (-1); + mpfr_set_ui_2exp (u, 1, mpfr_get_emax () - 1, MPFR_RNDN); + mpfr_nextbelow (u); + mpfr_mul_2exp (u, u, 1, MPFR_RNDN); + /* now u = (1 - 2^(-p))*2^emax is the largest number < +Inf, + it square root is near 0.707 and has exponent 0 > emax */ + /* for RNDN, the result should be +Inf */ + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_inf_p (r) && mpfr_sgn (r) > 0); + /* for RNDA, the result should be +Inf */ + inex = mpfr_sqrt (r, u, MPFR_RNDA); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_inf_p (r) && mpfr_sgn (r) > 0); + /* for RNDZ, the result should be u */ + inex = mpfr_sqrt (r, u, MPFR_RNDZ); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_equal_p (r, u)); + + mpfr_set_emax (0); + mpfr_set_ui_2exp (u, 1, mpfr_get_emax () - 1, MPFR_RNDN); + mpfr_nextbelow (u); + mpfr_mul_2exp (u, u, 1, MPFR_RNDN); + /* u = 1-2^(-p), its square root is > u, and should thus give +Inf when + rounding away */ + inex = mpfr_sqrt (r, u, MPFR_RNDA); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_inf_p (r) && mpfr_sgn (r) > 0); + + mpfr_clear (r); + mpfr_clear (u); + } + mpfr_set_emax (emax); +} + +static void +check_underflow (void) +{ + mpfr_t r, u; + mpfr_prec_t p; + mpfr_exp_t emin; + int inex; + + emin = mpfr_get_emin (); + for (p = MPFR_PREC_MIN; p <= 1024; p++) + { + mpfr_init2 (r, p); + mpfr_init2 (u, p); + + mpfr_set_emin (2); + mpfr_set_ui_2exp (u, 1, mpfr_get_emin () - 1, MPFR_RNDN); /* u = 2 */ + /* for RNDN, since sqrt(2) is closer from 2 than 0, the result is 2 */ + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_equal_p (r, u)); + MPFR_ASSERTN(mpfr_underflow_p ()); + /* for RNDA, the result should be u, and there is underflow for p > 1, + since for p=1 we have 1 < sqrt(2) < 2, but for p >= 2, sqrt(2) should + be rounded to a number <= 1.5, which is representable */ + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDA); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_equal_p (r, u)); + MPFR_ASSERTN((p == 1 && !mpfr_underflow_p ()) || + (p != 1 && mpfr_underflow_p ())); + /* for RNDZ, the result should be +0 */ + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDZ); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (r) && mpfr_signbit (r) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + /* generate an input u such that sqrt(u) < 0.5*2^emin but there is no + underflow since sqrt(u) >= pred(0.5*2^emin), thus u >= 2^(2emin-2) */ + mpfr_set_ui_2exp (u, 1, 2 * mpfr_get_emin () - 2, MPFR_RNDN); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex == 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDA); + MPFR_ASSERTN(inex == 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDZ); + MPFR_ASSERTN(inex == 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + + /* next number */ + mpfr_set_ui_2exp (u, 1, 2 * mpfr_get_emin () - 2, MPFR_RNDN); + mpfr_nextabove (u); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDA); + MPFR_ASSERTN(inex > 0); + mpfr_nextbelow (r); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDZ); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + + /* previous number */ + mpfr_set_ui_2exp (u, 1, 2 * mpfr_get_emin () - 2, MPFR_RNDN); + mpfr_nextbelow (u); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + /* since sqrt(u) is just below the middle between 0.5*2^emin and + the previous number (with unbounded exponent range), there is + underflow */ + MPFR_ASSERTN(mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDA); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(!mpfr_underflow_p ()); + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDZ); + MPFR_ASSERTN(inex < 0); + mpfr_nextabove (r); + MPFR_ASSERTN(mpfr_cmp_ui_2exp (r, 1, mpfr_get_emin () - 1) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_set_emin (3); + mpfr_set_ui_2exp (u, 1, mpfr_get_emin () - 1, MPFR_RNDN); /* u = 4 */ + /* sqrt(u) = 2 = 0.5^2^(emin-1) should be rounded to +0 */ + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (r) && mpfr_signbit (r) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + /* next number */ + mpfr_set_ui_2exp (u, 1, mpfr_get_emin () - 1, MPFR_RNDN); /* u = 4 */ + mpfr_nextabove (u); + /* sqrt(u) should be rounded to 4 */ + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_cmp_ui (r, 4) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_set_emin (4); + mpfr_set_ui_2exp (u, 1, mpfr_get_emin () - 1, MPFR_RNDN); /* u = 8 */ + /* sqrt(u) should be rounded to +0 */ + mpfr_clear_flags (); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_zero_p (r) && mpfr_signbit (r) == 0); + MPFR_ASSERTN(mpfr_underflow_p ()); + + mpfr_clear (r); + mpfr_clear (u); + } + mpfr_set_emin (emin); +} + +static void +coverage (void) +{ + mpfr_t r, t, u, v, w; + mpfr_prec_t p; + int inex; + + /* exercise even rule */ + for (p = MPFR_PREC_MIN; p <= 1024; p++) + { + mpfr_init2 (r, p); + mpfr_init2 (t, p + 1); + mpfr_init2 (u, 2 * p + 2); + mpfr_init2 (v, p); + mpfr_init2 (w, p); + do + mpfr_urandomb (v, RANDS); + while (mpfr_zero_p (v)); + mpfr_set (w, v, MPFR_RNDN); + mpfr_nextabove (w); /* w = nextabove(v) */ + mpfr_set (t, v, MPFR_RNDN); + mpfr_nextabove (t); + mpfr_mul (u, t, t, MPFR_RNDN); + inex = mpfr_sqrt (r, u, MPFR_RNDN); + if (mpfr_min_prec (v) < p) /* v is even */ + { + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_equal_p (r, v)); + } + else /* v is odd */ + { + MPFR_ASSERTN(inex > 0); + MPFR_ASSERTN(mpfr_equal_p (r, w)); + } + mpfr_clear (r); + mpfr_clear (t); + mpfr_clear (u); + mpfr_clear (v); + mpfr_clear (w); + } +} + #define TEST_FUNCTION test_sqrt #define TEST_RANDOM_POS 8 #include "tgeneric.c" @@ -701,6 +926,9 @@ main (void) tests_start_mpfr (); + coverage (); + check_underflow (); + check_overflow (); testall_rndf (16); for (p = MPFR_PREC_MIN; p <= 128; p++) { diff --git a/tests/tsub.c b/tests/tsub.c index 99e470747..51a38842e 100644 --- a/tests/tsub.c +++ b/tests/tsub.c @@ -143,6 +143,19 @@ check_diverse (void) exit (1); } + /* yet another coverage test */ + mpfr_set_prec (x, 2); + mpfr_set_prec (y, 3); + mpfr_set_prec (z, 1); + mpfr_set_ui_2exp (y, 1, mpfr_get_emax (), MPFR_RNDZ); + /* y = (1 - 2^(-3))*2^emax */ + mpfr_set_ui_2exp (z, 1, mpfr_get_emax () - 4, MPFR_RNDZ); + /* z = 2^(emax - 4) */ + /* y - z = (1 - 2^(-3) - 2^(-4))*2^emax > (1-2^(-2))*2^emax */ + inexact = mpfr_sub (x, y, z, MPFR_RNDU); + MPFR_ASSERTN(inexact > 0); + MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); + mpfr_set_prec (x, 288); mpfr_set_prec (y, 288); mpfr_set_prec (z, 288); diff --git a/tests/tzeta.c b/tests/tzeta.c index b23902f2f..56c25c4d9 100644 --- a/tests/tzeta.c +++ b/tests/tzeta.c @@ -26,10 +26,13 @@ static void test1 (void) { mpfr_t x, y; + int inex; mpfr_init2 (x, 32); mpfr_init2 (y, 42); + mpfr_clear_flags (); + mpfr_set_str_binary (x, "1.1111111101000111011010010010100e-1"); mpfr_zeta (y, x, MPFR_RNDN); /* shouldn't crash */ @@ -91,18 +94,29 @@ test1 (void) mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 3, -1) == 0); - mpfr_set_nan (x); - mpfr_zeta (y, x, MPFR_RNDN); - MPFR_ASSERTN(mpfr_nan_p (y)); + /* yet another coverage test (case beta <= 0.0) */ + mpfr_set_prec (x, 10); + mpfr_set_ui (x, 23, MPFR_RNDN); + mpfr_set_prec (y, 15); + inex = mpfr_zeta (y, x, MPFR_RNDN); + MPFR_ASSERTN(inex < 0); + MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); mpfr_set_inf (x, 1); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0); + /* Since some tests don't really check that the result is not NaN... */ + MPFR_ASSERTN (! mpfr_nanflag_p ()); + mpfr_set_inf (x, -1); mpfr_zeta (y, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (y)); + mpfr_set_nan (x); + mpfr_zeta (y, x, MPFR_RNDN); + MPFR_ASSERTN(mpfr_nan_p (y)); + mpfr_clear (x); mpfr_clear (y); } |