summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-04-11 13:54:39 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-04-11 13:54:39 +0000
commit985398b4b9dadafbdc1600e12707dee74cab4cd8 (patch)
treefffa9d39f59c68d812ee9e20deba3e565b1f7c19
parente9dc7e9f72cc13e5dfdd3cca1a56b2d4cc823e95 (diff)
downloadmpfr-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.c1
-rw-r--r--tests/tai.c94
-rw-r--r--tests/tdiv.c122
-rw-r--r--tests/tgmpop.c39
-rw-r--r--tests/tmul.c164
-rw-r--r--tests/tmul_2exp.c38
-rw-r--r--tests/tsqrt.c228
-rw-r--r--tests/tsub.c13
-rw-r--r--tests/tzeta.c20
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);
}