4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
30 #pragma weak __csqrt = csqrt
34 * dcomplex csqrt(dcomplex z);
37 * Let w=r+i*s = sqrt(x+iy). Then (r + i s) = r - s + i 2sr = x + i y.
39 * Hence x = r*r-s*s, y = 2sr.
41 * Note that x*x+y*y = (s*s+r*r)**2. Thus, we have
44 * (1) r + s = \/ x + y ,
51 * Perform (1)-(2) and (1)+(2), we obtain
54 * (4) 2 r = hypot(x,y)+x,
57 * (5) 2*s = hypot(x,y)-x
60 * where hypot(x,y) = \/ x + y .
62 * In order to avoid numerical cancellation, we use formula (4) for
63 * positive x, and (5) for negative x. The other component is then
64 * computed by formula (3).
70 * (assume x and y are of medium size, i.e., no over/underflow in squaring)
76 * r = ---------------------, s = -------; (6)
79 * (note that we choose sign(s) = sign(y) to force r >=0).
84 * s = ---------------------, r = -------; (7)
89 * One may use the polar coordinate of a complex number to justify the
90 * following exception cases:
92 * EXCEPTION CASES (conform to ISO/IEC 9899:1999(E)):
93 * csqrt(+-0+ i 0 ) = 0 + i 0
94 * csqrt( x + i inf ) = inf + i inf for all x (including NaN)
95 * csqrt( x + i NaN ) = NaN + i NaN with invalid for finite x
96 * csqrt(-inf+ iy ) = 0 + i inf for finite positive-signed y
97 * csqrt(+inf+ iy ) = inf + i 0 for finite positive-signed y
98 * csqrt(-inf+ i NaN) = NaN +-i inf
99 * csqrt(+inf+ i NaN) = inf + i NaN
100 * csqrt(NaN + i y ) = NaN + i NaN for finite y
101 * csqrt(NaN + i NaN) = NaN + i NaN
105 #include "libm.h" /* fabs/sqrt */
106 #include "complex_wrapper.h"
110 two300
= 2.03703597633448608627e+90,
111 twom300
= 4.90909346529772655310e-91,
112 two599
= 2.07475778444049647926e+180,
113 twom601
= 1.20495993255144205887e-181,
122 double x
, y
, t
, ax
, ay
;
123 int n
, ix
, iy
, hx
, hy
, lx
, ly
;
131 ix
= hx
& 0x7fffffff;
132 iy
= hy
& 0x7fffffff;
135 if (ix
>= 0x7ff00000 || iy
>= 0x7ff00000) {
136 /* x or y is Inf or NaN */
138 D_IM(ans
) = D_RE(ans
) = ay
;
139 else if (ISINF(ix
, lx
)) {
142 D_IM(ans
) = ay
* zero
;
144 D_RE(ans
) = ay
* zero
;
148 D_IM(ans
) = D_RE(ans
) = ax
+ ay
;
149 } else if ((iy
| ly
) == 0) { /* y = 0 */
151 D_RE(ans
) = sqrt(ax
);
154 D_IM(ans
) = sqrt(ax
);
157 } else if (ix
>= iy
) {
159 if (n
>= 30) { /* x >> y or y=0 */
161 } else if (ix
>= 0x5f300000) { /* x > 2**500 */
164 t
= two300
* sqrt(ax
+ sqrt(ax
* ax
+ y
* y
));
165 } else if (iy
< 0x20b00000) { /* y < 2**-500 */
168 t
= twom300
* sqrt(ax
+ sqrt(ax
* ax
+ y
* y
));
170 t
= sqrt(half
* (ax
+ sqrt(ax
* ax
+ ay
* ay
)));
173 D_IM(ans
) = ay
/ (t
+ t
);
176 D_RE(ans
) = ay
/ (t
+ t
);
180 if (n
>= 30) { /* y >> x */
183 else if (iy
>= 0x7fe00000)
184 t
= sqrt(half
* ay
+ half
* ax
);
185 else if (ix
<= 0x00100000)
186 t
= half
* sqrt(two
* (ay
+ ax
));
188 t
= sqrt(half
* (ay
+ ax
));
189 } else if (iy
>= 0x5f300000) { /* y > 2**500 */
192 t
= two300
* sqrt(ax
+ sqrt(ax
* ax
+ y
* y
));
193 } else if (ix
< 0x20b00000) { /* x < 2**-500 */
196 t
= twom300
* sqrt(ax
+ sqrt(ax
* ax
+ y
* y
));
198 t
= sqrt(half
* (ax
+ sqrt(ax
* ax
+ ay
* ay
)));
201 D_IM(ans
) = ay
/ (t
+ t
);
204 D_RE(ans
) = ay
/ (t
+ t
);
208 D_IM(ans
) = -D_IM(ans
);