summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exp.c11
-rw-r--r--exp_2.c5
-rw-r--r--gamma.c5
-rw-r--r--tests/texp.c20
-rw-r--r--tests/tgamma.c27
5 files changed, 62 insertions, 6 deletions
diff --git a/exp.c b/exp.c
index f4f323ccd..4682896b8 100644
--- a/exp.c
+++ b/exp.c
@@ -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);
}
diff --git a/exp_2.c b/exp_2.c
index b72f7250e..35437c9b3 100644
--- a/exp_2.c
+++ b/exp_2.c
@@ -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 */
diff --git a/gamma.c b/gamma.c
index f15dfedcd..dcbaf11d3 100644
--- a/gamma.c
+++ b/gamma.c
@@ -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 ();