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