usleep tests: Avoid failure due to known Cygwin 3.5.3 bug.
[gnulib.git] / tests / test-fenv-except-tracking-1.c
blobc0092d28b973b316e78fed4c01940cb21f71416f
1 /* Test of tracking of floating-point exceptions.
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 /* On *BSD/powerpc systems, raising FE_INVALID also sets FE_VXSOFT. */
27 #ifndef FE_VXSOFT
28 # define FE_VXSOFT 0
29 #endif
30 #ifndef FE_VXZDZ
31 # define FE_VXZDZ 0
32 #endif
34 static volatile double a, b, c;
36 int
37 main ()
39 /* Test setting all exception flags. */
40 if (feraiseexcept (FE_ALL_EXCEPT) != 0)
42 fputs ("Skipping test: floating-point exceptions are not supported on this machine.\n", stderr);
43 return 77;
45 ASSERT (/* with the libc's feraiseexcept(): */
46 fetestexcept (FE_ALL_EXCEPT) == FE_ALL_EXCEPT
47 || /* with gnulib's feraiseexcept(): */
48 (fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT)
49 == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW));
50 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
51 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
52 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
53 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
54 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
56 /* Test clearing all exception flags. */
57 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
58 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
59 ASSERT (fetestexcept (FE_INVALID) == 0);
60 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
61 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
62 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
63 ASSERT (fetestexcept (FE_INEXACT) == 0);
66 /* Test setting just one exception flag: FE_INVALID. */
67 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
68 ASSERT (feraiseexcept (FE_INVALID) == 0);
69 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == FE_INVALID);
70 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
71 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
72 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
73 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
74 ASSERT (fetestexcept (FE_INEXACT) == 0);
76 /* Test setting just one exception flag: FE_DIVBYZERO. */
77 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
78 ASSERT (feraiseexcept (FE_DIVBYZERO) == 0);
79 ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_DIVBYZERO);
80 ASSERT (fetestexcept (FE_INVALID) == 0);
81 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
82 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
83 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
84 ASSERT (fetestexcept (FE_INEXACT) == 0);
86 /* Test setting just one exception flag: FE_OVERFLOW.
87 On many architectures, this has the side-effect of also setting FE_INEXACT:
88 arm64, arm, alpha, hppa, ia64, loongarch64, s390, sh, sparc. */
89 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
90 ASSERT (feraiseexcept (FE_OVERFLOW) == 0);
91 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_INEXACT) == FE_OVERFLOW);
92 ASSERT (fetestexcept (FE_INVALID) == 0);
93 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
94 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
95 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
97 /* Test setting just one exception flag: FE_UNDERFLOW.
98 On many architectures, this has the side-effect of also setting FE_INEXACT:
99 arm64, arm, alpha, hppa, ia64, loongarch64, s390, sh, sparc. */
100 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
101 ASSERT (feraiseexcept (FE_UNDERFLOW) == 0);
102 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_INEXACT) == FE_UNDERFLOW);
103 ASSERT (fetestexcept (FE_INVALID) == 0);
104 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
105 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
106 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
108 /* Test setting just one exception flag: FE_INEXACT. */
109 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
110 ASSERT (feraiseexcept (FE_INEXACT) == 0);
111 ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_INEXACT);
112 ASSERT (fetestexcept (FE_INVALID) == 0);
113 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
114 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
115 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
116 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
119 /* Test clearing just one exception flag: FE_INVALID. */
120 ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0);
121 ASSERT (feclearexcept (FE_INVALID) == 0);
122 ASSERT (/* with the libc's feraiseexcept(): */
123 fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_INVALID)
124 || /* with gnulib's feraiseexcept(): */
125 fetestexcept (FE_ALL_EXCEPT)
126 == (FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW));
127 ASSERT (fetestexcept (FE_INVALID) == 0);
128 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
129 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
130 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
131 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
133 /* Test clearing just one exception flag: FE_DIVBYZERO. */
134 ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0);
135 ASSERT (feclearexcept (FE_DIVBYZERO) == 0);
136 ASSERT (/* with the libc's feraiseexcept(): */
137 fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_DIVBYZERO)
138 || /* with gnulib's feraiseexcept(): */
139 (fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT)
140 == (FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW));
141 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
142 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
143 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
144 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
145 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
147 /* Test clearing just one exception flag: FE_OVERFLOW. */
148 ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0);
149 ASSERT (feclearexcept (FE_OVERFLOW) == 0);
150 ASSERT (/* with the libc's feraiseexcept(): */
151 fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_OVERFLOW)
152 || /* with gnulib's feraiseexcept(): */
153 (fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT)
154 == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_UNDERFLOW));
155 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
156 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
157 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
158 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
159 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
161 /* Test clearing just one exception flag: FE_UNDERFLOW. */
162 ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0);
163 ASSERT (feclearexcept (FE_UNDERFLOW) == 0);
164 ASSERT (/* with the libc's feraiseexcept(): */
165 fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_UNDERFLOW)
166 || /* with gnulib's feraiseexcept(): */
167 (fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT)
168 == (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW));
169 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
170 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
171 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
172 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
173 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
175 /* Test clearing just one exception flag: FE_INEXACT. */
176 ASSERT (feraiseexcept (FE_ALL_EXCEPT) == 0);
177 ASSERT (feclearexcept (FE_INEXACT) == 0);
178 ASSERT (/* with the libc's feraiseexcept(): */
179 fetestexcept (FE_ALL_EXCEPT) == (FE_ALL_EXCEPT & ~FE_INEXACT)
180 || /* with gnulib's feraiseexcept(): */
181 (fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT)
182 == (FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW));
183 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
184 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
185 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
186 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
187 ASSERT (fetestexcept (FE_INEXACT) == 0);
190 #if !(defined __arm__ && defined __SOFTFP__)
191 /* Test the effects of an operation that produces FE_INVALID. */
192 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
193 a = 0; b = 0; c = a / b;
194 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXZDZ) == FE_INVALID);
195 ASSERT (fetestexcept (FE_INVALID) == FE_INVALID);
196 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
197 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
198 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
199 ASSERT (fetestexcept (FE_INEXACT) == 0);
201 /* Test the effects of an operation that produces FE_DIVBYZERO. */
202 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
203 a = 3; b = 0; c = a / b;
204 ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_DIVBYZERO);
205 ASSERT (fetestexcept (FE_INVALID) == 0);
206 ASSERT (fetestexcept (FE_DIVBYZERO) == FE_DIVBYZERO);
207 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
208 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
209 ASSERT (fetestexcept (FE_INEXACT) == 0);
211 /* Test the effects of an operation that produces FE_OVERFLOW. */
212 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
213 a = 1; for (int i = 0; i < 800; i++) a = 2.0 * a;
214 b = 1; for (int i = 0; i < 700; i++) b = 2.0 * b;
215 c = a * b;
217 int exc = fetestexcept (FE_ALL_EXCEPT);
218 ASSERT ((FE_OVERFLOW & ~exc) == 0);
219 ASSERT ((exc & ~(FE_OVERFLOW | FE_INEXACT)) == 0);
221 ASSERT (fetestexcept (FE_INVALID) == 0);
222 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
223 ASSERT (fetestexcept (FE_OVERFLOW) == FE_OVERFLOW);
224 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
226 /* Test the effects of an operation that produces FE_UNDERFLOW. */
227 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
228 a = 1; for (int i = 0; i < 800; i++) a = 0.5 * a;
229 b = 1; for (int i = 0; i < 700; i++) b = 0.5 * b;
230 c = a * b;
232 int exc = fetestexcept (FE_ALL_EXCEPT);
233 ASSERT ((FE_UNDERFLOW & ~exc) == 0);
234 ASSERT ((exc & ~(FE_UNDERFLOW | FE_INEXACT)) == 0);
236 ASSERT (fetestexcept (FE_INVALID) == 0);
237 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
238 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
239 ASSERT (fetestexcept (FE_UNDERFLOW) == FE_UNDERFLOW);
241 /* On alpha, this test works only when compiled with the GCC option
242 '-mieee-with-inexact'. */
243 # if !defined __alpha
244 /* Test the effects of an operation that produces FE_INEXACT. */
245 ASSERT (feclearexcept (FE_ALL_EXCEPT) == 0);
246 a = 1; b = 3; c = a / b;
247 ASSERT (fetestexcept (FE_ALL_EXCEPT) == FE_INEXACT);
248 ASSERT (fetestexcept (FE_INVALID) == 0);
249 ASSERT (fetestexcept (FE_DIVBYZERO) == 0);
250 ASSERT (fetestexcept (FE_OVERFLOW) == 0);
251 ASSERT (fetestexcept (FE_UNDERFLOW) == 0);
252 ASSERT (fetestexcept (FE_INEXACT) == FE_INEXACT);
253 # endif
254 #endif
257 return test_exit_status;