Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

complex.h

Go to the documentation of this file.
00001 // 
00002 // author="Tony Kirke" *
00003 // Copyright(c) 1993-1996 Tony Kirke
00004 /*
00005  * SPUC - Signal processing using C++ - A DSP library
00006  * 
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 #ifndef CMPLX_D
00022 #define CMPLX_D
00023 #include <cstdlib>
00024 #include <spuc.h>
00025 #include <cmath>
00026 namespace SPUC {
00029 template <class T> class complex
00030 {
00031   public:
00032   T re;
00033   T im;
00034 
00035   complex()
00036   {
00037     re = 0;
00038     im = 0;
00039   }
00040   void*  operator new (size_t) {
00041           T* re = new T;
00042           T* im = new T;
00043   }
00044   complex(T r, T i) :re(r), im(i) {}
00045   complex(T r) : re(r), im(0) {}
00046 //  template <> complex(const complex<long>& y) : re(y.re), im(y.im) {;}
00047 
00048   inline T real() { return(re);};
00049   inline T imag() { return(im);};
00050 
00051   friend T real( complex<T> y ) { return(y.re);}
00052   friend T imag( complex<T> y ) { return(y.im);}
00053 
00054   inline T operator=(T r)
00055   {
00056     re = r;
00057     im = 0;
00058     return r;
00059   }
00060 
00061   inline complex  operator =(const complex<T>& y)   {   
00062           re = (T)y.re; im = (T)y.im; return *this; 
00063   } 
00064   inline complex  operator *=(const complex<T>& y) {
00065           T r = re*y.re - im*y.im;
00066           im  = re*y.im + im*y.re;
00067           re = r;
00068           return *this;
00069   }
00070   inline complex  operator +=(const complex<T>& y) {
00071           re += y.re;
00072           im += y.im;
00073           return *this;
00074   }
00075   inline complex  operator -=(const complex<T>& y) {
00076           re -= y.re;
00077           im -= y.im;
00078           return *this;
00079   }
00080 
00081 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00082   operator const complex<long> () const {         return(complex<long>((long)re,(long)im));  }
00083 #endif
00084 };
00085 
00086 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00087 
00088 template <class T1, class T2> inline complex<T1> operator *(complex<T1> r, complex<T2> l)
00089 {
00090   complex<T1> x;
00091   x.re = ((r.re*l.re) - (r.im*l.im));
00092   x.im = (r.re*l.im + r.im*l.re);
00093   return x;  
00094   };
00096 template <class T1, class T2> inline complex<T1> operator +(complex<T1> r, complex<T2> l)
00097 {
00098   complex<T1> x;
00099   x.re = r.re + l.re;
00100   x.im = r.im + l.im;
00101   return x;  
00102 };
00104 template <class T> inline complex<T> operator +(complex<T> r, T l)
00105 {
00106   complex<T> x;
00107   x.re = r.re + l;
00108   x.im = r.im;
00109   return x;  
00110 };
00112 template <class T> inline complex<T> operator +(T r, complex<T> l)
00113 {
00114   complex<T> x;
00115   x.re = r + l.re;
00116   x.im = l.im;
00117   return x;  
00118 };
00119 
00121 template <class T1, class T2> inline complex<T1> operator -(complex<T1> r, complex<T2> l)
00122 {
00123   complex<T1> x;
00124   x.re = r.re - l.re;
00125   x.im = r.im - l.im;
00126   return x;  
00127 };
00129 template <class T> inline complex<T> operator -(complex<T> r, T l)
00130 {
00131   complex<T> x;
00132   x.re = r.re - l;
00133   x.im = r.im;
00134   return x;  
00135 };
00137 template <class T> inline complex<T> operator -(T r, complex<T> l)
00138 {
00139   complex<T> x;
00140   x.re = r - l.re;
00141   x.im = -l.im;
00142   return x;  
00143 };
00145 template <class T> inline complex<T> operator &(complex<T> r, T l)
00146 {
00147   complex<T> x;
00148   x.re = r.re & l;
00149   x.im = r.im & l;
00150   return x;  
00151 };
00153 template <class T> inline complex<T> operator &(T r, complex<T> l)
00154 {
00155   complex<T> x;
00156   x.re = r & l.re;
00157   x.im = r & l.im;
00158   return x;  
00159 };
00160 template <class T> inline complex<T> operator %(complex<T> r, T l)
00161 {
00162   complex<T> x;
00163   x.re = r.re % l;
00164   x.im = r.im % l;
00165   return x;  
00166 };
00168 template <class T> inline complex<T> operator ^(complex<T> r, T l)
00169 {
00170   complex<T> x;
00171   x.re = r.re ^ l;
00172   x.im = r.im ^ l;
00173   return x;  
00174 };
00176 template <class T> inline complex<T> operator ^(T r, complex<T> l)
00177 {
00178   complex<T> x;
00179   x.re = r ^ l.re;
00180   x.im = r ^ l.im;
00181   return x;  
00182 };
00183 template <class T> inline complex<T> operator |(complex<T> r, T l)
00184 {
00185   complex<T> x;
00186   x.re = r.re | l;
00187   x.im = r.im | l;
00188   return x;  
00189 };
00191 template <class T> inline complex<T> operator |(T r, complex<T> l)
00192 {
00193   complex<T> x;
00194   x.re = r | l.re;
00195   x.im = r | l.im;
00196   return x;  
00197 };
00198 
00200 template <class T> inline complex<T>  operator <<(complex<T> r, const long shift) 
00201 {
00202           complex<long> res = complex<long>(r.re << shift, r.im << shift);
00203           return(res);
00204 }
00206 template <class T> inline complex<T>  operator >>(complex<T> r, const long shift) 
00207 {
00208           complex<long> res = complex<long>(r.re >> shift, r.im >> shift);
00209           return(res);
00210 }
00212 template <class T> inline complex<T> operator -(complex<T> r)
00213 {
00214   complex<T> x;
00215   x.re = -r.re;
00216   x.im = -r.im;
00217   return x;  
00218 };
00219 
00220 
00221 
00222 
00224 inline complex<long> operator *( double r, complex<long> l)
00225 {
00226         return(complex<long>((long)floor((double)(r*l.re+0.5)),
00227                                                  (long)floor((double)(r*l.im+0.5))));
00228 
00229 };
00231 inline complex<double> operator *( long r, complex<double> l)
00232 {
00233   complex<double> x;
00234   x.re = (r*l.re);
00235   x.im = (r*l.im);
00236   return x;   
00237 };
00239 inline complex<double> operator *( double r, complex<double> l)
00240 {
00241   complex<double> x;
00242   x.re = (r*l.re);
00243   x.im = (r*l.im);
00244   return x;   
00245 };
00246 
00248 template <class T> inline complex<T> operator *(complex<T> r, T l)
00249 {
00250   complex<T> x;
00251   x.re = r.re*l;
00252   x.im = r.im*l;
00253   return x;  
00254 };
00255 
00257 template <class T> complex<T> operator /(complex<T> l, T r)
00258 {
00259   complex<T> x(0,0);
00260   if (r != 0)
00261   {
00262     x.re = l.re/r;
00263     x.im = l.im/r;
00264   }
00266   return x;  
00267 };
00268 
00270 template <class T1, class T2> complex<T1> operator /(complex<T1> r, complex<T2> l)
00271 {
00272   complex<T1> x;
00273   T2 den;
00274   den = magsq(l);
00275   x = (r * conj(l))/den;
00276   return x;  
00277 };
00278 
00280 template <class T1, class T2> inline bool operator ==(complex<T1> r, complex<T2> l)
00281 {
00282   return ((r.re == l.re) && (r.im == l.im));  
00283 };
00284 
00286 template <class T1, class T2> inline bool operator !=(complex<T1> r, complex<T2> l)
00287 {
00288   return ((r.re != l.re) || (r.im != l.im));  
00289 };
00290 
00292 inline complex<double> expj(double x)
00293 {
00294   complex<double> y;
00295   y.re = cos(x);
00296   y.im = sin(x);
00297   return y;
00298 }
00300 inline complex<double> polar(double amp,double arg)
00301 {
00302   complex<double> y;
00303   y.re = amp*cos(arg);
00304   y.im = amp*sin(arg);
00305   return y;
00306 }
00307 
00309 template <class T> inline complex<T> complexj(void)
00310 {
00311   return(complex<T>(0,1));
00312 }
00313 
00314 template <class T> inline T re(complex<T> x)
00315 {
00316   T y;
00317   y = x.re;
00318   return y;
00319 };
00320 
00321 template <class T> inline T im(complex<T> x)
00322 {
00323   T y;
00324   y = x.im;
00325   return y;
00326 };
00327 
00329 template <class T> inline complex<T> conj(complex<T> x)
00330 {
00331   complex<T> y;
00332   y.re = x.re;
00333   y.im = -x.im;
00334   return y;
00335 }
00337 template <class T> inline T magsq(complex<T> x)
00338 {
00339   T y;
00340   y = (x.re*x.re + x.im*x.im);
00341   return y;
00342 };
00344 template <class T> inline complex<double> norm(complex<T> x)
00345 {
00346   T y;
00347   y = ::sqrt(x.re*x.re + x.im*x.im);
00348   return (complex<double>(x.re/y,x.im/y));
00349 };
00350 
00351 
00352 template <class T> inline T approx_mag(complex<T> x)
00353 {
00354   return(MAX(abs(x.re),abs(x.im)) + MIN(abs(x.re),abs(x.im))/4);
00355 };
00356 
00357 template <class T> inline complex<T> maxvalue(complex<T> x1)
00358 {
00359   return(complex<T>(MAX(x1.re,x1.im)));
00360 };
00361 
00362 template <class T> inline complex<T> minimum(complex<T> x1, complex<T> x2)
00363 {
00364   return(complex<T>(MIN(x1.re,x2.re),MIN(x1.im,x2.im)));
00365 }
00366 template <class T> inline complex<T> maximum(complex<T> x1, complex<T> x2)
00367 {
00368   return(complex<T>(MAX(x1.re,x2.re),MAX(x1.im,x2.im)));
00369 };
00371 template <class T> inline double arg(const complex<T> x)
00372 {
00373   double TMPANG;
00374   if (real(x) == 0) {
00375      if (imag(x) < 0) return(3.0*PI/2.0);
00376      else return(PI/2.0);
00377   } else {
00378         TMPANG=atan((double)imag(x)/(double)real(x));
00379         if (real(x) < 0) TMPANG -= PI;
00380         if (TMPANG < 0) TMPANG += TWOPI;
00381   }
00382   return(TMPANG);
00383 }
00385 template <class T> inline complex<double> rational(complex<T> l) {
00386   return(complex<double>((double)l.re,(double)l.im));
00387 }
00388 
00390 inline complex<long> round(complex<long> in, long bits)
00391 {
00392   double scale = 1.0/(double)(1 << bits);
00393   return(complex<long>((long)floor((double)(scale*in.re)+0.5),
00394                      (long)floor((double)(scale*in.im)+0.5)));
00395 }
00397 inline complex<long> saturate(complex<long> in, long bits)
00398 {
00399   complex<long> out;
00400   long low_mask = ((1<<(bits-1)) - 1);
00401   if (labs(in.re) > low_mask) out.re = (in.re>0) ? low_mask : ~low_mask;
00402   else out.re = in.re;
00403   if (labs(in.im) > low_mask) out.im = (in.im>0) ? low_mask : ~low_mask;
00404   else out.im = in.im;
00405   return(out);
00406 }
00407 template <class T> complex<T> signbit(complex<T> in)
00408 {
00409   return(complex<T>(SGN(in.re),SGN(in.im)));
00410 }
00411 
00412 //template <class T> T real(complex<T>& y) {  return(y.re);}
00413 //template <class T> T imag(complex<T>& y) {  return(y.im);}
00414 
00415 template <class T> inline complex<double> reciprocal(complex<T> x)
00416 {
00417   T y;
00418   y = (x.re*x.re + x.im*x.im);
00419   return (complex<double>(x.re/y,-x.im/y));
00420 };
00422 template <class T> inline complex<T> sqr(complex<T> x)
00423 {
00424   return (x*x);
00425 };
00427 template <class T> inline complex<double> csqrt(complex<T> x)
00428 {
00429   double mag = sqrt(sqrt(magsq(x)));
00430   double ang = 0.5*arg(x); // ambiguity
00431   return(polar(mag,ang));
00432 };
00434 inline complex<double> exp(complex<double> x)
00435   { 
00436           return (::exp(x.real()) * expj(x.imag()));
00437   }
00439 inline double hypot(complex<double> z) { 
00440         double _hypot(double x, double y);
00441         return _hypot(z.imag(), z.real()); }
00442 #endif
00443 } // namespace SPUC 
00444 #endif

Generated on Fri Sep 16 11:02:26 2005 for spuc by  doxygen 1.4.4