summaryrefslogtreecommitdiff
path: root/tests/trint.c
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2003-10-21 12:33:17 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2003-10-21 12:33:17 +0000
commitc4eaf03391042f49a4cce89223047230297af999 (patch)
tree891e5a55320d7513bc2f8d1e27bf7bbbecd932ab /tests/trint.c
parent4084639de2b386e64eacaf0395f53af53675baa9 (diff)
downloadmpfr-c4eaf03391042f49a4cce89223047230297af999.tar.gz
Merged the mpfr-2-0-2-branch changes to the trunk.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2519 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'tests/trint.c')
-rw-r--r--tests/trint.c103
1 files changed, 96 insertions, 7 deletions
diff --git a/tests/trint.c b/tests/trint.c
index a0c3e8c87..b02b42221 100644
--- a/tests/trint.c
+++ b/tests/trint.c
@@ -21,8 +21,11 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "gmp.h"
+#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
#include "mpfr-test.h"
#if __STDC_VERSION__ >= 199901L
@@ -75,13 +78,27 @@ test_against_libc (void)
#endif
+static void
+err (char *str, mp_size_t s, mpfr_t x, mpfr_t y, mp_prec_t p, mp_rnd_t r,
+ int trint, int inexact)
+{
+ printf ("Error: %s\ns = %u, p = %u, r = %s, trint = %d, inexact = %d\nx = ",
+ str, (unsigned int) s, (unsigned int) p, mpfr_print_rnd_mode (r),
+ trint, inexact);
+ mpfr_print_binary (x);
+ printf ("\ny = ");
+ mpfr_print_binary (y);
+ printf ("\n");
+ exit (1);
+}
+
int
main (int argc, char *argv[])
{
mp_size_t s;
mpz_t z;
mp_prec_t p;
- mpfr_t x, y, t;
+ mpfr_t x, y, t, u, v;
mp_rnd_t r;
int inexact, sign_t;
@@ -91,6 +108,8 @@ main (int argc, char *argv[])
mpfr_init (y);
mpz_init (z);
mpfr_init (t);
+ mpfr_init (u);
+ mpfr_init (v);
mpz_set_ui (z, 1);
for (s = 2; s < 100; s++)
{
@@ -101,16 +120,22 @@ main (int argc, char *argv[])
mpz_add_ui (z, z, 1);
mpfr_set_prec (x, s);
mpfr_set_prec (t, s);
+ mpfr_set_prec (u, s);
if (mpfr_set_z (x, z, GMP_RNDN))
{
printf ("Error: mpfr_set_z should be exact (s = %u)\n",
(unsigned int) s);
exit (1);
}
+ if (randlimb () % 2)
+ mpfr_neg (x, x, GMP_RNDN);
+ if (randlimb () % 2)
+ mpfr_div_2ui (x, x, randlimb () % s, GMP_RNDN);
for (p = 2; p < 100; p++)
{
int trint;
mpfr_set_prec (y, p);
+ mpfr_set_prec (v, p);
for (r = 0; r < 4; r++)
for (trint = 0; trint < 2; trint++)
{
@@ -125,17 +150,79 @@ main (int argc, char *argv[])
else /* r = GMP_RNDD */
inexact = mpfr_floor (y, x);
if (mpfr_sub (t, y, x, GMP_RNDN))
- {
- printf ("Error: subtraction should be exact\n");
- exit (1);
- }
+ err ("subtraction 1 should be exact",
+ s, x, y, p, r, trint, inexact);
sign_t = mpfr_cmp_ui (t, 0);
if (((inexact == 0) && (sign_t != 0)) ||
((inexact < 0) && (sign_t >= 0)) ||
((inexact > 0) && (sign_t <= 0)))
+ err ("wrong inexact flag", s, x, y, p, r, trint, inexact);
+ if (inexact == 0)
+ continue; /* end of the test for exact results */
+
+ if (((r == GMP_RNDD || (r == GMP_RNDZ && MPFR_SIGN (x) > 0))
+ && inexact > 0) ||
+ ((r == GMP_RNDU || (r == GMP_RNDZ && MPFR_SIGN (x) < 0))
+ && inexact < 0))
+ err ("wrong rounding direction",
+ s, x, y, p, r, trint, inexact);
+ if (inexact < 0)
+ {
+ mpfr_add_ui (v, y, 1, GMP_RNDU);
+ if (mpfr_cmp (v, x) <= 0)
+ err ("representable integer between x and its "
+ "rounded value", s, x, y, p, r, trint, inexact);
+ }
+ else
+ {
+ mpfr_sub_ui (v, y, 1, GMP_RNDD);
+ if (mpfr_cmp (v, x) >= 0)
+ err ("representable integer between x and its "
+ "rounded value", s, x, y, p, r, trint, inexact);
+ }
+ if (r == GMP_RNDN)
{
- printf ("Wrong inexact flag\n");
- exit (1);
+ int cmp;
+ if (mpfr_sub (u, v, x, GMP_RNDN))
+ err ("subtraction 2 should be exact",
+ s, x, y, p, r, trint, inexact);
+ cmp = mpfr_cmp_abs (t, u);
+ if (cmp > 0)
+ err ("faithful rounding, but not the nearest integer",
+ s, x, y, p, r, trint, inexact);
+ if (cmp < 0)
+ continue;
+ /* |t| = |u|: x is the middle of two consecutive
+ representable integers. */
+ if (trint)
+ {
+ /* halfway case for mpfr_rint in GMP_RNDN rounding
+ mode: round to an even integer or mantissa. */
+ mpfr_div_2ui (y, y, 1, GMP_RNDZ);
+ if (!mpfr_integer_p (y))
+ err ("halfway case for mpfr_rint, result isn't an"
+ " even integer", s, x, y, p, r, trint, inexact);
+ /* If floor(x) and ceil(x) aren't both representable
+ integers, the mantissa must be even. */
+ mpfr_sub (v, v, y, GMP_RNDN);
+ mpfr_abs (v, v, GMP_RNDN);
+ if (mpfr_cmp_ui (v, 1) != 0)
+ {
+ mpfr_div_2si (y, y, MPFR_EXP (y) - MPFR_PREC (y)
+ + 1, GMP_RNDN);
+ if (!mpfr_integer_p (y))
+ err ("halfway case for mpfr_rint, mantissa isn't"
+ " even", s, x, y, p, r, trint, inexact);
+ }
+ }
+ else
+ { /* halfway case for mpfr_round: x must have been
+ rounded away from zero. */
+ if ((MPFR_SIGN (x) > 0 && inexact < 0) ||
+ (MPFR_SIGN (x) < 0 && inexact > 0))
+ err ("halfway case for mpfr_round, bad rounding"
+ " direction", s, x, y, p, r, trint, inexact);
+ }
}
}
}
@@ -144,6 +231,8 @@ main (int argc, char *argv[])
mpfr_clear (y);
mpz_clear (z);
mpfr_clear (t);
+ mpfr_clear (u);
+ mpfr_clear (v);
/* TODO: add hardcoded tests */
#if __STDC_VERSION__ >= 199901L