.
[glibc/history.git] / math / test-fenv.c
blob4b710d83f30d5232fb301f76a9172eda5ab7c02e
1 /* Copyright (C) 1997, 1998, 2000, 2001, 2003, 2007
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Andreas Jaeger <aj@suse.de> and
5 Ulrich Drepper <drepper@cygnus.com>, 1997.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
22 /* Tests for ISO C99 7.6: Floating-point environment */
24 #ifndef _GNU_SOURCE
25 # define _GNU_SOURCE
26 #endif
28 #include <complex.h>
29 #include <math.h>
30 #include <float.h>
31 #include <fenv.h>
33 #include <errno.h>
34 #include <signal.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <sys/wait.h>
40 #include <sys/resource.h>
43 Since not all architectures might define all exceptions, we define
44 a private set and map accordingly.
46 #define NO_EXC 0
47 #define INEXACT_EXC 0x1
48 #define DIVBYZERO_EXC 0x2
49 #define UNDERFLOW_EXC 0x04
50 #define OVERFLOW_EXC 0x08
51 #define INVALID_EXC 0x10
52 #define ALL_EXC \
53 (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC | \
54 INVALID_EXC)
56 static int count_errors;
58 /* Test whether a given exception was raised. */
59 static void
60 test_single_exception (short int exception,
61 short int exc_flag,
62 fexcept_t fe_flag,
63 const char *flag_name)
65 if (exception & exc_flag)
67 if (fetestexcept (fe_flag))
68 printf (" Pass: Exception \"%s\" is set\n", flag_name);
69 else
71 printf (" Fail: Exception \"%s\" is not set\n", flag_name);
72 ++count_errors;
75 else
77 if (fetestexcept (fe_flag))
79 printf (" Fail: Exception \"%s\" is set\n", flag_name);
80 ++count_errors;
82 else
84 printf (" Pass: Exception \"%s\" is not set\n", flag_name);
89 static void
90 test_exceptions (const char *test_name, short int exception,
91 int ignore_inexact)
93 printf ("Test: %s\n", test_name);
94 #ifdef FE_DIVBYZERO
95 test_single_exception (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
96 "DIVBYZERO");
97 #endif
98 #ifdef FE_INVALID
99 test_single_exception (exception, INVALID_EXC, FE_INVALID,
100 "INVALID");
101 #endif
102 #ifdef FE_INEXACT
103 if (!ignore_inexact)
104 test_single_exception (exception, INEXACT_EXC, FE_INEXACT,
105 "INEXACT");
106 #endif
107 #ifdef FE_UNDERFLOW
108 test_single_exception (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
109 "UNDERFLOW");
110 #endif
111 #ifdef FE_OVERFLOW
112 test_single_exception (exception, OVERFLOW_EXC, FE_OVERFLOW,
113 "OVERFLOW");
114 #endif
117 static void
118 print_rounding (int rounding)
121 switch (rounding)
123 #ifdef FE_TONEAREST
124 case FE_TONEAREST:
125 printf ("TONEAREST");
126 break;
127 #endif
128 #ifdef FE_UPWARD
129 case FE_UPWARD:
130 printf ("UPWARD");
131 break;
132 #endif
133 #ifdef FE_DOWNWARD
134 case FE_DOWNWARD:
135 printf ("DOWNWARD");
136 break;
137 #endif
138 #ifdef FE_TOWARDZERO
139 case FE_TOWARDZERO:
140 printf ("TOWARDZERO");
141 break;
142 #endif
144 printf (".\n");
148 static void
149 test_rounding (const char *test_name, int rounding_mode)
151 int curr_rounding = fegetround ();
153 printf ("Test: %s\n", test_name);
154 if (curr_rounding == rounding_mode)
156 printf (" Pass: Rounding mode is ");
157 print_rounding (curr_rounding);
159 else
161 ++count_errors;
162 printf (" Fail: Rounding mode is ");
163 print_rounding (curr_rounding);
168 static void
169 set_single_exc (const char *test_name, int fe_exc, fexcept_t exception)
171 char str[200];
172 /* The standard allows the inexact exception to be set together with the
173 underflow and overflow exceptions. So ignore the inexact flag if the
174 others are raised. */
175 int ignore_inexact = (fe_exc & (UNDERFLOW_EXC | OVERFLOW_EXC)) != 0;
177 strcpy (str, test_name);
178 strcat (str, ": set flag, with rest not set");
179 feclearexcept (FE_ALL_EXCEPT);
180 feraiseexcept (exception);
181 test_exceptions (str, fe_exc, ignore_inexact);
183 strcpy (str, test_name);
184 strcat (str, ": clear flag, rest also unset");
185 feclearexcept (exception);
186 test_exceptions (str, NO_EXC, ignore_inexact);
188 strcpy (str, test_name);
189 strcat (str, ": set flag, with rest set");
190 feraiseexcept (FE_ALL_EXCEPT ^ exception);
191 feraiseexcept (exception);
192 test_exceptions (str, ALL_EXC, 0);
194 strcpy (str, test_name);
195 strcat (str, ": clear flag, leave rest set");
196 feclearexcept (exception);
197 test_exceptions (str, ALL_EXC ^ fe_exc, 0);
200 static void
201 fe_tests (void)
203 /* clear all exceptions and test if all are cleared */
204 feclearexcept (FE_ALL_EXCEPT);
205 test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
206 NO_EXC, 0);
208 /* raise all exceptions and test if all are raised */
209 feraiseexcept (FE_ALL_EXCEPT);
210 test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
211 ALL_EXC, 0);
212 feclearexcept (FE_ALL_EXCEPT);
214 #ifdef FE_DIVBYZERO
215 set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC, FE_DIVBYZERO);
216 #endif
217 #ifdef FE_INVALID
218 set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC, FE_INVALID);
219 #endif
220 #ifdef FE_INEXACT
221 set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC, FE_INEXACT);
222 #endif
223 #ifdef FE_UNDERFLOW
224 set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC, FE_UNDERFLOW);
225 #endif
226 #ifdef FE_OVERFLOW
227 set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC, FE_OVERFLOW);
228 #endif
231 /* Test that program aborts with no masked interrupts */
232 static void
233 feenv_nomask_test (const char *flag_name, int fe_exc)
235 #if defined FE_NOMASK_ENV
236 int status;
237 pid_t pid;
238 fenv_t saved;
240 fegetenv (&saved);
241 errno = 0;
242 fesetenv (FE_NOMASK_ENV);
243 status = errno;
244 fesetenv (&saved);
245 if (status == ENOSYS)
247 printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n");
248 return;
251 printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n");
252 printf (" when feraiseexcept (%s) is called.\n", flag_name);
253 pid = fork ();
254 if (pid == 0)
256 #ifdef RLIMIT_CORE
257 /* Try to avoid dumping core. */
258 struct rlimit core_limit;
259 core_limit.rlim_cur = 0;
260 core_limit.rlim_max = 0;
261 setrlimit (RLIMIT_CORE, &core_limit);
262 #endif
264 fesetenv (FE_NOMASK_ENV);
265 feraiseexcept (fe_exc);
266 exit (2);
268 else if (pid < 0)
270 if (errno != ENOSYS)
272 printf (" Fail: Could not fork.\n");
273 ++count_errors;
275 else
276 printf (" `fork' not implemented, test ignored.\n");
278 else {
279 if (waitpid (pid, &status, 0) != pid)
281 printf (" Fail: waitpid call failed.\n");
282 ++count_errors;
284 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
285 printf (" Pass: Process received SIGFPE.\n");
286 else
288 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
289 status);
290 ++count_errors;
293 #endif
296 /* Test that program doesn't abort with default environment */
297 static void
298 feenv_mask_test (const char *flag_name, int fe_exc)
300 int status;
301 pid_t pid;
303 printf ("Test: after fesetenv (FE_DFL_ENV) processes will not abort\n");
304 printf (" when feraiseexcept (%s) is called.\n", flag_name);
305 pid = fork ();
306 if (pid == 0)
308 #ifdef RLIMIT_CORE
309 /* Try to avoid dumping core. */
310 struct rlimit core_limit;
311 core_limit.rlim_cur = 0;
312 core_limit.rlim_max = 0;
313 setrlimit (RLIMIT_CORE, &core_limit);
314 #endif
316 fesetenv (FE_DFL_ENV);
317 feraiseexcept (fe_exc);
318 exit (2);
320 else if (pid < 0)
322 if (errno != ENOSYS)
324 printf (" Fail: Could not fork.\n");
325 ++count_errors;
327 else
328 printf (" `fork' not implemented, test ignored.\n");
330 else {
331 if (waitpid (pid, &status, 0) != pid)
333 printf (" Fail: waitpid call failed.\n");
334 ++count_errors;
336 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
337 printf (" Pass: Process exited normally.\n");
338 else
340 printf (" Fail: Process exited abnormally with status %d.\n",
341 status);
342 ++count_errors;
347 /* Test that program aborts with no masked interrupts */
348 static void
349 feexcp_nomask_test (const char *flag_name, int fe_exc)
351 int status;
352 pid_t pid;
354 printf ("Test: after fedisableexcept (%s) processes will abort\n",
355 flag_name);
356 printf (" when feraiseexcept (%s) is called.\n", flag_name);
357 pid = fork ();
358 if (pid == 0)
360 #ifdef RLIMIT_CORE
361 /* Try to avoid dumping core. */
362 struct rlimit core_limit;
363 core_limit.rlim_cur = 0;
364 core_limit.rlim_max = 0;
365 setrlimit (RLIMIT_CORE, &core_limit);
366 #endif
368 fedisableexcept (FE_ALL_EXCEPT);
369 feenableexcept (fe_exc);
370 feraiseexcept (fe_exc);
371 exit (2);
373 else if (pid < 0)
375 if (errno != ENOSYS)
377 printf (" Fail: Could not fork.\n");
378 ++count_errors;
380 else
381 printf (" `fork' not implemented, test ignored.\n");
383 else {
384 if (waitpid (pid, &status, 0) != pid)
386 printf (" Fail: waitpid call failed.\n");
387 ++count_errors;
389 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
390 printf (" Pass: Process received SIGFPE.\n");
391 else
393 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
394 status);
395 ++count_errors;
400 /* Test that program doesn't abort with exception. */
401 static void
402 feexcp_mask_test (const char *flag_name, int fe_exc)
404 int status;
405 int exception;
406 pid_t pid;
408 printf ("Test: after fedisableexcept (%s) processes will not abort\n",
409 flag_name);
410 printf (" when feraiseexcept (%s) is called.\n", flag_name);
411 pid = fork ();
412 if (pid == 0)
414 #ifdef RLIMIT_CORE
415 /* Try to avoid dumping core. */
416 struct rlimit core_limit;
417 core_limit.rlim_cur = 0;
418 core_limit.rlim_max = 0;
419 setrlimit (RLIMIT_CORE, &core_limit);
420 #endif
421 feenableexcept (FE_ALL_EXCEPT);
422 exception = fe_exc;
423 #ifdef FE_INEXACT
424 /* The standard allows the inexact exception to be set together with the
425 underflow and overflow exceptions. So add FE_INEXACT to the set of
426 exceptions to be disabled if we will be raising underflow or
427 overflow. */
428 # ifdef FE_OVERFLOW
429 if (fe_exc & FE_OVERFLOW)
430 exception |= FE_INEXACT;
431 # endif
432 # ifdef FE_UNDERFLOW
433 if (fe_exc & FE_UNDERFLOW)
434 exception |= FE_INEXACT;
435 # endif
436 #endif
437 fedisableexcept (exception);
438 feraiseexcept (fe_exc);
439 exit (2);
441 else if (pid < 0)
443 if (errno != ENOSYS)
445 printf (" Fail: Could not fork.\n");
446 ++count_errors;
448 else
449 printf (" `fork' not implemented, test ignored.\n");
451 else {
452 if (waitpid (pid, &status, 0) != pid)
454 printf (" Fail: waitpid call failed.\n");
455 ++count_errors;
457 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
458 printf (" Pass: Process exited normally.\n");
459 else
461 printf (" Fail: Process exited abnormally with status %d.\n",
462 status);
463 ++count_errors;
469 /* Tests for feenableexcept/fedisableexcept/fegetexcept. */
470 static void
471 feenable_test (const char *flag_name, int fe_exc)
473 int excepts;
476 printf ("Tests for feenableexcepts etc. with flag %s\n", flag_name);
478 /* First disable all exceptions. */
479 if (fedisableexcept (FE_ALL_EXCEPT) == -1)
481 printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n");
482 ++count_errors;
483 /* If this fails, the other tests don't make sense. */
484 return;
486 excepts = fegetexcept ();
487 if (excepts != 0)
489 printf ("Test: fegetexcept (%s) failed, return should be 0, is %d\n",
490 flag_name, excepts);
491 ++count_errors;
494 excepts = feenableexcept (fe_exc);
495 if (excepts == -1)
497 printf ("Test: feenableexcept (%s) failed\n", flag_name);
498 ++count_errors;
499 return;
501 if (excepts != 0)
503 printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
504 flag_name, excepts);
505 ++count_errors;
508 excepts = fegetexcept ();
509 if (excepts != fe_exc)
511 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
512 flag_name, fe_exc, excepts);
513 ++count_errors;
516 /* And now disable the exception again. */
517 excepts = fedisableexcept (fe_exc);
518 if (excepts == -1)
520 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
521 ++count_errors;
522 return;
524 if (excepts != fe_exc)
526 printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
527 flag_name, fe_exc, excepts);
528 ++count_errors;
531 excepts = fegetexcept ();
532 if (excepts != 0)
534 printf ("Test: fegetexcept (%s) failed, return should be 0, is 0x%x\n",
535 flag_name, excepts);
536 ++count_errors;
539 /* Now the other way round: Enable all exceptions and disable just this one. */
540 if (feenableexcept (FE_ALL_EXCEPT) == -1)
542 printf ("Test: feenableexcept (FE_ALL_EXCEPT) failed\n");
543 ++count_errors;
544 /* If this fails, the other tests don't make sense. */
545 return;
548 excepts = fegetexcept ();
549 if (excepts != FE_ALL_EXCEPT)
551 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
552 flag_name, FE_ALL_EXCEPT, excepts);
553 ++count_errors;
556 excepts = fedisableexcept (fe_exc);
557 if (excepts == -1)
559 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
560 ++count_errors;
561 return;
563 if (excepts != FE_ALL_EXCEPT)
565 printf ("Test: fedisableexcept (%s) failed, return should be 0, is 0x%x\n",
566 flag_name, excepts);
567 ++count_errors;
570 excepts = fegetexcept ();
571 if (excepts != (FE_ALL_EXCEPT & ~fe_exc))
573 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
574 flag_name, (FE_ALL_EXCEPT & ~fe_exc), excepts);
575 ++count_errors;
578 /* And now enable the exception again. */
579 excepts = feenableexcept (fe_exc);
580 if (excepts == -1)
582 printf ("Test: feenableexcept (%s) failed\n", flag_name);
583 ++count_errors;
584 return;
586 if (excepts != (FE_ALL_EXCEPT & ~fe_exc))
588 printf ("Test: feenableexcept (%s) failed, return should be 0, is 0x%x\n",
589 flag_name, excepts);
590 ++count_errors;
593 excepts = fegetexcept ();
594 if (excepts != FE_ALL_EXCEPT)
596 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
597 flag_name, FE_ALL_EXCEPT, excepts);
598 ++count_errors;
600 feexcp_nomask_test (flag_name, fe_exc);
601 feexcp_mask_test (flag_name, fe_exc);
606 static void
607 fe_single_test (const char *flag_name, int fe_exc)
609 feenv_nomask_test (flag_name, fe_exc);
610 feenv_mask_test (flag_name, fe_exc);
611 feenable_test (flag_name, fe_exc);
615 static void
616 feenv_tests (void)
618 /* We might have some exceptions still set. */
619 feclearexcept (FE_ALL_EXCEPT);
621 #ifdef FE_DIVBYZERO
622 fe_single_test ("FE_DIVBYZERO", FE_DIVBYZERO);
623 #endif
624 #ifdef FE_INVALID
625 fe_single_test ("FE_INVALID", FE_INVALID);
626 #endif
627 #ifdef FE_INEXACT
628 fe_single_test ("FE_INEXACT", FE_INEXACT);
629 #endif
630 #ifdef FE_UNDERFLOW
631 fe_single_test ("FE_UNDERFLOW", FE_UNDERFLOW);
632 #endif
633 #ifdef FE_OVERFLOW
634 fe_single_test ("FE_OVERFLOW", FE_OVERFLOW);
635 #endif
636 fesetenv (FE_DFL_ENV);
640 static void
641 feholdexcept_tests (void)
643 fenv_t saved, saved2;
644 int res;
646 feclearexcept (FE_ALL_EXCEPT);
647 fedisableexcept (FE_ALL_EXCEPT);
648 #ifdef FE_DIVBYZERO
649 feraiseexcept (FE_DIVBYZERO);
650 #endif
651 test_exceptions ("feholdexcept_tests FE_DIVBYZERO test",
652 DIVBYZERO_EXC, 0);
653 res = feholdexcept (&saved);
654 if (res != 0)
656 printf ("feholdexcept failed: %d\n", res);
657 ++count_errors;
659 #if defined FE_TONEAREST && defined FE_TOWARDZERO
660 res = fesetround (FE_TOWARDZERO);
661 if (res != 0)
663 printf ("fesetround failed: %d\n", res);
664 ++count_errors;
666 #endif
667 test_exceptions ("feholdexcept_tests 0 test", NO_EXC, 0);
668 feraiseexcept (FE_INVALID);
669 test_exceptions ("feholdexcept_tests FE_INVALID test",
670 INVALID_EXC, 0);
671 res = feupdateenv (&saved);
672 if (res != 0)
674 printf ("feupdateenv failed: %d\n", res);
675 ++count_errors;
677 #if defined FE_TONEAREST && defined FE_TOWARDZERO
678 res = fegetround ();
679 if (res != FE_TONEAREST)
681 printf ("feupdateenv didn't restore rounding mode: %d\n", res);
682 ++count_errors;
684 #endif
685 test_exceptions ("feholdexcept_tests FE_DIVBYZERO|FE_INVALID test",
686 DIVBYZERO_EXC | INVALID_EXC, 0);
687 feclearexcept (FE_ALL_EXCEPT);
688 feraiseexcept (FE_INVALID);
689 #if defined FE_TONEAREST && defined FE_UPWARD
690 res = fesetround (FE_UPWARD);
691 if (res != 0)
693 printf ("fesetround failed: %d\n", res);
694 ++count_errors;
696 #endif
697 res = feholdexcept (&saved2);
698 if (res != 0)
700 printf ("feholdexcept failed: %d\n", res);
701 ++count_errors;
703 #if defined FE_TONEAREST && defined FE_UPWARD
704 res = fesetround (FE_TONEAREST);
705 if (res != 0)
707 printf ("fesetround failed: %d\n", res);
708 ++count_errors;
710 #endif
711 test_exceptions ("feholdexcept_tests 0 2nd test", NO_EXC, 0);
712 feraiseexcept (FE_INEXACT);
713 test_exceptions ("feholdexcept_tests FE_INEXACT test",
714 INEXACT_EXC, 0);
715 res = feupdateenv (&saved2);
716 if (res != 0)
718 printf ("feupdateenv failed: %d\n", res);
719 ++count_errors;
721 #if defined FE_TONEAREST && defined FE_UPWARD
722 res = fegetround ();
723 if (res != FE_UPWARD)
725 printf ("feupdateenv didn't restore rounding mode: %d\n", res);
726 ++count_errors;
728 fesetround (FE_TONEAREST);
729 #endif
730 test_exceptions ("feholdexcept_tests FE_INEXACT|FE_INVALID test",
731 INVALID_EXC | INEXACT_EXC, 0);
732 feclearexcept (FE_ALL_EXCEPT);
736 /* IEC 559 and ISO C99 define a default startup environment */
737 static void
738 initial_tests (void)
740 test_exceptions ("Initially all exceptions should be cleared",
741 NO_EXC, 0);
742 #ifdef FE_TONEAREST
743 test_rounding ("Rounding direction should be initalized to nearest",
744 FE_TONEAREST);
745 #endif
749 main (void)
751 initial_tests ();
752 fe_tests ();
753 feenv_tests ();
754 feholdexcept_tests ();
756 if (count_errors)
758 printf ("\n%d errors occurred.\n", count_errors);
759 exit (1);
761 printf ("\n All tests passed successfully.\n");
762 return 0;