1// TR1 complex -*- C++ -*-
2
3// Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24// <http://www.gnu.org/licenses/>.
25
26/** @file tr1/complex
27 *  This is a TR1 C++ Library header.
28 */
29
30#ifndef _GLIBCXX_TR1_COMPLEX
31#define _GLIBCXX_TR1_COMPLEX 1
32
33#pragma GCC system_header
34
35#include <complex>
36
37namespace std _GLIBCXX_VISIBILITY(default)
38{
39namespace tr1
40{
41_GLIBCXX_BEGIN_NAMESPACE_VERSION
42
43  /**
44   * @addtogroup complex_numbers
45   * @{
46   */
47
48#ifdef __GXX_EXPERIMENTAL_CXX0X__
49  using std::acos;
50  using std::asin;
51  using std::atan;
52#else
53  template<typename _Tp> std::complex<_Tp> acos(const std::complex<_Tp>&);
54  template<typename _Tp> std::complex<_Tp> asin(const std::complex<_Tp>&);
55  template<typename _Tp> std::complex<_Tp> atan(const std::complex<_Tp>&);
56#endif
57
58  template<typename _Tp> std::complex<_Tp> acosh(const std::complex<_Tp>&);
59  template<typename _Tp> std::complex<_Tp> asinh(const std::complex<_Tp>&);
60  template<typename _Tp> std::complex<_Tp> atanh(const std::complex<_Tp>&);
61
62  // The std::fabs return type in C++0x mode is different (just _Tp).
63  template<typename _Tp> std::complex<_Tp> fabs(const std::complex<_Tp>&);
64
65#ifndef __GXX_EXPERIMENTAL_CXX0X__
66  template<typename _Tp>
67    inline std::complex<_Tp>
68    __complex_acos(const std::complex<_Tp>& __z)
69    {
70      const std::complex<_Tp> __t = std::tr1::asin(__z);
71      const _Tp __pi_2 = 1.5707963267948966192313216916397514L;
72      return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag());
73    }
74
75#if _GLIBCXX_USE_C99_COMPLEX_TR1
76  inline __complex__ float
77  __complex_acos(__complex__ float __z)
78  { return __builtin_cacosf(__z); }
79
80  inline __complex__ double
81  __complex_acos(__complex__ double __z)
82  { return __builtin_cacos(__z); }
83
84  inline __complex__ long double
85  __complex_acos(const __complex__ long double& __z)
86  { return __builtin_cacosl(__z); }
87
88  template<typename _Tp>
89    inline std::complex<_Tp>
90    acos(const std::complex<_Tp>& __z)
91    { return __complex_acos(__z.__rep()); }
92#else
93  /// acos(__z) [8.1.2].
94  //  Effects:  Behaves the same as C99 function cacos, defined
95  //            in subclause 7.3.5.1.
96  template<typename _Tp>
97    inline std::complex<_Tp>
98    acos(const std::complex<_Tp>& __z)
99    { return __complex_acos(__z); }
100#endif
101
102  template<typename _Tp>
103    inline std::complex<_Tp>
104    __complex_asin(const std::complex<_Tp>& __z)
105    {
106      std::complex<_Tp> __t(-__z.imag(), __z.real());
107      __t = std::tr1::asinh(__t);
108      return std::complex<_Tp>(__t.imag(), -__t.real());
109    }
110
111#if _GLIBCXX_USE_C99_COMPLEX_TR1
112  inline __complex__ float
113  __complex_asin(__complex__ float __z)
114  { return __builtin_casinf(__z); }
115
116  inline __complex__ double
117  __complex_asin(__complex__ double __z)
118  { return __builtin_casin(__z); }
119
120  inline __complex__ long double
121  __complex_asin(const __complex__ long double& __z)
122  { return __builtin_casinl(__z); }
123
124  template<typename _Tp>
125    inline std::complex<_Tp>
126    asin(const std::complex<_Tp>& __z)
127    { return __complex_asin(__z.__rep()); }
128#else
129  /// asin(__z) [8.1.3].
130  //  Effects:  Behaves the same as C99 function casin, defined
131  //            in subclause 7.3.5.2.
132  template<typename _Tp>
133    inline std::complex<_Tp>
134    asin(const std::complex<_Tp>& __z)
135    { return __complex_asin(__z); }
136#endif
137
138  template<typename _Tp>
139    std::complex<_Tp>
140    __complex_atan(const std::complex<_Tp>& __z)
141    {
142      const _Tp __r2 = __z.real() * __z.real();
143      const _Tp __x = _Tp(1.0) - __r2 - __z.imag() * __z.imag();
144
145      _Tp __num = __z.imag() + _Tp(1.0);
146      _Tp __den = __z.imag() - _Tp(1.0);
147
148      __num = __r2 + __num * __num;
149      __den = __r2 + __den * __den;
150
151      return std::complex<_Tp>(_Tp(0.5) * atan2(_Tp(2.0) * __z.real(), __x),
152			       _Tp(0.25) * log(__num / __den));
153    }
154
155#if _GLIBCXX_USE_C99_COMPLEX_TR1
156  inline __complex__ float
157  __complex_atan(__complex__ float __z)
158  { return __builtin_catanf(__z); }
159
160  inline __complex__ double
161  __complex_atan(__complex__ double __z)
162  { return __builtin_catan(__z); }
163
164  inline __complex__ long double
165  __complex_atan(const __complex__ long double& __z)
166  { return __builtin_catanl(__z); }
167
168  template<typename _Tp>
169    inline std::complex<_Tp>
170    atan(const std::complex<_Tp>& __z)
171    { return __complex_atan(__z.__rep()); }
172#else
173  /// atan(__z) [8.1.4].
174  //  Effects:  Behaves the same as C99 function catan, defined
175  //            in subclause 7.3.5.3.
176  template<typename _Tp>
177    inline std::complex<_Tp>
178    atan(const std::complex<_Tp>& __z)
179    { return __complex_atan(__z); }
180#endif
181
182#endif // __GXX_EXPERIMENTAL_CXX0X__
183
184  template<typename _Tp>
185    std::complex<_Tp>
186    __complex_acosh(const std::complex<_Tp>& __z)
187    {
188      // Kahan's formula.
189      return _Tp(2.0) * std::log(std::sqrt(_Tp(0.5) * (__z + _Tp(1.0)))
190				 + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0))));
191    }
192
193#if _GLIBCXX_USE_C99_COMPLEX_TR1
194  inline __complex__ float
195  __complex_acosh(__complex__ float __z)
196  { return __builtin_cacoshf(__z); }
197
198  inline __complex__ double
199  __complex_acosh(__complex__ double __z)
200  { return __builtin_cacosh(__z); }
201
202  inline __complex__ long double
203  __complex_acosh(const __complex__ long double& __z)
204  { return __builtin_cacoshl(__z); }
205
206  template<typename _Tp>
207    inline std::complex<_Tp>
208    acosh(const std::complex<_Tp>& __z)
209    { return __complex_acosh(__z.__rep()); }
210#else
211  /// acosh(__z) [8.1.5].
212  //  Effects:  Behaves the same as C99 function cacosh, defined
213  //            in subclause 7.3.6.1.
214  template<typename _Tp>
215    inline std::complex<_Tp>
216    acosh(const std::complex<_Tp>& __z)
217    { return __complex_acosh(__z); }
218#endif
219
220  template<typename _Tp>
221    std::complex<_Tp>
222    __complex_asinh(const std::complex<_Tp>& __z)
223    {
224      std::complex<_Tp> __t((__z.real() - __z.imag())
225			    * (__z.real() + __z.imag()) + _Tp(1.0),
226			    _Tp(2.0) * __z.real() * __z.imag());
227      __t = std::sqrt(__t);
228
229      return std::log(__t + __z);
230    }
231
232#if _GLIBCXX_USE_C99_COMPLEX_TR1
233  inline __complex__ float
234  __complex_asinh(__complex__ float __z)
235  { return __builtin_casinhf(__z); }
236
237  inline __complex__ double
238  __complex_asinh(__complex__ double __z)
239  { return __builtin_casinh(__z); }
240
241  inline __complex__ long double
242  __complex_asinh(const __complex__ long double& __z)
243  { return __builtin_casinhl(__z); }
244
245  template<typename _Tp>
246    inline std::complex<_Tp>
247    asinh(const std::complex<_Tp>& __z)
248    { return __complex_asinh(__z.__rep()); }
249#else
250  /// asinh(__z) [8.1.6].
251  //  Effects:  Behaves the same as C99 function casin, defined
252  //            in subclause 7.3.6.2.
253  template<typename _Tp>
254    inline std::complex<_Tp>
255    asinh(const std::complex<_Tp>& __z)
256    { return __complex_asinh(__z); }
257#endif
258
259  template<typename _Tp>
260    std::complex<_Tp>
261    __complex_atanh(const std::complex<_Tp>& __z)
262    {
263      const _Tp __i2 = __z.imag() * __z.imag();
264      const _Tp __x = _Tp(1.0) - __i2 - __z.real() * __z.real();
265
266      _Tp __num = _Tp(1.0) + __z.real();
267      _Tp __den = _Tp(1.0) - __z.real();
268
269      __num = __i2 + __num * __num;
270      __den = __i2 + __den * __den;
271
272      return std::complex<_Tp>(_Tp(0.25) * (log(__num) - log(__den)),
273			       _Tp(0.5) * atan2(_Tp(2.0) * __z.imag(), __x));
274    }
275
276#if _GLIBCXX_USE_C99_COMPLEX_TR1
277  inline __complex__ float
278  __complex_atanh(__complex__ float __z)
279  { return __builtin_catanhf(__z); }
280
281  inline __complex__ double
282  __complex_atanh(__complex__ double __z)
283  { return __builtin_catanh(__z); }
284
285  inline __complex__ long double
286  __complex_atanh(const __complex__ long double& __z)
287  { return __builtin_catanhl(__z); }
288
289  template<typename _Tp>
290    inline std::complex<_Tp>
291    atanh(const std::complex<_Tp>& __z)
292    { return __complex_atanh(__z.__rep()); }
293#else
294  /// atanh(__z) [8.1.7].
295  //  Effects:  Behaves the same as C99 function catanh, defined
296  //            in subclause 7.3.6.3.
297  template<typename _Tp>
298    inline std::complex<_Tp>
299    atanh(const std::complex<_Tp>& __z)
300    { return __complex_atanh(__z); }
301#endif
302
303  template<typename _Tp>
304    inline std::complex<_Tp>
305    /// fabs(__z) [8.1.8].
306    //  Effects:  Behaves the same as C99 function cabs, defined
307    //            in subclause 7.3.8.1.
308    fabs(const std::complex<_Tp>& __z)
309    { return std::abs(__z); }
310
311  /// Additional overloads [8.1.9].
312#ifndef __GXX_EXPERIMENTAL_CXX0X__
313
314  template<typename _Tp>
315    inline typename __gnu_cxx::__promote<_Tp>::__type
316    arg(_Tp __x)
317    {
318      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
319#if (_GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC)
320      return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L)
321	                       : __type();
322#else
323      return std::arg(std::complex<__type>(__x));
324#endif
325    }
326
327  template<typename _Tp>
328    inline typename __gnu_cxx::__promote<_Tp>::__type
329    imag(_Tp)
330    { return _Tp(); }
331
332  template<typename _Tp>
333    inline typename __gnu_cxx::__promote<_Tp>::__type
334    norm(_Tp __x)
335    {
336      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
337      return __type(__x) * __type(__x);
338    }
339
340  template<typename _Tp>
341    inline typename __gnu_cxx::__promote<_Tp>::__type
342    real(_Tp __x)
343    { return __x; }
344
345#endif
346
347  template<typename _Tp, typename _Up>
348    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
349    pow(const std::complex<_Tp>& __x, const _Up& __y)
350    {
351      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
352      return std::pow(std::complex<__type>(__x), __type(__y));
353    }
354
355  template<typename _Tp, typename _Up>
356    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
357    pow(const _Tp& __x, const std::complex<_Up>& __y)
358    {
359      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
360      return std::pow(__type(__x), std::complex<__type>(__y));
361    }
362
363  template<typename _Tp, typename _Up>
364    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
365    pow(const std::complex<_Tp>& __x, const std::complex<_Up>& __y)
366    {
367      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
368      return std::pow(std::complex<__type>(__x),
369		      std::complex<__type>(__y));
370    }
371
372  using std::arg;
373
374  template<typename _Tp>
375    inline std::complex<_Tp>
376    conj(const std::complex<_Tp>& __z)
377    { return std::conj(__z); }
378
379  template<typename _Tp>
380    inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
381    conj(_Tp __x)
382    { return __x; }
383
384  using std::imag;
385  using std::norm;
386  using std::polar;
387
388  template<typename _Tp, typename _Up>
389    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
390    polar(const _Tp& __rho, const _Up& __theta)
391    {
392      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
393      return std::polar(__type(__rho), __type(__theta));
394    }
395
396  using std::real;
397
398  template<typename _Tp>
399    inline std::complex<_Tp>
400    pow(const std::complex<_Tp>& __x, const _Tp& __y)
401    { return std::pow(__x, __y); }
402
403  template<typename _Tp>
404    inline std::complex<_Tp>
405    pow(const _Tp& __x, const std::complex<_Tp>& __y)
406    { return std::pow(__x, __y); }
407
408  template<typename _Tp>
409    inline std::complex<_Tp>
410    pow(const std::complex<_Tp>& __x, const std::complex<_Tp>& __y)
411    { return std::pow(__x, __y); }
412
413// @} group complex_numbers
414
415_GLIBCXX_END_NAMESPACE_VERSION
416}
417}
418
419#endif // _GLIBCXX_TR1_COMPLEX
420