Update copyright notices with scripts/update-copyrights
[jlayton/glibc.git] / math / s_catanl.c
1 /* Return arc tangent of complex long double value.
2    Copyright (C) 1997-2014 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <complex.h>
21 #include <math.h>
22 #include <math_private.h>
23 #include <float.h>
24
25 /* To avoid spurious overflows, use this definition to treat IBM long
26    double as approximating an IEEE-style format.  */
27 #if LDBL_MANT_DIG == 106
28 # undef LDBL_EPSILON
29 # define LDBL_EPSILON 0x1p-106L
30 #endif
31
32 __complex__ long double
33 __catanl (__complex__ long double x)
34 {
35   __complex__ long double res;
36   int rcls = fpclassify (__real__ x);
37   int icls = fpclassify (__imag__ x);
38
39   if (__builtin_expect (rcls <= FP_INFINITE || icls <= FP_INFINITE, 0))
40     {
41       if (rcls == FP_INFINITE)
42         {
43           __real__ res = __copysignl (M_PI_2l, __real__ x);
44           __imag__ res = __copysignl (0.0, __imag__ x);
45         }
46       else if (icls == FP_INFINITE)
47         {
48           if (rcls >= FP_ZERO)
49             __real__ res = __copysignl (M_PI_2l, __real__ x);
50           else
51             __real__ res = __nanl ("");
52           __imag__ res = __copysignl (0.0, __imag__ x);
53         }
54       else if (icls == FP_ZERO || icls == FP_INFINITE)
55         {
56           __real__ res = __nanl ("");
57           __imag__ res = __copysignl (0.0, __imag__ x);
58         }
59       else
60         {
61           __real__ res = __nanl ("");
62           __imag__ res = __nanl ("");
63         }
64     }
65   else if (__builtin_expect (rcls == FP_ZERO && icls == FP_ZERO, 0))
66     {
67       res = x;
68     }
69   else
70     {
71       if (fabsl (__real__ x) >= 16.0L / LDBL_EPSILON
72           || fabsl (__imag__ x) >= 16.0L / LDBL_EPSILON)
73         {
74           __real__ res = __copysignl (M_PI_2l, __real__ x);
75           if (fabsl (__real__ x) <= 1.0L)
76             __imag__ res = 1.0L / __imag__ x;
77           else if (fabsl (__imag__ x) <= 1.0L)
78             __imag__ res = __imag__ x / __real__ x / __real__ x;
79           else
80             {
81               long double h = __ieee754_hypotl (__real__ x / 2.0L,
82                                                 __imag__ x / 2.0L);
83               __imag__ res = __imag__ x / h / h / 4.0L;
84             }
85         }
86       else
87         {
88           long double den, absx, absy;
89
90           absx = fabsl (__real__ x);
91           absy = fabsl (__imag__ x);
92           if (absx < absy)
93             {
94               long double t = absx;
95               absx = absy;
96               absy = t;
97             }
98
99           if (absy < LDBL_EPSILON / 2.0L)
100             den = (1.0L - absx) * (1.0L + absx);
101           else if (absx >= 1.0L)
102             den = (1.0L - absx) * (1.0L + absx) - absy * absy;
103           else if (absx >= 0.75L || absy >= 0.5L)
104             den = -__x2y2m1l (absx, absy);
105           else
106             den = (1.0L - absx) * (1.0L + absx) - absy * absy;
107
108           __real__ res = 0.5L * __ieee754_atan2l (2.0L * __real__ x, den);
109
110           if (fabsl (__imag__ x) == 1.0L
111               && fabsl (__real__ x) < LDBL_EPSILON * LDBL_EPSILON)
112             __imag__ res = (__copysignl (0.5L, __imag__ x)
113                             * (M_LN2l - __ieee754_logl (fabsl (__real__ x))));
114           else
115             {
116               long double r2 = 0.0L, num, f;
117
118               if (fabsl (__real__ x) >= LDBL_EPSILON * LDBL_EPSILON)
119                 r2 = __real__ x * __real__ x;
120
121               num = __imag__ x + 1.0L;
122               num = r2 + num * num;
123
124               den = __imag__ x - 1.0L;
125               den = r2 + den * den;
126
127               f = num / den;
128               if (f < 0.5L)
129                 __imag__ res = 0.25L * __ieee754_logl (f);
130               else
131                 {
132                   num = 4.0L * __imag__ x;
133                   __imag__ res = 0.25L * __log1pl (num / den);
134                 }
135             }
136         }
137
138       if (fabsl (__real__ res) < LDBL_MIN)
139         {
140           volatile long double force_underflow = __real__ res * __real__ res;
141           (void) force_underflow;
142         }
143       if (fabsl (__imag__ res) < LDBL_MIN)
144         {
145           volatile long double force_underflow = __imag__ res * __imag__ res;
146           (void) force_underflow;
147         }
148     }
149
150   return res;
151 }
152 weak_alias (__catanl, catanl)