summaryrefslogtreecommitdiff
path: root/gmp_op.c
diff options
context:
space:
mode:
authorpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2004-03-26 13:24:58 +0000
committerpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2004-03-26 13:24:58 +0000
commit07c212c9a824cfe947077b93c0635f0822a7d2fb (patch)
tree3fcfc434d666a59609742ac40b813fc004495f99 /gmp_op.c
parent40aa3e0140c2fcedde37cc1d7652ab2205f4d673 (diff)
downloadmpfr-07c212c9a824cfe947077b93c0635f0822a7d2fb.tar.gz
Fix a bug.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2856 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'gmp_op.c')
-rw-r--r--gmp_op.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/gmp_op.c b/gmp_op.c
index c9f733f23..9ab258e2c 100644
--- a/gmp_op.c
+++ b/gmp_op.c
@@ -150,6 +150,7 @@ mpfr_add_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z, mp_rnd_t rnd_mode)
mpfr_set_prec(q, p);
res = mpfr_set_q(q, z, GMP_RNDN); /* Error <= 1/2 ulp(q) */
+ /* If z if @INF@ (1/0), res = 0, so it quits immediately */
if (res == 0) /* Result is exact so we can add it directly!*/
{
res = mpfr_add(y, x, q, rnd_mode);
@@ -160,15 +161,19 @@ mpfr_add_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z, mp_rnd_t rnd_mode)
If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t)))
<= 2^(EXP(q)-EXP(t))
If EXP(q)-EXP(t)<0, <= 2^0 */
- err = (mp_exp_t) p - 1 - MAX(MPFR_GET_EXP(q)-MPFR_GET_EXP(t), 0);
- res = mpfr_can_round (t, err, GMP_RNDN, GMP_RNDZ,
- MPFR_PREC(y) + (rnd_mode == GMP_RNDN) );
- p += BITS_PER_MP_LIMB; /* Next precision if we continue */
- if (res != 0) /* We can round! */
+ /* We can get 0, but we can't round since q is inexact */
+ if (MPFR_LIKELY( !MPFR_IS_ZERO (t)))
{
- res = mpfr_set(y, t, rnd_mode);
- break;
+ err = (mp_exp_t) p - 1 - MAX(MPFR_GET_EXP(q)-MPFR_GET_EXP(t), 0);
+ res = mpfr_can_round (t, err, GMP_RNDN, GMP_RNDZ,
+ MPFR_PREC(y) + (rnd_mode == GMP_RNDN) );
+ if (res != 0) /* We can round! */
+ {
+ res = mpfr_set(y, t, rnd_mode);
+ break;
+ }
}
+ p += BITS_PER_MP_LIMB; /* Next precision if we continue */
}
mpfr_clears(t, q, NULL);
return res;
@@ -215,6 +220,7 @@ mpfr_sub_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z,mp_rnd_t rnd_mode)
mpfr_set_prec(q, p);
res = mpfr_set_q(q, z, GMP_RNDN); /* Error <= 1/2 ulp(q) */
+ /* If z if @INF@ (1/0), res = 0, so it quits immediately */
if (res == 0) /* Result is exact so we can add it directly!*/
{
res = mpfr_sub(y, x, q, rnd_mode);
@@ -225,15 +231,19 @@ mpfr_sub_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z,mp_rnd_t rnd_mode)
If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t)))
<= 2^(EXP(q)-EXP(t))
If EXP(q)-EXP(t)<0, <= 2^0 */
- err = (mp_exp_t) p - 1 - MAX(MPFR_GET_EXP(q)-MPFR_GET_EXP(t), 0);
- res = mpfr_can_round (t, err, GMP_RNDN, GMP_RNDZ,
- MPFR_PREC(y) + (rnd_mode == GMP_RNDN) );
+ /* We can get 0, but we can't round since q is inexact */
+ if (MPFR_LIKELY( !MPFR_IS_ZERO (t)))
+ {
+ err = (mp_exp_t) p - 1 - MAX(MPFR_GET_EXP(q)-MPFR_GET_EXP(t), 0);
+ res = mpfr_can_round (t, err, GMP_RNDN, GMP_RNDZ,
+ MPFR_PREC(y) + (rnd_mode == GMP_RNDN) );
+ if (res != 0) /* We can round! */
+ {
+ res = mpfr_set(y, t, rnd_mode);
+ break;
+ }
+ }
p += BITS_PER_MP_LIMB; /* Next precision if we continue */
- if (res != 0) /* We can round! */
- {
- res = mpfr_set(y, t, rnd_mode);
- break;
- }
}
mpfr_clears(t, q, NULL);
return res;