latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2002, 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 Digital Image/Signal Processing Library 00026 * file .......: ltiFastSVD.h 00027 * authors ....: Peter Doerfler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 12.06.02 00030 * revisions ..: $Id: ltiFastSVD.h,v 1.7 2006/09/11 17:03:34 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_FAST_SVD_H_ 00034 #define _LTI_FAST_SVD_H_ 00035 00036 #include "ltiLapackInterface.h" 00037 00038 #ifdef HAVE_LAPACK 00039 00040 #include "ltiSVD.h" 00041 00042 namespace lti { 00043 /** 00044 * A fast LAPACK-based method for computation of the singular value 00045 * decomposition SVD. Two routines can be chosen via the parameter 00046 * parameters::useDC. If this is true (default) the divide and 00047 * conquer method _GESDD is used which is generally faster 00048 * especially on large data but also requires more workspace. In 00049 * case memory allocation fails when using the faster version, 00050 * choose the simple driver _GESVD by setting parameters::useDC to 00051 * \a false. 00052 * 00053 * The size of the returned matrices depends on the value of 00054 * parameters::useMinDimensions. The input data matrix is of size 00055 * MxN. Let minMN=min(M,N). The vector containing the singular 00056 * values always has the size minMN. If the parameter is true, the 00057 * matrix with left singular vectors U is of size MxminMN and V 00058 * (right SV) is of size minMNxN. Otherwise, U is a MxM and V a NxN 00059 * matrix. 00060 * 00061 * \b Note: The functor returns U and V untransposed to be 00062 * compatible with singularValueDecomp. Both U and V can be 00063 * transposed by the algorithm -- which might even be faster -- by 00064 * setting parameters::transposeU or parameters::transposeV. 00065 * 00066 * The following are the man pages of the two LAPACK functions used: 00067 * ------------------------------------------------------------- 00068 * 00069 * SGESVD computes the singular value decomposition (SVD) of a real 00070 * M-by-N matrix A, optionally computing the left and/or right 00071 * singular vectors. The SVD is written 00072 * 00073 * A = U * SIGMA * transpose(V) 00074 * 00075 * where SIGMA is an M-by-N matrix which is zero except for its 00076 * min(m,n) diago nal elements, U is an M-by-M orthogonal matrix, 00077 * and V is an N-by-N orthogo nal matrix. The diagonal elements of 00078 * SIGMA are the singular values of A; they are real and 00079 * non-negative, and are returned in descending order. The first 00080 * min(m,n) columns of U and V are the left and right singular 00081 * vectors of A. 00082 * 00083 * Note that the routine returns VT = V**T, not V. 00084 * 00085 * --------------------------------------------------------------- 00086 * 00087 * SGESDD computes the singular value decomposition (SVD) of a real 00088 * M-by-N matrix A, optionally computing the left and right singular 00089 * vectors. If sin gular vectors are desired, it uses a 00090 * divide-and-conquer algorithm. 00091 * 00092 * The SVD is written 00093 * 00094 * A = U * SIGMA * transpose(V) 00095 * 00096 * where SIGMA is an M-by-N matrix which is zero except for its 00097 * min(m,n) diago nal elements, U is an M-by-M orthogonal matrix, 00098 * and V is an N-by-N orthogo nal matrix. The diagonal elements of 00099 * SIGMA are the singular values of A; they are real and 00100 * non-negative, and are returned in descending order. The first 00101 * min(m,n) columns of U and V are the left and right singular 00102 * vectors of A. 00103 * 00104 * Note that the routine returns VT = V**T, not V. 00105 * 00106 * The divide and conquer algorithm makes very mild assumptions 00107 * about floating point arithmetic. It will work on machines with a 00108 * guard digit in add/sub tract, or on those binary machines 00109 * without guard digits which subtract like the Cray X-MP, Cray 00110 * Y-MP, Cray C-90, or Cray-2. It could conceivably fail on 00111 * hexadecimal or decimal machines without guard digits, but we know 00112 * of none. 00113 * 00114 * 00115 * @ingroup lapack 00116 * 00117 * @see \ref lapack 00118 */ 00119 template<class T> 00120 class fastSVD : public singularValueDecomp<T>, lapackInterface { 00121 public: 00122 /** 00123 * FastSVD parameter class. \b Note that the sort parameter 00124 * inherited from singularValueDecomp<T> is always true for this 00125 * functor, since sorting is done automatically during computation 00126 * of singular values and vectors. 00127 */ 00128 class parameters : public singularValueDecomp<T>::parameters { 00129 public: 00130 /** 00131 * default constructor 00132 */ 00133 parameters() 00134 : singularValueDecomp<T>::parameters() { 00135 this->sort = true; 00136 useDC = true; 00137 useMinDimensions = true; 00138 }; 00139 00140 /** 00141 * copy constructor 00142 */ 00143 parameters(const parameters& other) { 00144 copy(other); 00145 }; 00146 00147 /** 00148 * If true the divide-and-conquer method for calculating the SVD 00149 * is used. This is generally faster, especially on large 00150 * matrices. However, it uses more temporary memory than the 00151 * simple method. Thus, if the computation fails due to memory 00152 * problems setting this parameter to false might solve the 00153 * problem. Default is true. 00154 */ 00155 bool useDC; 00156 00157 /** 00158 * Let the data matrix have M rows and N columns. Then, usually, 00159 * U will be an MxM orthogonal matrix and V an NxN orthogonal 00160 * matrix. However, there are only min(M,N) singular values. For 00161 * most applications it suffices to calculate only min(M,N) left 00162 * and right singular vectors, which is done when 00163 * useMinDimensions is true (default). All singular values are 00164 * calculated when false. 00165 */ 00166 bool useMinDimensions; 00167 00168 /** 00169 * returns the name of this type 00170 */ 00171 virtual const char* getTypeName() const { 00172 return "fastSVD::parameters"; 00173 }; 00174 00175 /** 00176 * copy member. 00177 */ 00178 parameters& copy(const parameters& other) { 00179 #ifndef _LTI_MSC_6 00180 // MS Visual C++ 6 is not able to compile this... 00181 singularValueDecomp<T>::parameters::copy(other); 00182 #else 00183 // ...so we have to use this workaround. 00184 // Conditional on that, copy may not be virtual. 00185 singularValueDecomp<T>::parameters& 00186 (singularValueDecomp<T>::parameters::* p_copy)(const singularValueDecomp<T>::parameters&) = 00187 singularValueDecomp<T>::parameters::copy; 00188 (this->*p_copy)(other); 00189 #endif 00190 00191 useDC = other.useDC; 00192 useMinDimensions = other.useMinDimensions; 00193 00194 return (*this); 00195 }; 00196 00197 /** 00198 * returns a pointer to a clone of the parameters. 00199 */ 00200 virtual functor::parameters* clone() const { 00201 return (new parameters(*this)); 00202 }; 00203 00204 # ifndef _LTI_MSC_6 00205 /** 00206 * read the parameters from the given ioHandler 00207 * @param handler the ioHandler to be used 00208 * @param complete if true (the default) the enclosing begin/end will 00209 * be also read, otherwise only the data block will be read. 00210 * @return true if write was successful 00211 */ 00212 virtual bool read(ioHandler &handler, const bool complete=true) 00213 # else 00214 bool readMS(ioHandler& handler,const bool complete=true) 00215 # endif 00216 { 00217 bool b=true; 00218 00219 if (complete) { 00220 b=handler.readBegin(); 00221 } 00222 00223 if (b) { 00224 lti::read(handler,"useDC",useDC); 00225 lti::read(handler,"useMinDimensions",useMinDimensions); 00226 } 00227 00228 # ifndef _LTI_MSC_6 00229 // This is the standard C++ code, which MS Visual C++ 6 is not 00230 // able to compile... 00231 b = b && singularValueDecomp<T>::parameters::read(handler,false); 00232 # else 00233 bool (functor::parameters::* p_readMS)(ioHandler&,const bool&) = 00234 functor::parameters::readMS; 00235 b = b && (this->*p_readMS)(handler,false); 00236 # endif 00237 00238 if (complete) { 00239 b=b && handler.readEnd(); 00240 } 00241 00242 return b; 00243 } 00244 00245 # ifdef _LTI_MSC_6 00246 /** 00247 * read the parameters from the given ioHandler 00248 * @param handler the ioHandler to be used 00249 * @param complete if true (the default) the enclosing begin/end will 00250 * be also read, otherwise only the data block will be read. 00251 * @return true if write was successful 00252 */ 00253 virtual bool read(ioHandler& handler,const bool complete=true) { 00254 // ...we need this workaround to cope with another really awful MSVC 00255 // bug. 00256 return readMS(handler,complete); 00257 } 00258 # endif 00259 00260 # ifndef _LTI_MSC_6 00261 /** 00262 * write the parameters in the given ioHandler 00263 * @param handler the ioHandler to be used 00264 * @param complete if true (the default) the enclosing begin/end will 00265 * be also written, otherwise only the data block will be 00266 * written. 00267 * @return true if write was successful 00268 */ 00269 virtual bool write(ioHandler& handler,const bool complete=true) const 00270 # else 00271 bool writeMS(ioHandler& handler,const bool complete=true) const 00272 # endif 00273 { 00274 bool b=true; 00275 00276 if (complete) { 00277 b=handler.writeBegin(); 00278 } 00279 00280 if (b) { 00281 lti::write(handler,"useDC",useDC); 00282 lti::write(handler,"useMinDimensions",useMinDimensions); 00283 } 00284 00285 # ifndef _LTI_MSC_6 00286 // This is the standard C++ code, which MS Visual C++ 6 is not 00287 // able to compile... 00288 b = b && singularValueDecomp<T>::parameters::write(handler,false); 00289 # else 00290 bool 00291 (functor::parameters::* p_writeMS)(ioHandler&,const bool&) const = 00292 functor::parameters::writeMS; 00293 b = b && (this->*p_writeMS)(handler,false); 00294 # endif 00295 00296 if (complete) { 00297 b=b && handler.writeEnd(); 00298 } 00299 00300 return b; 00301 } 00302 00303 # ifdef _LTI_MSC_6 00304 /** 00305 * write the parameters to the given ioHandler 00306 * @param handler the ioHandler to be used 00307 * @param complete if true (the default) the enclosing begin/end will 00308 * be also writen, otherwise only the data block will be writen. 00309 * @return true if write was successful 00310 */ 00311 virtual bool write(ioHandler& handler,const bool complete=true) { 00312 // ...we need this workaround to cope with another really awful MSVC 00313 // bug. 00314 return writeMS(handler,complete); 00315 } 00316 # endif 00317 00318 }; 00319 00320 /** 00321 * default constructor 00322 */ 00323 fastSVD(); 00324 00325 /** 00326 * constructor, sets the parameters 00327 */ 00328 fastSVD(const parameters& theParams); 00329 00330 /** 00331 * destructor 00332 */ 00333 virtual ~fastSVD(); 00334 00335 /** 00336 * returns the current parameters. 00337 */ 00338 const parameters& getParameters() const; 00339 00340 /** 00341 * clone this functor 00342 */ 00343 virtual functor* clone() const; 00344 00345 /** 00346 * Computes singular values as well as left and right singular 00347 * values. The method used for calculating the SVD is set by 00348 * parameters::useDC. The number of singular values is set by 00349 * parameters::useMinDimensions. Both the \a leftSV (U) and the \a 00350 * rightSV (V) can be transposed by setting parameters::transposeU 00351 * and parameters::transposeV, respectively. 00352 * 00353 * @param theMatrix data matrix with M rows and N columns. 00354 * @param leftSV left singular vectors in M or min(M,N) columns. 00355 * @param singularValues min(M,N) singular values 00356 * @param rightSV right singular vectors in N or min(M,N) columns. 00357 */ 00358 virtual bool apply(const matrix<T>& theMatrix, 00359 matrix<T>& leftSV, 00360 vector<T>& singularValues, 00361 matrix<T>& rightSV) const; 00362 00363 /** 00364 * On place version that computes singular values as well as left 00365 * and right singular values. The method used for calculating the 00366 * SVD is set by parameters::useDC. The number of singular values 00367 * is set by parameters::useMinDimensions. The \a rightSV (V) can 00368 * be transposed by setting parameters::transposeV. The parameter 00369 * parameters::transposeU has no effect. 00370 * 00371 * The left singular vectors are returned in \a theMatrix which 00372 * has M rows and N columns. If M>N only the first N left singular 00373 * values are returned in \a theMatrix. If M<=N all M left 00374 * singular values are returned in the first M columns of \a 00375 * theMatrix. 00376 * 00377 * @param theMatrix data matrix with M rows and N columns. 00378 * @param singularValues min(M,N) singular values 00379 * @param rightSV right singular vectors in N or min(M,N) columns. 00380 */ 00381 virtual bool apply(matrix<T>& theMatrix, 00382 vector<T>& singularValues, 00383 matrix<T>& rightSV) const; 00384 00385 00386 00387 /** 00388 * returns the name of this type 00389 */ 00390 virtual const char* getTypeName() const { 00391 return "fastSVD"; 00392 }; 00393 00394 private: 00395 // lapack routine in template form 00396 00397 int svd(char* jobu, char* jobvt, 00398 integer* m, integer* n, T* a, integer* lda, 00399 T* s, T* u, integer* ldu, T* vt, integer* ldvt, 00400 T* work, integer* lwork, 00401 integer* info) const; 00402 00403 int sdd(char* jobz, integer* m, integer* n, T* a, integer* lda, 00404 T* s, T* u, integer* ldu, T* vt, integer* ldvt, 00405 T* work, integer* lwork, integer* iwork, 00406 integer* info) const; 00407 }; 00408 00409 } 00410 00411 #endif 00412 #endif