/*RTS Complex number class. This class is CUDA compatible, and can therefore be used in CUDA code and on CUDA devices. */ #ifndef RTS_COMPLEX #define RTS_COMPLEX #include "cuda_callable.h" #include #include #include #include namespace rts { template struct rtsComplex { T r, i; //default constructor CUDA_CALLABLE rtsComplex() { r = 0.0; i = 0.0; } //access methods CUDA_CALLABLE T real() { return r; } CUDA_CALLABLE T real(T r_val) { r = r_val; return r_val; } CUDA_CALLABLE T imag() { return i; } CUDA_CALLABLE T imag(T i_val) { i = i_val; return i_val; } //constructor when given real and imaginary values CUDA_CALLABLE rtsComplex(T r, T i) { this->r = r; this->i = i; } //return the current value multiplied by i CUDA_CALLABLE rtsComplex imul() { rtsComplex result; result.r = -i; result.i = r; return result; } //ARITHMETIC OPERATORS-------------------- //binary + operator (returns the result of adding two complex values) CUDA_CALLABLE rtsComplex operator+ (const rtsComplex rhs) { rtsComplex result; result.r = r + rhs.r; result.i = i + rhs.i; return result; } CUDA_CALLABLE rtsComplex operator+ (const T rhs) { rtsComplex result; result.r = r + rhs; result.i = i; return result; } //binary - operator (returns the result of adding two complex values) CUDA_CALLABLE rtsComplex operator- (const rtsComplex rhs) { rtsComplex result; result.r = r - rhs.r; result.i = i - rhs.i; return result; } //binary - operator (returns the result of adding two complex values) CUDA_CALLABLE rtsComplex operator- (const T rhs) { rtsComplex result; result.r = r - rhs; result.i = i; return result; } //binary MULTIPLICATION operators (returns the result of multiplying complex values) CUDA_CALLABLE rtsComplex operator* (const rtsComplex rhs) { rtsComplex result; result.r = r * rhs.r - i * rhs.i; result.i = r * rhs.i + i * rhs.r; return result; } CUDA_CALLABLE rtsComplex operator* (const T rhs) { return rtsComplex(r * rhs, i * rhs); } //binary DIVISION operators (returns the result of dividing complex values) CUDA_CALLABLE rtsComplex operator/ (const rtsComplex rhs) { rtsComplex result; T denom = rhs.r * rhs.r + rhs.i * rhs.i; result.r = (r * rhs.r + i * rhs.i) / denom; result.i = (- r * rhs.i + i * rhs.r) / denom; return result; } CUDA_CALLABLE rtsComplex operator/ (const T rhs) { return rtsComplex(r / rhs, i / rhs); } //ASSIGNMENT operators----------------------------------- CUDA_CALLABLE rtsComplex & operator=(const rtsComplex &rhs) { //check for self-assignment if(this != &rhs) { this->r = rhs.r; this->i = rhs.i; } return *this; } CUDA_CALLABLE rtsComplex & operator=(const T &rhs) { this->r = rhs; this->i = 0; return *this; } //arithmetic assignment operators CUDA_CALLABLE rtsComplex operator+=(const rtsComplex &rhs) { *this = *this + rhs; return *this; } CUDA_CALLABLE rtsComplex operator+=(const T &rhs) { *this = *this + rhs; return *this; } CUDA_CALLABLE rtsComplex operator*=(const rtsComplex &rhs) { *this = *this * rhs; return *this; } CUDA_CALLABLE rtsComplex operator*=(const T &rhs) { *this = *this * rhs; return *this; } //divide and assign CUDA_CALLABLE rtsComplex operator/=(const rtsComplex &rhs) { *this = *this / rhs; return *this; } CUDA_CALLABLE rtsComplex operator/=(const T &rhs) { *this = *this / rhs; return *this; } //absolute value operator (returns the absolute value of the complex number) CUDA_CALLABLE T abs() { return std::sqrt(r * r + i * i); } CUDA_CALLABLE rtsComplex log() { rtsComplex result; result.r = std::log(std::sqrt(r * r + i * i)); result.i = std::atan2(i, r); return result; } CUDA_CALLABLE rtsComplex exp() { rtsComplex result; T e_r = std::exp(r); result.r = e_r * std::cos(i); result.i = e_r * std::sin(i); return result; } /*CUDA_CALLABLE complex pow(int y) { return pow((double)y); }*/ CUDA_CALLABLE rtsComplex pow(T y) { rtsComplex result; result = log() * y; return result.exp(); } CUDA_CALLABLE rtsComplex sqrt() { rtsComplex result; //convert to polar coordinates T a = std::sqrt(r*r + i*i); T theta = std::atan2(i, r); //find the square root T a_p = std::sqrt(a); T theta_p = theta/2.0; //convert back to cartesian coordinates result.r = a_p * std::cos(theta_p); result.i = a_p * std::sin(theta_p); return result; } std::string toStr() { std::stringstream ss; ss<<"("< rhs) { if(r == rhs.r && i == rhs.i) return true; return false; } CUDA_CALLABLE bool operator==(T rhs) { if(r == rhs && i == (T)0.0) return true; return false; } /*//FRIEND functions //unary minus operator (for negating the complex number) template CUDA_CALLABLE friend complex operator-(const complex &rhs); //multiplication by T values when the complex number isn't on the left hand side template CUDA_CALLABLE friend complex operator*(const A a, const complex b); //division by T values when the complex number isn't on the left hand side template CUDA_CALLABLE friend complex operator/(const A a, const complex b); //POW function //template CUDA_CALLABLE friend complex pow(const complex x, T y); template CUDA_CALLABLE friend complex pow(const complex x, int y); //log function template CUDA_CALLABLE friend complex log(complex x); //exp function template CUDA_CALLABLE friend complex exp(complex x); //sqrt function template CUDA_CALLABLE friend complex sqrt(complex x); //trigonometric functions template CUDA_CALLABLE friend complex sin(complex x); template CUDA_CALLABLE friend complex cos(complex x);*/ }; } //end RTS namespace //addition template CUDA_CALLABLE static rts::rtsComplex operator+(const double a, const rts::rtsComplex b) { return rts::rtsComplex(a + b.r, b.i); } //subtraction with a real value template CUDA_CALLABLE static rts::rtsComplex operator-(const double a, const rts::rtsComplex b) { return rts::rtsComplex(a - b.r, -b.i); } //minus sign template CUDA_CALLABLE static rts::rtsComplex operator-(const rts::rtsComplex &rhs) { return rts::rtsComplex(-rhs.r, -rhs.i); } //multiply a T value by a complex value template CUDA_CALLABLE static rts::rtsComplex operator*(const double a, const rts::rtsComplex b) { return rts::rtsComplex(a * b.r, a * b.i); } //divide a T value by a complex value template CUDA_CALLABLE static rts::rtsComplex operator/(const double a, const rts::rtsComplex b) { //return complex(a * b.r, a * b.i); rts::rtsComplex result; T denom = b.r * b.r + b.i * b.i; result.r = (a * b.r) / denom; result.i = -(a * b.i) / denom; return result; } //POW function /*template CUDA_CALLABLE static complex pow(complex x, int y) { return x.pow(y); }*/ template CUDA_CALLABLE static rts::rtsComplex pow(rts::rtsComplex x, T y) { return x.pow(y); } //log function template CUDA_CALLABLE static rts::rtsComplex log(rts::rtsComplex x) { return x.log(); } //exp function template CUDA_CALLABLE static rts::rtsComplex exp(rts::rtsComplex x) { return x.exp(); } //sqrt function template CUDA_CALLABLE static rts::rtsComplex sqrt(rts::rtsComplex x) { return x.sqrt(); } template CUDA_CALLABLE static T abs(rts::rtsComplex a) { return a.abs(); } template CUDA_CALLABLE static T real(rts::rtsComplex a) { return a.r; } //template CUDA_CALLABLE static float real(float a) { return a; } template CUDA_CALLABLE static T imag(rts::rtsComplex a) { return a.i; } //trigonometric functions template CUDA_CALLABLE rts::rtsComplex sin(const rts::rtsComplex x) { rts::rtsComplex result; result.r = std::sin(x.r) * std::cosh(x.i); result.i = std::cos(x.r) * std::sinh(x.i); return result; } template CUDA_CALLABLE rts::rtsComplex cos(const rts::rtsComplex x) { rts::rtsComplex result; result.r = std::cos(x.r) * std::cosh(x.i); result.i = -(std::sin(x.r) * std::sinh(x.i)); return result; } template std::ostream& operator<<(std::ostream& os, rts::rtsComplex x) { os<