latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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 .......: ltiQrDecomposition.h 00027 * authors ....: Arnd Hannemann 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 26.1.2004 00030 * revisions ..: $Id: ltiQrDecomposition.h,v 1.10 2006/09/11 17:05:13 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_QR_DECOMPOSITION_H_ 00034 #define _LTI_QR_DECOMPOSITION_H_ 00035 00036 00037 #include "ltiMatrix.h" 00038 #include "ltiLinearAlgebraFunctor.h" 00039 #include "ltiPerformanceConfig.h" 00040 00041 #ifdef HAVE_LAPACK 00042 #include "ltiLapackInterface.h" 00043 #endif 00044 00045 namespace lti { 00046 /** 00047 * This functor computes a QRDecomposition of a given rectangular 00048 * m x n Matrix A of the Form: 00049 * 00050 * A = Q * R 00051 * 00052 * Where R is an upper triangular m x m Matrix and Q is a 00053 * m x n orthogonal matrix. 00054 * Transpose of Q muliplied with Q itself is the identity Matrix. 00055 * 00056 * If LAPACK is not used or not available, A <b>must</b> be of full rang! 00057 * 00058 * \code 00059 * matrix<float> src(3,3); 00060 * float data[] = {1,2,3,4,5,6,7,8,9}; 00061 * src.fill(data); 00062 * matrix<float> q,r; 00063 * 00064 * qrDecomposition<float> qrd; 00065 * qrd.apply(src,q,r); 00066 * 00067 * matrix<float> result; 00068 * result.multiply(q,r); 00069 * 00070 * std::cout << "Q:\n" << q << "\n"; 00071 * std::cout << "R:\n" << r << "\n"; 00072 * // should be identical to src 00073 * std::cout << "A = Q * R:\n"<< result << "\n"; 00074 * 00075 * \endcode 00076 */ 00077 template <class T> 00078 #ifdef HAVE_LAPACK 00079 class qrDecomposition : public linearAlgebraFunctor, lapackInterface { 00080 #else 00081 class qrDecomposition : public linearAlgebraFunctor { 00082 #endif 00083 public: 00084 /** 00085 * The parameters for the class qrDecomposition 00086 */ 00087 class parameters : public linearAlgebraFunctor::parameters { 00088 public: 00089 00090 /** 00091 * Default constructor 00092 */ 00093 parameters() : linearAlgebraFunctor::parameters() { 00094 useLapack = true; 00095 performanceTweakThresholdForTranspose = 00096 _LTI_PERFORMANCE_QR_DECOMPOSITION; 00097 }; 00098 00099 /** 00100 * Copy constructor 00101 * @param other the parameters object to be copied 00102 */ 00103 parameters(const parameters& other) 00104 : linearAlgebraFunctor::parameters() { 00105 copy(other); 00106 }; 00107 00108 /** 00109 * Destructor 00110 */ 00111 ~parameters() { 00112 }; 00113 00114 /** 00115 * Returns name of this type 00116 */ 00117 const char* getTypeName() const { 00118 return "qrDecomposition<T>::parameters"; 00119 }; 00120 00121 /** 00122 * Copy the contents of a parameters object 00123 * @param other the parameters object to be copied 00124 * @return a reference to this parameters object 00125 */ 00126 parameters& copy(const parameters& other) { 00127 # ifndef _LTI_MSC_6 00128 // MS Visual C++ 6 is not able to compile this... 00129 linearAlgebraFunctor::parameters::copy(other); 00130 # else 00131 // ...so we have to use this workaround. 00132 // Conditional on that, copy may not be virtual. 00133 linearAlgebraFunctor::parameters& (linearAlgebraFunctor::parameters::* p_copy) 00134 (const linearAlgebraFunctor::parameters&) = 00135 linearAlgebraFunctor::parameters::copy; 00136 (this->*p_copy)(other); 00137 # endif 00138 00139 useLapack = other.useLapack; 00140 performanceTweakThresholdForTranspose = 00141 other.performanceTweakThresholdForTranspose; 00142 00143 return *this; 00144 }; 00145 00146 /** 00147 * Copy the contents of a parameters object 00148 * @param other the parameters object to be copied 00149 * @return a reference to this parameters object 00150 */ 00151 parameters& operator=(const parameters& other) { 00152 return copy(other); 00153 }; 00154 00155 00156 /** 00157 * Returns a pointer to a clone of the parameters 00158 */ 00159 virtual functor::parameters* clone() const { 00160 return new parameters(*this); 00161 }; 00162 00163 # ifndef _LTI_MSC_6 00164 /** 00165 * write the parameters in the given ioHandler 00166 * @param handler the ioHandler to be used 00167 * @param complete if true (the default) the enclosing begin/end will 00168 * be also written, otherwise only the data block will be written. 00169 * @return true if write was successful 00170 */ 00171 virtual bool write(ioHandler& handler,const bool complete=true) const 00172 # else 00173 /** 00174 * this function is required by MSVC only, as a workaround for a 00175 * very awful bug, which exists since MSVC V.4.0, and still by 00176 * V.6.0 with all bugfixes (so called "service packs") remains 00177 * there... This method is also public due to another bug, so please 00178 * NEVER EVER call this method directly: use write() instead 00179 */ 00180 bool writeMS(ioHandler& handler,const bool complete=true) const 00181 # endif 00182 { 00183 bool b = true; 00184 if (complete) { 00185 b = handler.writeBegin(); 00186 } 00187 00188 if (b) { 00189 00190 } 00191 00192 # ifndef _LTI_MSC_6 00193 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00194 // compile... 00195 b = b && linearAlgebraFunctor::parameters::write(handler,false); 00196 # else 00197 bool (linearAlgebraFunctor::parameters::* p_writeMS)(ioHandler&, 00198 const bool) const = 00199 linearAlgebraFunctor::parameters::writeMS; 00200 b = b && (this->*p_writeMS)(handler,false); 00201 # endif 00202 b = b && lti::write(handler, "useLapack", useLapack); 00203 b = b && lti::write(handler, "performanceTweakThresholdForTranspose", 00204 performanceTweakThresholdForTranspose); 00205 00206 if (complete) { 00207 b = b && handler.writeEnd(); 00208 } 00209 00210 return b; 00211 } 00212 00213 # ifdef _LTI_MSC_6 00214 /** 00215 * write the parameters in the given ioHandler 00216 * @param handler the ioHandler to be used 00217 * @param complete if true (the default) the enclosing begin/end will 00218 * be also written, otherwise only the data block will be written. 00219 * @return true if write was successful 00220 */ 00221 bool write(ioHandler& handler, 00222 const bool complete=true) const { 00223 // ...we need this workaround to cope with another really 00224 // awful MSVC bug. 00225 return writeMS(handler,complete); 00226 } 00227 # endif 00228 00229 00230 # ifndef _LTI_MSC_6 00231 /** 00232 * read the parameters from the given ioHandler 00233 * @param handler the ioHandler to be used 00234 * @param complete if true (the default) the enclosing begin/end will 00235 * be also written, otherwise only the data block will be written. 00236 * @return true if write was successful 00237 */ 00238 virtual bool read(ioHandler& handler,const bool complete=true) 00239 # else 00240 /** 00241 * this function is required by MSVC only, as a workaround for a 00242 * very awful bug, which exists since MSVC V.4.0, and still by 00243 * V.6.0 with all bugfixes (so called "service packs") remains 00244 * there... This method is also public due to another bug, so please 00245 * NEVER EVER call this method directly: use read() instead 00246 */ 00247 bool readMS(ioHandler& handler,const bool complete=true) 00248 # endif 00249 { 00250 bool b = true; 00251 if (complete) { 00252 b = handler.readBegin(); 00253 } 00254 00255 if (b) { 00256 00257 } 00258 00259 # ifndef _LTI_MSC_6 00260 // This is the standard C++ code, which MS Visual C++ 6 is not 00261 // able to compile... 00262 b = b && linearAlgebraFunctor::parameters::read(handler,false); 00263 # else 00264 bool (linearAlgebraFunctor::parameters::* p_readMS)(ioHandler&, 00265 const bool) = 00266 linearAlgebraFunctor::parameters::readMS; 00267 b = b && (this->*p_readMS)(handler,false); 00268 # endif 00269 b = b && lti::read(handler, "useLapack", useLapack); 00270 b = b && lti::read(handler, "performanceTweakThresholdForTranspose", 00271 performanceTweakThresholdForTranspose); 00272 00273 if (complete) { 00274 b = b && handler.readEnd(); 00275 } 00276 00277 return b; 00278 } 00279 00280 # ifdef _LTI_MSC_6 00281 /** 00282 * read the parameters from the given ioHandler 00283 * @param handler the ioHandler to be used 00284 * @param complete if true (the default) the enclosing begin/end will 00285 * be also written, otherwise only the data block will be written. 00286 * @return true if write was successful 00287 */ 00288 bool read(ioHandler& handler,const bool complete=true) { 00289 // ...we need this workaround to cope with another really awful MSVC 00290 // bug. 00291 return readMS(handler,complete); 00292 } 00293 # endif 00294 00295 // ------------------------------------------------ 00296 // the parameters 00297 // ------------------------------------------------ 00298 00299 /** 00300 * specifies if the lapack routine is used (if available) 00301 * for qr-decomposition. 00302 * If LAPACK is not used or not available, A <b>must</b> be of full rang! 00303 * 00304 * Default: true */ 00305 bool useLapack; 00306 00307 /** 00308 * Specifies above which matrix size, the matrix is internally transposed. 00309 * This parameter takes only effect if useLapack is false or LAPACK is 00310 * not available. 00311 * Due to memory access isues, the algorithm works a lot faster 00312 * especially for large matrices. 00313 * Both, collumns and rows are checked against this value. So a value of 50 00314 * means that the matrix must have at least 51 rows <b>and</b> at least 51 00315 * columns to be transposed. 00316 * 00317 * 00318 * Default: _LTI_PERFORMANCE_QR_DECOMPOSITION in ltiPerformanceConfig.h 00319 */ 00320 int performanceTweakThresholdForTranspose; 00321 00322 }; 00323 00324 /** 00325 * Default constructor 00326 */ 00327 qrDecomposition(); 00328 00329 /** 00330 * Construct a functor using the given parameters 00331 */ 00332 qrDecomposition(const parameters& par); 00333 00334 /** 00335 * Copy constructor 00336 * @param other the object to be copied 00337 */ 00338 qrDecomposition(const qrDecomposition& other); 00339 00340 /** 00341 * Destructor 00342 */ 00343 virtual ~qrDecomposition(); 00344 00345 /** 00346 * Returns the name of this type ("qrDecomposition") 00347 */ 00348 virtual const char* getTypeName() const; 00349 00350 //TODO: comment your apply methods! 00351 00352 00353 /** 00354 * operates on the given %parameter. 00355 * @param srcdest matrix<T> with the source data. The resulting Q 00356 * will be left here too. 00357 * @param r matrix<T> where R will be left. 00358 * @return true if apply successful or false otherwise. 00359 */ 00360 bool apply(matrix<T>& srcdest, matrix<T>& r) const; 00361 00362 00363 /** 00364 * operates on a copy of the given %parameters. 00365 * @param src matrix<T> with the source data. 00366 * @param q matrix<T> where Q will be left. 00367 * @param r matrix<T> where R will be left. 00368 * @return true if apply successful or false otherwise. 00369 */ 00370 bool apply(const matrix<T>& src, matrix<T>& q, matrix<T>& r) const; 00371 00372 /** 00373 * Copy data of "other" functor. 00374 * @param other the functor to be copied 00375 * @return a reference to this functor object 00376 */ 00377 qrDecomposition& copy(const qrDecomposition& other); 00378 00379 /** 00380 * Alias for copy member 00381 * @param other the functor to be copied 00382 * @return a reference to this functor object 00383 */ 00384 qrDecomposition& operator=(const qrDecomposition& other); 00385 00386 /** 00387 * Returns a pointer to a clone of this functor. 00388 */ 00389 virtual functor* clone() const; 00390 00391 /** 00392 * Returns used parameters 00393 */ 00394 const parameters& getParameters() const; 00395 00396 //TODO: comment the attributes of your functor 00397 // If you add more attributes manually, do not forget to do following: 00398 // 1. indicate in the default constructor the default values 00399 // 2. make sure that the copy member also copy your new attributes, or 00400 // to ensure there, that these attributes are properly initialized. 00401 00402 private: 00403 00404 /* 00405 * transpose the given matrix perform a column based algorithm and 00406 * transpose result again. 00407 * r must be initiated before invokation 00408 */ 00409 bool transApply(matrix<T>& srcdest, matrix<T>& r) const; 00410 00411 00412 #ifdef HAVE_LAPACK 00413 // LAPACK routines in template form 00414 00415 /* SGEQRF computes a QR factorization of a real M-by-N matrix A: 00416 * A = Q * R. */ 00417 int geqrf(integer* rows, integer* cols, T* a, integer* lda, T* tau, 00418 T* work, integer* lwork, integer* info) const; 00419 00420 00421 /* SORGQR generates an M-by-N real matrix Q with orthonormal columns, 00422 * which is defined as the first N columns of a product of K elementary 00423 * reflectors of order M 00424 * 00425 * Q = H(1) H(2) . . . H(k) 00426 * 00427 * as returned by SGEQRF. */ 00428 int orgqr(integer* rows, integer* cols, integer* k,T* a, integer* lda, 00429 T* tau, T* work, integer* lwork, integer* info) const; 00430 #endif 00431 00432 00433 }; 00434 } 00435 00436 #endif