| /**@file templates for Complex classes |
| unlike the built-in complex<> templates, these inline most operations for speed |
| */ |
| |
| /* |
| * Copyright 2008 Free Software Foundation, Inc. |
| * |
| * This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion. |
| * |
| * This use of this software may be subject to additional restrictions. |
| * See the LEGAL file in the main directory for details. |
| |
| This program 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. |
| |
| */ |
| |
| |
| |
| |
| #ifndef COMPLEXCPP_H |
| #define COMPLEXCPP_H |
| |
| #include <math.h> |
| #include <ostream> |
| |
| |
| template<class Real> class Complex { |
| |
| public: |
| |
| Real r, i; |
| |
| /**@name constructors */ |
| //@{ |
| /**@name from real */ |
| //@{ |
| Complex(Real real, Real imag) {r=real; i=imag;} // x=complex(a,b) |
| Complex(Real real) {r=real; i=0;} // x=complex(a) |
| //@} |
| /**@name from nothing */ |
| //@{ |
| Complex() {r=(Real)0; i=(Real)0;} // x=complex() |
| //@} |
| /**@name from other complex */ |
| //@{ |
| Complex(const Complex<float>& z) {r=z.r; i=z.i;} // x=complex(z) |
| Complex(const Complex<double>& z) {r=z.r; i=z.i;} // x=complex(z) |
| Complex(const Complex<long double>& z) {r=z.r; i=z.i;} // x=complex(z) |
| //@} |
| //@} |
| |
| /**@name casting up from basic numeric types */ |
| //@{ |
| Complex& operator=(char a) { r=(Real)a; i=(Real)0; return *this; } |
| Complex& operator=(int a) { r=(Real)a; i=(Real)0; return *this; } |
| Complex& operator=(long int a) { r=(Real)a; i=(Real)0; return *this; } |
| Complex& operator=(short a) { r=(Real)a; i=(Real)0; return *this; } |
| Complex& operator=(float a) { r=(Real)a; i=(Real)0; return *this; } |
| Complex& operator=(double a) { r=(Real)a; i=(Real)0; return *this; } |
| Complex& operator=(long double a) { r=(Real)a; i=(Real)0; return *this; } |
| //@} |
| |
| /**@name arithmetic */ |
| //@{ |
| /**@ binary operators */ |
| //@{ |
| Complex operator+(const Complex<Real>& a) const { return Complex<Real>(r+a.r, i+a.i); } |
| Complex operator+(Real a) const { return Complex<Real>(r+a,i); } |
| Complex operator-(const Complex<Real>& a) const { return Complex<Real>(r-a.r, i-a.i); } |
| Complex operator-(Real a) const { return Complex<Real>(r-a,i); } |
| Complex operator*(const Complex<Real>& a) const { return Complex<Real>(r*a.r-i*a.i, r*a.i+i*a.r); } |
| Complex operator*(Real a) const { return Complex<Real>(r*a, i*a); } |
| Complex operator/(const Complex<Real>& a) const { return operator*(a.inv()); } |
| Complex operator/(Real a) const { return Complex<Real>(r/a, i/a); } |
| //@} |
| /*@name component-wise product */ |
| //@{ |
| Complex operator&(const Complex<Real>& a) const { return Complex<Real>(r*a.r, i*a.i); } |
| //@} |
| /*@name inplace operations */ |
| //@{ |
| Complex& operator+=(const Complex<Real>&); |
| Complex& operator-=(const Complex<Real>&); |
| Complex& operator*=(const Complex<Real>&); |
| Complex& operator/=(const Complex<Real>&); |
| Complex& operator+=(Real); |
| Complex& operator-=(Real); |
| Complex& operator*=(Real); |
| Complex& operator/=(Real); |
| //@} |
| //@} |
| |
| /**@name comparisons */ |
| //@{ |
| bool operator==(const Complex<Real>& a) const { return ((i==a.i)&&(r==a.r)); } |
| bool operator!=(const Complex<Real>& a) const { return ((i!=a.i)||(r!=a.r)); } |
| bool operator<(const Complex<Real>& a) const { return norm2()<a.norm2(); } |
| bool operator>(const Complex<Real>& a) const { return norm2()>a.norm2(); } |
| //@} |
| |
| /// reciprocation |
| Complex inv() const; |
| |
| // unary functions -- inlined |
| /**@name unary functions */ |
| //@{ |
| /**@name inlined */ |
| //@{ |
| Complex conj() const { return Complex<Real>(r,-i); } |
| Real norm2() const { return i*i+r*r; } |
| Complex flip() const { return Complex<Real>(i,r); } |
| Real real() const { return r;} |
| Real imag() const { return i;} |
| Complex neg() const { return Complex<Real>(-r, -i); } |
| bool isZero() const { return ((r==(Real)0) && (i==(Real)0)); } |
| //@} |
| /**@name not inlined due to outside calls */ |
| //@{ |
| Real abs() const { return ::sqrt(norm2()); } |
| Real arg() const { return ::atan2(i,r); } |
| float dB() const { return 10.0*log10(norm2()); } |
| Complex exp() const { return expj(i)*(::exp(r)); } |
| Complex unit() const; ///< unit phasor with same angle |
| Complex log() const { return Complex(::log(abs()),arg()); } |
| Complex pow(double n) const { return expj(arg()*n)*(::pow(abs(),n)); } |
| Complex sqrt() const { return pow(0.5); } |
| //@} |
| //@} |
| |
| }; |
| |
| |
| /**@name standard Complex manifestations */ |
| //@{ |
| typedef Complex<float> complex; |
| typedef Complex<double> dcomplex; |
| typedef Complex<short> complex16; |
| typedef Complex<long> complex32; |
| //@} |
| |
| |
| template<class Real> inline Complex<Real> Complex<Real>::inv() const |
| { |
| Real nVal; |
| |
| nVal = norm2(); |
| return Complex<Real>(r/nVal, -i/nVal); |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator+=(const Complex<Real>& a) |
| { |
| r += a.r; |
| i += a.i; |
| return *this; |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator*=(const Complex<Real>& a) |
| { |
| operator*(a); |
| return *this; |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator-=(const Complex<Real>& a) |
| { |
| r -= a.r; |
| i -= a.i; |
| return *this; |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator/=(const Complex<Real>& a) |
| { |
| operator/(a); |
| return *this; |
| } |
| |
| |
| /* op= style operations with reals */ |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator+=(Real a) |
| { |
| r += a; |
| return *this; |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator*=(Real a) |
| { |
| r *=a; |
| i *=a; |
| return *this; |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator-=(Real a) |
| { |
| r -= a; |
| return *this; |
| } |
| |
| template<class Real> Complex<Real>& Complex<Real>::operator/=(Real a) |
| { |
| r /= a; |
| i /= a; |
| return *this; |
| } |
| |
| |
| template<class Real> Complex<Real> Complex<Real>::unit() const |
| { |
| Real absVal = abs(); |
| return (Complex<Real>(r/absVal, i/absVal)); |
| } |
| |
| |
| |
| /**@name complex functions outside of the Complex<> class. */ |
| //@{ |
| |
| /** this allows type-commutative multiplication */ |
| template<class Real> Complex<Real> operator*(Real a, const Complex<Real>& z) |
| { |
| return Complex<Real>(z.r*a, z.i*a); |
| } |
| |
| |
| /** this allows type-commutative addition */ |
| template<class Real> Complex<Real> operator+(Real a, const Complex<Real>& z) |
| { |
| return Complex<Real>(z.r+a, z.i); |
| } |
| |
| |
| /** this allows type-commutative subtraction */ |
| template<class Real> Complex<Real> operator-(Real a, const Complex<Real>& z) |
| { |
| return Complex<Real>(z.r-a, z.i); |
| } |
| |
| |
| |
| /// e^jphi |
| template<class Real> Complex<Real> expj(Real phi) |
| { |
| return Complex<Real>(cos(phi),sin(phi)); |
| } |
| |
| /// phasor expression of a complex number |
| template<class Real> Complex<Real> phasor(Real C, Real phi) |
| { |
| return (expj(phi)*C); |
| } |
| |
| /// formatted stream output |
| template<class Real> std::ostream& operator<<(std::ostream& os, const Complex<Real>& z) |
| { |
| os << z.r << ' '; |
| //os << z.r << ", "; |
| //if (z.i>=0) { os << "+"; } |
| os << z.i << "j"; |
| os << "\n"; |
| return os; |
| } |
| |
| //@} |
| |
| |
| #endif |