diff options
-rw-r--r-- | exp.c | 11 | ||||
-rw-r--r-- | exp_2.c | 5 | ||||
-rw-r--r-- | gamma.c | 5 | ||||
-rw-r--r-- | tests/texp.c | 20 | ||||
-rw-r--r-- | tests/tgamma.c | 27 |
5 files changed, 62 insertions, 6 deletions
@@ -31,7 +31,7 @@ MA 02111-1307, USA. */ int mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) { - int expx, precy; + int expx, precy, inexact; double d; if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(x) )) @@ -102,8 +102,11 @@ mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) return -MPFR_FROM_SIGN_TO_INT(signx); } - if (precy > MPFR_EXP_THRESHOLD) - return mpfr_exp_3 (y, x, rnd_mode); /* O(M(n) log(n)^2) */ + mpfr_save_emin_emax (); + if (MPFR_UNLIKELY(precy > MPFR_EXP_THRESHOLD)) + inexact = mpfr_exp_3 (y, x, rnd_mode); /* O(M(n) log(n)^2) */ else - return mpfr_exp_2 (y, x, rnd_mode); /* O(n^(1/3) M(n)) */ + inexact = mpfr_exp_2 (y, x, rnd_mode); /* O(n^(1/3) M(n)) */ + mpfr_restore_emin_emax (); + return mpfr_check_range (y, inexact, rnd_mode); } @@ -110,6 +110,10 @@ mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) TMP_DECL(marker); precy = MPFR_PREC(y); + +#ifdef DEBUG + printf("Py=%d Px=%d X=", MPFR_PREC(y), MPFR_PREC(x)); mpfr_dump (x); +#endif n = (int) (mpfr_get_d1 (x) / LOG2); @@ -192,6 +196,7 @@ mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) exps += mpz_normalize (ss, ss, q); } mpfr_set_z (s, ss, GMP_RNDN); + MPFR_SET_EXP(s, MPFR_GET_EXP (s) + exps); TMP_FREE(marker); /* don't need ss anymore */ @@ -99,6 +99,8 @@ mpfr_gamma (mpfr_ptr gamma, mpfr_srcptr x, mp_rnd_t rnd_mode) return mpfr_fac_ui (gamma, u - 1, rnd_mode); } + mpfr_save_emin_emax (); + realprec = prec_gamma + 10; mpfr_init2 (xp, 2); @@ -220,6 +222,7 @@ mpfr_gamma (mpfr_ptr gamma, mpfr_srcptr x, mp_rnd_t rnd_mode) mpfr_clear(GammaTrial); mpfr_clear (xp); + mpfr_restore_emin_emax (); - return inex; /* inexact result */ + return mpfr_check_range(gamma, inex, rnd_mode); } diff --git a/tests/texp.c b/tests/texp.c index ae0a2ec76..39b2ae2b5 100644 --- a/tests/texp.c +++ b/tests/texp.c @@ -284,6 +284,26 @@ check_special () mpfr_set_prec (y, 2); mpfr_exp_3 (y, x, GMP_RNDN); + /* Check some little things about overflow detection */ + mpfr_set_emin (-125); + mpfr_set_emax (128); + mpfr_set_prec (x, 107); + mpfr_set_prec (y, 107); + mpfr_set_str_binary (x, "0.11110000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000" + "00000000E4"); + mpfr_exp (y, x, GMP_RNDN); + if (mpfr_cmp_str (y, "0.11000111100001100110010101111101011010010101010000" + "1101110111100010111001011111111000110111001011001101010" + "01E22", 2, GMP_RNDN)) + { + printf ("Special overflow error (1)\n"); + mpfr_dump (y); + exit (1); + } + mpfr_set_emin (MPFR_EMIN_MIN); + mpfr_set_emax (MPFR_EMAX_MAX); + mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); diff --git a/tests/tgamma.c b/tests/tgamma.c index 9bd642d6b..5894bfd06 100644 --- a/tests/tgamma.c +++ b/tests/tgamma.c @@ -166,13 +166,38 @@ special (void) mpfr_clear (y); } +static void +special_overflow (void) +{ + mpfr_t x, y; + + mpfr_set_emin (-125); + mpfr_set_emax (128); + + mpfr_init2 (x, 24); + mpfr_init2 (y, 24); + mpfr_set_str_binary (x, "0.101100100000000000110100E7"); + mpfr_gamma (y, x, GMP_RNDN); + if (!mpfr_inf_p (y)) + { + printf("Overflow error.\n"); + mpfr_dump (y); + exit (1); + } + + mpfr_clear (y); + mpfr_clear (x); + mpfr_set_emin (MPFR_EMIN_MIN); + mpfr_set_emax (MPFR_EMAX_MAX); +} + int main (void) { tests_start_mpfr (); special (); - + special_overflow (); test_generic (2, 100, 2); tests_end_mpfr (); |