fix ulp check in sincosf
[libc-test.git] / src / math / fenv.c
blob91b6378323f07849fcc774a3f78928f8b077aeb6
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include "mtest.h"
6 static int test_status;
8 #define error(...) print(__FILE__, __LINE__, __VA_ARGS__)
9 static void print(char *f, int l, char *fmt, ...)
11 test_status = 1;
12 va_list ap;
13 printf("%s:%d: ", f, l);
14 va_start(ap, fmt);
15 vprintf(fmt, ap);
16 va_end(ap);
19 #define F(n) {#n, n}
21 static struct {
22 char *name;
23 int i;
24 } te[] = {
25 #ifdef FE_DIVBYZERO
26 F(FE_DIVBYZERO),
27 #endif
28 #ifdef FE_INEXACT
29 F(FE_INEXACT),
30 #endif
31 #ifdef FE_INVALID
32 F(FE_INVALID),
33 #endif
34 #ifdef FE_OVERFLOW
35 F(FE_OVERFLOW),
36 #endif
37 #ifdef FE_UNDERFLOW
38 F(FE_UNDERFLOW),
39 #endif
40 {0, 0}
43 static void test_except()
45 #pragma STDC FENV_ACCESS ON
46 int i,r;
47 fenv_t env;
49 for (i=0; te[i].i; i++) {
50 feclearexcept(FE_ALL_EXCEPT);
52 r = feraiseexcept(te[i].i);
53 if (r)
54 error("feraiseexcept(%s) returned %d\n", te[i].name, r);
55 r = fetestexcept(FE_ALL_EXCEPT);
56 if (r != te[i].i)
57 error("feraiseexcept(%s) want %d got %d\n",
58 te[i].name, te[i].i, r);
61 r = feraiseexcept(FE_ALL_EXCEPT);
62 if (r != 0)
63 error("feraisexcept(FE_ALL_EXCEPT) failed\n");
64 r = fegetenv(&env);
65 if (r != 0)
66 error("fegetenv(&env) = %d\n", r);
67 r = fetestexcept(FE_ALL_EXCEPT);
68 if (r != FE_ALL_EXCEPT)
69 error("fetestexcept failed: got 0x%x, want 0x%x (FE_ALL_ECXEPT)\n", r, FE_ALL_EXCEPT);
70 r = fesetenv(FE_DFL_ENV);
71 if (r != 0)
72 error("fesetenv(FE_DFL_ENV) = %d\n", r);
73 r = fetestexcept(FE_ALL_EXCEPT);
74 if (r != 0)
75 error("fesetenv(FE_DFL_ENV) did not clear exceptions: 0x%x\n", r);
76 r = fesetenv(&env);
77 if (r != 0)
78 error("fesetenv(&env) = %d\n", r);
79 r = fetestexcept(FE_ALL_EXCEPT);
80 if (r != FE_ALL_EXCEPT)
81 error("fesetenv(&env) did not restore exceptions: 0x%x\n", r);
84 static struct {
85 char *name;
86 int i;
87 } tr[] = {
88 F(FE_TONEAREST),
89 #ifdef FE_UPWARD
90 F(FE_UPWARD),
91 #endif
92 #ifdef FE_DOWNWARD
93 F(FE_DOWNWARD),
94 #endif
95 #ifdef FE_TOWARDZERO
96 F(FE_TOWARDZERO),
97 #endif
100 static void test_round()
102 #pragma STDC FENV_ACCESS ON
103 int i,r;
104 fenv_t env;
105 volatile float two100 = 0x1p100;
106 volatile float x;
108 for (i=0; i < sizeof tr/sizeof*tr; i++) {
109 if (tr[i].i < 0)
110 error("%s (%d) < 0\n", tr[i].name, tr[i].i);
111 for (r=0; r < i; r++)
112 if (tr[r].i == tr[i].i)
113 error("%s (%d) == %s (%d)\n",
114 tr[r].name, tr[r].i, tr[i].name, tr[i].i);
117 for (i=0; i < sizeof tr/sizeof*tr; i++) {
118 r = fesetround(tr[i].i);
119 if (r != 0)
120 error("fesetround(%s) = %d\n", tr[i].name, r);
121 r = fegetround();
122 if (r != tr[i].i)
123 error("fegetround() = 0x%x, wanted 0x%x (%s)\n", r, tr[i].i, tr[i].name);
126 #ifdef FE_UPWARD
127 r = fesetround(FE_UPWARD);
128 if (r != 0)
129 error("fesetround(FE_UPWARD) failed\n");
130 #endif
131 r = fegetenv(&env);
132 if (r != 0)
133 error("fegetenv(&env) = %d\n", r);
134 i = fegetround();
135 r = fesetenv(FE_DFL_ENV);
136 if (r != 0)
137 error("fesetenv(FE_DFL_ENV) = %d\n", r);
138 r = fegetround();
139 if (r != FE_TONEAREST)
140 error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST (0x%x), got 0x%x\n", FE_TONEAREST, r);
141 x = two100 + 1;
142 if (x != two100)
143 error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST, arithmetics rounds upward\n");
144 x = two100 - 1;
145 if (x != two100)
146 error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST, arithmetics rounds downward or tozero\n");
147 r = fesetenv(&env);
148 if (r != 0)
149 error("fesetenv(&env) = %d\n", r);
150 r = fegetround();
151 if (r != i)
152 error("fesetenv(&env) did not restore 0x%x, got 0x%x\n", i, r);
153 #ifdef FE_UPWARD
154 x = two100 + 1;
155 if (x == two100)
156 error("fesetenv did not restore upward rounding\n");
157 #endif
161 /* ieee double precision add operation */
162 static struct dd_d t[] = {
163 T(RN, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0)
164 T(RN, 0x1p+0, 0x1p-53, 0x1p+0, -0x1p-1, INEXACT)
165 T(RN, 0x1p+0, 0x1.01p-53, 0x1.0000000000001p+0, 0x1.fep-2, INEXACT)
166 T(RN, 0x1p+0, -0x1p-54, 0x1p+0, 0x1p-2, INEXACT)
167 T(RN, 0x1p+0, -0x1.01p-54, 0x1.fffffffffffffp-1, -0x1.fep-2, INEXACT)
168 T(RN, -0x1p+0, -0x1p-53, -0x1p+0, 0x1p-1, INEXACT)
169 T(RN, -0x1p+0, -0x1.01p-53, -0x1.0000000000001p+0, -0x1.fep-2, INEXACT)
170 T(RN, -0x1p+0, 0x1p-54, -0x1p+0, -0x1p-2, INEXACT)
171 T(RN, -0x1p+0, 0x1.01p-54, -0x1.fffffffffffffp-1, 0x1.fep-2, INEXACT)
173 T(RU, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0)
174 T(RU, 0x1p+0, 0x1p-53, 0x1.0000000000001p+0, 0x1p-1, INEXACT)
175 T(RU, 0x1p+0, 0x1.01p-53, 0x1.0000000000001p+0, 0x1.fep-2, INEXACT)
176 T(RU, 0x1p+0, -0x1p-54, 0x1p+0, 0x1p-2, INEXACT)
177 T(RU, 0x1p+0, -0x1.01p-54, 0x1p+0, 0x1.01p-2, INEXACT)
178 T(RU, -0x1p+0, -0x1p-53, -0x1p+0, 0x1p-1, INEXACT)
179 T(RU, -0x1p+0, -0x1.01p-53, -0x1p+0, 0x1.01p-1, INEXACT)
180 T(RU, -0x1p+0, 0x1p-54, -0x1.fffffffffffffp-1, 0x1p-1, INEXACT)
181 T(RU, -0x1p+0, 0x1.01p-54, -0x1.fffffffffffffp-1, 0x1.fep-2, INEXACT)
183 T(RD, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0)
184 T(RD, 0x1p+0, 0x1p-53, 0x1p+0, -0x1p-1, INEXACT)
185 T(RD, 0x1p+0, 0x1.01p-53, 0x1p+0, -0x1.01p-1, INEXACT)
186 T(RD, 0x1p+0, -0x1p-54, 0x1.fffffffffffffp-1, -0x1p-1, INEXACT)
187 T(RD, 0x1p+0, -0x1.01p-54, 0x1.fffffffffffffp-1, -0x1.fep-2, INEXACT)
188 T(RD, -0x1p+0, -0x1p-53, -0x1.0000000000001p+0, -0x1p-1, INEXACT)
189 T(RD, -0x1p+0, -0x1.01p-53, -0x1.0000000000001p+0, -0x1.fep-2, INEXACT)
190 T(RD, -0x1p+0, 0x1p-54, -0x1p+0, -0x1p-2, INEXACT)
191 T(RD, -0x1p+0, 0x1.01p-54, -0x1p+0, -0x1.01p-2, INEXACT)
193 T(RZ, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0)
194 T(RZ, 0x1p+0, 0x1p-53, 0x1p+0, -0x1p-1, INEXACT)
195 T(RZ, 0x1p+0, 0x1.01p-53, 0x1p+0, -0x1.01p-1, INEXACT)
196 T(RZ, 0x1p+0, -0x1p-54, 0x1.fffffffffffffp-1, -0x1p-1, INEXACT)
197 T(RZ, 0x1p+0, -0x1.01p-54, 0x1.fffffffffffffp-1, -0x1.fep-2, INEXACT)
198 T(RZ, -0x1p+0, -0x1p-53, -0x1p+0, 0x1p-1, INEXACT)
199 T(RZ, -0x1p+0, -0x1.01p-53, -0x1p+0, 0x1.01p-1, INEXACT)
200 T(RZ, -0x1p+0, 0x1p-54, -0x1.fffffffffffffp-1, 0x1p-1, INEXACT)
201 T(RZ, -0x1p+0, 0x1.01p-54, -0x1.fffffffffffffp-1, 0x1.fep-2, INEXACT)
204 static void test_round_add(void)
206 #pragma STDC FENV_ACCESS ON
207 double y;
208 float d;
209 int i;
210 struct dd_d *p;
212 for (i = 0; i < sizeof t/sizeof *t; i++) {
213 p = t + i;
215 if (p->r < 0)
216 continue;
217 fesetround(p->r);
218 y = p->x + p->x2;
219 d = ulperr(y, p->y, p->dy);
220 if (!checkcr(y, p->y, p->r)) {
221 printf("%s:%d: %s %a+%a want %a got %a ulperr %.3f = %a + %a\n",
222 p->file, p->line, rstr(p->r), p->x, p->x2, p->y, y, d, d-p->dy, p->dy);
223 test_status = 1;
228 static void test_bad(void)
230 fexcept_t f;
231 int r;
233 r = feclearexcept(FE_ALL_EXCEPT);
234 if (r != 0)
235 error("feclearexcept(FE_ALL_EXCEPT) failed\n");
236 r = fetestexcept(-1);
237 if (r != 0)
238 error("fetestexcept(-1) should return 0 when all exceptions are cleared, got %d\n", r);
239 r = feraiseexcept(1234567|FE_ALL_EXCEPT);
240 if (r != 0)
241 error("feraiseexcept returned non-zero for non-supported exceptions: %d\n", r);
242 r = feclearexcept(1234567|FE_ALL_EXCEPT);
243 if (r != 0)
244 error("feclearexcept returned non-zero for non-supported exceptions: %d\n", r);
245 r = fesetround(1234567);
246 if (r == 0)
247 error("fesetround should fail on invalid rounding mode\n");
248 r = fegetexceptflag(&f, 1234567);
249 if (r != 0)
250 error("fegetexceptflag returned non-zero for non-supported exceptions: %d\n", r);
251 r = fegetexceptflag(&f, 0);
252 if (r != 0)
253 error("fegetexceptflag(0) failed\n");
254 r = fesetexceptflag(&f, 1234567);
255 if (r != 0)
256 error("fesetexceptflag returned non-zero fir non-supported exceptions: %d\n", r);
259 int main(void)
261 test_except();
262 test_round();
263 test_round_add();
264 test_bad();
265 return test_status;