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