1 /* Copyright (C) 1997-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 /* Tests for ISO C99 7.6: Floating-point environment */
36 #include <sys/resource.h>
37 #include <math-tests.h>
40 Since not all architectures might define all exceptions, we define
41 a private set and map accordingly.
44 #define INEXACT_EXC 0x1
45 #define DIVBYZERO_EXC 0x2
46 #define UNDERFLOW_EXC 0x04
47 #define OVERFLOW_EXC 0x08
48 #define INVALID_EXC 0x10
50 (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC \
53 static int count_errors
;
56 /* Test whether a given exception was raised. */
58 test_single_exception (short int exception
,
61 const char *flag_name
)
63 if (exception
& exc_flag
)
65 if (fetestexcept (fe_flag
))
66 printf (" Pass: Exception \"%s\" is set\n", flag_name
);
69 printf (" Fail: Exception \"%s\" is not set\n", flag_name
);
75 if (fetestexcept (fe_flag
))
77 printf (" Fail: Exception \"%s\" is set\n", flag_name
);
82 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
);
169 set_single_exc (const char *test_name
, int fe_exc
, fexcept_t exception
)
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);
201 update_single_exc (const char *test_name
, const fenv_t
*envp
, int fe_exc
,
202 int fe_exc_clear
, int exception
)
205 /* The standard allows the inexact exception to be set together with the
206 underflow and overflow exceptions. So ignore the inexact flag if the
207 others are raised. */
208 int ignore_inexact
= (fe_exc
& (UNDERFLOW_EXC
| OVERFLOW_EXC
)) != 0;
210 strcpy (str
, test_name
);
211 strcat (str
, ": set flag, with rest not set");
212 feclearexcept (FE_ALL_EXCEPT
);
213 feraiseexcept (exception
);
215 test_exceptions (str
, fe_exc
, ignore_inexact
);
217 strcpy (str
, test_name
);
218 strcat (str
, ": clear flag, rest also unset");
219 feclearexcept (exception
);
221 test_exceptions (str
, fe_exc_clear
, ignore_inexact
);
228 /* clear all exceptions and test if all are cleared */
229 feclearexcept (FE_ALL_EXCEPT
);
230 test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
233 /* Skip further tests here if exceptions not supported. */
234 if (!EXCEPTION_TESTS (float) && FE_ALL_EXCEPT
!= 0)
236 /* raise all exceptions and test if all are raised */
237 feraiseexcept (FE_ALL_EXCEPT
);
238 test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
240 feclearexcept (FE_ALL_EXCEPT
);
243 set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC
, FE_DIVBYZERO
);
246 set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC
, FE_INVALID
);
249 set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC
, FE_INEXACT
);
252 set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC
, FE_UNDERFLOW
);
255 set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC
, FE_OVERFLOW
);
261 funcname (int (*func
)(const fenv_t
*))
263 if (func
== fesetenv
)
265 else if (func
== feupdateenv
)
266 return "feupdateenv";
267 __builtin_unreachable ();
270 /* Test that program aborts with no masked interrupts */
272 feenv_nomask_test (const char *flag_name
, int fe_exc
, int (*func
)(const fenv_t
*))
274 # if defined FE_NOMASK_ENV
278 if (!EXCEPTION_ENABLE_SUPPORTED (FE_ALL_EXCEPT
)
279 && func (FE_NOMASK_ENV
) != 0)
281 printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n");
285 printf ("Test: after %s (FE_NOMASK_ENV) processes will abort\n", funcname (func
));
286 printf (" when feraiseexcept (%s) is called.\n", flag_name
);
291 /* Try to avoid dumping core. */
292 struct rlimit core_limit
;
293 core_limit
.rlim_cur
= 0;
294 core_limit
.rlim_max
= 0;
295 setrlimit (RLIMIT_CORE
, &core_limit
);
298 fesetenv (FE_NOMASK_ENV
);
299 feraiseexcept (fe_exc
);
306 printf (" Fail: Could not fork.\n");
310 printf (" `fork' not implemented, test ignored.\n");
313 if (waitpid (pid
, &status
, 0) != pid
)
315 printf (" Fail: waitpid call failed.\n");
318 else if (WIFSIGNALED (status
) && WTERMSIG (status
) == SIGFPE
)
319 printf (" Pass: Process received SIGFPE.\n");
322 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
330 /* Test that program doesn't abort with default environment */
332 feenv_mask_test (const char *flag_name
, int fe_exc
, int (*func
)(const fenv_t
*))
337 printf ("Test: after %s (FE_DFL_ENV) processes will not abort\n", funcname (func
));
338 printf (" when feraiseexcept (%s) is called.\n", flag_name
);
343 /* Try to avoid dumping core. */
344 struct rlimit core_limit
;
345 core_limit
.rlim_cur
= 0;
346 core_limit
.rlim_max
= 0;
347 setrlimit (RLIMIT_CORE
, &core_limit
);
351 feraiseexcept (fe_exc
);
358 printf (" Fail: Could not fork.\n");
362 printf (" `fork' not implemented, test ignored.\n");
365 if (waitpid (pid
, &status
, 0) != pid
)
367 printf (" Fail: waitpid call failed.\n");
370 else if (WIFEXITED (status
) && WEXITSTATUS (status
) == 2)
371 printf (" Pass: Process exited normally.\n");
374 printf (" Fail: Process exited abnormally with status %d.\n",
381 /* Test that program aborts with no masked interrupts */
383 feexcp_nomask_test (const char *flag_name
, int fe_exc
)
388 if (!EXCEPTION_ENABLE_SUPPORTED (fe_exc
) && feenableexcept (fe_exc
) == -1)
390 printf ("Test: not testing feenableexcept, it isn't implemented.\n");
394 printf ("Test: after feenableexcept (%s) processes will abort\n",
396 printf (" when feraiseexcept (%s) is called.\n", flag_name
);
401 /* Try to avoid dumping core. */
402 struct rlimit core_limit
;
403 core_limit
.rlim_cur
= 0;
404 core_limit
.rlim_max
= 0;
405 setrlimit (RLIMIT_CORE
, &core_limit
);
408 fedisableexcept (FE_ALL_EXCEPT
);
409 feenableexcept (fe_exc
);
410 feraiseexcept (fe_exc
);
417 printf (" Fail: Could not fork.\n");
421 printf (" `fork' not implemented, test ignored.\n");
424 if (waitpid (pid
, &status
, 0) != pid
)
426 printf (" Fail: waitpid call failed.\n");
429 else if (WIFSIGNALED (status
) && WTERMSIG (status
) == SIGFPE
)
430 printf (" Pass: Process received SIGFPE.\n");
433 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
440 /* Test that program doesn't abort with exception. */
442 feexcp_mask_test (const char *flag_name
, int fe_exc
)
448 printf ("Test: after fedisableexcept (%s) processes will not abort\n",
450 printf (" when feraiseexcept (%s) is called.\n", flag_name
);
455 /* Try to avoid dumping core. */
456 struct rlimit core_limit
;
457 core_limit
.rlim_cur
= 0;
458 core_limit
.rlim_max
= 0;
459 setrlimit (RLIMIT_CORE
, &core_limit
);
461 feenableexcept (FE_ALL_EXCEPT
);
464 /* The standard allows the inexact exception to be set together with the
465 underflow and overflow exceptions. So add FE_INEXACT to the set of
466 exceptions to be disabled if we will be raising underflow or
469 if (fe_exc
& FE_OVERFLOW
)
470 exception
|= FE_INEXACT
;
473 if (fe_exc
& FE_UNDERFLOW
)
474 exception
|= FE_INEXACT
;
477 fedisableexcept (exception
);
478 feraiseexcept (fe_exc
);
485 printf (" Fail: Could not fork.\n");
489 printf (" `fork' not implemented, test ignored.\n");
492 if (waitpid (pid
, &status
, 0) != pid
)
494 printf (" Fail: waitpid call failed.\n");
497 else if (WIFEXITED (status
) && WEXITSTATUS (status
) == 2)
498 printf (" Pass: Process exited normally.\n");
501 printf (" Fail: Process exited abnormally with status %d.\n",
509 /* Tests for feenableexcept/fedisableexcept/fegetexcept. */
511 feenable_test (const char *flag_name
, int fe_exc
)
515 printf ("Tests for feenableexcepts etc. with flag %s\n", flag_name
);
517 /* First disable all exceptions. */
518 if (fedisableexcept (FE_ALL_EXCEPT
) == -1)
520 printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n");
522 /* If this fails, the other tests don't make sense. */
525 excepts
= fegetexcept ();
528 printf ("Test: fegetexcept (%s) failed, return should be 0, is %d\n",
532 excepts
= feenableexcept (fe_exc
);
533 if (!EXCEPTION_ENABLE_SUPPORTED (fe_exc
) && excepts
== -1)
535 printf ("Test: not testing feenableexcept, it isn't implemented.\n");
540 printf ("Test: feenableexcept (%s) failed\n", flag_name
);
546 printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
551 excepts
= fegetexcept ();
552 if (excepts
!= fe_exc
)
554 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
555 flag_name
, fe_exc
, excepts
);
559 /* And now disable the exception again. */
560 excepts
= fedisableexcept (fe_exc
);
563 printf ("Test: fedisableexcept (%s) failed\n", flag_name
);
567 if (excepts
!= fe_exc
)
569 printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
570 flag_name
, fe_exc
, excepts
);
574 excepts
= fegetexcept ();
577 printf ("Test: fegetexcept (%s) failed, return should be 0, is 0x%x\n",
582 /* Now the other way round: Enable all exceptions and disable just this one. */
583 if (feenableexcept (FE_ALL_EXCEPT
) == -1)
585 printf ("Test: feenableexcept (FE_ALL_EXCEPT) failed\n");
587 /* If this fails, the other tests don't make sense. */
591 excepts
= fegetexcept ();
592 if (excepts
!= FE_ALL_EXCEPT
)
594 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
595 flag_name
, FE_ALL_EXCEPT
, excepts
);
599 excepts
= fedisableexcept (fe_exc
);
602 printf ("Test: fedisableexcept (%s) failed\n", flag_name
);
606 if (excepts
!= FE_ALL_EXCEPT
)
608 printf ("Test: fedisableexcept (%s) failed, return should be 0, is 0x%x\n",
613 excepts
= fegetexcept ();
614 if (excepts
!= (FE_ALL_EXCEPT
& ~fe_exc
))
616 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
617 flag_name
, (FE_ALL_EXCEPT
& ~fe_exc
), excepts
);
621 /* And now enable the exception again. */
622 excepts
= feenableexcept (fe_exc
);
625 printf ("Test: feenableexcept (%s) failed\n", flag_name
);
629 if (excepts
!= (FE_ALL_EXCEPT
& ~fe_exc
))
631 printf ("Test: feenableexcept (%s) failed, return should be 0, is 0x%x\n",
636 excepts
= fegetexcept ();
637 if (excepts
!= FE_ALL_EXCEPT
)
639 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
640 flag_name
, FE_ALL_EXCEPT
, excepts
);
643 feexcp_nomask_test (flag_name
, fe_exc
);
644 feexcp_mask_test (flag_name
, fe_exc
);
650 fe_single_test (const char *flag_name
, int fe_exc
)
652 feenv_nomask_test (flag_name
, fe_exc
, fesetenv
);
653 feenv_mask_test (flag_name
, fe_exc
, fesetenv
);
654 feenable_test (flag_name
, fe_exc
);
659 feupdate_single_test (const char *flag_name
, int fe_exc
)
661 feenv_nomask_test (flag_name
, fe_exc
, feupdateenv
);
662 fesetenv (FE_DFL_ENV
);
663 feenv_mask_test (flag_name
, fe_exc
, feupdateenv
);
671 /* We might have some exceptions still set. */
672 feclearexcept (FE_ALL_EXCEPT
);
675 fe_single_test ("FE_DIVBYZERO", FE_DIVBYZERO
);
678 fe_single_test ("FE_INVALID", FE_INVALID
);
681 fe_single_test ("FE_INEXACT", FE_INEXACT
);
684 fe_single_test ("FE_UNDERFLOW", FE_UNDERFLOW
);
687 fe_single_test ("FE_OVERFLOW", FE_OVERFLOW
);
689 fesetenv (FE_DFL_ENV
);
694 feupdateenv_single_test (const char *test_name
, int fe_exc
, int exception
)
700 snprintf (str
, sizeof str
, "feupdateenv %s and FL_DFL_ENV", test_name
);
701 update_single_exc (str
, FE_DFL_ENV
, fe_exc
, NO_EXC
, exception
);
703 feraiseexcept (FE_ALL_EXCEPT
);
704 res
= fegetenv (&env
);
707 printf ("fegetenv failed: %d\n", res
);
712 snprintf (str
, sizeof str
, "feupdateenv %s and FE_ALL_EXCEPT", test_name
);
713 update_single_exc (str
, &env
, ALL_EXC
, ALL_EXC
, exception
);
718 feupdateenv_tests (void)
720 /* We might have some exceptions still set. */
721 feclearexcept (FE_ALL_EXCEPT
);
724 feupdate_single_test ("FE_DIVBYZERO", FE_DIVBYZERO
);
727 feupdate_single_test ("FE_INVALID", FE_INVALID
);
730 feupdate_single_test ("FE_INEXACT", FE_INEXACT
);
733 feupdate_single_test ("FE_UNDERFLOW", FE_UNDERFLOW
);
736 feupdate_single_test ("FE_OVERFLOW", FE_OVERFLOW
);
740 feupdateenv_single_test ("DIVBYZERO", DIVBYZERO_EXC
, FE_DIVBYZERO
);
743 feupdateenv_single_test ("INVALID", INVALID_EXC
, FE_INVALID
);
746 feupdateenv_single_test ("INEXACT", INEXACT_EXC
, FE_INEXACT
);
749 feupdateenv_single_test ("UNDERFLOW", UNDERFLOW_EXC
, FE_UNDERFLOW
);
752 feupdateenv_single_test ("OVERFLOW", OVERFLOW_EXC
, FE_OVERFLOW
);
755 feupdateenv (FE_DFL_ENV
);
760 feholdexcept_tests (void)
762 fenv_t saved
, saved2
;
765 feclearexcept (FE_ALL_EXCEPT
);
766 fedisableexcept (FE_ALL_EXCEPT
);
768 feraiseexcept (FE_DIVBYZERO
);
770 if (EXCEPTION_TESTS (float))
771 test_exceptions ("feholdexcept_tests FE_DIVBYZERO test",
773 res
= feholdexcept (&saved
);
776 printf ("feholdexcept failed: %d\n", res
);
779 #if defined FE_TONEAREST && defined FE_TOWARDZERO
780 res
= fesetround (FE_TOWARDZERO
);
781 if (res
!= 0 && ROUNDING_TESTS (float, FE_TOWARDZERO
))
783 printf ("fesetround failed: %d\n", res
);
787 test_exceptions ("feholdexcept_tests 0 test", NO_EXC
, 0);
789 feraiseexcept (FE_INVALID
);
790 if (EXCEPTION_TESTS (float))
791 test_exceptions ("feholdexcept_tests FE_INVALID test",
794 res
= feupdateenv (&saved
);
797 printf ("feupdateenv failed: %d\n", res
);
800 #if defined FE_TONEAREST && defined FE_TOWARDZERO
802 if (res
!= FE_TONEAREST
)
804 printf ("feupdateenv didn't restore rounding mode: %d\n", res
);
808 if (EXCEPTION_TESTS (float))
809 test_exceptions ("feholdexcept_tests FE_DIVBYZERO|FE_INVALID test",
810 DIVBYZERO_EXC
| INVALID_EXC
, 0);
811 feclearexcept (FE_ALL_EXCEPT
);
813 feraiseexcept (FE_INVALID
);
815 #if defined FE_TONEAREST && defined FE_UPWARD
816 res
= fesetround (FE_UPWARD
);
817 if (res
!= 0 && ROUNDING_TESTS (float, FE_UPWARD
))
819 printf ("fesetround failed: %d\n", res
);
823 res
= feholdexcept (&saved2
);
826 printf ("feholdexcept failed: %d\n", res
);
829 #if defined FE_TONEAREST && defined FE_UPWARD
830 res
= fesetround (FE_TONEAREST
);
833 printf ("fesetround failed: %d\n", res
);
837 test_exceptions ("feholdexcept_tests 0 2nd test", NO_EXC
, 0);
839 feraiseexcept (FE_INEXACT
);
840 if (EXCEPTION_TESTS (float))
841 test_exceptions ("feholdexcept_tests FE_INEXACT test",
844 res
= feupdateenv (&saved2
);
847 printf ("feupdateenv failed: %d\n", res
);
850 #if defined FE_TONEAREST && defined FE_UPWARD
852 if (res
!= FE_UPWARD
&& ROUNDING_TESTS (float, FE_UPWARD
))
854 printf ("feupdateenv didn't restore rounding mode: %d\n", res
);
857 fesetround (FE_TONEAREST
);
859 if (EXCEPTION_TESTS (float))
860 test_exceptions ("feholdexcept_tests FE_INEXACT|FE_INVALID test",
861 INVALID_EXC
| INEXACT_EXC
, 0);
862 feclearexcept (FE_ALL_EXCEPT
);
866 /* IEC 559 and ISO C99 define a default startup environment */
870 test_exceptions ("Initially all exceptions should be cleared",
873 test_rounding ("Rounding direction should be initialized to nearest",
884 feholdexcept_tests ();
885 feupdateenv_tests ();
889 printf ("\n%d errors occurred.\n", count_errors
);
892 printf ("\n All tests passed successfully.\n");
896 #include <support/test-driver.c>