Main Page | Class Hierarchy | Alphabetical List | Data Structures | File List | Data Fields | Globals

TComplex.h

Go to the documentation of this file.
00001 
00003 //                                                                      //
00004 // TComplex                                                             //
00005 //                                                                      //
00006 // Implement complex numbers in ROOT                                    //
00007 //                                                                      //
00009 
00010 #ifndef LITR_TComplex
00011 #define LITR_TComplex
00012 
00013 
00014 #undef   TCOMPLEX_USE_RTYPES_MACROS
00015 #define  TCOMPLEX_USE_DOUBLE
00016 
00017 #ifdef TCOMPLEX_USE_DOUBLE
00018 # define TComplexBase  Double_t
00019 #else
00020 # define TComplexBase  Real_t
00021 #endif
00022 
00023 #include <Riostream.h>
00024 #include <TBuffer.h>
00025 #include <TMath.h>
00026 
00027 class TCplxRhoPhi {
00028 protected:
00029 
00030   Double_t fRho;    //module of complex number
00031   Double_t fPhi;    //phase of complex number
00032 public:
00033   TCplxRhoPhi(Double_t x,Double_t y) { fRho = TMath::Sqrt(x*x+y*y);
00034                                        fPhi = atan2(y,x); }
00035   Double_t GetRho() { return fRho; }
00036   Double_t GetPhi() { return fPhi; }
00037   void Sqrt() { fRho = TMath::Sqrt(fRho); fPhi = fPhi/2.0; }
00038 };
00039 
00040 class TComplex {
00041 
00042 protected:
00043   friend TComplex operator + (const Double_t,const TComplex&);
00044   friend TComplex operator - (const Double_t,const TComplex&);
00045   friend TComplex operator * (const Int_t,const TComplex&);
00046   friend TComplex operator * (const Double_t,const TComplex&);
00047   friend TComplex operator * (const TComplex&,const TComplex&);
00048   friend TComplex operator * (TComplex&, TComplex&);
00049   friend TComplex operator % (const TComplex&,const TComplex&);
00050   friend TComplex operator / (const Double_t,const TComplex&);
00051   friend Bool_t   operator == (const TComplex&, const TComplex&);
00052   friend Bool_t   operator != (const TComplex&, const TComplex&);
00053   friend Bool_t   operator == (const TComplex&, const Double_t&);
00054   friend Bool_t   operator != (const TComplex&, const Double_t&);
00055   friend Double_t Abs(const TComplex&);
00056   friend Double_t Abs2(const TComplex&);
00057   friend TComplex Sqrt(const TComplex&);
00058   friend TComplex Sqrt3(const TComplex&, Int_t);
00059   friend TComplex Exp(const TComplex&);
00060   friend TComplex Log(const TComplex&);
00061   friend TComplex Log10(const TComplex&);
00062   friend TComplex Log2(const TComplex&);
00063   friend TComplex Sin(const TComplex&);
00064   friend TComplex Cos(const TComplex&);
00065   friend TComplex Power(const TComplex &z,Int_t n) { return Exp(n*Log(z)); }
00066   friend TComplex Power(const TComplex &z,Double_t x) { return Exp(x*Log(z)); }
00067   friend Double_t Phase(TComplex  z) { return TMath::ATan2(z.fIm,z.fRe);};
00068   friend istream &operator>>(istream&,TComplex&);
00069   friend ostream &operator<<(ostream&,TComplex&);
00070 
00071 public:
00072 
00073   TComplexBase fRe;     //real part
00074   TComplexBase fIm;     //imaginary part
00075   TComplex() { fRe=0.0; fIm =0.0; }
00076   TComplex(Double_t x,Double_t y=0) { fRe = x; fIm=y; }
00077   TComplex(const TComplex &z) { fRe = z.fRe; fIm = z.fIm; }
00078   Double_t Re()  const  { return fRe; }
00079   Double_t Im()  const  { return fIm; }
00080   Double_t Phase() { return TMath::ATan2(fIm,fRe);};
00081   void Set(Double_t x,Double_t y) { fRe = x; fIm = y; }
00082   void SetReal(Double_t x) { fRe = x; }
00083   void SetIm(Double_t y)   { fIm = y; }
00084   void C()                 { fIm = - fIm; }
00085   void PureReal()          { fIm = 0.0; }
00086   void PureIm()            { fRe = 0.0; }
00087   void SetNeg()            { fRe = -fRe; fIm = -fIm; }
00088   void Dump();
00089 
00090   operator Bool_t() { return fRe||fIm; };
00091   operator Double_t() { return fRe;};
00092   operator Int_t() { return Int_t(fRe);};
00093   
00094   
00096 
00097   Bool_t    operator!() { return (!fRe)&&(!fIm);};
00098   Bool_t    operator&&(TComplex &z) {
00099     return Bool_t()&&Bool_t(z);
00100   }
00101 
00102   TComplex  operator+(const TComplex& z) {
00103     //+ with other complex number
00104     TComplex z4;
00105     z4.fRe = fRe + z.fRe;
00106     z4.fIm = fIm + z.fIm;
00107     return z4;
00108   }
00109 
00110   TComplex  operator+(const Double_t x) {
00111     TComplex z4;
00112     z4.fRe = fRe + x;
00113     z4.fIm = fIm;
00114     return z4;
00115   }
00116   TComplex  operator+(const Int_t x) {
00117     TComplex z4;
00118     z4.fRe = fRe + x;
00119     z4.fIm = fIm;
00120     return z4;
00121   }
00123 
00124   TComplex operator -() {
00125     TComplex z;
00126     z.fRe = -fRe;
00127     z.fIm  = -fIm;
00128     return z;
00129   }
00130 
00131   TComplex  operator-(const TComplex& z) {
00132     //+ with other complex number
00133     TComplex z4;
00134     z4.fRe = fRe - z.fRe;
00135     z4.fIm = fIm - z.fIm;
00136     return z4;
00137   }
00138   
00139   TComplex  operator-(const Double_t x) {
00140     //- with other complex number
00141     TComplex z4;
00142     z4.fRe = fRe - x;
00143     z4.fIm = fIm;
00144     return z4;
00145   }
00146   TComplex  operator-(const Int_t x) {
00147     //- with other complex number
00148     TComplex z4;
00149     z4.fRe = fRe - x;
00150     z4.fIm = fIm;
00151     return z4;
00152   }
00153 
00155 
00156 
00157 
00159 
00160   TComplex& operator=(const TComplex &z) {
00161     //defines = for complex
00162     if (this != &z) {
00163       fRe = z.fRe;
00164       fIm = z.fIm;
00165     }
00166     return *this;
00167   }
00168   TComplex& operator=(const Double_t x) {
00169     //defines = for complex
00170     fRe = x;
00171     fIm = 0.0;
00172     return *this;
00173   }
00174 
00176   
00177   TComplex& operator+=(const Double_t& x) {
00178     fRe += x;
00179     return *this;
00180   }
00181   TComplex& operator+=(const TComplex& z) {
00182     //Add itself with a complex numbers
00183     fRe += z.fRe;
00184     fIm += z.fIm;
00185     return *this;
00186   }
00187 
00188   TComplex& operator-=(const Double_t& x) {
00189     fRe -= x;
00190     return *this;
00191   }
00192   TComplex& operator-=(const TComplex& z) {
00193     //Add itself with a complex numbers
00194     fRe -= z.fRe;
00195     fIm -= z.fIm;
00196     return *this;
00197   }
00198 
00200 
00201   TComplex& operator/=(const Double_t& x) {
00202     fRe /= x;
00203     fIm /= x;
00204     return *this;
00205   }
00206   
00207   TComplex& operator/=(const TComplex& z) {
00208     Double_t tmp,d;
00209     d = z.fRe*z.fRe + z.fIm*z.fIm;
00210     tmp = (fRe*z.fRe + fIm*z.fIm)/d;
00211     fIm = (fIm*z.fRe - fRe*z.fIm)/d;
00212     fRe = tmp;
00213     
00214     return *this;
00215   }
00216   
00218   
00219   TComplex& operator*=(const Double_t & x) {
00220     //Multiply itself with a float numbers
00221     fIm *=x;
00222     fRe *=x;
00223     return *this;
00224   }
00225 
00226   TComplex& operator*=(const TComplex& z) {
00227     //Multiply itself with a complex numbers
00228     register Double_t tmp =  fRe*z.fRe - fIm*z.fIm;
00229     fIm = fRe*z.fIm + fIm*z.fRe;
00230     fRe = tmp;
00231     return *this;
00232   }
00233 
00234 
00236   
00237   
00238   void FromRhoPhi(TCplxRhoPhi &r) {
00239     //returns from phase representation
00240     register Double_t rho;
00241     register Double_t phi;
00242     rho = r.GetRho();
00243     phi = r.GetPhi();
00244     fRe = rho*TMath::Cos(phi);
00245     fIm = rho*TMath::Sin(phi);
00246   }
00247   Bool_t IsComplex(Double_t limreal) {
00248     //if the abs. value of the imaginary part is smaller than limreal, make the
00249     //number real and returns kFALSE else returns kTRUE.
00250     const Double_t zero = 0.0;
00251     Bool_t cplx = kTRUE;
00252     if (TMath::Abs(fIm)<TMath::Abs(limreal)) {
00253       fIm = zero;
00254       cplx = kFALSE;
00255     }
00256     return cplx;
00257   }
00258   void BetterConj(TComplex &z2) {
00259     //Make this and z2 better complex conjugate
00260     const Double_t deux = 2.0;
00261     Double_t a,b;
00262     a = (fRe + z2.fRe)/deux;
00263     b = (fIm - z2.fIm)/deux;
00264     z2.fRe =  a;
00265     z2.fIm = -b;
00266     fRe    = a;
00267     fIm    = b;
00268   }
00269   void CosFromSin() {
00270     //  Given a complex number representing the sinus of a complex angle, returns
00271     //the complex value of the cosinus of the same complex angle. The value chosen
00272     //is the one with a positive real part, if the imaginary part is 0.
00273     //If the imaginary part is non-zero, the value chosen is the one with a
00274     //negative imaginary part. THE IMAGINARY PART OF THE RESULT IS ALWAYS CHOSEN
00275     //NEGATIVE IF IT IS NON-ZERO. This is an arbitrary choice motivated by the
00276     //fact that in Litrani, the phases of waves have to be negative when a wave
00277     //is absorbed, never positive which would correspond to an unphysical explosion
00278     //of the wave.
00279     const Double_t zero   = 0.0;
00280     const Double_t un     = 1.0;
00281     const Double_t vsmall = 1.0e-12;
00282     TComplex z;
00283     z = *this;z*=z;
00284     z = Sqrt(un - z);
00285     if (z.fIm>vsmall) z = zero - z;
00286     if (TMath::Abs(z.fIm)<=vsmall) z.fIm = zero;
00287     *this = z;
00288   }
00289   void RPhi(Double_t &r, Double_t &phi) {
00290     //  Calculates module (with sign !) and phase of a complex number.
00291     //If the real part of the complex number is negativ, returns a negative module.
00292     //Advantage : in case of a negative real number, the module stays negative and
00293     //the phase 0. A negative real number is not considered as a non-real, complex
00294     //number with a phase of pi.
00295     const Double_t zero   = 0.0;
00296     const Double_t wsmall = 1.0e-300;
00297     Double_t axr,axi;
00298     axr = TMath::Abs(fRe);
00299     axi = TMath::Abs(fIm);
00300     if ((axr<wsmall) && (axi<wsmall)) {
00301       r   = zero;
00302       phi = zero;
00303     }
00304     else {
00305       r   = TMath::Sqrt(fRe*fRe+fIm*fIm);
00306       if (fRe<zero) r = -r;
00307       if (axi<wsmall) {
00308     phi = zero;
00309       }
00310       else {
00311     phi = atan2(fIm,fRe);
00312     if (fRe<zero) {
00313       if (fIm>=zero) phi = phi - TMath::Pi();
00314       else phi = phi + TMath::Pi();
00315     }
00316       }
00317     }
00318   }
00319   
00320   TComplex operator*(const Double_t x) {
00321     TComplex z4;
00322     z4.fRe = fRe*x;
00323     z4.fIm = fIm*x;
00324     return z4;
00325   }
00326   TComplex operator*(const Int_t x) {
00327     TComplex z4;
00328     Double_t xx = x;
00329     z4.fRe = fRe*xx;
00330     z4.fIm = fIm*xx;
00331     return z4;
00332   }
00333 
00334   TComplex operator/(const TComplex &z) {
00335     //division with other complex number
00336     TComplex z4;
00337     Double_t d;
00338     d = z.fRe*z.fRe + z.fIm*z.fIm;
00339     z4.fRe = (fRe*z.fRe + fIm*z.fIm)/d;
00340     z4.fIm = (fIm*z.fRe - fRe*z.fIm)/d;
00341     return z4;
00342   }
00343   TComplex operator/(const Double_t x) {
00344     //division with other complex number
00345     TComplex z4;
00346     z4.fRe = fRe/x;
00347     z4.fIm = fIm/x;
00348     return z4;
00349   }
00350   TComplex operator/(const Int_t x) {
00351     //division with other complex number
00352     TComplex z4;
00353     Double_t xx = x;
00354     z4.fRe = fRe/xx;
00355     z4.fIm = fIm/xx;
00356     return z4;
00357   }
00358 
00359 
00360 
00361   void Print();
00362   void Test(Double_t,const TComplex&);
00363 
00364 #ifdef TCOMPLEX_USE_RTYPES_MACROS
00365   
00366   // The is the standard version using Rtypes.h-Macro
00367   //
00368   // ==> this results in a sizeof(TComplex)==20
00369 
00370   ClassDef(TComplex,0)
00371     
00372 #else
00373 
00374   // This Part I got from $(ROOTSYS)/include/Rtypes.h
00375   // and it correspond to the ClassDef-Macro. But because
00376   // we do not want to inherits from this base type
00377   //
00378   // ==> this results in a sizeof(TComplex)==16
00379 
00380  private: 
00381   static TClass *fgIsA; 
00382  public: 
00383   static TClass *Class(); 
00384   static const char *Class_Name(); 
00385   static Version_t Class_Version() { return 0; } 
00386   static void Dictionary(); 
00387   TClass *IsA() const { return TComplex::Class(); } 
00388   void ShowMembers(TMemberInspector &insp, char *parent); 
00389   void Streamer(TBuffer &b); 
00390   void StreamerNVirtual(TBuffer &b) { TComplex::Streamer(b); } 
00391   static const char *DeclFileName() { return __FILE__; } 
00392   static int DeclFileLine() { return __LINE__; } 
00393   static const char *ImplFileName(); 
00394 
00395 # if !defined(R__ACCESS_IN_SYMBOL) || defined(__CINT__)
00396   
00397   friend void ROOT__ShowMembersFunc(TComplex *obj, TMemberInspector &R__insp, 
00398                     char *R__parent); 
00399   
00400 # endif
00401   static int ImplFileLine();
00402 
00403 #endif
00404 
00405 };
00406 
00407 // Global Functions
00408 
00409 inline Double_t Dist(TComplex& z1, TComplex& z2) {
00410   return Abs(z1-z2);
00411 }
00412 
00413 inline TComplex operator + (const Double_t x, const TComplex &z) {
00414 //addition of a real and a complex
00415   return TComplex(x + z.fRe,z.fIm);
00416 }
00417 
00418 inline TComplex operator - (const Double_t x, const TComplex &z) {
00419 //substraction of a complex from a real
00420   return TComplex(x - z.fRe,-z.fIm);
00421 }
00422 inline TComplex operator * (const Int_t x, const TComplex &z) {
00423 //multiplication of a real by a complex
00424   return TComplex(x*z.fRe,x*z.fIm);
00425 }
00426 inline TComplex operator * (const Double_t x, const TComplex &z) {
00427 //multiplication of a real by a complex
00428   return TComplex(x*z.fRe,x*z.fIm);
00429 }
00430 inline TComplex operator * (const TComplex &x, const TComplex &y) {
00431 //multiplication of a complex by a complex
00432   return TComplex(x.fRe*y.fRe - x.fIm*y.fIm,x.fRe*y.fIm + x.fIm*y.fRe);
00433 }
00434 inline TComplex operator * (TComplex &x, TComplex &y) {
00435 //multiplication of a complex by a complex
00436   return TComplex(x.fRe*y.fRe - x.fIm*y.fIm,x.fRe*y.fIm + x.fIm*y.fRe);
00437 }
00438 inline TComplex operator % (const TComplex &x, const TComplex &y) {
00439 //multiplication of a complex-transposed by a complex
00440   return TComplex(x.fRe*y.fRe + x.fIm*y.fIm,x.fRe*y.fIm - x.fIm*y.fRe);
00441 }
00442 inline TComplex operator / (const Double_t x, const TComplex &z) {
00443 //division of a real by a complex
00444   TComplex z4;
00445   Double_t d;
00446   d = z.fRe*z.fRe + z.fIm*z.fIm;
00447   z4.fRe =  (x*z.fRe)/d;
00448   z4.fIm = -(x*z.fIm)/d;
00449   return z4;
00450 }
00451 
00452 inline Bool_t operator ==(const TComplex &z1, const TComplex &z2) {
00453   return ((z1.fRe==z2.fRe)&&(z1.fIm==z2.fIm));
00454 }
00455 
00456 inline Bool_t operator !=(const TComplex &z1, const TComplex &z2) {
00457   return ((z1.fRe!=z2.fRe)||(z1.fIm!=z2.fIm));
00458 }
00459 inline Bool_t operator ==(const TComplex &z1, const Double_t &d) {
00460   return ((z1.fRe==d)&&(z1.fIm==0.0));
00461 }
00462 
00463 inline Bool_t operator !=(const TComplex &z1, const Double_t &d) {
00464   return ((z1.fRe!=d)||(z1.fIm!=0.0));
00465 }
00466 inline Double_t Abs(const TComplex &z) {
00467 //Calculates the absolute value of a complex number
00468   return TMath::Sqrt(Abs2(z));
00469 }
00470 inline Double_t Abs2(const TComplex &z) {
00471 //Calculates the absolute value of a complex number
00472   return z.fRe*z.fRe + z.fIm*z.fIm;
00473 }
00474 
00475 inline TComplex Sqrt(const TComplex &z) {
00476 //Calculates the square root of a complex number
00477   const Double_t zero = 0.0;
00478   TComplex zz;
00479   if (z.fRe >= zero) {
00480     TCplxRhoPhi r(z.fRe,z.fIm);
00481     r.Sqrt();
00482     zz.FromRhoPhi(r);
00483   }
00484   else {
00485     TCplxRhoPhi r(-z.fRe,-z.fIm);
00486     r.Sqrt();
00487     zz.FromRhoPhi(r);
00488     TComplex j(0,1);
00489     //zz = zz*j;
00490     zz*=j;
00491   }
00492   return zz;
00493 }
00494 
00495 inline TComplex Sqrt3(const TComplex &z,Int_t k) {
00496 //
00497 //  Calculates the cubic root of a complex number.
00498 //  If the real part is negative, calculates the cubic root of minus the complex
00499 //number and then changes the sign of the solution.
00500 //  There are 3 possible solutions. k decides which one is taken :
00501 //    - k = 0  ==>  phi --> phi/3
00502 //    - k = 1  ==>  phi --> (phi+2pi)/3
00503 //    - k = 2  ==>  phi --> (phi-2pi)/3
00504 //
00505   const Double_t zero   = 0.0;
00506   const Double_t deux   = 2.0;
00507   const Double_t trois  = 3.0;
00508   const Double_t small  = 1.0e-7;
00509   const Double_t wsmall = 1.0e-300;
00510   Double_t rho,phi;
00511   Bool_t isreal,isneg;
00512   TComplex z1,zz;
00513   isreal = (TMath::Abs(z.fIm)<wsmall);
00514   isneg  = (z.fRe<zero);
00515   if (isneg) z1 = zero - z;
00516   else       z1 = z;
00517   k      = k % 3;
00518   TCplxRhoPhi r(z1.fRe,z1.fIm);
00519   rho = r.GetRho();
00520   phi = r.GetPhi();
00521   rho = TMath::Exp(TMath::Log(rho)/trois);
00522   switch (k) {
00523   case 0:
00524     phi = phi/trois;
00525     break;
00526   case 1:
00527     phi = (phi + deux*TMath::Pi())/trois;
00528     break;
00529   case 2:
00530     phi = (phi - deux*TMath::Pi())/trois;
00531     break;
00532   }
00533   zz.fRe = rho*TMath::Cos(phi);
00534   zz.fIm = rho*TMath::Sin(phi);
00535   if (isreal && (TMath::Abs(zz.fIm)<small)) zz.fIm = zero;
00536   if (isneg) zz = zero - zz;
00537   return zz;
00538 }
00539 
00540 inline TComplex Exp(const TComplex &z) {
00541 //Calculates the exponential of a complex number
00542   register Double_t ex;
00543   TComplex zz;
00544   ex = TMath::Exp(z.fRe);
00545   zz.fRe = ex*TMath::Cos(z.fIm);
00546   zz.fIm = ex*TMath::Sin(z.fIm);
00547   return zz;
00548 }
00549 
00550 inline TComplex Log(const TComplex &z) {
00551 //Calculates the logarithm of a complex number
00552   TComplex zz;
00553   TCplxRhoPhi r(z.fRe,z.fIm);
00554   zz.fRe = TMath::Log(r.GetRho());
00555   zz.fIm = r.GetPhi();
00556   return zz;
00557 }
00558 inline TComplex Log2(const TComplex &z) {
00559 //Calculates the logarithm of a complex number
00560   TComplex zz;
00561   TCplxRhoPhi r(z.fRe,z.fIm);
00562   zz.fRe = TMath::Log2(r.GetRho());
00563   zz.fIm = r.GetPhi();
00564   return zz;
00565 }
00566 inline TComplex Log10(const TComplex &z) {
00567 //Calculates the logarithm of a complex number
00568   TComplex zz;
00569   TCplxRhoPhi r(z.fRe,z.fIm);
00570   zz.fRe = TMath::Log10(r.GetRho());
00571   zz.fIm = r.GetPhi();
00572   return zz;
00573 }
00574 
00575 inline TComplex Sin(const TComplex &z) {
00576 //Calculates the sinus of a complex number
00577   const Double_t un   = 1.0;
00578   const Double_t deux = 2.0;
00579   TComplex zz;
00580   Double_t a,b;
00581   a = TMath::Exp(z.fIm);
00582   b = un/a;
00583   zz.fRe = ((a+b)*TMath::Sin(z.fRe))/deux;
00584   zz.fIm = ((a-b)*TMath::Cos(z.fRe))/deux;
00585   return zz;
00586 }
00587 
00588 inline TComplex Cos(const TComplex &z) {
00589 //Calculates the cosinus of a complex number
00590   const Double_t un   = 1.0;
00591   const Double_t deux = 2.0;
00592   TComplex zz;
00593   Double_t a,b;
00594   a = TMath::Exp(z.fIm);
00595   b = un/a;
00596   zz.fRe = ((a+b)*TMath::Cos(z.fRe))/deux;
00597   zz.fIm = ((b-a)*TMath::Sin(z.fRe))/deux;
00598   return zz;
00599 }
00600 
00601 
00602 extern       TComplex ComplexZero;
00603 extern       TComplex ComplexOne;
00604 extern       TComplex I;
00605 #endif

Generated on Fri Apr 23 16:23:43 2004 by doxygen 1.3.2