/**@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 #include template 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& z) {r=z.r; i=z.i;} // x=complex(z) Complex(const Complex& z) {r=z.r; i=z.i;} // x=complex(z) Complex(const Complex& 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& a) const { return Complex(r+a.r, i+a.i); } Complex operator+(Real a) const { return Complex(r+a,i); } Complex operator-(const Complex& a) const { return Complex(r-a.r, i-a.i); } Complex operator-(Real a) const { return Complex(r-a,i); } Complex operator*(const Complex& a) const { return Complex(r*a.r-i*a.i, r*a.i+i*a.r); } Complex operator*(Real a) const { return Complex(r*a, i*a); } Complex operator/(const Complex& a) const { return operator*(a.inv()); } Complex operator/(Real a) const { return Complex(r/a, i/a); } //@} /*@name component-wise product */ //@{ Complex operator&(const Complex& a) const { return Complex(r*a.r, i*a.i); } //@} /*@name inplace operations */ //@{ Complex& operator+=(const Complex&); Complex& operator-=(const Complex&); Complex& operator*=(const Complex&); Complex& operator/=(const Complex&); Complex& operator+=(Real); Complex& operator-=(Real); Complex& operator*=(Real); Complex& operator/=(Real); //@} //@} /**@name comparisons */ //@{ bool operator==(const Complex& a) const { return ((i==a.i)&&(r==a.r)); } bool operator!=(const Complex& a) const { return ((i!=a.i)||(r!=a.r)); } bool operator<(const Complex& a) const { return norm2()(const Complex& a) const { return norm2()>a.norm2(); } //@} /// reciprocation Complex inv() const; // unary functions -- inlined /**@name unary functions */ //@{ /**@name inlined */ //@{ Complex conj() const { return Complex(r,-i); } Real norm2() const { return i*i+r*r; } Complex flip() const { return Complex(i,r); } Real real() const { return r;} Real imag() const { return i;} Complex neg() const { return Complex(-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 complex; typedef Complex dcomplex; typedef Complex complex16; typedef Complex complex32; //@} template inline Complex Complex::inv() const { Real nVal; nVal = norm2(); return Complex(r/nVal, -i/nVal); } template Complex& Complex::operator+=(const Complex& a) { r += a.r; i += a.i; return *this; } template Complex& Complex::operator*=(const Complex& a) { operator*(a); return *this; } template Complex& Complex::operator-=(const Complex& a) { r -= a.r; i -= a.i; return *this; } template Complex& Complex::operator/=(const Complex& a) { operator/(a); return *this; } /* op= style operations with reals */ template Complex& Complex::operator+=(Real a) { r += a; return *this; } template Complex& Complex::operator*=(Real a) { r *=a; i *=a; return *this; } template Complex& Complex::operator-=(Real a) { r -= a; return *this; } template Complex& Complex::operator/=(Real a) { r /= a; i /= a; return *this; } template Complex Complex::unit() const { Real absVal = abs(); return (Complex(r/absVal, i/absVal)); } /**@name complex functions outside of the Complex<> class. */ //@{ /** this allows type-commutative multiplication */ template Complex operator*(Real a, const Complex& z) { return Complex(z.r*a, z.i*a); } /** this allows type-commutative addition */ template Complex operator+(Real a, const Complex& z) { return Complex(z.r+a, z.i); } /** this allows type-commutative subtraction */ template Complex operator-(Real a, const Complex& z) { return Complex(z.r-a, z.i); } /// e^jphi template Complex expj(Real phi) { return Complex(cos(phi),sin(phi)); } /// phasor expression of a complex number template Complex phasor(Real C, Real phi) { return (expj(phi)*C); } /// formatted stream output template std::ostream& operator<<(std::ostream& os, const Complex& z) { os << z.r << ' '; //os << z.r << ", "; //if (z.i>=0) { os << "+"; } os << z.i << "j"; return os; } //@} #endif