diff options
Diffstat (limited to 'gnulib/tests/test-round2.c')
m--------- | gnulib | 0 | ||||
-rw-r--r-- | gnulib/tests/test-round2.c | 113 |
2 files changed, 113 insertions, 0 deletions
diff --git a/gnulib b/gnulib deleted file mode 160000 -Subproject 443bc5ffcf7429e557f4a371b0661abe98ddbc1 diff --git a/gnulib/tests/test-round2.c b/gnulib/tests/test-round2.c new file mode 100644 index 0000000..f89badf --- /dev/null +++ b/gnulib/tests/test-round2.c @@ -0,0 +1,113 @@ +/* Test of rounding to nearest, breaking ties away from zero. + Copyright (C) 2007-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Ben Pfaff <blp@gnu.org>, 2007. + Heavily based on code by Bruno Haible. */ + +/* When this test fails on some platform, build it together with the gnulib + module 'fprintf-posix' for optimal debugging output. */ + +/* Get the two reference implementations of round under the names + round_reference1 and round_reference2. + + round.c will #include <config.h> for us. */ +#define FLOOR_BASED_ROUND round_reference1 +#define FLOOR_FREE_ROUND round_reference2 +#include "round.c" + +#include <math.h> +#include <float.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "verify.h" + +#ifdef USE_LONG_DOUBLE +# error Long double not supported. +#elif ! defined USE_FLOAT +# include "isnand-nolibm.h" +# define ISNAN isnand +# define FUNCTION "round" +# define DOUBLE_UINT uint64_t +# define DOUBLE_BITS 64 +# define NUM_HIGHBITS 13 +# define NUM_LOWBITS 4 +#else /* defined USE_FLOAT */ +# include "isnanf-nolibm.h" +# define ISNAN isnanf +# define FUNCTION "roundf" +# define DOUBLE_UINT uint32_t +# define DOUBLE_BITS 32 +# define NUM_HIGHBITS 12 +# define NUM_LOWBITS 4 +#endif + +/* Test for equality. */ +static bool +equal (const char *message, DOUBLE x, DOUBLE y0, DOUBLE y1) +{ + if (ISNAN (y0) ? ISNAN (y1) : y0 == y1) + return true; + else + { +#if GNULIB_TEST_FPRINTF_POSIX + fprintf (stderr, "%s: "FUNCTION"(%g(%a)) = %g(%a) or %g(%a)?\n", + message, x, x, y0, y0, y1, y1); +#endif + return false; + } +} + +/* Test the function for a given argument. */ +static bool +check (DOUBLE x) +{ + DOUBLE ref1 = round_reference1 (x); + DOUBLE ref2 = round_reference2 (x); + DOUBLE result = ROUND (x); + + /* If the reference implementations disagree, bail out immediately. */ + if (!equal ("reference implementations disagree", x, ref1, ref2)) + exit (EXIT_FAILURE); + + /* If the actual implementation is wrong, return an error code. */ + return equal ("bad round implementation", x, ref1, result); +} + +int +main (void) +{ + DOUBLE_UINT highbits, lowbits; + int error = 0; + for (highbits = 0; highbits < (1 << NUM_HIGHBITS); highbits++) + for (lowbits = 0; lowbits < (1 << NUM_LOWBITS); lowbits++) + { + /* Combine highbits and lowbits into a floating-point number, + sign-extending the lowbits to DOUBLE_BITS-NUM_HIGHBITS bits. */ + union { DOUBLE f; DOUBLE_UINT i; } janus; + verify (sizeof janus.f == sizeof janus.i); + janus.i = lowbits | (highbits << (DOUBLE_BITS - NUM_HIGHBITS)); + if (lowbits >> (NUM_LOWBITS - 1)) + janus.i |= ((DOUBLE_UINT) -1 + >> (NUM_LOWBITS + NUM_HIGHBITS) + << NUM_LOWBITS); + if (!check (janus.f)) + error = true; + } + return (error ? 1 : 0); +} |