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 .......: ltiUnifiedSVD.h 00027 * authors ....: Peter Doerfler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 20.11.2003 00030 * revisions ..: $Id: ltiUnifiedSVD.h,v 1.9 2007/01/10 02:26:26 alvarado Exp $ 00031 */ 00032 00033 #ifndef _LTI_UNIFIED_SVD_H_ 00034 #define _LTI_UNIFIED_SVD_H_ 00035 00036 #include "ltiSVD.h" 00037 #include "ltiLinearAlgebraFunctor.h" 00038 00039 namespace lti { 00040 /** 00041 * This functor is meant to be used for calculating the Singular 00042 * Vector Decomposition without need to think about the most 00043 * efficient usage of the available methods. If the LAPACK is 00044 * available it will automatically be used since it is much faster. 00045 * 00046 * It is preferred to use this class instead of the SVD functors 00047 * available. 00048 */ 00049 template<class T> 00050 class unifiedSVD : public linearAlgebraFunctor { 00051 public: 00052 /** 00053 * the parameters for the class unifiedSVD 00054 */ 00055 class parameters : public linearAlgebraFunctor::parameters { 00056 public: 00057 00058 /** 00059 * The SVD method to use. Note that functors 00060 * starting with Fast___ are only available if LAPACK is 00061 * used. The default is set according to your installation. 00062 */ 00063 enum eSVDType { 00064 SVD, /*!< use singularValueDecomp */ 00065 FastSVD = 10 /*!< use fastSVD */ 00066 }; 00067 00068 /** 00069 * default constructor 00070 */ 00071 parameters() : linearAlgebraFunctor::parameters() { 00072 00073 sort = true; 00074 transposeU = false; 00075 transposeV = false; 00076 useDC = true; 00077 useMinDimensions = true; 00078 #ifdef HAVE_LAPACK 00079 svdType = FastSVD; 00080 #else 00081 svdType = SVD; 00082 #endif 00083 }; 00084 00085 /** 00086 * copy constructor 00087 * @param other the parameters object to be copied 00088 */ 00089 parameters(const parameters& other) : linearAlgebraFunctor::parameters() { 00090 copy(other); 00091 } 00092 00093 /** 00094 * destructor 00095 */ 00096 ~parameters() { 00097 }; 00098 00099 /** 00100 * returns name of this type 00101 */ 00102 const char* getTypeName() const { 00103 return "unifiedSVD::parameters"; 00104 }; 00105 00106 /** 00107 * copy the contents of a parameters object 00108 * @param other the parameters object to be copied 00109 * @return a reference to this parameters object 00110 */ 00111 parameters& copy(const parameters& other) { 00112 # ifndef _LTI_MSC_6 00113 // MS Visual C++ 6 is not able to compile this... 00114 linearAlgebraFunctor::parameters::copy(other); 00115 # else 00116 // ...so we have to use this workaround. 00117 // Conditional on that, copy may not be virtual. 00118 linearAlgebraFunctor::parameters& (linearAlgebraFunctor::parameters::* p_copy) 00119 (const linearAlgebraFunctor::parameters&) = 00120 linearAlgebraFunctor::parameters::copy; 00121 (this->*p_copy)(other); 00122 # endif 00123 00124 00125 sort = other.sort; 00126 transposeU = other.transposeU; 00127 transposeV = other.transposeV; 00128 useDC = other.useDC; 00129 useMinDimensions = other.useMinDimensions; 00130 svdType = other.svdType; 00131 00132 00133 return *this; 00134 }; 00135 00136 /** 00137 * copy the contents of a parameters object 00138 * @param other the parameters object to be copied 00139 * @return a reference to this parameters object 00140 */ 00141 parameters& operator=(const parameters& other) { 00142 return copy(other); 00143 }; 00144 00145 /** 00146 * returns a pointer to a clone of the parameters 00147 */ 00148 virtual functor::parameters* clone() const { 00149 return new parameters(*this); 00150 }; 00151 00152 # ifndef _LTI_MSC_6 00153 /** 00154 * write the parameters in the given ioHandler 00155 * @param handler the ioHandler to be used 00156 * @param complete if true (the default) the enclosing begin/end will 00157 * be also written, otherwise only the data block will be written. 00158 * @return true if write was successful 00159 */ 00160 virtual bool write(ioHandler& handler,const bool complete=true) const 00161 # else 00162 /** 00163 * this function is required by MSVC only, as a workaround for a 00164 * very awful bug, which exists since MSVC V.4.0, and still by 00165 * V.6.0 with all bugfixes (so called "service packs") remains 00166 * there... This method is also public due to another bug, so please 00167 * NEVER EVER call this method directly: use write() instead 00168 */ 00169 bool writeMS(ioHandler& handler,const bool complete=true) const 00170 # endif 00171 { 00172 bool b = true; 00173 if (complete) { 00174 b = handler.writeBegin(); 00175 } 00176 00177 if (b) { 00178 00179 lti::write(handler,"sort",sort); 00180 lti::write(handler,"transposeU",transposeU); 00181 lti::write(handler,"transposeV",transposeV); 00182 lti::write(handler,"useDC",useDC); 00183 lti::write(handler,"useMinDimensions",useMinDimensions); 00184 00185 switch (svdType) { 00186 case SVD: 00187 lti::write(handler,"svdType","SVD"); 00188 break; 00189 case FastSVD: 00190 lti::write(handler,"svdType","FastSVD"); 00191 break; 00192 default: 00193 #ifdef HAVE_LAPACK 00194 lti::write(handler,"svdType","FastSVD"); 00195 #else 00196 lti::write(handler,"svdType","SVD"); 00197 #endif 00198 break; 00199 } 00200 00201 } 00202 00203 # ifndef _LTI_MSC_6 00204 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00205 // compile... 00206 b = b && linearAlgebraFunctor::parameters::write(handler,false); 00207 # else 00208 bool (linearAlgebraFunctor::parameters::* p_writeMS)(ioHandler&, 00209 const bool) const = 00210 linearAlgebraFunctor::parameters::writeMS; 00211 b = b && (this->*p_writeMS)(handler,false); 00212 # endif 00213 00214 if (complete) { 00215 b = b && handler.writeEnd(); 00216 } 00217 00218 return b; 00219 } 00220 00221 # ifdef _LTI_MSC_6 00222 /** 00223 * write the parameters in the given ioHandler 00224 * @param handler the ioHandler to be used 00225 * @param complete if true (the default) the enclosing begin/end will 00226 * be also written, otherwise only the data block will be written. 00227 * @return true if write was successful 00228 */ 00229 bool write(ioHandler& handler, 00230 const bool complete=true) const { 00231 // ...we need this workaround to cope with another really 00232 // awful MSVC bug. 00233 return writeMS(handler,complete); 00234 } 00235 # endif 00236 00237 00238 # ifndef _LTI_MSC_6 00239 /** 00240 * read the parameters from the given ioHandler 00241 * @param handler the ioHandler to be used 00242 * @param complete if true (the default) the enclosing begin/end will 00243 * be also written, otherwise only the data block will be written. 00244 * @return true if read was successful 00245 */ 00246 virtual bool read(ioHandler& handler,const bool complete=true) 00247 # else 00248 /** 00249 * this function is required by MSVC only, as a workaround for a 00250 * very awful bug, which exists since MSVC V.4.0, and still by 00251 * V.6.0 with all bugfixes (so called "service packs") remains 00252 * there... This method is also public due to another bug, so please 00253 * NEVER EVER call this method directly: use read() instead 00254 */ 00255 bool readMS(ioHandler& handler,const bool complete=true) 00256 # endif 00257 { 00258 bool b = true; 00259 if (complete) { 00260 b = handler.readBegin(); 00261 } 00262 00263 if (b) { 00264 00265 lti::read(handler,"sort",sort); 00266 lti::read(handler,"transposeU",transposeU); 00267 lti::read(handler,"transposeV",transposeV); 00268 lti::read(handler,"useDC",useDC); 00269 lti::read(handler,"useMinDimensions",useMinDimensions); 00270 00271 std::string tmp; 00272 lti::read(handler,"svdType",tmp); 00273 if (tmp=="SVD") { 00274 svdType = SVD; 00275 } else if (tmp=="FastSVD") { 00276 svdType = FastSVD; 00277 } else { 00278 #ifdef HAVE_LAPACK 00279 svdType = FastSVD; 00280 #else 00281 svdType = SVD; 00282 #endif 00283 } 00284 00285 } 00286 00287 # ifndef _LTI_MSC_6 00288 // This is the standard C++ code, which MS Visual C++ 6 is not 00289 // able to compile... 00290 b = b && linearAlgebraFunctor::parameters::read(handler,false); 00291 # else 00292 bool (linearAlgebraFunctor::parameters::* p_readMS)(ioHandler&, 00293 const bool) = 00294 linearAlgebraFunctor::parameters::readMS; 00295 b = b && (this->*p_readMS)(handler,false); 00296 # endif 00297 00298 if (complete) { 00299 b = b && handler.readEnd(); 00300 } 00301 00302 return b; 00303 } 00304 00305 # ifdef _LTI_MSC_6 00306 /** 00307 * read the parameters from the given ioHandler 00308 * @param handler the ioHandler to be used 00309 * @param complete if true (the default) the enclosing begin/end will 00310 * be also written, otherwise only the data block will be written. 00311 * @return true if read was successful 00312 */ 00313 bool read(ioHandler& handler,const bool complete=true) { 00314 // ...we need this workaround to cope with another really awful MSVC 00315 // bug. 00316 return readMS(handler,complete); 00317 } 00318 # endif 00319 00320 // ------------------------------------------------ 00321 // the parameters 00322 // ------------------------------------------------ 00323 00324 00325 /** 00326 * If true the eigenvalues and eigenvectors are sorted in 00327 * descending order. Default true. 00328 * 00329 * See singularValueDecomp<T>::parameters::sort. 00330 */ 00331 bool sort; 00332 00333 /** 00334 * If true the transpose of matrix U is returned instead of 00335 * U. Default false. 00336 * 00337 * See singularValueDecomp<T>::parameters::transposeU 00338 */ 00339 bool transposeU; 00340 00341 /** 00342 * If true the transpose of matrix V is returned instead of 00343 * V. Default false. 00344 * 00345 * See singularValueDecomp<T>::parameters::transposeV 00346 */ 00347 bool transposeV; 00348 00349 /** 00350 * This parameters is used only if svdType=FastSVD. It 00351 * determines whether the divide and conquer strategy is used or 00352 * not. Default true. 00353 * 00354 * See fastSVD<T>::parameters::useDC 00355 */ 00356 bool useDC; 00357 00358 /** 00359 * This parameters is used only if svdType=FastSVD. If true only 00360 * min(rows,columns) of the data matrix singular vectors are calculated. 00361 * 00362 * Default value: \c true. 00363 * 00364 * See fastSVD<T>::parameters::useMinDimensions 00365 */ 00366 bool useMinDimensions; 00367 00368 /** 00369 * The SVD type given is used. Note that you cannot use 00370 * fastSVD if LAPACK is not installed. The default is 00371 * dependent on the the system configuration: If LAPACK is 00372 * available, fastSVD is used, otherwise singularValueDecomp. 00373 */ 00374 eSVDType svdType; 00375 00376 00377 }; 00378 00379 /** 00380 * default constructor 00381 */ 00382 unifiedSVD(); 00383 00384 /** 00385 * Construct a functor using the given parameters 00386 */ 00387 unifiedSVD(const parameters& par); 00388 00389 /** 00390 * copy constructor 00391 * @param other the object to be copied 00392 */ 00393 unifiedSVD(const unifiedSVD& other); 00394 00395 /** 00396 * destructor 00397 */ 00398 virtual ~unifiedSVD(); 00399 00400 /** 00401 * returns the name of this type ("unifiedSVD") 00402 */ 00403 virtual const char* getTypeName() const; 00404 00405 /** 00406 * copy data of "other" functor. 00407 * @param other the functor to be copied 00408 * @return a reference to this functor object 00409 */ 00410 unifiedSVD& copy(const unifiedSVD& other); 00411 00412 /** 00413 * alias for copy member 00414 * @param other the functor to be copied 00415 * @return a reference to this functor object 00416 */ 00417 unifiedSVD& operator=(const unifiedSVD& other); 00418 00419 /** 00420 * returns a pointer to a clone of this functor. 00421 */ 00422 virtual functor* clone() const; 00423 00424 /** 00425 * set functor's parameters. 00426 * This member makes a copy of <em>theParam</em>: the functor 00427 * will keep its own copy of the parameters! 00428 * @return true if successful, false otherwise 00429 */ 00430 virtual bool updateParameters(); 00431 00432 /** 00433 * returns used parameters 00434 */ 00435 const parameters& getParameters() const; 00436 00437 /** 00438 * Read the functor from the given ioHandler. 00439 * 00440 * This method automatically sets the correct SVD solver 00441 * that is given in the parameters and transfers the relevant 00442 * parameters to that functor. 00443 * 00444 * @param handler the ioHandler to be used 00445 * @param complete if true (the default) the enclosing begin/end will 00446 * be also written, otherwise only the data block will be written. 00447 * @return true if write was successful 00448 */ 00449 virtual bool read(ioHandler& handler,const bool complete=true); 00450 00451 /** 00452 * OnPlace version of Singular Value Decomposition. Singular Value 00453 * Decomposition means that a m*n-matrix A is decomposed into three 00454 * matrices U,W,V, such that A = U*W*V'. U is m*n, W is a diagonal 00455 * matrix with n elements (which is implemented as vector), V is a 00456 * n*n-matrix. Note that the function returns V, not V'. 00457 * @param src matrix<T> with the source matrix, will also contain 00458 * the U matrix after the function has returned. If 00459 * src is a m*n matrix, U will also be of size m*n 00460 * @param w vector<T> with the singular values, sorted descendingly 00461 * The elements of this vector constitute the diagonal 00462 * of the W matrix. 00463 * @param v the V matrix 00464 * @return true is the decomposition was successfull, false if an 00465 * error occured 00466 */ 00467 inline bool decomposition(matrix<T>& src, 00468 vector<T>& w, 00469 matrix<T>& v) const { 00470 return svd->decomposition(src,w,v); 00471 } 00472 00473 /** 00474 * OnPlace version of Singular Value Decomposition. 00475 * @param src matrix<T> with the source matrix, will also contain 00476 * the U matrix after the function has returned. 00477 * @param w vector<T> with the singular values, sorted descendingly if 00478 * parameters::sort is true. 00479 * The elements of this vector constitute the diagonal 00480 * of the W matrix. 00481 * @param v the V matrix 00482 * @return true is the decomposition was successfull, false if an 00483 * error occured 00484 */ 00485 inline bool apply(matrix<T>& src, vector<T>& w, matrix<T>& v) const { 00486 return svd->apply(src,w,v); 00487 } 00488 00489 /** 00490 * OnCopy version of Singular Value Decomposition. 00491 * @param src matrix<T> with the source matrix 00492 * @param u the U matrix 00493 * @param w vector<T> with the singular values, sorted descendingly if 00494 * parameters::sort is true. 00495 * The elements of this vector constitute the diagonal 00496 * of the W matrix. 00497 * @param v the V matrix 00498 * @return true is the decomposition was successfull, false if an 00499 * error occured 00500 */ 00501 inline bool apply(const matrix<T>& src, matrix<T>& u, 00502 vector<T>& w, matrix<T>& v) const { 00503 return svd->apply(src,u,w,v); 00504 } 00505 00506 00507 protected: 00508 00509 /** 00510 * The actual eigenSystem. 00511 */ 00512 singularValueDecomp<T>* svd; 00513 00514 }; 00515 } 00516 00517 #endif