xref: /dflybsd-src/tools/regression/lib/libm/test-next.c (revision 7f8c68295613ce24cc71827cf210cb3d1e3bc69b)
1*7f8c6829SSascha Wildner /*-
2*7f8c6829SSascha Wildner  * Copyright (c) 2005 David Schultz <das@FreeBSD.org>
3*7f8c6829SSascha Wildner  * All rights reserved.
4*7f8c6829SSascha Wildner  *
5*7f8c6829SSascha Wildner  * Redistribution and use in source and binary forms, with or without
6*7f8c6829SSascha Wildner  * modification, are permitted provided that the following conditions
7*7f8c6829SSascha Wildner  * are met:
8*7f8c6829SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
9*7f8c6829SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
10*7f8c6829SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
11*7f8c6829SSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
12*7f8c6829SSascha Wildner  *    documentation and/or other materials provided with the distribution.
13*7f8c6829SSascha Wildner  *
14*7f8c6829SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*7f8c6829SSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*7f8c6829SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*7f8c6829SSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*7f8c6829SSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*7f8c6829SSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*7f8c6829SSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*7f8c6829SSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*7f8c6829SSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*7f8c6829SSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*7f8c6829SSascha Wildner  * SUCH DAMAGE.
25*7f8c6829SSascha Wildner  *
26*7f8c6829SSascha Wildner  * $FreeBSD: src/tools/regression/lib/msun/test-next.c,v 1.5 2012/11/17 01:53:51 svnexp Exp $
27*7f8c6829SSascha Wildner  */
28*7f8c6829SSascha Wildner 
29*7f8c6829SSascha Wildner /*
30*7f8c6829SSascha Wildner  * Test the correctness of nextafter{,f,l} and nexttoward{,f,l}.
31*7f8c6829SSascha Wildner  */
32*7f8c6829SSascha Wildner 
33*7f8c6829SSascha Wildner #include <fenv.h>
34*7f8c6829SSascha Wildner #include <float.h>
35*7f8c6829SSascha Wildner #include <math.h>
36*7f8c6829SSascha Wildner #include <stdio.h>
37*7f8c6829SSascha Wildner #include <stdlib.h>
38*7f8c6829SSascha Wildner 
39*7f8c6829SSascha Wildner #ifdef	__i386__
40*7f8c6829SSascha Wildner #include <ieeefp.h>
41*7f8c6829SSascha Wildner #endif
42*7f8c6829SSascha Wildner 
43*7f8c6829SSascha Wildner #define	ALL_STD_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | FE_INVALID |\
44*7f8c6829SSascha Wildner 			 FE_OVERFLOW | FE_UNDERFLOW)
45*7f8c6829SSascha Wildner #define	test(exp, ans, ex)	do {			\
46*7f8c6829SSascha Wildner 	double __ans = (ans);				\
47*7f8c6829SSascha Wildner 	feclearexcept(ALL_STD_EXCEPT);			\
48*7f8c6829SSascha Wildner 	_testl(#exp, __LINE__, (exp), __ans, (ex));	\
49*7f8c6829SSascha Wildner } while (0)
50*7f8c6829SSascha Wildner #define	testf(exp, ans, ex)	do {			\
51*7f8c6829SSascha Wildner 	float __ans = (ans);				\
52*7f8c6829SSascha Wildner 	feclearexcept(ALL_STD_EXCEPT);			\
53*7f8c6829SSascha Wildner 	_testl(#exp, __LINE__, (exp), __ans, (ex));	\
54*7f8c6829SSascha Wildner } while (0)
55*7f8c6829SSascha Wildner #define	testl(exp, ans, ex)	do {			\
56*7f8c6829SSascha Wildner 	long double __ans = (ans);			\
57*7f8c6829SSascha Wildner 	feclearexcept(ALL_STD_EXCEPT);			\
58*7f8c6829SSascha Wildner 	_testl(#exp, __LINE__, (exp), __ans, (ex));	\
59*7f8c6829SSascha Wildner } while (0)
60*7f8c6829SSascha Wildner #define	testboth(arg1, arg2, ans, ex, prec)	do {			\
61*7f8c6829SSascha Wildner 	test##prec(nextafter##prec((arg1), (arg2)), (ans), (ex));	\
62*7f8c6829SSascha Wildner 	test##prec(nexttoward##prec((arg1), (arg2)), (ans), (ex));	\
63*7f8c6829SSascha Wildner } while (0)
64*7f8c6829SSascha Wildner #define	testall(arg1, arg2, ans, ex)	do {		\
65*7f8c6829SSascha Wildner 	testboth((arg1), (arg2), (ans), (ex), );	\
66*7f8c6829SSascha Wildner 	testboth((arg1), (arg2), (ans), (ex), f);	\
67*7f8c6829SSascha Wildner 	testboth((arg1), (arg2), (ans), (ex), l);	\
68*7f8c6829SSascha Wildner } while (0)
69*7f8c6829SSascha Wildner 
70*7f8c6829SSascha Wildner static void _testl(const char *, int, long double, long double, int);
71*7f8c6829SSascha Wildner static double idd(double);
72*7f8c6829SSascha Wildner static float idf(float);
73*7f8c6829SSascha Wildner 
74*7f8c6829SSascha Wildner int
main(int argc,char * argv[])75*7f8c6829SSascha Wildner main(int argc, char *argv[])
76*7f8c6829SSascha Wildner {
77*7f8c6829SSascha Wildner 	static const int ex_under = FE_UNDERFLOW | FE_INEXACT;	/* shorthand */
78*7f8c6829SSascha Wildner 	static const int ex_over = FE_OVERFLOW | FE_INEXACT;
79*7f8c6829SSascha Wildner 	long double ldbl_small, ldbl_eps, ldbl_max;
80*7f8c6829SSascha Wildner 
81*7f8c6829SSascha Wildner 	printf("1..5\n");
82*7f8c6829SSascha Wildner 
83*7f8c6829SSascha Wildner #ifdef	__i386__
84*7f8c6829SSascha Wildner 	fpsetprec(FP_PE);
85*7f8c6829SSascha Wildner #endif
86*7f8c6829SSascha Wildner 	/*
87*7f8c6829SSascha Wildner 	 * We can't use a compile-time constant here because gcc on
88*7f8c6829SSascha Wildner 	 * FreeBSD/i386 assumes long doubles are truncated to the
89*7f8c6829SSascha Wildner 	 * double format.
90*7f8c6829SSascha Wildner 	 */
91*7f8c6829SSascha Wildner 	ldbl_small = ldexpl(1.0, LDBL_MIN_EXP - LDBL_MANT_DIG);
92*7f8c6829SSascha Wildner 	ldbl_eps = LDBL_EPSILON;
93*7f8c6829SSascha Wildner 	ldbl_max = ldexpl(1.0 - ldbl_eps / 2, LDBL_MAX_EXP);
94*7f8c6829SSascha Wildner 
95*7f8c6829SSascha Wildner 	/*
96*7f8c6829SSascha Wildner 	 * Special cases involving zeroes.
97*7f8c6829SSascha Wildner 	 */
98*7f8c6829SSascha Wildner #define	ztest(prec)							      \
99*7f8c6829SSascha Wildner 	test##prec(copysign##prec(1.0, nextafter##prec(0.0, -0.0)), -1.0, 0); \
100*7f8c6829SSascha Wildner 	test##prec(copysign##prec(1.0, nextafter##prec(-0.0, 0.0)), 1.0, 0);  \
101*7f8c6829SSascha Wildner 	test##prec(copysign##prec(1.0, nexttoward##prec(0.0, -0.0)), -1.0, 0);\
102*7f8c6829SSascha Wildner 	test##prec(copysign##prec(1.0, nexttoward##prec(-0.0, 0.0)), 1.0, 0)
103*7f8c6829SSascha Wildner 
104*7f8c6829SSascha Wildner 	ztest();
105*7f8c6829SSascha Wildner 	ztest(f);
106*7f8c6829SSascha Wildner 	ztest(l);
107*7f8c6829SSascha Wildner #undef	ztest
108*7f8c6829SSascha Wildner 
109*7f8c6829SSascha Wildner #define	stest(next, eps, prec)					\
110*7f8c6829SSascha Wildner 	test##prec(next(-0.0, 42.0), eps, ex_under);		\
111*7f8c6829SSascha Wildner 	test##prec(next(0.0, -42.0), -eps, ex_under);		\
112*7f8c6829SSascha Wildner 	test##prec(next(0.0, INFINITY), eps, ex_under);		\
113*7f8c6829SSascha Wildner 	test##prec(next(-0.0, -INFINITY), -eps, ex_under)
114*7f8c6829SSascha Wildner 
115*7f8c6829SSascha Wildner 	stest(nextafter, 0x1p-1074, );
116*7f8c6829SSascha Wildner 	stest(nextafterf, 0x1p-149f, f);
117*7f8c6829SSascha Wildner 	stest(nextafterl, ldbl_small, l);
118*7f8c6829SSascha Wildner 	stest(nexttoward, 0x1p-1074, );
119*7f8c6829SSascha Wildner 	stest(nexttowardf, 0x1p-149f, f);
120*7f8c6829SSascha Wildner 	stest(nexttowardl, ldbl_small, l);
121*7f8c6829SSascha Wildner #undef	stest
122*7f8c6829SSascha Wildner 
123*7f8c6829SSascha Wildner 	printf("ok 1 - next\n");
124*7f8c6829SSascha Wildner 
125*7f8c6829SSascha Wildner 	/*
126*7f8c6829SSascha Wildner 	 * `x == y' and NaN tests
127*7f8c6829SSascha Wildner 	 */
128*7f8c6829SSascha Wildner 	testall(42.0, 42.0, 42.0, 0);
129*7f8c6829SSascha Wildner 	testall(-42.0, -42.0, -42.0, 0);
130*7f8c6829SSascha Wildner 	testall(INFINITY, INFINITY, INFINITY, 0);
131*7f8c6829SSascha Wildner 	testall(-INFINITY, -INFINITY, -INFINITY, 0);
132*7f8c6829SSascha Wildner 	testall(NAN, 42.0, NAN, 0);
133*7f8c6829SSascha Wildner 	testall(42.0, NAN, NAN, 0);
134*7f8c6829SSascha Wildner 	testall(NAN, NAN, NAN, 0);
135*7f8c6829SSascha Wildner 
136*7f8c6829SSascha Wildner 	printf("ok 2 - next\n");
137*7f8c6829SSascha Wildner 
138*7f8c6829SSascha Wildner 	/*
139*7f8c6829SSascha Wildner 	 * Tests where x is an ordinary normalized number
140*7f8c6829SSascha Wildner 	 */
141*7f8c6829SSascha Wildner 	testboth(1.0, 2.0, 1.0 + DBL_EPSILON, 0, );
142*7f8c6829SSascha Wildner 	testboth(1.0, -INFINITY, 1.0 - DBL_EPSILON/2, 0, );
143*7f8c6829SSascha Wildner 	testboth(1.0, 2.0, 1.0 + FLT_EPSILON, 0, f);
144*7f8c6829SSascha Wildner 	testboth(1.0, -INFINITY, 1.0 - FLT_EPSILON/2, 0, f);
145*7f8c6829SSascha Wildner 	testboth(1.0, 2.0, 1.0 + ldbl_eps, 0, l);
146*7f8c6829SSascha Wildner 	testboth(1.0, -INFINITY, 1.0 - ldbl_eps/2, 0, l);
147*7f8c6829SSascha Wildner 
148*7f8c6829SSascha Wildner 	testboth(-1.0, 2.0, -1.0 + DBL_EPSILON/2, 0, );
149*7f8c6829SSascha Wildner 	testboth(-1.0, -INFINITY, -1.0 - DBL_EPSILON, 0, );
150*7f8c6829SSascha Wildner 	testboth(-1.0, 2.0, -1.0 + FLT_EPSILON/2, 0, f);
151*7f8c6829SSascha Wildner 	testboth(-1.0, -INFINITY, -1.0 - FLT_EPSILON, 0, f);
152*7f8c6829SSascha Wildner 	testboth(-1.0, 2.0, -1.0 + ldbl_eps/2, 0, l);
153*7f8c6829SSascha Wildner 	testboth(-1.0, -INFINITY, -1.0 - ldbl_eps, 0, l);
154*7f8c6829SSascha Wildner 
155*7f8c6829SSascha Wildner 	/* Cases where nextafter(...) != nexttoward(...) */
156*7f8c6829SSascha Wildner 	test(nexttoward(1.0, 1.0 + ldbl_eps), 1.0 + DBL_EPSILON, 0);
157*7f8c6829SSascha Wildner 	testf(nexttowardf(1.0, 1.0 + ldbl_eps), 1.0 + FLT_EPSILON, 0);
158*7f8c6829SSascha Wildner 	testl(nexttowardl(1.0, 1.0 + ldbl_eps), 1.0 + ldbl_eps, 0);
159*7f8c6829SSascha Wildner 
160*7f8c6829SSascha Wildner 	printf("ok 3 - next\n");
161*7f8c6829SSascha Wildner 
162*7f8c6829SSascha Wildner 	/*
163*7f8c6829SSascha Wildner 	 * Tests at word boundaries, normalization boundaries, etc.
164*7f8c6829SSascha Wildner 	 */
165*7f8c6829SSascha Wildner 	testboth(0x1.87654ffffffffp+0, INFINITY, 0x1.87655p+0, 0, );
166*7f8c6829SSascha Wildner 	testboth(0x1.87655p+0, -INFINITY, 0x1.87654ffffffffp+0, 0, );
167*7f8c6829SSascha Wildner 	testboth(0x1.fffffffffffffp+0, INFINITY, 0x1p1, 0, );
168*7f8c6829SSascha Wildner 	testboth(0x1p1, -INFINITY, 0x1.fffffffffffffp+0, 0, );
169*7f8c6829SSascha Wildner 	testboth(0x0.fffffffffffffp-1022, INFINITY, 0x1p-1022, 0, );
170*7f8c6829SSascha Wildner 	testboth(0x1p-1022, -INFINITY, 0x0.fffffffffffffp-1022, ex_under, );
171*7f8c6829SSascha Wildner 
172*7f8c6829SSascha Wildner 	testboth(0x1.fffffep0f, INFINITY, 0x1p1, 0, f);
173*7f8c6829SSascha Wildner 	testboth(0x1p1, -INFINITY, 0x1.fffffep0f, 0, f);
174*7f8c6829SSascha Wildner 	testboth(0x0.fffffep-126f, INFINITY, 0x1p-126f, 0, f);
175*7f8c6829SSascha Wildner 	testboth(0x1p-126f, -INFINITY, 0x0.fffffep-126f, ex_under, f);
176*7f8c6829SSascha Wildner 
177*7f8c6829SSascha Wildner #if LDBL_MANT_DIG == 53
178*7f8c6829SSascha Wildner 	testboth(0x1.87654ffffffffp+0L, INFINITY, 0x1.87655p+0L, 0, l);
179*7f8c6829SSascha Wildner 	testboth(0x1.87655p+0L, -INFINITY, 0x1.87654ffffffffp+0L, 0, l);
180*7f8c6829SSascha Wildner 	testboth(0x1.fffffffffffffp+0L, INFINITY, 0x1p1L, 0, l);
181*7f8c6829SSascha Wildner 	testboth(0x1p1L, -INFINITY, 0x1.fffffffffffffp+0L, 0, l);
182*7f8c6829SSascha Wildner 	testboth(0x0.fffffffffffffp-1022L, INFINITY, 0x1p-1022L, 0, l);
183*7f8c6829SSascha Wildner 	testboth(0x1p-1022L, -INFINITY, 0x0.fffffffffffffp-1022L, ex_under, l);
184*7f8c6829SSascha Wildner #elif LDBL_MANT_DIG == 64 && !defined(__i386)
185*7f8c6829SSascha Wildner 	testboth(0x1.87654321fffffffep+0L, INFINITY, 0x1.87654322p+0L, 0, l);
186*7f8c6829SSascha Wildner 	testboth(0x1.87654322p+0L, -INFINITY, 0x1.87654321fffffffep+0L, 0, l);
187*7f8c6829SSascha Wildner 	testboth(0x1.fffffffffffffffep0L, INFINITY, 0x1p1L, 0, l);
188*7f8c6829SSascha Wildner 	testboth(0x1p1L, -INFINITY, 0x1.fffffffffffffffep0L, 0, l);
189*7f8c6829SSascha Wildner 	testboth(0x0.fffffffffffffffep-16382L, INFINITY, 0x1p-16382L, 0, l);
190*7f8c6829SSascha Wildner 	testboth(0x1p-16382L, -INFINITY,
191*7f8c6829SSascha Wildner 	    0x0.fffffffffffffffep-16382L, ex_under, l);
192*7f8c6829SSascha Wildner #elif LDBL_MANT_DIG == 113
193*7f8c6829SSascha Wildner 	testboth(0x1.876543210987ffffffffffffffffp+0L, INFINITY,
194*7f8c6829SSascha Wildner 	    0x1.876543210988p+0, 0, l);
195*7f8c6829SSascha Wildner 	testboth(0x1.876543210988p+0L, -INFINITY,
196*7f8c6829SSascha Wildner 	    0x1.876543210987ffffffffffffffffp+0L, 0, l);
197*7f8c6829SSascha Wildner 	testboth(0x1.ffffffffffffffffffffffffffffp0L, INFINITY, 0x1p1L, 0, l);
198*7f8c6829SSascha Wildner 	testboth(0x1p1L, -INFINITY, 0x1.ffffffffffffffffffffffffffffp0L, 0, l);
199*7f8c6829SSascha Wildner 	testboth(0x0.ffffffffffffffffffffffffffffp-16382L, INFINITY,
200*7f8c6829SSascha Wildner 	    0x1p-16382L, 0, l);
201*7f8c6829SSascha Wildner 	testboth(0x1p-16382L, -INFINITY,
202*7f8c6829SSascha Wildner 	    0x0.ffffffffffffffffffffffffffffp-16382L, ex_under, l);
203*7f8c6829SSascha Wildner #endif
204*7f8c6829SSascha Wildner 
205*7f8c6829SSascha Wildner 	printf("ok 4 - next\n");
206*7f8c6829SSascha Wildner 
207*7f8c6829SSascha Wildner 	/*
208*7f8c6829SSascha Wildner 	 * Overflow tests
209*7f8c6829SSascha Wildner 	 */
210*7f8c6829SSascha Wildner 	test(idd(nextafter(DBL_MAX, INFINITY)), INFINITY, ex_over);
211*7f8c6829SSascha Wildner 	test(idd(nextafter(INFINITY, 0.0)), DBL_MAX, 0);
212*7f8c6829SSascha Wildner 	test(idd(nexttoward(DBL_MAX, DBL_MAX * 2.0L)), INFINITY, ex_over);
213*7f8c6829SSascha Wildner #if LDBL_MANT_DIG > 53
214*7f8c6829SSascha Wildner 	test(idd(nexttoward(INFINITY, DBL_MAX * 2.0L)), DBL_MAX, 0);
215*7f8c6829SSascha Wildner #endif
216*7f8c6829SSascha Wildner 
217*7f8c6829SSascha Wildner 	testf(idf(nextafterf(FLT_MAX, INFINITY)), INFINITY, ex_over);
218*7f8c6829SSascha Wildner 	testf(idf(nextafterf(INFINITY, 0.0)), FLT_MAX, 0);
219*7f8c6829SSascha Wildner 	testf(idf(nexttowardf(FLT_MAX, FLT_MAX * 2.0)), INFINITY, ex_over);
220*7f8c6829SSascha Wildner 	testf(idf(nexttowardf(INFINITY, FLT_MAX * 2.0)), FLT_MAX, 0);
221*7f8c6829SSascha Wildner 
222*7f8c6829SSascha Wildner 	testboth(ldbl_max, INFINITY, INFINITY, ex_over, l);
223*7f8c6829SSascha Wildner 	testboth(INFINITY, 0.0, ldbl_max, 0, l);
224*7f8c6829SSascha Wildner 
225*7f8c6829SSascha Wildner 	printf("ok 5 - next\n");
226*7f8c6829SSascha Wildner 
227*7f8c6829SSascha Wildner 	return (0);
228*7f8c6829SSascha Wildner }
229*7f8c6829SSascha Wildner 
230*7f8c6829SSascha Wildner static void
_testl(const char * exp,int line,long double actual,long double expected,int except)231*7f8c6829SSascha Wildner _testl(const char *exp, int line, long double actual, long double expected,
232*7f8c6829SSascha Wildner     int except)
233*7f8c6829SSascha Wildner {
234*7f8c6829SSascha Wildner 	int actual_except;
235*7f8c6829SSascha Wildner 
236*7f8c6829SSascha Wildner 	actual_except = fetestexcept(ALL_STD_EXCEPT);
237*7f8c6829SSascha Wildner 	if (actual != expected && !(isnan(actual) && isnan(expected))) {
238*7f8c6829SSascha Wildner 		fprintf(stderr, "%d: %s returned %La, expecting %La\n",
239*7f8c6829SSascha Wildner 		    line, exp, actual, expected);
240*7f8c6829SSascha Wildner 		abort();
241*7f8c6829SSascha Wildner 	}
242*7f8c6829SSascha Wildner 	if (actual_except != except) {
243*7f8c6829SSascha Wildner 		fprintf(stderr, "%d: %s raised 0x%x, expecting 0x%x\n",
244*7f8c6829SSascha Wildner 		    line, exp, actual_except, except);
245*7f8c6829SSascha Wildner 		abort();
246*7f8c6829SSascha Wildner 	}
247*7f8c6829SSascha Wildner }
248*7f8c6829SSascha Wildner 
249*7f8c6829SSascha Wildner /*
250*7f8c6829SSascha Wildner  * The idd() and idf() routines ensure that doubles and floats are
251*7f8c6829SSascha Wildner  * converted to their respective types instead of stored in the FPU
252*7f8c6829SSascha Wildner  * with extra precision.
253*7f8c6829SSascha Wildner  */
254*7f8c6829SSascha Wildner static double
idd(double x)255*7f8c6829SSascha Wildner idd(double x)
256*7f8c6829SSascha Wildner {
257*7f8c6829SSascha Wildner 	return (x);
258*7f8c6829SSascha Wildner }
259*7f8c6829SSascha Wildner 
260*7f8c6829SSascha Wildner static float
idf(float x)261*7f8c6829SSascha Wildner idf(float x)
262*7f8c6829SSascha Wildner {
263*7f8c6829SSascha Wildner 	return (x);
264*7f8c6829SSascha Wildner }
265