summaryrefslogtreecommitdiff
path: root/src/sub1.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sub1.c')
-rw-r--r--src/sub1.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/sub1.c b/src/sub1.c
index 9337cc235..5b475d9d3 100644
--- a/src/sub1.c
+++ b/src/sub1.c
@@ -123,11 +123,11 @@ mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
if (rnd_mode == MPFR_RNDF)
return mpfr_set4 (a, b, MPFR_RNDZ, MPFR_SIGN (a));
- MPFR_EXP (a) = exp_b; /* may be up to MPFR_EXP_MAX */
+ exp_a = exp_b; /* may be any out-of-range value due to UBF */
MPFR_RNDRAW_EVEN (inexact, a, MPFR_MANT (b), bq,
rnd_mode, MPFR_SIGN (a),
- if (MPFR_EXP (a) != MPFR_EXP_MAX)
- ++ MPFR_EXP (a));
+ if (exp_a != MPFR_EXP_MAX)
+ exp_a ++);
MPFR_LOG_MSG (("inexact=%d\n", inexact));
if (inexact == 0)
{
@@ -139,7 +139,7 @@ mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
if (! MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (a)))
{
inexact = MPFR_INT_SIGN (a);
- goto check_overflow;
+ goto end_of_c_small;
}
}
else /* inexact != 0 */
@@ -164,7 +164,7 @@ mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
which means we get a wrong rounded result if x == 1,
i.e. inexact == MPFR_EVEN_INEX (for positive numbers). */
if (MPFR_LIKELY (inexact != MPFR_EVEN_INEX * MPFR_INT_SIGN (a)))
- goto check_overflow;
+ goto end_of_c_small;
}
/* We need to take the value preceding |a|. We can't use
mpfr_nexttozero due to a possible out-of-range exponent.
@@ -174,16 +174,20 @@ mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
mpn_sub_1 (ap, ap, an, MPFR_LIMB_ONE << sh);
if (MPFR_UNLIKELY (MPFR_LIMB_MSB (ap[an-1]) == 0))
{
- MPFR_EXP (a) --;
+ exp_a --;
/* The following is valid whether an = 1 or an > 1. */
ap[an-1] |= MPFR_LIMB_HIGHBIT;
}
inexact = - MPFR_INT_SIGN (a);
- check_overflow:
- if (MPFR_UNLIKELY (MPFR_EXP (a) > __gmpfr_emax))
+ end_of_c_small:
+ /* The underflow case is possibly only with UBF. The overflow case
+ is also possible with normal FP due to rounding. */
+ if (MPFR_UNLIKELY (exp_a > __gmpfr_emax))
return mpfr_overflow (a, rnd_mode, MPFR_SIGN (a));
- else
- MPFR_RET (inexact);
+ if (MPFR_UNLIKELY (exp_a < __gmpfr_emin))
+ goto underflow;
+ MPFR_SET_EXP (a, exp_a);
+ MPFR_RET (inexact);
}
/* reserve a space to store b aligned with the result, i.e. shifted by