Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ColPivHouseholderQR.h
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> 00005 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> 00006 // 00007 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_H 00012 #define EIGEN_COLPIVOTINGHOUSEHOLDERQR_H 00013 00014 namespace Eigen { 00015 00016 /** \ingroup QR_Module 00017 * 00018 * \class ColPivHouseholderQR 00019 * 00020 * \brief Householder rank-revealing QR decomposition of a matrix with column-pivoting 00021 * 00022 * \param MatrixType the type of the matrix of which we are computing the QR decomposition 00023 * 00024 * This class performs a rank-revealing QR decomposition of a matrix \b A into matrices \b P, \b Q and \b R 00025 * such that 00026 * \f[ 00027 * \mathbf{A} \, \mathbf{P} = \mathbf{Q} \, \mathbf{R} 00028 * \f] 00029 * by using Householder transformations. Here, \b P is a permutation matrix, \b Q a unitary matrix and \b R an 00030 * upper triangular matrix. 00031 * 00032 * This decomposition performs column pivoting in order to be rank-revealing and improve 00033 * numerical stability. It is slower than HouseholderQR, and faster than FullPivHouseholderQR. 00034 * 00035 * \sa MatrixBase::colPivHouseholderQr() 00036 */ 00037 template<typename _MatrixType> class ColPivHouseholderQR 00038 { 00039 public: 00040 00041 typedef _MatrixType MatrixType; 00042 enum { 00043 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 00044 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 00045 Options = MatrixType::Options, 00046 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 00047 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 00048 }; 00049 typedef typename MatrixType::Scalar Scalar; 00050 typedef typename MatrixType::RealScalar RealScalar; 00051 typedef typename MatrixType::Index Index; 00052 typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, Options, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType; 00053 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType; 00054 typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType ; 00055 typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType; 00056 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType; 00057 typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType; 00058 typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type > HouseholderSequenceType ; 00059 00060 private: 00061 00062 typedef typename PermutationType::Index PermIndexType; 00063 00064 public: 00065 00066 /** 00067 * \brief Default Constructor. 00068 * 00069 * The default constructor is useful in cases in which the user intends to 00070 * perform decompositions via ColPivHouseholderQR::compute(const MatrixType&). 00071 */ 00072 ColPivHouseholderQR() 00073 : m_qr(), 00074 m_hCoeffs(), 00075 m_colsPermutation(), 00076 m_colsTranspositions(), 00077 m_temp(), 00078 m_colSqNorms(), 00079 m_isInitialized(false), 00080 m_usePrescribedThreshold(false) {} 00081 00082 /** \brief Default Constructor with memory preallocation 00083 * 00084 * Like the default constructor but with preallocation of the internal data 00085 * according to the specified problem \a size. 00086 * \sa ColPivHouseholderQR() 00087 */ 00088 ColPivHouseholderQR(Index rows, Index cols) 00089 : m_qr(rows, cols), 00090 m_hCoeffs((std::min)(rows,cols)), 00091 m_colsPermutation(PermIndexType(cols)), 00092 m_colsTranspositions(cols), 00093 m_temp(cols), 00094 m_colSqNorms(cols), 00095 m_isInitialized(false), 00096 m_usePrescribedThreshold(false) {} 00097 00098 /** \brief Constructs a QR factorization from a given matrix 00099 * 00100 * This constructor computes the QR factorization of the matrix \a matrix by calling 00101 * the method compute(). It is a short cut for: 00102 * 00103 * \code 00104 * ColPivHouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols()); 00105 * qr.compute(matrix); 00106 * \endcode 00107 * 00108 * \sa compute() 00109 */ 00110 ColPivHouseholderQR(const MatrixType& matrix) 00111 : m_qr(matrix.rows(), matrix.cols()), 00112 m_hCoeffs((std::min)(matrix.rows(),matrix.cols())), 00113 m_colsPermutation(PermIndexType(matrix.cols())), 00114 m_colsTranspositions(matrix.cols()), 00115 m_temp(matrix.cols()), 00116 m_colSqNorms(matrix.cols()), 00117 m_isInitialized(false), 00118 m_usePrescribedThreshold(false) 00119 { 00120 compute(matrix); 00121 } 00122 00123 /** This method finds a solution x to the equation Ax=b, where A is the matrix of which 00124 * *this is the QR decomposition, if any exists. 00125 * 00126 * \param b the right-hand-side of the equation to solve. 00127 * 00128 * \returns a solution. 00129 * 00130 * \note The case where b is a matrix is not yet implemented. Also, this 00131 * code is space inefficient. 00132 * 00133 * \note_about_checking_solutions 00134 * 00135 * \note_about_arbitrary_choice_of_solution 00136 * 00137 * Example: \include ColPivHouseholderQR_solve.cpp 00138 * Output: \verbinclude ColPivHouseholderQR_solve.out 00139 */ 00140 template<typename Rhs> 00141 inline const internal::solve_retval<ColPivHouseholderQR, Rhs> 00142 solve(const MatrixBase<Rhs>& b) const 00143 { 00144 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00145 return internal::solve_retval<ColPivHouseholderQR, Rhs>(*this, b.derived()); 00146 } 00147 00148 HouseholderSequenceType householderQ (void) const; 00149 HouseholderSequenceType matrixQ(void) const 00150 { 00151 return householderQ (); 00152 } 00153 00154 /** \returns a reference to the matrix where the Householder QR decomposition is stored 00155 */ 00156 const MatrixType& matrixQR () const 00157 { 00158 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00159 return m_qr; 00160 } 00161 00162 /** \returns a reference to the matrix where the result Householder QR is stored 00163 * \warning The strict lower part of this matrix contains internal values. 00164 * Only the upper triangular part should be referenced. To get it, use 00165 * \code matrixR().template triangularView<Upper>() \endcode 00166 * For rank-deficient matrices, use 00167 * \code 00168 * matrixR().topLeftCorner(rank(), rank()).template triangularView<Upper>() 00169 * \endcode 00170 */ 00171 const MatrixType& matrixR () const 00172 { 00173 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00174 return m_qr; 00175 } 00176 00177 ColPivHouseholderQR& compute(const MatrixType& matrix); 00178 00179 /** \returns a const reference to the column permutation matrix */ 00180 const PermutationType & colsPermutation () const 00181 { 00182 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00183 return m_colsPermutation; 00184 } 00185 00186 /** \returns the absolute value of the determinant of the matrix of which 00187 * *this is the QR decomposition. It has only linear complexity 00188 * (that is, O(n) where n is the dimension of the square matrix) 00189 * as the QR decomposition has already been computed. 00190 * 00191 * \note This is only for square matrices. 00192 * 00193 * \warning a determinant can be very big or small, so for matrices 00194 * of large enough dimension, there is a risk of overflow/underflow. 00195 * One way to work around that is to use logAbsDeterminant() instead. 00196 * 00197 * \sa logAbsDeterminant(), MatrixBase::determinant() 00198 */ 00199 typename MatrixType::RealScalar absDeterminant () const; 00200 00201 /** \returns the natural log of the absolute value of the determinant of the matrix of which 00202 * *this is the QR decomposition. It has only linear complexity 00203 * (that is, O(n) where n is the dimension of the square matrix) 00204 * as the QR decomposition has already been computed. 00205 * 00206 * \note This is only for square matrices. 00207 * 00208 * \note This method is useful to work around the risk of overflow/underflow that's inherent 00209 * to determinant computation. 00210 * 00211 * \sa absDeterminant(), MatrixBase::determinant() 00212 */ 00213 typename MatrixType::RealScalar logAbsDeterminant () const; 00214 00215 /** \returns the rank of the matrix of which *this is the QR decomposition. 00216 * 00217 * \note This method has to determine which pivots should be considered nonzero. 00218 * For that, it uses the threshold value that you can control by calling 00219 * setThreshold(const RealScalar&). 00220 */ 00221 inline Index rank () const 00222 { 00223 using std::abs; 00224 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00225 RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold(); 00226 Index result = 0; 00227 for(Index i = 0; i < m_nonzero_pivots; ++i) 00228 result += (abs(m_qr.coeff(i,i)) > premultiplied_threshold); 00229 return result; 00230 } 00231 00232 /** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition. 00233 * 00234 * \note This method has to determine which pivots should be considered nonzero. 00235 * For that, it uses the threshold value that you can control by calling 00236 * setThreshold(const RealScalar&). 00237 */ 00238 inline Index dimensionOfKernel () const 00239 { 00240 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00241 return cols() - rank (); 00242 } 00243 00244 /** \returns true if the matrix of which *this is the QR decomposition represents an injective 00245 * linear map, i.e. has trivial kernel; false otherwise. 00246 * 00247 * \note This method has to determine which pivots should be considered nonzero. 00248 * For that, it uses the threshold value that you can control by calling 00249 * setThreshold(const RealScalar&). 00250 */ 00251 inline bool isInjective () const 00252 { 00253 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00254 return rank () == cols(); 00255 } 00256 00257 /** \returns true if the matrix of which *this is the QR decomposition represents a surjective 00258 * linear map; false otherwise. 00259 * 00260 * \note This method has to determine which pivots should be considered nonzero. 00261 * For that, it uses the threshold value that you can control by calling 00262 * setThreshold(const RealScalar&). 00263 */ 00264 inline bool isSurjective () const 00265 { 00266 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00267 return rank () == rows(); 00268 } 00269 00270 /** \returns true if the matrix of which *this is the QR decomposition is invertible. 00271 * 00272 * \note This method has to determine which pivots should be considered nonzero. 00273 * For that, it uses the threshold value that you can control by calling 00274 * setThreshold(const RealScalar&). 00275 */ 00276 inline bool isInvertible () const 00277 { 00278 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00279 return isInjective () && isSurjective (); 00280 } 00281 00282 /** \returns the inverse of the matrix of which *this is the QR decomposition. 00283 * 00284 * \note If this matrix is not invertible, the returned matrix has undefined coefficients. 00285 * Use isInvertible() to first determine whether this matrix is invertible. 00286 */ 00287 inline const 00288 internal::solve_retval<ColPivHouseholderQR, typename MatrixType::IdentityReturnType> 00289 inverse () const 00290 { 00291 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00292 return internal::solve_retval<ColPivHouseholderQR,typename MatrixType::IdentityReturnType> 00293 (*this, MatrixType::Identity(m_qr.rows(), m_qr.cols())); 00294 } 00295 00296 inline Index rows() const { return m_qr.rows(); } 00297 inline Index cols() const { return m_qr.cols(); } 00298 00299 /** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q. 00300 * 00301 * For advanced uses only. 00302 */ 00303 const HCoeffsType& hCoeffs () const { return m_hCoeffs; } 00304 00305 /** Allows to prescribe a threshold to be used by certain methods, such as rank(), 00306 * who need to determine when pivots are to be considered nonzero. This is not used for the 00307 * QR decomposition itself. 00308 * 00309 * When it needs to get the threshold value, Eigen calls threshold(). By default, this 00310 * uses a formula to automatically determine a reasonable threshold. 00311 * Once you have called the present method setThreshold(const RealScalar&), 00312 * your value is used instead. 00313 * 00314 * \param threshold The new value to use as the threshold. 00315 * 00316 * A pivot will be considered nonzero if its absolute value is strictly greater than 00317 * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$ 00318 * where maxpivot is the biggest pivot. 00319 * 00320 * If you want to come back to the default behavior, call setThreshold(Default_t) 00321 */ 00322 ColPivHouseholderQR& setThreshold(const RealScalar& threshold) 00323 { 00324 m_usePrescribedThreshold = true; 00325 m_prescribedThreshold = threshold; 00326 return *this; 00327 } 00328 00329 /** Allows to come back to the default behavior, letting Eigen use its default formula for 00330 * determining the threshold. 00331 * 00332 * You should pass the special object Eigen::Default as parameter here. 00333 * \code qr.setThreshold(Eigen::Default); \endcode 00334 * 00335 * See the documentation of setThreshold(const RealScalar&). 00336 */ 00337 ColPivHouseholderQR& setThreshold(Default_t) 00338 { 00339 m_usePrescribedThreshold = false; 00340 return *this; 00341 } 00342 00343 /** Returns the threshold that will be used by certain methods such as rank(). 00344 * 00345 * See the documentation of setThreshold(const RealScalar&). 00346 */ 00347 RealScalar threshold() const 00348 { 00349 eigen_assert(m_isInitialized || m_usePrescribedThreshold); 00350 return m_usePrescribedThreshold ? m_prescribedThreshold 00351 // this formula comes from experimenting (see "LU precision tuning" thread on the list) 00352 // and turns out to be identical to Higham's formula used already in LDLt. 00353 : NumTraits<Scalar>::epsilon() * RealScalar(m_qr.diagonalSize()); 00354 } 00355 00356 /** \returns the number of nonzero pivots in the QR decomposition. 00357 * Here nonzero is meant in the exact sense, not in a fuzzy sense. 00358 * So that notion isn't really intrinsically interesting, but it is 00359 * still useful when implementing algorithms. 00360 * 00361 * \sa rank() 00362 */ 00363 inline Index nonzeroPivots () const 00364 { 00365 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00366 return m_nonzero_pivots; 00367 } 00368 00369 /** \returns the absolute value of the biggest pivot, i.e. the biggest 00370 * diagonal coefficient of R. 00371 */ 00372 RealScalar maxPivot () const { return m_maxpivot; } 00373 00374 /** \brief Reports whether the QR factorization was succesful. 00375 * 00376 * \note This function always returns \c Success. It is provided for compatibility 00377 * with other factorization routines. 00378 * \returns \c Success 00379 */ 00380 ComputationInfo info() const 00381 { 00382 eigen_assert(m_isInitialized && "Decomposition is not initialized."); 00383 return Success; 00384 } 00385 00386 protected: 00387 00388 static void check_template_parameters() 00389 { 00390 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 00391 } 00392 00393 MatrixType m_qr; 00394 HCoeffsType m_hCoeffs; 00395 PermutationType m_colsPermutation; 00396 IntRowVectorType m_colsTranspositions; 00397 RowVectorType m_temp; 00398 RealRowVectorType m_colSqNorms; 00399 bool m_isInitialized, m_usePrescribedThreshold; 00400 RealScalar m_prescribedThreshold, m_maxpivot; 00401 Index m_nonzero_pivots; 00402 Index m_det_pq; 00403 }; 00404 00405 template<typename MatrixType> 00406 typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::absDeterminant () const 00407 { 00408 using std::abs; 00409 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00410 eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!"); 00411 return abs(m_qr.diagonal().prod()); 00412 } 00413 00414 template<typename MatrixType> 00415 typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDeterminant() const 00416 { 00417 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00418 eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!"); 00419 return m_qr.diagonal().cwiseAbs().array().log().sum(); 00420 } 00421 00422 /** Performs the QR factorization of the given matrix \a matrix. The result of 00423 * the factorization is stored into \c *this, and a reference to \c *this 00424 * is returned. 00425 * 00426 * \sa class ColPivHouseholderQR, ColPivHouseholderQR(const MatrixType&) 00427 */ 00428 template<typename MatrixType> 00429 ColPivHouseholderQR<MatrixType> & ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix) 00430 { 00431 check_template_parameters(); 00432 00433 using std::abs; 00434 Index rows = matrix.rows(); 00435 Index cols = matrix.cols(); 00436 Index size = matrix.diagonalSize(); 00437 00438 // the column permutation is stored as int indices, so just to be sure: 00439 eigen_assert(cols<=NumTraits<int>::highest()); 00440 00441 m_qr = matrix; 00442 m_hCoeffs.resize(size); 00443 00444 m_temp.resize(cols); 00445 00446 m_colsTranspositions.resize(matrix.cols()); 00447 Index number_of_transpositions = 0; 00448 00449 m_colSqNorms.resize(cols); 00450 for(Index k = 0; k < cols; ++k) 00451 m_colSqNorms.coeffRef(k) = m_qr.col(k).squaredNorm(); 00452 00453 RealScalar threshold_helper = m_colSqNorms.maxCoeff() * numext::abs2(NumTraits<Scalar>::epsilon()) / RealScalar(rows); 00454 00455 m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case) 00456 m_maxpivot = RealScalar(0); 00457 00458 for(Index k = 0; k < size; ++k) 00459 { 00460 // first, we look up in our table m_colSqNorms which column has the biggest squared norm 00461 Index biggest_col_index; 00462 RealScalar biggest_col_sq_norm = m_colSqNorms.tail(cols-k).maxCoeff(&biggest_col_index); 00463 biggest_col_index += k; 00464 00465 // since our table m_colSqNorms accumulates imprecision at every step, we must now recompute 00466 // the actual squared norm of the selected column. 00467 // Note that not doing so does result in solve() sometimes returning inf/nan values 00468 // when running the unit test with 1000 repetitions. 00469 biggest_col_sq_norm = m_qr.col(biggest_col_index).tail(rows-k).squaredNorm(); 00470 00471 // we store that back into our table: it can't hurt to correct our table. 00472 m_colSqNorms.coeffRef(biggest_col_index) = biggest_col_sq_norm; 00473 00474 // Track the number of meaningful pivots but do not stop the decomposition to make 00475 // sure that the initial matrix is properly reproduced. See bug 941. 00476 if(m_nonzero_pivots==size && biggest_col_sq_norm < threshold_helper * RealScalar(rows-k)) 00477 m_nonzero_pivots = k; 00478 00479 // apply the transposition to the columns 00480 m_colsTranspositions.coeffRef(k) = biggest_col_index; 00481 if(k != biggest_col_index) { 00482 m_qr.col(k).swap(m_qr.col(biggest_col_index)); 00483 std::swap(m_colSqNorms.coeffRef(k), m_colSqNorms.coeffRef(biggest_col_index)); 00484 ++number_of_transpositions; 00485 } 00486 00487 // generate the householder vector, store it below the diagonal 00488 RealScalar beta; 00489 m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta); 00490 00491 // apply the householder transformation to the diagonal coefficient 00492 m_qr.coeffRef(k,k) = beta; 00493 00494 // remember the maximum absolute value of diagonal coefficients 00495 if(abs(beta) > m_maxpivot) m_maxpivot = abs(beta); 00496 00497 // apply the householder transformation 00498 m_qr.bottomRightCorner(rows-k, cols-k-1) 00499 .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1)); 00500 00501 // update our table of squared norms of the columns 00502 m_colSqNorms.tail(cols-k-1) -= m_qr.row(k).tail(cols-k-1).cwiseAbs2(); 00503 } 00504 00505 m_colsPermutation.setIdentity(PermIndexType(cols)); 00506 for(PermIndexType k = 0; k < size/*m_nonzero_pivots*/; ++k) 00507 m_colsPermutation.applyTranspositionOnTheRight(k, PermIndexType(m_colsTranspositions.coeff(k))); 00508 00509 m_det_pq = (number_of_transpositions%2) ? -1 : 1; 00510 m_isInitialized = true; 00511 00512 return *this; 00513 } 00514 00515 namespace internal { 00516 00517 template<typename _MatrixType, typename Rhs> 00518 struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs> 00519 : solve_retval_base<ColPivHouseholderQR<_MatrixType>, Rhs> 00520 { 00521 EIGEN_MAKE_SOLVE_HELPERS(ColPivHouseholderQR<_MatrixType>,Rhs) 00522 00523 template<typename Dest> void evalTo(Dest& dst) const 00524 { 00525 eigen_assert(rhs().rows() == dec().rows()); 00526 00527 const Index cols = dec().cols(), 00528 nonzero_pivots = dec().nonzeroPivots(); 00529 00530 if(nonzero_pivots == 0) 00531 { 00532 dst.setZero(); 00533 return; 00534 } 00535 00536 typename Rhs::PlainObject c(rhs()); 00537 00538 // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T 00539 c.applyOnTheLeft(householderSequence(dec().matrixQR(), dec().hCoeffs()) 00540 .setLength(dec().nonzeroPivots()) 00541 .transpose() 00542 ); 00543 00544 dec().matrixR() 00545 .topLeftCorner(nonzero_pivots, nonzero_pivots) 00546 .template triangularView<Upper>() 00547 .solveInPlace(c.topRows(nonzero_pivots)); 00548 00549 for(Index i = 0; i < nonzero_pivots; ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i); 00550 for(Index i = nonzero_pivots; i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero(); 00551 } 00552 }; 00553 00554 } // end namespace internal 00555 00556 /** \returns the matrix Q as a sequence of householder transformations. 00557 * You can extract the meaningful part only by using: 00558 * \code qr.householderQ().setLength(qr.nonzeroPivots()) \endcode*/ 00559 template<typename MatrixType> 00560 typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHouseholderQR<MatrixType> 00561 ::householderQ() const 00562 { 00563 eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 00564 return HouseholderSequenceType (m_qr, m_hCoeffs.conjugate()); 00565 } 00566 00567 /** \return the column-pivoting Householder QR decomposition of \c *this. 00568 * 00569 * \sa class ColPivHouseholderQR 00570 */ 00571 template<typename Derived> 00572 const ColPivHouseholderQR<typename MatrixBase<Derived>::PlainObject> 00573 MatrixBase<Derived>::colPivHouseholderQr() const 00574 { 00575 return ColPivHouseholderQR<PlainObject>(eval()); 00576 } 00577 00578 } // end namespace Eigen 00579 00580 #endif // EIGEN_COLPIVOTINGHOUSEHOLDERQR_H
Generated on Thu Nov 17 2022 22:01:27 by
1.7.2