00001
00002
00003
00004
00005
00006
00007 #ifndef CALC_CPX_H
00008 #define CALC_CPX_H
00009
00010
00011
00012
00013
00014 #include <cmath>
00015 #include <iostream>
00016
00017
00018
00019
00020
00021 namespace calc {
00022
00023
00024
00025
00031
00032
00043 template <typename aType>
00044 class Cpx {
00045
00046 public:
00047
00048
00049
00054 Cpx(void) {re=im=(aType)(0);}
00061 Cpx(float real) {re=(aType)(real); im=(aType)(0);}
00062 Cpx(char real) {re=(aType)(real); im=(aType)(0);}
00063 Cpx(char unsigned real) {re=(aType)(real); im=(aType)(0);}
00064 Cpx(short real) {re=(aType)(real); im=(aType)(0);}
00065 Cpx(short unsigned real) {re=(aType)(real); im=(aType)(0);}
00066 Cpx(int real) {re=(aType)(real); im=(aType)(0);}
00067 Cpx(int unsigned real) {re=(aType)(real); im=(aType)(0);}
00068 Cpx(long real) {re=(aType)(real); im=(aType)(0);}
00069 Cpx(long unsigned real) {re=(aType)(real); im=(aType)(0);}
00070 Cpx(double real) {re=(aType)(real); im=(aType)(0);}
00071 Cpx(double long real) {re=(aType)(real); im=(aType)(0);}
00078 Cpx(const float *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00079 Cpx(const char *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00080 Cpx(const char unsigned *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00081 Cpx(const short *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00082 Cpx(const short unsigned *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00083 Cpx(const int *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00084 Cpx(const int unsigned *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00085 Cpx(const long *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00086 Cpx(const long unsigned *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00087 Cpx(const double *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00088 Cpx(const double long *ptr) {re=(aType)(ptr[0]); im=(aType)(ptr[1]);}
00096 Cpx(float real, float imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00097 Cpx(char real, char imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00098 Cpx(char unsigned real, char unsigned imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00099 Cpx(short real, short imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00100 Cpx(short unsigned real, short unsigned imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00101 Cpx(int real, int imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00102 Cpx(int unsigned real, int unsigned imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00103 Cpx(long real, long imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00104 Cpx(long unsigned real, long unsigned imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00105 Cpx(double real, double imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00106 Cpx(double long real, double long imaginary) {re=(aType)(real); im=(aType)(imaginary);}
00113 Cpx(const Cpx<aType>& cm) {re=(aType)(cm.re); im=(aType)(cm.im);}
00118 ~Cpx(void) {}
00119
00120
00121
00122 aType magnitude (void) const;
00123 Cpx<aType> operator/ (const Cpx<aType>& cm) const;
00124 const Cpx<aType> operator/= (const Cpx<aType>& cm);
00125
00126
00136 aType magnitude2(void) const {return re*re+im*im;}
00152 operator aType *(void) {return &re;}
00161 const Cpx<aType> operator=(const Cpx<aType>& cm)
00162 {re=cm.re; im=cm.im; return *this;}
00169 Cpx<aType> operator~(void) const {return Cpx<aType>(re,-im);}
00182 std::ostream& stream(std::ostream& ostr) const
00183 {const bool bsg=(im<0); ostr<<re<<(bsg?"-i":"+i")<<(bsg?-im:im); return ostr;}
00184
00185
00186
00193 Cpx<aType> operator+(void) const {return Cpx<aType>(re,im);}
00202 Cpx<aType> operator+(aType scalar) const {return Cpx<aType>(re+scalar,im);}
00211 Cpx<aType> operator+(const Cpx<aType>& cm) const
00212 {return Cpx<aType>(re+cm.re,im+cm.im);}
00222 const Cpx<aType> operator+=(aType scalar) {re+=scalar; return *this;}
00232 const Cpx<aType> operator+=(const Cpx<aType>& cm)
00233 {re+=cm.re; im+=cm.im; return *this;}
00234
00235
00236
00243 Cpx<aType> operator-(void) const {return Cpx<aType>(-re,-im);}
00252 Cpx<aType> operator-(aType scalar) const {return Cpx<aType>(re-scalar,im);}
00261 Cpx<aType> operator-(const Cpx<aType>& cm) const
00262 {return Cpx<aType>(re-cm.re,im-cm.im);}
00272 const Cpx<aType> operator-=(double scalar) {re-=scalar; return *this;}
00282 const Cpx<aType> operator-=(const Cpx<aType>& cm)
00283 {re-=cm.re; im-=cm.im; return *this;}
00284
00285
00286
00295 Cpx<aType> operator*(aType scalar) const
00296 {return Cpx<aType>(re*scalar,im*scalar);}
00305 Cpx<aType> operator*(const Cpx<aType>& cm) const
00306 {return Cpx<aType>(re*cm.re-im*cm.im,im*cm.re+re*cm.im);}
00316 const Cpx<aType> operator*=(aType scalar)
00317 {re*=scalar; im*=scalar; return *this;}
00327 const Cpx<aType> operator*=(const Cpx<aType>& cm)
00328 {aType x=re*cm.re-im*cm.im; im=im*cm.re+re*cm.im; re=x; return *this;}
00329
00330
00331
00340 Cpx<aType> operator/(aType scalar) const
00341 {return Cpx<aType>(re/scalar,im/scalar);}
00351 const Cpx<aType> operator/=(aType scalar)
00352 {re/=scalar; im/=scalar; return *this;}
00353
00354
00355
00370 bool operator==(const Cpx<aType>& cm) const {return ((re==cm.re)&&(im==cm.im));}
00387 bool operator==(aType scalar) const {return ((im==(aType)(0))&&(re==scalar));}
00388
00389
00390
00405 bool operator!=(const Cpx<aType>& cm) const {return ((re!=cm.re)||(im!=cm.im));}
00422 bool operator!=(aType scalar) const {return ((im!=(aType)(0))||(re!=scalar));}
00423
00424
00425
00440 bool operator<(const Cpx<aType>& cm) const {return (magnitude2()<cm.magnitude2());}
00455 bool operator<=(const Cpx<aType>& cm) const {return (magnitude2()<=cm.magnitude2());}
00456
00457
00458
00473 bool operator>(const Cpx<aType>& cm) const {return (magnitude2()>cm.magnitude2());}
00488 bool operator>=(const Cpx<aType>& cm) const {return (magnitude2()>=cm.magnitude2());}
00489
00490
00491
00505 template <class bType>
00506 friend std::ostream& operator<<(std::ostream& ostr, const Cpx<bType>& cm)
00507 {ostr<<cm.re<<","<<cm.im; return ostr;}
00508
00509
00510
00520 template <class bType>
00521 friend Cpx<bType> operator+(bType scalar, const Cpx<bType>& cm)
00522 {return Cpx<bType>(cm.re+scalar,cm.im);}
00532 template <class bType>
00533 friend Cpx<bType> operator-(bType scalar, const Cpx<bType>& cm)
00534 {return Cpx<bType>(scalar-cm.re,-cm.im);}
00544 template <class bType>
00545 friend Cpx<bType> operator*(bType scalar, const Cpx<bType>& cm)
00546 {return Cpx<bType>(cm.re*scalar,cm.im*scalar);}
00556 template <class bType>
00557 friend Cpx<bType> operator/(bType scalar, const Cpx<bType>& cm)
00558 {bType u,v,fr; cm.absCpx(u,v);
00559 if(u<v) {
00560 const bType de=cm.im+cm.re*(fr=cm.re/cm.im);
00561 return Cpx<bType>(scalar*fr/de,-scalar/de);
00562 } else {
00563 const bType de=cm.re+cm.im*(fr=cm.im/cm.re);
00564 return Cpx<bType>(scalar/de,-scalar*fr/de);}}
00573 template <class bType>
00574 friend Cpx<bType> ceil(const Cpx<bType>& cm)
00575 {return Cpx<bType>((bType)(std::ceil(cm.re)),(bType)(std::ceil(cm.im)));}
00584 template <class bType>
00585 friend Cpx<bType> floor(const Cpx<bType>& cm)
00586 {return Cpx<bType>((bType)(std::floor(cm.re)),(bType)(std::floor(cm.im)));}
00587
00588
00589
00602 template <class bType>
00603 friend bType fabs(const Cpx<bType>& cm) {return cm.magnitude();}
00621 template <class bType>
00622 friend bool operator==(bType scalar, const Cpx<bType>& cm)
00623 {return ((cm.im==(bType)0)&&(cm.re==scalar));}
00641 template <class bType>
00642 friend bool operator!=(bType scalar, const Cpx<bType>& cm)
00643 {return ((cm.im!=(bType)0)||(cm.re!=scalar));}
00644
00645
00646
00660 template <class bType>
00661 friend Cpx<bType> sqrt(const Cpx<bType>& cm)
00662 {bType u,v,ra,fr; cm.absCpx(u,v);
00663 if((u+v)==(bType)(0)) return Cpx<bType>();
00664 if(u<v) {
00665 fr=u/v;
00666 ra=(bType)(std::sqrt(v*(fr+(bType)(std::sqrt((bType)(1)+fr*fr)))/(bType)(2)));
00667 } else {
00668 fr=v/u;
00669 ra=(bType)(std::sqrt(u*((bType)(1)+(bType)(std::sqrt((bType)(1)+fr*fr)))/(bType)(2)));
00670 }
00671 return ((cm.re>=(bType)(0))?Cpx<bType>(ra,cm.im/ra/(bType)(2))
00672 :Cpx<bType>(v/ra/(bType)(2),cm.sign(cm.im)*ra));}
00684 template <class bType>
00685 friend Cpx<bType> pow(bType scalar, const Cpx<bType>& cx)
00686 {bType ra,an;
00687 if(scalar<(bType)(0)) {
00688 an=cx.im*(bType)(std::log(-scalar))+(Cpx<bType>::PI)*cx.re;
00689 ra=(bType)(std::pow(-scalar,cx.re)*std::exp((Cpx<bType>::PI)*cx.im));
00690 } else if(scalar>(bType)(0)) {
00691 an=cx.im*(bType)(std::log(scalar));
00692 ra=(bType)(std::pow(scalar,cx.re));
00693 } else return Cpx<bType>();
00694 return Cpx<bType>(ra*std::cos(an),ra*std::sin(an));}
00710 template <class bType>
00711 friend Cpx<bType> pow(const Cpx<bType>& cm, bType scalar)
00712 {const bType an=scalar*(bType)(std::atan2(cm.im,cm.re));
00713 const bType ra=(bType)(std::pow(fabs(cm),scalar));
00714 return Cpx<bType>(ra*std::cos(an),ra*std::sin(an));}
00730 template <class bType>
00731 friend Cpx<bType> pow(const Cpx<bType>& cm, const Cpx<bType>& cx)
00732 {const bType an=cm.modCpx((bType)(std::atan2(cm.im,cm.re)));
00733 const bType ra=fabs(cm);
00734 const bType rx=(bType)(std::pow(ra,cx.re)*std::exp(-an*cx.im));
00735 const bType ax=an*cx.re+cx.im*(bType)(std::log(ra));
00736 return Cpx<bType>(rx*(bType)(std::cos(ax)),rx*(bType)(std::sin(ax)));}
00737
00738
00739
00748 template <class bType>
00749 friend Cpx<bType> exp(const Cpx<bType>& cm)
00750 {return (bType)(std::exp(cm.re))*
00751 Cpx<bType>(std::cos(cm.im),std::sin(cm.im));}
00764 template <class bType>
00765 friend Cpx<bType> log(const Cpx<bType>& cm)
00766 {return Cpx<bType>((bType)(0.5*std::log(cm.re*cm.re+cm.im*cm.im)),
00767 (bType)(cm.modCpx(std::atan2(cm.im,cm.re))));}
00781 template <class bType>
00782 friend Cpx<bType> log10(const Cpx<bType>& cm) {return log(cm)/Cpx<bType>::LN10;}
00783
00784
00785
00794 template <class bType>
00795 friend Cpx<bType> cos(const Cpx<bType>& cm)
00796 {bType ep,e2; cm.expCpx(ep,e2,cm.im);
00797 return Cpx<bType>(ep*(e2+(bType)(1))*(bType)(std::cos(cm.re)),
00798 cm.sign(cm.im)*ep*(e2-(bType)(1))*(bType)(std::sin(cm.re)));}
00807 template <class bType>
00808 friend Cpx<bType> sin(const Cpx<bType>& cm)
00809 {bType ep,e2; cm.expCpx(ep,e2,cm.im);
00810 return Cpx<bType>(ep*((bType)(1)+e2)*(bType)(std::sin(cm.re)),
00811 cm.sign(cm.im)*ep*((bType)(1)-e2)*(bType)(std::cos(cm.re)));}
00820 template <class bType>
00821 friend Cpx<bType> tan(const Cpx<bType>& cm)
00822 {const bType em=(bType)(std::exp((bType)(2)*((cm.im>(bType)(0))?-cm.im:cm.im)));
00823 const bType e2=em*em;
00824 const bType an=(bType)(2)*cm.re;
00825 const bType de=(bType)(2)*em*(bType)(std::cos(an))+(bType)(1)+e2;
00826 return Cpx<bType>((bType)(2)*em*(bType)(std::sin(an))/de,
00827 cm.sign(cm.im)*((bType)(1)-e2)/de);}
00828
00829
00830
00846 template <class bType>
00847 friend Cpx<bType> acos(const Cpx<bType>& cm)
00848 {const Cpx<bType> cn(-cm.im,cm.re);
00849 const Cpx<bType> cx=log(cn+sqrt(cn*cn+(bType)(1)));
00850 return Cpx<bType>((Cpx<bType>::PI)/(bType)(2)-cx.im,cx.re);}
00866 template <class bType>
00867 friend Cpx<bType> asin(const Cpx<bType>& cm)
00868 {const Cpx<bType> cn(-cm.im,cm.re);
00869 const Cpx<bType> cx=log(cn+sqrt(cn*cn+(bType)(1)));
00870 return Cpx<bType>(cx.im,-cx.re);}
00887 template <class bType>
00888 friend Cpx<bType> atan(const Cpx<bType>& cm)
00889 {const Cpx<bType> cn(-cm.im,cm.re);
00890 const Cpx<bType> cx=(log((bType)(1)+cn)-log((bType)(1)-cn))/(bType)(2);
00891 return Cpx<bType>(cx.im,-cx.re);}
00892
00893
00894
00903 template <class bType>
00904 friend Cpx<bType> cosh(const Cpx<bType>& cm)
00905 {bType ep,e2; cm.expCpx(ep,e2,cm.re);
00906 return Cpx<bType>(ep*((bType)(1)+e2)*(bType)(std::cos(cm.im)),
00907 cm.sign(cm.re)*ep*((bType)(1)-e2)*(bType)(std::sin(cm.im)));}
00916 template <class bType>
00917 friend Cpx<bType> sinh(const Cpx<bType>& cm)
00918 {bType ep,e2; cm.expCpx(ep,e2,cm.re);
00919 return Cpx<bType>(cm.sign(cm.re)*ep*((bType)(1)-e2)*(bType)(std::cos(cm.im)),
00920 ep*((bType)(1)+e2)*(bType)(std::sin(cm.im)));}
00929 template <class bType>
00930 friend Cpx<bType> tanh(const Cpx<bType>& cm)
00931 {const bType em=(bType)(std::exp((bType)(2)*(cm.re<(bType)(0)?cm.re:-cm.re)));
00932 const bType e2=em*em;
00933 const bType an=(bType)(2)*cm.im;
00934 const bType de=(bType)(2)*em*(bType)(std::cos(an))+(bType)(1)+e2;
00935 return Cpx<bType>(cm.sign(cm.re)*((bType)(1)-e2)/de,
00936 (bType)(2)*em*(bType)(std::sin(an))/de);}
00937
00938
00939
00952 template <class bType>
00953 friend Cpx<bType> acosh(const Cpx<bType>& cm)
00954 {return (bType)(2)*log(sqrt((cm+(bType)(1))/(bType)(2))
00955 +sqrt((cm-(bType)(1))/(bType)(2)));}
00971 template <class bType>
00972 friend Cpx<bType> asinh(const Cpx<bType>& cm)
00973 {return log(cm+sqrt(cm*cm+(bType)(1)));}
00990 template <class bType>
00991 friend Cpx<bType> atanh(const Cpx<bType>& cm)
00992 {return (log((bType)(1)+cm)-log((bType)(1)-cm))/(bType)(2);}
00993
00994
00995
00996 aType re;
00997 aType im;
00999 static const aType PI;
01000 static const aType LN10;
01001
01002 private:
01003
01004
01005
01006 static aType modCpx(aType scalar);
01007 static void expCpx(aType& ep, aType& e2, aType xin);
01008 void absCpx(aType& u, aType& v) const;
01009
01020 static aType sign(aType x) {return (x<(aType)(0)?(aType)(-1):(aType)(1));}
01021 };}
01022
01023
01024
01026 template <typename aType>
01027 const aType calc::Cpx<aType>::PI=3.141592653589793238462643;
01029 template <typename aType>
01030 const aType calc::Cpx<aType>::LN10=2.302585092994045684017991;
01031
01032
01033
01034
01035
01036 #endif
01037
01038
01039
01040
01041
01042 #include "Cpx.cpp"
01043
01044