1 | /* Compute complex natural logarithm for complex __float128. |
2 | Copyright (C) 1997-2012 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 "quadmath-imp.h" |
21 | |
22 | |
23 | __complex128 |
24 | clogq (__complex128 x) |
25 | { |
26 | __complex128 result; |
27 | int rcls = fpclassifyq (__real__ x); |
28 | int icls = fpclassifyq (__imag__ x); |
29 | |
30 | if (__builtin_expect (rcls == QUADFP_ZERO && icls == QUADFP_ZERO, 0)) |
31 | { |
32 | /* Real and imaginary part are 0.0. */ |
33 | __imag__ result = signbitq (__real__ x) ? M_PIq : 0.0Q; |
34 | __imag__ result = copysignq (__imag__ result, __imag__ x); |
35 | /* Yes, the following line raises an exception. */ |
36 | __real__ result = -1.0Q / fabsq (__real__ x); |
37 | } |
38 | else if (__builtin_expect (rcls != QUADFP_NAN && icls != QUADFP_NAN, 1)) |
39 | { |
40 | /* Neither real nor imaginary part is NaN. */ |
41 | __float128 absx = fabsq (__real__ x), absy = fabsq (__imag__ x); |
42 | int scale = 0; |
43 | |
44 | if (absx < absy) |
45 | { |
46 | __float128 t = absx; |
47 | absx = absy; |
48 | absy = t; |
49 | } |
50 | |
51 | if (absx > FLT128_MAX / 2.0) |
52 | { |
53 | scale = -1; |
54 | absx = scalbnq (absx, scale); |
55 | absy = (absy >= FLT128_MIN * 2.0Q ? scalbnq (absy, scale) : 0.0Q); |
56 | } |
57 | else if (absx < FLT128_MIN && absy < FLT128_MIN) |
58 | { |
59 | scale = FLT128_MANT_DIG; |
60 | absx = scalbnq (absx, scale); |
61 | absy = scalbnq (absy, scale); |
62 | } |
63 | |
64 | if (absx == 1.0Q && scale == 0) |
65 | { |
66 | __float128 absy2 = absy * absy; |
67 | if (absy2 <= FLT128_MIN * 2.0Q) |
68 | __real__ result = absy2 / 2.0Q - absy2 * absy2 / 4.0Q; |
69 | else |
70 | __real__ result = log1pq (absy2) / 2.0Q; |
71 | } |
72 | else if (absx > 1.0Q && absx < 2.0Q && absy < 1.0Q && scale == 0) |
73 | { |
74 | __float128 d2m1 = (absx - 1.0Q) * (absx + 1.0Q); |
75 | if (absy >= FLT128_EPSILON) |
76 | d2m1 += absy * absy; |
77 | __real__ result = log1pq (d2m1) / 2.0Q; |
78 | } |
79 | else if (absx < 1.0Q |
80 | && absx >= 0.75Q |
81 | && absy < FLT128_EPSILON / 2.0Q |
82 | && scale == 0) |
83 | { |
84 | __float128 d2m1 = (absx - 1.0Q) * (absx + 1.0Q); |
85 | __real__ result = log1pq (d2m1) / 2.0Q; |
86 | } |
87 | else if (absx < 1.0 && (absx >= 0.75Q || absy >= 0.5Q) && scale == 0) |
88 | { |
89 | __float128 d2m1 = __quadmath_x2y2m1q (absx, absy); |
90 | __real__ result = log1pq (d2m1) / 2.0Q; |
91 | } |
92 | else |
93 | { |
94 | __float128 d = hypotq (absx, absy); |
95 | __real__ result = logq (d) - scale * M_LN2q; |
96 | } |
97 | |
98 | __imag__ result = atan2q (__imag__ x, __real__ x); |
99 | } |
100 | else |
101 | { |
102 | __imag__ result = nanq ("" ); |
103 | if (rcls == QUADFP_INFINITE || icls == QUADFP_INFINITE) |
104 | /* Real or imaginary part is infinite. */ |
105 | __real__ result = HUGE_VALQ; |
106 | else |
107 | __real__ result = nanq ("" ); |
108 | } |
109 | |
110 | return result; |
111 | } |
112 | |