diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-01-31 16:21:15 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-01-31 16:21:15 +0000 |
commit | e901193d09fcf0c1635b41069cc8fe96839f899c (patch) | |
tree | edd1763746b7686c7782c13e131ea032641f4985 | |
parent | 9c8a33346df6d94c9bdf5bb77c1f81d468203272 (diff) | |
download | mpfr-e901193d09fcf0c1635b41069cc8fe96839f899c.tar.gz |
Added value coverage for tdiv_ui (combinations of rb and sb in the
different cases of the mpfr_div_ui code) and other tests.
(merged changesets r12164-12169 from the trunk)
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/4.0@12170 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | src/div_ui.c | 16 | ||||
-rw-r--r-- | src/mpfr-impl.h | 1 | ||||
-rw-r--r-- | tests/tdiv_ui.c | 162 |
3 files changed, 146 insertions, 33 deletions
diff --git a/src/div_ui.c b/src/div_ui.c index d4cc5a2da..b841e9642 100644 --- a/src/div_ui.c +++ b/src/div_ui.c @@ -23,6 +23,10 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., #define MPFR_NEED_LONGLONG_H #include "mpfr-impl.h" +#ifdef MPFR_COV_CHECK +int __gmpfr_cov_div_ui_sb[10][2] = { 0 }; +#endif + /* returns 0 if result exact, non-zero otherwise */ #undef mpfr_div_ui MPFR_HOT_FUNCTION_ATTR int @@ -161,6 +165,7 @@ mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, rb = 1; /* The sticky bit is 1 unless 2c-u = 0 and r = 0. */ sb |= 2 * c - u; + MPFR_COV_SET (div_ui_sb[0][!!sb]); } else /* 2*c < u */ { @@ -174,9 +179,15 @@ mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, for (i = 0; sb == 0 && i < -dif-1; i++) if (xp[i]) sb = 1; + /* The dif < -1 case with sb = 0, i.e. [2][0], will + ensure that the body of the loop is covered. */ + MPFR_COV_SET (div_ui_sb[1 + (dif < -1)][!!sb]); } else - sb |= c; + { + sb |= c; + MPFR_COV_SET (div_ui_sb[3][!!sb]); + } } } else @@ -184,6 +195,7 @@ mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, /* round bit is in tmp[0] */ rb = tmp[0] & (MPFR_LIMB_ONE << (sh - 1)); sb |= (tmp[0] & MPFR_LIMB_MASK(sh - 1)) | c; + MPFR_COV_SET (div_ui_sb[4+!!rb][!!sb]); } } else /* tmp[yn] != 0 */ @@ -207,11 +219,13 @@ mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, { rb = w & MPFR_LIMB_HIGHBIT; sb |= (w - rb) | c; + MPFR_COV_SET (div_ui_sb[6+!!rb][!!sb]); } else { rb = yp[0] & (MPFR_LIMB_ONE << (sh - 1)); sb |= (yp[0] & MPFR_LIMB_MASK(sh - 1)) | w | c; + MPFR_COV_SET (div_ui_sb[8+!!rb][!!sb]); } exp -= shlz; diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h index f4381bc3c..730beb802 100644 --- a/src/mpfr-impl.h +++ b/src/mpfr-impl.h @@ -2339,6 +2339,7 @@ __MPFR_DECLSPEC int mpfr_vasnprintf_aux (char**, char*, size_t, const char*, extern "C" { #endif +__MPFR_DECLSPEC extern int __gmpfr_cov_div_ui_sb[10][2]; __MPFR_DECLSPEC extern int __gmpfr_cov_sum_tmd[MPFR_RND_MAX][2][2][3][2][2]; #if defined (__cplusplus) diff --git a/tests/tdiv_ui.c b/tests/tdiv_ui.c index d6df0b240..9d88a81dd 100644 --- a/tests/tdiv_ui.c +++ b/tests/tdiv_ui.c @@ -353,46 +353,142 @@ corner_cases (int n) { mpfr_t x, y, t; unsigned long u, v; + int i, xn; if (MPFR_LIMB_MAX <= ULONG_MAX) { - /* we need xn > yn + 1, thus we take xn = 3 and yn = 1 */ - mpfr_init2 (x, 3 * GMP_NUMB_BITS); - mpfr_init2 (y, GMP_NUMB_BITS); - mpfr_init2 (t, 2 * GMP_NUMB_BITS); - while (n--) + /* We need xn > yn + 1, thus we take xn = 3 and yn = 1. + Also take xn = 4 to 6 to cover more code. */ + for (xn = 3; xn < 6; xn++) { - u = randlimb (); - do - v = randlimb (); - while (v <= MPFR_LIMB_HIGHBIT); - mpfr_set_ui (t, v, MPFR_RNDN); - mpfr_sub_d (t, t, 0.5, MPFR_RNDN); - /* t = v-1/2 */ - mpfr_mul_ui (x, t, u, MPFR_RNDN); - - /* when x = (v-1/2)*u, x/u should give v-1/2, which should give - either v (if v is even) or v-1 (if v is odd) */ - mpfr_div_ui (y, x, u, MPFR_RNDN); - MPFR_ASSERTN(mpfr_cmp_ui (y, v - (v & 1)) == 0); - - /* when x = (v-1/2)*u - epsilon, x/u should give v-1 */ - mpfr_nextbelow (x); - mpfr_div_ui (y, x, u, MPFR_RNDN); - MPFR_ASSERTN(mpfr_cmp_ui (y, v - 1) == 0); - - /* when x = (v-1/2)*u + epsilon, x/u should give v */ - mpfr_nextabove (x); - mpfr_nextabove (x); - mpfr_div_ui (y, x, u, MPFR_RNDN); - MPFR_ASSERTN(mpfr_cmp_ui (y, v) == 0); + mpfr_init2 (x, xn * GMP_NUMB_BITS); + mpfr_init2 (y, GMP_NUMB_BITS); + mpfr_init2 (t, 2 * GMP_NUMB_BITS); + for (i = 0; i < n; i++) + { + u = randlimb (); + do + v = randlimb (); + while (v <= MPFR_LIMB_HIGHBIT); + mpfr_set_ui (t, v, MPFR_RNDN); + mpfr_sub_d (t, t, 0.5, MPFR_RNDN); + /* t = v-1/2 */ + mpfr_mul_ui (x, t, u, MPFR_RNDN); + + /* when x = (v-1/2)*u, x/u should give v-1/2, which should give + either v (if v is even) or v-1 (if v is odd) */ + mpfr_div_ui (y, x, u, MPFR_RNDN); + MPFR_ASSERTN(mpfr_cmp_ui (y, v - (v & 1)) == 0); + + /* when x = (v-1/2)*u - epsilon, x/u should give v-1 */ + mpfr_nextbelow (x); + mpfr_div_ui (y, x, u, MPFR_RNDN); + MPFR_ASSERTN(mpfr_cmp_ui (y, v - 1) == 0); + + /* when x = (v-1/2)*u + epsilon, x/u should give v */ + mpfr_nextabove (x); + mpfr_nextabove (x); + mpfr_div_ui (y, x, u, MPFR_RNDN); + MPFR_ASSERTN(mpfr_cmp_ui (y, v) == 0); + } + mpfr_clear (x); + mpfr_clear (y); + mpfr_clear (t); } - mpfr_clear (x); - mpfr_clear (y); - mpfr_clear (t); } } +static void +midpoint_exact (void) +{ + mpfr_t x, y1, y2; + unsigned long j; + int i, kx, ky, px, pxmin, py, pymin, r; + int inex1, inex2; + + pymin = 1; + for (i = 3; i < 32; i += 2) + { + if ((i & (i-2)) == 1) + pymin++; + for (j = 1; j != 0; j++) + { + if (j == 31) + j = ULONG_MAX; + /* Test of (i*j) / j with various precisions. The target precisions + include: large, length(i), and length(i)-1; the latter case + corresponds to a midpoint. */ + mpfr_init2 (x, 5 + sizeof(long) * CHAR_BIT); + inex1 = mpfr_set_ui (x, j, MPFR_RNDN); + MPFR_ASSERTN (inex1 == 0); + inex1 = mpfr_mul_ui (x, x, i, MPFR_RNDN); + MPFR_ASSERTN (inex1 == 0); + /* x = (i*j) */ + pxmin = mpfr_min_prec (x); + if (pxmin < MPFR_PREC_MIN) + pxmin = MPFR_PREC_MIN; + for (kx = 0; kx < 8; kx++) + { + px = pxmin; + if (kx != 0) + px += randlimb () % (4 * GMP_NUMB_BITS); + inex1 = mpfr_prec_round (x, px, MPFR_RNDN); + MPFR_ASSERTN (inex1 == 0); + for (ky = 0; ky < 8; ky++) + { + py = pymin; + if (ky == 0) + py--; + else if (ky > 1) + py += randlimb () % (4 * GMP_NUMB_BITS); + mpfr_inits2 (py, y1, y2, (mpfr_ptr) 0); + RND_LOOP_NO_RNDF (r) + { + inex1 = mpfr_set_ui (y1, i, (mpfr_rnd_t) r); + inex2 = mpfr_div_ui (y2, x, j, (mpfr_rnd_t) r); + if (! mpfr_equal_p (y1, y2) || + ! SAME_SIGN (inex1, inex2)) + { + printf ("Error in midpoint_exact for " + "i=%d j=%lu px=%d py=%d %s\n", i, j, px, py, + mpfr_print_rnd_mode ((mpfr_rnd_t) r)); + printf ("Expected "); + mpfr_dump (y1); + printf ("with inex = %d\n", inex1); + printf ("Got "); + mpfr_dump (y2); + printf ("with inex = %d\n", inex2); + exit (1); + } + } + mpfr_clears (y1, y2, (mpfr_ptr) 0); + } + } + mpfr_clear (x); + } + } +} + +static void +check_coverage (void) +{ +#ifdef MPFR_COV_CHECK + int i, j; + int err = 0; + + for (i = 0; i < numberof (__gmpfr_cov_div_ui_sb); i++) + for (j = 0; j < 2; j++) + if (!__gmpfr_cov_div_ui_sb[i][j]) + { + printf ("mpfr_div_ui not tested on case %d, sb=%d\n", i, j); + err = 1; + } + + if (err) + exit (1); +#endif +} + #define TEST_FUNCTION mpfr_div_ui #define ULONG_ARG2 #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), 1, RANDS) @@ -435,7 +531,9 @@ main (int argc, char **argv) mpfr_clear (x); test_generic (MPFR_PREC_MIN, 200, 100); + midpoint_exact (); + check_coverage (); tests_end_mpfr (); return 0; } |