summaryrefslogtreecommitdiff
path: root/pow.c
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2003-10-10 09:05:15 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2003-10-10 09:05:15 +0000
commitd576f5ce56722d4dd32f1d0d02ffbefb26386d2d (patch)
treeb7296ab4ca506ce6f1a101d0bfc8d96d5d46a81b /pow.c
parentc491f054ee2b8ce0eafbc7023245e757ea16090e (diff)
downloadmpfr-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.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/pow.c b/pow.c
index f6cc45a3c..7c965f632 100644
--- a/pow.c
+++ b/pow.c
@@ -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;