latest version v1.9 - last update 10 Apr 2010 |
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