1 /* Test of tracking of floating-point exceptions.
2 Copyright (C) 2023-2025 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. */
26 /* On *BSD/powerpc systems, raising FE_INVALID also sets FE_VXSOFT. */
34 static volatile double a
, b
, c
;
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
);
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
;
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
;
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
);
257 return test_exit_status
;