usleep tests: Avoid failure due to known Cygwin 3.5.3 bug.
[gnulib.git] / tests / test-fenv-env-3.c
blobd88013c50732b477c268bb6f0278dd9e28b5838f
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 fegetenv() 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 (fegetenv (&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 (fegetenv (&env2) == 0);
56 /* Check that the exception flags are unmodified. */
57 if (supports_tracking)
58 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_INEXACT));
59 else
60 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
61 /* Check that the exception trap bits are unmodified. */
62 ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
64 /* Go back to env1. */
65 ASSERT (feupdateenv (&env1) == 0);
67 /* Check that the rounding direction has been restored. */
68 ASSERT (fegetround () == FE_TONEAREST);
69 /* Check that the exception flags are the union of the saved and of the
70 current exception flags. (The saved exception flags happen to be none
71 in this case.) */
72 if (supports_tracking)
73 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_INEXACT));
74 else
75 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
76 /* Check that the exception trap bits have been restored. */
77 ASSERT (fegetexcept () == 0);
79 /* Modify the rounding direction, the exception flags, and the exception
80 trap bits again. */
81 fesetround (FE_DOWNWARD);
82 ASSERT (fegetround () == FE_DOWNWARD);
83 feclearexcept (FE_INVALID | FE_OVERFLOW);
84 feraiseexcept (FE_UNDERFLOW | FE_INEXACT);
85 ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_UNDERFLOW | FE_INEXACT : 0));
86 feenableexcept (FE_INVALID);
87 ASSERT (fegetexcept () == (supports_trapping ? FE_INVALID : 0));
89 /* Go back to env2. */
90 ASSERT (feupdateenv (&env2) == 0);
92 /* Check that the rounding direction has been restored. */
93 ASSERT (fegetround () == FE_UPWARD);
94 /* Check that the exception flags are the union of the saved and of the
95 current exception flags. */
96 if (supports_tracking)
97 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
98 else
99 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
100 /* Check that the exception trap bits have been restored. */
101 ASSERT (fegetexcept () == (supports_trapping ? FE_DIVBYZERO : 0));
103 /* ======================================================================== */
104 /* FE_DFL_ENV */
106 /* Go back to the default environment. */
107 ASSERT (feupdateenv (FE_DFL_ENV) == 0);
109 /* Check that the rounding direction has been restored,
110 whereas the exception flags are unmodified. */
111 ASSERT (fegetround () == FE_TONEAREST);
112 if (supports_tracking)
113 ASSERT ((fetestexcept (FE_ALL_EXCEPT) & ~FE_VXSOFT) == (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
114 else
115 ASSERT (fetestexcept (FE_ALL_EXCEPT) == 0);
117 /* Enable trapping on FE_INVALID. */
118 feclearexcept (FE_INVALID);
119 feenableexcept (FE_INVALID);
120 ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
122 /* Go back to the default environment. */
123 ASSERT (feupdateenv (FE_DFL_ENV) == 0);
125 /* Check that the rounding direction has been restored,
126 whereas the exception flags are unmodified. */
127 ASSERT (fegetround () == FE_TONEAREST);
128 ASSERT (fetestexcept (FE_ALL_EXCEPT) == (supports_tracking ? FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT : 0));
130 /* Check that it has trapping on FE_INVALID disabled. */
131 ASSERT (fegetexcept () == 0);
133 double volatile a;
134 _GL_UNUSED double volatile b;
135 a = 0; b = a / a;
138 /* ======================================================================== */
139 /* Check that feupdateenv restores the trapping behaviour. */
141 /* Enable trapping on FE_INVALID. */
142 feclearexcept (FE_INVALID);
143 feenableexcept (FE_INVALID);
145 /* Go back to env1. */
146 ASSERT (feupdateenv (&env1) == 0);
148 /* Check that it has disabled trapping on FE_INVALID. */
149 ASSERT (fegetexcept () == 0);
151 double volatile a;
152 _GL_UNUSED double volatile b;
153 a = 0; b = a / a;
156 return test_exit_status;
157 #endif