1 /* Test of saving the floating-point exception status flags.
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. */
29 fexcept_t saved_flags_1
;
30 fexcept_t saved_flags_2
;
32 /* Test setting all exception flags. */
33 if (feraiseexcept (FE_INVALID
| FE_DIVBYZERO
| FE_OVERFLOW
| FE_UNDERFLOW
| FE_INEXACT
) != 0)
35 fputs ("Skipping test: floating-point exceptions are not supported on this machine.\n", stderr
);
39 /* Fill saved_flags_1. */
40 ASSERT (fegetexceptflag (&saved_flags_1
,
41 FE_INVALID
| FE_DIVBYZERO
| FE_OVERFLOW
| FE_UNDERFLOW
| FE_INEXACT
)
44 /* Clear some of the exception flags. */
45 ASSERT (feclearexcept (FE_OVERFLOW
| FE_UNDERFLOW
| FE_INEXACT
) == 0);
46 /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO. */
47 ASSERT (fetestexcept (FE_INVALID
) == FE_INVALID
);
48 ASSERT (fetestexcept (FE_DIVBYZERO
) == FE_DIVBYZERO
);
49 ASSERT (fetestexcept (FE_OVERFLOW
) == 0);
50 ASSERT (fetestexcept (FE_UNDERFLOW
) == 0);
51 ASSERT (fetestexcept (FE_INEXACT
) == 0);
53 /* Fill saved_flags_2. */
54 ASSERT (fegetexceptflag (&saved_flags_2
, FE_INVALID
| FE_OVERFLOW
) == 0);
56 /* Restore some of the exception flags. */
57 ASSERT (fesetexceptflag (&saved_flags_1
,
58 FE_INVALID
| FE_DIVBYZERO
| FE_OVERFLOW
| FE_UNDERFLOW
) == 0);
59 /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW. */
60 ASSERT (fetestexcept (FE_INVALID
) == FE_INVALID
);
61 ASSERT (fetestexcept (FE_DIVBYZERO
) == FE_DIVBYZERO
);
62 ASSERT (fetestexcept (FE_OVERFLOW
) == FE_OVERFLOW
);
63 ASSERT (fetestexcept (FE_UNDERFLOW
) == FE_UNDERFLOW
);
64 ASSERT (fetestexcept (FE_INEXACT
) == 0);
66 /* Clear some more exception flags. */
67 ASSERT (feclearexcept (FE_INVALID
) == 0);
68 /* Here, the set exception flags are FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW. */
69 ASSERT (fetestexcept (FE_INVALID
) == 0);
70 ASSERT (fetestexcept (FE_DIVBYZERO
) == FE_DIVBYZERO
);
71 ASSERT (fetestexcept (FE_OVERFLOW
) == FE_OVERFLOW
);
72 ASSERT (fetestexcept (FE_UNDERFLOW
) == FE_UNDERFLOW
);
73 ASSERT (fetestexcept (FE_INEXACT
) == 0);
75 /* Restore some more exception flags. */
76 ASSERT (fesetexceptflag (&saved_flags_2
, FE_OVERFLOW
) == 0);
77 /* Here, the set exception flags are FE_DIVBYZERO | FE_UNDERFLOW. */
78 ASSERT (fetestexcept (FE_INVALID
) == 0);
79 ASSERT (fetestexcept (FE_DIVBYZERO
) == FE_DIVBYZERO
);
80 ASSERT (fetestexcept (FE_OVERFLOW
) == 0);
81 ASSERT (fetestexcept (FE_UNDERFLOW
) == FE_UNDERFLOW
);
82 ASSERT (fetestexcept (FE_INEXACT
) == 0);
84 /* Restore some more exception flags. */
85 ASSERT (fesetexceptflag (&saved_flags_2
, FE_INVALID
) == 0);
86 /* Here, the set exception flags are FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW. */
87 ASSERT (fetestexcept (FE_INVALID
) == FE_INVALID
);
88 ASSERT (fetestexcept (FE_DIVBYZERO
) == FE_DIVBYZERO
);
89 ASSERT (fetestexcept (FE_OVERFLOW
) == 0);
90 ASSERT (fetestexcept (FE_UNDERFLOW
) == FE_UNDERFLOW
);
91 ASSERT (fetestexcept (FE_INEXACT
) == 0);
93 /* ======================================================================== */
94 /* Check that fesetexceptflag clears exception flags in both the 387 unit
95 and the SSE unit, on i386 and x86_64 CPUs. */
97 fexcept_t saved_flags_3
;
99 ASSERT (feclearexcept (FE_INVALID
) == 0);
101 ASSERT (fegetexceptflag (&saved_flags_3
, FE_INVALID
) == 0);
103 /* Set the FE_INVALID flag in the SSE unit. */
105 static volatile double a
, b
;
106 _GL_UNUSED
volatile double c
;
107 a
= 0.0; b
= 0.0; c
= a
/ b
;
109 /* Set the FE_INVALID flag in the 387 unit. */
111 static volatile long double al
, bl
;
112 _GL_UNUSED
volatile long double cl
;
113 al
= 0.0L; bl
= 0.0L; cl
= al
/ bl
;
116 /* Use fesetexceptflag to clear the FE_INVALID flag. */
117 ASSERT (fesetexceptflag (&saved_flags_3
, FE_INVALID
) == 0);
119 /* Check that it's clear in both units. */
120 ASSERT (fetestexcept (FE_INVALID
) == 0);
122 return test_exit_status
;