diff options
author | Paul Zimmermann <paul.zimmermann@inria.fr> | 2012-02-29 15:28:02 +0000 |
---|---|---|
committer | Paul Zimmermann <paul.zimmermann@inria.fr> | 2012-02-29 15:28:02 +0000 |
commit | 86483c8d97f2142029abe0cc35dd8bc245992fe4 (patch) | |
tree | 7ce13de4e114e79ed069976687ff8d8a460a8876 /src/sqr.c | |
parent | 1c870e7197608a75855bbfefe617a44f850458f5 (diff) | |
download | mpc-git-86483c8d97f2142029abe0cc35dd8bc245992fe4.tar.gz |
[src/sqr.c] fixed overflow bug found by nightly tests on hydra.org
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/mpc/trunk@1128 211d60ee-9f03-0410-a15a-8952a2c7a4e4
Diffstat (limited to 'src/sqr.c')
-rw-r--r-- | src/sqr.c | 45 |
1 files changed, 27 insertions, 18 deletions
@@ -172,29 +172,38 @@ mpc_sqr (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd) } else { + mpfr_rnd_t rnd_re = MPC_RND_RE (rnd); inexact |= mpfr_mul (u, u, v, GMP_RNDD); /* error 5 */ - /* checks that no overflow occurs: since u*v < 0 and we round down, - an overflow will give -Inf */ - MPC_ASSERT (mpfr_inf_p (u) == 0); - /* if an underflow happens (i.e., u = -0.5*2^emin since we round - away from zero), the result will be an underflow */ - if (mpfr_get_exp (u) == emin) + /* if an overflow occurs: since u*v < 0 and we round down, + the result is -Inf or -MAXDBL */ + if (mpfr_inf_p (u)) + { + /* replace by "correctly rounded overflow" */ + mpfr_set_si (u, -1, GMP_RNDN); + mpfr_mul_2ui (u, u, mpfr_get_emax (), rnd_re); + ok = 1; + } + else { - mpfr_rnd_t rnd_re = MPC_RND_RE (rnd); - if (rnd_re == GMP_RNDZ || rnd_re == GMP_RNDN || - rnd_re == GMP_RNDU) + /* if an underflow happens (i.e., u = -0.5*2^emin since we round + away from zero), the result will be an underflow */ + if (mpfr_get_exp (u) == emin) { - mpfr_set_ui (mpc_realref (rop), 0, rnd_re); - inex_re = 1; + if (rnd_re == GMP_RNDZ || rnd_re == GMP_RNDN || + rnd_re == GMP_RNDU) + { + mpfr_set_ui (mpc_realref (rop), 0, rnd_re); + inex_re = 1; + } + else /* round down or away from zero */ { + mpfr_set (mpc_realref (rop), u, rnd_re); + inex_re = -1; + } + break; } - else /* round down or away from zero */ { - mpfr_set (mpc_realref (rop), u, rnd_re); - inex_re = -1; - } - break; + ok = (!inexact) | mpfr_can_round (u, prec - 3, GMP_RNDD, + GMP_RNDZ, MPC_PREC_RE (rop) + (MPC_RND_RE (rnd) == GMP_RNDN)); } - ok = (!inexact) | mpfr_can_round (u, prec - 3, GMP_RNDD, GMP_RNDZ, - MPC_PREC_RE (rop) + (MPC_RND_RE (rnd) == GMP_RNDN)); if (ok) { inex_re = mpfr_set (mpc_realref (rop), u, MPC_RND_RE (rnd)); |