Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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