summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2007-12-18 15:17:09 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2007-12-18 15:17:09 +0000
commitfc967316e0e33f6f4390ef835ff311213221065e (patch)
treeebbb37da7e6997455562922a598704d7f34fa69a
parentd9ddf052467eaaabf520b61b54b68f9b477ced13 (diff)
downloadmpfr-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.c6
-rw-r--r--exp3.c12
-rw-r--r--exp_2.c9
-rw-r--r--expm1.c9
-rw-r--r--fma.c77
-rw-r--r--fms.c77
-rw-r--r--gamma.c10
-rw-r--r--mpfr-impl.h7
-rw-r--r--pow.c6
-rw-r--r--pow_ui.c41
-rw-r--r--pow_z.c48
-rw-r--r--rint.c18
-rw-r--r--sinh.c7
-rw-r--r--sinh_cosh.c7
14 files changed, 179 insertions, 155 deletions
diff --git a/exp2.c b/exp2.c
index f0dc681f6..e5f67a0c8 100644
--- a/exp2.c
+++ b/exp2.c
@@ -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);
diff --git a/exp3.c b/exp3.c
index 3a8c3fcf5..db1cbfd52 100644
--- a/exp3.c
+++ b/exp3.c
@@ -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.
diff --git a/exp_2.c b/exp_2.c
index 03fde2a16..965deb754 100644
--- a/exp_2.c
+++ b/exp_2.c
@@ -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.
diff --git a/expm1.c b/expm1.c
index b04908ddf..75e15d89c 100644
--- a/expm1.c
+++ b/expm1.c
@@ -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);
diff --git a/fma.c b/fma.c
index 51b74f1c1..73cd1c7b2 100644
--- a/fma.c
+++ b/fma.c
@@ -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;
}
diff --git a/fms.c b/fms.c
index f13f0dca3..3cefd6a84 100644
--- a/fms.c
+++ b/fms.c
@@ -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;
}
diff --git a/gamma.c b/gamma.c
index 6b9b43006..268163c07 100644
--- a/gamma.c
+++ b/gamma.c
@@ -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)
diff --git a/pow.c b/pow.c
index 06544f236..48fed51b4 100644
--- a/pow.c
+++ b/pow.c
@@ -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. */
diff --git a/pow_ui.c b/pow_ui.c
index 9738d227f..b29569f93 100644
--- a/pow_ui.c
+++ b/pow_ui.c
@@ -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);
}
diff --git a/pow_z.c b/pow_z.c
index db6b03b44..198ee8a5e 100644
--- a/pow_z.c
+++ b/pow_z.c
@@ -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;
}
diff --git a/rint.c b/rint.c
index e790e30e8..bf91b74fe 100644
--- a/rint.c
+++ b/rint.c
@@ -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);
diff --git a/sinh.c b/sinh.c
index 0add26042..f1dc59291 100644
--- a/sinh.c
+++ b/sinh.c
@@ -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));