xue@11: /* xue@11: Harmonic sinusoidal modelling and tools xue@11: xue@11: C++ code package for harmonic sinusoidal modelling and relevant signal processing. xue@11: Centre for Digital Music, Queen Mary, University of London. xue@11: This file copyright 2011 Wen Xue. xue@11: xue@11: This program is free software; you can redistribute it and/or xue@11: modify it under the terms of the GNU General Public License as xue@11: published by the Free Software Foundation; either version 2 of the xue@11: License, or (at your option) any later version. xue@11: */ xue@1: #ifndef XCOMPLEX xue@1: #define XCOMPLEX xue@1: xue@1: Chris@5: #include Chris@5: Chris@5: /** Chris@5: \file xcomplex.h - Xue's complex number class. xue@1: xue@1: This classes is modelled after standard c++ complex class, with a few additional methods. Unused xue@1: standard member and non-member functions/operators may not have been implemented. xue@1: */ xue@1: xue@1: template class cmplx xue@1: { xue@1: public: xue@1: //standard members xue@1: T x; xue@1: T y; xue@1: cmplx(){} xue@1: cmplx(const T& c, const T& d) {x=c; y=d;} xue@1: cmplx(const T& c) {x=c; y=0;} xue@1: template cmplx(const cmplx& c){x=c.x, y=c.y;} xue@1: xue@1: T real(){return x;} xue@1: T imag(){return y;} xue@1: xue@1: cmplx& operator=(const T& c){x=c; y=0; return *this;} xue@10: template cmplx& operator+=(const X& c){x+=c; return *this;} xue@10: template cmplx& operator-=(const X& c){x-=c; return *this;} xue@1: template cmplx& operator*=(const X& c){x*=c; y*=c; return *this;} xue@1: template cmplx& operator/=(const X& c){x/=c; y/=c; return *this;} xue@1: template cmplx& operator=(const cmplx& c){x=c.x; y=c.y; return* this;} xue@1: xue@1: template cmplx& operator+=(const cmplx& c){x+=c.x; y+=c.y; return *this;} xue@1: template cmplx& operator-=(const cmplx& c){x-=c.x; y-=c.y; return *this;} xue@1: template cmplx& operator*=(const cmplx& c){T tmpx=x*c.x-y*c.y; y=x*c.y+y*c.x; x=tmpx; return *this;} xue@1: template cmplx& operator/=(const cmplx& c){if (c.y==0){x/=c.x; y/=c.x;} else if (c.x==0){T tmpx=y/c.y; y=-x/c.y; x=tmpx;} else {T xm=c.x*c.x+c.y*c.y; T tmpx=(c.x*x+c.y*y)/xm; y=(y*c.x-x*c.y)/xm; x=tmpx;} return *this;} xue@1: xue@1: //non-standard members xue@1: //operator~: square of absolute value xue@1: T operator~() {return x*x+y*y;} xue@1: //operator*: complex conjugate xue@1: cmplx operator*(){cmplx result; result.x=x; result.y=-y; return result;} xue@1: //operator^: multiplicaiton with the complex conjugate of the argument xue@1: cmplx operator^(const cmplx &b){cmplx result; result.x=x*b.x+y*b.y; result.y=y*b.x-x*b.y; return result;} xue@1: //cinv: complex reciprocal xue@1: cmplx cinv(){cmplx result; if (y==0) result.x=1/x, result.y=0; else if (x==0) result.y=-1/y, result.x=0; else{T xm=x*x+y*y; result.x=x/xm; result.y=-y/xm;} return result;} xue@1: //rotate: rotate by an angle xue@1: cmplx& rotate(const T ph) {double s=sin(ph), c=cos(ph), tmpx; tmpx=x*c-y*s; y=x*s+y*c; x=tmpx; return *this;} xue@1: }; //*/ xue@1: //standard Non-member Operators xue@1: template cmplx operator+(const cmplx& a, const cmplx& b){cmplx result=a; result+=b; return result;} xue@1: template cmplx operator+(const cmplx& a, Tb& b){cmplx result=a; result+=b; return result;} xue@1: template cmplx operator+(T a, const cmplx& b){cmplx result=a; result+=b; return result;} xue@1: template cmplx operator-(const cmplx& a, const cmplx& b){cmplx result=a; result-=b; return result;} xue@1: template cmplx operator-(const cmplx& a, Tb& b){cmplx result=a; result-=b; return result;} xue@1: template cmplx operator-(T a, const cmplx& b){cmplx result=a; result-=b; return result;} xue@1: template cmplx operator*(const cmplx& a, const cmplx& b){cmplx result=a; result*=b; return result;} xue@1: template cmplx operator*(const cmplx& a, Tb& b){cmplx result=a; result*=b; return result;} xue@1: template cmplx operator*(T& a, const cmplx& b){cmplx result=b; result*=a; return result;} xue@1: template cmplx operator/(const cmplx& a, const cmplx& b){cmplx result=a; result/=b; return result;} xue@1: template cmplx operator/(const cmplx& a, Tb& b){cmplx result=a; result/=b; return result;} xue@1: template cmplx operator/(T a, const cmplx& b){cmplx result=a; result/=b; return result;} xue@1: template cmplx operator+(const cmplx& a){return a;} xue@1: template cmplx operator-(const cmplx& a){cmplx result; result.x=-a.x; result.y=-a.y; return result;} xue@1: template bool operator==(const cmplx& a, const cmplx& b){return (a.x==b.x && a.y==b.y);} xue@1: template bool operator==(const cmplx& a, Tb b){return (a.x==b && a.y==0);} xue@1: template bool operator==(Ta a, const cmplx& b){return (a==b.x && 0==b.y);} xue@1: template bool operator!=(const cmplx& a, const cmplx& b){return (a.x!=b.x || a.y!=b.y);} xue@1: template bool operator!=(const cmplx& a, Tb b){return (a.x!=b || a.y!=0);} xue@1: template bool operator!=(Ta a, const cmplx& b){return (a!=b.x || 0!=b.y);} xue@1: /* xue@1: template basic_istream& operator>>(istream&, complex&); xue@1: template basic_ostream& operator<<(ostream&, const complex&); xue@1: */ xue@1: //Values xue@1: template T real(const cmplx& a){return a.x;} xue@1: template T imag(const cmplx& a){return a.y;} xue@1: template T abs(const cmplx& a){return sqrt(a.x*a.x+a.y*a.y);} xue@1: template T fabs(const cmplx& a){return sqrt(a.x*a.x+a.y*a.y);} xue@1: template T arg(const cmplx& a){return (a.x==0 && a.y==0)?0:atan2(a.y, a.x);} xue@1: template T norm(const cmplx& a){return a.x*a.x+a.y*a.y;} xue@1: template cmplx conj(const cmplx& a){cmplx result; result.x=a.x; result.y=-a.y; return result;} xue@1: template cmplx polar(const T& r, const T& theta){cmplx result; result.x=r*cos(theta); result.y=r*sin(theta); return result;} xue@1: //Transcendentals xue@1: /* xue@1: template cmplx cos (const cmplx&); xue@1: template cmplx cosh (const cmplx&); xue@1: */ xue@1: template cmplx exp(const cmplx& a){return polar(exp(a.x), a.y);} xue@1: template cmplx log(const cmplx& a){cmplx result; result.x=0.5*log(norm(a)); result.y=arg(a); return result;} xue@1: /* xue@1: template cmplx log10 (const cmplx&); xue@1: template cmplx pow (const cmplx&, int); xue@1: */ xue@1: template cmplx pow(const cmplx& a, T& e){cmplx result; T rad=abs(a); T angle=arg(a); return polar(rad, angle*e);} xue@1: /* xue@1: template cmplx pow (const cmplx&, const cmplx&); xue@1: template cmplx pow (const T&, const cmplx&); xue@1: template cmplx sin (const cmplx&); xue@1: template cmplx sinh (const cmplx&); xue@1: */ xue@1: template cmplx sqrt(const cmplx& a){cmplx result; if (a.y==0) {if (a.x>=0){result.x=sqrt(a.x); result.y=0;} else{result.y=sqrt(-a.x); result.x=0;}} else {result.y=sqrt((sqrt(a.x*a.x+a.y*a.y)-a.x)*0.5); result.x=0.5*a.y/result.y;} return result;} xue@1: /* xue@1: template cmplx tan (const cmplx&); xue@1: template cmplx tanh (const cmplx&); xue@1: */ xue@1: xue@1: //non-standard non-member functions xue@1: //template operator^: multiplying one complex number with the complex conjugate of another xue@1: template cmplx operator^(const cmplx& a, const cmplx& b){cmplx result=a; result^=b; return result;} xue@1: xue@1: typedef cmplx cdouble; xue@1: typedef cmplx cfloat; xue@1: xue@1: #endif