]> git.ipfire.org Git - thirdparty/glibc.git/blame - math/test-fenv.c
Update.
[thirdparty/glibc.git] / math / test-fenv.c
CommitLineData
762a2918
UD
1/* Copyright (C) 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de> and
4 Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
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 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21/* Tests for ISO C 9X 7.6: Floating-point environment */
bca973bc
UD
22
23#ifndef _GNU_SOURCE
24# define _GNU_SOURCE
25#endif
26
27#include <complex.h>
28#include <math.h>
29#include <float.h>
30#include <fenv.h>
31
32#include <errno.h>
762a2918 33#include <signal.h>
bca973bc
UD
34#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
762a2918
UD
37#include <unistd.h>
38#include <sys/wait.h>
74015205 39#include <sys/resource.h>
bca973bc
UD
40
41/*
42 Since not all architectures might define all exceptions, we define
43 a private set and map accordingly.
44*/
45#define NO_EXC 0
46#define INEXACT_EXC 0x1
47#define DIVBYZERO_EXC 0x2
48#define UNDERFLOW_EXC 0x04
49#define OVERFLOW_EXC 0x08
50#define INVALID_EXC 0x10
51#define ALL_EXC \
52 (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC | \
53 INVALID_EXC)
54
55static int count_errors;
56
57/* Test whether a given exception was raised. */
58static void
59test_single_exception (short int exception,
60 short int exc_flag,
61 fexcept_t fe_flag,
62 const char *flag_name)
63{
64 if (exception & exc_flag)
65 {
66 if (fetestexcept (fe_flag))
67 printf (" Pass: Exception \"%s\" is set\n", flag_name);
68 else
69 {
70 printf (" Fail: Exception \"%s\" is not set\n", flag_name);
71 ++count_errors;
72 }
73 }
74 else
75 {
76 if (fetestexcept (fe_flag))
77 {
78 printf (" Fail: Exception \"%s\" is set\n", flag_name);
79 ++count_errors;
80 }
81 else
82 {
83 printf (" Pass: Exception \"%s\" is not set\n", flag_name);
84 }
85 }
86}
87
88static void
1522c368
UD
89test_exceptions (const char *test_name, short int exception,
90 int ignore_inexact)
bca973bc
UD
91{
92 printf ("Test: %s\n", test_name);
93#ifdef FE_DIVBYZERO
94 test_single_exception (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
95 "DIVBYZERO");
96#endif
97#ifdef FE_INVALID
98 test_single_exception (exception, INVALID_EXC, FE_INVALID,
99 "INVALID");
100#endif
101#ifdef FE_INEXACT
1522c368
UD
102 if (!ignore_inexact)
103 test_single_exception (exception, INEXACT_EXC, FE_INEXACT,
104 "INEXACT");
bca973bc
UD
105#endif
106#ifdef FE_UNDERFLOW
107 test_single_exception (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
108 "UNDERFLOW");
109#endif
110#ifdef FE_OVERFLOW
111 test_single_exception (exception, OVERFLOW_EXC, FE_OVERFLOW,
112 "OVERFLOW");
113#endif
114}
115
762a2918
UD
116static void
117print_rounding (int rounding)
118{
119
120 switch (rounding) {
121#ifdef FE_TONEAREST
122 case FE_TONEAREST:
123 printf ("TONEAREST");
124 break;
125#endif
126#ifdef FE_UPWARD
127 case FE_UPWARD:
128 printf ("UPWARD");
129 break;
130#endif
131#ifdef FE_DOWNWARD
132 case FE_DOWNWARD:
133 printf ("DOWNWARD");
134 break;
135#endif
136#ifdef FE_TOWARDZERO
137 case FE_TOWARDZERO:
138 printf ("TOWARDZERO");
139 break;
140#endif
141 }
142 printf (".\n");
143}
144
145
146static void
147test_rounding (const char *test_name, int rounding_mode)
148{
149 int curr_rounding = fegetround ();
150
151 printf ("Test: %s\n", test_name);
152 if (curr_rounding == rounding_mode)
153 {
154 printf (" Pass: Rounding mode is ");
155 print_rounding (curr_rounding);
156 }
157 else {
158 ++count_errors;
159 printf (" Fail: Rounding mode is ");
160 print_rounding (curr_rounding);
161 }
162}
163
bca973bc
UD
164
165static void
166set_single_exc (const char *test_name, int fe_exc, fexcept_t exception)
167{
168 char str[200];
1522c368
UD
169 /* The standard allows the inexact exception to be set together with the
170 underflow and overflow exceptions. So ignore the inexact flag if the
171 others are raised. */
172 int ignore_inexact = (fe_exc & (UNDERFLOW_EXC | OVERFLOW_EXC)) != 0;
bca973bc
UD
173
174 strcpy (str, test_name);
175 strcat (str, ": set flag, with rest not set");
176 feclearexcept (FE_ALL_EXCEPT);
177 feraiseexcept (exception);
1522c368 178 test_exceptions (str, fe_exc, ignore_inexact);
bca973bc
UD
179
180 strcpy (str, test_name);
181 strcat (str, ": clear flag, rest also unset");
182 feclearexcept (exception);
1522c368 183 test_exceptions (str, NO_EXC, ignore_inexact);
bca973bc
UD
184
185 strcpy (str, test_name);
186 strcat (str, ": set flag, with rest set");
187 feraiseexcept (FE_ALL_EXCEPT ^ exception);
188 feraiseexcept (exception);
1522c368 189 test_exceptions (str, ALL_EXC, 0);
bca973bc
UD
190
191 strcpy (str, test_name);
192 strcat (str, ": clear flag, leave rest set");
193 feclearexcept (exception);
1522c368 194 test_exceptions (str, ALL_EXC ^ fe_exc, 0);
bca973bc
UD
195}
196
197static void
198fe_tests (void)
199{
200 /* clear all exceptions and test if all are cleared */
201 feclearexcept (FE_ALL_EXCEPT);
202 test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
1522c368 203 NO_EXC, 0);
bca973bc
UD
204
205 /* raise all exceptions and test if all are raised */
206 feraiseexcept (FE_ALL_EXCEPT);
207 test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
1522c368 208 ALL_EXC, 0);
bca973bc
UD
209 feclearexcept (FE_ALL_EXCEPT);
210
bca973bc
UD
211#ifdef FE_DIVBYZERO
212 set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC, FE_DIVBYZERO);
213#endif
214#ifdef FE_INVALID
215 set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC, FE_INVALID);
216#endif
217#ifdef FE_INEXACT
218 set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC, FE_INEXACT);
219#endif
220#ifdef FE_UNDERFLOW
221 set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC, FE_UNDERFLOW);
222#endif
223#ifdef FE_OVERFLOW
224 set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC, FE_OVERFLOW);
225#endif
226}
227
762a2918
UD
228/* Test that program aborts with no masked interrupts */
229static void
230feenv_nomask_test (const char *flag_name, int fe_exc)
231{
0413b54c 232#if defined FE_NOMASK_ENV
762a2918
UD
233 int status;
234 pid_t pid;
0413b54c
UD
235 fenv_t saved;
236
237 fegetenv (&saved);
238 errno = 0;
239 fesetenv (FE_NOMASK_ENV);
240 status = errno;
241 fesetenv (&saved);
242 if (status == ENOSYS)
243 {
244 printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n");
245 return;
246 }
762a2918
UD
247
248 printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n");
249 printf (" when feraiseexcept (%s) is called.\n", flag_name);
762a2918
UD
250 pid = fork ();
251 if (pid == 0)
252 {
74015205
UD
253#ifdef RLIMIT_CORE
254 /* Try to avoid dumping core. */
255 struct rlimit core_limit;
256 core_limit.rlim_cur = 0;
257 core_limit.rlim_max = 0;
258 setrlimit (RLIMIT_CORE, &core_limit);
259#endif
260
2d7da676 261 fesetenv (FE_NOMASK_ENV);
762a2918
UD
262 feraiseexcept (fe_exc);
263 exit (2);
264 }
265 else if (pid < 0)
266 {
267 if (errno != ENOSYS)
268 {
269 printf (" Fail: Could not fork.\n");
270 ++count_errors;
271 }
272 else
273 printf (" `fork' not implemented, test ignored.\n");
274 }
275 else {
276 if (waitpid (pid, &status, 0) != pid)
277 {
278 printf (" Fail: waitpid call failed.\n");
279 ++count_errors;
280 }
281 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
282 printf (" Pass: Process received SIGFPE.\n");
283 else
284 {
285 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
286 status);
287 ++count_errors;
288 }
289 }
0413b54c 290#endif
762a2918
UD
291}
292
293/* Test that program doesn't abort with default environment */
294static void
295feenv_mask_test (const char *flag_name, int fe_exc)
296{
297 int status;
298 pid_t pid;
299
300 printf ("Test: after fesetenv (FE_DFL_ENV) processes will not abort\n");
301 printf (" when feraiseexcept (%s) is called.\n", flag_name);
762a2918
UD
302 pid = fork ();
303 if (pid == 0)
304 {
74015205
UD
305#ifdef RLIMIT_CORE
306 /* Try to avoid dumping core. */
307 struct rlimit core_limit;
308 core_limit.rlim_cur = 0;
309 core_limit.rlim_max = 0;
310 setrlimit (RLIMIT_CORE, &core_limit);
311#endif
312
2d7da676 313 fesetenv (FE_DFL_ENV);
762a2918
UD
314 feraiseexcept (fe_exc);
315 exit (2);
316 }
317 else if (pid < 0)
318 {
319 if (errno != ENOSYS)
320 {
321 printf (" Fail: Could not fork.\n");
322 ++count_errors;
323 }
324 else
325 printf (" `fork' not implemented, test ignored.\n");
326 }
327 else {
328 if (waitpid (pid, &status, 0) != pid)
329 {
330 printf (" Fail: waitpid call failed.\n");
331 ++count_errors;
332 }
333 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
334 printf (" Pass: Process exited normally.\n");
335 else
336 {
337 printf (" Fail: Process exited abnormally with status %d.\n",
338 status);
339 ++count_errors;
340 }
341 }
342}
343
344
345
346static void
347feenv_tests (void)
348{
349
350#ifdef FE_DIVBYZERO
351 feenv_nomask_test ("FE_DIVBYZERO", FE_DIVBYZERO);
352 feenv_mask_test ("FE_DIVBYZERO", FE_DIVBYZERO);
353#endif
354#ifdef FE_INVALID
355 feenv_nomask_test ("FE_INVALID", FE_INVALID);
356 feenv_mask_test ("FE_INVALID", FE_INVALID);
357#endif
358#ifdef FE_INEXACT
359 feenv_nomask_test ("FE_INEXACT", FE_INEXACT);
360 feenv_mask_test ("FE_INEXACT", FE_INEXACT);
361#endif
362#ifdef FE_UNDERFLOW
363 feenv_nomask_test ("FE_UNDERFLOW", FE_UNDERFLOW);
364 feenv_mask_test ("FE_UNDERFLOW", FE_UNDERFLOW);
365#endif
366#ifdef FE_OVERFLOW
367 feenv_nomask_test ("FE_OVERFLOW", FE_OVERFLOW);
368 feenv_mask_test ("FE_OVERFLOW", FE_OVERFLOW);
369#endif
370 fesetenv (FE_DFL_ENV);
371}
372
373
374/* IEC 559 and ISO C 9X define a default startup environment */
375static void
376initial_tests (void)
377{
378 test_exceptions ("Initially all exceptions should be cleared",
1522c368 379 NO_EXC, 0);
762a2918
UD
380 test_rounding ("Rounding direction should be initalized to nearest",
381 FE_TONEAREST);
382}
383
bca973bc
UD
384int
385main (void)
386{
762a2918 387 initial_tests ();
bca973bc 388 fe_tests ();
762a2918 389 feenv_tests ();
bca973bc
UD
390
391 if (count_errors)
392 {
393 printf ("\n%d errors occured.\n", count_errors);
394 exit (1);
395 }
396 printf ("\n All tests passed successfully.\n");
397 exit (0);
398}