remove accidentally committed core, add festenv, fegetenv test
[libc-test] / src / math / fenv.c
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include "mtest.h"
5
6 static int test_status;
7
8 #define error(...) print(__FILE__, __LINE__, __VA_ARGS__)
9 static void print(char *f, int l, char *fmt, ...)
10 {
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);
17 }
18
19 #define F(n) {#n, n}
20
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 };
41
42 static void test_except()
43 {
44         #pragma STDC FENV_ACCESS ON
45         int i,r;
46         fenv_t env;
47
48         for (i=0; i < sizeof te/sizeof*te; i++) {
49                 feclearexcept(FE_ALL_EXCEPT);
50
51                 r = feraiseexcept(te[i].i);
52                 if (r)
53                         error("feraiseexcept(%s) returned %d\n", te[i].name, r);
54                 r = fetestexcept(FE_ALL_EXCEPT);
55                 if (r != te[i].i)
56                         error("feraiseexcept(%s) want %d got %d\n",
57                                 te[i].name, te[i].i, r);
58         }
59
60         r = fegetenv(&env);
61         if (r != 0)
62                 error("fegetenv(&env) = %d\n", r);
63         i = fetestexcept(FE_ALL_EXCEPT);
64         r = fesetenv(FE_DFL_ENV);
65         if (r != 0)
66                 error("fesetenv(FE_DFL_ENV) = %d\n", r);
67         r = fetestexcept(FE_ALL_EXCEPT);
68         if (r != 0)
69                 error("fesetenv(FE_DFL_ENV) did not clear exceptions: 0x%x\n", r);
70         r = fesetenv(&env);
71         if (r != 0)
72                 error("fesetenv(&env) = %d\n", r);
73         r = fetestexcept(FE_ALL_EXCEPT);
74         if (r != i)
75                 error("fesetenv(&env) did not restore exceptions: 0x%x\n", r);
76 }
77
78 static struct {
79         char *name;
80         int i;
81 } tr[] = {
82         F(FE_TONEAREST),
83 #ifdef FE_UPWARD
84         F(FE_UPWARD),
85 #endif
86 #ifdef FE_DOWNWARD
87         F(FE_DOWNWARD),
88 #endif
89 #ifdef FE_TOWARDZERO
90         F(FE_TOWARDZERO),
91 #endif
92 };
93
94 static void test_round()
95 {
96         #pragma STDC FENV_ACCESS ON
97         int i,r;
98         fenv_t env;
99
100         for (i=0; i < sizeof tr/sizeof*tr; i++) {
101                 if (tr[i].i < 0)
102                         error("%s (%d) < 0\n", tr[i].name, tr[i].i);
103                 for (r=0; r < i; r++)
104                         if (tr[r].i == tr[i].i)
105                                 error("%s (%d) == %s (%d)\n",
106                                         tr[r].name, tr[r].i, tr[i].name, tr[i].i);
107         }
108
109         for (i=0; i < sizeof tr/sizeof*tr; i++) {
110                 r = fesetround(tr[i].i);
111                 if (r != 0)
112                         error("fesetround(%s) = %d\n", tr[i].name, r);
113                 r = fegetround();
114                 if (r != tr[i].i)
115                         error("fegetround() = 0x%x, wanted 0x%x (%s)\n", r, tr[i].i, tr[i].name);
116         }
117
118         r = fegetenv(&env);
119         if (r != 0)
120                 error("fegetenv(&env) = %d\n", r);
121         i = fegetround();
122         r = fesetenv(FE_DFL_ENV);
123         if (r != 0)
124                 error("fesetenv(FE_DFL_ENV) = %d\n", r);
125         r = fegetround();
126         if (r != FE_TONEAREST)
127                 error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST (0x%x), got 0x%x\n", FE_TONEAREST, r);
128         r = fesetenv(&env);
129         if (r != 0)
130                 error("fesetenv(&env) = %d\n", r);
131         r = fegetround();
132         if (r != i)
133                 error("fesetenv(&env) did not restore 0x%x, got 0x%x\n", i, r);
134 }
135
136 /* ieee double precision add operation */
137 static struct dd_d t[] = {
138 T(RN,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
139 T(RN,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
140 T(RN,                  0x1p+0,              0x1.01p-53,    0x1.0000000000001p+0,       0x1.fep-2, INEXACT)
141 T(RN,                  0x1p+0,                -0x1p-54,                  0x1p+0,          0x1p-2, INEXACT)
142 T(RN,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
143 T(RN,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
144 T(RN,                 -0x1p+0,             -0x1.01p-53,   -0x1.0000000000001p+0,      -0x1.fep-2, INEXACT)
145 T(RN,                 -0x1p+0,                 0x1p-54,                 -0x1p+0,         -0x1p-2, INEXACT)
146 T(RN,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
147
148 T(RU,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
149 T(RU,                  0x1p+0,                 0x1p-53,    0x1.0000000000001p+0,          0x1p-1, INEXACT)
150 T(RU,                  0x1p+0,              0x1.01p-53,    0x1.0000000000001p+0,       0x1.fep-2, INEXACT)
151 T(RU,                  0x1p+0,                -0x1p-54,                  0x1p+0,          0x1p-2, INEXACT)
152 T(RU,                  0x1p+0,             -0x1.01p-54,                  0x1p+0,       0x1.01p-2, INEXACT)
153 T(RU,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
154 T(RU,                 -0x1p+0,             -0x1.01p-53,                 -0x1p+0,       0x1.01p-1, INEXACT)
155 T(RU,                 -0x1p+0,                 0x1p-54,   -0x1.fffffffffffffp-1,          0x1p-1, INEXACT)
156 T(RU,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
157
158 T(RD,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
159 T(RD,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
160 T(RD,                  0x1p+0,              0x1.01p-53,                  0x1p+0,      -0x1.01p-1, INEXACT)
161 T(RD,                  0x1p+0,                -0x1p-54,    0x1.fffffffffffffp-1,         -0x1p-1, INEXACT)
162 T(RD,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
163 T(RD,                 -0x1p+0,                -0x1p-53,   -0x1.0000000000001p+0,         -0x1p-1, INEXACT)
164 T(RD,                 -0x1p+0,             -0x1.01p-53,   -0x1.0000000000001p+0,      -0x1.fep-2, INEXACT)
165 T(RD,                 -0x1p+0,                 0x1p-54,                 -0x1p+0,         -0x1p-2, INEXACT)
166 T(RD,                 -0x1p+0,              0x1.01p-54,                 -0x1p+0,      -0x1.01p-2, INEXACT)
167
168 T(RZ,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
169 T(RZ,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
170 T(RZ,                  0x1p+0,              0x1.01p-53,                  0x1p+0,      -0x1.01p-1, INEXACT)
171 T(RZ,                  0x1p+0,                -0x1p-54,    0x1.fffffffffffffp-1,         -0x1p-1, INEXACT)
172 T(RZ,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
173 T(RZ,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
174 T(RZ,                 -0x1p+0,             -0x1.01p-53,                 -0x1p+0,       0x1.01p-1, INEXACT)
175 T(RZ,                 -0x1p+0,                 0x1p-54,   -0x1.fffffffffffffp-1,          0x1p-1, INEXACT)
176 T(RZ,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
177 };
178
179 static void test_round_add(void)
180 {
181         #pragma STDC FENV_ACCESS ON
182         double y;
183         float d;
184         int i;
185         struct dd_d *p;
186
187         for (i = 0; i < sizeof t/sizeof *t; i++) {
188                 p = t + i;
189
190                 if (p->r < 0)
191                         continue;
192                 fesetround(p->r);
193                 y = p->x + p->x2;
194                 d = ulperr(y, p->y, p->dy);
195                 if (!checkcr(y, p->y, p->r)) {
196                         printf("%s:%d: %s %a+%a want %a got %a ulperr %.3f = %a + %a\n",
197                                 p->file, p->line, rstr(p->r), p->x, p->x2, p->y, y, d, d-p->dy, p->dy);
198                         test_status = 1;
199                 }
200         }
201 }
202
203 int main(void)
204 {
205         test_except();
206         test_round();
207         test_round_add();
208         return test_status;
209 }