1 /* Test fegetexceptflag and fesetexceptflag.
2 Copyright (C) 2016-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <fenv.h>
20 #include <stdio.h>
21 #include <math-tests.h>
22
23 /* Like feraiseexcept, but raise exactly the specified exceptions EXC,
24 without possibly raising "inexact" together with "overflow" or
25 "underflow" as permitted by ISO C. (This is not used with traps
26 enabled, so side-effects from raising and then clearing "inexact"
27 are irrelevant.) */
28
29 static int
feraiseexcept_exact(int exc)30 feraiseexcept_exact (int exc)
31 {
32 #ifdef FE_INEXACT
33 int mask = 0;
34 #ifdef FE_OVERFLOW
35 mask |= FE_OVERFLOW;
36 #endif
37 #ifdef FE_UNDERFLOW
38 mask |= FE_UNDERFLOW;
39 #endif
40 if ((exc & FE_INEXACT) != 0
41 || (exc & mask) == 0
42 || fetestexcept (FE_INEXACT) != 0)
43 return feraiseexcept (exc);
44 int ret = feraiseexcept (exc);
45 feclearexcept (FE_INEXACT);
46 return ret;
47 #else
48 return feraiseexcept (exc);
49 #endif
50 }
51
52 static int
test_set(int initial,const fexcept_t * saved,int mask,int expected)53 test_set (int initial, const fexcept_t *saved, int mask, int expected)
54 {
55 int result = 0;
56 feclearexcept (FE_ALL_EXCEPT);
57 printf ("Testing set: initial exceptions %x, mask %x, expected %x\n",
58 (unsigned int) initial, (unsigned int) mask,
59 (unsigned int) expected);
60 int ret = feraiseexcept_exact (initial);
61 if (ret != 0)
62 {
63 puts ("feraiseexcept failed");
64 if (initial == 0 || EXCEPTION_TESTS (float))
65 {
66 puts ("failure of feraiseexcept was unexpected");
67 result = 1;
68 }
69 else
70 puts ("failure of feraiseexcept OK, skipping further tests");
71 return result;
72 }
73 ret = fesetexceptflag (saved, mask);
74 if (ret != 0)
75 {
76 puts ("fesetexceptflag failed");
77 result = 1;
78 }
79 else
80 puts ("fesetexceptflag succeeded");
81 ret = fetestexcept (FE_ALL_EXCEPT);
82 if (ret != expected)
83 {
84 printf ("raised exceptions %x, expected %x\n",
85 (unsigned int) ret, (unsigned int) expected);
86 result = 1;
87 }
88 return result;
89 }
90
91 static int
test_except(int exc,const char * exc_name)92 test_except (int exc, const char *exc_name)
93 {
94 int result = 0;
95
96 printf ("Testing %s\n", exc_name);
97 feclearexcept (FE_ALL_EXCEPT);
98
99 fexcept_t clear_saved_exc, clear_saved_all;
100 int ret = fegetexceptflag (&clear_saved_exc, exc);
101 if (ret == 0)
102 printf ("fegetexceptflag (%s) succeeded\n", exc_name);
103 else
104 {
105 printf ("fegetexceptflag (%s) failed\n", exc_name);
106 result = 1;
107 return result;
108 }
109 ret = fegetexceptflag (&clear_saved_all, FE_ALL_EXCEPT);
110 if (ret == 0)
111 puts ("fegetexceptflag (FE_ALL_EXCEPT) succeeded");
112 else
113 {
114 puts ("fegetexceptflag (FE_ALL_EXCEPT) failed");
115 result = 1;
116 return result;
117 }
118
119 ret = feraiseexcept_exact (exc);
120 if (ret == 0)
121 printf ("feraiseexcept (%s) succeeded\n", exc_name);
122 else
123 {
124 printf ("feraiseexcept (%s) failed\n", exc_name);
125 if (exc == 0 || EXCEPTION_TESTS (float))
126 {
127 puts ("failure of feraiseexcept was unexpected");
128 result = 1;
129 }
130 else
131 puts ("failure of feraiseexcept OK, skipping further tests");
132 return result;
133 }
134
135 fexcept_t set_saved_exc, set_saved_all;
136 ret = fegetexceptflag (&set_saved_exc, exc);
137 if (ret == 0)
138 printf ("fegetexceptflag (%s) succeeded\n", exc_name);
139 else
140 {
141 printf ("fegetexceptflag (%s) failed\n", exc_name);
142 result = 1;
143 return result;
144 }
145 ret = fegetexceptflag (&set_saved_all, FE_ALL_EXCEPT);
146 if (ret == 0)
147 puts ("fegetexceptflag (FE_ALL_EXCEPT) succeeded");
148 else
149 {
150 puts ("fegetexceptflag (FE_ALL_EXCEPT) failed");
151 result = 1;
152 return result;
153 }
154
155 result |= test_set (0, &set_saved_exc, exc, exc);
156 result |= test_set (0, &set_saved_all, exc, exc);
157 result |= test_set (0, &set_saved_all, FE_ALL_EXCEPT, exc);
158 result |= test_set (0, &clear_saved_exc, exc, 0);
159 result |= test_set (0, &clear_saved_all, exc, 0);
160 result |= test_set (0, &clear_saved_all, FE_ALL_EXCEPT, 0);
161 result |= test_set (exc, &set_saved_exc, exc, exc);
162 result |= test_set (exc, &set_saved_all, exc, exc);
163 result |= test_set (exc, &set_saved_all, FE_ALL_EXCEPT, exc);
164 result |= test_set (exc, &clear_saved_exc, exc, 0);
165 result |= test_set (exc, &clear_saved_all, exc, 0);
166 result |= test_set (exc, &clear_saved_all, FE_ALL_EXCEPT, 0);
167 result |= test_set (FE_ALL_EXCEPT, &set_saved_exc, exc, FE_ALL_EXCEPT);
168 result |= test_set (FE_ALL_EXCEPT, &set_saved_all, exc, FE_ALL_EXCEPT);
169 result |= test_set (FE_ALL_EXCEPT, &set_saved_all, FE_ALL_EXCEPT, exc);
170 result |= test_set (FE_ALL_EXCEPT, &clear_saved_exc, exc,
171 FE_ALL_EXCEPT & ~exc);
172 result |= test_set (FE_ALL_EXCEPT, &clear_saved_all, exc,
173 FE_ALL_EXCEPT & ~exc);
174 result |= test_set (FE_ALL_EXCEPT, &clear_saved_all, FE_ALL_EXCEPT, 0);
175
176 return result;
177 }
178
179 static int
do_test(void)180 do_test (void)
181 {
182 int result = 0;
183
184 result |= test_except (0, "0");
185 result |= test_except (FE_ALL_EXCEPT, "FE_ALL_EXCEPT");
186 #ifdef FE_DIVBYZERO
187 result |= test_except (FE_DIVBYZERO, "FE_DIVBYZERO");
188 #endif
189 #ifdef FE_INEXACT
190 result |= test_except (FE_INEXACT, "FE_INEXACT");
191 #endif
192 #ifdef FE_INVALID
193 result |= test_except (FE_INVALID, "FE_INVALID");
194 #endif
195 #ifdef FE_OVERFLOW
196 result |= test_except (FE_OVERFLOW, "FE_OVERFLOW");
197 #endif
198 #ifdef FE_UNDERFLOW
199 result |= test_except (FE_UNDERFLOW, "FE_UNDERFLOW");
200 #endif
201
202 return result;
203 }
204
205 #define TEST_FUNCTION do_test ()
206 #include "../test-skeleton.c"
207