Eigne Matrix Class Library
Dependents: Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more
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 Tue Jul 12 2022 17:46:50 by 1.7.2