summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-05-28 04:59:39 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-05-28 04:59:39 +0000
commitcf11a3eb08d62789a6fdc3347da236c3c389743f (patch)
treebee39cc3ec584c505e659c2b6a6fc2af81d16ec9
parented11b5b94687c1a0cefe59f2e899c6e6f08ff589 (diff)
downloadmpfr-cf11a3eb08d62789a6fdc3347da236c3c389743f.tar.gz
start implementing RNDF (work in progress)
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/faithful@10380 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--TODO3
-rw-r--r--doc/mpfr.texi3
-rw-r--r--src/add1.c19
-rw-r--r--src/add1sp.c29
-rw-r--r--src/mpfr-impl.h13
-rw-r--r--src/mpfr.h5
-rw-r--r--src/mul.c10
-rw-r--r--src/print_rnd_mode.c4
-rw-r--r--src/round_near_x.c3
-rw-r--r--src/round_prec.c5
-rw-r--r--src/sub1.c11
-rw-r--r--src/sub1sp.c16
-rw-r--r--tests/tabs.c6
-rw-r--r--tests/tadd.c28
-rw-r--r--tests/tadd1sp.c7
-rw-r--r--tests/tcan_round.c2
-rw-r--r--tests/texceptions.c44
-rw-r--r--tests/tgeneric.c6
-rw-r--r--tests/tinternals.c6
-rw-r--r--tests/tmul.c2
-rw-r--r--tests/trint.c6
-rw-r--r--tests/tset.c7
-rw-r--r--tests/tsub.c6
-rw-r--r--tests/tsub1sp.c6
24 files changed, 198 insertions, 49 deletions
diff --git a/TODO b/TODO
index 700cc5875..910d60b9a 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,6 @@
+TODO for faithful branch:
+- deal with RNDF in mpfr_round_near_x (replaced by RNDZ)
+
Copyright 1999-2016 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
diff --git a/doc/mpfr.texi b/doc/mpfr.texi
index f5fa0037c..6492967ad 100644
--- a/doc/mpfr.texi
+++ b/doc/mpfr.texi
@@ -2840,7 +2840,8 @@ In other words, if the error on @var{b} is bounded by two to the power
you should give @var{err}=@var{prec}@minus{}@var{k}.
This function @strong{does not modify} its arguments.
-If @var{rnd1} is @code{MPFR_RNDN}, the error is considered to be either
+If @var{rnd1} is @code{MPFR_RNDN} or @code{MPFR_RNDF},
+the error is considered to be either
positive or negative, thus the possible range
is twice as large as with a directed rounding for @var{rnd1} (with the
same value of @var{err}).
diff --git a/src/add1.c b/src/add1.c
index abb9b40d3..0adb2c8a1 100644
--- a/src/add1.c
+++ b/src/add1.c
@@ -71,7 +71,7 @@ mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
exp = MPFR_GET_EXP (b);
MPFR_SET_SAME_SIGN(a, b);
MPFR_UPDATE2_RND_MODE(rnd_mode, MPFR_SIGN(b));
- /* now rnd_mode is either MPFR_RNDN, MPFR_RNDZ or MPFR_RNDA */
+ /* now rnd_mode is either MPFR_RNDN, MPFR_RNDZ, MPFR_RNDA or MPFR_RNDF. */
/* Note: exponents can be negative, but the unsigned subtraction is
a modular subtraction, so that one gets the correct result. */
diff_exp = (mpfr_uexp_t) exp - MPFR_GET_EXP(c);
@@ -185,7 +185,7 @@ mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
} /* cc */
} /* aq2 > diff_exp */
- /* non-significant bits of a */
+ /* zero the non-significant bits of a */
if (MPFR_LIKELY(rb < 0 && sh))
{
mp_limb_t mask, bb;
@@ -473,6 +473,21 @@ mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
} /* fb != 1 */
rounding:
+ /* fast track for faithful rounding */
+ if (rnd_mode == MPFR_RNDF)
+ {
+ /* The exact value of b + c is now in [a, a + 2[ where 2 stands for
+ the value of the lowest bit of ap[0]. If sh > 0, the difference
+ is less than ulp(a), thus we can return a. Note: we could return
+ add_one_ulp in all cases, which would give a simpler code here,
+ but the "add_one_ulp" code is more expensive. */
+ inex = 0;
+ if (sh)
+ goto set_exponent;
+ else /* we can return a+1 */
+ goto add_one_ulp;
+ }
+
/* rnd_mode should be one of MPFR_RNDN, MPFR_RNDZ or MPFR_RNDA */
if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
{
diff --git a/src/add1sp.c b/src/add1sp.c
index ac1d8b3f1..1452740d2 100644
--- a/src/add1sp.c
+++ b/src/add1sp.c
@@ -126,6 +126,13 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
mpn_rshift(ap, ap, n, 1); /* Shift mantissa A */
ap[n-1] |= MPFR_LIMB_HIGHBIT; /* Set MSB */
ap[0] &= ~MPFR_LIMB_MASK(sh); /* Clear LSB bit */
+
+ /* Fast track for faithful rounding: since b and c have the same
+ precision and the same exponent, the neglected value is either
+ 0 or 1/2 ulp(a), thus returning a is fine. */
+ if (rnd_mode == MPFR_RNDF)
+ goto set_exponent;
+
if ((limb & (MPFR_LIMB_ONE << sh)) == 0) /* Check exact case */
{ inexact = 0; goto set_exponent; }
/* Zero: Truncate
@@ -172,10 +179,13 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
else
{
/* d==p : Copy B in A */
- /* Away: Add 1
- Nearest: Even Rule if C is a power of 2, else Add 1
- Zero: Trunc */
- if (MPFR_LIKELY (rnd_mode == MPFR_RNDN))
+ /* Away: Add 1
+ Nearest: Even Rule if C is a power of 2, else Add 1
+ Zero: Trunc
+ Faithful: Trunc */
+ if (MPFR_LIKELY(rnd_mode == MPFR_RNDF))
+ goto copy_set_exponent;
+ else if (rnd_mode == MPFR_RNDN)
{
/* Check if C was a power of 2 */
cp = MPFR_MANT(c);
@@ -199,7 +209,7 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
goto copy_add_one_ulp;
}
}
- else
+ else /* 0 < d < p */
{
mp_limb_t mask;
mp_limb_t bcp, bcp1; /* Cp and C'p+1 */
@@ -239,6 +249,10 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
DEBUG( mpfr_print_mant_binary("B= ", MPFR_MANT(b), p) );
DEBUG( mpfr_print_mant_binary("After ", cp, p) );
+ /* fast track for RNDF */
+ if (rnd_mode == MPFR_RNDF)
+ goto clean;
+
/* Compute bcp=Cp and bcp1=C'p+1 */
if (MPFR_LIKELY (sh > 0))
{
@@ -302,6 +316,7 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
DEBUG (printf("sh=%u Cp=%lu C'p+1=%lu\n", sh,
(unsigned long) bcp, (unsigned long) bcp1));
+ clean:
/* Clean shifted C' */
mask = ~MPFR_LIMB_MASK(sh);
cp[0] &= mask;
@@ -332,7 +347,9 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
Nearest: Truncate but could be exact if Cp==0
Add 1 if C'p+1 !=0,
Even rule else */
- if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
+ if (MPFR_LIKELY(rnd_mode == MPFR_RNDF))
+ goto set_exponent;
+ else if (rnd_mode == MPFR_RNDN)
{
inexact = - (bcp1 != 0);
if (bcp == 0)
diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h
index 8e7ccaa60..c32a88f14 100644
--- a/src/mpfr-impl.h
+++ b/src/mpfr-impl.h
@@ -976,10 +976,8 @@ typedef intmax_t mpfr_eexp_t;
******************************************************/
/* MPFR_RND_MAX gives the number of supported rounding modes by all functions.
- * Once faithful rounding is implemented, MPFR_RNDA should be changed
- * to MPFR_RNDF. But this will also require more changes in the tests.
*/
-#define MPFR_RND_MAX ((mpfr_rnd_t)((MPFR_RNDA)+1))
+#define MPFR_RND_MAX ((mpfr_rnd_t)((MPFR_RNDF)+1))
/* We want to test this :
* (rnd == MPFR_RNDU && test) || (rnd == RNDD && !test)
@@ -990,7 +988,7 @@ typedef intmax_t mpfr_eexp_t;
/* We want to test if rnd = Zero, or Away.
'test' is 1 if negative, and 0 if positive. */
#define MPFR_IS_LIKE_RNDZ(rnd, test) \
- ((rnd) == MPFR_RNDZ || MPFR_IS_RNDUTEST_OR_RNDDNOTTEST (rnd, test))
+ ((rnd) == MPFR_RNDZ || (rnd) == MPFR_RNDF || MPFR_IS_RNDUTEST_OR_RNDDNOTTEST (rnd, test))
#define MPFR_IS_LIKE_RNDU(rnd, sign) \
(((rnd) == MPFR_RNDU) || \
@@ -1512,7 +1510,12 @@ typedef struct {
_ulp = MPFR_LIMB_ONE; \
} \
/* Rounding */ \
- if (rnd == MPFR_RNDN) \
+ if (rnd == MPFR_RNDF) \
+ { \
+ inexact = 0; \
+ goto trunc_doit; \
+ } \
+ else if (rnd == MPFR_RNDN) \
{ \
if (_rb == 0) \
{ \
diff --git a/src/mpfr.h b/src/mpfr.h
index 0fa453901..ca7ebbf8d 100644
--- a/src/mpfr.h
+++ b/src/mpfr.h
@@ -92,9 +92,6 @@ typedef unsigned int mpfr_flags_t;
MPFR_RNDU must appear just before MPFR_RNDD (see
MPFR_IS_RNDUTEST_OR_RNDDNOTTEST in mpfr-impl.h).
- MPFR_RNDF has been added, though not implemented yet, in order to avoid
- to break the ABI once faithful rounding gets implemented.
-
If you change the order of the rounding modes, please update the routines
in texceptions.c which assume 0=RNDN, 1=RNDZ, 2=RNDU, 3=RNDD, 4=RNDA.
*/
@@ -104,7 +101,7 @@ typedef enum {
MPFR_RNDU, /* round toward +Inf */
MPFR_RNDD, /* round toward -Inf */
MPFR_RNDA, /* round away from zero */
- MPFR_RNDF, /* faithful rounding (not implemented yet) */
+ MPFR_RNDF, /* faithful rounding */
MPFR_RNDNA=-1 /* round to nearest, with ties away from zero (mpfr_round) */
} mpfr_rnd_t;
diff --git a/src/mul.c b/src/mul.c
index f5ecb782c..574c846fd 100644
--- a/src/mul.c
+++ b/src/mul.c
@@ -280,7 +280,7 @@ mpfr_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
/* Note: the exponent of the exact result will be e = bx + cx + ec with
ec in {-1,0,1} and the following assumes that e is representable. */
- /* FIXME: Useful since we do an exponent check after ?
+ /* FIXME: Useful since we do an exponent check after?
* It is useful iff the precision is big, there is an overflow
* and we are doing further mults...*/
#ifdef HUGE
@@ -501,8 +501,12 @@ mpfr_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
/* if the most significant bit b1 is zero, we have only p-1 correct
bits */
- if (MPFR_UNLIKELY (!mpfr_round_p (tmp, tn, p + b1 - 1, MPFR_PREC(a)
- + (rnd_mode == MPFR_RNDN))))
+ if (rnd_mode == MPFR_RNDF && p + b1 - 1 >= MPFR_PREC(a))
+ {
+ /* we can round */
+ }
+ else if (MPFR_UNLIKELY (!mpfr_round_p (tmp, tn, p + b1 - 1,
+ MPFR_PREC(a) + (rnd_mode == MPFR_RNDN))))
{
tmp -= k - tn; /* tmp may have changed, FIX IT!!!!! */
goto full_multiply;
diff --git a/src/print_rnd_mode.c b/src/print_rnd_mode.c
index 4aed6a845..89780cf54 100644
--- a/src/print_rnd_mode.c
+++ b/src/print_rnd_mode.c
@@ -27,7 +27,7 @@ mpfr_print_rnd_mode (mpfr_rnd_t rnd_mode)
{
/* If we forget to update this function after a new rounding mode
is added, this will be detected by the following assertion. */
- MPFR_STAT_STATIC_ASSERT (MPFR_RND_MAX == MPFR_RNDA + 1);
+ MPFR_STAT_STATIC_ASSERT (MPFR_RND_MAX == MPFR_RNDF + 1);
switch (rnd_mode)
{
case MPFR_RNDD:
@@ -40,6 +40,8 @@ mpfr_print_rnd_mode (mpfr_rnd_t rnd_mode)
return "MPFR_RNDZ";
case MPFR_RNDA:
return "MPFR_RNDA";
+ case MPFR_RNDF:
+ return "MPFR_RNDF";
default:
return (const char*) 0;
}
diff --git a/src/round_near_x.c b/src/round_near_x.c
index 8f6016f3f..74a905526 100644
--- a/src/round_near_x.c
+++ b/src/round_near_x.c
@@ -159,6 +159,9 @@ mpfr_round_near_x (mpfr_ptr y, mpfr_srcptr v, mpfr_uexp_t err, int dir,
int inexact, sign;
mpfr_flags_t old_flags = __gmpfr_flags;
+ if (rnd == MPFR_RNDF)
+ rnd = MPFR_RNDZ;
+
MPFR_ASSERTD (!MPFR_IS_SINGULAR (v));
MPFR_ASSERTD (dir == 0 || dir == 1);
diff --git a/src/round_prec.c b/src/round_prec.c
index 710c9ac04..d4a5cb4a9 100644
--- a/src/round_prec.c
+++ b/src/round_prec.c
@@ -126,6 +126,8 @@ mpfr_prec_round (mpfr_ptr x, mpfr_prec_t prec, mpfr_rnd_t rnd_mode)
most 2^(MPFR_EXP(b)-err), returns 1 if one is able to round exactly
x to precision prec with direction rnd2, and 0 otherwise.
+ rnd1 = RNDN and RNDF are similar: the sign of the error is unknown.
+
Side effects: none.
*/
@@ -168,6 +170,9 @@ mpfr_can_round_raw (const mp_limb_t *bp, mp_size_t bn, int neg, mpfr_exp_t err0,
/* Transform RNDD and RNDU to Zero / Away */
MPFR_ASSERTD((neg == 0) || (neg == 1));
+ /* transform RNDF to RNDN */
+ if (rnd1 == MPFR_RNDF)
+ rnd1 = MPFR_RNDN;
if (rnd1 != MPFR_RNDN)
rnd1 = MPFR_IS_LIKE_RNDZ(rnd1, neg) ? MPFR_RNDZ : MPFR_RNDA;
if (rnd2 != MPFR_RNDN)
diff --git a/src/sub1.c b/src/sub1.c
index a0bee3d6a..b1e7dc981 100644
--- a/src/sub1.c
+++ b/src/sub1.c
@@ -104,6 +104,10 @@ mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
= B.BBBBBBBBBBBBBBB
- C.CCCCCCCCCCCCC */
/* A = S*ABS(B) +/- ulp(a) */
+
+ if (rnd_mode == MPFR_RNDF)
+ return mpfr_set4 (a, b, rnd_mode, MPFR_SIGN (a));
+
MPFR_SET_EXP (a, MPFR_GET_EXP (b));
MPFR_RNDRAW_EVEN (inexact, a, MPFR_MANT (b), bq,
rnd_mode, MPFR_SIGN (a),
@@ -324,7 +328,12 @@ mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
carry = ap[0] & MPFR_LIMB_MASK (sh);
ap[0] -= carry;
- if (rnd_mode == MPFR_RNDN)
+ if (rnd_mode == MPFR_RNDF)
+ {
+ inexact = 0;
+ goto truncate;
+ }
+ else if (rnd_mode == MPFR_RNDN)
{
if (MPFR_LIKELY(sh))
{
diff --git a/src/sub1sp.c b/src/sub1sp.c
index 9b4b0683d..ac3f74872 100644
--- a/src/sub1sp.c
+++ b/src/sub1sp.c
@@ -325,7 +325,10 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
/* Rounding is necessary since c0 = 1*/
/* Cp =-1 and C'p+1=0 */
bcp = 1; bcp1 = 0;
- if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
+
+ if (MPFR_LIKELY(rnd_mode == MPFR_RNDF))
+ goto truncate;
+ else if (rnd_mode == MPFR_RNDN)
{
/* Even Rule apply: Check Ap-1 */
if (MPFR_LIKELY( (ap[0] & (MPFR_LIMB_ONE<<sh)) == 0) )
@@ -429,7 +432,9 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
bp = MPFR_MANT (b);
/* Even if src and dest overlap, it is OK using MPN_COPY */
- if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
+ if (MPFR_LIKELY(rnd_mode == MPFR_RNDF))
+ goto truncate;
+ else if (rnd_mode == MPFR_RNDN)
{
if (MPFR_UNLIKELY( bcp && bcp1==0 ))
/* Cp=-1 and C'p+1=0: Even rule Apply! */
@@ -479,7 +484,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
/* Copy mantissa B in A */
MPN_COPY(ap, MPFR_MANT(b), n);
/* Round */
- if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
+ if (rnd_mode == MPFR_RNDF || rnd_mode == MPFR_RNDN)
goto truncate;
MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(a));
if (rnd_mode == MPFR_RNDZ)
@@ -666,7 +671,9 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
MPFR_ASSERTD( !(ap[0] & ~mask) );
/* Rounding */
- if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
+ if (MPFR_LIKELY(rnd_mode == MPFR_RNDF))
+ goto truncate;
+ else if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
{
if (MPFR_LIKELY(bcp==0))
goto truncate;
@@ -686,6 +693,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
/* Sub one ulp to the result */
sub_one_ulp:
+ MPFR_ASSERTD(rnd_mode != MPFR_RNDF);
mpn_sub_1 (ap, ap, n, MPFR_LIMB_ONE << sh);
/* Result should be smaller than exact value: inexact=-1 */
inexact = -1;
diff --git a/tests/tabs.c b/tests/tabs.c
index 9f5f5744c..0e6e208d0 100644
--- a/tests/tabs.c
+++ b/tests/tabs.c
@@ -53,14 +53,16 @@ check_inexact (void)
mpfr_set_prec (y, q);
RND_LOOP (rnd)
{
+ if (rnd == MPFR_RNDF)
+ continue; /* the test below makes no sense for RNDF */
inexact = mpfr_abs (y, x, (mpfr_rnd_t) rnd);
cmp = mpfr_cmp (y, absx);
if (((inexact == 0) && (cmp != 0)) ||
((inexact > 0) && (cmp <= 0)) ||
((inexact < 0) && (cmp >= 0)))
{
- printf ("Wrong inexact flag: expected %d, got %d\n",
- cmp, inexact);
+ printf ("Wrong inexact flag for %s: expected %d, got %d\n",
+ mpfr_print_rnd_mode (rnd), cmp, inexact);
printf ("x="); mpfr_dump (x);
printf ("absx="); mpfr_dump (absx);
printf ("y="); mpfr_dump (y);
diff --git a/tests/tadd.c b/tests/tadd.c
index 422b21cd9..71b0ecec1 100644
--- a/tests/tadd.c
+++ b/tests/tadd.c
@@ -517,7 +517,9 @@ check_inexact (void)
abs(EXP(x)-EXP(u)) + max(prec(x), prec(u)) + 1 */
pz = pz + MAX(MPFR_PREC(x), MPFR_PREC(u)) + 1;
mpfr_set_prec (z, pz);
- rnd = RND_RAND ();
+ do
+ rnd = RND_RAND ();
+ while (rnd == MPFR_RNDF);
if (test_add (z, x, u, rnd))
{
printf ("z <- x + u should be exact\n");
@@ -527,7 +529,10 @@ check_inexact (void)
exit (1);
}
{
- rnd = RND_RAND ();
+ do
+ rnd = RND_RAND ();
+ while (rnd == MPFR_RNDF);
+ /* the inexact return value has no sense with RNDF */
inexact = test_add (y, x, u, rnd);
cmp = mpfr_cmp (y, z);
if (((inexact == 0) && (cmp != 0)) ||
@@ -705,7 +710,10 @@ check_1111 (void)
test_add (c, c, one, MPFR_RNDN);
diff = (randlimb () % (2*m)) - m;
mpfr_mul_2si (c, c, diff, MPFR_RNDN);
- rnd_mode = RND_RAND ();
+ /* the inex return value has no sense with RNDF */
+ do
+ rnd_mode = RND_RAND ();
+ while (rnd_mode == MPFR_RNDF);
inex_a = test_add (a, b, c, rnd_mode);
mpfr_init2 (s, MPFR_PREC_MIN + 2*m);
inex_s = test_add (s, b, c, MPFR_RNDN); /* exact */
@@ -775,6 +783,9 @@ check_1minuseps (void)
mpfr_t s;
int inex_a, inex_s;
+ if (rnd_mode == MPFR_RNDF)
+ continue; /* inex_a, inex_s make no sense */
+
mpfr_set_ui (c, 1, MPFR_RNDN);
mpfr_div_ui (c, c, prec_a[ia] + supp_b[ic], MPFR_RNDN);
inex_a = test_add (a, b, c, (mpfr_rnd_t) rnd_mode);
@@ -1110,10 +1121,15 @@ check_extreme (void)
inex = mpfr_add (y, u, w, MPFR_RNDN);
MPFR_ASSERTN (inex == 0);
mpfr_prec_round (y, 32, (mpfr_rnd_t) r);
- if (! mpfr_equal_p (x, y))
+ /* for RNDF, the rounding directions are not necessarily consistent */
+ if (! mpfr_equal_p (x, y) && r != MPFR_RNDF)
{
- printf ("Error in check_extreme (%s, i = %d)\n",
- mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
+ printf ("Error in u + v (%s)\n",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) r));
+ printf ("u = ");
+ mpfr_dump (u);
+ printf ("v = ");
+ mpfr_dump (v);
printf ("Expected ");
mpfr_dump (y);
printf ("Got ");
diff --git a/tests/tadd1sp.c b/tests/tadd1sp.c
index 479e2b179..599d92eb6 100644
--- a/tests/tadd1sp.c
+++ b/tests/tadd1sp.c
@@ -123,6 +123,10 @@ check_random (mpfr_prec_t p)
if (MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c))
for (r = 0 ; r < MPFR_RND_MAX ; r++)
{
+ if (r == MPFR_RNDF) /* inexact makes no sense, moreover
+ mpfr_add1 and mpfr_add1sp could
+ return different values */
+ continue;
inexact1 = mpfr_add1(a1, b, c, (mpfr_rnd_t) r);
inexact2 = mpfr_add1sp(a2, b, c, (mpfr_rnd_t) r);
if (mpfr_cmp(a1, a2))
@@ -148,6 +152,9 @@ check_special (void)
for (r = 0 ; r < MPFR_RND_MAX ; r++)
{
+ if (r == MPFR_RNDF)
+ continue; /* inexact makes no sense, mpfr_add1 and mpfr_add1sp
+ could differ */
SET_PREC(53);
mpfr_set_str1 (b, "1@100");
mpfr_set_str1 (c, "1@1");
diff --git a/tests/tcan_round.c b/tests/tcan_round.c
index 46fb9fdfd..18544f6b0 100644
--- a/tests/tcan_round.c
+++ b/tests/tcan_round.c
@@ -68,6 +68,8 @@ test_pow2 (mpfr_exp_t i, mpfr_prec_t px, mpfr_rnd_t r1, mpfr_rnd_t r2,
mpfr_init2 (x, px);
mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN);
+ /* for mpfr_can_round, r1=RNDF is equivalent to r1=RNDN (the sign of the
+ error is not known) */
b = !!mpfr_can_round (x, i+1, r1, r2, prec);
/* Note: If mpfr_can_round succeeds for both
(r1,r2) = (MPFR_RNDD,MPFR_RNDN) and
diff --git a/tests/texceptions.c b/tests/texceptions.c
index dbd877885..cc8c91e96 100644
--- a/tests/texceptions.c
+++ b/tests/texceptions.c
@@ -56,10 +56,10 @@ check_default_rnd (void)
}
}
mpfr_set_default_rounding_mode ((mpfr_rnd_t) MPFR_RND_MAX);
- if (mpfr_get_default_rounding_mode() != MPFR_RNDA)
+ if (mpfr_get_default_rounding_mode() != MPFR_RNDF)
ERROR("ERROR in setting / getting default rounding mode (2)");
mpfr_set_default_rounding_mode((mpfr_rnd_t) -1);
- if (mpfr_get_default_rounding_mode() != MPFR_RNDA)
+ if (mpfr_get_default_rounding_mode() != MPFR_RNDF)
ERROR("ERROR in setting / getting default rounding mode (3)");
}
@@ -210,7 +210,25 @@ test_set_underflow (void)
j = s < 0 && i > 1 ? 5 - i : i;
inex = mpfr_underflow (x, (mpfr_rnd_t) i, s);
- if (mpfr_cmp (x, r[j]) || inex * t[j] <= 0)
+ /* for RNDF, inex has no meaning, just check that x is either
+ min or zero */
+ if (i == MPFR_RNDF)
+ {
+ if (mpfr_cmp (x, min) && mpfr_cmp (x, zero))
+ {
+ printf ("Error in test_set_underflow, sign = %d,"
+ " rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
+ printf ("Got\n");
+ mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
+ printf ("\ninstead of\n");
+ mpfr_out_str (stdout, 2, 0, zero, MPFR_RNDN);
+ printf ("\nor\n");
+ mpfr_out_str (stdout, 2, 0, min, MPFR_RNDN);
+ printf ("\n");
+ exit (1);
+ }
+ }
+ else if (mpfr_cmp (x, r[j]) || inex * t[j] <= 0)
{
printf ("Error in test_set_underflow, sign = %d,"
" rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
@@ -252,7 +270,25 @@ test_set_overflow (void)
j = s < 0 && i > 1 ? 5 - i : i;
inex = mpfr_overflow (x, (mpfr_rnd_t) i, s);
- if (mpfr_cmp (x, r[j]) || inex * t[j] <= 0)
+ /* for RNDF, inex has no meaning, just check that x is either
+ max or inf */
+ if (i == MPFR_RNDF)
+ {
+ if (mpfr_cmp (x, max) && mpfr_cmp (x, inf))
+ {
+ printf ("Error in test_set_overflow, sign = %d,"
+ " rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
+ printf ("Got\n");
+ mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
+ printf ("\ninstead of\n");
+ mpfr_out_str (stdout, 2, 0, max, MPFR_RNDN);
+ printf ("\nor\n");
+ mpfr_out_str (stdout, 2, 0, inf, MPFR_RNDN);
+ printf ("\n");
+ exit (1);
+ }
+ }
+ else if (mpfr_cmp (x, r[j]) || inex * t[j] <= 0)
{
printf ("Error in test_set_overflow, sign = %d,"
" rnd_mode = %s\n", s, mpfr_print_rnd_mode ((mpfr_rnd_t) i));
diff --git a/tests/tgeneric.c b/tests/tgeneric.c
index 78a852115..382c8ce55 100644
--- a/tests/tgeneric.c
+++ b/tests/tgeneric.c
@@ -307,8 +307,10 @@ test_generic (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int nmax)
/* Exponent range for the test. */
oemin = mpfr_get_emin ();
oemax = mpfr_get_emax ();
-
- rnd = RND_RAND ();
+
+ do
+ rnd = RND_RAND ();
+ while (rnd == MPFR_RNDF); /* inex makes no sense */
mpfr_clear_flags ();
#ifdef DEBUG_TGENERIC
TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (y));
diff --git a/tests/tinternals.c b/tests/tinternals.c
index 597aa31e3..6c670c451 100644
--- a/tests/tinternals.c
+++ b/tests/tinternals.c
@@ -69,6 +69,11 @@ test_round_near_x (void)
for (dir = 0; dir <= 1; dir++)
RND_LOOP(r)
{
+ /* the test below takes into account the ternary value,
+ which has no sense for RNDF */
+ if (r == MPFR_RNDF)
+ continue;
+
inex = mpfr_round_near_x (y, x, err, dir, (mpfr_rnd_t) r);
if (inex == 0 && err < 6)
@@ -80,6 +85,7 @@ test_round_near_x (void)
inex2 = ((dir ^ neg) ? mpfr_add : mpfr_sub)
(z, x, eps, (mpfr_rnd_t) r);
+ /* MPFR_RNDF has no specified ternary value */
if (inex * inex2 <= 0)
printf ("Bad return value (%d instead of %d) for:\n",
inex, inex2);
diff --git a/tests/tmul.c b/tests/tmul.c
index 7e25dbc84..c503ab2ab 100644
--- a/tests/tmul.c
+++ b/tests/tmul.c
@@ -232,7 +232,7 @@ check_exact (void)
printf ("inexact=0 but results differ\n");
exit (1);
}
- else if (inexact && (mpfr_cmp (c, d) == 0))
+ else if (inexact && (mpfr_cmp (c, d) == 0) && rnd != MPFR_RNDF)
{
printf ("inexact!=0 but results agree\n");
printf ("prec=%u rnd=%s a=", (unsigned int) prec,
diff --git a/tests/trint.c b/tests/trint.c
index e762b66b3..e7986ca88 100644
--- a/tests/trint.c
+++ b/tests/trint.c
@@ -171,8 +171,8 @@ special (void)
inex2 = mpfr_rint_##F (z, x, (mpfr_rnd_t) r); \
flags = __gmpfr_flags; \
if (! (mpfr_equal_p (y, z) && \
- SAME_SIGN (inex1, inex2) && \
- flags == ex_flags)) \
+ (r == MPFR_RNDF || (SAME_SIGN (inex1, inex2) && \
+ flags == ex_flags)))) \
{ \
printf ("Basic test failed on mpfr_rint_" #F \
", prec = %d, i = %d, %s\n", prec, s * i, \
@@ -548,7 +548,7 @@ main (int argc, char *argv[])
mpfr_rint_floor (y, x, MPFR_RNDD));
else
{
- MPFR_ASSERTN (r == MPFR_RNDA);
+ MPFR_ASSERTN (r == MPFR_RNDA || r == MPFR_RNDF);
continue;
}
if (mpfr_sub (t, y, x, MPFR_RNDN))
diff --git a/tests/tset.c b/tests/tset.c
index c7bfa3ad6..ad407b645 100644
--- a/tests/tset.c
+++ b/tests/tset.c
@@ -138,14 +138,17 @@ check_ternary_value (void)
mpfr_set_prec (y, q);
for (rnd = 0; rnd < MPFR_RND_MAX; rnd++)
{
+ if (rnd == MPFR_RNDF) /* the test below makes no sense */
+ continue;
inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
cmp = mpfr_cmp (y, x);
if (((inexact == 0) && (cmp != 0)) ||
((inexact > 0) && (cmp <= 0)) ||
((inexact < 0) && (cmp >= 0)))
{
- printf ("Wrong ternary value in mpfr_set: expected %d,"
- " got %d\n", cmp, inexact);
+ printf ("Wrong ternary value in mpfr_set for %s: expected"
+ " %d, got %d\n", mpfr_print_rnd_mode (rnd), cmp,
+ inexact);
exit (1);
}
/* Test mpfr_set function too */
diff --git a/tests/tsub.c b/tests/tsub.c
index a37399d81..71a57660c 100644
--- a/tests/tsub.c
+++ b/tests/tsub.c
@@ -443,14 +443,16 @@ check_inexact (void)
: MPFR_EXP(u) - MPFR_EXP(x);
pz = pz + MAX(MPFR_PREC(x), MPFR_PREC(u));
mpfr_set_prec (z, pz);
- rnd = RND_RAND ();
+ /* for RNDF, inexact makes no sense */
+ do rnd = RND_RAND (); while (rnd == MPFR_RNDF);
if (test_sub (z, x, u, rnd))
{
printf ("z <- x - u should be exact\n");
exit (1);
}
{
- rnd = RND_RAND ();
+ /* for RNDF, inexact makes no sense */
+ do rnd = RND_RAND (); while (rnd == MPFR_RNDF);
inexact = test_sub (y, x, u, rnd);
cmp = mpfr_cmp (y, z);
if (((inexact == 0) && (cmp != 0)) ||
diff --git a/tests/tsub1sp.c b/tests/tsub1sp.c
index 460a5dd6f..2920cb11f 100644
--- a/tests/tsub1sp.c
+++ b/tests/tsub1sp.c
@@ -83,6 +83,9 @@ check_random (mpfr_prec_t p)
if (MPFR_IS_PURE_FP(y) && MPFR_IS_PURE_FP(z))
for(r = 0 ; r < MPFR_RND_MAX ; r++)
{
+ if (r == MPFR_RNDF)
+ continue; /* mpfr_sub1 and mpfr_sub1sp could differ,
+ and inexact makes no sense */
inexact1 = mpfr_sub1(x2, y, z, (mpfr_rnd_t) r);
inexact2 = mpfr_sub1sp(x, y, z, (mpfr_rnd_t) r);
if (mpfr_cmp(x, x2))
@@ -108,6 +111,9 @@ check_special (void)
for (r = 0 ; r < MPFR_RND_MAX ; r++)
{
+ if (r == MPFR_RNDF)
+ continue; /* comparison between sub1 and sub1sp makes no sense here */
+
p = 53;
mpfr_set_prec(x, 53);
mpfr_set_prec(x2, 53);