diff options
-rw-r--r-- | mpn_exp.c | 17 | ||||
-rw-r--r-- | set_str.c | 8 | ||||
-rw-r--r-- | tests/tset_str.c | 15 |
3 files changed, 35 insertions, 5 deletions
@@ -30,7 +30,10 @@ MA 02111-1307, USA. */ that is: a*2^exp_r <= b^e <= 2^exp_r (a + 2^f), where a represents {a, n}, i.e. the integer - a[0] + a[1]*B + ... + a[n-1]*B^(n-1) where B=2^BITS_PER_MP_LIMB */ + a[0] + a[1]*B + ... + a[n-1]*B^(n-1) where B=2^BITS_PER_MP_LIMB + + Return -2 if an overflow occurred in the computation of exp_r. +*/ long mpfr_mpn_exp (mp_limb_t *a, mp_exp_t *exp_r, int b, mp_exp_t e, size_t n) @@ -91,7 +94,17 @@ mpfr_mpn_exp (mp_limb_t *a, mp_exp_t *exp_r, int b, mp_exp_t e, size_t n) /* set {c+n, 2n1-n} to 0 : {c, n} = {a, n}^2*K^n */ - f = 2 * f + n * BITS_PER_MP_LIMB; + /* check overflow on f */ + { + mp_exp_t oldf = f; + f = 2 * f; + if (f / 2 != oldf) + { + TMP_FREE(marker); + return -2; + } + } + f += n * BITS_PER_MP_LIMB; if ((c[2*n - 1] & MPFR_LIMB_HIGHBIT) == 0) { /* shift A by one bit to the left */ @@ -269,6 +269,11 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd) /* z is allocated at y - n */ z = y - n; err = mpfr_mpn_exp (z, &exp_z, base, exp_s - (mp_exp_t) pr, n); + if (err == -2) /* overflow in exp_z, return Inf */ + { + exp_y = __mpfr_emax; + goto free; + } exact = (exact && (err == -1)); /* multiply(y = 0.mant_s[0]...mant_s[pr-1])_base by base^(exp_s-g) */ @@ -363,6 +368,7 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd) exp_y ++; } + free: TMP_FREE(marker); /* Set sign of x before exp since check_range needs a valid sign */ @@ -372,7 +378,7 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd) MPFR_SET_POS(x); /* DO NOT USE MPFR_SET_EXP. The exp may be out of range! */ MPFR_EXP (x) = exp_y + n * BITS_PER_MP_LIMB; - res = mpfr_check_range (x, res, rnd ); + res = mpfr_check_range (x, res, rnd); end: (*__gmp_free_func) (str1, size_str1 * sizeof (char)); diff --git a/tests/tset_str.c b/tests/tset_str.c index f90db1f34..5e486d022 100644 --- a/tests/tset_str.c +++ b/tests/tset_str.c @@ -33,12 +33,12 @@ static void check_underflow (void) { mpfr_t a; - mp_exp_t emin; + mp_exp_t emin, emax; int res; mpfr_init (a); - /* Check undeflow */ + /* Check underflow */ emin = mpfr_get_emin (); mpfr_set_emin (-20); res = mpfr_set_str (a, "0.00000000001", 10, GMP_RNDZ); @@ -52,6 +52,17 @@ check_underflow (void) } mpfr_set_emin (emin); + /* check overflow */ + emax = mpfr_get_emax (); + mpfr_set_emax (1073741823); /* 2^30-1 */ + mpfr_set_str (a, "2E1000000000", 10, GMP_RNDN); + if (!mpfr_inf_p (a) || mpfr_sgn (a) < 0) + { + printf("ERROR for mpfr_set_str (a, \"2E1000000000\", 10, GMP_RNDN);\n"); + exit (1); + } + mpfr_set_emax (emax); + mpfr_clear (a); } |