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. */
26 /* Test the combination of feholdexcept() with fesetenv(). */
28 /* On *BSD/powerpc systems, raising FE_INVALID also sets FE_VXSOFT. */
36 #if defined __GLIBC__ && defined __arm__ && defined __SOFTFP__
37 fputs ("Skipping test: no floating-point environment exists on this machine\n", stderr
);
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 (fesetenv (&env1
) == 0);
64 /* Check that the rounding direction has been restored. */
65 ASSERT (fegetround () == FE_TONEAREST
);
66 /* Check that the exception flags have been restored. */
67 ASSERT (fetestexcept (FE_ALL_EXCEPT
) == 0);
68 /* Check that the exception trap bits have been restored. */
69 ASSERT (fegetexcept () == 0);
71 /* Modify the rounding direction, the exception flags, and the exception
73 fesetround (FE_DOWNWARD
);
74 ASSERT (fegetround () == FE_DOWNWARD
);
75 feclearexcept (FE_OVERFLOW
);
76 feraiseexcept (FE_UNDERFLOW
| FE_INEXACT
);
77 ASSERT (fetestexcept (FE_ALL_EXCEPT
) == (supports_tracking
? FE_UNDERFLOW
| FE_INEXACT
: 0));
78 feenableexcept (FE_INVALID
);
79 ASSERT (fegetexcept () == (supports_trapping
? FE_INVALID
: 0));
81 /* Go back to env2. */
82 ASSERT (fesetenv (&env2
) == 0);
84 /* Check that the rounding direction has been restored. */
85 ASSERT (fegetround () == FE_UPWARD
);
86 /* Check that the exception flags have been restored. */
87 if (supports_tracking
)
88 ASSERT ((fetestexcept (FE_ALL_EXCEPT
) & ~FE_VXSOFT
) == (FE_INVALID
| FE_OVERFLOW
| FE_INEXACT
));
90 ASSERT (fetestexcept (FE_ALL_EXCEPT
) == 0);
91 /* Check that the exception trap bits have been restored. */
92 ASSERT (fegetexcept () == (supports_trapping
? FE_DIVBYZERO
: 0));
94 /* ======================================================================== */
97 /* Enable trapping on FE_INVALID. */
98 feclearexcept (FE_INVALID
);
99 feenableexcept (FE_INVALID
);
100 ASSERT (fetestexcept (FE_ALL_EXCEPT
) == (supports_tracking
? FE_OVERFLOW
| FE_INEXACT
: 0));
102 /* Go back to the default environment. */
103 ASSERT (fesetenv (FE_DFL_ENV
) == 0);
105 /* Check its contents. */
106 ASSERT (fegetround () == FE_TONEAREST
);
107 ASSERT (fetestexcept (FE_ALL_EXCEPT
) == 0);
109 /* Check that it has trapping on FE_INVALID disabled. */
110 ASSERT (fegetexcept () == 0);
113 _GL_UNUSED
double volatile b
;
117 /* ======================================================================== */
118 /* Check that feholdexcept, unlike fegetenv, disables trapping. */
120 /* musl libc does not support floating-point exception trapping, even where
121 the hardware supports it. See
122 <https://wiki.musl-libc.org/functional-differences-from-glibc.html> */
123 # if !MUSL_LIBC || GNULIB_FEENABLEEXCEPT
124 /* Enable trapping on FE_INVALID. */
125 feclearexcept (FE_INVALID
);
126 if (feenableexcept (FE_INVALID
) != -1)
128 /* Call feholdexcept. */
129 ASSERT (feholdexcept (&env1
) == 0);
131 /* Check that it has disabled trapping on FE_INVALID. */
132 ASSERT (fegetexcept () == 0);
135 _GL_UNUSED
double volatile b
;
141 return test_exit_status
;