microblaze: Avoid clobbering register parameters in syscall
[glibc.git] / math / test-fenv.c
blobf6845301e6680b48879aecdb53487fde57a61d3d
1 /* Copyright (C) 1997-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@suse.de> and
4 Ulrich Drepper <drepper@cygnus.com>, 1997.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
20 /* Tests for ISO C99 7.6: Floating-point environment */
22 #ifndef _GNU_SOURCE
23 # define _GNU_SOURCE
24 #endif
26 #include <complex.h>
27 #include <math.h>
28 #include <float.h>
29 #include <fenv.h>
31 #include <errno.h>
32 #include <signal.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/wait.h>
38 #include <sys/resource.h>
39 #include <math-tests.h>
42 Since not all architectures might define all exceptions, we define
43 a private set and map accordingly.
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)
55 static int count_errors;
57 #if FE_ALL_EXCEPT
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);
88 #endif
90 static void
91 test_exceptions (const char *test_name, short int exception,
92 int ignore_inexact)
94 printf ("Test: %s\n", test_name);
95 #ifdef FE_DIVBYZERO
96 test_single_exception (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
97 "DIVBYZERO");
98 #endif
99 #ifdef FE_INVALID
100 test_single_exception (exception, INVALID_EXC, FE_INVALID,
101 "INVALID");
102 #endif
103 #ifdef FE_INEXACT
104 if (!ignore_inexact)
105 test_single_exception (exception, INEXACT_EXC, FE_INEXACT,
106 "INEXACT");
107 #endif
108 #ifdef FE_UNDERFLOW
109 test_single_exception (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
110 "UNDERFLOW");
111 #endif
112 #ifdef FE_OVERFLOW
113 test_single_exception (exception, OVERFLOW_EXC, FE_OVERFLOW,
114 "OVERFLOW");
115 #endif
118 static void
119 print_rounding (int rounding)
122 switch (rounding)
124 #ifdef FE_TONEAREST
125 case FE_TONEAREST:
126 printf ("TONEAREST");
127 break;
128 #endif
129 #ifdef FE_UPWARD
130 case FE_UPWARD:
131 printf ("UPWARD");
132 break;
133 #endif
134 #ifdef FE_DOWNWARD
135 case FE_DOWNWARD:
136 printf ("DOWNWARD");
137 break;
138 #endif
139 #ifdef FE_TOWARDZERO
140 case FE_TOWARDZERO:
141 printf ("TOWARDZERO");
142 break;
143 #endif
145 printf (".\n");
149 static void
150 test_rounding (const char *test_name, int rounding_mode)
152 int curr_rounding = fegetround ();
154 printf ("Test: %s\n", test_name);
155 if (curr_rounding == rounding_mode)
157 printf (" Pass: Rounding mode is ");
158 print_rounding (curr_rounding);
160 else
162 ++count_errors;
163 printf (" Fail: Rounding mode is ");
164 print_rounding (curr_rounding);
169 #if FE_ALL_EXCEPT
170 static void
171 set_single_exc (const char *test_name, int fe_exc, fexcept_t exception)
173 char str[200];
174 /* The standard allows the inexact exception to be set together with the
175 underflow and overflow exceptions. So ignore the inexact flag if the
176 others are raised. */
177 int ignore_inexact = (fe_exc & (UNDERFLOW_EXC | OVERFLOW_EXC)) != 0;
179 strcpy (str, test_name);
180 strcat (str, ": set flag, with rest not set");
181 feclearexcept (FE_ALL_EXCEPT);
182 feraiseexcept (exception);
183 test_exceptions (str, fe_exc, ignore_inexact);
185 strcpy (str, test_name);
186 strcat (str, ": clear flag, rest also unset");
187 feclearexcept (exception);
188 test_exceptions (str, NO_EXC, ignore_inexact);
190 strcpy (str, test_name);
191 strcat (str, ": set flag, with rest set");
192 feraiseexcept (FE_ALL_EXCEPT ^ exception);
193 feraiseexcept (exception);
194 test_exceptions (str, ALL_EXC, 0);
196 strcpy (str, test_name);
197 strcat (str, ": clear flag, leave rest set");
198 feclearexcept (exception);
199 test_exceptions (str, ALL_EXC ^ fe_exc, 0);
201 #endif
203 static void
204 fe_tests (void)
206 /* clear all exceptions and test if all are cleared */
207 feclearexcept (FE_ALL_EXCEPT);
208 test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
209 NO_EXC, 0);
211 /* Skip further tests here if exceptions not supported. */
212 if (!EXCEPTION_TESTS (float) && FE_ALL_EXCEPT != 0)
213 return;
214 /* raise all exceptions and test if all are raised */
215 feraiseexcept (FE_ALL_EXCEPT);
216 test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
217 ALL_EXC, 0);
218 feclearexcept (FE_ALL_EXCEPT);
220 #ifdef FE_DIVBYZERO
221 set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC, FE_DIVBYZERO);
222 #endif
223 #ifdef FE_INVALID
224 set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC, FE_INVALID);
225 #endif
226 #ifdef FE_INEXACT
227 set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC, FE_INEXACT);
228 #endif
229 #ifdef FE_UNDERFLOW
230 set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC, FE_UNDERFLOW);
231 #endif
232 #ifdef FE_OVERFLOW
233 set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC, FE_OVERFLOW);
234 #endif
237 #if FE_ALL_EXCEPT
238 /* Test that program aborts with no masked interrupts */
239 static void
240 feenv_nomask_test (const char *flag_name, int fe_exc)
242 # if defined FE_NOMASK_ENV
243 int status;
244 pid_t pid;
246 if (!EXCEPTION_ENABLE_SUPPORTED (FE_ALL_EXCEPT)
247 && fesetenv (FE_NOMASK_ENV) != 0)
249 printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n");
250 return;
253 printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n");
254 printf (" when feraiseexcept (%s) is called.\n", flag_name);
255 pid = fork ();
256 if (pid == 0)
258 # ifdef RLIMIT_CORE
259 /* Try to avoid dumping core. */
260 struct rlimit core_limit;
261 core_limit.rlim_cur = 0;
262 core_limit.rlim_max = 0;
263 setrlimit (RLIMIT_CORE, &core_limit);
264 # endif
266 fesetenv (FE_NOMASK_ENV);
267 feraiseexcept (fe_exc);
268 exit (2);
270 else if (pid < 0)
272 if (errno != ENOSYS)
274 printf (" Fail: Could not fork.\n");
275 ++count_errors;
277 else
278 printf (" `fork' not implemented, test ignored.\n");
280 else {
281 if (waitpid (pid, &status, 0) != pid)
283 printf (" Fail: waitpid call failed.\n");
284 ++count_errors;
286 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
287 printf (" Pass: Process received SIGFPE.\n");
288 else
290 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
291 status);
292 ++count_errors;
295 # endif
298 /* Test that program doesn't abort with default environment */
299 static void
300 feenv_mask_test (const char *flag_name, int fe_exc)
302 int status;
303 pid_t pid;
305 printf ("Test: after fesetenv (FE_DFL_ENV) processes will not abort\n");
306 printf (" when feraiseexcept (%s) is called.\n", flag_name);
307 pid = fork ();
308 if (pid == 0)
310 #ifdef RLIMIT_CORE
311 /* Try to avoid dumping core. */
312 struct rlimit core_limit;
313 core_limit.rlim_cur = 0;
314 core_limit.rlim_max = 0;
315 setrlimit (RLIMIT_CORE, &core_limit);
316 #endif
318 fesetenv (FE_DFL_ENV);
319 feraiseexcept (fe_exc);
320 exit (2);
322 else if (pid < 0)
324 if (errno != ENOSYS)
326 printf (" Fail: Could not fork.\n");
327 ++count_errors;
329 else
330 printf (" `fork' not implemented, test ignored.\n");
332 else {
333 if (waitpid (pid, &status, 0) != pid)
335 printf (" Fail: waitpid call failed.\n");
336 ++count_errors;
338 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
339 printf (" Pass: Process exited normally.\n");
340 else
342 printf (" Fail: Process exited abnormally with status %d.\n",
343 status);
344 ++count_errors;
349 /* Test that program aborts with no masked interrupts */
350 static void
351 feexcp_nomask_test (const char *flag_name, int fe_exc)
353 int status;
354 pid_t pid;
356 if (!EXCEPTION_ENABLE_SUPPORTED (fe_exc) && feenableexcept (fe_exc) == -1)
358 printf ("Test: not testing feenableexcept, it isn't implemented.\n");
359 return;
362 printf ("Test: after feenableexcept (%s) processes will abort\n",
363 flag_name);
364 printf (" when feraiseexcept (%s) is called.\n", flag_name);
365 pid = fork ();
366 if (pid == 0)
368 #ifdef RLIMIT_CORE
369 /* Try to avoid dumping core. */
370 struct rlimit core_limit;
371 core_limit.rlim_cur = 0;
372 core_limit.rlim_max = 0;
373 setrlimit (RLIMIT_CORE, &core_limit);
374 #endif
376 fedisableexcept (FE_ALL_EXCEPT);
377 feenableexcept (fe_exc);
378 feraiseexcept (fe_exc);
379 exit (2);
381 else if (pid < 0)
383 if (errno != ENOSYS)
385 printf (" Fail: Could not fork.\n");
386 ++count_errors;
388 else
389 printf (" `fork' not implemented, test ignored.\n");
391 else {
392 if (waitpid (pid, &status, 0) != pid)
394 printf (" Fail: waitpid call failed.\n");
395 ++count_errors;
397 else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE)
398 printf (" Pass: Process received SIGFPE.\n");
399 else
401 printf (" Fail: Process didn't receive signal and exited with status %d.\n",
402 status);
403 ++count_errors;
408 /* Test that program doesn't abort with exception. */
409 static void
410 feexcp_mask_test (const char *flag_name, int fe_exc)
412 int status;
413 int exception;
414 pid_t pid;
416 printf ("Test: after fedisableexcept (%s) processes will not abort\n",
417 flag_name);
418 printf (" when feraiseexcept (%s) is called.\n", flag_name);
419 pid = fork ();
420 if (pid == 0)
422 #ifdef RLIMIT_CORE
423 /* Try to avoid dumping core. */
424 struct rlimit core_limit;
425 core_limit.rlim_cur = 0;
426 core_limit.rlim_max = 0;
427 setrlimit (RLIMIT_CORE, &core_limit);
428 #endif
429 feenableexcept (FE_ALL_EXCEPT);
430 exception = fe_exc;
431 #ifdef FE_INEXACT
432 /* The standard allows the inexact exception to be set together with the
433 underflow and overflow exceptions. So add FE_INEXACT to the set of
434 exceptions to be disabled if we will be raising underflow or
435 overflow. */
436 # ifdef FE_OVERFLOW
437 if (fe_exc & FE_OVERFLOW)
438 exception |= FE_INEXACT;
439 # endif
440 # ifdef FE_UNDERFLOW
441 if (fe_exc & FE_UNDERFLOW)
442 exception |= FE_INEXACT;
443 # endif
444 #endif
445 fedisableexcept (exception);
446 feraiseexcept (fe_exc);
447 exit (2);
449 else if (pid < 0)
451 if (errno != ENOSYS)
453 printf (" Fail: Could not fork.\n");
454 ++count_errors;
456 else
457 printf (" `fork' not implemented, test ignored.\n");
459 else {
460 if (waitpid (pid, &status, 0) != pid)
462 printf (" Fail: waitpid call failed.\n");
463 ++count_errors;
465 else if (WIFEXITED (status) && WEXITSTATUS (status) == 2)
466 printf (" Pass: Process exited normally.\n");
467 else
469 printf (" Fail: Process exited abnormally with status %d.\n",
470 status);
471 ++count_errors;
477 /* Tests for feenableexcept/fedisableexcept/fegetexcept. */
478 static void
479 feenable_test (const char *flag_name, int fe_exc)
481 int excepts;
483 printf ("Tests for feenableexcepts etc. with flag %s\n", flag_name);
485 /* First disable all exceptions. */
486 if (fedisableexcept (FE_ALL_EXCEPT) == -1)
488 printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n");
489 ++count_errors;
490 /* If this fails, the other tests don't make sense. */
491 return;
493 excepts = fegetexcept ();
494 if (excepts != 0)
496 printf ("Test: fegetexcept (%s) failed, return should be 0, is %d\n",
497 flag_name, excepts);
498 ++count_errors;
500 excepts = feenableexcept (fe_exc);
501 if (!EXCEPTION_ENABLE_SUPPORTED (fe_exc) && excepts == -1)
503 printf ("Test: not testing feenableexcept, it isn't implemented.\n");
504 return;
506 if (excepts == -1)
508 printf ("Test: feenableexcept (%s) failed\n", flag_name);
509 ++count_errors;
510 return;
512 if (excepts != 0)
514 printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
515 flag_name, excepts);
516 ++count_errors;
519 excepts = fegetexcept ();
520 if (excepts != fe_exc)
522 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
523 flag_name, fe_exc, excepts);
524 ++count_errors;
527 /* And now disable the exception again. */
528 excepts = fedisableexcept (fe_exc);
529 if (excepts == -1)
531 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
532 ++count_errors;
533 return;
535 if (excepts != fe_exc)
537 printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
538 flag_name, fe_exc, excepts);
539 ++count_errors;
542 excepts = fegetexcept ();
543 if (excepts != 0)
545 printf ("Test: fegetexcept (%s) failed, return should be 0, is 0x%x\n",
546 flag_name, excepts);
547 ++count_errors;
550 /* Now the other way round: Enable all exceptions and disable just this one. */
551 if (feenableexcept (FE_ALL_EXCEPT) == -1)
553 printf ("Test: feenableexcept (FE_ALL_EXCEPT) failed\n");
554 ++count_errors;
555 /* If this fails, the other tests don't make sense. */
556 return;
559 excepts = fegetexcept ();
560 if (excepts != FE_ALL_EXCEPT)
562 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
563 flag_name, FE_ALL_EXCEPT, excepts);
564 ++count_errors;
567 excepts = fedisableexcept (fe_exc);
568 if (excepts == -1)
570 printf ("Test: fedisableexcept (%s) failed\n", flag_name);
571 ++count_errors;
572 return;
574 if (excepts != FE_ALL_EXCEPT)
576 printf ("Test: fedisableexcept (%s) failed, return should be 0, is 0x%x\n",
577 flag_name, excepts);
578 ++count_errors;
581 excepts = fegetexcept ();
582 if (excepts != (FE_ALL_EXCEPT & ~fe_exc))
584 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
585 flag_name, (FE_ALL_EXCEPT & ~fe_exc), excepts);
586 ++count_errors;
589 /* And now enable the exception again. */
590 excepts = feenableexcept (fe_exc);
591 if (excepts == -1)
593 printf ("Test: feenableexcept (%s) failed\n", flag_name);
594 ++count_errors;
595 return;
597 if (excepts != (FE_ALL_EXCEPT & ~fe_exc))
599 printf ("Test: feenableexcept (%s) failed, return should be 0, is 0x%x\n",
600 flag_name, excepts);
601 ++count_errors;
604 excepts = fegetexcept ();
605 if (excepts != FE_ALL_EXCEPT)
607 printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n",
608 flag_name, FE_ALL_EXCEPT, excepts);
609 ++count_errors;
611 feexcp_nomask_test (flag_name, fe_exc);
612 feexcp_mask_test (flag_name, fe_exc);
617 static void
618 fe_single_test (const char *flag_name, int fe_exc)
620 feenv_nomask_test (flag_name, fe_exc);
621 feenv_mask_test (flag_name, fe_exc);
622 feenable_test (flag_name, fe_exc);
624 #endif
627 static void
628 feenv_tests (void)
630 /* We might have some exceptions still set. */
631 feclearexcept (FE_ALL_EXCEPT);
633 #ifdef FE_DIVBYZERO
634 fe_single_test ("FE_DIVBYZERO", FE_DIVBYZERO);
635 #endif
636 #ifdef FE_INVALID
637 fe_single_test ("FE_INVALID", FE_INVALID);
638 #endif
639 #ifdef FE_INEXACT
640 fe_single_test ("FE_INEXACT", FE_INEXACT);
641 #endif
642 #ifdef FE_UNDERFLOW
643 fe_single_test ("FE_UNDERFLOW", FE_UNDERFLOW);
644 #endif
645 #ifdef FE_OVERFLOW
646 fe_single_test ("FE_OVERFLOW", FE_OVERFLOW);
647 #endif
648 fesetenv (FE_DFL_ENV);
652 static void
653 feholdexcept_tests (void)
655 fenv_t saved, saved2;
656 int res;
658 feclearexcept (FE_ALL_EXCEPT);
659 fedisableexcept (FE_ALL_EXCEPT);
660 #ifdef FE_DIVBYZERO
661 feraiseexcept (FE_DIVBYZERO);
662 #endif
663 if (EXCEPTION_TESTS (float))
664 test_exceptions ("feholdexcept_tests FE_DIVBYZERO test",
665 DIVBYZERO_EXC, 0);
666 res = feholdexcept (&saved);
667 if (res != 0)
669 printf ("feholdexcept failed: %d\n", res);
670 ++count_errors;
672 #if defined FE_TONEAREST && defined FE_TOWARDZERO
673 res = fesetround (FE_TOWARDZERO);
674 if (res != 0 && ROUNDING_TESTS (float, FE_TOWARDZERO))
676 printf ("fesetround failed: %d\n", res);
677 ++count_errors;
679 #endif
680 test_exceptions ("feholdexcept_tests 0 test", NO_EXC, 0);
681 #ifdef FE_INVALID
682 feraiseexcept (FE_INVALID);
683 if (EXCEPTION_TESTS (float))
684 test_exceptions ("feholdexcept_tests FE_INVALID test",
685 INVALID_EXC, 0);
686 #endif
687 res = feupdateenv (&saved);
688 if (res != 0)
690 printf ("feupdateenv failed: %d\n", res);
691 ++count_errors;
693 #if defined FE_TONEAREST && defined FE_TOWARDZERO
694 res = fegetround ();
695 if (res != FE_TONEAREST)
697 printf ("feupdateenv didn't restore rounding mode: %d\n", res);
698 ++count_errors;
700 #endif
701 if (EXCEPTION_TESTS (float))
702 test_exceptions ("feholdexcept_tests FE_DIVBYZERO|FE_INVALID test",
703 DIVBYZERO_EXC | INVALID_EXC, 0);
704 feclearexcept (FE_ALL_EXCEPT);
705 #ifdef FE_INVALID
706 feraiseexcept (FE_INVALID);
707 #endif
708 #if defined FE_TONEAREST && defined FE_UPWARD
709 res = fesetround (FE_UPWARD);
710 if (res != 0 && ROUNDING_TESTS (float, FE_UPWARD))
712 printf ("fesetround failed: %d\n", res);
713 ++count_errors;
715 #endif
716 res = feholdexcept (&saved2);
717 if (res != 0)
719 printf ("feholdexcept failed: %d\n", res);
720 ++count_errors;
722 #if defined FE_TONEAREST && defined FE_UPWARD
723 res = fesetround (FE_TONEAREST);
724 if (res != 0)
726 printf ("fesetround failed: %d\n", res);
727 ++count_errors;
729 #endif
730 test_exceptions ("feholdexcept_tests 0 2nd test", NO_EXC, 0);
731 #ifdef FE_INEXACT
732 feraiseexcept (FE_INEXACT);
733 if (EXCEPTION_TESTS (float))
734 test_exceptions ("feholdexcept_tests FE_INEXACT test",
735 INEXACT_EXC, 0);
736 #endif
737 res = feupdateenv (&saved2);
738 if (res != 0)
740 printf ("feupdateenv failed: %d\n", res);
741 ++count_errors;
743 #if defined FE_TONEAREST && defined FE_UPWARD
744 res = fegetround ();
745 if (res != FE_UPWARD && ROUNDING_TESTS (float, FE_UPWARD))
747 printf ("feupdateenv didn't restore rounding mode: %d\n", res);
748 ++count_errors;
750 fesetround (FE_TONEAREST);
751 #endif
752 if (EXCEPTION_TESTS (float))
753 test_exceptions ("feholdexcept_tests FE_INEXACT|FE_INVALID test",
754 INVALID_EXC | INEXACT_EXC, 0);
755 feclearexcept (FE_ALL_EXCEPT);
759 /* IEC 559 and ISO C99 define a default startup environment */
760 static void
761 initial_tests (void)
763 test_exceptions ("Initially all exceptions should be cleared",
764 NO_EXC, 0);
765 #ifdef FE_TONEAREST
766 test_rounding ("Rounding direction should be initalized to nearest",
767 FE_TONEAREST);
768 #endif
772 main (void)
774 initial_tests ();
775 fe_tests ();
776 feenv_tests ();
777 feholdexcept_tests ();
779 if (count_errors)
781 printf ("\n%d errors occurred.\n", count_errors);
782 exit (1);
784 printf ("\n All tests passed successfully.\n");
785 return 0;