summaryrefslogtreecommitdiff
path: root/pow_si.c
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2007-01-19 08:31:32 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2007-01-19 08:31:32 +0000
commit2333ddd1383458a2fc880963da7fdefe9953b5f2 (patch)
tree9050ba0fb4d018cf2f7eeda6af3b2c31473b141a /pow_si.c
parent7be4f4de79ec24eae29e0dd95007d194f592760f (diff)
downloadmpfr-2333ddd1383458a2fc880963da7fdefe9953b5f2.tar.gz
pow_si.c: fixed the overflow detection for x power of 2 and n negative.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@4345 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'pow_si.c')
-rw-r--r--pow_si.c19
1 files changed, 8 insertions, 11 deletions
diff --git a/pow_si.c b/pow_si.c
index b1ef90ab7..2eb3c32e7 100644
--- a/pow_si.c
+++ b/pow_si.c
@@ -67,21 +67,18 @@ mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mp_rnd_t rnd)
/* detect exact powers: x^(-n) is exact iff x is a power of 2 */
if (mpfr_cmp_si_2exp (x, MPFR_SIGN(x), MPFR_EXP(x) - 1) == 0)
{
- mp_exp_t expx = MPFR_EXP (x) - 1; /* Warning: x and y may be
- the same variable */
- mpfr_set_si (y, (n % 2) ? MPFR_INT_SIGN (x) : 1, rnd);
- MPFR_ASSERTD (MPFR_EXP (y) == 1);
+ mp_exp_t expx = MPFR_EXP (x) - 1, expy;
MPFR_ASSERTD (n < 0);
/* Warning: n * expx may overflow!
Some systems (apparently alpha-freebsd) abort with
LONG_MIN / 1, and LONG_MIN / -1 is undefined. */
- if (n != -1 && expx > 0 && expx > MPFR_EXP_MIN / n)
- MPFR_EXP (y) = MPFR_EMIN_MIN - 1; /* Underflow */
- else if (n != -1 && expx < 0 && expx < MPFR_EXP_MAX / n)
- MPFR_EXP (y) = MPFR_EMAX_MAX + 1; /* Overflow */
- else
- MPFR_EXP (y) += n * expx;
- return mpfr_check_range (y, 0, rnd);
+ expy =
+ n != -1 && expx > 0 && expx > (__gmpfr_emin - 1) / n ?
+ MPFR_EMIN_MIN - 2 /* Underflow */ :
+ n != -1 && expx < 0 && expx < (__gmpfr_emax - 1) / n ?
+ MPFR_EMAX_MAX /* Overflow */ : n * expx;
+ return mpfr_set_si_2exp (y, n % 2 ? MPFR_INT_SIGN (x) : 1,
+ expy, rnd);
}
n = -n;