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

ltiUnifiedSymmetricEigenSystem.h

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 .......: ltiUnifiedSymmetricEigenSystem.h
00027  * authors ....: Peter Doerfler
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 18.11.2003
00030  * revisions ..: $Id: ltiUnifiedSymmetricEigenSystem.h,v 1.10 2006/02/08 12:51:11 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_UNIFIED_SYMMETRIC_EIGEN_SYSTEM_H_
00034 #define _LTI_UNIFIED_SYMMETRIC_EIGEN_SYSTEM_H_
00035 
00036 #include "ltiEigenSystem.h"
00037 #include "ltiLinearAlgebraFunctor.h"
00038 
00039 namespace lti {
00040   /**
00041    * This functor is meant to be used for solving any symmetric
00042    * Eigenvalue problem without need to think about the most efficient
00043    * usage of the available methods. If LAPACK is available it will
00044    * automatically be used since it is much faster than other
00045    * implementations in the LTI-Lib.
00046    *
00047    * This functor only handles symmetric Eigenvalue problems. For
00048    * non-symmetric or general EV problems there is only a LAPACK
00049    * functor: genEigenSystem. For the generalized symmetric eigenvalue
00050    * problem use unifiedGeneralizedEigenSystem.
00051    *
00052    * It is preferred to use this class instead of the symmetric
00053    * eigenSystem functors available (fastEigenSystem, jacobi).
00054    */
00055   template<class T>
00056   class unifiedSymmetricEigenSystem : public linearAlgebraFunctor {
00057   public:
00058     /**
00059      * the parameters for the class unifiedSymmetricEigenSystem
00060      */
00061     class parameters : public linearAlgebraFunctor::parameters {
00062     public:
00063 
00064       /**
00065        * The Eigensystem solution method to use. Note that functors
00066        * starting with Fast___ are only available if LAPACK is
00067        * used. The default is set according to your installation.
00068        */
00069       enum eEigenSystemType {
00070         Jacobi,               /*!< use jacobi */
00071         FastEigenSystem = 10  /*!< use fastEigenSystem */
00072       };
00073 
00074       /**
00075        * default constructor
00076        */
00077       parameters() : linearAlgebraFunctor::parameters() {
00078         
00079         sort = true;
00080         dimensions = 0;
00081         useRRR = false;
00082 #ifdef HAVE_LAPACK
00083         esType = FastEigenSystem;
00084 #else
00085         esType = Jacobi;
00086 #endif
00087       };
00088 
00089       /**
00090        * copy constructor
00091        * @param other the parameters object to be copied
00092        */
00093       parameters(const parameters& other) : linearAlgebraFunctor::parameters() {
00094         copy(other);
00095       }
00096       
00097       /**
00098        * destructor
00099        */
00100       ~parameters() {
00101       };
00102 
00103       /**
00104        * returns name of this type
00105        */
00106       const char* getTypeName() const {
00107         return "unifiedSymmetricEigenSystem::parameters";
00108       };
00109 
00110       /**
00111        * copy the contents of a parameters object
00112        * @param other the parameters object to be copied
00113        * @return a reference to this parameters object
00114        */
00115       parameters& copy(const parameters& other) {
00116 #     ifndef _LTI_MSC_6
00117         // MS Visual C++ 6 is not able to compile this...
00118         linearAlgebraFunctor::parameters::copy(other);
00119 #     else
00120         // ...so we have to use this workaround.
00121         // Conditional on that, copy may not be virtual.
00122         linearAlgebraFunctor::parameters& (linearAlgebraFunctor::parameters::* p_copy)
00123                             (const linearAlgebraFunctor::parameters&) =
00124                             linearAlgebraFunctor::parameters::copy;
00125         (this->*p_copy)(other);
00126 #     endif
00127 
00128         
00129         sort       = other.sort;
00130         dimensions = other.dimensions;
00131         useRRR     = other.useRRR;
00132         esType     = other.esType;
00133         
00134         return *this;
00135       };
00136 
00137       /**
00138        * copy the contents of a parameters object
00139        * @param other the parameters object to be copied
00140        * @return a reference to this parameters object
00141        */
00142       parameters& operator=(const parameters& other) {
00143         return copy(other);
00144       };
00145 
00146       /**
00147        * returns a pointer to a clone of the parameters
00148        */
00149       virtual functor::parameters* clone() const {
00150         return new parameters(*this);
00151       };
00152 
00153 #     ifndef _LTI_MSC_6
00154       /**
00155        * write the parameters in the given ioHandler
00156        * @param handler the ioHandler to be used
00157        * @param complete if true (the default) the enclosing begin/end will
00158        *        be also written, otherwise only the data block will be written.
00159        * @return true if write was successful
00160        */
00161       virtual bool write(ioHandler& handler,const bool complete=true) const
00162 #     else
00163       /**
00164        * this function is required by MSVC only, as a workaround for a
00165        * very awful bug, which exists since MSVC V.4.0, and still by
00166        * V.6.0 with all bugfixes (so called "service packs") remains
00167        * there...  This method is also public due to another bug, so please
00168        * NEVER EVER call this method directly: use write() instead
00169        */
00170       bool writeMS(ioHandler& handler,const bool complete=true) const
00171 #     endif
00172       {
00173         bool b = true;
00174         if (complete) {
00175           b = handler.writeBegin();
00176         }
00177         
00178         if (b) {
00179           
00180           lti::write(handler,"sort",sort);
00181           lti::write(handler,"dimensions",dimensions);
00182           lti::write(handler,"useRRR",useRRR);
00183           
00184           switch (esType) {
00185             case Jacobi:
00186               lti::write(handler,"esType","Jacobi");
00187               break;
00188             case FastEigenSystem:
00189               lti::write(handler,"esType","FastEigenSystem");
00190               break;
00191             default:
00192 #ifdef HAVE_LAPACK
00193               lti::write(handler,"esType","FastEigenSystem");
00194 #else              
00195               lti::write(handler,"esType","Jacobi");
00196 #endif
00197               break;
00198           }
00199 
00200         }
00201 
00202 #     ifndef _LTI_MSC_6
00203         // This is the standard C++ code, which MS Visual C++ 6 is not able to
00204         // compile...
00205         b = b && linearAlgebraFunctor::parameters::write(handler,false);
00206 #     else
00207         bool (linearAlgebraFunctor::parameters::* p_writeMS)(ioHandler&,
00208                                                          const bool) const =
00209           linearAlgebraFunctor::parameters::writeMS;
00210         b = b && (this->*p_writeMS)(handler,false);
00211 #     endif
00212 
00213         if (complete) {
00214           b = b && handler.writeEnd();
00215         }
00216 
00217         return b;
00218       }
00219 
00220 #     ifdef _LTI_MSC_6
00221       /**
00222        * write the parameters in the given ioHandler
00223        * @param handler the ioHandler to be used
00224        * @param complete if true (the default) the enclosing begin/end will
00225        *        be also written, otherwise only the data block will be written.
00226        * @return true if write was successful
00227        */
00228       bool write(ioHandler& handler,
00229                  const bool complete=true) const {
00230         // ...we need this workaround to cope with another really
00231         // awful MSVC bug.
00232         return writeMS(handler,complete);
00233       }
00234 #     endif
00235 
00236 
00237 #     ifndef _LTI_MSC_6
00238       /**
00239        * read the parameters from the given ioHandler
00240        * @param handler the ioHandler to be used
00241        * @param complete if true (the default) the enclosing begin/end will
00242        *        be also written, otherwise only the data block will be written.
00243        * @return true if write was successful
00244        */
00245       virtual bool read(ioHandler& handler,const bool complete=true)
00246 #     else
00247       /**
00248        * this function is required by MSVC only, as a workaround for a
00249        * very awful bug, which exists since MSVC V.4.0, and still by
00250        * V.6.0 with all bugfixes (so called "service packs") remains
00251        * there...  This method is also public due to another bug, so please
00252        * NEVER EVER call this method directly: use read() instead
00253        */
00254       bool readMS(ioHandler& handler,const bool complete=true)
00255 #     endif
00256       {
00257         bool b = true;
00258         if (complete) {
00259           b = handler.readBegin();
00260         }
00261         
00262         if (b) {
00263           
00264           lti::read(handler,"sort",sort);
00265           lti::read(handler,"dimensions",dimensions);
00266           lti::read(handler,"useRRR",useRRR);
00267 
00268           std::string tmp;
00269           lti::read(handler,"esType",tmp);
00270           if (tmp=="Jacobi") {
00271             esType = Jacobi;
00272           } else if (tmp=="FastEigenSystem") {
00273             esType = FastEigenSystem;
00274           } else {
00275 #ifdef HAVE_LAPACK
00276             esType = FastEigenSystem;
00277 #else
00278             esType = Jacobi;
00279 #endif
00280           }
00281 
00282         }
00283 
00284 #       ifndef _LTI_MSC_6
00285         // This is the standard C++ code, which MS Visual C++ 6 is not
00286         // able to compile...
00287         b = b && linearAlgebraFunctor::parameters::read(handler,false);
00288 #       else
00289         bool (linearAlgebraFunctor::parameters::* p_readMS)(ioHandler&,
00290                                                         const bool) =
00291           linearAlgebraFunctor::parameters::readMS;
00292         b = b && (this->*p_readMS)(handler,false);
00293 #       endif
00294 
00295         if (complete) {
00296           b = b && handler.readEnd();
00297         }
00298         
00299         return b;
00300       }
00301 
00302 #     ifdef _LTI_MSC_6
00303       /**
00304        * read the parameters from the given ioHandler
00305        * @param handler the ioHandler to be used
00306        * @param complete if true (the default) the enclosing begin/end will
00307        *        be also written, otherwise only the data block will be written.
00308        * @return true if write was successful
00309        */
00310       bool read(ioHandler& handler,const bool complete=true) {
00311         // ...we need this workaround to cope with another really awful MSVC
00312         // bug.
00313         return readMS(handler,complete);
00314       }
00315 #     endif
00316 
00317       // ------------------------------------------------
00318       // the parameters
00319       // ------------------------------------------------
00320 
00321 
00322       /**
00323        * If true the eigenvalues and eigenvectors are sorted in
00324        * descending order. Default true.
00325        *
00326        * See eigenSystem<T>::parameters::sort.
00327        */
00328       bool sort;
00329 
00330       /**
00331        * The number of eigenvalues/-vectors to be calculated. If zero
00332        * all EV are calculated. Default 0.
00333        *
00334        * See also:
00335        * - jacobi<T>::parameters::dimensions
00336        * - fastEigenSystem<T>::parameters::dimensions
00337        */
00338       int dimensions;
00339 
00340       /**
00341        * This parameter is used only if esType=FastEigenSystem. It
00342        * determines whether the relatively robust representation is
00343        * used. This can be much faster than the default but might also
00344        * hang. For this reason:
00345        *
00346        * Default: false
00347        *
00348        * See alse:
00349        * - fastEigenSystem<T>::parameters::useRRR;
00350        */
00351       bool useRRR;
00352 
00353       /**
00354        * The eigenSystem given is used. Note that you cannot use
00355        * fastEigenSystem if LAPACK is not installed. The default is
00356        * dependent on the the system configuration: If LAPACK is
00357        * available, fastEigenSystem is used, otherwise jacobi.
00358        */
00359       eEigenSystemType esType;
00360 
00361 
00362     };
00363 
00364     /**
00365      * default constructor
00366      */
00367     unifiedSymmetricEigenSystem();
00368 
00369     /**
00370      * Construct a functor using the given parameters
00371      */
00372     unifiedSymmetricEigenSystem(const parameters& par);
00373 
00374     /**
00375      * copy constructor
00376      * @param other the object to be copied
00377      */
00378     unifiedSymmetricEigenSystem(const unifiedSymmetricEigenSystem& other);
00379 
00380     /**
00381      * destructor
00382      */
00383     virtual ~unifiedSymmetricEigenSystem();
00384 
00385     /**
00386      * returns the name of this type ("unifiedSymmetricEigenSystem")
00387      */
00388     virtual const char* getTypeName() const;
00389 
00390     /**
00391      * copy data of "other" functor.
00392      * @param other the functor to be copied
00393      * @return a reference to this functor object
00394      */
00395     unifiedSymmetricEigenSystem& copy(const unifiedSymmetricEigenSystem& other);
00396 
00397     /**
00398      * alias for copy member
00399      * @param other the functor to be copied
00400      * @return a reference to this functor object
00401      */
00402     unifiedSymmetricEigenSystem& 
00403     operator=(const unifiedSymmetricEigenSystem& other);
00404 
00405     /**
00406      * returns a pointer to a clone of this functor.
00407      */
00408     virtual functor* clone() const;
00409 
00410     /**
00411      * set functor's parameters.
00412      * This member makes a copy of <em>theParam</em>: the functor
00413      * will keep its own copy of the parameters!
00414      * @return true if successful, false otherwise
00415      */
00416     virtual bool updateParameters();
00417 
00418     /**
00419      * returns used parameters
00420      */
00421     const parameters& getParameters() const;
00422 
00423     /**
00424      * Read the functor from the given ioHandler. 
00425      *
00426      * This method automatically sets the correct eigensystem solver
00427      * that is given in the parameters and transfers the relevant
00428      * parameters to that functor.
00429      *
00430      * @param handler the ioHandler to be used
00431      * @param complete if true (the default) the enclosing begin/end will
00432      *        be also written, otherwise only the data block will be written.
00433      * @return true if write was successful
00434      */
00435     virtual bool read(ioHandler& handler,const bool complete=true);
00436 
00437     /**
00438      * The apply method calls the eigenSystem method chosen in the
00439      * parameters or automatically derived from the system
00440      * configuration.
00441      * 
00442      * @param theMatrix matrix to be transformed
00443      * @param eigenvalues elements will contain the eigenvalues
00444      * @param eigenvectors columns will contain the eigenvectors
00445      *        corresponding to the eigenvalues
00446      * @return bool true if successful, false otherwise.
00447      */
00448     inline bool apply(const matrix<T>& theMatrix,
00449                       vector<T>& eigenvalues,
00450                       matrix<T>& eigenvectors) const {
00451       return eigen->apply(theMatrix, eigenvalues, eigenvectors);
00452     }
00453     
00454   protected:
00455     
00456     /**
00457      * The actual eigenSystem.
00458      */
00459     eigenSystem<T>* eigen;
00460     
00461   };
00462 }
00463 
00464 #endif

Generated on Sat Apr 10 15:26:20 2010 for LTI-Lib by Doxygen 1.6.1