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, see
19 <http://www.gnu.org/licenses/>. */
21 /* Tests for ISO C99 7.6: Floating-point environment */
39 #include <sys/resource.h>
42 Since not all architectures might define all exceptions, we define
43 a private set and map accordingly.
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
52 (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC | \
55 static int count_errors;
57 /* Test whether a given exception was raised. */
59 test_single_exception (short int exception,
62 const char *flag_name)
64 if (exception & exc_flag)
66 if (fetestexcept (fe_flag))
67 printf (" Pass: Exception \"%s\" is set\n", flag_name);
70 printf (" Fail: Exception \"%s\" is not set\n", flag_name);
76 if (fetestexcept (fe_flag))
78 printf (" Fail: Exception \"%s\" is set\n", flag_name);
83 printf (" Pass: Exception \"%s\" is not set\n", flag_name);
89 test_exceptions (const char *test_name, short int exception,
92 printf ("Test: %s\n", test_name);
94 test_single_exception (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
98 test_single_exception (exception, INVALID_EXC, FE_INVALID,
103 test_single_exception (exception, INEXACT_EXC, FE_INEXACT,
107 test_single_exception (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
111 test_single_exception (exception, OVERFLOW_EXC, FE_OVERFLOW,
117 print_rounding (int rounding)
124 printf ("TONEAREST");
139 printf ("TOWARDZERO");
148 test_rounding (const char *test_name, int rounding_mode)
150 int curr_rounding = fegetround ();
152 printf ("Test: %s\n", test_name);
153 if (curr_rounding == rounding_mode)
155 printf (" Pass: Rounding mode is ");
156 print_rounding (curr_rounding);
161 printf (" Fail: Rounding mode is ");
162 print_rounding (curr_rounding);
168 set_single_exc (const char *test_name, int fe_exc, fexcept_t exception)
171 /* The standard allows the inexact exception to be set together with the
172 underflow and overflow exceptions. So ignore the inexact flag if the
173 others are raised. */
174 int ignore_inexact = (fe_exc & (UNDERFLOW_EXC | OVERFLOW_EXC)) != 0;
176 strcpy (str, test_name);
177 strcat (str, ": set flag, with rest not set");
178 feclearexcept (FE_ALL_EXCEPT);
179 feraiseexcept (exception);
180 test_exceptions (str, fe_exc, ignore_inexact);
182 strcpy (str, test_name);
183 strcat (str, ": clear flag, rest also unset");
184 feclearexcept (exception);
185 test_exceptions (str, NO_EXC, ignore_inexact);
187 strcpy (str, test_name);
188 strcat (str, ": set flag, with rest set");
189 feraiseexcept (FE_ALL_EXCEPT ^ exception);
190 feraiseexcept (exception);
191 test_exceptions (str, ALL_EXC, 0);
193 strcpy (str, test_name);
194 strcat (str, ": clear flag, leave rest set");
195 feclearexcept (exception);
196 test_exceptions (str, ALL_EXC ^ fe_exc, 0);
202 /* clear all exceptions and test if all are cleared */
203 feclearexcept (FE_ALL_EXCEPT);
204 test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
207 /* raise all exceptions and test if all are raised */
208 feraiseexcept (FE_ALL_EXCEPT);
209 test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
211 feclearexcept (FE_ALL_EXCEPT);
214 set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC, FE_DIVBYZERO);
217 set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC, FE_INVALID);
220 set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC, FE_INEXACT);
223 set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC, FE_UNDERFLOW);
226 set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC, FE_OVERFLOW);
230 /* Test that program aborts with no masked interrupts */
232 feenv_nomask_test (const char *flag_name, int fe_exc)
234 #if defined FE_NOMASK_ENV
241 fesetenv (FE_NOMASK_ENV);
244 if (status == ENOSYS)
246 printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n");
250 printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n");
251 printf (" when feraiseexcept (%s) is called.\n", flag_name);
256 /* Try to avoid dumping core. */
257 struct rlimit core_limit;
258 core_limit.rlim_cur = 0;
259 core_limit.rlim_max = 0;
260 setrlimit (RLIMIT_CORE, &core_limit);
263 fesetenv (FE_NOMASK_ENV);
264 feraiseexcept (fe_exc);
271 printf (" Fail: Could not fork.\n");
275 printf (" `fork' not implemented, test ignored.\n");
278 if (waitpid (pid, &status, 0) != pid)
280 printf (" Fail: waitpid call failed.\n");
283 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
284 printf (" Pass: Process received SIGFPE.\n");
287 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
295 /* Test that program doesn't abort with default environment */
297 feenv_mask_test (const char *flag_name, int fe_exc)
302 printf ("Test: after fesetenv (FE_DFL_ENV) processes will not abort\n");
303 printf (" when feraiseexcept (%s) is called.\n", flag_name);
308 /* Try to avoid dumping core. */
309 struct rlimit core_limit;
310 core_limit.rlim_cur = 0;
311 core_limit.rlim_max = 0;
312 setrlimit (RLIMIT_CORE, &core_limit);
315 fesetenv (FE_DFL_ENV);
316 feraiseexcept (fe_exc);
323 printf (" Fail: Could not fork.\n");
327 printf (" `fork' not implemented, test ignored.\n");
330 if (waitpid (pid, &status, 0) != pid)
332 printf (" Fail: waitpid call failed.\n");
335 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
336 printf (" Pass: Process exited normally.\n");
339 printf (" Fail: Process exited abnormally with status %d.\n",
346 /* Test that program aborts with no masked interrupts */
348 feexcp_nomask_test (const char *flag_name, int fe_exc)
353 printf ("Test: after fedisableexcept (%s) processes will abort\n",
355 printf (" when feraiseexcept (%s) is called.\n", flag_name);
360 /* Try to avoid dumping core. */
361 struct rlimit core_limit;
362 core_limit.rlim_cur = 0;
363 core_limit.rlim_max = 0;
364 setrlimit (RLIMIT_CORE, &core_limit);
367 fedisableexcept (FE_ALL_EXCEPT);
368 feenableexcept (fe_exc);
369 feraiseexcept (fe_exc);
376 printf (" Fail: Could not fork.\n");
380 printf (" `fork' not implemented, test ignored.\n");
383 if (waitpid (pid, &status, 0) != pid)
385 printf (" Fail: waitpid call failed.\n");
388 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
389 printf (" Pass: Process received SIGFPE.\n");
392 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
399 /* Test that program doesn't abort with exception. */
401 feexcp_mask_test (const char *flag_name, int fe_exc)
407 printf ("Test: after fedisableexcept (%s) processes will not abort\n",
409 printf (" when feraiseexcept (%s) is called.\n", flag_name);
414 /* Try to avoid dumping core. */
415 struct rlimit core_limit;
416 core_limit.rlim_cur = 0;
417 core_limit.rlim_max = 0;
418 setrlimit (RLIMIT_CORE, &core_limit);
420 feenableexcept (FE_ALL_EXCEPT);
423 /* The standard allows the inexact exception to be set together with the
424 underflow and overflow exceptions. So add FE_INEXACT to the set of
425 exceptions to be disabled if we will be raising underflow or
428 if (fe_exc & FE_OVERFLOW)
429 exception |= FE_INEXACT;
432 if (fe_exc & FE_UNDERFLOW)
433 exception |= FE_INEXACT;
436 fedisableexcept (exception);
437 feraiseexcept (fe_exc);
444 printf (" Fail: Could not fork.\n");
448 printf (" `fork' not implemented, test ignored.\n");
451 if (waitpid (pid, &status, 0) != pid)
453 printf (" Fail: waitpid call failed.\n");
456 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
457 printf (" Pass: Process exited normally.\n");
460 printf (" Fail: Process exited abnormally with status %d.\n",
468 /* Tests for feenableexcept/fedisableexcept/fegetexcept. */
470 feenable_test (const char *flag_name, int fe_exc)
475 printf ("Tests for feenableexcepts etc. with flag %s\n", flag_name);
477 /* First disable all exceptions. */
478 if (fedisableexcept (FE_ALL_EXCEPT) == -1)
480 printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n");
482 /* If this fails, the other tests don't make sense. */
485 excepts = fegetexcept ();
488 printf ("Test: fegetexcept (%s) failed, return should be 0, is %d\n",
493 excepts = feenableexcept (fe_exc);
496 printf ("Test: feenableexcept (%s) failed\n", flag_name);
502 printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
507 excepts = fegetexcept ();
508 if (excepts != fe_exc)
510 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
511 flag_name, fe_exc, excepts);
515 /* And now disable the exception again. */
516 excepts = fedisableexcept (fe_exc);
519 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
523 if (excepts != fe_exc)
525 printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
526 flag_name, fe_exc, excepts);
530 excepts = fegetexcept ();
533 printf ("Test: fegetexcept (%s) failed, return should be 0, is 0x%x\n",
538 /* Now the other way round: Enable all exceptions and disable just this one. */
539 if (feenableexcept (FE_ALL_EXCEPT) == -1)
541 printf ("Test: feenableexcept (FE_ALL_EXCEPT) failed\n");
543 /* If this fails, the other tests don't make sense. */
547 excepts = fegetexcept ();
548 if (excepts != FE_ALL_EXCEPT)
550 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
551 flag_name, FE_ALL_EXCEPT, excepts);
555 excepts = fedisableexcept (fe_exc);
558 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
562 if (excepts != FE_ALL_EXCEPT)
564 printf ("Test: fedisableexcept (%s) failed, return should be 0, is 0x%x\n",
569 excepts = fegetexcept ();
570 if (excepts != (FE_ALL_EXCEPT & ~fe_exc))
572 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
573 flag_name, (FE_ALL_EXCEPT & ~fe_exc), excepts);
577 /* And now enable the exception again. */
578 excepts = feenableexcept (fe_exc);
581 printf ("Test: feenableexcept (%s) failed\n", flag_name);
585 if (excepts != (FE_ALL_EXCEPT & ~fe_exc))
587 printf ("Test: feenableexcept (%s) failed, return should be 0, is 0x%x\n",
592 excepts = fegetexcept ();
593 if (excepts != FE_ALL_EXCEPT)
595 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
596 flag_name, FE_ALL_EXCEPT, excepts);
599 feexcp_nomask_test (flag_name, fe_exc);
600 feexcp_mask_test (flag_name, fe_exc);
606 fe_single_test (const char *flag_name, int fe_exc)
608 feenv_nomask_test (flag_name, fe_exc);
609 feenv_mask_test (flag_name, fe_exc);
610 feenable_test (flag_name, fe_exc);
617 /* We might have some exceptions still set. */
618 feclearexcept (FE_ALL_EXCEPT);
621 fe_single_test ("FE_DIVBYZERO", FE_DIVBYZERO);
624 fe_single_test ("FE_INVALID", FE_INVALID);
627 fe_single_test ("FE_INEXACT", FE_INEXACT);
630 fe_single_test ("FE_UNDERFLOW", FE_UNDERFLOW);
633 fe_single_test ("FE_OVERFLOW", FE_OVERFLOW);
635 fesetenv (FE_DFL_ENV);
640 feholdexcept_tests (void)
642 fenv_t saved, saved2;
645 feclearexcept (FE_ALL_EXCEPT);
646 fedisableexcept (FE_ALL_EXCEPT);
648 feraiseexcept (FE_DIVBYZERO);
650 test_exceptions ("feholdexcept_tests FE_DIVBYZERO test",
652 res = feholdexcept (&saved);
655 printf ("feholdexcept failed: %d\n", res);
658 #if defined FE_TONEAREST && defined FE_TOWARDZERO
659 res = fesetround (FE_TOWARDZERO);
662 printf ("fesetround failed: %d\n", res);
666 test_exceptions ("feholdexcept_tests 0 test", NO_EXC, 0);
668 feraiseexcept (FE_INVALID);
669 test_exceptions ("feholdexcept_tests FE_INVALID test",
672 res = feupdateenv (&saved);
675 printf ("feupdateenv failed: %d\n", res);
678 #if defined FE_TONEAREST && defined FE_TOWARDZERO
680 if (res != FE_TONEAREST)
682 printf ("feupdateenv didn't restore rounding mode: %d\n", res);
686 test_exceptions ("feholdexcept_tests FE_DIVBYZERO|FE_INVALID test",
687 DIVBYZERO_EXC | INVALID_EXC, 0);
688 feclearexcept (FE_ALL_EXCEPT);
690 feraiseexcept (FE_INVALID);
692 #if defined FE_TONEAREST && defined FE_UPWARD
693 res = fesetround (FE_UPWARD);
696 printf ("fesetround failed: %d\n", res);
700 res = feholdexcept (&saved2);
703 printf ("feholdexcept failed: %d\n", res);
706 #if defined FE_TONEAREST && defined FE_UPWARD
707 res = fesetround (FE_TONEAREST);
710 printf ("fesetround failed: %d\n", res);
714 test_exceptions ("feholdexcept_tests 0 2nd test", NO_EXC, 0);
716 feraiseexcept (FE_INEXACT);
717 test_exceptions ("feholdexcept_tests FE_INEXACT test",
720 res = feupdateenv (&saved2);
723 printf ("feupdateenv failed: %d\n", res);
726 #if defined FE_TONEAREST && defined FE_UPWARD
728 if (res != FE_UPWARD)
730 printf ("feupdateenv didn't restore rounding mode: %d\n", res);
733 fesetround (FE_TONEAREST);
735 test_exceptions ("feholdexcept_tests FE_INEXACT|FE_INVALID test",
736 INVALID_EXC | INEXACT_EXC, 0);
737 feclearexcept (FE_ALL_EXCEPT);
741 /* IEC 559 and ISO C99 define a default startup environment */
745 test_exceptions ("Initially all exceptions should be cleared",
748 test_rounding ("Rounding direction should be initalized to nearest",
759 feholdexcept_tests ();
763 printf ("\n%d errors occurred.\n", count_errors);
766 printf ("\n All tests passed successfully.\n");