diff options
author | thevenyp <thevenyp@280ebfd0-de03-0410-8827-d642c229c3f4> | 2008-02-27 11:13:18 +0000 |
---|---|---|
committer | thevenyp <thevenyp@280ebfd0-de03-0410-8827-d642c229c3f4> | 2008-02-27 11:13:18 +0000 |
commit | 4eef2a6de0affc21d70c074f35d0a2e5d17b60d0 (patch) | |
tree | 086892836c664d0bab04fbcf58783ce7a744d4ba | |
parent | a53b5f84e27622e106289bd7f7369aa87bc4eb10 (diff) | |
download | mpfr-4eef2a6de0affc21d70c074f35d0a2e5d17b60d0.tar.gz |
add_d.c, div_d.c, sub_d.c, d_div.c, d_sub.c: restore flags in case of exception. This fixes the bug revealed by MPFR_SUSPICIOUS_OVERFLOW
tests/tadd_d.c, tests/tsub_d.c, tests/tdiv_d.c, tests/tmul_d.c, tests/td_sub.c, tests/td_div.c, test/tmul_d.c: add checks for exception flags and ternary value
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@5322 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | add_d.c | 4 | ||||
-rw-r--r-- | d_div.c | 4 | ||||
-rw-r--r-- | d_sub.c | 4 | ||||
-rw-r--r-- | div_d.c | 4 | ||||
-rw-r--r-- | sub_d.c | 4 | ||||
-rw-r--r-- | tests/tadd_d.c | 22 | ||||
-rw-r--r-- | tests/td_div.c | 29 | ||||
-rw-r--r-- | tests/td_sub.c | 22 | ||||
-rw-r--r-- | tests/tdiv_d.c | 27 | ||||
-rw-r--r-- | tests/tmul_d.c | 31 | ||||
-rw-r--r-- | tests/tsub_d.c | 22 |
11 files changed, 124 insertions, 49 deletions
@@ -39,8 +39,10 @@ mpfr_add_d (mpfr_ptr a, mpfr_srcptr b, double c, mp_rnd_t rnd_mode) inexact = mpfr_set_d (d, c, rnd_mode); MPFR_ASSERTN (inexact == 0); + mpfr_clear_flags (); inexact = mpfr_add (a, b, d, rnd_mode); - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) + if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a) + || (__gmpfr_flags & MPFR_FLAGS_ALL))) { MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); } @@ -39,8 +39,10 @@ mpfr_d_div (mpfr_ptr a, double b, mpfr_srcptr c, mp_rnd_t rnd_mode) inexact = mpfr_set_d (d, b, rnd_mode); MPFR_ASSERTN (inexact == 0); + mpfr_clear_flags (); inexact = mpfr_div (a, d, c, rnd_mode); - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) + if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a) + || (__gmpfr_flags & MPFR_FLAGS_ALL))) { MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); } @@ -39,8 +39,10 @@ mpfr_d_sub (mpfr_ptr a, double b, mpfr_srcptr c, mp_rnd_t rnd_mode) inexact = mpfr_set_d (d, b, rnd_mode); MPFR_ASSERTN (inexact == 0); + mpfr_clear_flags (); inexact = mpfr_sub (a, d, c, rnd_mode); - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) + if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a) + || (__gmpfr_flags & MPFR_FLAGS_ALL))) { MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); } @@ -39,8 +39,10 @@ mpfr_div_d (mpfr_ptr a, mpfr_srcptr b, double c, mp_rnd_t rnd_mode) inexact = mpfr_set_d (d, c, rnd_mode); MPFR_ASSERTN (inexact == 0); + mpfr_clear_flags (); inexact = mpfr_div (a, b, d, rnd_mode); - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) + if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a) + || (__gmpfr_flags & MPFR_FLAGS_ALL))) { MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); } @@ -39,8 +39,10 @@ mpfr_sub_d (mpfr_ptr a, mpfr_srcptr b, double c, mp_rnd_t rnd_mode) inexact = mpfr_set_d (d, c, rnd_mode); MPFR_ASSERTN (inexact == 0); + mpfr_clear_flags (); inexact = mpfr_sub (a, b, d, rnd_mode); - if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a))) + if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a) + || (__gmpfr_flags & MPFR_FLAGS_ALL))) { MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags); } diff --git a/tests/tadd_d.c b/tests/tadd_d.c index 09b8f0075..88305dcd1 100644 --- a/tests/tadd_d.c +++ b/tests/tadd_d.c @@ -93,26 +93,36 @@ static void check_nans (void) { mpfr_t x, y; + int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* nan + 1.0 is nan */ mpfr_set_nan (x); - mpfr_add_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_add_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); /* +inf + 1.0 == +inf */ mpfr_set_inf (x, 1); - mpfr_add_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_add_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) > 0); + MPFR_ASSERTN (MPFR_IS_POS (y)); /* -inf + 1.0 == -inf */ mpfr_set_inf (x, -1); - mpfr_add_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_add_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) < 0); + MPFR_ASSERTN (MPFR_IS_NEG (y)); mpfr_clear (x); mpfr_clear (y); @@ -124,7 +134,7 @@ check_nans (void) #include "tgeneric.c" int -main (int argc, char *argv[]) +main (void) { tests_start_mpfr (); diff --git a/tests/td_div.c b/tests/td_div.c index d8103d783..9598134b5 100644 --- a/tests/td_div.c +++ b/tests/td_div.c @@ -32,32 +32,45 @@ static void check_nans (void) { mpfr_t x, y; + int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* 1.0 / nan is nan */ mpfr_set_nan (x); - mpfr_d_div (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_div (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); /* 1.0 / +inf == +0 */ mpfr_set_inf (x, 1); - mpfr_d_div (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_div (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_zero_p (y)); - MPFR_ASSERTN (MPFR_SIGN (y) > 0); + MPFR_ASSERTN (MPFR_IS_POS (y)); /* 1.0 / -inf == -0 */ mpfr_set_inf (x, -1); - mpfr_d_div (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_div (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_zero_p (y)); - MPFR_ASSERTN (MPFR_SIGN (y) < 0); + MPFR_ASSERTN (MPFR_IS_NEG (y)); /* 1.0 / 0 == +inf */ mpfr_set_d (x, 0.0, GMP_RNDN); - mpfr_d_div (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_div (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) > 0); + MPFR_ASSERTN (MPFR_IS_POS (y)); mpfr_clear (x); mpfr_clear (y); @@ -69,7 +82,7 @@ check_nans (void) #include "tgeneric.c" int -main (int argc, char *argv[]) +main (void) { mpfr_t x, y, z; double d; diff --git a/tests/td_sub.c b/tests/td_sub.c index a584d294f..5a42df048 100644 --- a/tests/td_sub.c +++ b/tests/td_sub.c @@ -32,26 +32,36 @@ static void check_nans (void) { mpfr_t x, y; + int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* 1.0 - nan is nan */ mpfr_set_nan (x); - mpfr_d_sub (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_sub (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); /* 1.0 - +inf == -inf */ mpfr_set_inf (x, 1); - mpfr_d_sub (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_sub (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) < 0); + MPFR_ASSERTN (MPFR_IS_NEG (y)); /* 1.0 - -inf == +inf */ mpfr_set_inf (x, -1); - mpfr_d_sub (y, 1.0, x, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_d_sub (y, 1.0, x, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) > 0); + MPFR_ASSERTN (MPFR_IS_POS (y)); mpfr_clear (x); mpfr_clear (y); @@ -63,7 +73,7 @@ check_nans (void) #include "tgeneric.c" int -main (int argc, char *argv[]) +main (void) { mpfr_t x, y, z; double d; diff --git a/tests/tdiv_d.c b/tests/tdiv_d.c index 46cc61f58..8c6401749 100644 --- a/tests/tdiv_d.c +++ b/tests/tdiv_d.c @@ -32,30 +32,43 @@ static void check_nans (void) { mpfr_t x, y; + int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* nan / 1.0 is nan */ mpfr_set_nan (x); - mpfr_div_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_div_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); /* +inf / 1.0 == +inf */ mpfr_set_inf (x, 1); - mpfr_div_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_div_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) > 0); + MPFR_ASSERTN (MPFR_IS_POS (y)); /* -inf / 1.0 == -inf */ mpfr_set_inf (x, -1); - mpfr_div_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_div_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) < 0); + MPFR_ASSERTN (MPFR_IS_NEG (y)); /* 0.0 / 0.0 is nan */ mpfr_set_d (x, 0.0, GMP_RNDN); - mpfr_div_d (y, x, 0.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_div_d (y, x, 0.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); mpfr_clear (x); @@ -68,7 +81,7 @@ check_nans (void) #include "tgeneric.c" int -main (int argc, char *argv[]) +main (void) { mpfr_t x, y, z; double d; diff --git a/tests/tmul_d.c b/tests/tmul_d.c index a4a4cdfc5..7af865545 100644 --- a/tests/tmul_d.c +++ b/tests/tmul_d.c @@ -32,6 +32,7 @@ static void check_nans (void) { mpfr_t x, y; + int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); @@ -39,27 +40,35 @@ check_nans (void) /* nan * 1.0 is nan */ mpfr_set_nan (x); mpfr_clear_flags(); - mpfr_mul_d (y, x, 1.0, GMP_RNDN); - MPFR_ASSERTN (mpfr_nan_p (y) && mpfr_nanflag_p()); + inexact = mpfr_mul_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); + MPFR_ASSERTN (mpfr_nan_p (y)); /* +inf * 1.0 == +inf */ mpfr_set_inf (x, 1); mpfr_clear_flags(); - mpfr_mul_d (y, x, 1.0, GMP_RNDN); - MPFR_ASSERTN (mpfr_inf_p (y) && !mpfr_overflow_p()); - MPFR_ASSERTN (mpfr_sgn (y) > 0); + inexact = mpfr_mul_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); + MPFR_ASSERTN (mpfr_inf_p (y)); + MPFR_ASSERTN (MPFR_IS_POS (y)); /* +inf * 0.0 is nan */ mpfr_clear_flags(); - mpfr_mul_d (y, x, 0.0, GMP_RNDN); - MPFR_ASSERTN (mpfr_nan_p (y) || mpfr_nanflag_p()); + inexact = mpfr_mul_d (y, x, 0.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); + MPFR_ASSERTN (mpfr_nan_p (y)); /* -inf * 1.0 == -inf */ mpfr_set_inf (x, -1); mpfr_clear_flags(); - mpfr_mul_d (y, x, 1.0, GMP_RNDN); - MPFR_ASSERTN (mpfr_inf_p (y) && !mpfr_overflow_p()); - MPFR_ASSERTN (mpfr_sgn (y) < 0); + inexact = mpfr_mul_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); + MPFR_ASSERTN (mpfr_inf_p (y)); + MPFR_ASSERTN (MPFR_IS_NEG (y)); mpfr_clear (x); mpfr_clear (y); @@ -71,7 +80,7 @@ check_nans (void) #include "tgeneric.c" int -main (int argc, char *argv[]) +main (void) { mpfr_t x, y, z; double d; diff --git a/tests/tsub_d.c b/tests/tsub_d.c index 036ae9c43..61b52dabb 100644 --- a/tests/tsub_d.c +++ b/tests/tsub_d.c @@ -32,26 +32,36 @@ static void check_nans (void) { mpfr_t x, y; + int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* nan - 1.0 is nan */ mpfr_set_nan (x); - mpfr_sub_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_sub_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN ((__gmpfr_flags ^ MPFR_FLAGS_NAN) == 0); MPFR_ASSERTN (mpfr_nan_p (y)); /* +inf - 1.0 == +inf */ mpfr_set_inf (x, 1); - mpfr_sub_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_sub_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) > 0); + MPFR_ASSERTN (MPFR_IS_POS (y)); /* -inf - 1.0 == -inf */ mpfr_set_inf (x, -1); - mpfr_sub_d (y, x, 1.0, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_sub_d (y, x, 1.0, GMP_RNDN); + MPFR_ASSERTN (inexact == 0); + MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); - MPFR_ASSERTN (mpfr_sgn (y) < 0); + MPFR_ASSERTN (MPFR_IS_NEG (y)); mpfr_clear (x); mpfr_clear (y); @@ -63,7 +73,7 @@ check_nans (void) #include "tgeneric.c" int -main (int argc, char *argv[]) +main (void) { mpfr_t x, y, z; double d; |