xref: /dflybsd-src/tools/regression/lib/libm/test-csqrt.c (revision 7f8c68295613ce24cc71827cf210cb3d1e3bc69b)
1*7f8c6829SSascha Wildner /*-
2*7f8c6829SSascha Wildner  * Copyright (c) 2007 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-csqrt.c,v 1.2 2008/03/30 20:09:51 das Exp $
27*7f8c6829SSascha Wildner  */
28*7f8c6829SSascha Wildner 
29*7f8c6829SSascha Wildner /*
30*7f8c6829SSascha Wildner  * Tests for csqrt{,f}()
31*7f8c6829SSascha Wildner  */
32*7f8c6829SSascha Wildner 
33*7f8c6829SSascha Wildner #include <assert.h>
34*7f8c6829SSascha Wildner #include <complex.h>
35*7f8c6829SSascha Wildner #include <float.h>
36*7f8c6829SSascha Wildner #include <math.h>
37*7f8c6829SSascha Wildner #include <stdio.h>
38*7f8c6829SSascha Wildner 
39*7f8c6829SSascha Wildner #define	N(i)	(sizeof(i) / sizeof((i)[0]))
40*7f8c6829SSascha Wildner 
41*7f8c6829SSascha Wildner /*
42*7f8c6829SSascha Wildner  * This is a test hook that can point to csqrtl(), _csqrt(), or to _csqrtf().
43*7f8c6829SSascha Wildner  * The latter two convert to float or double, respectively, and test csqrtf()
44*7f8c6829SSascha Wildner  * and csqrt() with the same arguments.
45*7f8c6829SSascha Wildner  */
46*7f8c6829SSascha Wildner long double complex (*t_csqrt)(long double complex);
47*7f8c6829SSascha Wildner 
48*7f8c6829SSascha Wildner static long double complex
_csqrtf(long double complex d)49*7f8c6829SSascha Wildner _csqrtf(long double complex d)
50*7f8c6829SSascha Wildner {
51*7f8c6829SSascha Wildner 
52*7f8c6829SSascha Wildner 	return (csqrtf((float complex)d));
53*7f8c6829SSascha Wildner }
54*7f8c6829SSascha Wildner 
55*7f8c6829SSascha Wildner static long double complex
_csqrt(long double complex d)56*7f8c6829SSascha Wildner _csqrt(long double complex d)
57*7f8c6829SSascha Wildner {
58*7f8c6829SSascha Wildner 
59*7f8c6829SSascha Wildner 	return (csqrt((double complex)d));
60*7f8c6829SSascha Wildner }
61*7f8c6829SSascha Wildner 
62*7f8c6829SSascha Wildner #pragma	STDC CX_LIMITED_RANGE	off
63*7f8c6829SSascha Wildner 
64*7f8c6829SSascha Wildner /*
65*7f8c6829SSascha Wildner  * XXX gcc implements complex multiplication incorrectly. In
66*7f8c6829SSascha Wildner  * particular, it implements it as if the CX_LIMITED_RANGE pragma
67*7f8c6829SSascha Wildner  * were ON. Consequently, we need this function to form numbers
68*7f8c6829SSascha Wildner  * such as x + INFINITY * I, since gcc evalutes INFINITY * I as
69*7f8c6829SSascha Wildner  * NaN + INFINITY * I.
70*7f8c6829SSascha Wildner  */
71*7f8c6829SSascha Wildner static inline long double complex
cpackl(long double x,long double y)72*7f8c6829SSascha Wildner cpackl(long double x, long double y)
73*7f8c6829SSascha Wildner {
74*7f8c6829SSascha Wildner 	long double complex z;
75*7f8c6829SSascha Wildner 
76*7f8c6829SSascha Wildner 	__real__ z = x;
77*7f8c6829SSascha Wildner 	__imag__ z = y;
78*7f8c6829SSascha Wildner 	return (z);
79*7f8c6829SSascha Wildner }
80*7f8c6829SSascha Wildner 
81*7f8c6829SSascha Wildner /*
82*7f8c6829SSascha Wildner  * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0.
83*7f8c6829SSascha Wildner  * Fail an assertion if they differ.
84*7f8c6829SSascha Wildner  */
85*7f8c6829SSascha Wildner static void
assert_equal(long double complex d1,long double complex d2)86*7f8c6829SSascha Wildner assert_equal(long double complex d1, long double complex d2)
87*7f8c6829SSascha Wildner {
88*7f8c6829SSascha Wildner 
89*7f8c6829SSascha Wildner 	if (isnan(creall(d1))) {
90*7f8c6829SSascha Wildner 		assert(isnan(creall(d2)));
91*7f8c6829SSascha Wildner 	} else {
92*7f8c6829SSascha Wildner 		assert(creall(d1) == creall(d2));
93*7f8c6829SSascha Wildner 		assert(copysignl(1.0, creall(d1)) ==
94*7f8c6829SSascha Wildner 		       copysignl(1.0, creall(d2)));
95*7f8c6829SSascha Wildner 	}
96*7f8c6829SSascha Wildner 	if (isnan(cimagl(d1))) {
97*7f8c6829SSascha Wildner 		assert(isnan(cimagl(d2)));
98*7f8c6829SSascha Wildner 	} else {
99*7f8c6829SSascha Wildner 		assert(cimagl(d1) == cimagl(d2));
100*7f8c6829SSascha Wildner 		assert(copysignl(1.0, cimagl(d1)) ==
101*7f8c6829SSascha Wildner 		       copysignl(1.0, cimagl(d2)));
102*7f8c6829SSascha Wildner 	}
103*7f8c6829SSascha Wildner }
104*7f8c6829SSascha Wildner 
105*7f8c6829SSascha Wildner /*
106*7f8c6829SSascha Wildner  * Test csqrt for some finite arguments where the answer is exact.
107*7f8c6829SSascha Wildner  * (We do not test if it produces correctly rounded answers when the
108*7f8c6829SSascha Wildner  * result is inexact, nor do we check whether it throws spurious
109*7f8c6829SSascha Wildner  * exceptions.)
110*7f8c6829SSascha Wildner  */
111*7f8c6829SSascha Wildner static void
test_finite()112*7f8c6829SSascha Wildner test_finite()
113*7f8c6829SSascha Wildner {
114*7f8c6829SSascha Wildner 	static const double tests[] = {
115*7f8c6829SSascha Wildner 	     /* csqrt(a + bI) = x + yI */
116*7f8c6829SSascha Wildner 	     /* a	b	x	y */
117*7f8c6829SSascha Wildner 		0,	8,	2,	2,
118*7f8c6829SSascha Wildner 		0,	-8,	2,	-2,
119*7f8c6829SSascha Wildner 		4,	0,	2,	0,
120*7f8c6829SSascha Wildner 		-4,	0,	0,	2,
121*7f8c6829SSascha Wildner 		3,	4,	2,	1,
122*7f8c6829SSascha Wildner 		3,	-4,	2,	-1,
123*7f8c6829SSascha Wildner 		-3,	4,	1,	2,
124*7f8c6829SSascha Wildner 		-3,	-4,	1,	-2,
125*7f8c6829SSascha Wildner 		5,	12,	3,	2,
126*7f8c6829SSascha Wildner 		7,	24,	4,	3,
127*7f8c6829SSascha Wildner 		9,	40,	5,	4,
128*7f8c6829SSascha Wildner 		11,	60,	6,	5,
129*7f8c6829SSascha Wildner 		13,	84,	7,	6,
130*7f8c6829SSascha Wildner 		33,	56,	7,	4,
131*7f8c6829SSascha Wildner 		39,	80,	8,	5,
132*7f8c6829SSascha Wildner 		65,	72,	9,	4,
133*7f8c6829SSascha Wildner 		987,	9916,	74,	67,
134*7f8c6829SSascha Wildner 		5289,	6640,	83,	40,
135*7f8c6829SSascha Wildner 		460766389075.0, 16762287900.0, 678910, 12345
136*7f8c6829SSascha Wildner 	};
137*7f8c6829SSascha Wildner 	/*
138*7f8c6829SSascha Wildner 	 * We also test some multiples of the above arguments. This
139*7f8c6829SSascha Wildner 	 * array defines which multiples we use. Note that these have
140*7f8c6829SSascha Wildner 	 * to be small enough to not cause overflow for float precision
141*7f8c6829SSascha Wildner 	 * with all of the constants in the above table.
142*7f8c6829SSascha Wildner 	 */
143*7f8c6829SSascha Wildner 	static const double mults[] = {
144*7f8c6829SSascha Wildner 		1,
145*7f8c6829SSascha Wildner 		2,
146*7f8c6829SSascha Wildner 		3,
147*7f8c6829SSascha Wildner 		13,
148*7f8c6829SSascha Wildner 		16,
149*7f8c6829SSascha Wildner 		0x1.p30,
150*7f8c6829SSascha Wildner 		0x1.p-30,
151*7f8c6829SSascha Wildner 	};
152*7f8c6829SSascha Wildner 
153*7f8c6829SSascha Wildner 	double a, b;
154*7f8c6829SSascha Wildner 	double x, y;
155*7f8c6829SSascha Wildner 	int i, j;
156*7f8c6829SSascha Wildner 
157*7f8c6829SSascha Wildner 	for (i = 0; i < N(tests); i += 4) {
158*7f8c6829SSascha Wildner 		for (j = 0; j < N(mults); j++) {
159*7f8c6829SSascha Wildner 			a = tests[i] * mults[j] * mults[j];
160*7f8c6829SSascha Wildner 			b = tests[i + 1] * mults[j] * mults[j];
161*7f8c6829SSascha Wildner 			x = tests[i + 2] * mults[j];
162*7f8c6829SSascha Wildner 			y = tests[i + 3] * mults[j];
163*7f8c6829SSascha Wildner 			assert(t_csqrt(cpackl(a, b)) == cpackl(x, y));
164*7f8c6829SSascha Wildner 		}
165*7f8c6829SSascha Wildner 	}
166*7f8c6829SSascha Wildner 
167*7f8c6829SSascha Wildner }
168*7f8c6829SSascha Wildner 
169*7f8c6829SSascha Wildner /*
170*7f8c6829SSascha Wildner  * Test the handling of +/- 0.
171*7f8c6829SSascha Wildner  */
172*7f8c6829SSascha Wildner static void
test_zeros()173*7f8c6829SSascha Wildner test_zeros()
174*7f8c6829SSascha Wildner {
175*7f8c6829SSascha Wildner 
176*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(0.0, 0.0)), cpackl(0.0, 0.0));
177*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(-0.0, 0.0)), cpackl(0.0, 0.0));
178*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(0.0, -0.0)), cpackl(0.0, -0.0));
179*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(-0.0, -0.0)), cpackl(0.0, -0.0));
180*7f8c6829SSascha Wildner }
181*7f8c6829SSascha Wildner 
182*7f8c6829SSascha Wildner /*
183*7f8c6829SSascha Wildner  * Test the handling of infinities when the other argument is not NaN.
184*7f8c6829SSascha Wildner  */
185*7f8c6829SSascha Wildner static void
test_infinities()186*7f8c6829SSascha Wildner test_infinities()
187*7f8c6829SSascha Wildner {
188*7f8c6829SSascha Wildner 	static const double vals[] = {
189*7f8c6829SSascha Wildner 		0.0,
190*7f8c6829SSascha Wildner 		-0.0,
191*7f8c6829SSascha Wildner 		42.0,
192*7f8c6829SSascha Wildner 		-42.0,
193*7f8c6829SSascha Wildner 		INFINITY,
194*7f8c6829SSascha Wildner 		-INFINITY,
195*7f8c6829SSascha Wildner 	};
196*7f8c6829SSascha Wildner 
197*7f8c6829SSascha Wildner 	int i;
198*7f8c6829SSascha Wildner 
199*7f8c6829SSascha Wildner 	for (i = 0; i < N(vals); i++) {
200*7f8c6829SSascha Wildner 		if (isfinite(vals[i])) {
201*7f8c6829SSascha Wildner 			assert_equal(t_csqrt(cpackl(-INFINITY, vals[i])),
202*7f8c6829SSascha Wildner 			    cpackl(0.0, copysignl(INFINITY, vals[i])));
203*7f8c6829SSascha Wildner 			assert_equal(t_csqrt(cpackl(INFINITY, vals[i])),
204*7f8c6829SSascha Wildner 			    cpackl(INFINITY, copysignl(0.0, vals[i])));
205*7f8c6829SSascha Wildner 		}
206*7f8c6829SSascha Wildner 		assert_equal(t_csqrt(cpackl(vals[i], INFINITY)),
207*7f8c6829SSascha Wildner 		    cpackl(INFINITY, INFINITY));
208*7f8c6829SSascha Wildner 		assert_equal(t_csqrt(cpackl(vals[i], -INFINITY)),
209*7f8c6829SSascha Wildner 		    cpackl(INFINITY, -INFINITY));
210*7f8c6829SSascha Wildner 	}
211*7f8c6829SSascha Wildner }
212*7f8c6829SSascha Wildner 
213*7f8c6829SSascha Wildner /*
214*7f8c6829SSascha Wildner  * Test the handling of NaNs.
215*7f8c6829SSascha Wildner  */
216*7f8c6829SSascha Wildner static void
test_nans()217*7f8c6829SSascha Wildner test_nans()
218*7f8c6829SSascha Wildner {
219*7f8c6829SSascha Wildner 
220*7f8c6829SSascha Wildner 	assert(creall(t_csqrt(cpackl(INFINITY, NAN))) == INFINITY);
221*7f8c6829SSascha Wildner 	assert(isnan(cimagl(t_csqrt(cpackl(INFINITY, NAN)))));
222*7f8c6829SSascha Wildner 
223*7f8c6829SSascha Wildner 	assert(isnan(creall(t_csqrt(cpackl(-INFINITY, NAN)))));
224*7f8c6829SSascha Wildner 	assert(isinf(cimagl(t_csqrt(cpackl(-INFINITY, NAN)))));
225*7f8c6829SSascha Wildner 
226*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, INFINITY)),
227*7f8c6829SSascha Wildner 		     cpackl(INFINITY, INFINITY));
228*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, -INFINITY)),
229*7f8c6829SSascha Wildner 		     cpackl(INFINITY, -INFINITY));
230*7f8c6829SSascha Wildner 
231*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(0.0, NAN)), cpackl(NAN, NAN));
232*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(-0.0, NAN)), cpackl(NAN, NAN));
233*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(42.0, NAN)), cpackl(NAN, NAN));
234*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(-42.0, NAN)), cpackl(NAN, NAN));
235*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, 0.0)), cpackl(NAN, NAN));
236*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, -0.0)), cpackl(NAN, NAN));
237*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, 42.0)), cpackl(NAN, NAN));
238*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, -42.0)), cpackl(NAN, NAN));
239*7f8c6829SSascha Wildner 	assert_equal(t_csqrt(cpackl(NAN, NAN)), cpackl(NAN, NAN));
240*7f8c6829SSascha Wildner }
241*7f8c6829SSascha Wildner 
242*7f8c6829SSascha Wildner /*
243*7f8c6829SSascha Wildner  * Test whether csqrt(a + bi) works for inputs that are large enough to
244*7f8c6829SSascha Wildner  * cause overflow in hypot(a, b) + a. In this case we are using
245*7f8c6829SSascha Wildner  *	csqrt(115 + 252*I) == 14 + 9*I
246*7f8c6829SSascha Wildner  * scaled up to near MAX_EXP.
247*7f8c6829SSascha Wildner  */
248*7f8c6829SSascha Wildner static void
test_overflow(int maxexp)249*7f8c6829SSascha Wildner test_overflow(int maxexp)
250*7f8c6829SSascha Wildner {
251*7f8c6829SSascha Wildner 	long double a, b;
252*7f8c6829SSascha Wildner 	long double complex result;
253*7f8c6829SSascha Wildner 
254*7f8c6829SSascha Wildner 	a = ldexpl(115 * 0x1p-8, maxexp);
255*7f8c6829SSascha Wildner 	b = ldexpl(252 * 0x1p-8, maxexp);
256*7f8c6829SSascha Wildner 	result = t_csqrt(cpackl(a, b));
257*7f8c6829SSascha Wildner 	assert(creall(result) == ldexpl(14 * 0x1p-4, maxexp / 2));
258*7f8c6829SSascha Wildner 	assert(cimagl(result) == ldexpl(9 * 0x1p-4, maxexp / 2));
259*7f8c6829SSascha Wildner }
260*7f8c6829SSascha Wildner 
261*7f8c6829SSascha Wildner int
main(int argc,char * argv[])262*7f8c6829SSascha Wildner main(int argc, char *argv[])
263*7f8c6829SSascha Wildner {
264*7f8c6829SSascha Wildner 
265*7f8c6829SSascha Wildner 	printf("1..15\n");
266*7f8c6829SSascha Wildner 
267*7f8c6829SSascha Wildner 	/* Test csqrt() */
268*7f8c6829SSascha Wildner 	t_csqrt = _csqrt;
269*7f8c6829SSascha Wildner 
270*7f8c6829SSascha Wildner 	test_finite();
271*7f8c6829SSascha Wildner 	printf("ok 1 - csqrt\n");
272*7f8c6829SSascha Wildner 
273*7f8c6829SSascha Wildner 	test_zeros();
274*7f8c6829SSascha Wildner 	printf("ok 2 - csqrt\n");
275*7f8c6829SSascha Wildner 
276*7f8c6829SSascha Wildner 	test_infinities();
277*7f8c6829SSascha Wildner 	printf("ok 3 - csqrt\n");
278*7f8c6829SSascha Wildner 
279*7f8c6829SSascha Wildner 	test_nans();
280*7f8c6829SSascha Wildner 	printf("ok 4 - csqrt\n");
281*7f8c6829SSascha Wildner 
282*7f8c6829SSascha Wildner 	test_overflow(DBL_MAX_EXP);
283*7f8c6829SSascha Wildner 	printf("ok 5 - csqrt\n");
284*7f8c6829SSascha Wildner 
285*7f8c6829SSascha Wildner 	/* Now test csqrtf() */
286*7f8c6829SSascha Wildner 	t_csqrt = _csqrtf;
287*7f8c6829SSascha Wildner 
288*7f8c6829SSascha Wildner 	test_finite();
289*7f8c6829SSascha Wildner 	printf("ok 6 - csqrt\n");
290*7f8c6829SSascha Wildner 
291*7f8c6829SSascha Wildner 	test_zeros();
292*7f8c6829SSascha Wildner 	printf("ok 7 - csqrt\n");
293*7f8c6829SSascha Wildner 
294*7f8c6829SSascha Wildner 	test_infinities();
295*7f8c6829SSascha Wildner 	printf("ok 8 - csqrt\n");
296*7f8c6829SSascha Wildner 
297*7f8c6829SSascha Wildner 	test_nans();
298*7f8c6829SSascha Wildner 	printf("ok 9 - csqrt\n");
299*7f8c6829SSascha Wildner 
300*7f8c6829SSascha Wildner 	test_overflow(FLT_MAX_EXP);
301*7f8c6829SSascha Wildner 	printf("ok 10 - csqrt\n");
302*7f8c6829SSascha Wildner 
303*7f8c6829SSascha Wildner 	/* Now test csqrtl() */
304*7f8c6829SSascha Wildner 	t_csqrt = csqrtl;
305*7f8c6829SSascha Wildner 
306*7f8c6829SSascha Wildner 	test_finite();
307*7f8c6829SSascha Wildner 	printf("ok 11 - csqrt\n");
308*7f8c6829SSascha Wildner 
309*7f8c6829SSascha Wildner 	test_zeros();
310*7f8c6829SSascha Wildner 	printf("ok 12 - csqrt\n");
311*7f8c6829SSascha Wildner 
312*7f8c6829SSascha Wildner 	test_infinities();
313*7f8c6829SSascha Wildner 	printf("ok 13 - csqrt\n");
314*7f8c6829SSascha Wildner 
315*7f8c6829SSascha Wildner 	test_nans();
316*7f8c6829SSascha Wildner 	printf("ok 14 - csqrt\n");
317*7f8c6829SSascha Wildner 
318*7f8c6829SSascha Wildner 	test_overflow(LDBL_MAX_EXP);
319*7f8c6829SSascha Wildner 	printf("ok 15 - csqrt\n");
320*7f8c6829SSascha Wildner 
321*7f8c6829SSascha Wildner 	return (0);
322*7f8c6829SSascha Wildner }
323