1*7f8c6829SSascha Wildner /*-
2*7f8c6829SSascha Wildner  * Copyright (c) 2008 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-invtrig.c,v 1.3 2010/12/06 00:02:49 das Exp $
27*7f8c6829SSascha Wildner  */
28*7f8c6829SSascha Wildner 
29*7f8c6829SSascha Wildner /*
30*7f8c6829SSascha Wildner  * Tests for corner cases in the inverse trigonometric functions. Some
31*7f8c6829SSascha Wildner  * accuracy tests are included as well, but these are very basic
32*7f8c6829SSascha Wildner  * sanity checks, not intended to be comprehensive.
33*7f8c6829SSascha Wildner  */
34*7f8c6829SSascha Wildner 
35*7f8c6829SSascha Wildner #include <assert.h>
36*7f8c6829SSascha Wildner #include <fenv.h>
37*7f8c6829SSascha Wildner #include <float.h>
38*7f8c6829SSascha Wildner #include <math.h>
39*7f8c6829SSascha Wildner #include <stdio.h>
40*7f8c6829SSascha Wildner 
41*7f8c6829SSascha Wildner #define	ALL_STD_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
42*7f8c6829SSascha Wildner 			 FE_OVERFLOW | FE_UNDERFLOW)
43*7f8c6829SSascha Wildner 
44*7f8c6829SSascha Wildner #define	LEN(a)		(sizeof(a) / sizeof((a)[0]))
45*7f8c6829SSascha Wildner 
46*7f8c6829SSascha Wildner #pragma STDC FENV_ACCESS ON
47*7f8c6829SSascha Wildner 
48*7f8c6829SSascha Wildner /*
49*7f8c6829SSascha Wildner  * Test that a function returns the correct value and sets the
50*7f8c6829SSascha Wildner  * exception flags correctly. A tolerance specifying the maximum
51*7f8c6829SSascha Wildner  * relative error allowed may be specified. For the 'testall'
52*7f8c6829SSascha Wildner  * functions, the tolerance is specified in ulps.
53*7f8c6829SSascha Wildner  *
54*7f8c6829SSascha Wildner  * These are macros instead of functions so that assert provides more
55*7f8c6829SSascha Wildner  * meaningful error messages.
56*7f8c6829SSascha Wildner  */
57*7f8c6829SSascha Wildner #define	test_tol(func, x, result, tol, excepts) do {			\
58*7f8c6829SSascha Wildner 	volatile long double _in = (x), _out = (result);		\
59*7f8c6829SSascha Wildner 	assert(feclearexcept(FE_ALL_EXCEPT) == 0);			\
60*7f8c6829SSascha Wildner 	assert(fpequal(func(_in), _out, (tol)));			\
61*7f8c6829SSascha Wildner 	assert((func, fetestexcept(ALL_STD_EXCEPT) == (excepts)));	\
62*7f8c6829SSascha Wildner } while (0)
63*7f8c6829SSascha Wildner #define test(func, x, result, excepts)					\
64*7f8c6829SSascha Wildner 	test_tol(func, (x), (result), 0, (excepts))
65*7f8c6829SSascha Wildner 
66*7f8c6829SSascha Wildner #define	testall_tol(prefix, x, result, tol, excepts) do {		\
67*7f8c6829SSascha Wildner 	test_tol(prefix, (double)(x), (double)(result),			\
68*7f8c6829SSascha Wildner 		 (tol) * ldexp(1.0, 1 - DBL_MANT_DIG), (excepts));	\
69*7f8c6829SSascha Wildner 	test_tol(prefix##f, (float)(x), (float)(result),		\
70*7f8c6829SSascha Wildner 		 (tol) * ldexpf(1.0, 1 - FLT_MANT_DIG), (excepts));	\
71*7f8c6829SSascha Wildner 	test_tol(prefix##l, (x), (result),				\
72*7f8c6829SSascha Wildner 		 (tol) * ldexpl(1.0, 1 - LDBL_MANT_DIG), (excepts));	\
73*7f8c6829SSascha Wildner } while (0)
74*7f8c6829SSascha Wildner #define testall(prefix, x, result, excepts)				\
75*7f8c6829SSascha Wildner 	testall_tol(prefix, (x), (result), 0, (excepts))
76*7f8c6829SSascha Wildner 
77*7f8c6829SSascha Wildner #define	test2_tol(func, y, x, result, tol, excepts) do {		\
78*7f8c6829SSascha Wildner 	volatile long double _iny = (y), _inx = (x), _out = (result);	\
79*7f8c6829SSascha Wildner 	assert(feclearexcept(FE_ALL_EXCEPT) == 0);			\
80*7f8c6829SSascha Wildner 	assert(fpequal(func(_iny, _inx), _out, (tol)));			\
81*7f8c6829SSascha Wildner 	assert((func, fetestexcept(ALL_STD_EXCEPT) == (excepts)));	\
82*7f8c6829SSascha Wildner } while (0)
83*7f8c6829SSascha Wildner #define test2(func, y, x, result, excepts)				\
84*7f8c6829SSascha Wildner 	test2_tol(func, (y), (x), (result), 0, (excepts))
85*7f8c6829SSascha Wildner 
86*7f8c6829SSascha Wildner #define	testall2_tol(prefix, y, x, result, tol, excepts) do {		\
87*7f8c6829SSascha Wildner 	test2_tol(prefix, (double)(y), (double)(x), (double)(result),	\
88*7f8c6829SSascha Wildner 		  (tol) * ldexp(1.0, 1 - DBL_MANT_DIG), (excepts));	\
89*7f8c6829SSascha Wildner 	test2_tol(prefix##f, (float)(y), (float)(x), (float)(result),	\
90*7f8c6829SSascha Wildner 		  (tol) * ldexpf(1.0, 1 - FLT_MANT_DIG), (excepts));	\
91*7f8c6829SSascha Wildner 	test2_tol(prefix##l, (y), (x), (result),			\
92*7f8c6829SSascha Wildner 		  (tol) * ldexpl(1.0, 1 - LDBL_MANT_DIG), (excepts));	\
93*7f8c6829SSascha Wildner } while (0)
94*7f8c6829SSascha Wildner #define testall2(prefix, y, x, result, excepts)				\
95*7f8c6829SSascha Wildner 	testall2_tol(prefix, (y), (x), (result), 0, (excepts))
96*7f8c6829SSascha Wildner 
97*7f8c6829SSascha Wildner long double
98*7f8c6829SSascha Wildner pi =   3.14159265358979323846264338327950280e+00L,
99*7f8c6829SSascha Wildner pio3 = 1.04719755119659774615421446109316766e+00L,
100*7f8c6829SSascha Wildner c3pi = 9.42477796076937971538793014983850839e+00L,
101*7f8c6829SSascha Wildner c5pi = 1.57079632679489661923132169163975140e+01L,
102*7f8c6829SSascha Wildner c7pi = 2.19911485751285526692385036829565196e+01L,
103*7f8c6829SSascha Wildner c5pio3 = 5.23598775598298873077107230546583851e+00L,
104*7f8c6829SSascha Wildner sqrt2m1 = 4.14213562373095048801688724209698081e-01L;
105*7f8c6829SSascha Wildner 
106*7f8c6829SSascha Wildner /*
107*7f8c6829SSascha Wildner  * Determine whether x and y are equal to within a relative error of tol,
108*7f8c6829SSascha Wildner  * with two special rules:
109*7f8c6829SSascha Wildner  *	+0.0 != -0.0
110*7f8c6829SSascha Wildner  *	 NaN == NaN
111*7f8c6829SSascha Wildner  */
112*7f8c6829SSascha Wildner int
fpequal(long double x,long double y,long double tol)113*7f8c6829SSascha Wildner fpequal(long double x, long double y, long double tol)
114*7f8c6829SSascha Wildner {
115*7f8c6829SSascha Wildner 	fenv_t env;
116*7f8c6829SSascha Wildner 	int ret;
117*7f8c6829SSascha Wildner 
118*7f8c6829SSascha Wildner 	if (isnan(x) && isnan(y))
119*7f8c6829SSascha Wildner 		return (1);
120*7f8c6829SSascha Wildner 	if (!signbit(x) != !signbit(y))
121*7f8c6829SSascha Wildner 		return (0);
122*7f8c6829SSascha Wildner 	if (x == y)
123*7f8c6829SSascha Wildner 		return (1);
124*7f8c6829SSascha Wildner 	if (tol == 0)
125*7f8c6829SSascha Wildner 		return (0);
126*7f8c6829SSascha Wildner 
127*7f8c6829SSascha Wildner 	/* Hard case: need to check the tolerance. */
128*7f8c6829SSascha Wildner 	feholdexcept(&env);
129*7f8c6829SSascha Wildner 	ret = fabsl(x - y) <= fabsl(y * tol);
130*7f8c6829SSascha Wildner 	fesetenv(&env);
131*7f8c6829SSascha Wildner 	return (ret);
132*7f8c6829SSascha Wildner }
133*7f8c6829SSascha Wildner 
134*7f8c6829SSascha Wildner /*
135*7f8c6829SSascha Wildner  * Test special case inputs in asin(), acos() and atan(): signed
136*7f8c6829SSascha Wildner  * zeroes, infinities, and NaNs.
137*7f8c6829SSascha Wildner  */
138*7f8c6829SSascha Wildner static void
test_special(void)139*7f8c6829SSascha Wildner test_special(void)
140*7f8c6829SSascha Wildner {
141*7f8c6829SSascha Wildner 
142*7f8c6829SSascha Wildner 	testall(asin, 0.0, 0.0, 0);
143*7f8c6829SSascha Wildner 	testall(acos, 0.0, pi / 2, FE_INEXACT);
144*7f8c6829SSascha Wildner 	testall(atan, 0.0, 0.0, 0);
145*7f8c6829SSascha Wildner 	testall(asin, -0.0, -0.0, 0);
146*7f8c6829SSascha Wildner 	testall(acos, -0.0, pi / 2, FE_INEXACT);
147*7f8c6829SSascha Wildner 	testall(atan, -0.0, -0.0, 0);
148*7f8c6829SSascha Wildner 
149*7f8c6829SSascha Wildner 	testall(asin, INFINITY, NAN, FE_INVALID);
150*7f8c6829SSascha Wildner 	testall(acos, INFINITY, NAN, FE_INVALID);
151*7f8c6829SSascha Wildner 	testall(atan, INFINITY, pi / 2, FE_INEXACT);
152*7f8c6829SSascha Wildner 	testall(asin, -INFINITY, NAN, FE_INVALID);
153*7f8c6829SSascha Wildner 	testall(acos, -INFINITY, NAN, FE_INVALID);
154*7f8c6829SSascha Wildner 	testall(atan, -INFINITY, -pi / 2, FE_INEXACT);
155*7f8c6829SSascha Wildner 
156*7f8c6829SSascha Wildner 	testall(asin, NAN, NAN, 0);
157*7f8c6829SSascha Wildner 	testall(acos, NAN, NAN, 0);
158*7f8c6829SSascha Wildner 	testall(atan, NAN, NAN, 0);
159*7f8c6829SSascha Wildner }
160*7f8c6829SSascha Wildner 
161*7f8c6829SSascha Wildner /*
162*7f8c6829SSascha Wildner  * Test special case inputs in atan2(), where the exact value of y/x is
163*7f8c6829SSascha Wildner  * zero or non-finite.
164*7f8c6829SSascha Wildner  */
165*7f8c6829SSascha Wildner static void
test_special_atan2(void)166*7f8c6829SSascha Wildner test_special_atan2(void)
167*7f8c6829SSascha Wildner {
168*7f8c6829SSascha Wildner 	long double z;
169*7f8c6829SSascha Wildner 	int e;
170*7f8c6829SSascha Wildner 
171*7f8c6829SSascha Wildner 	testall2(atan2, 0.0, -0.0, pi, FE_INEXACT);
172*7f8c6829SSascha Wildner 	testall2(atan2, -0.0, -0.0, -pi, FE_INEXACT);
173*7f8c6829SSascha Wildner 	testall2(atan2, 0.0, 0.0, 0.0, 0);
174*7f8c6829SSascha Wildner 	testall2(atan2, -0.0, 0.0, -0.0, 0);
175*7f8c6829SSascha Wildner 
176*7f8c6829SSascha Wildner 	testall2(atan2, INFINITY, -INFINITY, c3pi / 4, FE_INEXACT);
177*7f8c6829SSascha Wildner 	testall2(atan2, -INFINITY, -INFINITY, -c3pi / 4, FE_INEXACT);
178*7f8c6829SSascha Wildner 	testall2(atan2, INFINITY, INFINITY, pi / 4, FE_INEXACT);
179*7f8c6829SSascha Wildner 	testall2(atan2, -INFINITY, INFINITY, -pi / 4, FE_INEXACT);
180*7f8c6829SSascha Wildner 
181*7f8c6829SSascha Wildner 	/* Tests with one input in the range (0, Inf]. */
182*7f8c6829SSascha Wildner 	z = 1.23456789L;
183*7f8c6829SSascha Wildner 	for (e = FLT_MIN_EXP - FLT_MANT_DIG; e <= FLT_MAX_EXP; e++) {
184*7f8c6829SSascha Wildner 		test2(atan2f, 0.0, ldexpf(z, e), 0.0, 0);
185*7f8c6829SSascha Wildner 		test2(atan2f, -0.0, ldexpf(z, e), -0.0, 0);
186*7f8c6829SSascha Wildner 		test2(atan2f, 0.0, ldexpf(-z, e), (float)pi, FE_INEXACT);
187*7f8c6829SSascha Wildner 		test2(atan2f, -0.0, ldexpf(-z, e), (float)-pi, FE_INEXACT);
188*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(z, e), 0.0, (float)pi / 2, FE_INEXACT);
189*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(z, e), -0.0, (float)pi / 2, FE_INEXACT);
190*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(-z, e), 0.0, (float)-pi / 2, FE_INEXACT);
191*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(-z, e), -0.0, (float)-pi / 2, FE_INEXACT);
192*7f8c6829SSascha Wildner 	}
193*7f8c6829SSascha Wildner 	for (e = DBL_MIN_EXP - DBL_MANT_DIG; e <= DBL_MAX_EXP; e++) {
194*7f8c6829SSascha Wildner 		test2(atan2, 0.0, ldexp(z, e), 0.0, 0);
195*7f8c6829SSascha Wildner 		test2(atan2, -0.0, ldexp(z, e), -0.0, 0);
196*7f8c6829SSascha Wildner 		test2(atan2, 0.0, ldexp(-z, e), (double)pi, FE_INEXACT);
197*7f8c6829SSascha Wildner 		test2(atan2, -0.0, ldexp(-z, e), (double)-pi, FE_INEXACT);
198*7f8c6829SSascha Wildner 		test2(atan2, ldexp(z, e), 0.0, (double)pi / 2, FE_INEXACT);
199*7f8c6829SSascha Wildner 		test2(atan2, ldexp(z, e), -0.0, (double)pi / 2, FE_INEXACT);
200*7f8c6829SSascha Wildner 		test2(atan2, ldexp(-z, e), 0.0, (double)-pi / 2, FE_INEXACT);
201*7f8c6829SSascha Wildner 		test2(atan2, ldexp(-z, e), -0.0, (double)-pi / 2, FE_INEXACT);
202*7f8c6829SSascha Wildner 	}
203*7f8c6829SSascha Wildner 	for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e <= LDBL_MAX_EXP; e++) {
204*7f8c6829SSascha Wildner 		test2(atan2l, 0.0, ldexpl(z, e), 0.0, 0);
205*7f8c6829SSascha Wildner 		test2(atan2l, -0.0, ldexpl(z, e), -0.0, 0);
206*7f8c6829SSascha Wildner 		test2(atan2l, 0.0, ldexpl(-z, e), pi, FE_INEXACT);
207*7f8c6829SSascha Wildner 		test2(atan2l, -0.0, ldexpl(-z, e), -pi, FE_INEXACT);
208*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(z, e), 0.0, pi / 2, FE_INEXACT);
209*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(z, e), -0.0, pi / 2, FE_INEXACT);
210*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(-z, e), 0.0, -pi / 2, FE_INEXACT);
211*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(-z, e), -0.0, -pi / 2, FE_INEXACT);
212*7f8c6829SSascha Wildner 	}
213*7f8c6829SSascha Wildner 
214*7f8c6829SSascha Wildner 	/* Tests with one input in the range (0, Inf). */
215*7f8c6829SSascha Wildner 	for (e = FLT_MIN_EXP - FLT_MANT_DIG; e <= FLT_MAX_EXP - 1; e++) {
216*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(z, e), INFINITY, 0.0, 0);
217*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(-z,e), INFINITY, -0.0, 0);
218*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(z, e), -INFINITY, (float)pi, FE_INEXACT);
219*7f8c6829SSascha Wildner 		test2(atan2f, ldexpf(-z,e), -INFINITY, (float)-pi, FE_INEXACT);
220*7f8c6829SSascha Wildner 		test2(atan2f, INFINITY, ldexpf(z,e), (float)pi/2, FE_INEXACT);
221*7f8c6829SSascha Wildner 		test2(atan2f, INFINITY, ldexpf(-z,e), (float)pi/2, FE_INEXACT);
222*7f8c6829SSascha Wildner 		test2(atan2f, -INFINITY, ldexpf(z,e), (float)-pi/2,FE_INEXACT);
223*7f8c6829SSascha Wildner 		test2(atan2f, -INFINITY, ldexpf(-z,e),(float)-pi/2,FE_INEXACT);
224*7f8c6829SSascha Wildner 	}
225*7f8c6829SSascha Wildner 	for (e = DBL_MIN_EXP - DBL_MANT_DIG; e <= DBL_MAX_EXP - 1; e++) {
226*7f8c6829SSascha Wildner 		test2(atan2, ldexp(z, e), INFINITY, 0.0, 0);
227*7f8c6829SSascha Wildner 		test2(atan2, ldexp(-z,e), INFINITY, -0.0, 0);
228*7f8c6829SSascha Wildner 		test2(atan2, ldexp(z, e), -INFINITY, (double)pi, FE_INEXACT);
229*7f8c6829SSascha Wildner 		test2(atan2, ldexp(-z,e), -INFINITY, (double)-pi, FE_INEXACT);
230*7f8c6829SSascha Wildner 		test2(atan2, INFINITY, ldexp(z,e), (double)pi/2, FE_INEXACT);
231*7f8c6829SSascha Wildner 		test2(atan2, INFINITY, ldexp(-z,e), (double)pi/2, FE_INEXACT);
232*7f8c6829SSascha Wildner 		test2(atan2, -INFINITY, ldexp(z,e), (double)-pi/2,FE_INEXACT);
233*7f8c6829SSascha Wildner 		test2(atan2, -INFINITY, ldexp(-z,e),(double)-pi/2,FE_INEXACT);
234*7f8c6829SSascha Wildner 	}
235*7f8c6829SSascha Wildner 	for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e <= LDBL_MAX_EXP - 1; e++) {
236*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(z, e), INFINITY, 0.0, 0);
237*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(-z,e), INFINITY, -0.0, 0);
238*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(z, e), -INFINITY, pi, FE_INEXACT);
239*7f8c6829SSascha Wildner 		test2(atan2l, ldexpl(-z,e), -INFINITY, -pi, FE_INEXACT);
240*7f8c6829SSascha Wildner 		test2(atan2l, INFINITY, ldexpl(z, e), pi / 2, FE_INEXACT);
241*7f8c6829SSascha Wildner 		test2(atan2l, INFINITY, ldexpl(-z, e), pi / 2, FE_INEXACT);
242*7f8c6829SSascha Wildner 		test2(atan2l, -INFINITY, ldexpl(z, e), -pi / 2, FE_INEXACT);
243*7f8c6829SSascha Wildner 		test2(atan2l, -INFINITY, ldexpl(-z, e), -pi / 2, FE_INEXACT);
244*7f8c6829SSascha Wildner 	}
245*7f8c6829SSascha Wildner }
246*7f8c6829SSascha Wildner 
247*7f8c6829SSascha Wildner /*
248*7f8c6829SSascha Wildner  * Test various inputs to asin(), acos() and atan() and verify that the
249*7f8c6829SSascha Wildner  * results are accurate to within 1 ulp.
250*7f8c6829SSascha Wildner  */
251*7f8c6829SSascha Wildner static void
test_accuracy(void)252*7f8c6829SSascha Wildner test_accuracy(void)
253*7f8c6829SSascha Wildner {
254*7f8c6829SSascha Wildner 
255*7f8c6829SSascha Wildner 	/* We expect correctly rounded results for these basic cases. */
256*7f8c6829SSascha Wildner 	testall(asin, 1.0, pi / 2, FE_INEXACT);
257*7f8c6829SSascha Wildner 	testall(acos, 1.0, 0, 0);
258*7f8c6829SSascha Wildner 	testall(atan, 1.0, pi / 4, FE_INEXACT);
259*7f8c6829SSascha Wildner 	testall(asin, -1.0, -pi / 2, FE_INEXACT);
260*7f8c6829SSascha Wildner 	testall(acos, -1.0, pi, FE_INEXACT);
261*7f8c6829SSascha Wildner 	testall(atan, -1.0, -pi / 4, FE_INEXACT);
262*7f8c6829SSascha Wildner 
263*7f8c6829SSascha Wildner 	/*
264*7f8c6829SSascha Wildner 	 * Here we expect answers to be within 1 ulp, although inexactness
265*7f8c6829SSascha Wildner 	 * in the input, combined with double rounding, could cause larger
266*7f8c6829SSascha Wildner 	 * errors.
267*7f8c6829SSascha Wildner 	 */
268*7f8c6829SSascha Wildner 
269*7f8c6829SSascha Wildner 	testall_tol(asin, sqrtl(2) / 2, pi / 4, 1, FE_INEXACT);
270*7f8c6829SSascha Wildner 	testall_tol(acos, sqrtl(2) / 2, pi / 4, 1, FE_INEXACT);
271*7f8c6829SSascha Wildner 	testall_tol(asin, -sqrtl(2) / 2, -pi / 4, 1, FE_INEXACT);
272*7f8c6829SSascha Wildner 	testall_tol(acos, -sqrtl(2) / 2, c3pi / 4, 1, FE_INEXACT);
273*7f8c6829SSascha Wildner 
274*7f8c6829SSascha Wildner 	testall_tol(asin, sqrtl(3) / 2, pio3, 1, FE_INEXACT);
275*7f8c6829SSascha Wildner 	testall_tol(acos, sqrtl(3) / 2, pio3 / 2, 1, FE_INEXACT);
276*7f8c6829SSascha Wildner 	testall_tol(atan, sqrtl(3), pio3, 1, FE_INEXACT);
277*7f8c6829SSascha Wildner 	testall_tol(asin, -sqrtl(3) / 2, -pio3, 1, FE_INEXACT);
278*7f8c6829SSascha Wildner 	testall_tol(acos, -sqrtl(3) / 2, c5pio3 / 2, 1, FE_INEXACT);
279*7f8c6829SSascha Wildner 	testall_tol(atan, -sqrtl(3), -pio3, 1, FE_INEXACT);
280*7f8c6829SSascha Wildner 
281*7f8c6829SSascha Wildner 	testall_tol(atan, sqrt2m1, pi / 8, 1, FE_INEXACT);
282*7f8c6829SSascha Wildner 	testall_tol(atan, -sqrt2m1, -pi / 8, 1, FE_INEXACT);
283*7f8c6829SSascha Wildner }
284*7f8c6829SSascha Wildner 
285*7f8c6829SSascha Wildner /*
286*7f8c6829SSascha Wildner  * Test inputs to atan2() where x is a power of 2. These are easy cases
287*7f8c6829SSascha Wildner  * because y/x is exact.
288*7f8c6829SSascha Wildner  */
289*7f8c6829SSascha Wildner static void
test_p2x_atan2(void)290*7f8c6829SSascha Wildner test_p2x_atan2(void)
291*7f8c6829SSascha Wildner {
292*7f8c6829SSascha Wildner 
293*7f8c6829SSascha Wildner 	testall2(atan2, 1.0, 1.0, pi / 4, FE_INEXACT);
294*7f8c6829SSascha Wildner 	testall2(atan2, 1.0, -1.0, c3pi / 4, FE_INEXACT);
295*7f8c6829SSascha Wildner 	testall2(atan2, -1.0, 1.0, -pi / 4, FE_INEXACT);
296*7f8c6829SSascha Wildner 	testall2(atan2, -1.0, -1.0, -c3pi / 4, FE_INEXACT);
297*7f8c6829SSascha Wildner 
298*7f8c6829SSascha Wildner 	testall2_tol(atan2, sqrt2m1 * 2, 2.0, pi / 8, 1, FE_INEXACT);
299*7f8c6829SSascha Wildner 	testall2_tol(atan2, sqrt2m1 * 2, -2.0, c7pi / 8, 1, FE_INEXACT);
300*7f8c6829SSascha Wildner 	testall2_tol(atan2, -sqrt2m1 * 2, 2.0, -pi / 8, 1, FE_INEXACT);
301*7f8c6829SSascha Wildner 	testall2_tol(atan2, -sqrt2m1 * 2, -2.0, -c7pi / 8, 1, FE_INEXACT);
302*7f8c6829SSascha Wildner 
303*7f8c6829SSascha Wildner 	testall2_tol(atan2, sqrtl(3) * 0.5, 0.5, pio3, 1, FE_INEXACT);
304*7f8c6829SSascha Wildner 	testall2_tol(atan2, sqrtl(3) * 0.5, -0.5, pio3 * 2, 1, FE_INEXACT);
305*7f8c6829SSascha Wildner 	testall2_tol(atan2, -sqrtl(3) * 0.5, 0.5, -pio3, 1, FE_INEXACT);
306*7f8c6829SSascha Wildner 	testall2_tol(atan2, -sqrtl(3) * 0.5, -0.5, -pio3 * 2, 1, FE_INEXACT);
307*7f8c6829SSascha Wildner }
308*7f8c6829SSascha Wildner 
309*7f8c6829SSascha Wildner /*
310*7f8c6829SSascha Wildner  * Test inputs very close to 0.
311*7f8c6829SSascha Wildner  */
312*7f8c6829SSascha Wildner static void
test_tiny(void)313*7f8c6829SSascha Wildner test_tiny(void)
314*7f8c6829SSascha Wildner {
315*7f8c6829SSascha Wildner 	float tiny = 0x1.23456p-120f;
316*7f8c6829SSascha Wildner 
317*7f8c6829SSascha Wildner 	testall(asin, tiny, tiny, FE_INEXACT);
318*7f8c6829SSascha Wildner 	testall(acos, tiny, pi / 2, FE_INEXACT);
319*7f8c6829SSascha Wildner 	testall(atan, tiny, tiny, FE_INEXACT);
320*7f8c6829SSascha Wildner 
321*7f8c6829SSascha Wildner 	testall(asin, -tiny, -tiny, FE_INEXACT);
322*7f8c6829SSascha Wildner 	testall(acos, -tiny, pi / 2, FE_INEXACT);
323*7f8c6829SSascha Wildner 	testall(atan, -tiny, -tiny, FE_INEXACT);
324*7f8c6829SSascha Wildner 
325*7f8c6829SSascha Wildner 	/* Test inputs to atan2() that would cause y/x to underflow. */
326*7f8c6829SSascha Wildner 	test2(atan2f, 0x1.0p-100, 0x1.0p100, 0.0, FE_INEXACT | FE_UNDERFLOW);
327*7f8c6829SSascha Wildner 	test2(atan2, 0x1.0p-1000, 0x1.0p1000, 0.0, FE_INEXACT | FE_UNDERFLOW);
328*7f8c6829SSascha Wildner 	test2(atan2l, ldexpl(1.0, 100 - LDBL_MAX_EXP),
329*7f8c6829SSascha Wildner 	      ldexpl(1.0, LDBL_MAX_EXP - 100), 0.0, FE_INEXACT | FE_UNDERFLOW);
330*7f8c6829SSascha Wildner 	test2(atan2f, -0x1.0p-100, 0x1.0p100, -0.0, FE_INEXACT | FE_UNDERFLOW);
331*7f8c6829SSascha Wildner 	test2(atan2, -0x1.0p-1000, 0x1.0p1000, -0.0, FE_INEXACT | FE_UNDERFLOW);
332*7f8c6829SSascha Wildner 	test2(atan2l, -ldexpl(1.0, 100 - LDBL_MAX_EXP),
333*7f8c6829SSascha Wildner 	      ldexpl(1.0, LDBL_MAX_EXP - 100), -0.0, FE_INEXACT | FE_UNDERFLOW);
334*7f8c6829SSascha Wildner 	test2(atan2f, 0x1.0p-100, -0x1.0p100, (float)pi, FE_INEXACT);
335*7f8c6829SSascha Wildner 	test2(atan2, 0x1.0p-1000, -0x1.0p1000, (double)pi, FE_INEXACT);
336*7f8c6829SSascha Wildner 	test2(atan2l, ldexpl(1.0, 100 - LDBL_MAX_EXP),
337*7f8c6829SSascha Wildner 	      -ldexpl(1.0, LDBL_MAX_EXP - 100), pi, FE_INEXACT);
338*7f8c6829SSascha Wildner 	test2(atan2f, -0x1.0p-100, -0x1.0p100, (float)-pi, FE_INEXACT);
339*7f8c6829SSascha Wildner 	test2(atan2, -0x1.0p-1000, -0x1.0p1000, (double)-pi, FE_INEXACT);
340*7f8c6829SSascha Wildner 	test2(atan2l, -ldexpl(1.0, 100 - LDBL_MAX_EXP),
341*7f8c6829SSascha Wildner 	      -ldexpl(1.0, LDBL_MAX_EXP - 100), -pi, FE_INEXACT);
342*7f8c6829SSascha Wildner }
343*7f8c6829SSascha Wildner 
344*7f8c6829SSascha Wildner /*
345*7f8c6829SSascha Wildner  * Test very large inputs to atan().
346*7f8c6829SSascha Wildner  */
347*7f8c6829SSascha Wildner static void
test_atan_huge(void)348*7f8c6829SSascha Wildner test_atan_huge(void)
349*7f8c6829SSascha Wildner {
350*7f8c6829SSascha Wildner 	float huge = 0x1.23456p120;
351*7f8c6829SSascha Wildner 
352*7f8c6829SSascha Wildner 	testall(atan, huge, pi / 2, FE_INEXACT);
353*7f8c6829SSascha Wildner 	testall(atan, -huge, -pi / 2, FE_INEXACT);
354*7f8c6829SSascha Wildner 
355*7f8c6829SSascha Wildner 	/* Test inputs to atan2() that would cause y/x to overflow. */
356*7f8c6829SSascha Wildner 	test2(atan2f, 0x1.0p100, 0x1.0p-100, (float)pi / 2, FE_INEXACT);
357*7f8c6829SSascha Wildner 	test2(atan2, 0x1.0p1000, 0x1.0p-1000, (double)pi / 2, FE_INEXACT);
358*7f8c6829SSascha Wildner 	test2(atan2l, ldexpl(1.0, LDBL_MAX_EXP - 100),
359*7f8c6829SSascha Wildner 	      ldexpl(1.0, 100 - LDBL_MAX_EXP), pi / 2, FE_INEXACT);
360*7f8c6829SSascha Wildner 	test2(atan2f, -0x1.0p100, 0x1.0p-100, (float)-pi / 2, FE_INEXACT);
361*7f8c6829SSascha Wildner 	test2(atan2, -0x1.0p1000, 0x1.0p-1000, (double)-pi / 2, FE_INEXACT);
362*7f8c6829SSascha Wildner 	test2(atan2l, -ldexpl(1.0, LDBL_MAX_EXP - 100),
363*7f8c6829SSascha Wildner 	      ldexpl(1.0, 100 - LDBL_MAX_EXP), -pi / 2, FE_INEXACT);
364*7f8c6829SSascha Wildner 
365*7f8c6829SSascha Wildner 	test2(atan2f, 0x1.0p100, -0x1.0p-100, (float)pi / 2, FE_INEXACT);
366*7f8c6829SSascha Wildner 	test2(atan2, 0x1.0p1000, -0x1.0p-1000, (double)pi / 2, FE_INEXACT);
367*7f8c6829SSascha Wildner 	test2(atan2l, ldexpl(1.0, LDBL_MAX_EXP - 100),
368*7f8c6829SSascha Wildner 	      -ldexpl(1.0, 100 - LDBL_MAX_EXP), pi / 2, FE_INEXACT);
369*7f8c6829SSascha Wildner 	test2(atan2f, -0x1.0p100, -0x1.0p-100, (float)-pi / 2, FE_INEXACT);
370*7f8c6829SSascha Wildner 	test2(atan2, -0x1.0p1000, -0x1.0p-1000, (double)-pi / 2, FE_INEXACT);
371*7f8c6829SSascha Wildner 	test2(atan2l, -ldexpl(1.0, LDBL_MAX_EXP - 100),
372*7f8c6829SSascha Wildner 	      -ldexpl(1.0, 100 - LDBL_MAX_EXP), -pi / 2, FE_INEXACT);
373*7f8c6829SSascha Wildner }
374*7f8c6829SSascha Wildner 
375*7f8c6829SSascha Wildner /*
376*7f8c6829SSascha Wildner  * Test that sin(asin(x)) == x, and similarly for acos() and atan().
377*7f8c6829SSascha Wildner  * You need to have a working sinl(), cosl(), and tanl() for these
378*7f8c6829SSascha Wildner  * tests to pass.
379*7f8c6829SSascha Wildner  */
380*7f8c6829SSascha Wildner static long double
sinasinf(float x)381*7f8c6829SSascha Wildner sinasinf(float x)
382*7f8c6829SSascha Wildner {
383*7f8c6829SSascha Wildner 
384*7f8c6829SSascha Wildner 	return (sinl(asinf(x)));
385*7f8c6829SSascha Wildner }
386*7f8c6829SSascha Wildner 
387*7f8c6829SSascha Wildner static long double
sinasin(double x)388*7f8c6829SSascha Wildner sinasin(double x)
389*7f8c6829SSascha Wildner {
390*7f8c6829SSascha Wildner 
391*7f8c6829SSascha Wildner 	return (sinl(asin(x)));
392*7f8c6829SSascha Wildner }
393*7f8c6829SSascha Wildner 
394*7f8c6829SSascha Wildner static long double
sinasinl(long double x)395*7f8c6829SSascha Wildner sinasinl(long double x)
396*7f8c6829SSascha Wildner {
397*7f8c6829SSascha Wildner 
398*7f8c6829SSascha Wildner 	return (sinl(asinl(x)));
399*7f8c6829SSascha Wildner }
400*7f8c6829SSascha Wildner 
401*7f8c6829SSascha Wildner static long double
cosacosf(float x)402*7f8c6829SSascha Wildner cosacosf(float x)
403*7f8c6829SSascha Wildner {
404*7f8c6829SSascha Wildner 
405*7f8c6829SSascha Wildner 	return (cosl(acosf(x)));
406*7f8c6829SSascha Wildner }
407*7f8c6829SSascha Wildner 
408*7f8c6829SSascha Wildner static long double
cosacos(double x)409*7f8c6829SSascha Wildner cosacos(double x)
410*7f8c6829SSascha Wildner {
411*7f8c6829SSascha Wildner 
412*7f8c6829SSascha Wildner 	return (cosl(acos(x)));
413*7f8c6829SSascha Wildner }
414*7f8c6829SSascha Wildner 
415*7f8c6829SSascha Wildner static long double
cosacosl(long double x)416*7f8c6829SSascha Wildner cosacosl(long double x)
417*7f8c6829SSascha Wildner {
418*7f8c6829SSascha Wildner 
419*7f8c6829SSascha Wildner 	return (cosl(acosl(x)));
420*7f8c6829SSascha Wildner }
421*7f8c6829SSascha Wildner 
422*7f8c6829SSascha Wildner static long double
tanatanf(float x)423*7f8c6829SSascha Wildner tanatanf(float x)
424*7f8c6829SSascha Wildner {
425*7f8c6829SSascha Wildner 
426*7f8c6829SSascha Wildner 	return (tanl(atanf(x)));
427*7f8c6829SSascha Wildner }
428*7f8c6829SSascha Wildner 
429*7f8c6829SSascha Wildner static long double
tanatan(double x)430*7f8c6829SSascha Wildner tanatan(double x)
431*7f8c6829SSascha Wildner {
432*7f8c6829SSascha Wildner 
433*7f8c6829SSascha Wildner 	return (tanl(atan(x)));
434*7f8c6829SSascha Wildner }
435*7f8c6829SSascha Wildner 
436*7f8c6829SSascha Wildner static long double
tanatanl(long double x)437*7f8c6829SSascha Wildner tanatanl(long double x)
438*7f8c6829SSascha Wildner {
439*7f8c6829SSascha Wildner 
440*7f8c6829SSascha Wildner 	return (tanl(atanl(x)));
441*7f8c6829SSascha Wildner }
442*7f8c6829SSascha Wildner 
443*7f8c6829SSascha Wildner static void
test_inverse(void)444*7f8c6829SSascha Wildner test_inverse(void)
445*7f8c6829SSascha Wildner {
446*7f8c6829SSascha Wildner 	float i;
447*7f8c6829SSascha Wildner 
448*7f8c6829SSascha Wildner 	for (i = -1; i <= 1; i += 0x1.0p-12f) {
449*7f8c6829SSascha Wildner 		testall_tol(sinasin, i, i, 2, i == 0 ? 0 : FE_INEXACT);
450*7f8c6829SSascha Wildner 		/* The relative error for cosacos is very large near x=0. */
451*7f8c6829SSascha Wildner 		if (fabsf(i) > 0x1.0p-4f)
452*7f8c6829SSascha Wildner 			testall_tol(cosacos, i, i, 16, i == 1 ? 0 : FE_INEXACT);
453*7f8c6829SSascha Wildner 		testall_tol(tanatan, i, i, 2, i == 0 ? 0 : FE_INEXACT);
454*7f8c6829SSascha Wildner 	}
455*7f8c6829SSascha Wildner }
456*7f8c6829SSascha Wildner 
457*7f8c6829SSascha Wildner int
main(int argc,char * argv[])458*7f8c6829SSascha Wildner main(int argc, char *argv[])
459*7f8c6829SSascha Wildner {
460*7f8c6829SSascha Wildner 
461*7f8c6829SSascha Wildner 	printf("1..7\n");
462*7f8c6829SSascha Wildner 
463*7f8c6829SSascha Wildner 	test_special();
464*7f8c6829SSascha Wildner 	printf("ok 1 - special\n");
465*7f8c6829SSascha Wildner 
466*7f8c6829SSascha Wildner 	test_special_atan2();
467*7f8c6829SSascha Wildner 	printf("ok 2 - atan2 special\n");
468*7f8c6829SSascha Wildner 
469*7f8c6829SSascha Wildner 	test_accuracy();
470*7f8c6829SSascha Wildner 	printf("ok 3 - accuracy\n");
471*7f8c6829SSascha Wildner 
472*7f8c6829SSascha Wildner 	test_p2x_atan2();
473*7f8c6829SSascha Wildner 	printf("ok 4 - atan2 p2x\n");
474*7f8c6829SSascha Wildner 
475*7f8c6829SSascha Wildner 	test_tiny();
476*7f8c6829SSascha Wildner 	printf("ok 5 - tiny inputs\n");
477*7f8c6829SSascha Wildner 
478*7f8c6829SSascha Wildner 	test_atan_huge();
479*7f8c6829SSascha Wildner 	printf("ok 6 - atan huge inputs\n");
480*7f8c6829SSascha Wildner 
481*7f8c6829SSascha Wildner 	test_inverse();
482*7f8c6829SSascha Wildner 	printf("ok 7 - inverse\n");
483*7f8c6829SSascha Wildner 
484*7f8c6829SSascha Wildner 	return (0);
485*7f8c6829SSascha Wildner }
486