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