2 * Copyright (c) 2008 David Schultz <das@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Tests for fma{,f,l}().
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
41 #define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
42 FE_OVERFLOW | FE_UNDERFLOW)
44 #pragma STDC FENV_ACCESS ON
47 * Test that a function returns the correct value and sets the
48 * exception flags correctly. The exceptmask specifies which
49 * exceptions we should check. We need to be lenient for several
50 * reasons, but mainly because on some architectures it's impossible
51 * to raise FE_OVERFLOW without raising FE_INEXACT.
53 * These are macros instead of functions so that assert provides more
54 * meaningful error messages.
56 #define test(func, x, y, z, result, exceptmask, excepts) do { \
57 assert(feclearexcept(FE_ALL_EXCEPT) == 0); \
58 assert(fpequal((func)((x), (y), (z)), (result))); \
59 assert(((func), fetestexcept(exceptmask) == (excepts))); \
62 #define testall(x, y, z, result, exceptmask, excepts) do { \
63 test(fma, (x), (y), (z), (double)(result), (exceptmask), (excepts)); \
64 test(fmaf, (x), (y), (z), (float)(result), (exceptmask), (excepts)); \
65 test(fmal, (x), (y), (z), (result), (exceptmask), (excepts)); \
68 /* Test in all rounding modes. */
69 #define testrnd(func, x, y, z, rn, ru, rd, rz, exceptmask, excepts) do { \
70 fesetround(FE_TONEAREST); \
71 test((func), (x), (y), (z), (rn), (exceptmask), (excepts)); \
72 fesetround(FE_UPWARD); \
73 test((func), (x), (y), (z), (ru), (exceptmask), (excepts)); \
74 fesetround(FE_DOWNWARD); \
75 test((func), (x), (y), (z), (rd), (exceptmask), (excepts)); \
76 fesetround(FE_TOWARDZERO); \
77 test((func), (x), (y), (z), (rz), (exceptmask), (excepts)); \
81 * Determine whether x and y are equal, with two special rules:
86 fpequal(long double x, long double y)
89 return ((x == y && !signbit(x) == !signbit(y))
90 || (isnan(x) && isnan(y)));
96 const int rd = (fegetround() == FE_DOWNWARD);
98 testall(0.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
99 testall(1.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
100 testall(0.0, 1.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
101 testall(0.0, 0.0, 1.0, 1.0, ALL_STD_EXCEPT, 0);
103 testall(-0.0, 0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
104 testall(0.0, -0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
105 testall(-0.0, -0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
106 testall(0.0, 0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
107 testall(-0.0, -0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
109 testall(-0.0, 0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0);
110 testall(0.0, -0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0);
112 testall(-1.0, 1.0, 1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
113 testall(1.0, -1.0, 1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
114 testall(-1.0, -1.0, -1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
116 switch (fegetround()) {
119 test(fmaf, -FLT_MIN, FLT_MIN, 0.0, -0.0,
120 ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW);
121 test(fma, -DBL_MIN, DBL_MIN, 0.0, -0.0,
122 ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW);
123 test(fmal, -LDBL_MIN, LDBL_MIN, 0.0, -0.0,
124 ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW);
129 test_infinities(void)
132 testall(INFINITY, 1.0, -1.0, INFINITY, ALL_STD_EXCEPT, 0);
133 testall(-1.0, INFINITY, 0.0, -INFINITY, ALL_STD_EXCEPT, 0);
134 testall(0.0, 0.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
135 testall(1.0, 1.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
136 testall(1.0, 1.0, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0);
138 testall(INFINITY, -INFINITY, 1.0, -INFINITY, ALL_STD_EXCEPT, 0);
139 testall(INFINITY, INFINITY, 1.0, INFINITY, ALL_STD_EXCEPT, 0);
140 testall(-INFINITY, -INFINITY, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
142 testall(0.0, INFINITY, 1.0, NAN, ALL_STD_EXCEPT, FE_INVALID);
143 testall(INFINITY, 0.0, -0.0, NAN, ALL_STD_EXCEPT, FE_INVALID);
145 /* The invalid exception is optional in this case. */
146 testall(INFINITY, 0.0, NAN, NAN, ALL_STD_EXCEPT & ~FE_INVALID, 0);
148 testall(INFINITY, INFINITY, -INFINITY, NAN,
149 ALL_STD_EXCEPT, FE_INVALID);
150 testall(-INFINITY, INFINITY, INFINITY, NAN,
151 ALL_STD_EXCEPT, FE_INVALID);
152 testall(INFINITY, -1.0, INFINITY, NAN,
153 ALL_STD_EXCEPT, FE_INVALID);
155 test(fmaf, FLT_MAX, FLT_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0);
156 test(fma, DBL_MAX, DBL_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0);
157 test(fmal, LDBL_MAX, LDBL_MAX, -INFINITY, -INFINITY,
159 test(fmaf, FLT_MAX, -FLT_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
160 test(fma, DBL_MAX, -DBL_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
161 test(fmal, LDBL_MAX, -LDBL_MAX, INFINITY, INFINITY,
169 testall(NAN, 0.0, 0.0, NAN, ALL_STD_EXCEPT, 0);
170 testall(1.0, NAN, 1.0, NAN, ALL_STD_EXCEPT, 0);
171 testall(1.0, -1.0, NAN, NAN, ALL_STD_EXCEPT, 0);
172 testall(0.0, 0.0, NAN, NAN, ALL_STD_EXCEPT, 0);
173 testall(NAN, NAN, NAN, NAN, ALL_STD_EXCEPT, 0);
175 /* x*y should not raise an inexact/overflow/underflow if z is NaN. */
176 testall(M_PI, M_PI, NAN, NAN, ALL_STD_EXCEPT, 0);
177 test(fmaf, FLT_MIN, FLT_MIN, NAN, NAN, ALL_STD_EXCEPT, 0);
178 test(fma, DBL_MIN, DBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0);
179 test(fmal, LDBL_MIN, LDBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0);
180 test(fmaf, FLT_MAX, FLT_MAX, NAN, NAN, ALL_STD_EXCEPT, 0);
181 test(fma, DBL_MAX, DBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0);
182 test(fmal, LDBL_MAX, LDBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0);
186 * Tests for cases where z is very small compared to x*y.
192 /* x*y positive, z positive */
193 if (fegetround() == FE_UPWARD) {
194 test(fmaf, 1.0, 1.0, 0x1.0p-100, 1.0 + FLT_EPSILON,
195 ALL_STD_EXCEPT, FE_INEXACT);
196 test(fma, 1.0, 1.0, 0x1.0p-200, 1.0 + DBL_EPSILON,
197 ALL_STD_EXCEPT, FE_INEXACT);
198 test(fmal, 1.0, 1.0, 0x1.0p-200, 1.0 + LDBL_EPSILON,
199 ALL_STD_EXCEPT, FE_INEXACT);
201 testall(0x1.0p100, 1.0, 0x1.0p-100, 0x1.0p100,
202 ALL_STD_EXCEPT, FE_INEXACT);
205 /* x*y negative, z negative */
206 if (fegetround() == FE_DOWNWARD) {
207 test(fmaf, -1.0, 1.0, -0x1.0p-100, -(1.0 + FLT_EPSILON),
208 ALL_STD_EXCEPT, FE_INEXACT);
209 test(fma, -1.0, 1.0, -0x1.0p-200, -(1.0 + DBL_EPSILON),
210 ALL_STD_EXCEPT, FE_INEXACT);
211 test(fmal, -1.0, 1.0, -0x1.0p-200, -(1.0 + LDBL_EPSILON),
212 ALL_STD_EXCEPT, FE_INEXACT);
214 testall(0x1.0p100, -1.0, -0x1.0p-100, -0x1.0p100,
215 ALL_STD_EXCEPT, FE_INEXACT);
218 /* x*y positive, z negative */
219 if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) {
220 test(fmaf, 1.0, 1.0, -0x1.0p-100, 1.0 - FLT_EPSILON / 2,
221 ALL_STD_EXCEPT, FE_INEXACT);
222 test(fma, 1.0, 1.0, -0x1.0p-200, 1.0 - DBL_EPSILON / 2,
223 ALL_STD_EXCEPT, FE_INEXACT);
224 test(fmal, 1.0, 1.0, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2,
225 ALL_STD_EXCEPT, FE_INEXACT);
227 testall(0x1.0p100, 1.0, -0x1.0p-100, 0x1.0p100,
228 ALL_STD_EXCEPT, FE_INEXACT);
231 /* x*y negative, z positive */
232 if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) {
233 test(fmaf, -1.0, 1.0, 0x1.0p-100, -1.0 + FLT_EPSILON / 2,
234 ALL_STD_EXCEPT, FE_INEXACT);
235 test(fma, -1.0, 1.0, 0x1.0p-200, -1.0 + DBL_EPSILON / 2,
236 ALL_STD_EXCEPT, FE_INEXACT);
237 test(fmal, -1.0, 1.0, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2,
238 ALL_STD_EXCEPT, FE_INEXACT);
240 testall(-0x1.0p100, 1.0, 0x1.0p-100, -0x1.0p100,
241 ALL_STD_EXCEPT, FE_INEXACT);
246 * Tests for cases where z is very large compared to x*y.
252 /* z positive, x*y positive */
253 if (fegetround() == FE_UPWARD) {
254 test(fmaf, 0x1.0p-50, 0x1.0p-50, 1.0, 1.0 + FLT_EPSILON,
255 ALL_STD_EXCEPT, FE_INEXACT);
256 test(fma, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + DBL_EPSILON,
257 ALL_STD_EXCEPT, FE_INEXACT);
258 test(fmal, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + LDBL_EPSILON,
259 ALL_STD_EXCEPT, FE_INEXACT);
261 testall(-0x1.0p-50, -0x1.0p-50, 0x1.0p100, 0x1.0p100,
262 ALL_STD_EXCEPT, FE_INEXACT);
265 /* z negative, x*y negative */
266 if (fegetround() == FE_DOWNWARD) {
267 test(fmaf, -0x1.0p-50, 0x1.0p-50, -1.0, -(1.0 + FLT_EPSILON),
268 ALL_STD_EXCEPT, FE_INEXACT);
269 test(fma, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + DBL_EPSILON),
270 ALL_STD_EXCEPT, FE_INEXACT);
271 test(fmal, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + LDBL_EPSILON),
272 ALL_STD_EXCEPT, FE_INEXACT);
274 testall(0x1.0p-50, -0x1.0p-50, -0x1.0p100, -0x1.0p100,
275 ALL_STD_EXCEPT, FE_INEXACT);
278 /* z negative, x*y positive */
279 if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) {
280 test(fmaf, -0x1.0p-50, -0x1.0p-50, -1.0,
281 -1.0 + FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT);
282 test(fma, -0x1.0p-100, -0x1.0p-100, -1.0,
283 -1.0 + DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT);
284 test(fmal, -0x1.0p-100, -0x1.0p-100, -1.0,
285 -1.0 + LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT);
287 testall(0x1.0p-50, 0x1.0p-50, -0x1.0p100, -0x1.0p100,
288 ALL_STD_EXCEPT, FE_INEXACT);
291 /* z positive, x*y negative */
292 if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) {
293 test(fmaf, 0x1.0p-50, -0x1.0p-50, 1.0, 1.0 - FLT_EPSILON / 2,
294 ALL_STD_EXCEPT, FE_INEXACT);
295 test(fma, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - DBL_EPSILON / 2,
296 ALL_STD_EXCEPT, FE_INEXACT);
297 test(fmal, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - LDBL_EPSILON / 2,
298 ALL_STD_EXCEPT, FE_INEXACT);
300 testall(-0x1.0p-50, 0x1.0p-50, 0x1.0p100, 0x1.0p100,
301 ALL_STD_EXCEPT, FE_INEXACT);
309 /* ilogb(x*y) - ilogb(z) = 20 */
310 testrnd(fmaf, -0x1.c139d8p-51, -0x1.600e7ap32, 0x1.26558cp-38,
311 0x1.34e48ap-18, 0x1.34e48cp-18, 0x1.34e48ap-18, 0x1.34e48ap-18,
312 ALL_STD_EXCEPT, FE_INEXACT);
313 testrnd(fma, -0x1.c139d7b84f1a3p-51, -0x1.600e7a2a16484p32,
314 0x1.26558cac31580p-38, 0x1.34e48a78aae97p-18,
315 0x1.34e48a78aae97p-18, 0x1.34e48a78aae96p-18,
316 0x1.34e48a78aae96p-18, ALL_STD_EXCEPT, FE_INEXACT);
317 #if LDBL_MANT_DIG == 113
318 testrnd(fmal, -0x1.c139d7b84f1a3079263afcc5bae3p-51L,
319 -0x1.600e7a2a164840edbe2e7d301a72p32L,
320 0x1.26558cac315807eb07e448042101p-38L,
321 0x1.34e48a78aae96c76ed36077dd387p-18L,
322 0x1.34e48a78aae96c76ed36077dd388p-18L,
323 0x1.34e48a78aae96c76ed36077dd387p-18L,
324 0x1.34e48a78aae96c76ed36077dd387p-18L,
325 ALL_STD_EXCEPT, FE_INEXACT);
326 #elif LDBL_MANT_DIG == 64
327 testrnd(fmal, -0x1.c139d7b84f1a307ap-51L, -0x1.600e7a2a164840eep32L,
328 0x1.26558cac315807ecp-38L, 0x1.34e48a78aae96c78p-18L,
329 0x1.34e48a78aae96c78p-18L, 0x1.34e48a78aae96c76p-18L,
330 0x1.34e48a78aae96c76p-18L, ALL_STD_EXCEPT, FE_INEXACT);
331 #elif LDBL_MANT_DIG == 53
332 testrnd(fmal, -0x1.c139d7b84f1a3p-51L, -0x1.600e7a2a16484p32L,
333 0x1.26558cac31580p-38L, 0x1.34e48a78aae97p-18L,
334 0x1.34e48a78aae97p-18L, 0x1.34e48a78aae96p-18L,
335 0x1.34e48a78aae96p-18L, ALL_STD_EXCEPT, FE_INEXACT);
338 /* ilogb(x*y) - ilogb(z) = -40 */
339 testrnd(fmaf, 0x1.98210ap53, 0x1.9556acp-24, 0x1.d87da4p70,
340 0x1.d87da4p70, 0x1.d87da6p70, 0x1.d87da4p70, 0x1.d87da4p70,
341 ALL_STD_EXCEPT, FE_INEXACT);
342 testrnd(fma, 0x1.98210ac83fe2bp53, 0x1.9556ac1475f0fp-24,
343 0x1.d87da3aafc60ep70, 0x1.d87da3aafda40p70,
344 0x1.d87da3aafda40p70, 0x1.d87da3aafda3fp70,
345 0x1.d87da3aafda3fp70, ALL_STD_EXCEPT, FE_INEXACT);
346 #if LDBL_MANT_DIG == 113
347 testrnd(fmal, 0x1.98210ac83fe2a8f65b6278b74cebp53L,
348 0x1.9556ac1475f0f28968b61d0de65ap-24L,
349 0x1.d87da3aafc60d830aa4c6d73b749p70L,
350 0x1.d87da3aafda3f36a69eb86488224p70L,
351 0x1.d87da3aafda3f36a69eb86488225p70L,
352 0x1.d87da3aafda3f36a69eb86488224p70L,
353 0x1.d87da3aafda3f36a69eb86488224p70L,
354 ALL_STD_EXCEPT, FE_INEXACT);
355 #elif LDBL_MANT_DIG == 64
356 testrnd(fmal, 0x1.98210ac83fe2a8f6p53L, 0x1.9556ac1475f0f28ap-24L,
357 0x1.d87da3aafc60d83p70L, 0x1.d87da3aafda3f36ap70L,
358 0x1.d87da3aafda3f36ap70L, 0x1.d87da3aafda3f368p70L,
359 0x1.d87da3aafda3f368p70L, ALL_STD_EXCEPT, FE_INEXACT);
360 #elif LDBL_MANT_DIG == 53
361 testrnd(fmal, 0x1.98210ac83fe2bp53L, 0x1.9556ac1475f0fp-24L,
362 0x1.d87da3aafc60ep70L, 0x1.d87da3aafda40p70L,
363 0x1.d87da3aafda40p70L, 0x1.d87da3aafda3fp70L,
364 0x1.d87da3aafda3fp70L, ALL_STD_EXCEPT, FE_INEXACT);
369 test_double_rounding(void)
373 * a = 0x1.8000000000001p0
374 * b = 0x1.8000000000001p0
375 * c = -0x0.0000000000000000000000000080...1p+1
376 * a * b = 0x1.2000000000001800000000000080p+1
378 * The correct behavior is to round DOWN to 0x1.2000000000001p+1 in
379 * round-to-nearest mode. An implementation that computes a*b+c in
380 * double+double precision, however, will get 0x1.20000000000018p+1,
383 fesetround(FE_TONEAREST);
384 test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
385 -0x1.0000000000001p-104, 0x1.2000000000001p+1,
386 ALL_STD_EXCEPT, FE_INEXACT);
387 fesetround(FE_DOWNWARD);
388 test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
389 -0x1.0000000000001p-104, 0x1.2000000000001p+1,
390 ALL_STD_EXCEPT, FE_INEXACT);
391 fesetround(FE_UPWARD);
392 test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
393 -0x1.0000000000001p-104, 0x1.2000000000002p+1,
394 ALL_STD_EXCEPT, FE_INEXACT);
396 fesetround(FE_TONEAREST);
397 test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1,
398 ALL_STD_EXCEPT, FE_INEXACT);
399 fesetround(FE_DOWNWARD);
400 test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1,
401 ALL_STD_EXCEPT, FE_INEXACT);
402 fesetround(FE_UPWARD);
403 test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200004p+1,
404 ALL_STD_EXCEPT, FE_INEXACT);
406 fesetround(FE_TONEAREST);
407 #if LDBL_MANT_DIG == 64
408 test(fmal, 0x1.4p+0L, 0x1.0000000000000004p+0L, 0x1p-128L,
409 0x1.4000000000000006p+0L, ALL_STD_EXCEPT, FE_INEXACT);
410 #elif LDBL_MANT_DIG == 113
411 /* XXX untested test */
412 test(fmal, 0x1.4p+0L, 0x1.0000000000000000000000000002p+0L, 0x1p-224L,
413 0x1.4000000000000000000000000003p+0L, ALL_STD_EXCEPT, FE_INEXACT);
419 main(int argc, char *argv[])
421 int rmodes[] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO };
428 for (i = 0; i < nitems(rmodes); i++, j++) {
429 printf("rmode = %d\n", rmodes[i]);
430 fesetround(rmodes[i]);
432 printf("ok %d - fma zeroes\n", j);
435 for (i = 0; i < nitems(rmodes); i++, j++) {
436 printf("rmode = %d\n", rmodes[i]);
437 fesetround(rmodes[i]);
439 printf("ok %d - fma infinities\n", j);
442 fesetround(FE_TONEAREST);
444 printf("ok %d - fma NaNs\n", j);
447 for (i = 0; i < nitems(rmodes); i++, j++) {
448 printf("rmode = %d\n", rmodes[i]);
449 fesetround(rmodes[i]);
451 printf("ok %d - fma small z\n", j);
454 for (i = 0; i < nitems(rmodes); i++, j++) {
455 printf("rmode = %d\n", rmodes[i]);
456 fesetround(rmodes[i]);
458 printf("ok %d - fma big z\n", j);
461 fesetround(FE_TONEAREST);
463 printf("ok %d - fma accuracy\n", j);
466 test_double_rounding();
467 printf("ok %d - fma double rounding\n", j);
472 * - Tests for subnormals
473 * - Cancellation tests (e.g., z = (double)x*y, but x*y is inexact)