diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-09-02 07:13:38 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-09-02 07:13:38 +0000 |
commit | b4df47ef18e9e516e90a97d2e6626e4dc493d813 (patch) | |
tree | a39018105250ca3eda936cdd57b32fbfe1fef45e /tests/tcan_round.c | |
parent | 61816b69da7f34b565572ec787a6302205d3256d (diff) | |
download | mpfr-b4df47ef18e9e516e90a97d2e6626e4dc493d813.tar.gz |
Merged the following changesets from the trunk:
r10664-10686,10689-10690,10692,10695-10696,10699-10775
i.e. all the latest changes except for src/{add1sp.c,sub1sp.c}
to avoid build failures (to be solved later).
Currently only tcan_round fails, due to MPFR_RNDF.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/faithful@10776 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'tests/tcan_round.c')
-rw-r--r-- | tests/tcan_round.c | 123 |
1 files changed, 117 insertions, 6 deletions
diff --git a/tests/tcan_round.c b/tests/tcan_round.c index 18544f6b0..c4193e222 100644 --- a/tests/tcan_round.c +++ b/tests/tcan_round.c @@ -22,6 +22,44 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., #include "mpfr-test.h" +/* Simple cases where err - prec is large enough. + One can get failures as a consequence of r9883. */ +static void +test_simple (void) +{ + int t[4] = { 2, 3, -2, -3 }; /* test powers of 2 and non-powers of 2 */ + int i; + int r1, r2; + + for (i = 0; i < 4; i++) + RND_LOOP (r1) + RND_LOOP (r2) + { + mpfr_t b; + int p, err, prec, inex, c; + + p = 12 + (randlimb() % (2 * GMP_NUMB_BITS)); + err = p - 3; + prec = 4; + mpfr_init2 (b, p); + inex = mpfr_set_si (b, t[i], MPFR_RNDN); + MPFR_ASSERTN (inex == 0); + c = mpfr_can_round (b, err, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, prec); + /* If r1 == r2, we can round. + TODO: complete this test for r1 != r2. */ + if (r1 == r2 && !c) + { + printf ("Error in test_simple for i=%d," + " err=%d r1=%s, r2=%s, p=%d\n", i, err, + mpfr_print_rnd_mode ((mpfr_rnd_t) r1), + mpfr_print_rnd_mode ((mpfr_rnd_t) r2), p); + printf ("b="); mpfr_dump (b); + exit (1); + } + mpfr_clear (b); + } +} + #define MAX_LIMB_SIZE 100 static void @@ -88,12 +126,7 @@ test_pow2 (mpfr_exp_t i, mpfr_prec_t px, mpfr_rnd_t r1, mpfr_rnd_t r2, MPFR_IS_LIKE_RNDU (r1, MPFR_SIGN_POS) ? (MPFR_IS_LIKE_RNDD (r2, MPFR_SIGN_POS) ? 0 : prec < i) : (r2 != MPFR_RNDN ? 0 : prec < i); - /* We only require mpfr_can_round to return 1 when we can really - round, it is allowed to return 0 in some rare boundary cases, - for example when x = 2^k and the error is 0.25 ulp. - Note: if this changes in the future, the test could be improved by - removing the "&& expected_b == 0" below. */ - if (b != expected_b && expected_b == 0) + if (b != expected_b) { printf ("Error for x=2^%d, px=%lu, err=%d, r1=%s, r2=%s, prec=%d\n", (int) i, (unsigned long) px, (int) i + 1, @@ -119,6 +152,80 @@ test_pow2 (mpfr_exp_t i, mpfr_prec_t px, mpfr_rnd_t r1, mpfr_rnd_t r2, mpfr_clear (x); } +static void +check_can_round (void) +{ + mpfr_t x, xinf, xsup, yinf, ysup; + int precx, precy, err; + int rnd1, rnd2; + int i, u[3] = { 0, 1, 256 }; + int inex; + int expected, got; + + mpfr_inits2 (4 * GMP_NUMB_BITS, x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0); + + for (precx = 3 * GMP_NUMB_BITS - 3; precx <= 3 * GMP_NUMB_BITS + 3; precx++) + { + mpfr_set_prec (x, precx); + for (precy = precx - 4; precy <= precx + 4; precy++) + { + mpfr_set_prec (yinf, precy); + mpfr_set_prec (ysup, precy); + + for (i = 0; i <= 3; i++) + { + if (i <= 2) + { + /* Test x = 2^(precx - 1) + u */ + mpfr_set_ui_2exp (x, 1, precx - 1, MPFR_RNDN); + mpfr_add_ui (x, x, u[i], MPFR_RNDN); + } + else + { + /* Test x = 2^precx - 1 */ + mpfr_set_ui_2exp (x, 1, precx, MPFR_RNDN); + mpfr_sub_ui (x, x, 1, MPFR_RNDN); + } + MPFR_ASSERTN (mpfr_get_exp (x) == precx); + + for (err = precy; err <= precy + 3; err++) + { + mpfr_set_ui_2exp (xinf, 1, precx - err, MPFR_RNDN); + inex = mpfr_add (xsup, x, xinf, MPFR_RNDN); + MPFR_ASSERTN (inex == 0); + inex = mpfr_sub (xinf, x, xinf, MPFR_RNDN); + MPFR_ASSERTN (inex == 0); + RND_LOOP (rnd1) + RND_LOOP (rnd2) + { + mpfr_set (yinf, MPFR_IS_LIKE_RNDD (rnd1, 1) ? + x : xinf, (mpfr_rnd_t) rnd2); + mpfr_set (ysup, MPFR_IS_LIKE_RNDU (rnd1, 1) ? + x : xsup, (mpfr_rnd_t) rnd2); + expected = !! mpfr_equal_p (yinf, ysup); + got = !! mpfr_can_round (x, err, (mpfr_rnd_t) rnd1, + (mpfr_rnd_t) rnd2, precy); + if (got != expected) + { + printf ("Error in check_can_round on:\n" + "precx=%d, precy=%d, i=%d, err=%d, " + "rnd1=%s, rnd2=%s: got %d\n", + precx, precy, i, err, + mpfr_print_rnd_mode ((mpfr_rnd_t) rnd1), + mpfr_print_rnd_mode ((mpfr_rnd_t) rnd2), + got); + printf ("x="); mpfr_dump (x); + exit (1); + } + } + } + } + } + } + + mpfr_clears (x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0); +} + int main (void) { @@ -129,6 +236,8 @@ main (void) tests_start_mpfr (); + test_simple (); + /* checks that rounds to nearest sets the last bit to zero in case of equal distance */ mpfr_init2 (x, 59); @@ -202,6 +311,8 @@ main (void) mpfr_clear (x); + check_can_round (); + check_round_p (); tests_end_mpfr (); |