diff options
-rw-r--r-- | tests/refmpf.c | 169 |
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; +} |