alpaka
Abstraction Library for Parallel Kernel Acceleration
Complex.hpp
Go to the documentation of this file.
1 /* Copyright 2022 Sergei Bastrakov
2  * SPDX-License-Identifier: MPL-2.0
3  */
4 
5 #pragma once
6 
7 #include "alpaka/core/Common.hpp"
9 
10 #include <cmath>
11 #include <complex>
12 #include <iostream>
13 #include <type_traits>
14 
15 namespace alpaka
16 {
17  //! Implementation of a complex number useable on host and device.
18  //!
19  //! It follows the layout of std::complex and so array-oriented access.
20  //! The class template implements all methods and operators as std::complex<T>.
21  //! Additionally, it provides an implicit conversion to and from std::complex<T>.
22  //! All methods besides operators << and >> are host-device.
23  //! It does not provide non-member functions of std::complex besides the operators.
24  //! Those are provided the same way as alpaka math functions for real numbers.
25  //!
26  //! Note that unlike most of alpaka, this is a concrete type template, and not merely a concept.
27  //!
28  //! Naming and order of the methods match https://en.cppreference.com/w/cpp/numeric/complex in C++17.
29  //! Implementation chose to not extend it e.g. by adding constexpr to some places that would get it in C++20.
30  //! The motivation is that with internal conversion to std::complex<T> for CPU backends, it would define the common
31  //! interface for genetic code anyways.
32  //! So it is more clear to have alpaka's interface exactly matching when possible, and not "improving".
33  //!
34  //! @tparam T type of the real and imaginary part: float, double, or long double.
35  template<typename T>
36  class Complex
37  {
38  public:
39  // Make sure the input type is floating-point
40  static_assert(std::is_floating_point_v<T>);
41 
42  //! Type of the real and imaginary parts
43  using value_type = T;
44 
45  //! Constructor from the given real and imaginary parts
46  constexpr ALPAKA_FN_HOST_ACC Complex(T const& real = T{}, T const& imag = T{}) : m_real(real), m_imag(imag)
47  {
48  }
49 
50  //! Copy constructor
51  constexpr Complex(Complex const& other) = default;
52 
53  //! Constructor from Complex of another type
54  template<typename U>
55  constexpr ALPAKA_FN_HOST_ACC Complex(Complex<U> const& other)
56  : m_real(static_cast<T>(other.real()))
57  , m_imag(static_cast<T>(other.imag()))
58  {
59  }
60 
61  //! Constructor from std::complex
62  constexpr ALPAKA_FN_HOST_ACC Complex(std::complex<T> const& other) : m_real(other.real()), m_imag(other.imag())
63  {
64  }
65 
66  //! Conversion to std::complex
67  constexpr ALPAKA_FN_HOST_ACC operator std::complex<T>() const
68  {
69  return std::complex<T>{m_real, m_imag};
70  }
71 
72  //! Assignment
73  Complex& operator=(Complex const&) = default;
74 
75  //! Get the real part
76  constexpr ALPAKA_FN_HOST_ACC T real() const
77  {
78  return m_real;
79  }
80 
81  //! Set the real part
82  constexpr ALPAKA_FN_HOST_ACC void real(T value)
83  {
84  m_real = value;
85  }
86 
87  //! Get the imaginary part
88  constexpr ALPAKA_FN_HOST_ACC T imag() const
89  {
90  return m_imag;
91  }
92 
93  //! Set the imaginary part
94  constexpr ALPAKA_FN_HOST_ACC void imag(T value)
95  {
96  m_imag = value;
97  }
98 
99  //! Addition assignment with a real number
101  {
102  m_real += other;
103  return *this;
104  }
105 
106  //! Addition assignment with a complex number
107  template<typename U>
109  {
110  m_real += static_cast<T>(other.real());
111  m_imag += static_cast<T>(other.imag());
112  return *this;
113  }
114 
115  //! Subtraction assignment with a real number
117  {
118  m_real -= other;
119  return *this;
120  }
121 
122  //! Subtraction assignment with a complex number
123  template<typename U>
125  {
126  m_real -= static_cast<T>(other.real());
127  m_imag -= static_cast<T>(other.imag());
128  return *this;
129  }
130 
131  //! Multiplication assignment with a real number
133  {
134  m_real *= other;
135  m_imag *= other;
136  return *this;
137  }
138 
139  //! Multiplication assignment with a complex number
140  template<typename U>
142  {
143  auto const newReal = m_real * static_cast<T>(other.real()) - m_imag * static_cast<T>(other.imag());
144  auto const newImag = m_imag * static_cast<T>(other.real()) + m_real * static_cast<T>(other.imag());
145  m_real = newReal;
146  m_imag = newImag;
147  return *this;
148  }
149 
150  //! Division assignment with a real number
152  {
153  m_real /= other;
154  m_imag /= other;
155  return *this;
156  }
157 
158  //! Division assignment with a complex number
159  template<typename U>
161  {
162  return *this *= Complex{
163  static_cast<T>(other.real() / (other.real() * other.real() + other.imag() * other.imag())),
164  static_cast<T>(-other.imag() / (other.real() * other.real() + other.imag() * other.imag()))};
165  }
166 
167  private:
168  //! Real and imaginary parts, storage enables array-oriented access
169  T m_real, m_imag;
170  };
171 
172  //! Host-device arithmetic operations matching std::complex<T>.
173  //!
174  //! They take and return alpaka::Complex.
175  //!
176  //! @{
177  //!
178 
179  //! Unary plus (added for compatibility with std::complex)
180  template<typename T>
182  {
183  return val;
184  }
185 
186  //! Unary minus
187  template<typename T>
189  {
190  return Complex<T>{-val.real(), -val.imag()};
191  }
192 
193  //! Addition of two complex numbers
194  template<typename T>
196  {
197  return Complex<T>{lhs.real() + rhs.real(), lhs.imag() + rhs.imag()};
198  }
199 
200  //! Addition of a complex and a real number
201  template<typename T>
203  {
204  return Complex<T>{lhs.real() + rhs, lhs.imag()};
205  }
206 
207  //! Addition of a real and a complex number
208  template<typename T>
210  {
211  return Complex<T>{lhs + rhs.real(), rhs.imag()};
212  }
213 
214  //! Subtraction of two complex numbers
215  template<typename T>
217  {
218  return Complex<T>{lhs.real() - rhs.real(), lhs.imag() - rhs.imag()};
219  }
220 
221  //! Subtraction of a complex and a real number
222  template<typename T>
224  {
225  return Complex<T>{lhs.real() - rhs, lhs.imag()};
226  }
227 
228  //! Subtraction of a real and a complex number
229  template<typename T>
231  {
232  return Complex<T>{lhs - rhs.real(), -rhs.imag()};
233  }
234 
235  //! Muptiplication of two complex numbers
236  template<typename T>
238  {
239  return Complex<T>{
240  lhs.real() * rhs.real() - lhs.imag() * rhs.imag(),
241  lhs.imag() * rhs.real() + lhs.real() * rhs.imag()};
242  }
243 
244  //! Muptiplication of a complex and a real number
245  template<typename T>
247  {
248  return Complex<T>{lhs.real() * rhs, lhs.imag() * rhs};
249  }
250 
251  //! Muptiplication of a real and a complex number
252  template<typename T>
254  {
255  return Complex<T>{lhs * rhs.real(), lhs * rhs.imag()};
256  }
257 
258  //! Division of two complex numbers
259  template<typename T>
261  {
262  return Complex<T>{
263  (lhs.real() * rhs.real() + lhs.imag() * rhs.imag()) / (rhs.real() * rhs.real() + rhs.imag() * rhs.imag()),
264  (lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / (rhs.real() * rhs.real() + rhs.imag() * rhs.imag())};
265  }
266 
267  //! Division of complex and a real number
268  template<typename T>
270  {
271  return Complex<T>{lhs.real() / rhs, lhs.imag() / rhs};
272  }
273 
274  //! Division of a real and a complex number
275  template<typename T>
277  {
278  return Complex<T>{
279  lhs * rhs.real() / (rhs.real() * rhs.real() + rhs.imag() * rhs.imag()),
280  -lhs * rhs.imag() / (rhs.real() * rhs.real() + rhs.imag() * rhs.imag())};
281  }
282 
283  //! Equality of two complex numbers
284  template<typename T>
285  constexpr ALPAKA_FN_HOST_ACC bool operator==(Complex<T> const& lhs, Complex<T> const& rhs)
286  {
287  return math::floatEqualExactNoWarning(lhs.real(), rhs.real())
288  && math::floatEqualExactNoWarning(lhs.imag(), rhs.imag());
289  }
290 
291  //! Equality of a complex and a real number
292  template<typename T>
293  constexpr ALPAKA_FN_HOST_ACC bool operator==(Complex<T> const& lhs, T const& rhs)
294  {
295  return math::floatEqualExactNoWarning(lhs.real(), rhs)
296  && math::floatEqualExactNoWarning(lhs.imag(), static_cast<T>(0));
297  }
298 
299  //! Equality of a real and a complex number
300  template<typename T>
301  constexpr ALPAKA_FN_HOST_ACC bool operator==(T const& lhs, Complex<T> const& rhs)
302  {
303  return math::floatEqualExactNoWarning(lhs, rhs.real())
304  && math::floatEqualExactNoWarning(static_cast<T>(0), rhs.imag());
305  }
306 
307  //! Inequality of two complex numbers.
308  //!
309  //! @note this and other versions of operator != should be removed since C++20, as so does std::complex
310  template<typename T>
311  constexpr ALPAKA_FN_HOST_ACC bool operator!=(Complex<T> const& lhs, Complex<T> const& rhs)
312  {
313  return !(lhs == rhs);
314  }
315 
316  //! Inequality of a complex and a real number
317  template<typename T>
318  constexpr ALPAKA_FN_HOST_ACC bool operator!=(Complex<T> const& lhs, T const& rhs)
319  {
320  return !math::floatEqualExactNoWarning(lhs.real(), rhs)
321  || !math::floatEqualExactNoWarning(lhs.imag(), static_cast<T>(0));
322  }
323 
324  //! Inequality of a real and a complex number
325  template<typename T>
326  constexpr ALPAKA_FN_HOST_ACC bool operator!=(T const& lhs, Complex<T> const& rhs)
327  {
328  return !math::floatEqualExactNoWarning(lhs, rhs.real())
329  || !math::floatEqualExactNoWarning(static_cast<T>(0), rhs.imag());
330  }
331 
332  //! @}
333 
334  //! Host-only output of a complex number
335  template<typename T, typename TChar, typename TTraits>
336  std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& os, Complex<T> const& x)
337  {
338  os << x.operator std::complex<T>();
339  return os;
340  }
341 
342  //! Host-only input of a complex number
343  template<typename T, typename TChar, typename TTraits>
344  std::basic_istream<TChar, TTraits>& operator>>(std::basic_istream<TChar, TTraits>& is, Complex<T> const& x)
345  {
346  std::complex<T> z;
347  is >> z;
348  x = z;
349  return is;
350  }
351 
352  //! Host-only math functions matching std::complex<T>.
353  //!
354  //! Due to issue #1688, these functions are technically marked host-device and suppress related warnings.
355  //! However, they must be called for host only.
356  //!
357  //! They take and return alpaka::Complex (or a real number when appropriate).
358  //! Internally cast, fall back to std::complex implementation and cast back.
359  //! These functions can be used directly on the host side.
360  //! They are also picked up by ADL in math traits for CPU backends.
361  //!
362  //! On the device side, alpaka math traits must be used instead.
363  //! Note that the set of the traits is currently a bit smaller.
364  //!
365  //! @{
366  //!
367 
368  //! Absolute value
370  template<typename T>
371  constexpr ALPAKA_FN_HOST_ACC T abs(Complex<T> const& x)
372  {
373  return std::abs(std::complex<T>(x));
374  }
375 
376  //! Arc cosine
378  template<typename T>
380  {
381  return std::acos(std::complex<T>(x));
382  }
383 
384  //! Arc hyperbolic cosine
386  template<typename T>
388  {
389  return std::acosh(std::complex<T>(x));
390  }
391 
392  //! Argument
394  template<typename T>
395  constexpr ALPAKA_FN_HOST_ACC T arg(Complex<T> const& x)
396  {
397  return std::arg(std::complex<T>(x));
398  }
399 
400  //! Arc sine
402  template<typename T>
404  {
405  return std::asin(std::complex<T>(x));
406  }
407 
408  //! Arc hyperbolic sine
410  template<typename T>
412  {
413  return std::asinh(std::complex<T>(x));
414  }
415 
416  //! Arc tangent
418  template<typename T>
420  {
421  return std::atan(std::complex<T>(x));
422  }
423 
424  //! Arc hyperbolic tangent
426  template<typename T>
428  {
429  return std::atanh(std::complex<T>(x));
430  }
431 
432  //! Complex conjugate
434  template<typename T>
436  {
437  return std::conj(std::complex<T>(x));
438  }
439 
440  //! Cosine
442  template<typename T>
444  {
445  return std::cos(std::complex<T>(x));
446  }
447 
448  //! Hyperbolic cosine
450  template<typename T>
452  {
453  return std::cosh(std::complex<T>(x));
454  }
455 
456  //! Exponential
458  template<typename T>
460  {
461  return std::exp(std::complex<T>(x));
462  }
463 
464  //! Natural logarithm
466  template<typename T>
468  {
469  return std::log(std::complex<T>(x));
470  }
471 
472  //! Base 10 logarithm
474  template<typename T>
476  {
477  return std::log10(std::complex<T>(x));
478  }
479 
480  //! Squared magnitude
482  template<typename T>
483  constexpr ALPAKA_FN_HOST_ACC T norm(Complex<T> const& x)
484  {
485  return std::norm(std::complex<T>(x));
486  }
487 
488  //! Get a complex number with given magnitude and phase angle
490  template<typename T>
491  constexpr ALPAKA_FN_HOST_ACC Complex<T> polar(T const& r, T const& theta = T())
492  {
493  return std::polar(r, theta);
494  }
495 
496  //! Complex power of a complex number
498  template<typename T, typename U>
499  constexpr ALPAKA_FN_HOST_ACC auto pow(Complex<T> const& x, Complex<U> const& y)
500  {
501  // Use same type promotion as std::pow
502  auto const result = std::pow(std::complex<T>(x), std::complex<U>(y));
503  using ValueType = typename decltype(result)::value_type;
504  return Complex<ValueType>(result);
505  }
506 
507  //! Real power of a complex number
509  template<typename T, typename U>
510  constexpr ALPAKA_FN_HOST_ACC auto pow(Complex<T> const& x, U const& y)
511  {
512  return pow(x, Complex<U>(y));
513  }
514 
515  //! Complex power of a real number
517  template<typename T, typename U>
518  constexpr ALPAKA_FN_HOST_ACC auto pow(T const& x, Complex<U> const& y)
519  {
520  return pow(Complex<T>(x), y);
521  }
522 
523  //! Projection onto the Riemann sphere
525  template<typename T>
527  {
528  return std::proj(std::complex<T>(x));
529  }
530 
531  //! Sine
533  template<typename T>
535  {
536  return std::sin(std::complex<T>(x));
537  }
538 
539  //! Hyperbolic sine
541  template<typename T>
543  {
544  return std::sinh(std::complex<T>(x));
545  }
546 
547  //! Square root
549  template<typename T>
551  {
552  return std::sqrt(std::complex<T>(x));
553  }
554 
555  //! Tangent
557  template<typename T>
559  {
560  return std::tan(std::complex<T>(x));
561  }
562 
563  //! Hyperbolic tangent
565  template<typename T>
567  {
568  return std::tanh(std::complex<T>(x));
569  }
570 
571  //! @}
572 
573 } // namespace alpaka
Implementation of a complex number useable on host and device.
Definition: Complex.hpp:37
T value_type
Type of the real and imaginary parts.
Definition: Complex.hpp:43
ALPAKA_FN_HOST_ACC Complex & operator-=(Complex< U > const &other)
Subtraction assignment with a complex number.
Definition: Complex.hpp:124
ALPAKA_FN_HOST_ACC Complex & operator+=(T const &other)
Addition assignment with a real number.
Definition: Complex.hpp:100
ALPAKA_FN_HOST_ACC Complex & operator*=(T const &other)
Multiplication assignment with a real number.
Definition: Complex.hpp:132
ALPAKA_FN_HOST_ACC Complex & operator-=(T const &other)
Subtraction assignment with a real number.
Definition: Complex.hpp:116
ALPAKA_FN_HOST_ACC Complex & operator*=(Complex< U > const &other)
Multiplication assignment with a complex number.
Definition: Complex.hpp:141
constexpr ALPAKA_FN_HOST_ACC void imag(T value)
Set the imaginary part.
Definition: Complex.hpp:94
constexpr ALPAKA_FN_HOST_ACC T real() const
Get the real part.
Definition: Complex.hpp:76
constexpr ALPAKA_FN_HOST_ACC void real(T value)
Set the real part.
Definition: Complex.hpp:82
constexpr ALPAKA_FN_HOST_ACC Complex(std::complex< T > const &other)
Constructor from std::complex.
Definition: Complex.hpp:62
ALPAKA_FN_HOST_ACC Complex & operator+=(Complex< U > const &other)
Addition assignment with a complex number.
Definition: Complex.hpp:108
constexpr ALPAKA_FN_HOST_ACC Complex(T const &real=T{}, T const &imag=T{})
Constructor from the given real and imaginary parts.
Definition: Complex.hpp:46
ALPAKA_FN_HOST_ACC Complex & operator/=(Complex< U > const &other)
Division assignment with a complex number.
Definition: Complex.hpp:160
constexpr Complex(Complex const &other)=default
Copy constructor.
constexpr ALPAKA_FN_HOST_ACC Complex(Complex< U > const &other)
Constructor from Complex of another type.
Definition: Complex.hpp:55
Complex & operator=(Complex const &)=default
Assignment.
ALPAKA_FN_HOST_ACC Complex & operator/=(T const &other)
Division assignment with a real number.
Definition: Complex.hpp:151
constexpr ALPAKA_FN_HOST_ACC T imag() const
Get the imaginary part.
Definition: Complex.hpp:88
#define ALPAKA_FN_HOST_ACC
Definition: Common.hpp:39
#define ALPAKA_NO_HOST_ACC_WARNING
Disable nvcc warning: 'calling a host function from host device function.' Usage: ALPAKA_NO_HOST_ACC_...
Definition: Common.hpp:82
ALPAKA_FN_INLINE ALPAKA_FN_HOST_ACC auto floatEqualExactNoWarning(T a, T b) -> bool
The alpaka accelerator library.
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > proj(Complex< T > const &x)
Projection onto the Riemann sphere.
Definition: Complex.hpp:526
ALPAKA_FN_HOST_ACC Complex< T > operator-(Complex< T > const &val)
Unary minus.
Definition: Complex.hpp:188
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > sqrt(Complex< T > const &x)
Square root.
Definition: Complex.hpp:550
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > tanh(Complex< T > const &x)
Hyperbolic tangent.
Definition: Complex.hpp:566
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > acosh(Complex< T > const &x)
Arc hyperbolic cosine.
Definition: Complex.hpp:387
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto pow(T const &x, Complex< U > const &y)
Complex power of a real number.
Definition: Complex.hpp:518
std::basic_ostream< TChar, TTraits > & operator<<(std::basic_ostream< TChar, TTraits > &os, Complex< T > const &x)
Host-only output of a complex number.
Definition: Complex.hpp:336
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > cos(Complex< T > const &x)
Cosine.
Definition: Complex.hpp:443
ALPAKA_FN_HOST_ACC Complex< T > operator/(Complex< T > const &lhs, Complex< T > const &rhs)
Division of two complex numbers.
Definition: Complex.hpp:260
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC T arg(Complex< T > const &x)
Argument.
Definition: Complex.hpp:395
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > cosh(Complex< T > const &x)
Hyperbolic cosine.
Definition: Complex.hpp:451
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > log(Complex< T > const &x)
Natural logarithm.
Definition: Complex.hpp:467
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC T norm(Complex< T > const &x)
Squared magnitude.
Definition: Complex.hpp:483
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > sin(Complex< T > const &x)
Sine.
Definition: Complex.hpp:534
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > sinh(Complex< T > const &x)
Hyperbolic sine.
Definition: Complex.hpp:542
constexpr ALPAKA_FN_HOST_ACC bool operator==(Complex< T > const &lhs, Complex< T > const &rhs)
Equality of two complex numbers.
Definition: Complex.hpp:285
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > acos(Complex< T > const &x)
Arc cosine.
Definition: Complex.hpp:379
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > atan(Complex< T > const &x)
Arc tangent.
Definition: Complex.hpp:419
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > polar(T const &r, T const &theta=T())
Get a complex number with given magnitude and phase angle.
Definition: Complex.hpp:491
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > tan(Complex< T > const &x)
Tangent.
Definition: Complex.hpp:558
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > asinh(Complex< T > const &x)
Arc hyperbolic sine.
Definition: Complex.hpp:411
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto pow(Complex< T > const &x, Complex< U > const &y)
Complex power of a complex number.
Definition: Complex.hpp:499
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > asin(Complex< T > const &x)
Arc sine.
Definition: Complex.hpp:403
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > atanh(Complex< T > const &x)
Arc hyperbolic tangent.
Definition: Complex.hpp:427
std::basic_istream< TChar, TTraits > & operator>>(std::basic_istream< TChar, TTraits > &is, Complex< T > const &x)
Host-only input of a complex number.
Definition: Complex.hpp:344
ALPAKA_FN_HOST_ACC Complex< T > operator+(Complex< T > const &val)
Host-device arithmetic operations matching std::complex<T>.
Definition: Complex.hpp:181
constexpr ALPAKA_FN_HOST_ACC bool operator!=(Complex< T > const &lhs, Complex< T > const &rhs)
Inequality of two complex numbers.
Definition: Complex.hpp:311
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > conj(Complex< T > const &x)
Complex conjugate.
Definition: Complex.hpp:435
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC T abs(Complex< T > const &x)
Host-only math functions matching std::complex<T>.
Definition: Complex.hpp:371
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > log10(Complex< T > const &x)
Base 10 logarithm.
Definition: Complex.hpp:475
constexpr ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC Complex< T > exp(Complex< T > const &x)
Exponential.
Definition: Complex.hpp:459
ALPAKA_FN_HOST_ACC Complex< T > operator*(Complex< T > const &lhs, Complex< T > const &rhs)
Muptiplication of two complex numbers.
Definition: Complex.hpp:237