Lines Matching full:complex
3 #include <complex>
8 #include <thrust/complex.h>
21 // c10::complex is an implementation of complex numbers that aims
24 // Most of the APIs duplicates std::complex
25 // Reference: https://en.cppreference.com/w/cpp/numeric/complex
27 // [NOTE: Complex Operator Unification]
28 // Operators currently use a mix of std::complex, thrust::complex, and
29 // c10::complex internally. The end state is that all operators will use
30 // c10::complex internally. Until then, there may be some hacks to support all
37 // https://en.cppreference.com/w/cpp/numeric/complex/complex
39 // Since C++14, all constructors are constexpr in std::complex
43 // `constexpr complex( const T& re = T(), const T& im = T() );`
48 // - std::complex defines converting constructor between float/double/long
53 // - We also define explicit casting from std::complex/thrust::complex
61 // https://en.cppreference.com/w/cpp/numeric/complex/operator%3D
68 // - In std, this is templated as complex& operator=(const T& x)
69 // with specialization `complex& operator=(T x)` for float/double/long
70 // double Since we only support float and double, on will use `complex&
83 // std::complex does not have casting operators. We define casting operators
84 // casting to std::complex and thrust::complex
89 // std::complex has custom literals `i`, `if` and `il` defined in namespace
92 // same behavior as in std::complex, instead, we define _if, _id to construct
93 // float/double complex literals.
109 // operating with another complex number. For the operating with a real number,
121 // - complex + complex
122 // - complex + real
123 // - real + complex
128 // - complex == complex
129 // - complex == real
130 // - real == complex
136 // These are implemented by casting to std::complex
140 // TODO(@zasdfgbnm): c10::complex<c10::Half> is not currently supported,
143 // - thrust::complex only support float and double
146 struct alignas(sizeof(T) * 2) complex { struct
152 constexpr complex() = default; argument
153 C10_HOST_DEVICE constexpr complex(const T& re, const T& im = T())
156 explicit constexpr complex(const std::complex<U>& other) in complex() argument
157 : complex(other.real(), other.imag()) {} in complex()
160 explicit C10_HOST_DEVICE complex(const thrust::complex<U>& other) in complex() function
163 // explicit C10_HOST_DEVICE complex(const thrust::complex<U> &other):
164 // complex(other.real(), other.imag()) {}
167 // Use SFINAE to specialize casting constructor for c10::complex<float> and
168 // c10::complex<double>
170 C10_HOST_DEVICE explicit constexpr complex( in complex() argument
171 const std::enable_if_t<std::is_same_v<U, float>, complex<double>>& other) in complex()
174 C10_HOST_DEVICE constexpr complex( in complex() argument
175 const std::enable_if_t<std::is_same_v<U, double>, complex<float>>& other) in complex()
178 constexpr complex<T>& operator=(T re) {
184 constexpr complex<T>& operator+=(T re) {
189 constexpr complex<T>& operator-=(T re) {
194 constexpr complex<T>& operator*=(T re) {
200 constexpr complex<T>& operator/=(T re) {
207 constexpr complex<T>& operator=(const complex<U>& rhs) {
214 constexpr complex<T>& operator+=(const complex<U>& rhs) {
221 constexpr complex<T>& operator-=(const complex<U>& rhs) {
228 constexpr complex<T>& operator*=(const complex<U>& rhs) {
245 constexpr FORCE_INLINE_APPLE complex<T>& operator/=(const complex<U>& rhs) argument
248 // the calculation below follows numpy's complex division
265 /* divide by zeros should yield a complex inf or nan */ argument
285 constexpr complex<T>& operator=(const std::complex<U>& rhs) { argument
293 C10_HOST_DEVICE complex<T>& operator=(const thrust::complex<U>& rhs) {
301 explicit constexpr operator std::complex<U>() const { in complex() argument
302 return std::complex<U>(std::complex<T>(real(), imag())); in complex()
307 C10_HOST_DEVICE explicit operator thrust::complex<U>() const { in complex() function
308 return static_cast<thrust::complex<U>>(thrust::complex<T>(real(), imag())); in complex()
333 constexpr complex<float> operator""_if(long double imag) { argument
334 return complex<float>(0.0f, static_cast<float>(imag));
337 constexpr complex<double> operator""_id(long double imag) {
338 return complex<double>(0.0, static_cast<double>(imag));
341 constexpr complex<float> operator""_if(unsigned long long imag) {
342 return complex<float>(0.0f, static_cast<float>(imag));
345 constexpr complex<double> operator""_id(unsigned long long imag) {
346 return complex<double>(0.0, static_cast<double>(imag));
352 constexpr complex<T> operator+(const complex<T>& val) {
357 constexpr complex<T> operator-(const complex<T>& val) {
358 return complex<T>(-val.real(), -val.imag());
362 constexpr complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs) {
363 complex<T> result = lhs;
368 constexpr complex<T> operator+(const complex<T>& lhs, const T& rhs) {
369 complex<T> result = lhs;
374 constexpr complex<T> operator+(const T& lhs, const complex<T>& rhs) {
375 return complex<T>(lhs + rhs.real(), rhs.imag());
379 constexpr complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs) {
380 complex<T> result = lhs;
385 constexpr complex<T> operator-(const complex<T>& lhs, const T& rhs) {
386 complex<T> result = lhs;
391 constexpr complex<T> operator-(const T& lhs, const complex<T>& rhs) {
392 complex<T> result = -rhs;
397 constexpr complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs) {
398 complex<T> result = lhs;
403 constexpr complex<T> operator*(const complex<T>& lhs, const T& rhs) {
404 complex<T> result = lhs;
409 constexpr complex<T> operator*(const T& lhs, const complex<T>& rhs) {
410 complex<T> result = rhs;
415 constexpr complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs) {
416 complex<T> result = lhs;
421 constexpr complex<T> operator/(const complex<T>& lhs, const T& rhs) {
422 complex<T> result = lhs;
427 constexpr complex<T> operator/(const T& lhs, const complex<T>& rhs) {
428 complex<T> result(lhs, T());
432 // Define operators between integral scalars and c10::complex. std::complex does
434 // saves a lot of "static_cast" when operate a complex and an integer. This
442 constexpr c10::complex<fT> operator+(const c10::complex<fT>& a, const iT& b) {
447 constexpr c10::complex<fT> operator+(const iT& a, const c10::complex<fT>& b) {
452 constexpr c10::complex<fT> operator-(const c10::complex<fT>& a, const iT& b) {
457 constexpr c10::complex<fT> operator-(const iT& a, const c10::complex<fT>& b) {
462 constexpr c10::complex<fT> operator*(const c10::complex<fT>& a, const iT& b) {
467 constexpr c10::complex<fT> operator*(const iT& a, const c10::complex<fT>& b) {
472 constexpr c10::complex<fT> operator/(const c10::complex<fT>& a, const iT& b) {
477 constexpr c10::complex<fT> operator/(const iT& a, const c10::complex<fT>& b) {
484 constexpr bool operator==(const complex<T>& lhs, const complex<T>& rhs) {
489 constexpr bool operator==(const complex<T>& lhs, const T& rhs) {
494 constexpr bool operator==(const T& lhs, const complex<T>& rhs) {
499 constexpr bool operator!=(const complex<T>& lhs, const complex<T>& rhs) {
504 constexpr bool operator!=(const complex<T>& lhs, const T& rhs) {
509 constexpr bool operator!=(const T& lhs, const complex<T>& rhs) {
516 const complex<T>& x) {
517 return (os << static_cast<std::complex<T>>(x));
523 complex<T>& x) {
524 std::complex<T> tmp;
539 constexpr T real(const c10::complex<T>& z) { in real()
544 constexpr T imag(const c10::complex<T>& z) { in imag()
549 C10_HOST_DEVICE T abs(const c10::complex<T>& z) { in abs()
551 return thrust::abs(static_cast<thrust::complex<T>>(z)); in abs()
553 return std::abs(static_cast<std::complex<T>>(z)); in abs()
564 C10_HOST_DEVICE T arg(const c10::complex<T>& z) { in arg()
571 constexpr T norm(const c10::complex<T>& z) { in norm()
576 // constexpr std::complex<float> conj( float z );
578 // constexpr std::complex<double> conj( DoubleOrInteger z );
579 // constexpr std::complex<long double> conj( long double z );
583 constexpr c10::complex<T> conj(const c10::complex<T>& z) { in conj()
584 return c10::complex<T>(z.real(), -z.imag()); in conj()
587 // Thrust does not have complex --> complex version of thrust::proj,
592 // returns std::complex. Use c10::polar instead;
599 C10_HOST_DEVICE complex<T> polar(const T& r, const T& theta = T()) {
601 return static_cast<complex<T>>(thrust::polar(r, theta));
605 return complex<T>(r * std::cos(theta), r * std::sin(theta));
616 // utilities for complex types