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