• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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__)
print(char * f,int l,char * fmt,...)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 	{0, 0}
41 };
42 
test_except()43 static void test_except()
44 {
45 	#pragma STDC FENV_ACCESS ON
46 	int i,r;
47 	fenv_t env;
48 
49 	for (i=0; te[i].i; i++) {
50 		feclearexcept(FE_ALL_EXCEPT);
51 
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 #if defined FE_OVERFLOW && defined FE_INEXACT
58 			if (te[i].i == FE_OVERFLOW && r == (FE_OVERFLOW|FE_INEXACT))
59 				continue;
60 #endif
61 #if defined FE_UNDERFLOW && defined FE_INEXACT
62 			if (te[i].i == FE_UNDERFLOW && r == (FE_UNDERFLOW|FE_INEXACT))
63 				continue;
64 #endif
65 			error("feraiseexcept(%s) want %d got %d\n",
66 				te[i].name, te[i].i, r);
67 		}
68 	}
69 
70 	r = feraiseexcept(FE_ALL_EXCEPT);
71 	if (r != 0)
72 		error("feraisexcept(FE_ALL_EXCEPT) failed\n");
73 	r = fegetenv(&env);
74 	if (r != 0)
75 		error("fegetenv(&env) = %d\n", r);
76 	r = fetestexcept(FE_ALL_EXCEPT);
77 	if (r != FE_ALL_EXCEPT)
78 		error("fetestexcept failed: got 0x%x, want 0x%x (FE_ALL_ECXEPT)\n", r, FE_ALL_EXCEPT);
79 	r = fesetenv(FE_DFL_ENV);
80 	if (r != 0)
81 		error("fesetenv(FE_DFL_ENV) = %d\n", r);
82 	r = fetestexcept(FE_ALL_EXCEPT);
83 	if (r != 0)
84 		error("fesetenv(FE_DFL_ENV) did not clear exceptions: 0x%x\n", r);
85 	r = fesetenv(&env);
86 	if (r != 0)
87 		error("fesetenv(&env) = %d\n", r);
88 	r = fetestexcept(FE_ALL_EXCEPT);
89 	if (r != FE_ALL_EXCEPT)
90 		error("fesetenv(&env) did not restore exceptions: 0x%x\n", r);
91 }
92 
93 static struct {
94 	char *name;
95 	int i;
96 } tr[] = {
97 	F(FE_TONEAREST),
98 #ifdef FE_UPWARD
99 	F(FE_UPWARD),
100 #endif
101 #ifdef FE_DOWNWARD
102 	F(FE_DOWNWARD),
103 #endif
104 #ifdef FE_TOWARDZERO
105 	F(FE_TOWARDZERO),
106 #endif
107 };
108 
test_round()109 static void test_round()
110 {
111 	#pragma STDC FENV_ACCESS ON
112 	int i,r;
113 	fenv_t env;
114 	volatile float two100 = 0x1p100;
115 	volatile float x;
116 
117 	for (i=0; i < sizeof tr/sizeof*tr; i++) {
118 		if (tr[i].i < 0)
119 			error("%s (%d) < 0\n", tr[i].name, tr[i].i);
120 		for (r=0; r < i; r++)
121 			if (tr[r].i == tr[i].i)
122 				error("%s (%d) == %s (%d)\n",
123 					tr[r].name, tr[r].i, tr[i].name, tr[i].i);
124 	}
125 
126 	for (i=0; i < sizeof tr/sizeof*tr; i++) {
127 		r = fesetround(tr[i].i);
128 		if (r != 0)
129 			error("fesetround(%s) = %d\n", tr[i].name, r);
130 		r = fegetround();
131 		if (r != tr[i].i)
132 			error("fegetround() = 0x%x, wanted 0x%x (%s)\n", r, tr[i].i, tr[i].name);
133 	}
134 
135 #ifdef FE_UPWARD
136 	r = fesetround(FE_UPWARD);
137 	if (r != 0)
138 		error("fesetround(FE_UPWARD) failed\n");
139 #endif
140 	r = fegetenv(&env);
141 	if (r != 0)
142 		error("fegetenv(&env) = %d\n", r);
143 	i = fegetround();
144 	r = fesetenv(FE_DFL_ENV);
145 	if (r != 0)
146 		error("fesetenv(FE_DFL_ENV) = %d\n", r);
147 	r = fegetround();
148 	if (r != FE_TONEAREST)
149 		error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST (0x%x), got 0x%x\n", FE_TONEAREST, r);
150 	x = two100 + 1;
151 	if (x != two100)
152 		error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST, arithmetics rounds upward\n");
153 	x = two100 - 1;
154 	if (x != two100)
155 		error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST, arithmetics rounds downward or tozero\n");
156 	r = fesetenv(&env);
157 	if (r != 0)
158 		error("fesetenv(&env) = %d\n", r);
159 	r = fegetround();
160 	if (r != i)
161 		error("fesetenv(&env) did not restore 0x%x, got 0x%x\n", i, r);
162 #ifdef FE_UPWARD
163 	x = two100 + 1;
164 	if (x == two100)
165 		error("fesetenv did not restore upward rounding\n");
166 #endif
167 
168 }
169 
170 /* ieee double precision add operation */
171 static struct dd_d t[] = {
172 T(RN,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
173 T(RN,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
174 T(RN,                  0x1p+0,              0x1.01p-53,    0x1.0000000000001p+0,       0x1.fep-2, INEXACT)
175 T(RN,                  0x1p+0,                -0x1p-54,                  0x1p+0,          0x1p-2, INEXACT)
176 T(RN,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
177 T(RN,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
178 T(RN,                 -0x1p+0,             -0x1.01p-53,   -0x1.0000000000001p+0,      -0x1.fep-2, INEXACT)
179 T(RN,                 -0x1p+0,                 0x1p-54,                 -0x1p+0,         -0x1p-2, INEXACT)
180 T(RN,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
181 
182 T(RU,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
183 T(RU,                  0x1p+0,                 0x1p-53,    0x1.0000000000001p+0,          0x1p-1, INEXACT)
184 T(RU,                  0x1p+0,              0x1.01p-53,    0x1.0000000000001p+0,       0x1.fep-2, INEXACT)
185 T(RU,                  0x1p+0,                -0x1p-54,                  0x1p+0,          0x1p-2, INEXACT)
186 T(RU,                  0x1p+0,             -0x1.01p-54,                  0x1p+0,       0x1.01p-2, INEXACT)
187 T(RU,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
188 T(RU,                 -0x1p+0,             -0x1.01p-53,                 -0x1p+0,       0x1.01p-1, INEXACT)
189 T(RU,                 -0x1p+0,                 0x1p-54,   -0x1.fffffffffffffp-1,          0x1p-1, INEXACT)
190 T(RU,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
191 
192 T(RD,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
193 T(RD,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
194 T(RD,                  0x1p+0,              0x1.01p-53,                  0x1p+0,      -0x1.01p-1, INEXACT)
195 T(RD,                  0x1p+0,                -0x1p-54,    0x1.fffffffffffffp-1,         -0x1p-1, INEXACT)
196 T(RD,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
197 T(RD,                 -0x1p+0,                -0x1p-53,   -0x1.0000000000001p+0,         -0x1p-1, INEXACT)
198 T(RD,                 -0x1p+0,             -0x1.01p-53,   -0x1.0000000000001p+0,      -0x1.fep-2, INEXACT)
199 T(RD,                 -0x1p+0,                 0x1p-54,                 -0x1p+0,         -0x1p-2, INEXACT)
200 T(RD,                 -0x1p+0,              0x1.01p-54,                 -0x1p+0,      -0x1.01p-2, INEXACT)
201 
202 T(RZ,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
203 T(RZ,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
204 T(RZ,                  0x1p+0,              0x1.01p-53,                  0x1p+0,      -0x1.01p-1, INEXACT)
205 T(RZ,                  0x1p+0,                -0x1p-54,    0x1.fffffffffffffp-1,         -0x1p-1, INEXACT)
206 T(RZ,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
207 T(RZ,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
208 T(RZ,                 -0x1p+0,             -0x1.01p-53,                 -0x1p+0,       0x1.01p-1, INEXACT)
209 T(RZ,                 -0x1p+0,                 0x1p-54,   -0x1.fffffffffffffp-1,          0x1p-1, INEXACT)
210 T(RZ,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
211 };
212 
test_round_add(void)213 static void test_round_add(void)
214 {
215 	#pragma STDC FENV_ACCESS ON
216 	double y;
217 	float d;
218 	int i;
219 	struct dd_d *p;
220 
221 	for (i = 0; i < sizeof t/sizeof *t; i++) {
222 		p = t + i;
223 
224 		if (p->r < 0)
225 			continue;
226 		fesetround(p->r);
227 		y = p->x + p->x2;
228 		d = ulperr(y, p->y, p->dy);
229 		if (!checkcr(y, p->y, p->r)) {
230 			printf("%s:%d: %s %a+%a want %a got %a ulperr %.3f = %a + %a\n",
231 				p->file, p->line, rstr(p->r), p->x, p->x2, p->y, y, d, d-p->dy, p->dy);
232 			test_status = 1;
233 		}
234 	}
235 }
236 
test_bad(void)237 static void test_bad(void)
238 {
239 	fexcept_t f;
240 	int r;
241 
242 	r = feclearexcept(FE_ALL_EXCEPT);
243 	if (r != 0)
244 		error("feclearexcept(FE_ALL_EXCEPT) failed\n");
245 	r = fetestexcept(-1);
246 	if (r != 0)
247 		error("fetestexcept(-1) should return 0 when all exceptions are cleared, got %d\n", r);
248 	r = feraiseexcept(1234567|FE_ALL_EXCEPT);
249 	if (r != 0)
250 		error("feraiseexcept returned non-zero for non-supported exceptions: %d\n", r);
251 	r = feclearexcept(1234567|FE_ALL_EXCEPT);
252 	if (r != 0)
253 		error("feclearexcept returned non-zero for non-supported exceptions: %d\n", r);
254 	r = fesetround(1234567);
255 	if (r == 0)
256 		error("fesetround should fail on invalid rounding mode\n");
257 	r = fegetexceptflag(&f, 1234567);
258 	if (r != 0)
259 		error("fegetexceptflag returned non-zero for non-supported exceptions: %d\n", r);
260 	r = fegetexceptflag(&f, 0);
261 	if (r != 0)
262 		error("fegetexceptflag(0) failed\n");
263 	r = fesetexceptflag(&f, 1234567);
264 	if (r != 0)
265 		error("fesetexceptflag returned non-zero fir non-supported exceptions: %d\n", r);
266 }
267 
main(void)268 int main(void)
269 {
270 	test_except();
271 	test_round();
272 	test_round_add();
273 	test_bad();
274 	return test_status;
275 }
276