diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-05-28 04:59:39 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-05-28 04:59:39 +0000 |
commit | cf11a3eb08d62789a6fdc3347da236c3c389743f (patch) | |
tree | bee39cc3ec584c505e659c2b6a6fc2af81d16ec9 | |
parent | ed11b5b94687c1a0cefe59f2e899c6e6f08ff589 (diff) | |
download | mpfr-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-- | TODO | 3 | ||||
-rw-r--r-- | doc/mpfr.texi | 3 | ||||
-rw-r--r-- | src/add1.c | 19 | ||||
-rw-r--r-- | src/add1sp.c | 29 | ||||
-rw-r--r-- | src/mpfr-impl.h | 13 | ||||
-rw-r--r-- | src/mpfr.h | 5 | ||||
-rw-r--r-- | src/mul.c | 10 | ||||
-rw-r--r-- | src/print_rnd_mode.c | 4 | ||||
-rw-r--r-- | src/round_near_x.c | 3 | ||||
-rw-r--r-- | src/round_prec.c | 5 | ||||
-rw-r--r-- | src/sub1.c | 11 | ||||
-rw-r--r-- | src/sub1sp.c | 16 | ||||
-rw-r--r-- | tests/tabs.c | 6 | ||||
-rw-r--r-- | tests/tadd.c | 28 | ||||
-rw-r--r-- | tests/tadd1sp.c | 7 | ||||
-rw-r--r-- | tests/tcan_round.c | 2 | ||||
-rw-r--r-- | tests/texceptions.c | 44 | ||||
-rw-r--r-- | tests/tgeneric.c | 6 | ||||
-rw-r--r-- | tests/tinternals.c | 6 | ||||
-rw-r--r-- | tests/tmul.c | 2 | ||||
-rw-r--r-- | tests/trint.c | 6 | ||||
-rw-r--r-- | tests/tset.c | 7 | ||||
-rw-r--r-- | tests/tsub.c | 6 | ||||
-rw-r--r-- | tests/tsub1sp.c | 6 |
24 files changed, 198 insertions, 49 deletions
@@ -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; @@ -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); |