16#ifndef KOKKOS_COMPLEX_HPP
17#define KOKKOS_COMPLEX_HPP
18#ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
19#define KOKKOS_IMPL_PUBLIC_INCLUDE
20#define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_COMPLEX
24#include <Kokkos_MathematicalFunctions.hpp>
25#include <Kokkos_NumericTraits.hpp>
26#include <Kokkos_ReductionIdentity.hpp>
27#include <impl/Kokkos_Error.hpp>
41template <
class RealType>
43#ifdef KOKKOS_ENABLE_COMPLEX_ALIGN
44 alignas(2 *
sizeof(RealType))
56 KOKKOS_DEFAULTED_FUNCTION
60 KOKKOS_DEFAULTED_FUNCTION
63 KOKKOS_DEFAULTED_FUNCTION
69 std::enable_if_t<std::is_convertible<RType, RealType>::value,
int> = 0>
74 : re_(other.real()), im_(other.imag()) {}
81 KOKKOS_INLINE_FUNCTION
82 complex(
const std::complex<RealType>& src)
noexcept
89 : re_(
reinterpret_cast<const RealType (&)[2]
>(src)[0]),
90 im_(
reinterpret_cast<const RealType (&)[2]
>(src)[1]) {}
98 operator std::complex<RealType>() const noexcept {
99 return std::complex<RealType>(re_, im_);
104 KOKKOS_INLINE_FUNCTION
complex(
const RealType& val) noexcept
105 : re_(val), im_(
static_cast<RealType
>(0)) {}
108 KOKKOS_INLINE_FUNCTION
109 complex(
const RealType& re,
const RealType& im) noexcept : re_(re), im_(im) {}
129 KOKKOS_INLINE_FUNCTION
130 constexpr RealType&
imag() noexcept {
return im_; }
133 KOKKOS_INLINE_FUNCTION
134 constexpr RealType&
real() noexcept {
return re_; }
137 KOKKOS_INLINE_FUNCTION
138 constexpr RealType
imag() const noexcept {
return im_; }
141 KOKKOS_INLINE_FUNCTION
142 constexpr RealType
real() const noexcept {
return re_; }
145 KOKKOS_INLINE_FUNCTION
146 constexpr void imag(RealType v)
noexcept { im_ = v; }
149 KOKKOS_INLINE_FUNCTION
150 constexpr void real(RealType v)
noexcept { re_ = v; }
152 constexpr KOKKOS_INLINE_FUNCTION
complex& operator+=(
159 constexpr KOKKOS_INLINE_FUNCTION complex& operator+=(
160 const RealType& src)
noexcept {
165 constexpr KOKKOS_INLINE_FUNCTION
complex& operator-=(
172 constexpr KOKKOS_INLINE_FUNCTION
complex& operator-=(
173 const RealType& src)
noexcept {
178 constexpr KOKKOS_INLINE_FUNCTION
complex& operator*=(
180 const RealType realPart = re_ * src.re_ - im_ * src.im_;
181 const RealType imagPart = re_ * src.im_ + im_ * src.re_;
187 constexpr KOKKOS_INLINE_FUNCTION
complex& operator*=(
188 const RealType& src)
noexcept {
195 constexpr KOKKOS_INLINE_FUNCTION
complex& operator/=(
200 const RealType s = fabs(y.real()) + fabs(y.imag());
206 if (s == RealType(0)) {
210 const complex x_scaled(this->re_ / s, this->im_ / s);
211 const complex y_conj_scaled(y.re_ / s, -(y.im_) / s);
212 const RealType y_scaled_abs =
213 y_conj_scaled.re_ * y_conj_scaled.re_ +
214 y_conj_scaled.im_ * y_conj_scaled.im_;
215 *
this = x_scaled * y_conj_scaled;
216 *
this /= y_scaled_abs;
221 constexpr KOKKOS_INLINE_FUNCTION
complex& operator/=(
222 const std::complex<RealType>& y)
noexcept(
noexcept(RealType{} /
227 const RealType s = fabs(y.real()) + fabs(y.imag());
232 if (s == RealType(0)) {
236 const complex x_scaled(this->re_ / s, this->im_ / s);
237 const complex y_conj_scaled(y.re_ / s, -(y.im_) / s);
238 const RealType y_scaled_abs =
239 y_conj_scaled.re_ * y_conj_scaled.re_ +
240 y_conj_scaled.im_ * y_conj_scaled.im_;
241 *
this = x_scaled * y_conj_scaled;
242 *
this /= y_scaled_abs;
247 constexpr KOKKOS_INLINE_FUNCTION
complex& operator/=(
248 const RealType& src)
noexcept(
noexcept(RealType{} / RealType{})) {
254#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
258 std::enable_if_t<std::is_convertible<RType, RealType>::value,
int> = 0>
259 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
264 : re_(src.re_), im_(src.im_) {}
286 template <
class Complex,
287 std::enable_if_t<std::is_same<Complex, complex>::value,
int> = 0>
288 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
void operator=(
289 const Complex& src)
volatile noexcept {
309 template <
class Complex,
310 std::enable_if_t<std::is_same<Complex, complex>::value,
int> = 0>
311 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
volatile complex& operator=(
312 const volatile Complex& src)
volatile noexcept {
331 template <
class Complex,
332 std::enable_if_t<std::is_same<Complex, complex>::value,
int> = 0>
333 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
complex& operator=(
334 const volatile Complex& src)
noexcept {
344 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
void operator=(
345 const volatile RealType& val)
noexcept {
353 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
complex& operator=(
354 const RealType& val)
volatile noexcept {
362 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
complex& operator=(
363 const volatile RealType& val)
volatile noexcept {
370 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
volatile RealType&
371 imag() volatile noexcept {
376 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
volatile RealType&
377 real() volatile noexcept {
382 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION RealType imag() const
388 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION RealType real() const
393 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
void operator+=(
399 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
void operator+=(
400 const volatile RealType& src)
volatile noexcept {
404 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
void operator*=(
406 const RealType realPart = re_ * src.re_ - im_ * src.im_;
407 const RealType imagPart = re_ * src.im_ + im_ * src.re_;
413 KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION
void operator*=(
414 const volatile RealType& src)
volatile noexcept {
429template <
class RealType1,
class RealType2>
432 using common_type = std::common_type_t<RealType1, RealType2>;
433 return common_type(x.real()) == common_type(y.real()) &&
434 common_type(x.imag()) == common_type(y.imag());
440template <
class RealType1,
class RealType2>
441inline bool operator==(std::complex<RealType1>
const& x,
443 using common_type = std::common_type_t<RealType1, RealType2>;
444 return common_type(x.real()) == common_type(y.real()) &&
445 common_type(x.imag()) == common_type(y.imag());
449template <
class RealType1,
class RealType2>
451 std::complex<RealType2>
const& y)
noexcept {
452 using common_type = std::common_type_t<RealType1, RealType2>;
453 return common_type(x.real()) == common_type(y.real()) &&
454 common_type(x.imag()) == common_type(y.imag());
459 class RealType1,
class RealType2,
461 std::enable_if_t<std::is_convertible<RealType2, RealType1>::value,
int> = 0>
463 RealType2
const& y)
noexcept {
464 using common_type = std::common_type_t<RealType1, RealType2>;
465 return common_type(x.real()) == common_type(y) &&
466 common_type(x.imag()) == common_type(0);
471 class RealType1,
class RealType2,
473 std::enable_if_t<std::is_convertible<RealType1, RealType2>::value,
int> = 0>
474KOKKOS_INLINE_FUNCTION
bool operator==(RealType1
const& x,
476 using common_type = std::common_type_t<RealType1, RealType2>;
477 return common_type(x) == common_type(y.real()) &&
478 common_type(0) == common_type(y.imag());
482template <
class RealType1,
class RealType2>
485 using common_type = std::common_type_t<RealType1, RealType2>;
486 return common_type(x.real()) != common_type(y.real()) ||
487 common_type(x.imag()) != common_type(y.imag());
491template <
class RealType1,
class RealType2>
492inline bool operator!=(std::complex<RealType1>
const& x,
494 using common_type = std::common_type_t<RealType1, RealType2>;
495 return common_type(x.real()) != common_type(y.real()) ||
496 common_type(x.imag()) != common_type(y.imag());
500template <
class RealType1,
class RealType2>
502 std::complex<RealType2>
const& y)
noexcept {
503 using common_type = std::common_type_t<RealType1, RealType2>;
504 return common_type(x.real()) != common_type(y.real()) ||
505 common_type(x.imag()) != common_type(y.imag());
510 class RealType1,
class RealType2,
512 std::enable_if_t<std::is_convertible<RealType2, RealType1>::value,
int> = 0>
514 RealType2
const& y)
noexcept {
515 using common_type = std::common_type_t<RealType1, RealType2>;
516 return common_type(x.real()) != common_type(y) ||
517 common_type(x.imag()) != common_type(0);
522 class RealType1,
class RealType2,
524 std::enable_if_t<std::is_convertible<RealType1, RealType2>::value,
int> = 0>
525KOKKOS_INLINE_FUNCTION
bool operator!=(RealType1
const& x,
527 using common_type = std::common_type_t<RealType1, RealType2>;
528 return common_type(x) != common_type(y.real()) ||
529 common_type(0) != common_type(y.imag());
536template <
class RealType1,
class RealType2>
540 x.imag() + y.imag());
544template <
class RealType1,
class RealType2>
552template <
class RealType1,
class RealType2>
560template <
class RealType>
567template <
class RealType1,
class RealType2>
571 x.imag() - y.imag());
575template <
class RealType1,
class RealType2>
583template <
class RealType1,
class RealType2>
591template <
class RealType>
598template <
class RealType1,
class RealType2>
602 x.real() * y.real() - x.imag() * y.imag(),
603 x.real() * y.imag() + x.imag() * y.real());
614template <
class RealType1,
class RealType2>
618 x.real() * y.real() - x.imag() * y.imag(),
619 x.real() * y.imag() + x.imag() * y.real());
626template <
class RealType1,
class RealType2>
637template <
class RealType1,
class RealType2>
645template <
class RealType>
650template <
class ArithmeticType>
651KOKKOS_INLINE_FUNCTION
constexpr Impl::promote_t<ArithmeticType> imag(
653 return ArithmeticType();
657template <
class RealType>
662template <
class ArithmeticType>
663KOKKOS_INLINE_FUNCTION
constexpr Impl::promote_t<ArithmeticType> real(
670KOKKOS_INLINE_FUNCTION
complex<T> polar(
const T& r,
const T& theta = T()) {
671 KOKKOS_EXPECTS(r >= 0);
672 return complex<T>(r * cos(theta), r * sin(theta));
676template <
class RealType>
678 return hypot(x.real(), x.imag());
685 T theta = atan2(x.imag(), x.real());
686 return polar(pow(r, y), y * theta);
697 return x == T() ? T() : exp(y * log(x));
700template <
class T,
class U,
701 class = std::enable_if_t<std::is_arithmetic<T>::value>>
704 using type = Impl::promote_2_t<T, U>;
708template <
class T,
class U,
709 class = std::enable_if_t<std::is_arithmetic<U>::value>>
712 using type = Impl::promote_2_t<T, U>;
716template <
class T,
class U>
719 using type = Impl::promote_2_t<T, U>;
725template <
class RealType>
726KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> sqrt(
728 RealType r = x.real();
729 RealType i = x.imag();
731 if (r == RealType()) {
732 RealType t = sqrt(fabs(i) / 2);
733 return Kokkos::complex<RealType>(t, i < RealType() ? -t : t);
735 RealType t = sqrt(2 * (abs(x) + fabs(r)));
737 return r > RealType() ? Kokkos::complex<RealType>(u, i / t)
738 : Kokkos::
complex<RealType>(fabs(i) / t,
739 i < RealType() ? -u : u);
744template <
class RealType>
750template <
class ArithmeticType>
753 using type = Impl::promote_t<ArithmeticType>;
758template <
class RealType>
764template <
class RealType>
765KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> log(
767 RealType phi = atan2(x.imag(), x.real());
768 return Kokkos::complex<RealType>(log(abs(x)), phi);
772template <
class RealType>
773KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> log10(
775 return log(x) / log(RealType(10));
779template <
class RealType>
780KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> sin(
782 return Kokkos::complex<RealType>(sin(x.real()) * cosh(x.imag()),
783 cos(x.real()) * sinh(x.imag()));
787template <
class RealType>
788KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> cos(
790 return Kokkos::complex<RealType>(cos(x.real()) * cosh(x.imag()),
791 -sin(x.real()) * sinh(x.imag()));
795template <
class RealType>
796KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> tan(
798 return sin(x) / cos(x);
802template <
class RealType>
803KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> sinh(
805 return Kokkos::complex<RealType>(sinh(x.real()) * cos(x.imag()),
806 cosh(x.real()) * sin(x.imag()));
810template <
class RealType>
811KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> cosh(
813 return Kokkos::complex<RealType>(cosh(x.real()) * cos(x.imag()),
814 sinh(x.real()) * sin(x.imag()));
818template <
class RealType>
819KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> tanh(
821 return sinh(x) / cosh(x);
825template <
class RealType>
826KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> asinh(
828 return log(x + sqrt(x * x + RealType(1.0)));
832template <
class RealType>
833KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> acosh(
835 return RealType(2.0) * log(sqrt(RealType(0.5) * (x + RealType(1.0))) +
836 sqrt(RealType(0.5) * (x - RealType(1.0))));
840template <
class RealType>
841KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> atanh(
843 const RealType i2 = x.imag() * x.imag();
844 const RealType r = RealType(1.0) - i2 - x.real() * x.real();
846 RealType p = RealType(1.0) + x.real();
847 RealType m = RealType(1.0) - x.real();
852 RealType phi = atan2(RealType(2.0) * x.imag(), r);
853 return Kokkos::complex<RealType>(RealType(0.25) * (log(p) - log(m)),
854 RealType(0.5) * phi);
858template <
class RealType>
859KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> asin(
861 Kokkos::complex<RealType> t =
862 asinh(Kokkos::complex<RealType>(-x.imag(), x.real()));
863 return Kokkos::complex<RealType>(t.
imag(), -t.
real());
867template <
class RealType>
868KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> acos(
870 Kokkos::complex<RealType> t = asin(x);
871 RealType pi_2 = acos(RealType(0.0));
872 return Kokkos::complex<RealType>(pi_2 - t.
real(), -t.
imag());
876template <
class RealType>
877KOKKOS_INLINE_FUNCTION Kokkos::complex<RealType> atan(
879 const RealType r2 = x.real() * x.real();
880 const RealType i = RealType(1.0) - r2 - x.imag() * x.imag();
882 RealType p = x.imag() + RealType(1.0);
883 RealType m = x.imag() - RealType(1.0);
888 return Kokkos::complex<RealType>(
889 RealType(0.5) * atan2(RealType(2.0) * x.real(), i),
890 RealType(0.25) * log(p / m));
896template <
class RealType>
899 std::exp(c.real()) * std::sin(c.imag()));
903template <
class RealType1,
class RealType2>
906 const RealType2& y)
noexcept(
noexcept(RealType1{} / RealType2{})) {
912template <
class RealType1,
class RealType2>
920 using common_real_type = std::common_type_t<RealType1, RealType2>;
921 const common_real_type s = fabs(real(y)) + fabs(imag(y));
931 const RealType1 y_scaled_abs =
932 real(y_conj_scaled) * real(y_conj_scaled) +
933 imag(y_conj_scaled) * imag(y_conj_scaled);
935 result /= y_scaled_abs;
941template <
class RealType1,
class RealType2>
943operator/(
const RealType1& x,
949template <
class RealType>
951 const std::complex<RealType> x_std(Kokkos::real(x), Kokkos::imag(x));
956template <
class RealType>
958 std::complex<RealType> x_std;
965struct reduction_identity<Kokkos::
complex<T>> {
966 using t_red_ident = reduction_identity<T>;
967 KOKKOS_FORCEINLINE_FUNCTION
constexpr static Kokkos::complex<T>
969 return Kokkos::complex<T>(t_red_ident::sum(), t_red_ident::sum());
971 KOKKOS_FORCEINLINE_FUNCTION
constexpr static Kokkos::complex<T>
973 return Kokkos::complex<T>(t_red_ident::prod(), t_red_ident::sum());
979#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_COMPLEX
980#undef KOKKOS_IMPL_PUBLIC_INCLUDE
981#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_COMPLEX
Partial reimplementation of std::complex that works as the result of a Kokkos::parallel_reduce.
KOKKOS_INLINE_FUNCTION constexpr RealType imag() const noexcept
The imaginary part of this complex number.
RealType value_type
The type of the real or imaginary parts of this complex number.
KOKKOS_INLINE_FUNCTION constexpr RealType & real() noexcept
The real part of this complex number.
complex & operator=(const std::complex< RealType > &src) noexcept
Assignment operator from std::complex.
KOKKOS_DEFAULTED_FUNCTION complex(const complex &) noexcept=default
Copy constructor.
KOKKOS_INLINE_FUNCTION constexpr void real(RealType v) noexcept
Set the real part of this complex number.
KOKKOS_INLINE_FUNCTION complex(const RealType &re, const RealType &im) noexcept
Constructor that takes the real and imaginary parts.
KOKKOS_INLINE_FUNCTION constexpr RealType & imag() noexcept
The imaginary part of this complex number.
KOKKOS_INLINE_FUNCTION constexpr RealType real() const noexcept
The real part of this complex number.
KOKKOS_INLINE_FUNCTION complex & operator=(const RealType &val) noexcept
Assignment operator (from a real number).
KOKKOS_INLINE_FUNCTION constexpr void imag(RealType v) noexcept
Set the imaginary part of this complex number.
KOKKOS_DEFAULTED_FUNCTION complex()=default
Default constructor (initializes both real and imaginary parts to zero).
KOKKOS_INLINE_FUNCTION complex(const RealType &val) noexcept
Constructor that takes just the real part, and sets the imaginary part to zero.
KOKKOS_INLINE_FUNCTION complex(const std::complex< RealType > &src) noexcept
Conversion constructor from std::complex.
KOKKOS_INLINE_FUNCTION complex(const complex< RType > &other) noexcept
Conversion constructor from compatible RType.