diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-12-20 13:29:13 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-12-20 13:29:13 +0000 |
commit | 8810a86640231455f9bef7db6711d2ee934baf02 (patch) | |
tree | 6ddd1e6e093a7fdcff9011fc66daab95e6377843 /src/sum.c | |
parent | b39b2c10d3c012c785e6e845aacda43845c8625e (diff) | |
download | mpfr-8810a86640231455f9bef7db6711d2ee934baf02.tar.gz |
[src/sum.c] Improvement for MPFR_RNDF, but still based on the change
done in r10512, which was incorrect; added a FIXME (a non-regression
test needs to be added first).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/faithful@11077 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/sum.c')
-rw-r--r-- | src/sum.c | 44 |
1 files changed, 32 insertions, 12 deletions
@@ -634,14 +634,40 @@ sum_aux (mpfr_ptr sum, mpfr_ptr *const x, unsigned long n, mpfr_rnd_t rnd, u = e - sq; /* e being the exponent, u is the ulp of the target */ - MPFR_LOG_MSG (("cancel=%Pd" + /* neg = 1 if negative, 0 if positive. */ + neg = wp[ws-1] >> (GMP_NUMB_BITS - 1); + MPFR_ASSERTD (neg == 0 || neg == 1); + + sgn = neg ? -1 : 1; + MPFR_ASSERTN (sgn == (neg ? MPFR_SIGN_NEG : MPFR_SIGN_POS)); + + MPFR_LOG_MSG (("neg=%d sgn=%d cancel=%Pd" " e=%" MPFR_EXP_FSPEC "d" " u=%" MPFR_EXP_FSPEC "d" " maxexp=%" MPFR_EXP_FSPEC "d%s\n", - cancel, (mpfr_eexp_t) e, (mpfr_eexp_t) u, + neg, sgn, cancel, (mpfr_eexp_t) e, (mpfr_eexp_t) u, (mpfr_eexp_t) maxexp, maxexp == MPFR_EXP_MIN ? " (MPFR_EXP_MIN)" : "")); + if (rnd == MPFR_RNDF) + { + /* FIXME: The following is like MPFR_RNDD on the approximate + value. This means that one may not get a faithfully rounded + result. One needs to take the rounding bit into account. + Reusing the generic code by delaying the rnd == MPFR_RNDF + test is not a good idea, because this code does more than + necessary for a faithful rounding; just copy some parts + from it. + However, the tests currently pass. We need to trigger a failure + first. */ + corr = 0; + inex = 0; /* not meaningful, but needs to have a value */ + } + else /* rnd != MPFR_RNDF */ + { + /* Note: This block has not been reindented after this test + for MPFR_RNDF has been added in the faithful branch. */ + if (MPFR_LIKELY (u > minexp)) { mpfr_prec_t tq; @@ -821,13 +847,6 @@ sum_aux (mpfr_ptr sum, mpfr_ptr *const x, unsigned long n, mpfr_rnd_t rnd, MPFR_ASSERTD (rbit == 0 || rbit == 1); - /* neg = 1 if negative, 0 if positive. */ - neg = wp[ws-1] >> (GMP_NUMB_BITS - 1); - MPFR_ASSERTD (neg == 0 || neg == 1); - - sgn = neg ? -1 : 1; - MPFR_ASSERTN (sgn == (neg ? MPFR_SIGN_NEG : MPFR_SIGN_POS)); - MPFR_LOG_MSG (("tmd=%d lbit=%d rbit=%d inex=%d neg=%d\n", tmd, (int) lbit, (int) rbit, inex, neg)); @@ -846,9 +865,7 @@ sum_aux (mpfr_ptr sum, mpfr_ptr *const x, unsigned long n, mpfr_rnd_t rnd, * change of the binade. */ - if (rnd == MPFR_RNDF) - corr = 0; - else if (tmd == 0) /* no TMD */ + if (tmd == 0) /* no TMD */ { switch (rnd) { @@ -1006,6 +1023,9 @@ sum_aux (mpfr_ptr sum, mpfr_ptr *const x, unsigned long n, mpfr_rnd_t rnd, corr = (int) rbit; } + /* Note: The above block has not be reindented. */ + } /* rnd != MPFR_RNDF */ + MPFR_LOG_MSG (("neg=%d corr=%d inex=%d\n", neg, corr, inex)); /* Sign handling (-> absolute value and sign), together with |