diff options
-rw-r--r-- | pow.c | 17 | ||||
-rw-r--r-- | tests/tpow.c | 28 |
2 files changed, 43 insertions, 2 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; diff --git a/tests/tpow.c b/tests/tpow.c index 368c29199..fa183e77e 100644 --- a/tests/tpow.c +++ b/tests/tpow.c @@ -268,7 +268,7 @@ particular_cases (void) } static void -underflows(void) +underflows (void) { mpfr_t x, y; int i; @@ -299,6 +299,30 @@ underflows(void) mpfr_clear (y); } +static void +overflows (void) +{ + mpfr_t a, b; + + /* bug found by Ming J. Tsai <mingjt@delvron.us>, 4 Oct 2003 */ + + mpfr_init_set_d (a, 5.1e32, GMP_RNDN); + mpfr_init (b); + + mpfr_pow (b, a, a, GMP_RNDN); + if (!(mpfr_inf_p (b) && mpfr_sgn (b) > 0)) + { + printf ("Error for a^a for a=5.1e32\n"); + printf ("Expected +Inf, got "); + mpfr_out_str (stdout, 10, 0, b, GMP_RNDN); + printf ("\n"); + exit (1); + } + + mpfr_clear(a); + mpfr_clear(b); +} + int main (void) { @@ -317,6 +341,8 @@ main (void) /* underflows (); */ + overflows (); + tests_end_mpfr (); return 0; } |