]> git.ipfire.org Git - thirdparty/glibc.git/blob - math/test-fenvinline.c
fe0cc435b13eec136b206748f290e362015161a7
[thirdparty/glibc.git] / math / test-fenvinline.c
1 /* Test for fenv inline implementations.
2 Copyright (C) 2015-2019 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifndef _GNU_SOURCE
20 # define _GNU_SOURCE
21 #endif
22
23 /* To make sure the fenv inline function are used. */
24 #undef __NO_MATH_INLINES
25
26 #include <fenv.h>
27 #include <stdio.h>
28 #include <math-tests.h>
29
30 /*
31 Since not all architectures might define all exceptions, we define
32 a private set and map accordingly.
33 */
34 #define NO_EXC 0
35 #define INEXACT_EXC 0x1
36 #define DIVBYZERO_EXC 0x2
37 #define UNDERFLOW_EXC 0x04
38 #define OVERFLOW_EXC 0x08
39 #define INVALID_EXC 0x10
40 #define ALL_EXC \
41 (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC \
42 | INVALID_EXC)
43 static int count_errors;
44
45 #if FE_ALL_EXCEPT
46 static void
47 test_single_exception_fp_int (int exception,
48 int exc_flag,
49 int fe_flag,
50 const char *flag_name)
51 {
52 if (exception & exc_flag)
53 {
54 if (fetestexcept (fe_flag))
55 printf (" Pass: Exception \"%s\" is set\n", flag_name);
56 else
57 {
58 printf (" Fail: Exception \"%s\" is not set\n", flag_name);
59 ++count_errors;
60 }
61 }
62 else
63 {
64 if (fetestexcept (fe_flag))
65 {
66 printf (" Fail: Exception \"%s\" is set\n", flag_name);
67 ++count_errors;
68 }
69 else
70 printf (" Pass: Exception \"%s\" is not set\n", flag_name);
71 }
72 }
73 /* Test whether a given exception was raised. */
74 static void
75 test_single_exception_fp_double (int exception,
76 int exc_flag,
77 double fe_flag,
78 const char *flag_name)
79 {
80 if (exception & exc_flag)
81 {
82 if (fetestexcept (fe_flag))
83 printf (" Pass: Exception \"%s\" is set\n", flag_name);
84 else
85 {
86 printf (" Fail: Exception \"%s\" is not set\n", flag_name);
87 ++count_errors;
88 }
89 }
90 else
91 {
92 if (fetestexcept (fe_flag))
93 {
94 printf (" Fail: Exception \"%s\" is set\n", flag_name);
95 ++count_errors;
96 }
97 else
98 printf (" Pass: Exception \"%s\" is not set\n", flag_name);
99 }
100 }
101 #endif
102
103 static void
104 test_exceptions (const char *test_name, int exception)
105 {
106 printf ("Test: %s\n", test_name);
107 #ifdef FE_DIVBYZERO
108 test_single_exception_fp_double (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
109 "DIVBYZERO");
110 #endif
111 #ifdef FE_INVALID
112 test_single_exception_fp_double (exception, INVALID_EXC, FE_INVALID,
113 "INVALID");
114 #endif
115 #ifdef FE_INEXACT
116 test_single_exception_fp_double (exception, INEXACT_EXC, FE_INEXACT,
117 "INEXACT");
118 #endif
119 #ifdef FE_UNDERFLOW
120 test_single_exception_fp_double (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
121 "UNDERFLOW");
122 #endif
123 #ifdef FE_OVERFLOW
124 test_single_exception_fp_double (exception, OVERFLOW_EXC, FE_OVERFLOW,
125 "OVERFLOW");
126 #endif
127 }
128
129 static void
130 test_exceptionflag (void)
131 {
132 printf ("Test: fegetexceptionflag (FE_ALL_EXCEPT)\n");
133 #if FE_ALL_EXCEPT
134 fexcept_t excepts;
135
136 feclearexcept (FE_ALL_EXCEPT);
137
138 feraiseexcept (FE_INVALID);
139 fegetexceptflag (&excepts, FE_ALL_EXCEPT);
140
141 feclearexcept (FE_ALL_EXCEPT);
142 feraiseexcept (FE_OVERFLOW | FE_INEXACT);
143
144 fesetexceptflag (&excepts, FE_ALL_EXCEPT);
145
146 test_single_exception_fp_int (INVALID_EXC, INVALID_EXC, FE_INVALID,
147 "INVALID (int)");
148 test_single_exception_fp_int (INVALID_EXC, OVERFLOW_EXC, FE_OVERFLOW,
149 "OVERFLOW (int)");
150 test_single_exception_fp_int (INVALID_EXC, INEXACT_EXC, FE_INEXACT,
151 "INEXACT (int)");
152
153 /* Same test, but using double as argument */
154 feclearexcept (FE_ALL_EXCEPT);
155
156 feraiseexcept (FE_INVALID);
157 fegetexceptflag (&excepts, (double)FE_ALL_EXCEPT);
158
159 feclearexcept (FE_ALL_EXCEPT);
160 feraiseexcept (FE_OVERFLOW | FE_INEXACT);
161
162 fesetexceptflag (&excepts, (double)FE_ALL_EXCEPT);
163
164 test_single_exception_fp_double (INVALID_EXC, INVALID_EXC, FE_INVALID,
165 "INVALID (double)");
166 test_single_exception_fp_double (INVALID_EXC, OVERFLOW_EXC, FE_OVERFLOW,
167 "OVERFLOW (double)");
168 test_single_exception_fp_double (INVALID_EXC, INEXACT_EXC, FE_INEXACT,
169 "INEXACT (double)");
170 #endif
171 }
172
173 static void
174 test_fesetround (void)
175 {
176 #if defined FE_TONEAREST && defined FE_TOWARDZERO
177 int res1;
178 int res2;
179
180 printf ("Tests for fesetround\n");
181
182 /* The fesetround should not itself cause the test to fail, however it
183 should either succeed for both 'int' and 'double' argument, or fail
184 for both. */
185 res1 = fesetround ((int) FE_TOWARDZERO);
186 res2 = fesetround ((double) FE_TOWARDZERO);
187 if (res1 != res2)
188 {
189 printf ("fesetround (FE_TOWARDZERO) failed: %d, %d\n", res1, res2);
190 ++count_errors;
191 }
192
193 res1 = fesetround ((int) FE_TONEAREST);
194 res2 = fesetround ((double) FE_TONEAREST);
195 if (res1 != res2)
196 {
197 printf ("fesetround (FE_TONEAREST) failed: %d, %d\n", res1, res2);
198 ++count_errors;
199 }
200 #endif
201 }
202
203 #if FE_ALL_EXCEPT
204 /* Tests for feenableexcept/fedisableexcept. */
205 static void
206 feenable_test (const char *flag_name, fexcept_t fe_exc)
207 {
208 int fe_exci = fe_exc;
209 double fe_excd = fe_exc;
210 int excepts;
211
212 /* First disable all exceptions. */
213 if (fedisableexcept (FE_ALL_EXCEPT) == -1)
214 {
215 printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n");
216 ++count_errors;
217 /* If this fails, the other tests don't make sense. */
218 return;
219 }
220
221 /* Test for inline macros using integer argument. */
222 excepts = feenableexcept (fe_exci);
223 if (!EXCEPTION_ENABLE_SUPPORTED (fe_exci) && excepts == -1)
224 {
225 printf ("Test: not testing feenableexcept, it isn't implemented.\n");
226 return;
227 }
228 if (excepts == -1)
229 {
230 printf ("Test: feenableexcept (%s) failed\n", flag_name);
231 ++count_errors;
232 return;
233 }
234 if (excepts != 0)
235 {
236 printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
237 flag_name, excepts);
238 ++count_errors;
239 }
240
241 /* And now disable the exception again. */
242 excepts = fedisableexcept (fe_exc);
243 if (excepts == -1)
244 {
245 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
246 ++count_errors;
247 return;
248 }
249 if (excepts != fe_exc)
250 {
251 printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
252 flag_name, (unsigned int)fe_exc, excepts);
253 ++count_errors;
254 }
255
256 /* Test for inline macros using double argument. */
257 excepts = feenableexcept (fe_excd);
258 if (!EXCEPTION_ENABLE_SUPPORTED (fe_excd) && excepts == -1)
259 {
260 printf ("Test: not testing feenableexcept, it isn't implemented.\n");
261 return;
262 }
263 if (excepts == -1)
264 {
265 printf ("Test: feenableexcept (%s) failed\n", flag_name);
266 ++count_errors;
267 return;
268 }
269 if (excepts != 0)
270 {
271 printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
272 flag_name, excepts);
273 ++count_errors;
274 }
275
276 /* And now disable the exception again. */
277 excepts = fedisableexcept (fe_exc);
278 if (excepts == -1)
279 {
280 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
281 ++count_errors;
282 return;
283 }
284 if (excepts != fe_exc)
285 {
286 printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
287 flag_name, (unsigned int)fe_exc, excepts);
288 ++count_errors;
289 }
290 }
291 #endif
292
293 static void
294 test_feenabledisable (void)
295 {
296 printf ("Tests for feenableexcepts/fedisableexcept\n");
297
298 /* We might have some exceptions still set. */
299 feclearexcept (FE_ALL_EXCEPT);
300
301 #ifdef FE_DIVBYZERO
302 feenable_test ("FE_DIVBYZERO", FE_DIVBYZERO);
303 #endif
304 #ifdef FE_INVALID
305 feenable_test ("FE_INVALID", FE_INVALID);
306 #endif
307 #ifdef FE_INEXACT
308 feenable_test ("FE_INEXACT", FE_INEXACT);
309 #endif
310 #ifdef FE_UNDERFLOW
311 feenable_test ("FE_UNDERFLOW", FE_UNDERFLOW);
312 #endif
313 #ifdef FE_OVERFLOW
314 feenable_test ("FE_OVERFLOW", FE_OVERFLOW);
315 #endif
316 fesetenv (FE_DFL_ENV);
317 }
318
319 static int
320 do_test (void)
321 {
322 /* clear all exceptions and test if all are cleared */
323 feclearexcept (FE_ALL_EXCEPT);
324 test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
325 NO_EXC);
326
327 /* raise all exceptions and test if all are raised */
328 feraiseexcept (FE_ALL_EXCEPT);
329 if (EXCEPTION_TESTS (float))
330 test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
331 ALL_EXC);
332
333 /* Same test, but using double as argument */
334 feclearexcept ((double)FE_ALL_EXCEPT);
335 test_exceptions ("feclearexcept ((double)FE_ALL_EXCEPT) clears all exceptions",
336 NO_EXC);
337
338 feraiseexcept ((double)FE_ALL_EXCEPT);
339 if (EXCEPTION_TESTS (float))
340 test_exceptions ("feraiseexcept ((double)FE_ALL_EXCEPT) raises all exceptions",
341 ALL_EXC);
342
343 if (EXCEPTION_TESTS (float))
344 test_exceptionflag ();
345
346 test_fesetround ();
347
348 test_feenabledisable ();
349
350 return count_errors;
351 }
352
353 #define TEST_FUNCTION do_test ()
354 #include "../test-skeleton.c"