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 __catanl = catanl
34 * ldcomplex catanl(ldcomplex z);
36 * Atan(z) return A + Bi where,
38 * A = --- * atan2(2x, 1-x*x-y*y)
41 * 1 [ x*x + (y+1)*(y+1) ] 1 4y
42 * B = --- log [ ----------------- ] = - log (1+ -----------------)
43 * 4 [ x*x + (y-1)*(y-1) ] 4 x*x + (y-1)*(y-1)
46 * = t - 2t + -- t - ..., where t = -----------------
49 * Let w = atan(z=x+yi) = A + B i. Then tan(w) = z.
50 * Since sin(w) = (exp(iw)-exp(-iw))/(2i), cos(w)=(exp(iw)+exp(-iw))/(2),
51 * Let p = exp(iw), then z = tan(w) = ((p-1/p)/(p+1/p))/i, or
52 * iz = (p*p-1)/(p*p+1), or, after simplification,
53 * p*p = (1+iz)/(1-iz) ... (1)
54 * LHS of (1) = exp(2iw) = exp(2i(A+Bi)) = exp(-2B)*exp(2iA)
55 * = exp(-2B)*(cos(2A)+i*sin(2A)) ... (2)
56 * 1-y+ix (1-y+ix)*(1+y+ix) 1-x*x-y*y + 2xi
57 * RHS of (1) = ------ = ----------------- = --------------- ... (3)
58 * 1+y-ix (1+y)**2 + x**2 (1+y)**2 + x**2
60 * Comparing the real and imaginary parts of (2) and (3), we have:
61 * cos(2A) : 1-x*x-y*y = sin(2A) : 2x
63 * tan(2A) = 2x/(1-x*x-y*y), or
64 * A = 0.5 * atan2(2x, 1-x*x-y*y) ... (4)
66 * For the imaginary part B, Note that |p*p| = exp(-2B), and
67 * |1+iz| |i-z| hypot(x,(y-1))
68 * |----| = |---| = --------------
69 * |1-iz| |i+z| hypot(x,(y+1))
72 * exp(4B) = -----------------, or
75 * 1 [x^2+(y+1)^2] 1 4y
76 * B = - log [-----------] = - log(1+ -------------) ... (5)
77 * 4 [x^2+(y-1)^2] 4 x^2+(y-1)^2
81 * Note that: if catan( x, y) = ( u, v), then
82 * catan(-x, y) = (-u, v)
83 * catan( x,-y) = ( u,-v)
85 * Also, catan(x,y) = -i*catanh(-y,x), or
86 * catanh(x,y) = i*catan(-y,x)
87 * So, if catanh(y,x) = (v,u), then catan(x,y) = -i*(-v,u) = (u,v), i.e.,
90 * EXCEPTION CASES (conform to ISO/IEC 9899:1999(E)):
91 * catan( 0 , 0 ) = (0 , 0 )
92 * catan( NaN, 0 ) = (NaN , 0 )
93 * catan( 0 , 1 ) = (0 , +inf) with divide-by-zero
94 * catan( inf, y ) = (pi/2 , 0 ) for finite +y
95 * catan( NaN, y ) = (NaN , NaN ) with invalid for finite y != 0
96 * catan( x , inf ) = (pi/2 , 0 ) for finite +x
97 * catan( inf, inf ) = (pi/2 , 0 )
98 * catan( NaN, inf ) = (NaN , 0 )
99 * catan( x , NaN ) = (NaN , NaN ) with invalid for finite x
100 * catan( inf, NaN ) = (pi/2 , +-0 )
104 #include "libm.h" /* atan2l/atanl/fabsl/isinfl/iszerol/log1pl/logl */
105 #include "complex_wrapper.h"
106 #include "longdouble.h"
109 static const long double
114 ln2
= 6.931471805599453094172321214581765680755e-0001L,
115 pi_2
= 1.570796326794896619231321691639751442098584699687552910487472L,
117 E
= 2.910383045673370361328125000000000000000e-11L, /* 2**-35 */
118 Einv
= 3.435973836800000000000000000000000000000e+10L; /* 2**+35 */
120 E
= 8.673617379884035472059622406959533691406e-19L, /* 2**-60 */
121 Einv
= 1.152921504606846976000000000000000000000e18L
; /* 2**+60 */
126 catanl(ldcomplex z
) {
128 long double x
, y
, t1
, ax
, ay
, t
;
137 ix
= hx
& 0x7fffffff;
138 iy
= hy
& 0x7fffffff;
140 /* x is inf or NaN */
141 if (ix
>= 0x7fff0000) {
147 if (iszerol(y
) || (isinfl(y
)))
150 LD_IM(ans
) = (fabsl(y
) - ay
) / (fabsl(y
) - ay
);
152 } else if (iy
>= 0x7fff0000) {
153 /* y is inf or NaN */
158 LD_RE(ans
) = (fabsl(x
) - ax
) / (fabsl(x
) - ax
);
161 } else if (iszerol(x
)) {
166 * A = --- * atan2(2x, 1-x*x-y*y) = --- atan2(0,1-|y|)
169 * 1 [ (y+1)*(y+1) ] 1 2 1 2y
170 * B = - log [ ----------- ] = - log (1+ ---) or - log(1+ ----)
171 * 4 [ (y-1)*(y-1) ] 2 y-1 2 1-y
176 /* y=1: catan(0,1)=(0,+inf) with 1/0 signal */
177 LD_IM(ans
) = ay
/ ax
;
179 } else if (ay
> one
) { /* y>1 */
180 LD_IM(ans
) = half
* log1pl(two
/ (-t
));
183 LD_IM(ans
) = half
* log1pl((ay
+ ay
) / t
);
186 } else if (ay
< E
* (one
+ ax
)) {
189 * Tiny y (relative to 1+|x|)
191 * where E=2**-29, -35, -60 for double, extended, quad precision
194 * A = - * atan2(2x,1-x*x-y*y) ~ [ 1 1+x
195 * 2 [x>=1: - atan2(2,(1-x)*(-----))
199 * B ~ t*(1-2t), where t = ----------------- is tiny
203 * (when x < 2**-60, t = ----------- )
213 else if (ix
> 0x403b0000)
216 t
= ay
/ (ax
* ax
+ t1
* t1
);
217 LD_IM(ans
) = t
* (one
- two
* t
);
220 LD_RE(ans
) = atanl(ax
);
222 LD_RE(ans
) = half
* atan2l(two
, (one
- ax
) * (one
+
225 } else if (ay
> Einv
* (one
+ ax
)) {
228 * Huge y relative to 1+|x|
229 * |y| > Einv*(1+|x|), where Einv~2**(prec/2+3),
231 * A ~ --- * atan2(2x, -y*y) ~ pi/2
234 * B ~ t*(1-2t), where t = --------------- is tiny
239 t
= (ay
/ (ay
- one
)) / (ay
- one
);
240 LD_IM(ans
) = t
* (one
- (t
+ t
));
241 } else if (ay
== one
) {
246 * A = - * atan2(2x, -x*x) = --- atan2(2,-x)
249 * 1 [ x*x+4] 1 4 [ 0.5(log2-logx) if
250 * B = - log [ -----] = - log (1+ ---) = [ |x|<E, else 0.25*
251 * 4 [ x*x ] 4 x*x [ log1p((2/x)*(2/x))
254 LD_RE(ans
) = half
* atan2l(two
, -ax
);
256 LD_IM(ans
) = half
* (ln2
- logl(ax
));
259 LD_IM(ans
) = 0.25L * log1pl(t
* t
);
261 } else if (ax
> Einv
* Einv
) {
267 * A ~ --- * atan2(2x, -x*x-y*y) ~ ---
270 * B ~ t*(1-2t), where t = --------------- = (-------------- )/x
271 * x*x+(y-1)*(y-1) 1+((y-1)/x)^2
275 t
= ((ay
/ ax
) / (one
+ ((ay
- one
) / ax
) * ((ay
- one
) /
277 LD_IM(ans
) = t
* (one
- (t
+ t
));
278 } else if (ax
< E
* E
* E
* E
) {
282 * when |x| < E^4, (note that y != 1)
284 * A = --- * atan2(2x, 1-x*x-y*y) ~ --- * atan2(2x,1-y*y)
287 * 1 [ (y+1)*(y+1) ] 1 2 1 2y
288 * B = - log [ ----------- ] = - log (1+ ---) or - log(1+ ----)
289 * 4 [ (y-1)*(y-1) ] 2 y-1 2 1-y
292 LD_RE(ans
) = half
* atan2l(ax
+ ax
, (one
- ay
) * (one
+ ay
));
293 if (ay
> one
) /* y>1 */
294 LD_IM(ans
) = half
* log1pl(two
/ (ay
- one
));
296 LD_IM(ans
) = half
* log1pl((ay
+ ay
) / (one
- ay
));
302 * A = --- * atan2(2x, 1-x*x-y*y)
305 * 1 [ x*x+(y+1)*(y+1) ] 1 4y
306 * B = - log [ --------------- ] = - log (1+ -----------------)
307 * 4 [ x*x+(y-1)*(y-1) ] 4 x*x + (y-1)*(y-1)
311 if (iy
>= 0x3ffe0000 && iy
< 0x40000000) {
313 LD_RE(ans
) = half
* (atan2l((ax
+ ax
), (t
* (one
+
315 } else if (ix
>= 0x3ffe0000 && ix
< 0x40000000) {
317 LD_RE(ans
) = half
* atan2l((ax
+ ax
), ((one
- ax
) *
318 (one
+ ax
) - ay
* ay
));
320 LD_RE(ans
) = half
* atan2l((ax
+ ax
), ((one
- ax
*
322 LD_IM(ans
) = 0.25L * log1pl((4.0L * ay
) / (ax
* ax
+ t
* t
));
325 LD_RE(ans
) = -LD_RE(ans
);
327 LD_IM(ans
) = -LD_IM(ans
);