clang  14.0.0git
complex_cmath.h
Go to the documentation of this file.
1 //===------------------------- __complex_cmath.h --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // std::complex header copied from the libcxx source and simplified for use in
10 // OpenMP target offload regions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef _OPENMP
15 #error "This file is for OpenMP compilation only."
16 #endif
17 
18 #ifndef __cplusplus
19 #error "This file is for C++ compilation only."
20 #endif
21 
22 #ifndef _LIBCPP_COMPLEX
23 #define _LIBCPP_COMPLEX
24 
25 #include <cmath>
26 #include <type_traits>
27 
28 #define __DEVICE__ static constexpr __attribute__((nothrow))
29 
30 namespace std {
31 
32 // abs
33 
34 template <class _Tp> __DEVICE__ _Tp abs(const std::complex<_Tp> &__c) {
35  return hypot(__c.real(), __c.imag());
36 }
37 
38 // arg
39 
40 template <class _Tp> __DEVICE__ _Tp arg(const std::complex<_Tp> &__c) {
41  return atan2(__c.imag(), __c.real());
42 }
43 
44 template <class _Tp>
45 typename enable_if<is_integral<_Tp>::value || is_same<_Tp, double>::value,
46  double>::type
47 arg(_Tp __re) {
48  return atan2(0., __re);
49 }
50 
51 template <class _Tp>
52 typename enable_if<is_same<_Tp, float>::value, float>::type arg(_Tp __re) {
53  return atan2f(0.F, __re);
54 }
55 
56 // norm
57 
58 template <class _Tp> __DEVICE__ _Tp norm(const std::complex<_Tp> &__c) {
59  if (std::isinf(__c.real()))
60  return abs(__c.real());
61  if (std::isinf(__c.imag()))
62  return abs(__c.imag());
63  return __c.real() * __c.real() + __c.imag() * __c.imag();
64 }
65 
66 // conj
67 
68 template <class _Tp> std::complex<_Tp> conj(const std::complex<_Tp> &__c) {
69  return std::complex<_Tp>(__c.real(), -__c.imag());
70 }
71 
72 // proj
73 
74 template <class _Tp> std::complex<_Tp> proj(const std::complex<_Tp> &__c) {
75  std::complex<_Tp> __r = __c;
76  if (std::isinf(__c.real()) || std::isinf(__c.imag()))
77  __r = std::complex<_Tp>(INFINITY, copysign(_Tp(0), __c.imag()));
78  return __r;
79 }
80 
81 // polar
82 
83 template <class _Tp>
84 complex<_Tp> polar(const _Tp &__rho, const _Tp &__theta = _Tp()) {
85  if (std::isnan(__rho) || signbit(__rho))
86  return std::complex<_Tp>(_Tp(NAN), _Tp(NAN));
87  if (std::isnan(__theta)) {
88  if (std::isinf(__rho))
89  return std::complex<_Tp>(__rho, __theta);
90  return std::complex<_Tp>(__theta, __theta);
91  }
92  if (std::isinf(__theta)) {
93  if (std::isinf(__rho))
94  return std::complex<_Tp>(__rho, _Tp(NAN));
95  return std::complex<_Tp>(_Tp(NAN), _Tp(NAN));
96  }
97  _Tp __x = __rho * cos(__theta);
98  if (std::isnan(__x))
99  __x = 0;
100  _Tp __y = __rho * sin(__theta);
101  if (std::isnan(__y))
102  __y = 0;
103  return std::complex<_Tp>(__x, __y);
104 }
105 
106 // log
107 
108 template <class _Tp> std::complex<_Tp> log(const std::complex<_Tp> &__x) {
109  return std::complex<_Tp>(log(abs(__x)), arg(__x));
110 }
111 
112 // log10
113 
114 template <class _Tp> std::complex<_Tp> log10(const std::complex<_Tp> &__x) {
115  return log(__x) / log(_Tp(10));
116 }
117 
118 // sqrt
119 
120 template <class _Tp>
121 __DEVICE__ std::complex<_Tp> sqrt(const std::complex<_Tp> &__x) {
122  if (std::isinf(__x.imag()))
123  return std::complex<_Tp>(_Tp(INFINITY), __x.imag());
124  if (std::isinf(__x.real())) {
125  if (__x.real() > _Tp(0))
126  return std::complex<_Tp>(__x.real(), std::isnan(__x.imag())
127  ? __x.imag()
128  : copysign(_Tp(0), __x.imag()));
129  return std::complex<_Tp>(std::isnan(__x.imag()) ? __x.imag() : _Tp(0),
130  copysign(__x.real(), __x.imag()));
131  }
132  return polar(sqrt(abs(__x)), arg(__x) / _Tp(2));
133 }
134 
135 // exp
136 
137 template <class _Tp>
138 __DEVICE__ std::complex<_Tp> exp(const std::complex<_Tp> &__x) {
139  _Tp __i = __x.imag();
140  if (std::isinf(__x.real())) {
141  if (__x.real() < _Tp(0)) {
142  if (!std::isfinite(__i))
143  __i = _Tp(1);
144  } else if (__i == 0 || !std::isfinite(__i)) {
145  if (std::isinf(__i))
146  __i = _Tp(NAN);
147  return std::complex<_Tp>(__x.real(), __i);
148  }
149  } else if (std::isnan(__x.real()) && __x.imag() == 0)
150  return __x;
151  _Tp __e = exp(__x.real());
152  return std::complex<_Tp>(__e * cos(__i), __e * sin(__i));
153 }
154 
155 // pow
156 
157 template <class _Tp>
158 std::complex<_Tp> pow(const std::complex<_Tp> &__x,
159  const std::complex<_Tp> &__y) {
160  return exp(__y * log(__x));
161 }
162 
163 // __sqr, computes pow(x, 2)
164 
165 template <class _Tp> std::complex<_Tp> __sqr(const std::complex<_Tp> &__x) {
166  return std::complex<_Tp>((__x.real() - __x.imag()) *
167  (__x.real() + __x.imag()),
168  _Tp(2) * __x.real() * __x.imag());
169 }
170 
171 // asinh
172 
173 template <class _Tp>
174 __DEVICE__ std::complex<_Tp> asinh(const std::complex<_Tp> &__x) {
175  const _Tp __pi(atan2(+0., -0.));
176  if (std::isinf(__x.real())) {
177  if (std::isnan(__x.imag()))
178  return __x;
179  if (std::isinf(__x.imag()))
180  return std::complex<_Tp>(__x.real(),
181  copysign(__pi * _Tp(0.25), __x.imag()));
182  return std::complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag()));
183  }
184  if (std::isnan(__x.real())) {
185  if (std::isinf(__x.imag()))
186  return std::complex<_Tp>(__x.imag(), __x.real());
187  if (__x.imag() == 0)
188  return __x;
189  return std::complex<_Tp>(__x.real(), __x.real());
190  }
191  if (std::isinf(__x.imag()))
192  return std::complex<_Tp>(copysign(__x.imag(), __x.real()),
193  copysign(__pi / _Tp(2), __x.imag()));
194  std::complex<_Tp> __z = log(__x + sqrt(__sqr(__x) + _Tp(1)));
195  return std::complex<_Tp>(copysign(__z.real(), __x.real()),
196  copysign(__z.imag(), __x.imag()));
197 }
198 
199 // acosh
200 
201 template <class _Tp>
202 __DEVICE__ std::complex<_Tp> acosh(const std::complex<_Tp> &__x) {
203  const _Tp __pi(atan2(+0., -0.));
204  if (std::isinf(__x.real())) {
205  if (std::isnan(__x.imag()))
206  return std::complex<_Tp>(abs(__x.real()), __x.imag());
207  if (std::isinf(__x.imag())) {
208  if (__x.real() > 0)
209  return std::complex<_Tp>(__x.real(),
210  copysign(__pi * _Tp(0.25), __x.imag()));
211  else
212  return std::complex<_Tp>(-__x.real(),
213  copysign(__pi * _Tp(0.75), __x.imag()));
214  }
215  if (__x.real() < 0)
216  return std::complex<_Tp>(-__x.real(), copysign(__pi, __x.imag()));
217  return std::complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag()));
218  }
219  if (std::isnan(__x.real())) {
220  if (std::isinf(__x.imag()))
221  return std::complex<_Tp>(abs(__x.imag()), __x.real());
222  return std::complex<_Tp>(__x.real(), __x.real());
223  }
224  if (std::isinf(__x.imag()))
225  return std::complex<_Tp>(abs(__x.imag()),
226  copysign(__pi / _Tp(2), __x.imag()));
227  std::complex<_Tp> __z = log(__x + sqrt(__sqr(__x) - _Tp(1)));
228  return std::complex<_Tp>(copysign(__z.real(), _Tp(0)),
229  copysign(__z.imag(), __x.imag()));
230 }
231 
232 // atanh
233 
234 template <class _Tp>
235 __DEVICE__ std::complex<_Tp> atanh(const std::complex<_Tp> &__x) {
236  const _Tp __pi(atan2(+0., -0.));
237  if (std::isinf(__x.imag())) {
238  return std::complex<_Tp>(copysign(_Tp(0), __x.real()),
239  copysign(__pi / _Tp(2), __x.imag()));
240  }
241  if (std::isnan(__x.imag())) {
242  if (std::isinf(__x.real()) || __x.real() == 0)
243  return std::complex<_Tp>(copysign(_Tp(0), __x.real()), __x.imag());
244  return std::complex<_Tp>(__x.imag(), __x.imag());
245  }
246  if (std::isnan(__x.real())) {
247  return std::complex<_Tp>(__x.real(), __x.real());
248  }
249  if (std::isinf(__x.real())) {
250  return std::complex<_Tp>(copysign(_Tp(0), __x.real()),
251  copysign(__pi / _Tp(2), __x.imag()));
252  }
253  if (abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) {
254  return std::complex<_Tp>(copysign(_Tp(INFINITY), __x.real()),
255  copysign(_Tp(0), __x.imag()));
256  }
257  std::complex<_Tp> __z = log((_Tp(1) + __x) / (_Tp(1) - __x)) / _Tp(2);
258  return std::complex<_Tp>(copysign(__z.real(), __x.real()),
259  copysign(__z.imag(), __x.imag()));
260 }
261 
262 // sinh
263 
264 template <class _Tp>
265 __DEVICE__ std::complex<_Tp> sinh(const std::complex<_Tp> &__x) {
266  if (std::isinf(__x.real()) && !std::isfinite(__x.imag()))
267  return std::complex<_Tp>(__x.real(), _Tp(NAN));
268  if (__x.real() == 0 && !std::isfinite(__x.imag()))
269  return std::complex<_Tp>(__x.real(), _Tp(NAN));
270  if (__x.imag() == 0 && !std::isfinite(__x.real()))
271  return __x;
272  return std::complex<_Tp>(sinh(__x.real()) * cos(__x.imag()),
273  cosh(__x.real()) * sin(__x.imag()));
274 }
275 
276 // cosh
277 
278 template <class _Tp>
279 __DEVICE__ std::complex<_Tp> cosh(const std::complex<_Tp> &__x) {
280  if (std::isinf(__x.real()) && !std::isfinite(__x.imag()))
281  return std::complex<_Tp>(abs(__x.real()), _Tp(NAN));
282  if (__x.real() == 0 && !std::isfinite(__x.imag()))
283  return std::complex<_Tp>(_Tp(NAN), __x.real());
284  if (__x.real() == 0 && __x.imag() == 0)
285  return std::complex<_Tp>(_Tp(1), __x.imag());
286  if (__x.imag() == 0 && !std::isfinite(__x.real()))
287  return std::complex<_Tp>(abs(__x.real()), __x.imag());
288  return std::complex<_Tp>(cosh(__x.real()) * cos(__x.imag()),
289  sinh(__x.real()) * sin(__x.imag()));
290 }
291 
292 // tanh
293 
294 template <class _Tp>
295 __DEVICE__ std::complex<_Tp> tanh(const std::complex<_Tp> &__x) {
296  if (std::isinf(__x.real())) {
297  if (!std::isfinite(__x.imag()))
298  return std::complex<_Tp>(_Tp(1), _Tp(0));
299  return std::complex<_Tp>(_Tp(1),
300  copysign(_Tp(0), sin(_Tp(2) * __x.imag())));
301  }
302  if (std::isnan(__x.real()) && __x.imag() == 0)
303  return __x;
304  _Tp __2r(_Tp(2) * __x.real());
305  _Tp __2i(_Tp(2) * __x.imag());
306  _Tp __d(cosh(__2r) + cos(__2i));
307  _Tp __2rsh(sinh(__2r));
308  if (std::isinf(__2rsh) && std::isinf(__d))
309  return std::complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1),
310  __2i > _Tp(0) ? _Tp(0) : _Tp(-0.));
311  return std::complex<_Tp>(__2rsh / __d, sin(__2i) / __d);
312 }
313 
314 // asin
315 
316 template <class _Tp>
317 __DEVICE__ std::complex<_Tp> asin(const std::complex<_Tp> &__x) {
318  std::complex<_Tp> __z = asinh(complex<_Tp>(-__x.imag(), __x.real()));
319  return std::complex<_Tp>(__z.imag(), -__z.real());
320 }
321 
322 // acos
323 
324 template <class _Tp>
325 __DEVICE__ std::complex<_Tp> acos(const std::complex<_Tp> &__x) {
326  const _Tp __pi(atan2(+0., -0.));
327  if (std::isinf(__x.real())) {
328  if (std::isnan(__x.imag()))
329  return std::complex<_Tp>(__x.imag(), __x.real());
330  if (std::isinf(__x.imag())) {
331  if (__x.real() < _Tp(0))
332  return std::complex<_Tp>(_Tp(0.75) * __pi, -__x.imag());
333  return std::complex<_Tp>(_Tp(0.25) * __pi, -__x.imag());
334  }
335  if (__x.real() < _Tp(0))
336  return std::complex<_Tp>(__pi,
337  signbit(__x.imag()) ? -__x.real() : __x.real());
338  return std::complex<_Tp>(_Tp(0),
339  signbit(__x.imag()) ? __x.real() : -__x.real());
340  }
341  if (std::isnan(__x.real())) {
342  if (std::isinf(__x.imag()))
343  return std::complex<_Tp>(__x.real(), -__x.imag());
344  return std::complex<_Tp>(__x.real(), __x.real());
345  }
346  if (std::isinf(__x.imag()))
347  return std::complex<_Tp>(__pi / _Tp(2), -__x.imag());
348  if (__x.real() == 0 && (__x.imag() == 0 || isnan(__x.imag())))
349  return std::complex<_Tp>(__pi / _Tp(2), -__x.imag());
350  std::complex<_Tp> __z = log(__x + sqrt(__sqr(__x) - _Tp(1)));
351  if (signbit(__x.imag()))
352  return std::complex<_Tp>(abs(__z.imag()), abs(__z.real()));
353  return std::complex<_Tp>(abs(__z.imag()), -abs(__z.real()));
354 }
355 
356 // atan
357 
358 template <class _Tp>
359 __DEVICE__ std::complex<_Tp> atan(const std::complex<_Tp> &__x) {
360  std::complex<_Tp> __z = atanh(complex<_Tp>(-__x.imag(), __x.real()));
361  return std::complex<_Tp>(__z.imag(), -__z.real());
362 }
363 
364 // sin
365 
366 template <class _Tp>
367 __DEVICE__ std::complex<_Tp> sin(const std::complex<_Tp> &__x) {
368  std::complex<_Tp> __z = sinh(complex<_Tp>(-__x.imag(), __x.real()));
369  return std::complex<_Tp>(__z.imag(), -__z.real());
370 }
371 
372 // cos
373 
374 template <class _Tp> std::complex<_Tp> cos(const std::complex<_Tp> &__x) {
375  return cosh(complex<_Tp>(-__x.imag(), __x.real()));
376 }
377 
378 // tan
379 
380 template <class _Tp>
381 __DEVICE__ std::complex<_Tp> tan(const std::complex<_Tp> &__x) {
382  std::complex<_Tp> __z = tanh(complex<_Tp>(-__x.imag(), __x.real()));
383  return std::complex<_Tp>(__z.imag(), -__z.real());
384 }
385 
386 } // namespace std
387 
388 #endif
std::pow
std::complex< _Tp > pow(const std::complex< _Tp > &__x, const std::complex< _Tp > &__y)
Definition: complex_cmath.h:158
__x
static __inline unsigned char unsigned int __x
Definition: adxintrin.h:22
type
atan2f
__DEVICE__ float atan2f(float __a, float __b)
Definition: __clang_cuda_math.h:68
std::sin
__DEVICE__ std::complex< _Tp > sin(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:367
copysign
#define copysign(__x, __y)
Definition: tgmath.h:618
signbit
__DEVICE__ bool signbit(float __x)
Test for sign bit.
Definition: __clang_cuda_cmath.h:170
hypot
#define hypot(__x, __y)
Definition: tgmath.h:833
isnan
__DEVICE__ bool isnan(float __x)
Test for a NaN.
Definition: __clang_cuda_cmath.h:108
std::asin
__DEVICE__ std::complex< _Tp > asin(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:317
std::atan
__DEVICE__ std::complex< _Tp > atan(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:359
std::tan
__DEVICE__ std::complex< _Tp > tan(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:381
std::exp
__DEVICE__ std::complex< _Tp > exp(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:138
std::log
std::complex< _Tp > log(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:108
isfinite
__DEVICE__ bool isfinite(float __x)
Test for finite value.
Definition: __clang_cuda_cmath.h:103
std::tanh
__DEVICE__ std::complex< _Tp > tanh(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:295
std::polar
complex< _Tp > polar(const _Tp &__rho, const _Tp &__theta=_Tp())
Definition: complex_cmath.h:84
std::asinh
__DEVICE__ std::complex< _Tp > asinh(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:174
__y
static __inline unsigned char unsigned int unsigned int __y
Definition: adxintrin.h:22
std::sqrt
__DEVICE__ std::complex< _Tp > sqrt(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:121
std::conj
std::complex< _Tp > conj(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:68
std::atanh
__DEVICE__ std::complex< _Tp > atanh(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:235
atan2
#define atan2(__x, __y)
Definition: tgmath.h:566
isinf
__DEVICE__ bool isinf(float __x)
Test for infinity value (+ve or -ve) .
Definition: __clang_cuda_cmath.h:101
std::norm
__DEVICE__ _Tp norm(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:58
std::acos
__DEVICE__ std::complex< _Tp > acos(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:325
std::proj
std::complex< _Tp > proj(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:74
std::acosh
__DEVICE__ std::complex< _Tp > acosh(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:202
NAN
#define NAN
A constant expression of type float representing a quiet NaN.
Definition: opencl-c-base.h:226
std
Definition: Format.h:4034
std::cosh
__DEVICE__ std::complex< _Tp > cosh(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:279
std::cos
std::complex< _Tp > cos(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:374
std::arg
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:40
std::__sqr
std::complex< _Tp > __sqr(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:165
INFINITY
#define INFINITY
A constant expression of type float representing positive or unsigned infinity.
Definition: opencl-c-base.h:221
std::abs
__DEVICE__ _Tp abs(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:34
std::sinh
__DEVICE__ std::complex< _Tp > sinh(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:265
__c
static __inline__ vector float vector float vector float __c
Definition: altivec.h:4751
std::log10
std::complex< _Tp > log10(const std::complex< _Tp > &__x)
Definition: complex_cmath.h:114
__DEVICE__
#define __DEVICE__
Definition: complex_cmath.h:28