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 .......: ltiGeneralizedEigenSystem.h 00027 * authors ....: Peter Doerfler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 10.7.2003 00030 * revisions ..: $Id: ltiGeneralizedEigenSystem.h,v 1.10 2006/02/08 12:24:25 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_GENERALIZED_EIGEN_SYSTEM_H_ 00034 #define _LTI_GENERALIZED_EIGEN_SYSTEM_H_ 00035 00036 #include "ltiLinearAlgebraFunctor.h" 00037 #include "ltiVector.h" 00038 #include "ltiMatrix.h" 00039 #include "ltiCholeskyDecomposition.h" 00040 #include "ltiForwardSubstitution.h" 00041 #include "ltiBackSubstitution.h" 00042 #include "ltiEigenSystem.h" 00043 00044 namespace lti { 00045 /** 00046 * Computes all the eigenvalues, and optionally, the eigenvectors 00047 * of a real generalized symmetric-definite eigenproblem, of the 00048 * form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric 00049 * and B is also positive definite. 00050 * 00051 * If parameters::sort is true the eigenvalues and corresponding 00052 * eigenvectors are sorted in descending order. Default is true. 00053 */ 00054 template<class T> 00055 class generalizedEigenSystem : public linearAlgebraFunctor { 00056 public: 00057 /** 00058 * the parameters for the class generalizedEigenSystem 00059 */ 00060 class parameters : public eigenSystem<T>::parameters { 00061 public: 00062 /** 00063 * default constructor. Set sort to true. 00064 */ 00065 parameters() : eigenSystem<T>::parameters(), dimensions(0) { 00066 00067 }; 00068 00069 /** 00070 * copy constructor 00071 * @param other the parameters object to be copied 00072 */ 00073 parameters(const parameters& other) : eigenSystem<T>::parameters() { 00074 copy(other); 00075 } 00076 00077 /** 00078 * destructor 00079 */ 00080 ~parameters() { 00081 }; 00082 00083 /** 00084 * returns name of this type 00085 */ 00086 const char* getTypeName() const { 00087 return "generalizedEigenSystem::parameters"; 00088 }; 00089 00090 /** 00091 * copy the contents of a parameters object 00092 * @param other the parameters object to be copied 00093 * @return a reference to this parameters object 00094 */ 00095 parameters& copy(const parameters& other) { 00096 # ifndef _LTI_MSC_6 00097 // MS Visual C++ 6 is not able to compile this... 00098 eigenSystem<T>::parameters::copy(other); 00099 # else 00100 // ...so we have to use this workaround. 00101 // Conditional on that, copy may not be virtual. 00102 functor::parameters& (functor::parameters::* p_copy) 00103 (const functor::parameters&) = 00104 functor::parameters::copy; 00105 (this->*p_copy)(other); 00106 # endif 00107 00108 00109 dimensions = other.dimensions; 00110 00111 return *this; 00112 }; 00113 00114 /** 00115 * copy the contents of a parameters object 00116 * @param other the parameters object to be copied 00117 * @return a reference to this parameters object 00118 */ 00119 parameters& operator=(const parameters& other) { 00120 return copy(other); 00121 }; 00122 00123 /** 00124 * returns a pointer to a clone of the parameters 00125 */ 00126 virtual functor::parameters* clone() const { 00127 return new parameters(*this); 00128 }; 00129 00130 # ifndef _LTI_MSC_6 00131 /** 00132 * write the parameters in the given ioHandler 00133 * @param handler the ioHandler to be used 00134 * @param complete if true (the default) the enclosing begin/end will 00135 * be also written, otherwise only the data block will be written. 00136 * @return true if write was successful 00137 */ 00138 virtual bool write(ioHandler& handler,const bool complete=true) const 00139 # else 00140 /** 00141 * this function is required by MSVC only, as a workaround for a 00142 * very awful bug, which exists since MSVC V.4.0, and still by 00143 * V.6.0 with all bugfixes (so called "service packs") remains 00144 * there... This method is also public due to another bug, so please 00145 * NEVER EVER call this method directly: use write() instead 00146 */ 00147 bool writeMS(ioHandler& handler,const bool complete=true) const 00148 # endif 00149 { 00150 bool b = true; 00151 if (complete) { 00152 b = handler.writeBegin(); 00153 } 00154 00155 if (b) { 00156 00157 lti::write(handler,"dimensions",dimensions); 00158 } 00159 00160 # ifndef _LTI_MSC_6 00161 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00162 // compile... 00163 b = b && eigenSystem<T>::parameters::write(handler,false); 00164 # else 00165 bool (eigenSystem<T>::parameters::* p_writeMS)(ioHandler&, 00166 const bool) const = 00167 eigenSystem<T>::parameters::writeMS; 00168 b = b && (this->*p_writeMS)(handler,false); 00169 # endif 00170 00171 if (complete) { 00172 b = b && handler.writeEnd(); 00173 } 00174 00175 return b; 00176 } 00177 00178 # ifdef _LTI_MSC_6 00179 /** 00180 * write the parameters in the given ioHandler 00181 * @param handler the ioHandler to be used 00182 * @param complete if true (the default) the enclosing begin/end will 00183 * be also written, otherwise only the data block will be written. 00184 * @return true if write was successful 00185 */ 00186 bool write(ioHandler& handler, 00187 const bool complete=true) const { 00188 // ...we need this workaround to cope with another really 00189 // awful MSVC bug. 00190 return writeMS(handler,complete); 00191 } 00192 # endif 00193 00194 00195 # ifndef _LTI_MSC_6 00196 /** 00197 * read the parameters from the given ioHandler 00198 * @param handler the ioHandler to be used 00199 * @param complete if true (the default) the enclosing begin/end will 00200 * be also written, otherwise only the data block will be written. 00201 * @return true if write was successful 00202 */ 00203 virtual bool read(ioHandler& handler,const bool complete=true) 00204 # else 00205 /** 00206 * this function is required by MSVC only, as a workaround for a 00207 * very awful bug, which exists since MSVC V.4.0, and still by 00208 * V.6.0 with all bugfixes (so called "service packs") remains 00209 * there... This method is also public due to another bug, so please 00210 * NEVER EVER call this method directly: use read() instead 00211 */ 00212 bool readMS(ioHandler& handler,const bool complete=true) 00213 # endif 00214 { 00215 bool b = true; 00216 if (complete) { 00217 b = handler.readBegin(); 00218 } 00219 00220 if (b) { 00221 00222 lti::read(handler,"dimensions",dimensions); 00223 } 00224 00225 # ifndef _LTI_MSC_6 00226 // This is the standard C++ code, which MS Visual C++ 6 is not 00227 // able to compile... 00228 b = b && eigenSystem<T>::parameters::read(handler,false); 00229 # else 00230 bool (eigenSystem<T>::parameters::* p_readMS)(ioHandler&, 00231 const bool) = 00232 eigenSystem<T>::parameters::readMS; 00233 b = b && (this->*p_readMS)(handler,false); 00234 # endif 00235 00236 if (complete) { 00237 b = b && handler.readEnd(); 00238 } 00239 00240 return b; 00241 } 00242 00243 # ifdef _LTI_MSC_6 00244 /** 00245 * read the parameters from the given ioHandler 00246 * @param handler the ioHandler to be used 00247 * @param complete if true (the default) the enclosing begin/end will 00248 * be also written, otherwise only the data block will be written. 00249 * @return true if write was successful 00250 */ 00251 bool read(ioHandler& handler,const bool complete=true) { 00252 // ...we need this workaround to cope with another really awful MSVC 00253 // bug. 00254 return readMS(handler,complete); 00255 } 00256 # endif 00257 00258 // ------------------------------------------------ 00259 // the parameters 00260 // ------------------------------------------------ 00261 00262 //TODO: comment the parameters of your functor 00263 // If you add more parameters manually, do not forget to do following: 00264 // 1. indicate in the default constructor the default values 00265 // 2. make sure that the copy member also copy your new parameters 00266 // 3. make sure that the read and write members also read and 00267 // write your parameters 00268 00269 00270 /** 00271 * number of dimensions calculated. The default is zero. In this 00272 * case, all eigenvectors and eigenvalues are calculated. 00273 * 00274 * This option is only provided for compatibility with the 00275 * fastGeneralizedEigenSystem functor based on LAPACK, but it 00276 * does not make (yet) the computation of the eigensolution any 00277 * faster. It just will cut the already computed complete 00278 * solution to the desired size! 00279 * 00280 * Default value: 0 (implying all eigenvalues will be computed) 00281 */ 00282 int dimensions; 00283 00284 }; 00285 00286 /** 00287 * default constructor 00288 */ 00289 generalizedEigenSystem(); 00290 00291 /** 00292 * Construct a functor using the given parameters 00293 */ 00294 generalizedEigenSystem(const parameters& par); 00295 00296 /** 00297 * copy constructor 00298 * @param other the object to be copied 00299 */ 00300 generalizedEigenSystem(const generalizedEigenSystem& other); 00301 00302 /** 00303 * destructor 00304 */ 00305 virtual ~generalizedEigenSystem(); 00306 00307 /** 00308 * returns the name of this type ("generalizedEigenSystem") 00309 */ 00310 virtual const char* getTypeName() const; 00311 00312 /** 00313 * Computes eigenvalues and eigenvectors of the given matrix. The 00314 * functor can efficiently calculate only a few dimensions of the 00315 * eigenspace, taking those with the largest eigenvalues. The 00316 * number of dimensions is set with parameters::dimensions. 00317 * 00318 * @param a the symmetric matrix A 00319 * @param b the symmetric, positive definite matrix B 00320 * @param eigenvalues elements will contain the eigenvalues 00321 * @param eigenvectors columns will contain the eigenvectors 00322 * corresponding to the eigenvalues 00323 */ 00324 virtual bool apply(const matrix<T>& a, 00325 const matrix<T>& b, 00326 vector<T>& eigenvalues, 00327 matrix<T>& eigenvectors) const; 00328 00329 /** 00330 * Computes eigenvalues and eigenvectors of the given matrix. The 00331 * functor can efficiently calculate only a few dimensions of the 00332 * eigenspace, taking those with the largest eigenvalues. The 00333 * number of dimensions is set with parameters::dimensions. 00334 * 00335 * @param a the symmetric matrix A 00336 * @param b the symmetric, positive definite matrix B 00337 * @param eigenvalues elements will contain the eigenvalues 00338 */ 00339 virtual bool apply(const matrix<T>& a, 00340 const matrix<T>& b, 00341 vector<T>& eigenvalues) const; 00342 00343 /** 00344 * copy data of "other" functor. 00345 * @param other the functor to be copied 00346 * @return a reference to this functor object 00347 */ 00348 generalizedEigenSystem& copy(const generalizedEigenSystem& other); 00349 00350 /** 00351 * alias for copy member 00352 * @param other the functor to be copied 00353 * @return a reference to this functor object 00354 */ 00355 generalizedEigenSystem& operator=(const generalizedEigenSystem& other); 00356 00357 /** 00358 * returns a pointer to a clone of this functor. 00359 */ 00360 virtual functor* clone() const; 00361 00362 /** 00363 * returns used parameters 00364 */ 00365 const parameters& getParameters() const; 00366 00367 /** 00368 * set functor's parameters. 00369 * This member makes a copy of <em>theParam</em>: the functor 00370 * will keep its own copy of the parameters! 00371 * @return true if successful, false otherwise 00372 */ 00373 virtual bool updateParameters(); 00374 00375 private: 00376 00377 choleskyDecomposition<T> cholesky; 00378 00379 forwardSubstitution<T> fSubst; 00380 backSubstitution<T> bSubst; 00381 00382 jacobi<T> simpleEigen; 00383 }; 00384 } 00385 00386 #endif