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