summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-01-31 16:21:15 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-01-31 16:21:15 +0000
commite901193d09fcf0c1635b41069cc8fe96839f899c (patch)
treeedd1763746b7686c7782c13e131ea032641f4985
parent9c8a33346df6d94c9bdf5bb77c1f81d468203272 (diff)
downloadmpfr-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.c16
-rw-r--r--src/mpfr-impl.h1
-rw-r--r--tests/tdiv_ui.c162
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;
}