diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2003-10-10 09:05:15 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2003-10-10 09:05:15 +0000 |
commit | d576f5ce56722d4dd32f1d0d02ffbefb26386d2d (patch) | |
tree | b7296ab4ca506ce6f1a101d0bfc8d96d5d46a81b /pow.c | |
parent | c491f054ee2b8ce0eafbc7023245e757ea16090e (diff) | |
download | mpfr-d576f5ce56722d4dd32f1d0d02ffbefb26386d2d.tar.gz |
fixed bug in mpfr_pow found by Ming J. Tsai (overflow)
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2487 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'pow.c')
-rw-r--r-- | pow.c | 17 |
1 files changed, 16 insertions, 1 deletions
@@ -240,7 +240,7 @@ mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) { int negative; /* Determine the sign now, in case y and z are the same object */ - negative = MPFR_SIGN(x) < 0 && is_odd(y); + negative = MPFR_SIGN(x) < 0 && is_odd (y); MPFR_CLEAR_FLAGS(z); if (MPFR_SIGN(y) < 0) MPFR_SET_INF(z); @@ -258,6 +258,21 @@ mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) MPFR_RET(0); } + /* detect overflows: |x^y| >= 2^EMAX when (EXP(x)-1) * y >= EMAX for y > 0, + or EXP(x) * y >= EMAX for y < 0 */ + { + double exy; + int negative; + + exy = (double) (mpfr_sgn (y) > 0) ? MPFR_EXP(x) - 1 : MPFR_EXP(x); + exy *= mpfr_get_d (y, GMP_RNDZ); + if (exy >= (double) __gmpfr_emax) + { + negative = MPFR_SIGN(x) < 0 && is_odd (y); + return mpfr_set_overflow (z, rnd_mode, negative ? -1 : 1); + } + } + if (mpfr_integer_p (y)) { mpz_t zi; |