maint: update copyright
[gnulib.git] / tests / test-round2.c
1 /* Test of rounding to nearest, breaking ties away from zero.
2    Copyright (C) 2007-2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Ben Pfaff <blp@gnu.org>, 2007.
18    Heavily based on code by Bruno Haible. */
19
20 /* When this test fails on some platform, build it together with the gnulib
21    module 'fprintf-posix' for optimal debugging output.  */
22
23 /* Get the two reference implementations of round under the names
24    round_reference1 and round_reference2.
25
26    round.c will #include <config.h> for us. */
27 #define FLOOR_BASED_ROUND round_reference1
28 #define FLOOR_FREE_ROUND round_reference2
29 #include "round.c"
30
31 #include <math.h>
32 #include <float.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 #include "verify.h"
39
40 #ifdef USE_LONG_DOUBLE
41 # error Long double not supported.
42 #elif ! defined USE_FLOAT
43 # include "isnand-nolibm.h"
44 # define ISNAN isnand
45 # define FUNCTION "round"
46 # define DOUBLE_UINT uint64_t
47 # define DOUBLE_BITS 64
48 # define NUM_HIGHBITS 13
49 # define NUM_LOWBITS 4
50 #else /* defined USE_FLOAT */
51 # include "isnanf-nolibm.h"
52 # define ISNAN isnanf
53 # define FUNCTION "roundf"
54 # define DOUBLE_UINT uint32_t
55 # define DOUBLE_BITS 32
56 # define NUM_HIGHBITS 12
57 # define NUM_LOWBITS 4
58 #endif
59
60 /* Test for equality.  */
61 static bool
62 equal (const char *message, DOUBLE x, DOUBLE y0, DOUBLE y1)
63 {
64   if (ISNAN (y0) ? ISNAN (y1) : y0 == y1)
65     return true;
66   else
67     {
68 #if GNULIB_TEST_FPRINTF_POSIX
69       fprintf (stderr, "%s: "FUNCTION"(%g(%a)) = %g(%a) or %g(%a)?\n",
70                message, x, x, y0, y0, y1, y1);
71 #endif
72       return false;
73     }
74 }
75
76 /* Test the function for a given argument.  */
77 static bool
78 check (DOUBLE x)
79 {
80   DOUBLE ref1 = round_reference1 (x);
81   DOUBLE ref2 = round_reference2 (x);
82   DOUBLE result = ROUND (x);
83
84   /* If the reference implementations disagree, bail out immediately.  */
85   if (!equal ("reference implementations disagree", x, ref1, ref2))
86     exit (EXIT_FAILURE);
87
88   /* If the actual implementation is wrong, return an error code.  */
89   return equal ("bad round implementation", x, ref1, result);
90 }
91
92 int
93 main (void)
94 {
95   DOUBLE_UINT highbits, lowbits;
96   int error = 0;
97   for (highbits = 0; highbits < (1 << NUM_HIGHBITS); highbits++)
98     for (lowbits = 0; lowbits < (1 << NUM_LOWBITS); lowbits++)
99       {
100         /* Combine highbits and lowbits into a floating-point number,
101            sign-extending the lowbits to DOUBLE_BITS-NUM_HIGHBITS bits.  */
102         union { DOUBLE f; DOUBLE_UINT i; } janus;
103         verify (sizeof janus.f == sizeof janus.i);
104         janus.i = lowbits | (highbits << (DOUBLE_BITS - NUM_HIGHBITS));
105         if (lowbits >> (NUM_LOWBITS - 1))
106           janus.i |= ((DOUBLE_UINT) -1
107                       >> (NUM_LOWBITS + NUM_HIGHBITS)
108                       << NUM_LOWBITS);
109         if (!check (janus.f))
110           error = true;
111       }
112   return (error ? 1 : 0);
113 }