// Rascal, the Advanced Scientific CALculator // Copyright (C) 2001, Sebastian Ritterbusch (Rascal@Ritterbusch.de) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // 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. See the // GNU General Public License for more detauls. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // #ifndef MCOMPLEX_HPP_INCLUDED #define MCOMPLEX_HPP_INCLUDED #include template class mcomplex { private: T r,i; public: mcomplex(void) {} mcomplex(const T & a,const T & b=0) : r(a),i(b) {} mcomplex(const mcomplex & x) : r(x.r),i(x.i) {} const T & real(void) const { return r; } const T & imag(void) const { return i; } friend ostream & operator <<(ostream & o,const mcomplex & a) { o << a.r << ' ' << a.i; return o; } friend inline mcomplex operator -(const mcomplex & a) { return mcomplex(-a.r,-a.i); } friend inline mcomplex operator +(const mcomplex & a) { return a; } friend inline mcomplex & operator +=(mcomplex & a,const mcomplex & b) { a.r+=b.r;a.i+=b.i;return a; } friend inline mcomplex & operator +=(mcomplex & a,const T & b) { a.r+=b;return a; } friend inline mcomplex operator +(const mcomplex & a,const mcomplex & b) { return mcomplex(a.r+b.r,a.i+b.i); } friend inline mcomplex operator +(const T & a,const mcomplex & b) { return mcomplex(a+b.r,b.i); } friend inline mcomplex operator +(const mcomplex & b,const T & a) { return mcomplex(b.r+a,b.i); } friend inline mcomplex & operator -=(mcomplex & a,const mcomplex & b) { a.r-=b.r;a.i-=b.i;return a; } friend inline mcomplex & operator -=(mcomplex & a,const T & b) { a.r-=b;return a; } friend inline mcomplex operator -(const mcomplex & a,const mcomplex & b) { return mcomplex(a.r-b.r,a.i-b.i); } friend inline mcomplex operator -(const T & a,const mcomplex & b) { return mcomplex(a-b.r,-b.i); } friend inline mcomplex operator -(const mcomplex & b,const T & a) { return mcomplex(b.r-a,b.i); } friend inline mcomplex & operator *=(mcomplex & a,const mcomplex & b) { T r=a.r*b.r-a.i*b.i;a.i=a.r*b.i+a.i*b.r;a.r=r;return a; } friend inline mcomplex & operator *=(mcomplex & a,const T & b) { a.r*=b;a.i*=b; return a; } friend inline mcomplex operator *(const mcomplex & a,const mcomplex & b) { return mcomplex(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r); } friend inline mcomplex operator *(const T & a,const mcomplex & b) { return mcomplex(a*b.r,a*b.i); } friend inline mcomplex operator *(const mcomplex & b,const T & a) { return mcomplex(b.r*a,b.i*a); } friend inline mcomplex & operator /=(mcomplex & a,const mcomplex & b) { T q=b.r*b.r+b.i*b.i,r=(a.r*b.r+a.i*b.i)/q;a.i=(a.i*b.r-a.r*b.i)/q;a.r=r;return a; } friend inline mcomplex & operator /=(mcomplex & a,const T & b) { a.r/=b;a.i/=b; return a; } friend inline mcomplex operator /(const mcomplex & a,const mcomplex & b) { T q=b.r*b.r+b.i*b.i; return mcomplex((a.r*b.r+a.i*b.i)/q,(a.i*b.r-a.r*b.i)/q); } friend inline mcomplex operator /(const T & a,const mcomplex & b) { T q=b.r*b.r+b.i*b.i; return mcomplex((a*b.r)/q,(-a*b.i)/q); } friend inline mcomplex operator /(const mcomplex & b,const T & a) { return mcomplex(b.r/a,b.i/a); } friend inline int operator ==(const mcomplex & a,const mcomplex & b) { return (a.r==b.r) && (a.i==b.i); } friend inline int operator !=(const mcomplex & a,const mcomplex & b) { return (a.r!=b.r) || (a.i!=b.i); } friend inline T abs(const mcomplex & a) { return sqrt((a.r*a.r)+(a.i*a.i)); } friend inline T arg(const mcomplex & a) { if(a.r>0) return asin(a.i/abs(a)); else if(a.i>0) return 4*atan(T(1))-asin(a.i/abs(a)); else if(a.i<0) return -4*atan(T(1))-asin(a.i/abs(a)); else if(abs(a)==0) return T(0); else return 4*atan(T(1)); } // Standard functions friend inline mcomplex exp(const mcomplex & a) { // e^(x+iy)=e^x * (cos(y)+i*sin(y)) T ex(exp(a.r)); return mcomplex(ex*cos(a.i),ex*sin(a.i)); } friend inline mcomplex log(const mcomplex & a) { // ln(x+iy)=ln(abs(x+iy))+i*arg(x+iy) return mcomplex(log(abs(a)),arg(a)); } friend inline mcomplex pow(const mcomplex & a,const mcomplex & b) { // a^b=e^(b*ln(a)); return exp(b*log(a)); } friend inline mcomplex sqrt(const mcomplex & a) { // really slow... using polar representation would be better return pow(a,mcomplex(.5)); } friend inline mcomplex sqr(const mcomplex & a) { return mcomplex(sqr(a.r)-sqr(a.i),2*a.r*a.i); } friend inline mcomplex sin(const mcomplex & a) { // sin(x+iy)=sin(x)*cosh(y)+i*cos(x)*sinh(y) return mcomplex(sin(a.r)*cosh(a.i),cos(a.r)*sinh(a.i)); } friend inline mcomplex cos(const mcomplex & a) { // cos(x+iy)=cos(x)*cosh(y)-i*sin(x)*sinh(y) return mcomplex(cos(a.r)*cosh(a.i),-sin(a.r)*sinh(a.i)); } friend inline mcomplex tan(const mcomplex & a) { // tan(x+iy)=(sin(2*x)+i*sinh(2*y))/(cos(2*x)+cosh(2*y)) T q(cos(2*a.r)+cosh(2*a.i)); return mcomplex(sin(a.r+a.r)/q,sinh(a.i+a.i)/q); } friend inline mcomplex cot(const mcomplex & a) { return T(1)/tan(a); } friend inline mcomplex sinh(const mcomplex & a) { // sinh(x+iy)=sin(x)*cos(y)+i*cosh(x)*sin(y) return mcomplex(sinh(a.r)*cos(a.i),cosh(a.r)*sin(a.i)); } friend inline mcomplex cosh(const mcomplex & a) { // cosh(x+iy)=cosh(x)*cos(y)+i*sinh(x)*sin(y) return mcomplex(cosh(a.r)*cos(a.i),sinh(a.r)*sin(a.i)); } friend inline mcomplex tanh(const mcomplex & a) { // tan(x+iy)=(sinh(2*x)+i*sin(2*y))/(cosh(2*x)+cos(2*y)) T q(cosh(a.r+a.r)+cos(a.i+a.i)); return mcomplex(sinh(a.r+a.r)/q,sin(a.i+a.i)/q); } friend inline mcomplex coth(const mcomplex & a) { return T(1)/tan(a); } friend inline mcomplex asin(const mcomplex & z) { // arcsin(a)=-i*ln(i*z+sqrt(1-z*z)) mcomplex i(0,1); return -i*log(i*z+sqrt(1-z*z)); } friend inline mcomplex acos(const mcomplex & z) { // arccos(a)=-i*ln(z+sqrt(z*z-1)) mcomplex i(0,1); return -i*log(z+sqrt(z*z-1)); } friend inline mcomplex atan(const mcomplex & z) { // arctan(a)=(1/2*i)*ln((1+i*z)/(1-i*z)) mcomplex i(0,1); return (1/(2*i))*log((1+i*z)/(1-i*z)); } friend inline mcomplex acot(const mcomplex & z) { // arccot(a)=-(1/2*i)*ln((i*z+1)/(i*z-1)) mcomplex i(0,1); return -(1/(2*i))*log((i*z+1)/(i*z-1)); } friend inline mcomplex asinh(const mcomplex & z) { // arsinh(z)=ln(z+sqrt(z*z+1)) return log(z+sqrt(z*z+1)); } friend inline mcomplex acosh(const mcomplex & z) { // arcosh(z)=ln(z+sqrt(z*z-1)) return log(z+sqrt(z*z+1)); } friend inline mcomplex atanh(const mcomplex & z) { // artanh(z)=ln((1+z)/(1-z))/2 return log((1+z)/(1-z))/2; } friend inline mcomplex acoth(const mcomplex & z) { // arcoth(z)=ln((z+1)/(z-1))/2 return log((z+1)/(z-1))/2; } }; #endif