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