summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2020-03-13 16:40:17 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2020-03-13 16:40:17 +0000
commitb3ef2cd93f039a3209455dc1d4fb4c05aa26024d (patch)
treeea4c6bc71fda8d5f726ba52f98f9bdfb6da7bcf3
parent3ef6af7ad85f4ff77099b45a4aef48d24894024f (diff)
downloadmpfr-b3ef2cd93f039a3209455dc1d4fb4c05aa26024d.tar.gz
[tests] Update to test the ternary value in test5rm() when possible,
and support the exact cases. * tests.c: - test5rm(): modified the prototype again and the behavior. Now, either only one test is done and the ternary value is not checked, or the test is done in the 5 rounding modes and the ternary value is checked. - data_check(): corresponding update; updated description. - bad_cases(): test the exact cases too. * tatanh.c: for the bad_cases() call, reduce emax to avoid errors in the generation of bad cases due to the rounding of tanh(y) to 1, which does not correspond to a bad case for atanh, but to an exact case. * tlog1p.c: for the bad_cases() call, reduce emax to avoid errors in the generation of bad cases due to the rounding of expm1(y) to -1, which does not correspond to a bad case for log1p, but to an exact case. * trec_sqrt.c: corrected the bad_cases() call to avoid negative numbers. Note: the following tests GMP_CHECK_RANDOMIZE=5 ./tacos GMP_CHECK_RANDOMIZE=6 ./tatan GMP_CHECK_RANDOMIZE=4 ./tcos currently fail, but because of a change in r13783 (see associated log for the reason). To be fixed later. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@13787 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--tests/tatanh.c2
-rw-r--r--tests/tests.c98
-rw-r--r--tests/tlog1p.c2
-rw-r--r--tests/trec_sqrt.c2
4 files changed, 58 insertions, 46 deletions
diff --git a/tests/tatanh.c b/tests/tatanh.c
index b524829d1..0ed66befb 100644
--- a/tests/tatanh.c
+++ b/tests/tatanh.c
@@ -178,7 +178,7 @@ main (int argc, char *argv[])
test_generic (MPFR_PREC_MIN, 100, 25);
data_check ("data/atanh", mpfr_atanh, "mpfr_atanh");
- bad_cases (mpfr_atanh, mpfr_tanh, "mpfr_atanh", 256, -128, 9,
+ bad_cases (mpfr_atanh, mpfr_tanh, "mpfr_atanh", 256, -128, 8,
4, 128, 800, 100);
tests_end_mpfr ();
diff --git a/tests/tests.c b/tests/tests.c
index 2a34508f3..a82a44a54 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -704,31 +704,35 @@ tests_default_random (mpfr_ptr x, int pos, mpfr_exp_t emin, mpfr_exp_t emax,
mpfr_neg (x, x, MPFR_RNDN);
}
-/* Argument test_one is a boolean. If it is true, then the function is
- tested in only one rounding mode (the one provided in rnd). Otherwise,
- the function is tested in the 5 rounding modes, and rnd must initially
- be MPFR_RNDZ; the successive rounding modes are:
+/* If sb = -1, then the function is tested in only one rounding mode
+ (the one provided in rnd) and the ternary value is not checked.
+ Otherwise, the function is tested in the 5 rounding modes, rnd must
+ initially be MPFR_RNDZ, y = RNDZ(f(x)), and sb is 0 if f(x) is exact,
+ 1 if f(x) is inexact (in which case, y must be a regular number,
+ i.e. not the result of an overflow or an underflow); the successive
+ rounding modes are:
* MPFR_RNDZ, MPFR_RNDD, MPFR_RNDA, MPFR_RNDU, MPFR_RNDN for positive y;
* MPFR_RNDZ, MPFR_RNDU, MPFR_RNDA, MPFR_RNDD, MPFR_RNDN for negative y;
for the last test MPFR_RNDN, the target precision is decreased by 1 in
order to be able to deduce the result (anyway, for a hard-to-round case
in directed rounding modes, if yprec is chosen to be minimum precision
preserving this hard-to-round case, then one has a hard-to-round case
- in round-to-nearest for precision yprec-1).
- Argument exact should be 1 when f(x) is exact, and 0 otherwise; if
- test_one is true, a value of -1 means that one does not know (TODO:
- the current data that provide no information should be updated to
- avoid this value, whose support should be removed in the future).
+ in round-to-nearest for precision yprec-1). If the target precision was
+ MPFR_PREC_MIN, then skip the MPFR_RNDN test; thus to test exact special
+ cases, use a target precision larger than MPFR_PREC_MIN.
+ Note: if y is a regular number, sb corresponds to the sticky bit when
+ considering round-to-nearest with precision yprec-1.
As examples of use, see the calls to test5rm from the data_check and
bad_cases functions. */
static void
test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
- mpfr_rnd_t rnd, int test_one, int exact, const char *name)
+ mpfr_rnd_t rnd, int sb, const char *name)
{
mpfr_prec_t yprec = MPFR_PREC (y);
mpfr_rnd_t rndnext = MPFR_RND_MAX; /* means uninitialized */
+ int expected_inex = INT_MIN;
- MPFR_ASSERTN (test_one || (rnd == MPFR_RNDZ && exact != -1));
+ MPFR_ASSERTN (sb == -1 || rnd == MPFR_RNDZ);
mpfr_set_prec (z, yprec);
while (1)
{
@@ -736,7 +740,13 @@ test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
MPFR_ASSERTN (rnd != MPFR_RND_MAX);
inex = fct (z, x, rnd);
- if (! SAME_VAL (y, z)) /* TODO: also check inex */
+ if (sb == -1)
+ expected_inex = inex; /* not checked */
+ else if (rnd != MPFR_RNDN)
+ expected_inex =
+ sb == 0 ? 0 : MPFR_IS_LIKE_RNDD (rnd, MPFR_SIGN (y)) ? -1 : 1;
+ MPFR_ASSERTN (expected_inex != INT_MIN);
+ if (!(SAME_VAL (y, z) || SAME_SIGN (inex, expected_inex)))
{
printf ("Error for %s with xprec=%lu, yprec=%lu, rnd=%s\nx = ",
name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec,
@@ -747,21 +757,12 @@ test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
printf ("\ngot ");
mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
printf ("\n");
- exit (1);
- }
- if (exact == 1 && inex != 0)
- {
- printf ("Error for %s with xprec=%lu, yprec=%lu, rnd=%s\nx = ",
- name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec,
- mpfr_print_rnd_mode (rnd));
- mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
- printf ("\nexact case, but non-zero ternary value (%d)\n", inex);
+ if (sb != -1)
+ printf ("Expected inex = %d, got %d\n", expected_inex, inex);
exit (1);
}
- /* TODO: if test_one is false, the code currently assumes that exact
- is false. */
- if (test_one || rnd == MPFR_RNDN)
+ if (sb == -1 || rnd == MPFR_RNDN)
break;
else if (rnd == MPFR_RNDZ)
{
@@ -773,7 +774,8 @@ test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
rnd = rndnext;
if (rnd == MPFR_RNDA)
{
- mpfr_nexttoinf (y);
+ if (sb)
+ mpfr_nexttoinf (y);
rndnext = MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU;
}
else if (rndnext != MPFR_RNDN)
@@ -782,10 +784,14 @@ test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
{
if (yprec == MPFR_PREC_MIN)
break;
- /* MPFR_RNDZ is used due to the previous mpfr_nexttoinf for
- the MPFR_RNDA test: RNDN(p,w) = RNDZ(p,RNDA(p+1,w)) if w
- is not a midpoint in precision p. */
- mpfr_prec_round (y, --yprec, MPFR_RNDZ);
+ /* If sb = 1, then mpfr_nexttoinf was called on y for the
+ MPFR_RNDA test, i.e. y = RNDA(yprec,f(x)); we use MPFR_RNDZ
+ since one has the property RNDN(p,w) = RNDZ(p,RNDA(p+1,w))
+ when w is not a midpoint in precision p. If sb = 0, then
+ y = f(x), so that RNDN(yprec-1,f(x)) = RNDN(yprec-1,y). */
+ inex = mpfr_prec_round (y, --yprec, sb ? MPFR_RNDZ : MPFR_RNDN);
+ expected_inex = sb ?
+ MPFR_SIGN (y) * (inex == 0 ? 1 : -1) : inex;
mpfr_set_prec (z, yprec);
}
}
@@ -805,10 +811,10 @@ test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
x is the input (hexadecimal format)
y is the expected output (hexadecimal format) for foo(x) with rounding rnd
- If rnd is Z, then y is the expected output in round-toward-zero, the
- four directed rounding modes are tested, and the round-to-nearest
- mode is tested in precision yprec-1. See details in the description
- of test5rm above.
+ If rnd is Z, then y is the expected output in round-toward-zero and
+ it is assumed to be inexact; the four directed rounding modes are
+ tested, and the round-to-nearest mode is tested in precision yprec-1.
+ See details in the description of test5rm above.
If rnd is *, y must be an exact case (possibly a special case).
All the rounding modes are tested and the ternary value is checked
@@ -946,9 +952,9 @@ data_check (const char *f, int (*foo) (FLIST), const char *name)
exit (1);
}
if (r == '*')
- test5rm (foo, x, y, z, MPFR_RNDZ, 0, 1, name);
+ test5rm (foo, x, y, z, MPFR_RNDZ, 0, name);
else
- test5rm (foo, x, y, z, rnd, r != 'Z', -1, name);
+ test5rm (foo, x, y, z, rnd, r == 'Z' ? 1 : -1, name);
}
}
@@ -993,7 +999,7 @@ bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name,
for (i = 0; i < n; i++)
{
mpfr_prec_t px, py, pz;
- int inex;
+ int inex_inv, inex, sb;
if (dbg)
printf ("bad_cases: %s, i = %d\n", name, i);
@@ -1011,7 +1017,7 @@ bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name,
if (dbg)
printf ("bad_cases: xprec =%4ld\n", (long) px);
mpfr_clear_flags ();
- inv (x, y, MPFR_RNDN);
+ inex_inv = inv (x, y, MPFR_RNDN);
if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ())
{
if (dbg)
@@ -1029,14 +1035,20 @@ bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name,
{
pz += 32;
mpfr_set_prec (z, pz);
- if (fct (z, x, MPFR_RNDN) == 0)
+ sb = fct (z, x, MPFR_RNDN) != 0;
+ if (!sb)
{
if (dbg)
printf ("bad_cases: exact case\n");
- /* TODO: Exact cases are not tested yet. This needs a change
- in test5rm. Moreover, one should also test the value just
- below and the value just above the exact case. */
- goto next_i;
+ if (inex_inv)
+ {
+ printf ("bad_cases: f exact while f^(-1) inexact,\n"
+ "due to a poor choice of the parameters.\n");
+ exit (1);
+ /* alternatively, goto next_i */
+ }
+ inex = 0;
+ break;
}
if (dbg)
{
@@ -1091,7 +1103,7 @@ bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name,
printf ("\n");
}
/* Note: y is now the expected result rounded toward zero. */
- test5rm (fct, x, y, z, MPFR_RNDZ, 0, 0, name);
+ test5rm (fct, x, y, z, MPFR_RNDZ, sb, name);
next_i:
/* In case the exponent range has been changed by
tests_default_random()... */
diff --git a/tests/tlog1p.c b/tests/tlog1p.c
index ad591f8bc..d9f7db948 100644
--- a/tests/tlog1p.c
+++ b/tests/tlog1p.c
@@ -139,7 +139,7 @@ main (int argc, char *argv[])
test_generic (MPFR_PREC_MIN, 100, 50);
data_check ("data/log1p", mpfr_log1p, "mpfr_log1p");
- bad_cases (mpfr_log1p, mpfr_expm1, "mpfr_log1p", 256, -64, 40,
+ bad_cases (mpfr_log1p, mpfr_expm1, "mpfr_log1p", 256, -64, 9,
4, 128, 800, 40);
tests_end_mpfr ();
diff --git a/tests/trec_sqrt.c b/tests/trec_sqrt.c
index 148d494a2..480d83001 100644
--- a/tests/trec_sqrt.c
+++ b/tests/trec_sqrt.c
@@ -186,7 +186,7 @@ main (void)
test_generic (MPFR_PREC_MIN, 300, 15);
data_check ("data/rec_sqrt", mpfr_rec_sqrt, "mpfr_rec_sqrt");
- bad_cases (mpfr_rec_sqrt, pm2, "mpfr_rec_sqrt", 8, -256, 255, 4, 128,
+ bad_cases (mpfr_rec_sqrt, pm2, "mpfr_rec_sqrt", 0, -256, 255, 4, 128,
800, 50);
tests_end_mpfr ();