diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2007-12-18 15:17:09 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2007-12-18 15:17:09 +0000 |
commit | fc967316e0e33f6f4390ef835ff311213221065e (patch) | |
tree | ebbb37da7e6997455562922a598704d7f34fa69a | |
parent | d9ddf052467eaaabf520b61b54b68f9b477ced13 (diff) | |
download | mpfr-feature-block.tar.gz |
Use MPFR_BLOCK_* macros, fixing potential bugs. At the same time, bugsfeature-block
in pow_ui.c and pow_z.c were fixed (corresponding to r5108 and r5110).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/feature-block@5114 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | exp2.c | 6 | ||||
-rw-r--r-- | exp3.c | 12 | ||||
-rw-r--r-- | exp_2.c | 9 | ||||
-rw-r--r-- | expm1.c | 9 | ||||
-rw-r--r-- | fma.c | 77 | ||||
-rw-r--r-- | fms.c | 77 | ||||
-rw-r--r-- | gamma.c | 10 | ||||
-rw-r--r-- | mpfr-impl.h | 7 | ||||
-rw-r--r-- | pow.c | 6 | ||||
-rw-r--r-- | pow_ui.c | 41 | ||||
-rw-r--r-- | pow_z.c | 48 | ||||
-rw-r--r-- | rint.c | 18 | ||||
-rw-r--r-- | sinh.c | 7 | ||||
-rw-r--r-- | sinh_cosh.c | 7 |
14 files changed, 179 insertions, 155 deletions
@@ -138,8 +138,10 @@ mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) mpfr_clear (xfrac); mpfr_clear_flags (); mpfr_mul_2si (y, y, xint, GMP_RNDN); /* exact or overflow */ - /* Note: We can have an overflow only when t was rounded up to 2. */ - MPFR_ASSERTD (!mpfr_overflow_p () || inexact > 0); + /* Note: We can have an overflow only when t was rounded up to 2. + We do not check the overflow flag as it could have already been + set before the call to mpfr_exp2. */ + MPFR_ASSERTD (MPFR_IS_PURE_FP (y) || inexact > 0); MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (y, inexact, rnd_mode); @@ -198,6 +198,8 @@ mpfr_exp_3 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) MPFR_ZIV_INIT (ziv_loop, realprec); for (;;) { + MPFR_BLOCK_DECL (flags); + k = MPFR_INT_CEIL_LOG2 (Prec) - MPFR_LOG2_BITS_PER_MP_LIMB; /* now we have to extract */ @@ -237,11 +239,11 @@ mpfr_exp_3 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) (*__gmp_free_func) (P, 3*(k+2)*sizeof(mpz_t)); (*__gmp_free_func) (mult, 2*(k+2)*sizeof(mp_prec_t)); - mpfr_clear_flags (); - for (loop = 0; loop < shift_x; loop++) - mpfr_mul (tmp, tmp, tmp, GMP_RNDD); + MPFR_BLOCK (flags, + for (loop = 0; loop < shift_x; loop++) + mpfr_mul (tmp, tmp, tmp, GMP_RNDD)); - if (MPFR_UNLIKELY (mpfr_overflow_p ())) + if (MPFR_OVERFLOW (flags)) { /* We hack to set a FP number outside the valid range so that mpfr_check_range properly generates an overflow */ @@ -250,7 +252,7 @@ mpfr_exp_3 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) inexact = 1; break; } - else if (MPFR_UNLIKELY (mpfr_underflow_p ())) + else if (MPFR_UNDERFLOW (flags)) { /* We hack to set a FP number outside the valid range so that mpfr_check_range properly generates an underflow. @@ -131,6 +131,8 @@ mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) MPFR_ZIV_INIT (loop, q); for (;;) { + MPFR_BLOCK_DECL (flags); + MPFR_LOG_MSG (("n=%d K=%d l=%d q=%d\n",n,K,l,q) ); /* if n<0, we have to get an upper bound of log(2) @@ -181,10 +183,9 @@ mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) MPFR_SET_EXP(s, MPFR_GET_EXP (s) + exps); MPFR_TMP_FREE(marker); /* don't need ss anymore */ - mpfr_clear_underflow (); - mpfr_mul_2si (s, s, n, GMP_RNDU); + MPFR_BLOCK (flags, mpfr_mul_2si (s, s, n, GMP_RNDU)); /* Check if an overflow occurs */ - if (MPFR_UNLIKELY (MPFR_IS_INF (s))) + if (MPFR_OVERFLOW (flags)) { /* We hack to set a FP number outside the valid range so that mpfr_check_range properly generates an overflow */ @@ -194,7 +195,7 @@ mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode) break; } /* Check if an underflow occurs */ - else if (MPFR_UNLIKELY (mpfr_underflow_p ())) + else if (MPFR_UNDERFLOW (flags)) { /* We hack to set a FP number outside the valid range so that mpfr_check_range properly generates an underflow. @@ -124,16 +124,17 @@ mpfr_expm1 (mpfr_ptr y, mpfr_srcptr x , mp_rnd_t rnd_mode) MPFR_ZIV_INIT (loop, Nt); for (;;) { - mpfr_clear_flags (); + MPFR_BLOCK_DECL (flags); + /* exp(x) may overflow and underflow */ - mpfr_exp (t, x, GMP_RNDN); /* exp(x)*/ - if (MPFR_UNLIKELY (mpfr_overflow_p ())) + MPFR_BLOCK (flags, mpfr_exp (t, x, GMP_RNDN)); + if (MPFR_OVERFLOW (flags)) { inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN_POS); MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW); break; } - else if (MPFR_UNLIKELY (mpfr_underflow_p ())) + else if (MPFR_UNDERFLOW (flags)) { inexact = mpfr_set_si (y, -1, rnd_mode); MPFR_ASSERTD (inexact == 0); @@ -145,6 +145,7 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, { mpfr_t zo4; mpfr_srcptr zz; + MPFR_BLOCK_DECL (flags); if (MPFR_GET_EXP (u) > MPFR_GET_EXP (z) && MPFR_GET_EXP (u) - MPFR_GET_EXP (z) > MPFR_PREC (u)) @@ -163,14 +164,13 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, zz = zo4; } - mpfr_clear_flags (); /* Let's recall that u = x*y/4 and zz = z/4 (or z if the following addition would give the same result). */ - inexact = mpfr_add (s, u, zz, rnd_mode); + MPFR_BLOCK (flags, inexact = mpfr_add (s, u, zz, rnd_mode)); /* u and zz have different signs, so that an overflow is not possible. But an underflow is theoretically possible! */ - if (mpfr_underflow_p ()) + if (MPFR_UNDERFLOW (flags)) { MPFR_ASSERTN (zz != z); MPFR_ASSERTN (0); /* TODO... */ @@ -183,7 +183,7 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, if (zz != z) mpfr_clear (zo4); mpfr_clear (u); - MPFR_ASSERTN (! mpfr_overflow_p ()); + MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); inex2 = mpfr_mul_2ui (s, s, 2, rnd_mode); if (inex2) /* overflow */ { @@ -212,6 +212,7 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, { mp_exp_unsigned_t uscale; mpfr_t scaled_v; + MPFR_BLOCK_DECL (flags); uscale = (mp_exp_unsigned_t) pzs - diffexp + 1; MPFR_ASSERTN (uscale > 0); @@ -222,22 +223,22 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, MPFR_ASSERTN (inexact == 0); /* TODO: overflow case */ new_z = scaled_z; /* Now we need to recompute u = xy * 2^scale. */ - mpfr_clear_flags (); - if (MPFR_GET_EXP (x) < MPFR_GET_EXP (y)) - { - mpfr_init2 (scaled_v, MPFR_PREC (x)); - mpfr_mul_2ui (scaled_v, x, scale, GMP_RNDN); - mpfr_mul (u, scaled_v, y, GMP_RNDN); - } - else - { - mpfr_init2 (scaled_v, MPFR_PREC (y)); - mpfr_mul_2ui (scaled_v, y, scale, GMP_RNDN); - mpfr_mul (u, x, scaled_v, GMP_RNDN); - } + MPFR_BLOCK (flags, + if (MPFR_GET_EXP (x) < MPFR_GET_EXP (y)) + { + mpfr_init2 (scaled_v, MPFR_PREC (x)); + mpfr_mul_2ui (scaled_v, x, scale, GMP_RNDN); + mpfr_mul (u, scaled_v, y, GMP_RNDN); + } + else + { + mpfr_init2 (scaled_v, MPFR_PREC (y)); + mpfr_mul_2ui (scaled_v, y, scale, GMP_RNDN); + mpfr_mul (u, x, scaled_v, GMP_RNDN); + }); mpfr_clear (scaled_v); - MPFR_ASSERTN (! mpfr_overflow_p ()); - xy_underflows = mpfr_underflow_p (); + MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); + xy_underflows = MPFR_UNDERFLOW (flags); } else { @@ -254,25 +255,31 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, MPFR_SIGN (y))); } - mpfr_clear_flags (); - inexact = mpfr_add (s, u, new_z, rnd_mode); - mpfr_clear (u); + { + MPFR_BLOCK_DECL (flags); - if (scale != 0) - { - int inex2; + MPFR_BLOCK (flags, inexact = mpfr_add (s, u, new_z, rnd_mode)); + mpfr_clear (u); - mpfr_clear (scaled_z); - /* Here an overflow is theoretically possible, in which case - the result may be wrong, hence the assert. An underflow - is not possible, but let's check that anyway. */ - MPFR_ASSERTN (! mpfr_overflow_p ()); /* TODO... */ - MPFR_ASSERTN (! mpfr_underflow_p ()); /* not possible */ - inex2 = mpfr_div_2ui (s, s, scale, GMP_RNDN); - if (inex2) /* underflow */ - inexact = inex2; - } + if (scale != 0) + { + int inex2; + + mpfr_clear (scaled_z); + /* Here an overflow is theoretically possible, in which case + the result may be wrong, hence the assert. An underflow + is not possible, but let's check that anyway. */ + MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); /* TODO... */ + MPFR_ASSERTN (! MPFR_UNDERFLOW (flags)); /* not possible */ + inex2 = mpfr_div_2ui (s, s, scale, GMP_RNDN); + if (inex2) /* underflow */ + inexact = inex2; + } + } + /* FIXME/TODO: I'm not sure that the following is correct. + Check for possible spurious exceptions due to intermediate + computations. */ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); goto end; } @@ -147,6 +147,7 @@ mpfr_fms (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, { mpfr_t zo4; mpfr_srcptr zz; + MPFR_BLOCK_DECL (flags); if (MPFR_GET_EXP (u) > MPFR_GET_EXP (z) && MPFR_GET_EXP (u) - MPFR_GET_EXP (z) > MPFR_PREC (u)) @@ -165,14 +166,13 @@ mpfr_fms (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, zz = zo4; } - mpfr_clear_flags (); /* Let's recall that u = x*y/4 and zz = z/4 (or z if the following subtraction would give the same result). */ - inexact = mpfr_sub (s, u, zz, rnd_mode); + MPFR_BLOCK (flags, inexact = mpfr_sub (s, u, zz, rnd_mode)); /* u and zz have the same sign, so that an overflow is not possible. But an underflow is theoretically possible! */ - if (mpfr_underflow_p ()) + if (MPFR_UNDERFLOW (flags)) { MPFR_ASSERTN (zz != z); MPFR_ASSERTN (0); /* TODO... */ @@ -185,7 +185,7 @@ mpfr_fms (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, if (zz != z) mpfr_clear (zo4); mpfr_clear (u); - MPFR_ASSERTN (! mpfr_overflow_p ()); + MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); inex2 = mpfr_mul_2ui (s, s, 2, rnd_mode); if (inex2) /* overflow */ { @@ -214,6 +214,7 @@ mpfr_fms (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, { mp_exp_unsigned_t uscale; mpfr_t scaled_v; + MPFR_BLOCK_DECL (flags); uscale = (mp_exp_unsigned_t) pzs - diffexp + 1; MPFR_ASSERTN (uscale > 0); @@ -224,22 +225,22 @@ mpfr_fms (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, MPFR_ASSERTN (inexact == 0); /* TODO: overflow case */ new_z = scaled_z; /* Now we need to recompute u = xy * 2^scale. */ - mpfr_clear_flags (); - if (MPFR_GET_EXP (x) < MPFR_GET_EXP (y)) - { - mpfr_init2 (scaled_v, MPFR_PREC (x)); - mpfr_mul_2ui (scaled_v, x, scale, GMP_RNDN); - mpfr_mul (u, scaled_v, y, GMP_RNDN); - } - else - { - mpfr_init2 (scaled_v, MPFR_PREC (y)); - mpfr_mul_2ui (scaled_v, y, scale, GMP_RNDN); - mpfr_mul (u, x, scaled_v, GMP_RNDN); - } + MPFR_BLOCK (flags, + if (MPFR_GET_EXP (x) < MPFR_GET_EXP (y)) + { + mpfr_init2 (scaled_v, MPFR_PREC (x)); + mpfr_mul_2ui (scaled_v, x, scale, GMP_RNDN); + mpfr_mul (u, scaled_v, y, GMP_RNDN); + } + else + { + mpfr_init2 (scaled_v, MPFR_PREC (y)); + mpfr_mul_2ui (scaled_v, y, scale, GMP_RNDN); + mpfr_mul (u, x, scaled_v, GMP_RNDN); + }); mpfr_clear (scaled_v); - MPFR_ASSERTN (! mpfr_overflow_p ()); - xy_underflows = mpfr_underflow_p (); + MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); + xy_underflows = MPFR_UNDERFLOW (flags); } else { @@ -256,25 +257,31 @@ mpfr_fms (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z, MPFR_SIGN (y))); } - mpfr_clear_flags (); - inexact = mpfr_sub (s, u, new_z, rnd_mode); - mpfr_clear (u); + { + MPFR_BLOCK_DECL (flags); - if (scale != 0) - { - int inex2; + MPFR_BLOCK (flags, inexact = mpfr_sub (s, u, new_z, rnd_mode)); + mpfr_clear (u); - mpfr_clear (scaled_z); - /* Here an overflow is theoretically possible, in which case - the result may be wrong, hence the assert. An underflow - is not possible, but let's check that anyway. */ - MPFR_ASSERTN (! mpfr_overflow_p ()); /* TODO... */ - MPFR_ASSERTN (! mpfr_underflow_p ()); /* not possible */ - inex2 = mpfr_div_2ui (s, s, scale, GMP_RNDN); - if (inex2) /* underflow */ - inexact = inex2; - } + if (scale != 0) + { + int inex2; + + mpfr_clear (scaled_z); + /* Here an overflow is theoretically possible, in which case + the result may be wrong, hence the assert. An underflow + is not possible, but let's check that anyway. */ + MPFR_ASSERTN (! MPFR_OVERFLOW (flags)); /* TODO... */ + MPFR_ASSERTN (! MPFR_UNDERFLOW (flags)); /* not possible */ + inex2 = mpfr_div_2ui (s, s, scale, GMP_RNDN); + if (inex2) /* underflow */ + inexact = inex2; + } + } + /* FIXME/TODO: I'm not sure that the following is correct. + Check for possible spurious exceptions due to intermediate + computations. */ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); goto end; } @@ -230,12 +230,11 @@ mpfr_gamma (mpfr_ptr gamma, mpfr_srcptr x, mp_rnd_t rnd_mode) >= 2 * (x/e)^x / x for x >= 1 */ if (compared > 0) { - int overflow; mpfr_t yp; + MPFR_BLOCK_DECL (flags); /* 1/e rounded down to 53 bits */ #define EXPM1_STR "0.010111100010110101011000110110001011001110111100111" - mpfr_clear_overflow (); mpfr_init2 (xp, 53); mpfr_init2 (yp, 53); mpfr_set_str_binary (xp, EXPM1_STR); @@ -245,12 +244,11 @@ mpfr_gamma (mpfr_ptr gamma, mpfr_srcptr x, mp_rnd_t rnd_mode) mpfr_set_str_binary (yp, EXPM1_STR); mpfr_mul (xp, xp, yp, GMP_RNDZ); /* x^(x-2) / e^(x-1) */ mpfr_mul (xp, xp, yp, GMP_RNDZ); /* x^(x-2) / e^x */ - mpfr_mul (xp, xp, x, GMP_RNDZ); /* x^(x-1) / e^x */ - mpfr_mul_2ui (xp, xp, 1, GMP_RNDZ); - overflow = mpfr_overflow_p (); + mpfr_mul (xp, xp, x, GMP_RNDZ); /* lower bound on x^(x-1) / e^x */ + MPFR_BLOCK (flags, mpfr_mul_2ui (xp, xp, 1, GMP_RNDZ)); mpfr_clear (xp); mpfr_clear (yp); - return (overflow) ? mpfr_overflow (gamma, rnd_mode, 1) + return MPFR_OVERFLOW (flags) ? mpfr_overflow (gamma, rnd_mode, 1) : mpfr_gamma_aux (gamma, x, rnd_mode); } diff --git a/mpfr-impl.h b/mpfr-impl.h index c6e5e9a9f..5afca5881 100644 --- a/mpfr-impl.h +++ b/mpfr-impl.h @@ -279,7 +279,9 @@ __MPFR_DECLSPEC extern const mpfr_t __gmpfr_four; avoid these pitfalls, it is recommended to use the following macros. Other use of the exception-flag predicate functions/macros will be detected by mpfrlint. - Note: _op can be either a statement or an expression. */ + Note: _op can be either a statement or an expression. + MPFR_BLOCK_EXCEP should be used only inside a block; it is useful to + detect some exception in order to exit the block as soon as possible. */ #define MPFR_BLOCK_DECL(_flags) unsigned int _flags #define MPFR_BLOCK(_flags,_op) \ do \ @@ -290,6 +292,9 @@ __MPFR_DECLSPEC extern const mpfr_t __gmpfr_four; } \ while (0) #define MPFR_BLOCK_TEST(_flags,_f) MPFR_UNLIKELY ((_flags) & (_f)) +#define MPFR_BLOCK_EXCEP (__gmpfr_flags & (MPFR_FLAGS_UNDERFLOW | \ + MPFR_FLAGS_OVERFLOW | \ + MPFR_FLAGS_NAN)) /* Let's use a MPFR_ prefix, because e.g. OVERFLOW is defined by glibc's math.h, though this is not a reserved identifier! */ #define MPFR_UNDERFLOW(_flags) MPFR_BLOCK_TEST (_flags, MPFR_FLAGS_UNDERFLOW) @@ -478,6 +478,7 @@ mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (t))) { mp_prec_t Ntmin; + MPFR_BLOCK_DECL (flags); MPFR_ASSERTN (!k_non_zero); MPFR_ASSERTN (!MPFR_IS_NAN (t)); @@ -495,11 +496,10 @@ mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) /* Overflow. */ /* Note: we can probably use a low precision for this test. */ - mpfr_clear_flags (); mpfr_log (t, absx, GMP_RNDD); /* ln|x| */ mpfr_mul (t, y, t, GMP_RNDD); /* y*ln|x| */ - mpfr_exp (t, t, GMP_RNDD); /* exp(y*ln|x|)*/ - if (mpfr_overflow_p ()) + MPFR_BLOCK (flags, mpfr_exp (t, t, GMP_RNDD)); /* exp(y*ln|x|)*/ + if (MPFR_OVERFLOW (flags)) { /* We have computed a lower bound on |x|^y, and it overflowed. Therefore we have a real overflow on |x|^y. */ @@ -35,6 +35,7 @@ mpfr_pow_ui (mpfr_ptr x, mpfr_srcptr y, unsigned long int n, mp_rnd_t rnd) mp_rnd_t rnd1; MPFR_SAVE_EXPO_DECL (expo); MPFR_ZIV_DECL (loop); + MPFR_BLOCK_DECL (flags); if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (y))) { @@ -99,24 +100,24 @@ mpfr_pow_ui (mpfr_ptr x, mpfr_srcptr y, unsigned long int n, mp_rnd_t rnd) for (;;) { int i; + for (m = n, i = 0; m; i++, m >>= 1) ; /* now 2^(i-1) <= n < 2^i */ MPFR_ASSERTD (prec > (mpfr_prec_t) i); err = prec - 1 - (mpfr_prec_t) i; MPFR_ASSERTD (i >= 1); - mpfr_clear_overflow (); - mpfr_clear_underflow (); /* First step: compute square from y */ - inexact = mpfr_mul (res, y, y, GMP_RNDU); - if (n & (1UL << (i-2))) - inexact |= mpfr_mul (res, res, y, rnd1); - for (i -= 3; i >= 0 && !mpfr_overflow_p () && !mpfr_underflow_p (); i--) - { - inexact |= mpfr_mul (res, res, res, GMP_RNDU); - if (n & (1UL << i)) - inexact |= mpfr_mul (res, res, y, rnd1); - } + MPFR_BLOCK (flags, + inexact = mpfr_mul (res, y, y, GMP_RNDU); + if (n & (1UL << (i-2))) + inexact |= mpfr_mul (res, res, y, rnd1); + for (i -= 3; i >= 0 && !MPFR_BLOCK_EXCEP; i--) + { + inexact |= mpfr_mul (res, res, res, GMP_RNDU); + if (n & (1UL << i)) + inexact |= mpfr_mul (res, res, y, rnd1); + }); /* let r(n) be the number of roundings: we have r(2)=1, r(3)=2, and r(2n)=2r(n)+1, r(2n+1)=2r(n)+2, thus r(n)=n-1. Using Higham's method, to each rounding corresponds a factor @@ -126,7 +127,7 @@ mpfr_pow_ui (mpfr_ptr x, mpfr_srcptr y, unsigned long int n, mp_rnd_t rnd) error of 2^(1+i)*ulp(res). */ if (MPFR_LIKELY (inexact == 0 - || mpfr_overflow_p () || mpfr_underflow_p () + || MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags) || MPFR_CAN_ROUND (res, err, MPFR_PREC (x), rnd))) break; /* Actualisation of the precision */ @@ -135,26 +136,26 @@ mpfr_pow_ui (mpfr_ptr x, mpfr_srcptr y, unsigned long int n, mp_rnd_t rnd) } MPFR_ZIV_FREE (loop); - inexact = mpfr_set (x, res, rnd); - mpfr_clear (res); - /* Check Overflow */ - if (MPFR_UNLIKELY (mpfr_overflow_p ())) + if (MPFR_OVERFLOW (flags)) { + mpfr_clear (res); MPFR_SAVE_EXPO_FREE (expo); return mpfr_overflow (x, rnd, (n % 2) ? MPFR_SIGN (y) : MPFR_SIGN_POS); } /* Check Underflow */ - else if (MPFR_UNLIKELY (mpfr_underflow_p ())) + else if (MPFR_UNDERFLOW (flags)) { - if (rnd == GMP_RNDN) - rnd = GMP_RNDZ; + mpfr_clear (res); MPFR_SAVE_EXPO_FREE (expo); - return mpfr_underflow (x, rnd, + return mpfr_underflow (x, rnd == GMP_RNDN ? GMP_RNDZ : rnd, (n % 2) ? MPFR_SIGN(y) : MPFR_SIGN_POS); } + inexact = mpfr_set (x, res, rnd); + mpfr_clear (res); + MPFR_SAVE_EXPO_FREE (expo); return mpfr_check_range (x, inexact, rnd); } @@ -33,6 +33,7 @@ mpfr_pow_pos_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t rnd) mpz_t absz; mp_size_t size_z; MPFR_ZIV_DECL (loop); + MPFR_BLOCK_DECL (flags); MPFR_ASSERTD (mpz_sgn (z) != 0); @@ -56,23 +57,22 @@ mpfr_pow_pos_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t rnd) MPFR_ASSERTD (prec > (mpfr_prec_t) i); err = prec - 1 - (mpfr_prec_t) i; MPFR_ASSERTD (i >= 2); - mpfr_clear_overflow (); - mpfr_clear_underflow (); /* First step: compute square from y */ - inexact = mpfr_mul (res, x, x, GMP_RNDU); - if (mpz_tstbit (absz, i-2)) - inexact |= mpfr_mul (res, res, x, rnd1); - for (i -= 3; i >= 0 && !mpfr_underflow_p() && !mpfr_overflow_p (); i--) - { - inexact |= mpfr_mul (res, res, res, GMP_RNDU); - if (mpz_tstbit (absz, i)) - inexact |= mpfr_mul (res, res, x, rnd1); - } + MPFR_BLOCK (flags, + inexact = mpfr_mul (res, x, x, GMP_RNDU); + if (mpz_tstbit (absz, i-2)) + inexact |= mpfr_mul (res, res, x, rnd1); + for (i -= 3; i >= 0 && !MPFR_BLOCK_EXCEP; i--) + { + inexact |= mpfr_mul (res, res, res, GMP_RNDU); + if (mpz_tstbit (absz, i)) + inexact |= mpfr_mul (res, res, x, rnd1); + }); /* printf ("pow_z "); mpfr_dump_mant (MPFR_MANT (res), prec, MPFR_PREC (x), err); */ if (MPFR_LIKELY (inexact == 0 - || mpfr_overflow_p () || mpfr_underflow_p () + || MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags) || MPFR_CAN_ROUND (res, err, MPFR_PREC (y), rnd))) break; /* Actualisation of the precision */ @@ -81,21 +81,19 @@ mpfr_pow_pos_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t rnd) } MPFR_ZIV_FREE (loop); - inexact = mpfr_set (y, res, rnd); - mpfr_clear (res); - /* Check Overflow */ - if (MPFR_UNLIKELY (mpfr_overflow_p ())) - return mpfr_overflow (y, rnd, - mpz_odd_p (absz) ? MPFR_SIGN (x) : MPFR_SIGN_POS); + if (MPFR_OVERFLOW (flags)) + inexact = mpfr_overflow (y, rnd, mpz_odd_p (absz) ? + MPFR_SIGN (x) : MPFR_SIGN_POS); /* Check Underflow */ - else if (MPFR_UNLIKELY (mpfr_underflow_p ())) - { - if (rnd == GMP_RNDN) - rnd = GMP_RNDZ; - return mpfr_underflow (y, rnd, - mpz_odd_p (absz) ? MPFR_SIGN (x) : MPFR_SIGN_POS); - } + else if (MPFR_UNDERFLOW (flags)) + inexact = mpfr_underflow (y, rnd == GMP_RNDN ? GMP_RNDZ : rnd, + mpz_odd_p (absz) ? MPFR_SIGN (x) : + MPFR_SIGN_POS); + else + inexact = mpfr_set (y, res, rnd); + + mpfr_clear (res); return inexact; } @@ -341,13 +341,13 @@ mpfr_rint_round (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) mpfr_t tmp; int inex; MPFR_SAVE_EXPO_DECL (expo); + MPFR_BLOCK_DECL (flags); MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (tmp, MPFR_PREC (u)); /* round(u) is representable in tmp unless an overflow occurs */ - mpfr_clear_overflow (); - mpfr_round (tmp, u); - inex = (mpfr_overflow_p () + MPFR_BLOCK (flags, mpfr_round (tmp, u)); + inex = (MPFR_OVERFLOW (flags) ? mpfr_overflow (r, rnd_mode, MPFR_SIGN (u)) : mpfr_set (r, tmp, rnd_mode)); mpfr_clear (tmp); @@ -392,13 +392,13 @@ mpfr_rint_ceil (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) mpfr_t tmp; int inex; MPFR_SAVE_EXPO_DECL (expo); + MPFR_BLOCK_DECL (flags); MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (tmp, MPFR_PREC (u)); /* ceil(u) is representable in tmp unless an overflow occurs */ - mpfr_clear_overflow (); - mpfr_ceil (tmp, u); - inex = (mpfr_overflow_p () + MPFR_BLOCK (flags, mpfr_ceil (tmp, u)); + inex = (MPFR_OVERFLOW (flags) ? mpfr_overflow (r, rnd_mode, MPFR_SIGN_POS) : mpfr_set (r, tmp, rnd_mode)); mpfr_clear (tmp); @@ -419,13 +419,13 @@ mpfr_rint_floor (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) mpfr_t tmp; int inex; MPFR_SAVE_EXPO_DECL (expo); + MPFR_BLOCK_DECL (flags); MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (tmp, MPFR_PREC (u)); /* floor(u) is representable in tmp unless an overflow occurs */ - mpfr_clear_overflow (); - mpfr_floor (tmp, u); - inex = (mpfr_overflow_p () + MPFR_BLOCK (flags, mpfr_floor (tmp, u)); + inex = (MPFR_OVERFLOW (flags) ? mpfr_overflow (r, rnd_mode, MPFR_SIGN_NEG) : mpfr_set (r, tmp, rnd_mode)); mpfr_clear (tmp); @@ -89,12 +89,13 @@ mpfr_sinh (mpfr_ptr y, mpfr_srcptr xt, mp_rnd_t rnd_mode) MPFR_ZIV_INIT (loop, Nt); for (;;) { + MPFR_BLOCK_DECL (flags); + /* compute sinh */ - mpfr_clear_flags (); - mpfr_exp (t, x, GMP_RNDD); /* exp(x) */ + MPFR_BLOCK (flags, mpfr_exp (t, x, GMP_RNDD)); /* exp(x) can overflow! */ /* BUG/TODO/FIXME: exp can overflow but sinh may be representable! */ - if (MPFR_UNLIKELY (mpfr_overflow_p ())) + if (MPFR_OVERFLOW (flags)) { inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN (xt)); MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW); diff --git a/sinh_cosh.c b/sinh_cosh.c index 633cc4f00..4886efc05 100644 --- a/sinh_cosh.c +++ b/sinh_cosh.c @@ -91,13 +91,14 @@ mpfr_sinh_cosh (mpfr_ptr sh, mpfr_ptr ch, mpfr_srcptr xt, mp_rnd_t rnd_mode) MPFR_ZIV_INIT (loop, N); for (;;) { + MPFR_BLOCK_DECL (flags); + /* compute sinh_cosh */ - mpfr_clear_flags (); - mpfr_exp (s, x, GMP_RNDD); /* exp(x) */ + MPFR_BLOCK (flags, mpfr_exp (s, x, GMP_RNDD)); /* exp(x) can overflow! */ /* BUG/TODO/FIXME: exp can overflow but sinh or cosh may be representable! */ - if (MPFR_UNLIKELY (mpfr_overflow_p ())) + if (MPFR_OVERFLOW (flags)) { inexact_ch = mpfr_overflow (ch, rnd_mode, MPFR_SIGN_POS); inexact_sh = mpfr_overflow (sh, rnd_mode, MPFR_SIGN (xt)); |