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 __catan = catan
34 * dcomplex catan(dcomplex z);
41 * Re w = - arctan(-----------) = - ATAN2(2x, 1 - x - y )
47 * Im w = - log(------------) .= --- log [ 1 + ------------- ]
49 * (x + (y-1) ) x + (y-1)
52 * = t - 2t + -- t - ..., where t = -----------------
55 * Note that: if catan( x, y) = ( u, v), then
56 * catan(-x, y) = (-u, v)
57 * catan( x,-y) = ( u,-v)
59 * Also, catan(x,y) = -i*catanh(-y,x), or
60 * catanh(x,y) = i*catan(-y,x)
61 * So, if catanh(y,x) = (v,u), then catan(x,y) = -i*(-v,u) = (u,v), i.e.,
64 * EXCEPTION CASES (conform to ISO/IEC 9899:1999(E)):
65 * catan( 0 , 0 ) = (0 , 0 )
66 * catan( NaN, 0 ) = (NaN , 0 )
67 * catan( 0 , 1 ) = (0 , +inf) with divide-by-zero
68 * catan( inf, y ) = (pi/2 , 0 ) for finite +y
69 * catan( NaN, y ) = (NaN , NaN ) with invalid for finite y != 0
70 * catan( x , inf ) = (pi/2 , 0 ) for finite +x
71 * catan( inf, inf ) = (pi/2 , 0 )
72 * catan( NaN, inf ) = (NaN , 0 )
73 * catan( x , NaN ) = (NaN , NaN ) with invalid for finite x
74 * catan( inf, NaN ) = (pi/2 , +-0 )
78 #include "libm.h" /* atan/atan2/fabs/log/log1p */
79 #include "complex_wrapper.h"
83 pi_2
= 1.570796326794896558e+00,
87 ln2
= 6.931471805599453094172321214581765680755e-0001,
94 double x
, y
, ax
, ay
, t
;
106 ix
= hx
& 0x7fffffff;
107 iy
= hy
& 0x7fffffff;
109 /* x is inf or NaN */
110 if (ix
>= 0x7ff00000) {
116 if ((iy
| ly
) == 0 || (ISINF(iy
, ly
)))
119 D_IM(ans
) = (fabs(y
) - ay
) / (fabs(y
) - ay
);
121 } else if (iy
>= 0x7ff00000) {
122 /* y is inf or NaN */
127 D_RE(ans
) = (fabs(x
) - ax
) / (fabs(x
) - ax
);
130 } else if ((ix
| lx
) == 0) {
135 * A = --- * atan2(2x, 1-x*x-y*y) = --- atan2(0,1-|y|)
138 * 1 [ (y+1)*(y+1) ] 1 2 1 2y
139 * B = - log [ ------------ ] = - log (1+ ---) or - log(1+ ----)
140 * 4 [ (y-1)*(y-1) ] 2 y-1 2 1-y
144 if (((iy
- 0x3ff00000) | ly
) == 0) {
145 /* y=1: catan(0,1)=(0,+inf) with 1/0 signal */
148 } else if (iy
>= 0x3ff00000) { /* y>1 */
149 D_IM(ans
) = half
* log1p(two
/ (-t
));
152 D_IM(ans
) = half
* log1p((ay
+ ay
) / t
);
155 } else if (iy
< 0x3e200000 || ((ix
- iy
) >> 20) >= 30) {
158 * Tiny y (relative to 1+|x|)
160 * where E=2**-29, -35, -60 for double, double extended, quad precision
163 * A = --- * atan2(2x, 1-x*x-y*y) ~ [ 1 1+x
164 * 2 [ x>=1: - atan2(2,(1-x)*(-----))
168 * B ~ t*(1-2t), where t = ----------------- is tiny
173 D_RE(ans
) = atan(ax
);
175 D_RE(ans
) = half
* atan2(two
, (one
- ax
) * (one
+
177 if ((iy
| ly
) == 0) {
181 t
= ay
/ ((ay
- one
) * (ay
- one
));
182 else if (ix
> 0x41c00000)
185 t
= ay
/ (ax
* ax
+ (ay
- one
) * (ay
- one
));
186 D_IM(ans
) = t
* (one
- (t
+ t
));
188 } else if (iy
>= 0x41c00000 && ((iy
- ix
) >> 20) >= 30) {
191 * Huge y relative to 1+|x|
192 * |y| > Einv*(1+|x|), where Einv~2**(prec/2+3),
194 * A ~ --- * atan2(2x, -y*y) ~ pi/2
197 * B ~ t*(1-2t), where t = --------------- is tiny
202 t
= (ay
/ (ay
- one
)) / (ay
- one
);
203 D_IM(ans
) = t
* (one
- (t
+ t
));
204 } else if (((iy
- 0x3ff00000) | ly
) == 0) {
209 * A = --- * atan2(2x, -x*x) = --- atan2(2,-x)
212 * 1 [x*x + 4] 1 4 [ 0.5(log2-logx) if
213 * B = - log [-------] = - log (1+ ---) = [ |x|<E, else 0.25*
214 * 4 [ x*x ] 4 x*x [ log1p((2/x)*(2/x))
217 D_RE(ans
) = half
* atan2(two
, -ax
);
219 D_IM(ans
) = half
* (ln2
- log(ax
));
222 D_IM(ans
) = 0.25 * log1p(t
* t
);
224 } else if (ix
>= 0x43900000) {
230 * A ~ --- * atan2(2x, -x*x-y*y) ~ ---
233 * B ~ t*(1-2t), where t = --------------- = (-------------- )/x
234 * x*x+(y-1)*(y-1) 1+((y-1)/x)^2
238 t
= ((ay
/ ax
) / (one
+ ((ay
- one
) / ax
) * ((ay
- one
) /
240 D_IM(ans
) = t
* (one
- (t
+ t
));
241 } else if (ix
< 0x38b00000) {
245 * when |x| < E^4, (note that y != 1)
247 * A = --- * atan2(2x, 1-x*x-y*y) ~ --- * atan2(2x,(1-y)*(1+y))
250 * 1 [(y+1)*(y+1)] 1 2 1 2y
251 * B = - log [-----------] = - log (1+ ---) or - log(1+ ----)
252 * 4 [(y-1)*(y-1)] 2 y-1 2 1-y
255 D_RE(ans
) = half
* atan2(ax
+ ax
, (one
- ay
) * (one
+ ay
));
256 if (iy
>= 0x3ff00000)
257 D_IM(ans
) = half
* log1p(two
/ (ay
- one
));
259 D_IM(ans
) = half
* log1p((ay
+ ay
) / (one
- ay
));
265 * A = --- * atan2(2x, 1-x*x-y*y)
268 * 1 [x*x+(y+1)*(y+1)] 1 4y
269 * B = - log [---------------] = - log (1+ -----------------)
270 * 4 [x*x+(y-1)*(y-1)] 4 x*x + (y-1)*(y-1)
274 if (iy
>= 0x3fe00000 && iy
< 0x40000000) {
276 D_RE(ans
) = half
* (atan2((ax
+ ax
), (t
* (one
+ ay
) -
278 } else if (ix
>= 0x3fe00000 && ix
< 0x40000000) {
280 D_RE(ans
) = half
* atan2((ax
+ ax
), ((one
- ax
) *
281 (one
+ ax
) - ay
* ay
));
283 D_RE(ans
) = half
* atan2((ax
+ ax
), ((one
- ax
* ax
) -
285 D_IM(ans
) = 0.25 * log1p((4.0 * ay
) / (ax
* ax
+ t
* t
));
288 D_RE(ans
) = -D_RE(ans
);
290 D_IM(ans
) = -D_IM(ans
);