summaryrefslogtreecommitdiff
path: root/tests/refmpf.c
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2004-03-03 21:16:59 +0100
committerKevin Ryde <user42@zip.com.au>2004-03-03 21:16:59 +0100
commit99d0daf5d6c61e30264b8e806956bcae3538c356 (patch)
tree88cbbecb32add703d95229dd2285bf60bbb059dd /tests/refmpf.c
parent7e1609cee5f2a47ebd615ca812223274a68c2d01 (diff)
downloadgmp-99d0daf5d6c61e30264b8e806956bcae3538c356.tar.gz
* tests/refmpf.c, tests/tests.h (refmpf_fill, refmpf_normalize,
refmpf_validate, refmpf_validate_division): New functions.
Diffstat (limited to 'tests/refmpf.c')
-rw-r--r--tests/refmpf.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/tests/refmpf.c b/tests/refmpf.c
index 1537b8105..0fe6561f4 100644
--- a/tests/refmpf.c
+++ b/tests/refmpf.c
@@ -142,6 +142,29 @@ refmpf_add_ulp (mpf_ptr f)
}
}
+/* Fill f with size limbs of the given value, setup as an integer. */
+void
+refmpf_fill (mpf_ptr f, mp_size_t size, mp_limb_t value)
+{
+ ASSERT (size >= 0);
+ size = MIN (PREC(f) + 1, size);
+ SIZ(f) = size;
+ EXP(f) = size;
+ refmpn_fill (PTR(f), size, value);
+}
+
+/* Strip high zero limbs from the f data, adjusting exponent accordingly. */
+void
+refmpf_normalize (mpf_ptr f)
+{
+ while (SIZ(f) != 0 && PTR(f)[ABSIZ(f)-1] == 0)
+ {
+ SIZ(f) = (SIZ(f) >= 0 ? SIZ(f)-1 : SIZ(f)+1);
+ EXP(f) --;
+ }
+ if (SIZ(f) == 0)
+ EXP(f) = 0;
+}
/* Like mpf_set_prec, but taking a precision in limbs.
PREC(f) ends up as the given "prec" value. */
@@ -235,3 +258,149 @@ done:
EXP (w) = exp;
TMP_FREE (mark);
}
+
+
+/* Validate got by comparing to want. Return 1 if good, 0 if bad.
+
+ The data in got is compared to that in want, up to either PREC(got) limbs
+ or the size of got, whichever is bigger. Clearly we always demand
+ PREC(got) of accuracy, but we go further and say that if got is bigger
+ then any extra must be correct too.
+
+ want needs to have enough data to allow this comparison. The size in
+ want doesn't have to be that big though, if it's smaller then further low
+ limbs are taken to be zero.
+
+ This validation approach is designed to allow some flexibility in exactly
+ how much data is generated by an mpf function, ie. either prec or prec+1
+ limbs. We don't try to make a reference function that emulates that same
+ size decision, instead the idea is for a validation function to generate
+ at least as much data as the real function, then compare. */
+
+int
+refmpf_validate (const char *name, mpf_srcptr got, mpf_srcptr want)
+{
+ int bad = 0;
+ mp_size_t gsize, wsize, cmpsize, i;
+ mp_srcptr gp, wp;
+ mp_limb_t glimb, wlimb;
+
+ MPF_CHECK_FORMAT (got);
+
+ if (EXP (got) != EXP (want))
+ {
+ printf ("%s: wrong exponent\n", name);
+ bad = 1;
+ }
+
+ gsize = SIZ (got);
+ wsize = SIZ (want);
+ if ((gsize < 0 && wsize > 0) || (gsize > 0 && wsize < 0))
+ {
+ printf ("%s: wrong sign\n", name);
+ bad = 1;
+ }
+
+ gsize = ABS (gsize);
+ wsize = ABS (wsize);
+
+ /* most significant limb of respective data */
+ gp = PTR (got) + gsize - 1;
+ wp = PTR (want) + wsize - 1;
+
+ /* compare limb data */
+ cmpsize = MAX (PREC (got), gsize);
+ for (i = 0; i < cmpsize; i++)
+ {
+ glimb = (i < gsize ? gp[-i] : 0);
+ wlimb = (i < wsize ? wp[-i] : 0);
+
+ if (glimb != wlimb)
+ {
+ printf ("%s: wrong data starting at index %ld from top\n",
+ name, (long) i);
+ bad = 1;
+ break;
+ }
+ }
+
+ if (bad)
+ {
+ printf (" prec %d\n", PREC(got));
+ printf (" exp got %ld\n", (long) EXP(got));
+ printf (" exp want %ld\n", (long) EXP(want));
+ printf (" size got %d\n", SIZ(got));
+ printf (" size want %d\n", SIZ(want));
+ printf (" limbs (high to low)\n");
+ printf (" got ");
+ for (i = ABSIZ(got)-1; i >= 0; i--)
+ {
+ gmp_printf ("%MX", PTR(got)[i]);
+ if (i != 0)
+ printf (",");
+ }
+ printf ("\n");
+ printf (" want ");
+ for (i = ABSIZ(want)-1; i >= 0; i--)
+ {
+ gmp_printf ("%MX", PTR(want)[i]);
+ if (i != 0)
+ printf (",");
+ }
+ printf ("\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int
+refmpf_validate_division (const char *name, mpf_srcptr got,
+ mpf_srcptr n, mpf_srcptr d)
+{
+ mp_size_t nsize, dsize, sign, prec, qsize, tsize;
+ mp_srcptr np, dp;
+ mp_ptr tp, qp, rp;
+ mpf_t want;
+ int ret;
+
+ nsize = SIZ (n);
+ dsize = SIZ (d);
+ ASSERT_ALWAYS (dsize != 0);
+
+ sign = nsize ^ dsize;
+ nsize = ABS (nsize);
+ dsize = ABS (dsize);
+
+ np = PTR (n);
+ dp = PTR (d);
+ prec = PREC (got);
+
+ EXP (want) = EXP (n) - EXP (d) + 1;
+
+ qsize = prec + 2; /* at least prec+1 limbs, after high zero */
+ tsize = qsize + dsize - 1; /* dividend size to give desired qsize */
+
+ /* dividend n, extended or truncated */
+ tp = refmpn_malloc_limbs (tsize);
+ refmpn_copy_extend (tp, tsize, np, nsize);
+
+ qp = refmpn_malloc_limbs (qsize);
+ rp = refmpn_malloc_limbs (dsize); /* remainder, unused */
+
+ ASSERT_ALWAYS (qsize == tsize - dsize + 1);
+ refmpn_tdiv_qr (qp, rp, (mp_size_t) 0, tp, tsize, dp, dsize);
+
+ PTR (want) = qp;
+ SIZ (want) = (sign >= 0 ? qsize : -qsize);
+ refmpf_normalize (want);
+
+ ret = refmpf_validate (name, got, want);
+
+ free (tp);
+ free (qp);
+ free (rp);
+
+ return ret;
+}