xref: /freebsd/lib/msun/tests/fma_test.c (revision 8a7d0e8ce3d2e756fbecc374b6379d0ce8458654)
1*8a7d0e8cSEnji Cooper /*-
2*8a7d0e8cSEnji Cooper  * Copyright (c) 2008 David Schultz <das@FreeBSD.org>
3*8a7d0e8cSEnji Cooper  * All rights reserved.
4*8a7d0e8cSEnji Cooper  *
5*8a7d0e8cSEnji Cooper  * Redistribution and use in source and binary forms, with or without
6*8a7d0e8cSEnji Cooper  * modification, are permitted provided that the following conditions
7*8a7d0e8cSEnji Cooper  * are met:
8*8a7d0e8cSEnji Cooper  * 1. Redistributions of source code must retain the above copyright
9*8a7d0e8cSEnji Cooper  *    notice, this list of conditions and the following disclaimer.
10*8a7d0e8cSEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
11*8a7d0e8cSEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
12*8a7d0e8cSEnji Cooper  *    documentation and/or other materials provided with the distribution.
13*8a7d0e8cSEnji Cooper  *
14*8a7d0e8cSEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*8a7d0e8cSEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*8a7d0e8cSEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*8a7d0e8cSEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*8a7d0e8cSEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*8a7d0e8cSEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*8a7d0e8cSEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*8a7d0e8cSEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*8a7d0e8cSEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*8a7d0e8cSEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*8a7d0e8cSEnji Cooper  * SUCH DAMAGE.
25*8a7d0e8cSEnji Cooper  */
26*8a7d0e8cSEnji Cooper 
27*8a7d0e8cSEnji Cooper /*
28*8a7d0e8cSEnji Cooper  * Tests for fma{,f,l}().
29*8a7d0e8cSEnji Cooper  */
30*8a7d0e8cSEnji Cooper 
31*8a7d0e8cSEnji Cooper #include <sys/cdefs.h>
32*8a7d0e8cSEnji Cooper __FBSDID("$FreeBSD$");
33*8a7d0e8cSEnji Cooper 
34*8a7d0e8cSEnji Cooper #include <sys/param.h>
35*8a7d0e8cSEnji Cooper #include <assert.h>
36*8a7d0e8cSEnji Cooper #include <fenv.h>
37*8a7d0e8cSEnji Cooper #include <float.h>
38*8a7d0e8cSEnji Cooper #include <math.h>
39*8a7d0e8cSEnji Cooper #include <stdio.h>
40*8a7d0e8cSEnji Cooper #include <stdlib.h>
41*8a7d0e8cSEnji Cooper 
42*8a7d0e8cSEnji Cooper #include "test-utils.h"
43*8a7d0e8cSEnji Cooper 
44*8a7d0e8cSEnji Cooper #pragma STDC FENV_ACCESS ON
45*8a7d0e8cSEnji Cooper 
46*8a7d0e8cSEnji Cooper /*
47*8a7d0e8cSEnji Cooper  * Test that a function returns the correct value and sets the
48*8a7d0e8cSEnji Cooper  * exception flags correctly. The exceptmask specifies which
49*8a7d0e8cSEnji Cooper  * exceptions we should check. We need to be lenient for several
50*8a7d0e8cSEnji Cooper  * reasons, but mainly because on some architectures it's impossible
51*8a7d0e8cSEnji Cooper  * to raise FE_OVERFLOW without raising FE_INEXACT.
52*8a7d0e8cSEnji Cooper  *
53*8a7d0e8cSEnji Cooper  * These are macros instead of functions so that assert provides more
54*8a7d0e8cSEnji Cooper  * meaningful error messages.
55*8a7d0e8cSEnji Cooper  */
56*8a7d0e8cSEnji Cooper #define	test(func, x, y, z, result, exceptmask, excepts) do {		\
57*8a7d0e8cSEnji Cooper 	volatile long double _vx = (x), _vy = (y), _vz = (z);		\
58*8a7d0e8cSEnji Cooper 	assert(feclearexcept(FE_ALL_EXCEPT) == 0);			\
59*8a7d0e8cSEnji Cooper 	assert(fpequal((func)(_vx, _vy, _vz), (result)));		\
60*8a7d0e8cSEnji Cooper 	assert(((void)(func), fetestexcept(exceptmask) == (excepts)));	\
61*8a7d0e8cSEnji Cooper } while (0)
62*8a7d0e8cSEnji Cooper 
63*8a7d0e8cSEnji Cooper #define	testall(x, y, z, result, exceptmask, excepts)	do {		\
64*8a7d0e8cSEnji Cooper 	test(fma, (double)(x), (double)(y), (double)(z),		\
65*8a7d0e8cSEnji Cooper 		(double)(result), (exceptmask), (excepts));		\
66*8a7d0e8cSEnji Cooper 	test(fmaf, (float)(x), (float)(y), (float)(z),			\
67*8a7d0e8cSEnji Cooper 		(float)(result), (exceptmask), (excepts));		\
68*8a7d0e8cSEnji Cooper 	test(fmal, (x), (y), (z), (result), (exceptmask), (excepts));	\
69*8a7d0e8cSEnji Cooper } while (0)
70*8a7d0e8cSEnji Cooper 
71*8a7d0e8cSEnji Cooper /* Test in all rounding modes. */
72*8a7d0e8cSEnji Cooper #define	testrnd(func, x, y, z, rn, ru, rd, rz, exceptmask, excepts)	do { \
73*8a7d0e8cSEnji Cooper 	fesetround(FE_TONEAREST);					\
74*8a7d0e8cSEnji Cooper 	test((func), (x), (y), (z), (rn), (exceptmask), (excepts));	\
75*8a7d0e8cSEnji Cooper 	fesetround(FE_UPWARD);						\
76*8a7d0e8cSEnji Cooper 	test((func), (x), (y), (z), (ru), (exceptmask), (excepts));	\
77*8a7d0e8cSEnji Cooper 	fesetround(FE_DOWNWARD);					\
78*8a7d0e8cSEnji Cooper 	test((func), (x), (y), (z), (rd), (exceptmask), (excepts));	\
79*8a7d0e8cSEnji Cooper 	fesetround(FE_TOWARDZERO);					\
80*8a7d0e8cSEnji Cooper 	test((func), (x), (y), (z), (rz), (exceptmask), (excepts));	\
81*8a7d0e8cSEnji Cooper } while (0)
82*8a7d0e8cSEnji Cooper 
83*8a7d0e8cSEnji Cooper /*
84*8a7d0e8cSEnji Cooper  * This is needed because clang constant-folds fma in ways that are incorrect
85*8a7d0e8cSEnji Cooper  * in rounding modes other than FE_TONEAREST.
86*8a7d0e8cSEnji Cooper  */
87*8a7d0e8cSEnji Cooper volatile double one = 1.0;
88*8a7d0e8cSEnji Cooper 
89*8a7d0e8cSEnji Cooper static void
90*8a7d0e8cSEnji Cooper test_zeroes(void)
91*8a7d0e8cSEnji Cooper {
92*8a7d0e8cSEnji Cooper 	const int rd = (fegetround() == FE_DOWNWARD);
93*8a7d0e8cSEnji Cooper 
94*8a7d0e8cSEnji Cooper 	testall(0.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
95*8a7d0e8cSEnji Cooper 	testall(1.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
96*8a7d0e8cSEnji Cooper 	testall(0.0, 1.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
97*8a7d0e8cSEnji Cooper 	testall(0.0, 0.0, 1.0, 1.0, ALL_STD_EXCEPT, 0);
98*8a7d0e8cSEnji Cooper 
99*8a7d0e8cSEnji Cooper 	testall(-0.0, 0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
100*8a7d0e8cSEnji Cooper 	testall(0.0, -0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
101*8a7d0e8cSEnji Cooper 	testall(-0.0, -0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0);
102*8a7d0e8cSEnji Cooper 	testall(0.0, 0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
103*8a7d0e8cSEnji Cooper 	testall(-0.0, -0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
104*8a7d0e8cSEnji Cooper 
105*8a7d0e8cSEnji Cooper 	testall(-0.0, 0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0);
106*8a7d0e8cSEnji Cooper 	testall(0.0, -0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0);
107*8a7d0e8cSEnji Cooper 
108*8a7d0e8cSEnji Cooper 	testall(-one, one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
109*8a7d0e8cSEnji Cooper 	testall(one, -one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
110*8a7d0e8cSEnji Cooper 	testall(-one, -one, -one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
111*8a7d0e8cSEnji Cooper 
112*8a7d0e8cSEnji Cooper 	switch (fegetround()) {
113*8a7d0e8cSEnji Cooper 	case FE_TONEAREST:
114*8a7d0e8cSEnji Cooper 	case FE_TOWARDZERO:
115*8a7d0e8cSEnji Cooper 		test(fmaf, -FLT_MIN, FLT_MIN, 0.0, -0.0,
116*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW);
117*8a7d0e8cSEnji Cooper 		test(fma, -DBL_MIN, DBL_MIN, 0.0, -0.0,
118*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW);
119*8a7d0e8cSEnji Cooper 		test(fmal, -LDBL_MIN, LDBL_MIN, 0.0, -0.0,
120*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW);
121*8a7d0e8cSEnji Cooper 	}
122*8a7d0e8cSEnji Cooper }
123*8a7d0e8cSEnji Cooper 
124*8a7d0e8cSEnji Cooper static void
125*8a7d0e8cSEnji Cooper test_infinities(void)
126*8a7d0e8cSEnji Cooper {
127*8a7d0e8cSEnji Cooper 
128*8a7d0e8cSEnji Cooper 	testall(INFINITY, 1.0, -1.0, INFINITY, ALL_STD_EXCEPT, 0);
129*8a7d0e8cSEnji Cooper 	testall(-1.0, INFINITY, 0.0, -INFINITY, ALL_STD_EXCEPT, 0);
130*8a7d0e8cSEnji Cooper 	testall(0.0, 0.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
131*8a7d0e8cSEnji Cooper 	testall(1.0, 1.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
132*8a7d0e8cSEnji Cooper 	testall(1.0, 1.0, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0);
133*8a7d0e8cSEnji Cooper 
134*8a7d0e8cSEnji Cooper 	testall(INFINITY, -INFINITY, 1.0, -INFINITY, ALL_STD_EXCEPT, 0);
135*8a7d0e8cSEnji Cooper 	testall(INFINITY, INFINITY, 1.0, INFINITY, ALL_STD_EXCEPT, 0);
136*8a7d0e8cSEnji Cooper 	testall(-INFINITY, -INFINITY, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
137*8a7d0e8cSEnji Cooper 
138*8a7d0e8cSEnji Cooper 	testall(0.0, INFINITY, 1.0, NAN, ALL_STD_EXCEPT, FE_INVALID);
139*8a7d0e8cSEnji Cooper 	testall(INFINITY, 0.0, -0.0, NAN, ALL_STD_EXCEPT, FE_INVALID);
140*8a7d0e8cSEnji Cooper 
141*8a7d0e8cSEnji Cooper 	/* The invalid exception is optional in this case. */
142*8a7d0e8cSEnji Cooper 	testall(INFINITY, 0.0, NAN, NAN, ALL_STD_EXCEPT & ~FE_INVALID, 0);
143*8a7d0e8cSEnji Cooper 
144*8a7d0e8cSEnji Cooper 	testall(INFINITY, INFINITY, -INFINITY, NAN,
145*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INVALID);
146*8a7d0e8cSEnji Cooper 	testall(-INFINITY, INFINITY, INFINITY, NAN,
147*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INVALID);
148*8a7d0e8cSEnji Cooper 	testall(INFINITY, -1.0, INFINITY, NAN,
149*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INVALID);
150*8a7d0e8cSEnji Cooper 
151*8a7d0e8cSEnji Cooper 	test(fmaf, FLT_MAX, FLT_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0);
152*8a7d0e8cSEnji Cooper 	test(fma, DBL_MAX, DBL_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0);
153*8a7d0e8cSEnji Cooper 	test(fmal, LDBL_MAX, LDBL_MAX, -INFINITY, -INFINITY,
154*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, 0);
155*8a7d0e8cSEnji Cooper 	test(fmaf, FLT_MAX, -FLT_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
156*8a7d0e8cSEnji Cooper 	test(fma, DBL_MAX, -DBL_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
157*8a7d0e8cSEnji Cooper 	test(fmal, LDBL_MAX, -LDBL_MAX, INFINITY, INFINITY,
158*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, 0);
159*8a7d0e8cSEnji Cooper }
160*8a7d0e8cSEnji Cooper 
161*8a7d0e8cSEnji Cooper static void
162*8a7d0e8cSEnji Cooper test_nans(void)
163*8a7d0e8cSEnji Cooper {
164*8a7d0e8cSEnji Cooper 
165*8a7d0e8cSEnji Cooper 	testall(NAN, 0.0, 0.0, NAN, ALL_STD_EXCEPT, 0);
166*8a7d0e8cSEnji Cooper 	testall(1.0, NAN, 1.0, NAN, ALL_STD_EXCEPT, 0);
167*8a7d0e8cSEnji Cooper 	testall(1.0, -1.0, NAN, NAN, ALL_STD_EXCEPT, 0);
168*8a7d0e8cSEnji Cooper 	testall(0.0, 0.0, NAN, NAN, ALL_STD_EXCEPT, 0);
169*8a7d0e8cSEnji Cooper 	testall(NAN, NAN, NAN, NAN, ALL_STD_EXCEPT, 0);
170*8a7d0e8cSEnji Cooper 
171*8a7d0e8cSEnji Cooper 	/* x*y should not raise an inexact/overflow/underflow if z is NaN. */
172*8a7d0e8cSEnji Cooper 	testall(M_PI, M_PI, NAN, NAN, ALL_STD_EXCEPT, 0);
173*8a7d0e8cSEnji Cooper 	test(fmaf, FLT_MIN, FLT_MIN, NAN, NAN, ALL_STD_EXCEPT, 0);
174*8a7d0e8cSEnji Cooper 	test(fma, DBL_MIN, DBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0);
175*8a7d0e8cSEnji Cooper 	test(fmal, LDBL_MIN, LDBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0);
176*8a7d0e8cSEnji Cooper 	test(fmaf, FLT_MAX, FLT_MAX, NAN, NAN, ALL_STD_EXCEPT, 0);
177*8a7d0e8cSEnji Cooper 	test(fma, DBL_MAX, DBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0);
178*8a7d0e8cSEnji Cooper 	test(fmal, LDBL_MAX, LDBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0);
179*8a7d0e8cSEnji Cooper }
180*8a7d0e8cSEnji Cooper 
181*8a7d0e8cSEnji Cooper /*
182*8a7d0e8cSEnji Cooper  * Tests for cases where z is very small compared to x*y.
183*8a7d0e8cSEnji Cooper  */
184*8a7d0e8cSEnji Cooper static void
185*8a7d0e8cSEnji Cooper test_small_z(void)
186*8a7d0e8cSEnji Cooper {
187*8a7d0e8cSEnji Cooper 
188*8a7d0e8cSEnji Cooper 	/* x*y positive, z positive */
189*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_UPWARD) {
190*8a7d0e8cSEnji Cooper 		test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON,
191*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
192*8a7d0e8cSEnji Cooper 		test(fma, one, one, 0x1.0p-200, 1.0 + DBL_EPSILON,
193*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
194*8a7d0e8cSEnji Cooper 		test(fmal, one, one, 0x1.0p-200, 1.0 + LDBL_EPSILON,
195*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
196*8a7d0e8cSEnji Cooper 	} else {
197*8a7d0e8cSEnji Cooper 		testall(0x1.0p100, one, 0x1.0p-100, 0x1.0p100,
198*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
199*8a7d0e8cSEnji Cooper 	}
200*8a7d0e8cSEnji Cooper 
201*8a7d0e8cSEnji Cooper 	/* x*y negative, z negative */
202*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_DOWNWARD) {
203*8a7d0e8cSEnji Cooper 		test(fmaf, -one, one, -0x1.0p-100, -(1.0 + FLT_EPSILON),
204*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
205*8a7d0e8cSEnji Cooper 		test(fma, -one, one, -0x1.0p-200, -(1.0 + DBL_EPSILON),
206*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
207*8a7d0e8cSEnji Cooper 		test(fmal, -one, one, -0x1.0p-200, -(1.0 + LDBL_EPSILON),
208*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
209*8a7d0e8cSEnji Cooper 	} else {
210*8a7d0e8cSEnji Cooper 		testall(0x1.0p100, -one, -0x1.0p-100, -0x1.0p100,
211*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
212*8a7d0e8cSEnji Cooper 	}
213*8a7d0e8cSEnji Cooper 
214*8a7d0e8cSEnji Cooper 	/* x*y positive, z negative */
215*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) {
216*8a7d0e8cSEnji Cooper 		test(fmaf, one, one, -0x1.0p-100, 1.0 - FLT_EPSILON / 2,
217*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
218*8a7d0e8cSEnji Cooper 		test(fma, one, one, -0x1.0p-200, 1.0 - DBL_EPSILON / 2,
219*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
220*8a7d0e8cSEnji Cooper 		test(fmal, one, one, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2,
221*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
222*8a7d0e8cSEnji Cooper 	} else {
223*8a7d0e8cSEnji Cooper 		testall(0x1.0p100, one, -0x1.0p-100, 0x1.0p100,
224*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
225*8a7d0e8cSEnji Cooper 	}
226*8a7d0e8cSEnji Cooper 
227*8a7d0e8cSEnji Cooper 	/* x*y negative, z positive */
228*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) {
229*8a7d0e8cSEnji Cooper 		test(fmaf, -one, one, 0x1.0p-100, -1.0 + FLT_EPSILON / 2,
230*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
231*8a7d0e8cSEnji Cooper 		test(fma, -one, one, 0x1.0p-200, -1.0 + DBL_EPSILON / 2,
232*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
233*8a7d0e8cSEnji Cooper 		test(fmal, -one, one, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2,
234*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
235*8a7d0e8cSEnji Cooper 	} else {
236*8a7d0e8cSEnji Cooper 		testall(-0x1.0p100, one, 0x1.0p-100, -0x1.0p100,
237*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
238*8a7d0e8cSEnji Cooper 	}
239*8a7d0e8cSEnji Cooper }
240*8a7d0e8cSEnji Cooper 
241*8a7d0e8cSEnji Cooper /*
242*8a7d0e8cSEnji Cooper  * Tests for cases where z is very large compared to x*y.
243*8a7d0e8cSEnji Cooper  */
244*8a7d0e8cSEnji Cooper static void
245*8a7d0e8cSEnji Cooper test_big_z(void)
246*8a7d0e8cSEnji Cooper {
247*8a7d0e8cSEnji Cooper 
248*8a7d0e8cSEnji Cooper 	/* z positive, x*y positive */
249*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_UPWARD) {
250*8a7d0e8cSEnji Cooper 		test(fmaf, 0x1.0p-50, 0x1.0p-50, 1.0, 1.0 + FLT_EPSILON,
251*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
252*8a7d0e8cSEnji Cooper 		test(fma, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + DBL_EPSILON,
253*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
254*8a7d0e8cSEnji Cooper 		test(fmal, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + LDBL_EPSILON,
255*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
256*8a7d0e8cSEnji Cooper 	} else {
257*8a7d0e8cSEnji Cooper 		testall(-0x1.0p-50, -0x1.0p-50, 0x1.0p100, 0x1.0p100,
258*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
259*8a7d0e8cSEnji Cooper 	}
260*8a7d0e8cSEnji Cooper 
261*8a7d0e8cSEnji Cooper 	/* z negative, x*y negative */
262*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_DOWNWARD) {
263*8a7d0e8cSEnji Cooper 		test(fmaf, -0x1.0p-50, 0x1.0p-50, -1.0, -(1.0 + FLT_EPSILON),
264*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
265*8a7d0e8cSEnji Cooper 		test(fma, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + DBL_EPSILON),
266*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
267*8a7d0e8cSEnji Cooper 		test(fmal, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + LDBL_EPSILON),
268*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
269*8a7d0e8cSEnji Cooper 	} else {
270*8a7d0e8cSEnji Cooper 		testall(0x1.0p-50, -0x1.0p-50, -0x1.0p100, -0x1.0p100,
271*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
272*8a7d0e8cSEnji Cooper 	}
273*8a7d0e8cSEnji Cooper 
274*8a7d0e8cSEnji Cooper 	/* z negative, x*y positive */
275*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) {
276*8a7d0e8cSEnji Cooper 		test(fmaf, -0x1.0p-50, -0x1.0p-50, -1.0,
277*8a7d0e8cSEnji Cooper 		     -1.0 + FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT);
278*8a7d0e8cSEnji Cooper 		test(fma, -0x1.0p-100, -0x1.0p-100, -1.0,
279*8a7d0e8cSEnji Cooper 		     -1.0 + DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT);
280*8a7d0e8cSEnji Cooper 		test(fmal, -0x1.0p-100, -0x1.0p-100, -1.0,
281*8a7d0e8cSEnji Cooper 		     -1.0 + LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT);
282*8a7d0e8cSEnji Cooper 	} else {
283*8a7d0e8cSEnji Cooper 		testall(0x1.0p-50, 0x1.0p-50, -0x1.0p100, -0x1.0p100,
284*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
285*8a7d0e8cSEnji Cooper 	}
286*8a7d0e8cSEnji Cooper 
287*8a7d0e8cSEnji Cooper 	/* z positive, x*y negative */
288*8a7d0e8cSEnji Cooper 	if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) {
289*8a7d0e8cSEnji Cooper 		test(fmaf, 0x1.0p-50, -0x1.0p-50, 1.0, 1.0 - FLT_EPSILON / 2,
290*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
291*8a7d0e8cSEnji Cooper 		test(fma, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - DBL_EPSILON / 2,
292*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
293*8a7d0e8cSEnji Cooper 		test(fmal, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - LDBL_EPSILON / 2,
294*8a7d0e8cSEnji Cooper 		     ALL_STD_EXCEPT, FE_INEXACT);
295*8a7d0e8cSEnji Cooper 	} else {
296*8a7d0e8cSEnji Cooper 		testall(-0x1.0p-50, 0x1.0p-50, 0x1.0p100, 0x1.0p100,
297*8a7d0e8cSEnji Cooper 			ALL_STD_EXCEPT, FE_INEXACT);
298*8a7d0e8cSEnji Cooper 	}
299*8a7d0e8cSEnji Cooper }
300*8a7d0e8cSEnji Cooper 
301*8a7d0e8cSEnji Cooper static void
302*8a7d0e8cSEnji Cooper test_accuracy(void)
303*8a7d0e8cSEnji Cooper {
304*8a7d0e8cSEnji Cooper 
305*8a7d0e8cSEnji Cooper 	/* ilogb(x*y) - ilogb(z) = 20 */
306*8a7d0e8cSEnji Cooper 	testrnd(fmaf, -0x1.c139d8p-51, -0x1.600e7ap32, 0x1.26558cp-38,
307*8a7d0e8cSEnji Cooper 		0x1.34e48ap-18, 0x1.34e48cp-18, 0x1.34e48ap-18, 0x1.34e48ap-18,
308*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INEXACT);
309*8a7d0e8cSEnji Cooper 	testrnd(fma, -0x1.c139d7b84f1a3p-51, -0x1.600e7a2a16484p32,
310*8a7d0e8cSEnji Cooper 		0x1.26558cac31580p-38, 0x1.34e48a78aae97p-18,
311*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae97p-18, 0x1.34e48a78aae96p-18,
312*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96p-18, ALL_STD_EXCEPT, FE_INEXACT);
313*8a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113
314*8a7d0e8cSEnji Cooper 	testrnd(fmal, -0x1.c139d7b84f1a3079263afcc5bae3p-51L,
315*8a7d0e8cSEnji Cooper 		-0x1.600e7a2a164840edbe2e7d301a72p32L,
316*8a7d0e8cSEnji Cooper 		0x1.26558cac315807eb07e448042101p-38L,
317*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96c76ed36077dd387p-18L,
318*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96c76ed36077dd388p-18L,
319*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96c76ed36077dd387p-18L,
320*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96c76ed36077dd387p-18L,
321*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INEXACT);
322*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64
323*8a7d0e8cSEnji Cooper 	testrnd(fmal, -0x1.c139d7b84f1a307ap-51L, -0x1.600e7a2a164840eep32L,
324*8a7d0e8cSEnji Cooper 		0x1.26558cac315807ecp-38L, 0x1.34e48a78aae96c78p-18L,
325*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96c78p-18L, 0x1.34e48a78aae96c76p-18L,
326*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96c76p-18L, ALL_STD_EXCEPT, FE_INEXACT);
327*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53
328*8a7d0e8cSEnji Cooper 	testrnd(fmal, -0x1.c139d7b84f1a3p-51L, -0x1.600e7a2a16484p32L,
329*8a7d0e8cSEnji Cooper 		0x1.26558cac31580p-38L, 0x1.34e48a78aae97p-18L,
330*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae97p-18L, 0x1.34e48a78aae96p-18L,
331*8a7d0e8cSEnji Cooper 		0x1.34e48a78aae96p-18L, ALL_STD_EXCEPT, FE_INEXACT);
332*8a7d0e8cSEnji Cooper #endif
333*8a7d0e8cSEnji Cooper 
334*8a7d0e8cSEnji Cooper 	/* ilogb(x*y) - ilogb(z) = -40 */
335*8a7d0e8cSEnji Cooper 	testrnd(fmaf, 0x1.98210ap53, 0x1.9556acp-24, 0x1.d87da4p70,
336*8a7d0e8cSEnji Cooper 		0x1.d87da4p70, 0x1.d87da6p70, 0x1.d87da4p70, 0x1.d87da4p70,
337*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INEXACT);
338*8a7d0e8cSEnji Cooper 	testrnd(fma, 0x1.98210ac83fe2bp53, 0x1.9556ac1475f0fp-24,
339*8a7d0e8cSEnji Cooper 		0x1.d87da3aafc60ep70, 0x1.d87da3aafda40p70,
340*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda40p70, 0x1.d87da3aafda3fp70,
341*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3fp70, ALL_STD_EXCEPT, FE_INEXACT);
342*8a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113
343*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.98210ac83fe2a8f65b6278b74cebp53L,
344*8a7d0e8cSEnji Cooper 		0x1.9556ac1475f0f28968b61d0de65ap-24L,
345*8a7d0e8cSEnji Cooper 		0x1.d87da3aafc60d830aa4c6d73b749p70L,
346*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3f36a69eb86488224p70L,
347*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3f36a69eb86488225p70L,
348*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3f36a69eb86488224p70L,
349*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3f36a69eb86488224p70L,
350*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INEXACT);
351*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64
352*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.98210ac83fe2a8f6p53L, 0x1.9556ac1475f0f28ap-24L,
353*8a7d0e8cSEnji Cooper 		0x1.d87da3aafc60d83p70L, 0x1.d87da3aafda3f36ap70L,
354*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3f36ap70L, 0x1.d87da3aafda3f368p70L,
355*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3f368p70L, ALL_STD_EXCEPT, FE_INEXACT);
356*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53
357*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.98210ac83fe2bp53L, 0x1.9556ac1475f0fp-24L,
358*8a7d0e8cSEnji Cooper 		0x1.d87da3aafc60ep70L, 0x1.d87da3aafda40p70L,
359*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda40p70L, 0x1.d87da3aafda3fp70L,
360*8a7d0e8cSEnji Cooper 		0x1.d87da3aafda3fp70L, ALL_STD_EXCEPT, FE_INEXACT);
361*8a7d0e8cSEnji Cooper #endif
362*8a7d0e8cSEnji Cooper 
363*8a7d0e8cSEnji Cooper 	/* ilogb(x*y) - ilogb(z) = 0 */
364*8a7d0e8cSEnji Cooper 	testrnd(fmaf, 0x1.31ad02p+100, 0x1.2fbf7ap-42, -0x1.c3e106p+58,
365*8a7d0e8cSEnji Cooper 		-0x1.64c27cp+56, -0x1.64c27ap+56, -0x1.64c27cp+56,
366*8a7d0e8cSEnji Cooper 		-0x1.64c27ap+56, ALL_STD_EXCEPT, FE_INEXACT);
367*8a7d0e8cSEnji Cooper 	testrnd(fma, 0x1.31ad012ede8aap+100, 0x1.2fbf79c839067p-42,
368*8a7d0e8cSEnji Cooper 		-0x1.c3e106929056ep+58, -0x1.64c282b970a5fp+56,
369*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a5ep+56, -0x1.64c282b970a5fp+56,
370*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a5ep+56, ALL_STD_EXCEPT, FE_INEXACT);
371*8a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113
372*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.31ad012ede8aa282fa1c19376d16p+100L,
373*8a7d0e8cSEnji Cooper 		 0x1.2fbf79c839066f0f5c68f6d2e814p-42L,
374*8a7d0e8cSEnji Cooper 		-0x1.c3e106929056ec19de72bfe64215p+58L,
375*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a612598fc025ca8cddp+56L,
376*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a612598fc025ca8cddp+56L,
377*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a612598fc025ca8cdep+56L,
378*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a612598fc025ca8cddp+56L,
379*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT, FE_INEXACT);
380*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64
381*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.31ad012ede8aa4eap+100L, 0x1.2fbf79c839066aeap-42L,
382*8a7d0e8cSEnji Cooper 		-0x1.c3e106929056e61p+58L, -0x1.64c282b970a60298p+56L,
383*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a60298p+56L, -0x1.64c282b970a6029ap+56L,
384*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a60298p+56L, ALL_STD_EXCEPT, FE_INEXACT);
385*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53
386*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.31ad012ede8aap+100L, 0x1.2fbf79c839067p-42L,
387*8a7d0e8cSEnji Cooper 		-0x1.c3e106929056ep+58L, -0x1.64c282b970a5fp+56L,
388*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a5ep+56L, -0x1.64c282b970a5fp+56L,
389*8a7d0e8cSEnji Cooper 		-0x1.64c282b970a5ep+56L, ALL_STD_EXCEPT, FE_INEXACT);
390*8a7d0e8cSEnji Cooper #endif
391*8a7d0e8cSEnji Cooper 
392*8a7d0e8cSEnji Cooper 	/* x*y (rounded) ~= -z */
393*8a7d0e8cSEnji Cooper 	/* XXX spurious inexact exceptions */
394*8a7d0e8cSEnji Cooper 	testrnd(fmaf, 0x1.bbffeep-30, -0x1.1d164cp-74, 0x1.ee7296p-104,
395*8a7d0e8cSEnji Cooper 		-0x1.c46ea8p-128, -0x1.c46ea8p-128, -0x1.c46ea8p-128,
396*8a7d0e8cSEnji Cooper 		-0x1.c46ea8p-128, ALL_STD_EXCEPT & ~FE_INEXACT, 0);
397*8a7d0e8cSEnji Cooper 	testrnd(fma, 0x1.bbffeea6fc7d6p-30, 0x1.1d164c6cbf078p-74,
398*8a7d0e8cSEnji Cooper 		-0x1.ee72993aff948p-104, -0x1.71f72ac7d9d8p-159,
399*8a7d0e8cSEnji Cooper 		-0x1.71f72ac7d9d8p-159, -0x1.71f72ac7d9d8p-159,
400*8a7d0e8cSEnji Cooper 		-0x1.71f72ac7d9d8p-159, ALL_STD_EXCEPT & ~FE_INEXACT, 0);
401*8a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113
402*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.bbffeea6fc7d65927d147f437675p-30L,
403*8a7d0e8cSEnji Cooper 		0x1.1d164c6cbf078b7a22607d1cd6a2p-74L,
404*8a7d0e8cSEnji Cooper 		-0x1.ee72993aff94973876031bec0944p-104L,
405*8a7d0e8cSEnji Cooper 		0x1.64e086175b3a2adc36e607058814p-217L,
406*8a7d0e8cSEnji Cooper 		0x1.64e086175b3a2adc36e607058814p-217L,
407*8a7d0e8cSEnji Cooper 		0x1.64e086175b3a2adc36e607058814p-217L,
408*8a7d0e8cSEnji Cooper 		0x1.64e086175b3a2adc36e607058814p-217L,
409*8a7d0e8cSEnji Cooper 		ALL_STD_EXCEPT & ~FE_INEXACT, 0);
410*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64
411*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.bbffeea6fc7d6592p-30L, 0x1.1d164c6cbf078b7ap-74L,
412*8a7d0e8cSEnji Cooper 		-0x1.ee72993aff949736p-104L, 0x1.af190e7a1ee6ad94p-168L,
413*8a7d0e8cSEnji Cooper 		0x1.af190e7a1ee6ad94p-168L, 0x1.af190e7a1ee6ad94p-168L,
414*8a7d0e8cSEnji Cooper 		0x1.af190e7a1ee6ad94p-168L, ALL_STD_EXCEPT & ~FE_INEXACT, 0);
415*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53
416*8a7d0e8cSEnji Cooper 	testrnd(fmal, 0x1.bbffeea6fc7d6p-30L, 0x1.1d164c6cbf078p-74L,
417*8a7d0e8cSEnji Cooper 		-0x1.ee72993aff948p-104L, -0x1.71f72ac7d9d8p-159L,
418*8a7d0e8cSEnji Cooper 		-0x1.71f72ac7d9d8p-159L, -0x1.71f72ac7d9d8p-159L,
419*8a7d0e8cSEnji Cooper 		-0x1.71f72ac7d9d8p-159L, ALL_STD_EXCEPT & ~FE_INEXACT, 0);
420*8a7d0e8cSEnji Cooper #endif
421*8a7d0e8cSEnji Cooper }
422*8a7d0e8cSEnji Cooper 
423*8a7d0e8cSEnji Cooper static void
424*8a7d0e8cSEnji Cooper test_double_rounding(void)
425*8a7d0e8cSEnji Cooper {
426*8a7d0e8cSEnji Cooper 
427*8a7d0e8cSEnji Cooper 	/*
428*8a7d0e8cSEnji Cooper 	 *     a =  0x1.8000000000001p0
429*8a7d0e8cSEnji Cooper 	 *     b =  0x1.8000000000001p0
430*8a7d0e8cSEnji Cooper 	 *     c = -0x0.0000000000000000000000000080...1p+1
431*8a7d0e8cSEnji Cooper 	 * a * b =  0x1.2000000000001800000000000080p+1
432*8a7d0e8cSEnji Cooper 	 *
433*8a7d0e8cSEnji Cooper 	 * The correct behavior is to round DOWN to 0x1.2000000000001p+1 in
434*8a7d0e8cSEnji Cooper 	 * round-to-nearest mode.  An implementation that computes a*b+c in
435*8a7d0e8cSEnji Cooper 	 * double+double precision, however, will get 0x1.20000000000018p+1,
436*8a7d0e8cSEnji Cooper 	 * and then round UP.
437*8a7d0e8cSEnji Cooper 	 */
438*8a7d0e8cSEnji Cooper 	fesetround(FE_TONEAREST);
439*8a7d0e8cSEnji Cooper 	test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
440*8a7d0e8cSEnji Cooper 	     -0x1.0000000000001p-104, 0x1.2000000000001p+1,
441*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, FE_INEXACT);
442*8a7d0e8cSEnji Cooper 	fesetround(FE_DOWNWARD);
443*8a7d0e8cSEnji Cooper 	test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
444*8a7d0e8cSEnji Cooper 	     -0x1.0000000000001p-104, 0x1.2000000000001p+1,
445*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, FE_INEXACT);
446*8a7d0e8cSEnji Cooper 	fesetround(FE_UPWARD);
447*8a7d0e8cSEnji Cooper 	test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
448*8a7d0e8cSEnji Cooper 	     -0x1.0000000000001p-104, 0x1.2000000000002p+1,
449*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, FE_INEXACT);
450*8a7d0e8cSEnji Cooper 
451*8a7d0e8cSEnji Cooper 	fesetround(FE_TONEAREST);
452*8a7d0e8cSEnji Cooper 	test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1,
453*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, FE_INEXACT);
454*8a7d0e8cSEnji Cooper 	fesetround(FE_DOWNWARD);
455*8a7d0e8cSEnji Cooper 	test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1,
456*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, FE_INEXACT);
457*8a7d0e8cSEnji Cooper 	fesetround(FE_UPWARD);
458*8a7d0e8cSEnji Cooper 	test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200004p+1,
459*8a7d0e8cSEnji Cooper 	     ALL_STD_EXCEPT, FE_INEXACT);
460*8a7d0e8cSEnji Cooper 
461*8a7d0e8cSEnji Cooper 	fesetround(FE_TONEAREST);
462*8a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 64
463*8a7d0e8cSEnji Cooper 	test(fmal, 0x1.4p+0L, 0x1.0000000000000004p+0L, 0x1p-128L,
464*8a7d0e8cSEnji Cooper 	     0x1.4000000000000006p+0L, ALL_STD_EXCEPT, FE_INEXACT);
465*8a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 113
466*8a7d0e8cSEnji Cooper 	test(fmal, 0x1.8000000000000000000000000001p+0L,
467*8a7d0e8cSEnji Cooper 	     0x1.8000000000000000000000000001p+0L,
468*8a7d0e8cSEnji Cooper 	     -0x1.0000000000000000000000000001p-224L,
469*8a7d0e8cSEnji Cooper 	     0x1.2000000000000000000000000001p+1L, ALL_STD_EXCEPT, FE_INEXACT);
470*8a7d0e8cSEnji Cooper #endif
471*8a7d0e8cSEnji Cooper 
472*8a7d0e8cSEnji Cooper }
473*8a7d0e8cSEnji Cooper 
474*8a7d0e8cSEnji Cooper int
475*8a7d0e8cSEnji Cooper main(int argc, char *argv[])
476*8a7d0e8cSEnji Cooper {
477*8a7d0e8cSEnji Cooper 	int rmodes[] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO };
478*8a7d0e8cSEnji Cooper 	int i, j;
479*8a7d0e8cSEnji Cooper 
480*8a7d0e8cSEnji Cooper #if defined(__i386__)
481*8a7d0e8cSEnji Cooper 	printf("1..0 # SKIP all testcases fail on i386\n");
482*8a7d0e8cSEnji Cooper 	exit(0);
483*8a7d0e8cSEnji Cooper #endif
484*8a7d0e8cSEnji Cooper 
485*8a7d0e8cSEnji Cooper 	j = 1;
486*8a7d0e8cSEnji Cooper 
487*8a7d0e8cSEnji Cooper 	printf("1..19\n");
488*8a7d0e8cSEnji Cooper 
489*8a7d0e8cSEnji Cooper 	for (i = 0; i < nitems(rmodes); i++, j++) {
490*8a7d0e8cSEnji Cooper 		printf("rmode = %d\n", rmodes[i]);
491*8a7d0e8cSEnji Cooper 		fesetround(rmodes[i]);
492*8a7d0e8cSEnji Cooper 		test_zeroes();
493*8a7d0e8cSEnji Cooper 		printf("ok %d - fma zeroes\n", j);
494*8a7d0e8cSEnji Cooper 	}
495*8a7d0e8cSEnji Cooper 
496*8a7d0e8cSEnji Cooper 	for (i = 0; i < nitems(rmodes); i++, j++) {
497*8a7d0e8cSEnji Cooper #if defined(__amd64__)
498*8a7d0e8cSEnji Cooper 		printf("ok %d # SKIP testcase fails assertion on "
499*8a7d0e8cSEnji Cooper 		    "amd64\n", j);
500*8a7d0e8cSEnji Cooper 		continue;
501*8a7d0e8cSEnji Cooper #endif
502*8a7d0e8cSEnji Cooper 		printf("rmode = %d\n", rmodes[i]);
503*8a7d0e8cSEnji Cooper 		fesetround(rmodes[i]);
504*8a7d0e8cSEnji Cooper 		test_infinities();
505*8a7d0e8cSEnji Cooper 		printf("ok %d - fma infinities\n", j);
506*8a7d0e8cSEnji Cooper 	}
507*8a7d0e8cSEnji Cooper 
508*8a7d0e8cSEnji Cooper 	fesetround(FE_TONEAREST);
509*8a7d0e8cSEnji Cooper 	test_nans();
510*8a7d0e8cSEnji Cooper 	printf("ok 9 - fma NaNs\n");
511*8a7d0e8cSEnji Cooper 
512*8a7d0e8cSEnji Cooper 	for (i = 0; i < nitems(rmodes); i++, j++) {
513*8a7d0e8cSEnji Cooper 		printf("rmode = %d\n", rmodes[i]);
514*8a7d0e8cSEnji Cooper 		fesetround(rmodes[i]);
515*8a7d0e8cSEnji Cooper 		test_small_z();
516*8a7d0e8cSEnji Cooper 		printf("ok %d - fma small z\n", j);
517*8a7d0e8cSEnji Cooper 	}
518*8a7d0e8cSEnji Cooper 
519*8a7d0e8cSEnji Cooper 	for (i = 0; i < nitems(rmodes); i++, j++) {
520*8a7d0e8cSEnji Cooper 		printf("rmode = %d\n", rmodes[i]);
521*8a7d0e8cSEnji Cooper 		fesetround(rmodes[i]);
522*8a7d0e8cSEnji Cooper 		test_big_z();
523*8a7d0e8cSEnji Cooper 		printf("ok %d - fma big z\n", j);
524*8a7d0e8cSEnji Cooper 	}
525*8a7d0e8cSEnji Cooper 
526*8a7d0e8cSEnji Cooper 	fesetround(FE_TONEAREST);
527*8a7d0e8cSEnji Cooper 	test_accuracy();
528*8a7d0e8cSEnji Cooper 	printf("ok %d - fma accuracy\n", j);
529*8a7d0e8cSEnji Cooper 	j++;
530*8a7d0e8cSEnji Cooper 
531*8a7d0e8cSEnji Cooper 	test_double_rounding();
532*8a7d0e8cSEnji Cooper 	printf("ok %d - fma double rounding\n", j);
533*8a7d0e8cSEnji Cooper 	j++;
534*8a7d0e8cSEnji Cooper 
535*8a7d0e8cSEnji Cooper 	/*
536*8a7d0e8cSEnji Cooper 	 * TODO:
537*8a7d0e8cSEnji Cooper 	 * - Tests for subnormals
538*8a7d0e8cSEnji Cooper 	 * - Cancellation tests (e.g., z = (double)x*y, but x*y is inexact)
539*8a7d0e8cSEnji Cooper 	 */
540*8a7d0e8cSEnji Cooper 
541*8a7d0e8cSEnji Cooper 	return (0);
542*8a7d0e8cSEnji Cooper }
543