/******************************************************************************** * * * D o u b l e - P r e c i s i o n C o m p l e x N u m b e r * * * ********************************************************************************* * Copyright (C) 2006,2024 by Jeroen van der Zijp. All Rights Reserved. * ********************************************************************************* * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see * ********************************************************************************/ #ifndef FXCOMPLEXD_H #define FXCOMPLEXD_H namespace FX { /// Double-precision complex class FXAPI FXComplexd { public: FXdouble re; FXdouble im; public: /// Default constructor; value is not initialized FXComplexd(){ } /// Construct from real FXComplexd(FXdouble r):re(r),im(0.0){ } /// Construct from components FXComplexd(FXdouble r,FXdouble i):re(r),im(i){ } /// Initialize from another complex FXComplexd(const FXComplexd& c):re(c.re),im(c.im){ } /// Set value from real FXComplexd& set(FXdouble r){ re=r; im=0.0; return *this; } /// Set value from components FXComplexd& set(FXdouble r,FXdouble i){ re=r; im=i; return *this;} /// Set value from another complex FXComplexd& set(const FXComplexd& c){ re=c.re; im=c.im; return *this;} /// Test if zero FXbool operator!() const { return (re==0.0) && (im==0.0); } /// Access real part FXdouble& real(){ return re; } const FXdouble& real() const { return re; } /// Access imaginary part FXdouble& imag(){ return im; } const FXdouble& imag() const { return im; } /// Squared modulus FXdouble modulus2() const { return re*re+im*im; } /// Modulus or absolute value of complex FXdouble modulus() const { return Math::sqrt(modulus2()); } /// Argument of complex FXdouble argument() const { return Math::atan2(im,re); } /// Return a non-const reference to the ith element FXdouble& operator[](FXint i){ return (&re)[i]; } /// Return a const reference to the ith element const FXdouble& operator[](FXint i) const { return (&re)[i]; } /// Unary FXComplexd operator+() const { return *this; } FXComplexd operator-() const { return FXComplexd(-re,-im); } /// Assignment from real FXComplexd& operator=(const FXdouble r){ return set(r); } /// Assignment from another complex FXComplexd& operator=(const FXComplexd& c){ return set(c); } /// Assigning operators with real FXComplexd& operator+=(FXdouble r){ re+=r; return *this; } FXComplexd& operator-=(FXdouble r){ re-=r; return *this; } FXComplexd& operator*=(FXdouble r){ re*=r; im*=r; return *this; } FXComplexd& operator/=(FXdouble r){ re/=r; im/=r; return *this; } /// Assigning operators with another complex FXComplexd& operator+=(const FXComplexd& c){ return set(re+c.re,im+c.im); } FXComplexd& operator-=(const FXComplexd& c){ return set(re-c.re,im-c.im); } FXComplexd& operator*=(const FXComplexd& c){ return set(re*c.re-im*c.im,re*c.im+im*c.re); } FXComplexd& operator/=(const FXComplexd& c){ FXdouble m=c.re*c.re+c.im*c.im; return set((re*c.re+im*c.im)/m,(im*c.re-re*c.im)/m); } /// Destructor ~FXComplexd(){} }; /// Return complex complex conjugate static inline FXComplexd conj(const FXComplexd& c){ return FXComplexd(c.real(),-c.imag()); } /// Return complex number from modulus and argument static inline FXComplexd polar(FXdouble mod,FXdouble arg){ return FXComplexd(Math::cos(arg)*mod,Math::sin(arg)*mod); } /// Return norm of complex static inline FXdouble norm(const FXComplexd& c){ return c.real()*c.real()+c.imag()*c.imag(); } /// Return modulus or absolute value of complex static inline FXdouble abs(const FXComplexd& c){ return Math::sqrt(norm(c)); } /// Return argument of complex static inline FXdouble arg(const FXComplexd& c){ return Math::atan2(c.imag(),c.real()); } /// Returns the complex base e exponential of c static inline FXComplexd exp(const FXComplexd& c){ return polar(Math::exp(c.real()),c.imag()); } /// Returns the complex base e logarithm of c static inline FXComplexd log(const FXComplexd& c){ return FXComplexd(Math::log(abs(c)),arg(c)); } /// Equality between complex and real static inline FXbool operator==(const FXComplexd& c,FXdouble r){ return c.real()==r && c.imag()==0.0; } static inline FXbool operator!=(const FXComplexd& c,FXdouble r){ return c.real()!=r || c.imag()!=0.0; } /// Equality between real and complex static inline FXbool operator==(FXdouble r,const FXComplexd& c){ return r==c.real() && c.imag()==0.0; } static inline FXbool operator!=(FXdouble r,const FXComplexd& c){ return r!=c.real() || c.imag()!=0.0; } /// Equality between one complex and another static inline FXbool operator==(const FXComplexd& a,const FXComplexd& b){ return a.real()==b.real() && a.imag()==b.imag(); } static inline FXbool operator!=(const FXComplexd& a,const FXComplexd& b){ return a.real()!=b.real() || a.imag()!=b.imag(); } /// Operators between complex and real static inline FXComplexd operator+(const FXComplexd& a,FXdouble b){ return FXComplexd(a.real()+b,a.imag()); } static inline FXComplexd operator-(const FXComplexd& a,FXdouble b){ return FXComplexd(a.real()-b,a.imag()); } static inline FXComplexd operator*(const FXComplexd& a,FXdouble b){ return FXComplexd(a.real()*b,a.imag()*b); } static inline FXComplexd operator/(const FXComplexd& a,FXdouble b){ return FXComplexd(a.real()/b,a.imag()/b); } /// Operators between real and complex static inline FXComplexd operator+(FXdouble a,const FXComplexd& b){ return FXComplexd(a+b.real(),b.imag()); } static inline FXComplexd operator-(FXdouble a,const FXComplexd& b){ return FXComplexd(a-b.real(),-b.imag()); } static inline FXComplexd operator*(FXdouble a,const FXComplexd& b){ return FXComplexd(a*b.real(),a*b.imag()); } static inline FXComplexd operator/(FXdouble a,const FXComplexd& b){ FXdouble m=norm(b); return FXComplexd((a*b.real())/m,(-a*b.imag())/m); } /// Operators between one complex and another static inline FXComplexd operator+(const FXComplexd& a,const FXComplexd& b){ return FXComplexd(a.real()+b.real(),a.imag()+b.imag()); } static inline FXComplexd operator-(const FXComplexd& a,const FXComplexd& b){ return FXComplexd(a.real()-b.real(),a.imag()-b.imag()); } static inline FXComplexd operator*(const FXComplexd& a,const FXComplexd& b){ return FXComplexd(a.real()*b.real()-a.imag()*b.imag(),a.real()*b.imag()+a.imag()*b.real()); } static inline FXComplexd operator/(const FXComplexd& a,const FXComplexd& b){ FXdouble m=norm(b); return FXComplexd((a.real()*b.real()+a.imag()*b.imag())/m,(a.imag()*b.real()-a.real()*b.imag())/m); } /// Linearly interpolate complex numbers u and v as f goes from 0...1 static inline FXComplexd lerp(const FXComplexd& u,const FXComplexd& v,FXdouble f){ return (v-u)*f+u; } /// Complex square root extern FXAPI FXComplexd csqrt(const FXComplexd& c); /// Complex sine extern FXAPI FXComplexd csin(const FXComplexd& c); /// Complex cosine extern FXAPI FXComplexd ccos(const FXComplexd& c); /// Complex square root extern FXAPI FXComplexd ctan(const FXComplexd& c); /// Complex hyperbolic sine extern FXAPI FXComplexd csinh(const FXComplexd& c); /// Complex hyperbolic cosine extern FXAPI FXComplexd ccosh(const FXComplexd& c); /// Complex hyperbolic tangent extern FXAPI FXComplexd ctanh(const FXComplexd& c); /// Save to a stream extern FXAPI FXStream& operator<<(FXStream& store,const FXComplexd& c); /// Load from a stream extern FXAPI FXStream& operator>>(FXStream& store,FXComplexd& c); } #endif