LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiComplex.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /* -------------------------------------------------------------------
00025  * project ....: LTI-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiComplex.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 6.4.2003
00030  * revisions ..: $Id: ltiComplex.h,v 1.8 2006/02/08 12:14:30 ltilib Exp $
00031  */
00032 
00033 /**
00034  * \file ltiComplex.h
00035  * The standard \c complex header provide by the different compilers and 
00036  * library versions different functionality.  For the LTI-Lib this file
00037  * provides a unified implementation.
00038  */
00039 
00040 #ifndef _LTI_COMPLEX_H
00041 #define _LTI_COMPLEX_H
00042 
00043 #ifdef _LTI_MSC_6
00044 #pragma warning(disable:4275) // warnings for complex<T> 
00045                               // disabled (dll stuff in 
00046                               // MS implementation)
00047 #endif
00048 
00049 #include "ltiMath.h"
00050 #include <complex>
00051 #include <iostream>
00052 
00053 #ifdef _LTI_GNUC_2
00054 namespace std {
00055   typedef ios ios_base;
00056 }
00057 #endif
00058 
00059 namespace lti {    
00060   /**
00061    * Class to represent and manipulate complex numbers.
00062    *
00063    * The complex numbers contain a real and an imaginary part, which can
00064    * be accessed through the methods real() and imag().
00065    *
00066    * The interface of this class is similar to the one provided by the
00067    * Standard C++ library.  It has being included in the LTI-Lib because 
00068    * different library versions do not provide the same functionality.
00069    *
00070    * Note that many of the provided mathematical operations make only
00071    * sense if the type used for the components of the complex number
00072    * is double or float.
00073    */
00074   template<typename T>
00075   class complex {
00076   public:
00077     typedef T value_type;
00078     
00079     /**
00080      * default constructor.
00081      */
00082     complex(const T& = T(), const T & = T());
00083     
00084     /**
00085      * copy constructor
00086      */
00087     template<class U>
00088     complex(const complex<U>& other) 
00089       : realPart(static_cast<T>(other.realPart)),
00090         imagPart(static_cast<T>(other.imagPart)) {  
00091     }
00092     
00093     /**
00094      * cast a std::complex to an lti::complex of the same type
00095      */
00096     complex(const std::complex<T>& other);
00097 
00098     /**
00099      * cast a lti::complex into a std::complex of the same type
00100      */
00101     operator std::complex<T>() {
00102       return std::complex<T>(real(),imag());
00103     }
00104 
00105     /**
00106      * return the real component of the complex number
00107      */
00108     T real() const;
00109     
00110     /**
00111      * return the imaginary component of the complex number
00112      */
00113     T imag() const;
00114     
00115     /**
00116      * copy a real number into this complex one, making the imaginary part
00117      * zero.
00118      */
00119     complex<T>& operator=(const T& other);
00120     
00121     /**
00122      * add a real number to this complex one.
00123      */     
00124     complex<T>& operator+=(const T& other);
00125     
00126     /**
00127      * subtract a real number to this complex one.
00128      */     
00129     complex<T>& operator-=(const T& other);
00130     
00131     /**
00132      * multiply this complex number with a real one.
00133      */     
00134     complex<T>& operator*=(const T& other);
00135     
00136     /**
00137      * divide this complex number by a real one.
00138      */     
00139     complex<T>& operator/=(const T& other);
00140     
00141     /**
00142      * copy another complex number into this one
00143      */
00144     template<typename U>
00145     complex<T>& operator=(const complex<U>& other) {
00146       realPart = other.realPart;
00147       imagPart = other.imagPart;
00148       return (*this);
00149     };
00150     
00151     /**
00152      * add another complex number
00153      */
00154     template<typename U>
00155     complex<T>& operator+=(const complex<U>& other) {
00156       realPart+=static_cast<T>(other.realPart);
00157       imagPart+=static_cast<T>(other.imagPart);
00158       return (*this);
00159     }
00160     
00161     /**
00162      * subtract another complex number
00163      */
00164     template<typename U>
00165     complex<T>& operator-=(const complex<U>& other) {
00166       realPart-=static_cast<T>(other.realPart);
00167       imagPart-=static_cast<T>(other.imagPart);
00168       return (*this);
00169     }
00170     
00171     /**
00172      * multiply with another complex number
00173      */
00174     template<typename U>
00175     complex<T>& operator*=(const complex<U>& other) {
00176       const T re = realPart * other.real() - imagPart * other.imag();
00177       imagPart = realPart * other.imag() + imagPart * other.real();
00178       realPart = re;
00179       return *this;
00180     }
00181     
00182     /**
00183      * divide with another complex number
00184      */
00185     template<typename U>
00186     complex<T>& operator/=(const complex<U>& other) {
00187       const T norm = other.real()*other.real() + other.imag()*other.imag();
00188       const T re = (realPart * other.real() + imagPart * other.imag())/norm;
00189       imagPart = (imagPart * other.real() - realPart * other.imag())/norm;
00190       realPart = re;
00191       return *this;
00192     }
00193 
00194   private:
00195     /**
00196        * real component
00197        */
00198     T realPart;
00199     
00200     /**
00201        * imaginary component
00202        */
00203     T imagPart;
00204   };
00205 
00206   // -------------------------------------------------------------------------
00207   // implementation
00208   // -------------------------------------------------------------------------
00209 
00210   template<typename T>
00211   inline T complex<T>::real() const {
00212     return realPart; 
00213   }
00214   
00215   template<typename T>
00216   inline T complex<T>::imag() const {
00217     return imagPart; 
00218   }
00219   
00220   template<typename T>
00221   inline complex<T>::complex(const T& re, const T& im)
00222     : realPart(re), imagPart(im) { }
00223 
00224   template<typename T>
00225     inline complex<T>::complex(const std::complex<T>& other)
00226     : realPart(other.real()), imagPart(other.imag()) { }
00227   
00228   template<typename T>
00229   complex<T>& complex<T>::operator=(const T& other) {
00230     realPart = other;
00231     imagPart = T();
00232     return *this;
00233   } 
00234 
00235   template<typename T>
00236   inline complex<T>& complex<T>::operator+=(const T& other) {
00237     realPart += other;
00238     return *this;
00239   }
00240   
00241   template<typename T>
00242   inline complex<T>& complex<T>::operator-=(const T& other) {
00243     realPart -= other;
00244     return *this;
00245   }
00246 
00247   template<typename T>
00248   complex<T>&  complex<T>::operator*=(const T& other) {
00249     realPart *= other;
00250     imagPart *= other;
00251     return *this;
00252   }
00253 
00254   template<typename T>
00255   complex<T>& complex<T>::operator/=(const T& other) {
00256     realPart /= other;
00257     imagPart /= other;
00258     return *this;
00259   }
00260 
00261 
00262 
00263 
00264   // -------------------------------------------------------------------------
00265   // global operators
00266   // -------------------------------------------------------------------------
00267   /**
00268    * @name operators for complex numbers
00269    */
00270   //@{
00271     
00272   /**
00273    * add two complex numbers
00274    */
00275   template<typename T>
00276   inline complex<T> operator+(const complex<T>& a, const complex<T>& b) {
00277     return complex<T>(a) += b; 
00278   }
00279 
00280   /**
00281    * add a complex number with a real number
00282    */
00283   template<typename T>
00284   inline complex<T> operator+(const complex<T>& a, const T& b) {
00285     return complex<T>(a) += b; 
00286   }
00287 
00288   /**
00289    * add a real number with a complex number
00290    */
00291   template<typename T>
00292   inline complex<T> operator+(const T& a, const complex<T>& b) {
00293     return complex<T>(b) += a; 
00294   }
00295 
00296   /**
00297    * subtract two complex numbers
00298    */
00299   template<typename T>
00300   inline complex<T> operator-(const complex<T>& a, const complex<T>& b) {
00301     return complex<T>(a) -= b; 
00302   }
00303     
00304   /**
00305    * subtract a real number from a complex one
00306    */
00307   template<typename T>
00308   inline complex<T> operator-(const complex<T>& a, const T& b) {
00309     return complex<T>(a) -= b; 
00310   }
00311 
00312   /**
00313    * subtract a complex number from a real one
00314    */
00315   template<typename T>
00316   inline complex<T> operator-(const T& a, const complex<T>& b) {
00317     return complex<T>(a) -= b;
00318   }
00319 
00320   /**
00321    * multiply two complex numbers
00322    */
00323   template<typename T>
00324   inline complex<T> operator*(const complex<T>& a, const complex<T>& b) {
00325     return complex<T>(a) *= b; 
00326   }
00327 
00328   /**
00329    * multiply a complex number with a real one
00330    */
00331   template<typename T>
00332   inline complex<T> operator*(const complex<T>& a, const T& b) {
00333     return complex<T>(a) *= b; 
00334   }
00335 
00336   /**
00337    * multiply a real number with a complex one
00338    */
00339   template<typename T>
00340   inline complex<T> operator*(const T& a, const complex<T>& b) {
00341     return complex<T>(b) *= a;
00342   }
00343 
00344   /**
00345    * divide two complex numbers
00346    */
00347   template<typename T>
00348   inline complex<T> operator/(const complex<T>& a, const complex<T>& b) {
00349     return complex<T>(a) /= b; 
00350   }
00351     
00352   /**
00353    * divide a complex number by a real one
00354    */
00355   template<typename T>
00356   inline complex<T> operator/(const complex<T>& a, const T& b) {
00357     return complex<T>(a) /= b; 
00358   }
00359 
00360   /**
00361    * divide a real number by a complex one
00362    */
00363   template<typename T>
00364   inline complex<T> operator/(const T& a, const complex<T>& b) {
00365     return complex<T>(a) /= b; 
00366   }
00367 
00368   /**
00369    * plus sign a complex number
00370    */
00371   template<typename T>
00372   inline complex<T> operator+(const complex<T>& a) {
00373     return a;
00374   }
00375 
00376   /**
00377    * minus sign a complex number
00378    */
00379   template<typename T>
00380   inline complex<T> operator-(const complex<T>& a) {
00381     return complex<T>(-a.real(), -a.imag());
00382   }
00383 
00384   /**
00385    * compare if two complex numbers are equal
00386    */
00387   template<typename T>
00388   inline bool operator==(const complex<T>& a, const complex<T>& b) {
00389     return (a.real() == b.real()) && (a.imag() == b.imag());
00390   }
00391 
00392   /**
00393    * compare if two complex numbers differ
00394    */
00395   template<typename T>
00396   inline bool operator==(const complex<T>& a, const T& b) {
00397     return (a.real() == b) && (a.imag() == T());
00398   }
00399 
00400   /**
00401    * compare if a real number and a complex number are the same
00402    */
00403   template<typename T>
00404   inline bool operator==(const T& a, const complex<T>& b) {
00405     return (a == b.real()) && (T() == b.imag()); 
00406   }
00407 
00408   /**
00409    * compare if two complex numbers differ
00410    */
00411   template<typename T>
00412   inline bool operator!=(const complex<T>& a, const complex<T>& b) {
00413     return (a.real() != b.real()) || (a.imag() != b.imag());
00414   }
00415 
00416   /**
00417    * compare if a complex number and a real one differ
00418    */
00419   template<typename T>
00420   inline bool operator!=(const complex<T>& a, const T& b) {
00421     return (a.real() != b) || (a.imag() != T());
00422   }
00423 
00424   /**
00425    * compare if a real number and a complex one differ
00426    */
00427   template<typename T>
00428   inline bool operator!=(const T& a, const complex<T>& b) {
00429     return (a != b.real()) || (T() != b.imag());
00430   }
00431 
00432   /**
00433    * a complex number is "less than" another one if its real part is
00434    * smaller, or when both real parts are identical, if its imaginary
00435    * part is smaller
00436    */
00437   template<typename T>
00438   inline bool operator<(const complex<T>& a,const complex<T>& b) {
00439     return ((a.real()<b.real()) || 
00440             ((a.real() == b.real()) && (a.imag() < b.imag())));
00441   }
00442 
00443   /**
00444    * a complex number is "less than" another one if its real part is
00445    * smaller, or when both real parts are identical, if its imaginary
00446    * part is smaller
00447    */
00448   template<typename T>
00449   inline bool operator<(const complex<T>& a,const T& b) {
00450     return ((a.real()<b) || 
00451             ((a.real() == b) && (a.imag() < T())));
00452   }
00453 
00454   /**
00455    * a complex number is "less than" another one if its real part is
00456    * smaller, or when both real parts are identical, if its imaginary
00457    * part is smaller
00458    */
00459   template<typename T>
00460   inline bool operator<(const T& a,const complex<T>& b) {
00461     return ((a<b.real()) || 
00462             ((a == b.real()) && (T() < b.imag())));
00463   }
00464 
00465   /**
00466    * a complex number is "greater than" another one if its real part is
00467    * greater, or when both real parts are identical, if its imaginary
00468    * part is greater
00469    */
00470   template<typename T>
00471   inline bool operator>(const complex<T>& a,const complex<T>& b) {
00472     return ((a.real()>b.real()) || 
00473             ((a.real() == b.real()) && (a.imag() > b.imag())));
00474   }
00475 
00476   /**
00477    * a complex number is "greater than" another one if its real part is
00478    * greater, or when both real parts are identical, if its imaginary
00479    * part is greater
00480    */
00481   template<typename T>
00482   inline bool operator>(const complex<T>& a,const T& b) {
00483     return ((a.real()>b) || 
00484             ((a.real() == b) && (a.imag() > T())));
00485   }
00486 
00487   /**
00488    * a complex number is "greater than" another one if its real part is
00489    * greater, or when both real parts are identical, if its imaginary
00490    * part is greater
00491    */
00492   template<typename T>
00493   inline bool operator>(const T& a,const complex<T>& b) {
00494     return ((a > b.real()) || 
00495             ( (a == b.real()) && ( b.imag() < T(0) ) ));
00496   }
00497 
00498   /**
00499    * get the real part of a complex number
00500    */
00501   template<typename T>
00502   inline T real(const complex<T>& cn) {
00503     return cn.real(); 
00504   }
00505     
00506   /**
00507    * get the imaginary part of a complex number
00508    */
00509   template<typename T>
00510   inline T imag(const complex<T>& cn) {
00511     return cn.imag(); 
00512   }
00513 
00514   /**
00515    * get the absolute value of a complex number
00516    */
00517   template<typename T>
00518   inline T abs(const complex<T>& cn) {
00519     T a = cn.real();
00520     T b = cn.imag();
00521 
00522     const T tmp = max(abs(a), abs(b));
00523     if (tmp == T()) { // zero?
00524       return tmp;
00525     }
00526 
00527     a /= tmp; // normalize for more numerical stability
00528     b /= tmp;
00529     return tmp * sqrt(a * a + b * b);
00530   }
00531 
00532   /**
00533    * get the argument (angle or phase) of a complex number
00534    */
00535   template<typename T>
00536   inline T arg(const complex<T>& cn) {
00537     return atan2(cn.imag(), cn.real());
00538   }
00539 
00540 
00541   /**
00542    * return the square magnitude of the given complex number
00543    */ 
00544   template<typename T>
00545   inline T norm(const complex<T>& cn) {
00546     const T a(cn.real),b(cn.imag());
00547     return (a*a+b*b);
00548   }
00549 
00550   /**
00551    * convert the given polar values into a complex number
00552    *
00553    * @param radius magnitude of the number
00554    * @param angle  angle of the number
00555    * 
00556    * @return Equivalent complex number to the polar one
00557    */
00558   template<typename T>
00559   inline complex<T> polar(const T& radius, const T& angle) {
00560     return complex<T>(radius * cos(angle), radius * sin(angle)); 
00561   }
00562 
00563   /**
00564    * return the conjugate of the complex number
00565    */
00566   template<typename T>
00567   inline complex<T> conj(const complex<T>& cn) {
00568     return complex<T>(cn.real(), -cn.imag()); 
00569   }
00570   
00571   /**
00572    * cosine of a complex number
00573    */
00574   template<typename T>
00575   inline complex<T> cos(const complex<T>& cn) {
00576     const T a = cn.real();
00577     const T b = cn.imag();
00578     return complex<T>(cos(a) * std::cosh(b), -sin(a) * std::sinh(b));
00579   }
00580 
00581   /**
00582    * hyperbolic cosine of a complex number
00583    */
00584   template<typename T>
00585   inline complex<T> cosh(const complex<T>& cn) {
00586     const T a = cn.real();
00587     const T b = cn.imag();
00588     return complex<T>(std::cosh(a) * cos(b), std::sinh(a) * sin(b));
00589   }
00590 
00591   template<typename T>
00592   inline complex<T> acos(const complex<T>& cn) {
00593     complex<T> tmp(log(cn+sqrt(cn*cn-T(1))));
00594     return complex<T>(tmp.imag(),-tmp.real());;
00595   }
00596 
00597   /**
00598    * exponetial of a complex number
00599    */
00600   template<typename T>
00601   inline complex<T> exp(const complex<T>& cn) {
00602     return polar(exp(cn.real()), cn.imag()); 
00603   }
00604 
00605   /**
00606    * natural logarithm of a complex number (base \e e)
00607    */
00608   template<typename T>
00609   inline complex<T> log(const complex<T>& cn) {
00610     return complex<T>(log(abs(cn)), arg(cn)); 
00611   }
00612 
00613   /**
00614    * logarithm base 10 of a complex number
00615    */
00616   template<typename T>
00617   inline complex<T> log10(const complex<T>& cn) {
00618     return log(cn) / log(T(10.0)); 
00619   }
00620 
00621   /**
00622    * sine of a complex number
00623    */
00624   template<typename T>
00625   inline complex<T> sin(const complex<T>& cn) {
00626     const T a = cn.real();
00627     const T b = cn.imag();
00628     return complex<T>(sin(a) * std::cosh(b), cos(a) * std::sinh(b)); 
00629   }
00630   
00631   /**
00632    * hyperbolic sine of a complex number
00633    */
00634   template<typename T>
00635   inline complex<T> sinh(const complex<T>& cn) {
00636     const T a = cn.real();
00637     const T  b = cn.imag();
00638     return complex<T>(std::sinh(a) * cos(b), std::cosh(a) * sin(b));
00639   }
00640 
00641   template<typename T>
00642   inline complex<T> asin(const complex<T>& cn) {
00643     complex<T> tmp(log(complex<T>(-cn.imag(),cn.real())+sqrt(1-cn*cn)));
00644     return complex<T>(tmp.imag(),-tmp.real());;
00645   }
00646 
00647   /**
00648    * square root of a complex number.
00649    *
00650    * A there are always two solutions for sqrt(x+iy), this method provides
00651    * the first one consisting in sqrt(m*e^(i*a))=sqrt(m)*e^(i*a/2)
00652    */
00653   template<typename T>
00654   complex<T> sqrt(const complex<T>& cn) {
00655     T a = cn.real();
00656     T b = cn.imag();
00657 
00658     if (a == T()) {
00659       T other = sqrt(abs(b) / 2);
00660       return complex<T>(other, b < T() ? -other : other);
00661     }
00662     else {
00663       T other = sqrt(2 * (abs(cn) + abs(a)));
00664       T tmp = other / 2;
00665       return (a > T()) ? 
00666         complex<T>(tmp, b / other)
00667         : complex<T>(abs(b) / other, b < T() ? -tmp : tmp);
00668     }
00669   }
00670 
00671   /**
00672    * cube root of a complex number
00673    *
00674    * A there are always two solutions for sqrt(x+iy), this method provides
00675    * the first one consisting in sqrt(m*e^(i*a))=sqrt(m)*e^(i*a/2)
00676    */
00677   template<typename T>
00678   inline complex<T> cbrt(const complex<T>& cn) {
00679     const T m = abs(cn);
00680     const T a = arg(cn);
00681     return polar(pow(double(m),1.0/3.0),m/3.0);
00682   }
00683 
00684   /**
00685    * cube root of a complex number (alias for cbrt())
00686    */
00687   template<typename T>
00688   inline complex<T> cubeRoot(const complex<T>& cn) {
00689     return cbrt(cn);
00690   }  
00691   
00692   /**
00693    * tangent of a complex number
00694    */
00695   template<typename T>
00696   inline complex<T> tan(const complex<T>& cn) {
00697     return sin(cn) / cos(cn);
00698   }
00699 
00700   /**
00701    * hyperbolic tangent of a complex number
00702    */
00703   template<typename T>
00704   inline complex<T> tanh(const complex<T>& cn) {
00705     return std::sinh(cn) / std::cosh(cn);
00706   }
00707 
00708   /**
00709    * hyperbolic arc tangent of a complex number
00710    */
00711   template<typename T>
00712   inline complex<T> atan(const complex<T>& cn) {
00713     return log((complex<T>(1)+complex<T>(-cn.real(),cn.imag()))/
00714                (complex<T>(1)-complex<T>(-cn.real(),cn.imag())))/
00715       (complex<T>(0,2));
00716   }
00717 
00718   /**
00719    * complex number to the power of \a b, with \b real
00720    */
00721   template<typename T>
00722   inline complex<T> pow(const complex<T>& a, const T& b) {
00723     return exp(b * log(a));
00724   }
00725 
00726   /**
00727    * complex number to the power of \a b, with \b complex
00728    */
00729   template<typename T>
00730   inline complex<T> pow(const complex<T>& a, const complex<T>& b) {
00731     return exp(b * log(a));
00732   }
00733 
00734   /**
00735    * real number to the power of \a b, with \b complex
00736    */
00737   template<typename T>
00738   inline complex<T> pow(const T& a, const complex<T>& b) {
00739     return exp(b * log(a));
00740   }
00741 
00742   /**
00743    * read the vector from the given ioHandler.  The complete flag indicates
00744    * if the enclosing begin and end should be also be readed
00745    *
00746    * @ingroup gStorable
00747    */
00748   template <typename T>
00749   bool read(ioHandler& handler,complex<T>& p,const bool complete=true) {
00750     bool b(true);
00751     
00752     if (complete) {
00753       b = b && handler.readBegin();
00754     }
00755 
00756     T re,im;
00757     b = b && handler.read(re);
00758     b = b && handler.readDataSeparator();
00759     b = b && handler.read(im);
00760 
00761     p=complex<T>(re,im);
00762     
00763     if (complete) {
00764       b = b && handler.readEnd();
00765     }
00766     
00767     return b;
00768   };
00769 
00770   /**
00771    * write the vector in the given ioHandler.  The complete flag indicates
00772    * if the enclosing begin and end should be also be written or not
00773    *
00774    * @ingroup gStorable
00775    */
00776   template<typename T>
00777   bool write(ioHandler& handler,const complex<T>& p,const bool complete=true) {
00778     bool b(true);
00779     
00780     if (complete) {
00781       b = b && handler.writeBegin();
00782     }
00783     
00784     b = b && handler.write(p.real());
00785     b = b && handler.writeDataSeparator();
00786     b = b && handler.write(p.imag());
00787     
00788     if (complete) {
00789       b = b && handler.writeEnd();
00790     }
00791     
00792     return b;
00793   };
00794 
00795 } // end namespace lti
00796 
00797 namespace std {
00798 
00799   template<typename T>
00800   inline istream& operator>>(istream& in, lti::complex<T>& a) {
00801     T re, im;
00802     char ch;
00803     in >> ch;
00804     if (ch == '(') {
00805       in >> re >> ch;
00806       if (ch == ',') {
00807         in >> im >> ch;
00808         if (ch == ')') {
00809           a = lti::complex<T>(re, im);
00810         } else {
00811           in.setstate(ios_base::failbit);
00812         }
00813       }
00814       else if (ch == ')') {
00815         a = lti::complex<T>(re, T(0));
00816       } else {
00817         in.setstate(ios_base::failbit);
00818       }
00819     }
00820     else {
00821       in.putback(ch);
00822       in >> re;
00823       a = lti::complex<T>(re, T(0));
00824     }
00825     return in;
00826   }
00827 
00828   template<typename T>
00829   inline ostream& operator<<(ostream& out, const lti::complex<T>& a) {
00830     out << '(' << a.real() << ',' << a.imag() << ')';
00831     return out;
00832   }
00833 
00834 } // namespace std
00835 
00836 #endif 

Generated on Sat Apr 10 15:25:16 2010 for LTI-Lib by Doxygen 1.6.1