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