usleep tests: Avoid failure due to known Cygwin 3.5.3 bug.
[gnulib.git] / tests / test-fenv-env-5.c
blob5d4fc520e3d5229857f92043b3819d5a8bcbe429
1 /* Test of controlling the floating-point environment.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program 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
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2023. */
19 #include <config.h>
21 /* Specification. */
22 #include <fenv.h>
24 #include "macros.h"
26 /* Test the combination of feholdexcept() with feupdateenv(). */
28 /* On *BSD/powerpc systems, raising FE_INVALID also sets FE_VXSOFT. */
29 #ifndef FE_VXSOFT
30 # define FE_VXSOFT 0
31 #endif
33 int
34 main ()
36 #if defined __GLIBC__ && defined __arm__ && defined __SOFTFP__
37 fputs ("Skipping test: no floating-point environment exists on this machine\n", stderr);
38 return 77;
39 #else
40 fenv_t env1, env2;
42 /* Get to a known initial state. */
43 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
45 /* Save the current environment in env1. */
46 ASSERT (feholdexcept (&env1) == 0);
48 /* Modify the current environment. */
49 fesetround (FE_UPWARD);
50 int supports_tracking = (feraiseexcept (FE_INVALID | FE_OVERFLOW | FE_INEXACT) == 0);
51 int supports_trapping = (feenableexcept (FE_DIVBYZERO) != -1);
53 /* Save the current environment in env2. */
54 ASSERT (feholdexcept (&env2) == 0);
56 /* Check that the exception flags are cleared. */
57 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
58 /* Check that the exception trap bits are cleared. */
59 ASSERT (fegetexcept () == 0);
61 /* Go back to env1. */
62 ASSERT (feupdateenv (&env1) == 0);
64 /* Check that the rounding direction has been restored. */
65 ASSERT (fegetround () == FE_TONEAREST);
66 /* Check that the exception flags are the union of the saved and of the
67 current exception flags. (The saved exception flags and the current
68 exception flags both happen to be none in this case.) */
69 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
70 /* Check that the exception trap bits have been restored. */
71 ASSERT (fegetexcept () == 0);
73 /* Modify the rounding direction, the exception flags, and the exception
74 trap bits again. */
75 fesetround (FE_DOWNWARD);
76 ASSERT (fegetround () == FE_DOWNWARD);
77 feclearexcept (FE_OVERFLOW);
78 feraiseexcept (FE_UNDERFLOW | FE_INEXACT);
79 ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0));
80 feenableexcept (FE_INVALID);
81 ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
83 /* Go back to env2. */
84 ASSERT (feupdateenv (&env2) == 0);
86 /* Check that the rounding direction has been restored. */
87 ASSERT (fegetround () == FE_UPWARD);
88 /* Check that the exception flags are the union of the saved and of the
89 current exception flags. */
90 if (supports_tracking)
91 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
92 else
93 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
94 /* Check that the exception trap bits have been restored. */
95 ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
97 /* ======================================================================== */
98 /* FE_DFL_ENV */
100 /* Go back to the default environment. */
101 ASSERT (feupdateenv (FE_DFL_ENV) == 0);
103 /* Check that the rounding direction has been restored,
104 whereas the exception flags are unmodified. */
105 ASSERT (fegetround () == FE_TONEAREST);
106 if (supports_tracking)
107 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
108 else
109 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
111 /* Enable trapping on FE_INVALID. */
112 feclearexcept (FE_INVALID);
113 feenableexcept (FE_INVALID);
114 ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
116 /* Go back to the default environment. */
117 ASSERT (feupdateenv (FE_DFL_ENV) == 0);
119 /* Check that the rounding direction has been restored,
120 whereas the exception flags are unmodified. */
121 ASSERT (fegetround () == FE_TONEAREST);
122 ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
124 /* Check that it has trapping on FE_INVALID disabled. */
125 ASSERT (fegetexcept () == 0);
127 double volatile a;
128 _GL_UNUSED double volatile b;
129 a = 0; b = a / a;
132 /* ======================================================================== */
133 /* Check that feholdexcept, unlike fegetenv, disables trapping. */
135 /* musl libc does not support floating-point exception trapping, even where
136 the hardware supports it. See
137 <https://wiki.musl-libc.org/functional-differences-from-glibc.html> */
138 # if !MUSL_LIBC || GNULIB_FEENABLEEXCEPT
139 /* Enable trapping on FE_INVALID. */
140 feclearexcept (FE_INVALID);
141 if (feenableexcept (FE_INVALID) != -1)
143 /* Call feholdexcept. */
144 ASSERT (feholdexcept (&env1) == 0);
146 /* Check that it has disabled trapping on FE_INVALID. */
147 ASSERT (fegetexcept () == 0);
149 double volatile a;
150 _GL_UNUSED double volatile b;
151 a = 0; b = a / a;
154 # endif
156 return test_exit_status;
157 #endif