last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998-2005 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 /** 00042 * \file cvrQrDecomposition.h 00043 * Compute the QR decomposition of a matrix. 00044 * \author Arnd Hannemann 00045 * \date 26.01.2004 00046 * 00047 * $Id: cvrQrDecomposition.h,v 1.12 2006/09/07 13:38:37 doerfler Exp $ 00048 */ 00049 00050 #ifndef _CVR_QR_DECOMPOSITION_H_ 00051 #define _CVR_QR_DECOMPOSITION_H_ 00052 00053 00054 #include "cvrMatrix.h" 00055 #include "cvrLinearAlgebraFunctor.h" 00056 #include "cvrPerformanceConfig.h" 00057 00058 #ifdef HAVE_LAPACK 00059 #include "cvrLapackInterface.h" 00060 #endif 00061 00062 namespace cvr { 00063 /** 00064 * This functor computes a QRDecomposition of a given rectangular 00065 * m x n Matrix A of the Form: 00066 * 00067 * A = Q * R 00068 * 00069 * Where R is an upper triangular m x m Matrix and Q is a m x n orthogonal 00070 * matrix, i.e. the transposed matrix of Q multiplied with Q itself is the 00071 * identity matrix. 00072 * 00073 * If LAPACK is not used or not available, A \b must be of full rank! 00074 * 00075 * \code 00076 * matrix<float> src(3,3); 00077 * float data[] = {1,2,3,4,5,6,7,8,9}; 00078 * src.fill(data); 00079 * matrix<float> q,r; 00080 * 00081 * qrDecomposition<float> qrd; 00082 * qrd.apply(src,q,r); 00083 * 00084 * matrix<float> result; 00085 * result.multiply(q,r); 00086 * 00087 * std::cout << "Q:\n" << q << "\n"; 00088 * std::cout << "R:\n" << r << "\n"; 00089 * // should be identical to src 00090 * std::cout << "A = Q * R:\n"<< result << "\n"; 00091 * 00092 * \endcode 00093 * 00094 * \ingroup gLinearAlgebra 00095 */ 00096 template<typename T> 00097 class qrDecomposition : public linearAlgebraFunctor 00098 #ifdef HAVE_LAPACK 00099 , public lapackInterface 00100 #endif 00101 { 00102 00103 public: 00104 /** 00105 * The parameters for the class qrDecomposition 00106 */ 00107 class parameters : public linearAlgebraFunctor::parameters { 00108 public: 00109 00110 /** 00111 * Default constructor 00112 */ 00113 parameters(); 00114 00115 /** 00116 * Copy constructor 00117 * @param other the parameters object to be copied 00118 */ 00119 parameters(const parameters& other); 00120 00121 /** 00122 * Destructor 00123 */ 00124 ~parameters(); 00125 00126 /** 00127 * Copy the contents of a parameters object 00128 * @param other the parameters object to be copied 00129 * @return a reference to this parameters object 00130 */ 00131 parameters& copy(const parameters& other); 00132 00133 /** 00134 * Copy the contents of a parameters object 00135 * @param other the parameters object to be copied 00136 * @return a reference to this parameters object 00137 */ 00138 parameters& operator=(const parameters& other); 00139 00140 /** 00141 * Returns the name of this class. 00142 */ 00143 const std::string& name() const; 00144 00145 /** 00146 * Returns a pointer to a clone of the parameters 00147 */ 00148 virtual parameters* clone() const; 00149 00150 /** 00151 * Returns a pointer to a clone of the parameters 00152 */ 00153 virtual parameters* newInstance() const; 00154 00155 /** 00156 * write the parameters in the given ioHandler 00157 * @param handler the ioHandler to be used 00158 * @param complete if true (the default) the enclosing begin/end will 00159 * be also written, otherwise only the data block will be written. 00160 * @return true if write was successful 00161 */ 00162 virtual bool write(ioHandler& handler, const bool complete=true) const; 00163 00164 /** 00165 * read the parameters from 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 read(ioHandler& handler, const bool complete=true); 00172 00173 // ------------------------------------------------ 00174 // the parameters 00175 // ------------------------------------------------ 00176 00177 /** 00178 * Specifies above which matrix size, the matrix is internally 00179 * transposed. 00180 * 00181 * This parameter takes only effect if useLapack is false or LAPACK is 00182 * not available. 00183 * 00184 * Due to memory access issues, the algorithm works a lot faster 00185 * especially for large matrices. 00186 * 00187 * Both, columns and rows are checked against this value. So a 00188 * value of 50 means that the matrix must have at least 51 rows 00189 * <b>and</b> at least 51 columns to be transposed. 00190 * 00191 * 00192 * Default: _CVR_PERFORMANCE_QR_DECOMPOSITION in cvrPerformanceConfig.h 00193 */ 00194 int performanceTweakThresholdForTranspose; 00195 00196 }; 00197 00198 /** 00199 * Default constructor 00200 */ 00201 qrDecomposition(); 00202 00203 /** 00204 * Construct a functor using the given parameters 00205 */ 00206 qrDecomposition(const parameters& par); 00207 00208 /** 00209 * Copy constructor 00210 * @param other the object to be copied 00211 */ 00212 qrDecomposition(const qrDecomposition& other); 00213 00214 /** 00215 * Destructor 00216 */ 00217 virtual ~qrDecomposition(); 00218 00219 /** 00220 * Apply QR using column pivoting (in place) 00221 * 00222 * @param arh The source matrix on input, and on output 00223 * the compact representation (R + elementary reflectors) 00224 * @param tau The beta components on output 00225 * @param p The column permutation vector on output 00226 * @return true if the application was successful, false otherwise 00227 */ 00228 bool apply(matrix<T>& arh, vector<T>& tau, vector<integer>& p) const; 00229 00230 /** 00231 * Apply QR using column pivoting (on copy) 00232 * 00233 * @param a The source matrix on input 00234 * @param rh The compact representation (R + elementary reflectors) on 00235 * output 00236 * @param tau The beta components on output 00237 * @param p The column permutation vector on output 00238 * @return true if the application was successful, false otherwise 00239 */ 00240 bool apply(const matrix<T>& a, 00241 matrix<T>& rh, 00242 vector<T>& tau, 00243 vector<integer>& p) const; 00244 00245 /** 00246 * Apply QR (in place) 00247 * 00248 * @param arh The source matrix on input, and on output 00249 * the compact representation (R + elementary reflectors) 00250 * @param tau The beta components on output 00251 * @return true if the application was successful, false otherwise 00252 */ 00253 bool apply(matrix<T>& arh, vector<T>& tau) const; 00254 00255 /** 00256 * Apply QR (on copy) 00257 * 00258 * @param a The source matrix on input 00259 * @param rh The compact representation (R + elementary 00260 * reflectors) on output 00261 * @param tau The beta components on output 00262 * @return true if the application was successful, false otherwise 00263 */ 00264 bool apply(const matrix<T>& a, matrix<T>& rh, vector<T>& tau) const; 00265 00266 /** 00267 * Extract R from RH. 00268 * 00269 * @param rh The compact representation (R + elementary reflectors) 00270 * on input 00271 * @param r R on output 00272 */ 00273 bool extractR(const matrix<T>& rh, matrix<T>& r) const; 00274 00275 /** 00276 * Compute Q from RH and tau. 00277 * 00278 * @param rh The compact representation (R + elementary reflectors) 00279 * on input 00280 * @param tau The beta components on input 00281 * @param q Q on output 00282 */ 00283 bool computeQ(const matrix<T>& rh, vector<T>& tau, matrix<T>& q) const; 00284 00285 /** 00286 * Builds the permutation matrix for the given permutation vector 00287 * 00288 * @param pv The column permutation vector on input 00289 * @param pm The column permutation matrix on output 00290 */ 00291 void buildPermutationMatrix(const vector<integer>& pv, 00292 matrix<T>& pm) const; 00293 00294 /** 00295 * Computes the QR decomposition. 00296 * 00297 * \warning You usually don't need this explicit decomposition, since most 00298 * methods use the compact outputs of the other apply() to speed up the 00299 * computations. However, this is provided for completeness. 00300 * 00301 * @param A input m x n matrix. 00302 * @param Q Q is a m x n orthogonal matrix. 00303 * @param R R is an upper triangular m x m matrix. 00304 * @return \c true if successful or \c false otherwise. 00305 */ 00306 bool apply(const matrix<T>& A, 00307 matrix<T>& Q, 00308 matrix<T>& R) const; 00309 00310 /** 00311 * Copy data of "other" functor. 00312 * @param other the functor to be copied 00313 * @return a reference to this functor object 00314 */ 00315 qrDecomposition& copy(const qrDecomposition& other); 00316 00317 /** 00318 * Alias for copy member. 00319 * @param other the functor to be copied 00320 * @return a reference to this functor object 00321 */ 00322 qrDecomposition& operator=(const qrDecomposition& other); 00323 00324 /** 00325 * Returns the name of this class. 00326 */ 00327 const std::string& name() const; 00328 00329 /** 00330 * Returns a pointer to a clone of this functor. 00331 */ 00332 virtual qrDecomposition<T>* clone() const; 00333 00334 /** 00335 * Returns a pointer to a clone of this functor. 00336 */ 00337 virtual qrDecomposition<T>* newInstance() const; 00338 00339 /** 00340 * Returns used parameters 00341 */ 00342 const parameters& getParameters() const; 00343 00344 private: 00345 00346 #ifdef HAVE_LAPACK 00347 00348 // LAPACK routines in template form 00349 00350 /* *GEQRF computes a QR factorization of a real M-by-N matrix A: 00351 * A = Q * R. */ 00352 int geqrf(integer* rows, integer* cols, T* a, integer* lda, T* tau, 00353 T* work, integer* lwork, integer* info) const; 00354 00355 /* *ORGQR generates an M-by-N real matrix Q with orthonormal columns, 00356 * which is defined as the first N columns of a product of K elementary 00357 * reflectors of order M 00358 * 00359 * Q = H(1) H(2) . . . H(k) 00360 * 00361 * as returned by SGEQRF. */ 00362 int orgqr(integer* rows, integer* cols, integer* k,T* a, integer* lda, 00363 T* tau, T* work, integer* lwork, integer* info) const; 00364 00365 /* *GEQP3 computes a QR factorization with column pivoting of a 00366 * matrix A: A*P = Q*R using Level 3 BLAS. */ 00367 int geqp3(integer* rows, integer* cols, T* a, integer* lda, integer *jpvt, 00368 T* tau, T* work, integer* lwork, integer* info) const; 00369 00370 #endif 00371 00372 /** 00373 * Implementation of QR decomposition using Householder reflections. 00374 * The boolean parameter 'useColumnPivoting'specifies if column 00375 * pivoting should be used. If so, the permutation vector p will contain 00376 * the result of the columnwise pivoting. 00377 * 00378 * @param arh On input, the input matrix. 00379 * On output, the compact form representation 00380 * of R and the essential parts of the Householder vectors. 00381 * @param tau On output, the beta components. 00382 * @param p On output, the permutation vector if useColumnPivoting 00383 * was set to true. 00384 * @param useColumnPivoting Determines if column pivoting should be used 00385 * @return true if the computation was succesfull, false otherwise. 00386 */ 00387 bool computeHouseholderQr(matrix<T>& arh, 00388 vector<T>& tau, 00389 vector<integer>& p, 00390 bool useColumnPivoting) const; 00391 00392 }; 00393 00394 } 00395 00396 #endif