Refactor tst-strtod-round.c
[glibc.git] / stdlib / tst-strtod-round.c
bloba2cd2ab636575d9a58a3b4a94804b5dd88045c42
1 /* Test for correct rounding of results of strtod and related
2 functions.
3 Copyright (C) 2012-2016 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 /* Defining _LIBC_TEST ensures long double math functions are
21 declared in the headers. */
22 #define _LIBC_TEST 1
23 #include <fenv.h>
24 #include <float.h>
25 #include <math.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <math-tests.h>
32 struct exactness
34 bool f;
35 bool d;
36 bool ld;
39 struct test_results {
40 float f;
41 double d;
42 long double ld;
45 struct test {
46 const char *s;
47 struct exactness exact;
48 struct test_results rd, rn, rz, ru;
51 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
52 # define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du, \
53 ld53exact, ld53d, ld53n, ld53z, ld53u, \
54 ld64iexact, ld64id, ld64in, ld64iz, ld64iu, \
55 ld64mexact, ld64md, ld64mn, ld64mz, ld64mu, \
56 ld106exact, ld106d, ld106n, ld106z, ld106u, \
57 ld113exact, ld113d, ld113n, ld113z, ld113u) \
58 { \
59 s, \
60 { fexact, dexact, ld53exact }, \
61 { fd, dd, ld53d }, \
62 { fn, dn, ld53n }, \
63 { fz, dz, ld53z }, \
64 { fu, du, ld53u } \
66 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && LDBL_MIN_EXP == -16381
67 /* This is for the Intel extended float format. */
68 # define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du, \
69 ld53exact, ld53d, ld53n, ld53z, ld53u, \
70 ld64iexact, ld64id, ld64in, ld64iz, ld64iu, \
71 ld64mexact, ld64md, ld64mn, ld64mz, ld64mu, \
72 ld106exact, ld106d, ld106n, ld106z, ld106u, \
73 ld113exact, ld113d, ld113n, ld113z, ld113u) \
74 { \
75 s, \
76 { fexact, dexact, ld64iexact }, \
77 { fd, dd, ld64id }, \
78 { fn, dn, ld64in }, \
79 { fz, dz, ld64iz }, \
80 { fu, du, ld64iu } \
82 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && LDBL_MIN_EXP == -16382
83 /* This is for the Motorola extended float format. */
84 # define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du, \
85 ld53exact, ld53d, ld53n, ld53z, ld53u, \
86 ld64iexact, ld64id, ld64in, ld64iz, ld64iu, \
87 ld64mexact, ld64md, ld64mn, ld64mz, ld64mu, \
88 ld106exact, ld106d, ld106n, ld106z, ld106u, \
89 ld113exact, ld113d, ld113n, ld113z, ld113u) \
90 { \
91 s, \
92 { fexact, dexact, ld64mexact }, \
93 { fd, dd, ld64md }, \
94 { fn, dn, ld64mn }, \
95 { fz, dz, ld64mz }, \
96 { fu, du, ld64mu } \
98 #elif LDBL_MANT_DIG == 106 && LDBL_MAX_EXP == 1024
99 # define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du, \
100 ld53exact, ld53d, ld53n, ld53z, ld53u, \
101 ld64iexact, ld64id, ld64in, ld64iz, ld64iu, \
102 ld64mexact, ld64md, ld64mn, ld64mz, ld64mu, \
103 ld106exact, ld106d, ld106n, ld106z, ld106u, \
104 ld113exact, ld113d, ld113n, ld113z, ld113u) \
106 s, \
107 { fexact, dexact, ld106exact }, \
108 { fd, dd, ld106d }, \
109 { fn, dn, ld106n }, \
110 { fz, dz, ld106z }, \
111 { fu, du, ld106u } \
113 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
114 # define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du, \
115 ld53exact, ld53d, ld53n, ld53z, ld53u, \
116 ld64iexact, ld64id, ld64in, ld64iz, ld64iu, \
117 ld64mexact, ld64md, ld64mn, ld64mz, ld64mu, \
118 ld106exact, ld106d, ld106n, ld106z, ld106u, \
119 ld113exact, ld113d, ld113n, ld113z, ld113u) \
121 s, \
122 { fexact, dexact, ld113exact }, \
123 { fd, dd, ld113d }, \
124 { fn, dn, ld113n }, \
125 { fz, dz, ld113z }, \
126 { fu, du, ld113u } \
128 #else
129 # error "unknown long double format"
130 #endif
132 /* Include the generated test data. */
133 #include "tst-strtod-round-data.h"
135 static int
136 test_in_one_mode (const char *s, const struct test_results *expected,
137 const struct exactness *exact, const char *mode_name,
138 bool float_round_ok, bool double_round_ok,
139 bool long_double_round_ok)
141 int result = 0;
142 float f = strtof (s, NULL);
143 double d = strtod (s, NULL);
144 long double ld = strtold (s, NULL);
145 if (f != expected->f
146 || copysignf (1.0f, f) != copysignf (1.0f, expected->f))
148 printf ("strtof (%s) returned %a not %a (%s)\n", s, f,
149 expected->f, mode_name);
150 if (float_round_ok || exact->f)
151 result = 1;
152 else
153 printf ("ignoring this inexact result\n");
155 if (d != expected->d
156 || copysign (1.0, d) != copysign (1.0, expected->d))
158 printf ("strtod (%s) returned %a not %a (%s)\n", s, d,
159 expected->d, mode_name);
160 if (double_round_ok || exact->d)
161 result = 1;
162 else
163 printf ("ignoring this inexact result\n");
165 if (ld != expected->ld
166 || copysignl (1.0L, ld) != copysignl (1.0L, expected->ld))
168 printf ("strtold (%s) returned %La not %La (%s)\n", s, ld,
169 expected->ld, mode_name);
170 if ((long_double_round_ok && LDBL_MANT_DIG != 106) || exact->ld)
171 result = 1;
172 else
173 printf ("ignoring this inexact result\n");
175 return result;
178 static int
179 do_test (void)
181 int save_round_mode __attribute__ ((unused)) = fegetround ();
182 int result = 0;
183 for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
185 result |= test_in_one_mode (tests[i].s, &tests[i].rn, &tests[i].exact,
186 "default rounding mode",
187 true, true, true);
188 #ifdef FE_DOWNWARD
189 if (!fesetround (FE_DOWNWARD))
191 result |= test_in_one_mode (tests[i].s, &tests[i].rd,
192 &tests[i].exact, "FE_DOWNWARD",
193 ROUNDING_TESTS (float, FE_DOWNWARD),
194 ROUNDING_TESTS (double, FE_DOWNWARD),
195 ROUNDING_TESTS (long double,
196 FE_DOWNWARD));
197 fesetround (save_round_mode);
199 #endif
200 #ifdef FE_TOWARDZERO
201 if (!fesetround (FE_TOWARDZERO))
203 result |= test_in_one_mode (tests[i].s, &tests[i].rz,
204 &tests[i].exact, "FE_TOWARDZERO",
205 ROUNDING_TESTS (float, FE_TOWARDZERO),
206 ROUNDING_TESTS (double, FE_TOWARDZERO),
207 ROUNDING_TESTS (long double,
208 FE_TOWARDZERO));
209 fesetround (save_round_mode);
211 #endif
212 #ifdef FE_UPWARD
213 if (!fesetround (FE_UPWARD))
215 result |= test_in_one_mode (tests[i].s, &tests[i].ru,
216 &tests[i].exact, "FE_UPWARD",
217 ROUNDING_TESTS (float, FE_UPWARD),
218 ROUNDING_TESTS (double, FE_UPWARD),
219 ROUNDING_TESTS (long double, FE_UPWARD));
220 fesetround (save_round_mode);
222 #endif
224 return result;
227 #define TEST_FUNCTION do_test ()
228 #include "../test-skeleton.c"