1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library 2*bf2c3715SXin Li // for linear algebra. 3*bf2c3715SXin Li // 4*bf2c3715SXin Li // Copyright (C) 2008-2009 Gael Guennebaud <[email protected]> 5*bf2c3715SXin Li // Copyright (C) 2009 Benoit Jacob <[email protected]> 6*bf2c3715SXin Li // 7*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla 8*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed 9*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10*bf2c3715SXin Li 11*bf2c3715SXin Li #ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_H 12*bf2c3715SXin Li #define EIGEN_COLPIVOTINGHOUSEHOLDERQR_H 13*bf2c3715SXin Li 14*bf2c3715SXin Li namespace Eigen { 15*bf2c3715SXin Li 16*bf2c3715SXin Li namespace internal { 17*bf2c3715SXin Li template<typename _MatrixType> struct traits<ColPivHouseholderQR<_MatrixType> > 18*bf2c3715SXin Li : traits<_MatrixType> 19*bf2c3715SXin Li { 20*bf2c3715SXin Li typedef MatrixXpr XprKind; 21*bf2c3715SXin Li typedef SolverStorage StorageKind; 22*bf2c3715SXin Li typedef int StorageIndex; 23*bf2c3715SXin Li enum { Flags = 0 }; 24*bf2c3715SXin Li }; 25*bf2c3715SXin Li 26*bf2c3715SXin Li } // end namespace internal 27*bf2c3715SXin Li 28*bf2c3715SXin Li /** \ingroup QR_Module 29*bf2c3715SXin Li * 30*bf2c3715SXin Li * \class ColPivHouseholderQR 31*bf2c3715SXin Li * 32*bf2c3715SXin Li * \brief Householder rank-revealing QR decomposition of a matrix with column-pivoting 33*bf2c3715SXin Li * 34*bf2c3715SXin Li * \tparam _MatrixType the type of the matrix of which we are computing the QR decomposition 35*bf2c3715SXin Li * 36*bf2c3715SXin Li * This class performs a rank-revealing QR decomposition of a matrix \b A into matrices \b P, \b Q and \b R 37*bf2c3715SXin Li * such that 38*bf2c3715SXin Li * \f[ 39*bf2c3715SXin Li * \mathbf{A} \, \mathbf{P} = \mathbf{Q} \, \mathbf{R} 40*bf2c3715SXin Li * \f] 41*bf2c3715SXin Li * by using Householder transformations. Here, \b P is a permutation matrix, \b Q a unitary matrix and \b R an 42*bf2c3715SXin Li * upper triangular matrix. 43*bf2c3715SXin Li * 44*bf2c3715SXin Li * This decomposition performs column pivoting in order to be rank-revealing and improve 45*bf2c3715SXin Li * numerical stability. It is slower than HouseholderQR, and faster than FullPivHouseholderQR. 46*bf2c3715SXin Li * 47*bf2c3715SXin Li * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. 48*bf2c3715SXin Li * 49*bf2c3715SXin Li * \sa MatrixBase::colPivHouseholderQr() 50*bf2c3715SXin Li */ 51*bf2c3715SXin Li template<typename _MatrixType> class ColPivHouseholderQR 52*bf2c3715SXin Li : public SolverBase<ColPivHouseholderQR<_MatrixType> > 53*bf2c3715SXin Li { 54*bf2c3715SXin Li public: 55*bf2c3715SXin Li 56*bf2c3715SXin Li typedef _MatrixType MatrixType; 57*bf2c3715SXin Li typedef SolverBase<ColPivHouseholderQR> Base; 58*bf2c3715SXin Li friend class SolverBase<ColPivHouseholderQR>; 59*bf2c3715SXin Li 60*bf2c3715SXin Li EIGEN_GENERIC_PUBLIC_INTERFACE(ColPivHouseholderQR) 61*bf2c3715SXin Li enum { 62*bf2c3715SXin Li MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 63*bf2c3715SXin Li MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime 64*bf2c3715SXin Li }; 65*bf2c3715SXin Li typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType; 66*bf2c3715SXin Li typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType; 67*bf2c3715SXin Li typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType; 68*bf2c3715SXin Li typedef typename internal::plain_row_type<MatrixType>::type RowVectorType; 69*bf2c3715SXin Li typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType; 70*bf2c3715SXin Li typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType; 71*bf2c3715SXin Li typedef typename MatrixType::PlainObject PlainObject; 72*bf2c3715SXin Li 73*bf2c3715SXin Li private: 74*bf2c3715SXin Li 75*bf2c3715SXin Li typedef typename PermutationType::StorageIndex PermIndexType; 76*bf2c3715SXin Li 77*bf2c3715SXin Li public: 78*bf2c3715SXin Li 79*bf2c3715SXin Li /** 80*bf2c3715SXin Li * \brief Default Constructor. 81*bf2c3715SXin Li * 82*bf2c3715SXin Li * The default constructor is useful in cases in which the user intends to 83*bf2c3715SXin Li * perform decompositions via ColPivHouseholderQR::compute(const MatrixType&). 84*bf2c3715SXin Li */ 85*bf2c3715SXin Li ColPivHouseholderQR() 86*bf2c3715SXin Li : m_qr(), 87*bf2c3715SXin Li m_hCoeffs(), 88*bf2c3715SXin Li m_colsPermutation(), 89*bf2c3715SXin Li m_colsTranspositions(), 90*bf2c3715SXin Li m_temp(), 91*bf2c3715SXin Li m_colNormsUpdated(), 92*bf2c3715SXin Li m_colNormsDirect(), 93*bf2c3715SXin Li m_isInitialized(false), 94*bf2c3715SXin Li m_usePrescribedThreshold(false) {} 95*bf2c3715SXin Li 96*bf2c3715SXin Li /** \brief Default Constructor with memory preallocation 97*bf2c3715SXin Li * 98*bf2c3715SXin Li * Like the default constructor but with preallocation of the internal data 99*bf2c3715SXin Li * according to the specified problem \a size. 100*bf2c3715SXin Li * \sa ColPivHouseholderQR() 101*bf2c3715SXin Li */ 102*bf2c3715SXin Li ColPivHouseholderQR(Index rows, Index cols) 103*bf2c3715SXin Li : m_qr(rows, cols), 104*bf2c3715SXin Li m_hCoeffs((std::min)(rows,cols)), 105*bf2c3715SXin Li m_colsPermutation(PermIndexType(cols)), 106*bf2c3715SXin Li m_colsTranspositions(cols), 107*bf2c3715SXin Li m_temp(cols), 108*bf2c3715SXin Li m_colNormsUpdated(cols), 109*bf2c3715SXin Li m_colNormsDirect(cols), 110*bf2c3715SXin Li m_isInitialized(false), 111*bf2c3715SXin Li m_usePrescribedThreshold(false) {} 112*bf2c3715SXin Li 113*bf2c3715SXin Li /** \brief Constructs a QR factorization from a given matrix 114*bf2c3715SXin Li * 115*bf2c3715SXin Li * This constructor computes the QR factorization of the matrix \a matrix by calling 116*bf2c3715SXin Li * the method compute(). It is a short cut for: 117*bf2c3715SXin Li * 118*bf2c3715SXin Li * \code 119*bf2c3715SXin Li * ColPivHouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols()); 120*bf2c3715SXin Li * qr.compute(matrix); 121*bf2c3715SXin Li * \endcode 122*bf2c3715SXin Li * 123*bf2c3715SXin Li * \sa compute() 124*bf2c3715SXin Li */ 125*bf2c3715SXin Li template<typename InputType> 126*bf2c3715SXin Li explicit ColPivHouseholderQR(const EigenBase<InputType>& matrix) 127*bf2c3715SXin Li : m_qr(matrix.rows(), matrix.cols()), 128*bf2c3715SXin Li m_hCoeffs((std::min)(matrix.rows(),matrix.cols())), 129*bf2c3715SXin Li m_colsPermutation(PermIndexType(matrix.cols())), 130*bf2c3715SXin Li m_colsTranspositions(matrix.cols()), 131*bf2c3715SXin Li m_temp(matrix.cols()), 132*bf2c3715SXin Li m_colNormsUpdated(matrix.cols()), 133*bf2c3715SXin Li m_colNormsDirect(matrix.cols()), 134*bf2c3715SXin Li m_isInitialized(false), 135*bf2c3715SXin Li m_usePrescribedThreshold(false) 136*bf2c3715SXin Li { 137*bf2c3715SXin Li compute(matrix.derived()); 138*bf2c3715SXin Li } 139*bf2c3715SXin Li 140*bf2c3715SXin Li /** \brief Constructs a QR factorization from a given matrix 141*bf2c3715SXin Li * 142*bf2c3715SXin Li * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref. 143*bf2c3715SXin Li * 144*bf2c3715SXin Li * \sa ColPivHouseholderQR(const EigenBase&) 145*bf2c3715SXin Li */ 146*bf2c3715SXin Li template<typename InputType> 147*bf2c3715SXin Li explicit ColPivHouseholderQR(EigenBase<InputType>& matrix) 148*bf2c3715SXin Li : m_qr(matrix.derived()), 149*bf2c3715SXin Li m_hCoeffs((std::min)(matrix.rows(),matrix.cols())), 150*bf2c3715SXin Li m_colsPermutation(PermIndexType(matrix.cols())), 151*bf2c3715SXin Li m_colsTranspositions(matrix.cols()), 152*bf2c3715SXin Li m_temp(matrix.cols()), 153*bf2c3715SXin Li m_colNormsUpdated(matrix.cols()), 154*bf2c3715SXin Li m_colNormsDirect(matrix.cols()), 155*bf2c3715SXin Li m_isInitialized(false), 156*bf2c3715SXin Li m_usePrescribedThreshold(false) 157*bf2c3715SXin Li { 158*bf2c3715SXin Li computeInPlace(); 159*bf2c3715SXin Li } 160*bf2c3715SXin Li 161*bf2c3715SXin Li #ifdef EIGEN_PARSED_BY_DOXYGEN 162*bf2c3715SXin Li /** This method finds a solution x to the equation Ax=b, where A is the matrix of which 163*bf2c3715SXin Li * *this is the QR decomposition, if any exists. 164*bf2c3715SXin Li * 165*bf2c3715SXin Li * \param b the right-hand-side of the equation to solve. 166*bf2c3715SXin Li * 167*bf2c3715SXin Li * \returns a solution. 168*bf2c3715SXin Li * 169*bf2c3715SXin Li * \note_about_checking_solutions 170*bf2c3715SXin Li * 171*bf2c3715SXin Li * \note_about_arbitrary_choice_of_solution 172*bf2c3715SXin Li * 173*bf2c3715SXin Li * Example: \include ColPivHouseholderQR_solve.cpp 174*bf2c3715SXin Li * Output: \verbinclude ColPivHouseholderQR_solve.out 175*bf2c3715SXin Li */ 176*bf2c3715SXin Li template<typename Rhs> 177*bf2c3715SXin Li inline const Solve<ColPivHouseholderQR, Rhs> 178*bf2c3715SXin Li solve(const MatrixBase<Rhs>& b) const; 179*bf2c3715SXin Li #endif 180*bf2c3715SXin Li 181*bf2c3715SXin Li HouseholderSequenceType householderQ() const; 182*bf2c3715SXin Li HouseholderSequenceType matrixQ() const 183*bf2c3715SXin Li { 184*bf2c3715SXin Li return householderQ(); 185*bf2c3715SXin Li } 186*bf2c3715SXin Li 187*bf2c3715SXin Li /** \returns a reference to the matrix where the Householder QR decomposition is stored 188*bf2c3715SXin Li */ 189*bf2c3715SXin Li const MatrixType& matrixQR() const 190*bf2c3715SXin Li { 191*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 192*bf2c3715SXin Li return m_qr; 193*bf2c3715SXin Li } 194*bf2c3715SXin Li 195*bf2c3715SXin Li /** \returns a reference to the matrix where the result Householder QR is stored 196*bf2c3715SXin Li * \warning The strict lower part of this matrix contains internal values. 197*bf2c3715SXin Li * Only the upper triangular part should be referenced. To get it, use 198*bf2c3715SXin Li * \code matrixR().template triangularView<Upper>() \endcode 199*bf2c3715SXin Li * For rank-deficient matrices, use 200*bf2c3715SXin Li * \code 201*bf2c3715SXin Li * matrixR().topLeftCorner(rank(), rank()).template triangularView<Upper>() 202*bf2c3715SXin Li * \endcode 203*bf2c3715SXin Li */ 204*bf2c3715SXin Li const MatrixType& matrixR() const 205*bf2c3715SXin Li { 206*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 207*bf2c3715SXin Li return m_qr; 208*bf2c3715SXin Li } 209*bf2c3715SXin Li 210*bf2c3715SXin Li template<typename InputType> 211*bf2c3715SXin Li ColPivHouseholderQR& compute(const EigenBase<InputType>& matrix); 212*bf2c3715SXin Li 213*bf2c3715SXin Li /** \returns a const reference to the column permutation matrix */ 214*bf2c3715SXin Li const PermutationType& colsPermutation() const 215*bf2c3715SXin Li { 216*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 217*bf2c3715SXin Li return m_colsPermutation; 218*bf2c3715SXin Li } 219*bf2c3715SXin Li 220*bf2c3715SXin Li /** \returns the absolute value of the determinant of the matrix of which 221*bf2c3715SXin Li * *this is the QR decomposition. It has only linear complexity 222*bf2c3715SXin Li * (that is, O(n) where n is the dimension of the square matrix) 223*bf2c3715SXin Li * as the QR decomposition has already been computed. 224*bf2c3715SXin Li * 225*bf2c3715SXin Li * \note This is only for square matrices. 226*bf2c3715SXin Li * 227*bf2c3715SXin Li * \warning a determinant can be very big or small, so for matrices 228*bf2c3715SXin Li * of large enough dimension, there is a risk of overflow/underflow. 229*bf2c3715SXin Li * One way to work around that is to use logAbsDeterminant() instead. 230*bf2c3715SXin Li * 231*bf2c3715SXin Li * \sa logAbsDeterminant(), MatrixBase::determinant() 232*bf2c3715SXin Li */ 233*bf2c3715SXin Li typename MatrixType::RealScalar absDeterminant() const; 234*bf2c3715SXin Li 235*bf2c3715SXin Li /** \returns the natural log of the absolute value of the determinant of the matrix of which 236*bf2c3715SXin Li * *this is the QR decomposition. It has only linear complexity 237*bf2c3715SXin Li * (that is, O(n) where n is the dimension of the square matrix) 238*bf2c3715SXin Li * as the QR decomposition has already been computed. 239*bf2c3715SXin Li * 240*bf2c3715SXin Li * \note This is only for square matrices. 241*bf2c3715SXin Li * 242*bf2c3715SXin Li * \note This method is useful to work around the risk of overflow/underflow that's inherent 243*bf2c3715SXin Li * to determinant computation. 244*bf2c3715SXin Li * 245*bf2c3715SXin Li * \sa absDeterminant(), MatrixBase::determinant() 246*bf2c3715SXin Li */ 247*bf2c3715SXin Li typename MatrixType::RealScalar logAbsDeterminant() const; 248*bf2c3715SXin Li 249*bf2c3715SXin Li /** \returns the rank of the matrix of which *this is the QR decomposition. 250*bf2c3715SXin Li * 251*bf2c3715SXin Li * \note This method has to determine which pivots should be considered nonzero. 252*bf2c3715SXin Li * For that, it uses the threshold value that you can control by calling 253*bf2c3715SXin Li * setThreshold(const RealScalar&). 254*bf2c3715SXin Li */ 255*bf2c3715SXin Li inline Index rank() const 256*bf2c3715SXin Li { 257*bf2c3715SXin Li using std::abs; 258*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 259*bf2c3715SXin Li RealScalar premultiplied_threshold = abs(m_maxpivot) * threshold(); 260*bf2c3715SXin Li Index result = 0; 261*bf2c3715SXin Li for(Index i = 0; i < m_nonzero_pivots; ++i) 262*bf2c3715SXin Li result += (abs(m_qr.coeff(i,i)) > premultiplied_threshold); 263*bf2c3715SXin Li return result; 264*bf2c3715SXin Li } 265*bf2c3715SXin Li 266*bf2c3715SXin Li /** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition. 267*bf2c3715SXin Li * 268*bf2c3715SXin Li * \note This method has to determine which pivots should be considered nonzero. 269*bf2c3715SXin Li * For that, it uses the threshold value that you can control by calling 270*bf2c3715SXin Li * setThreshold(const RealScalar&). 271*bf2c3715SXin Li */ 272*bf2c3715SXin Li inline Index dimensionOfKernel() const 273*bf2c3715SXin Li { 274*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 275*bf2c3715SXin Li return cols() - rank(); 276*bf2c3715SXin Li } 277*bf2c3715SXin Li 278*bf2c3715SXin Li /** \returns true if the matrix of which *this is the QR decomposition represents an injective 279*bf2c3715SXin Li * linear map, i.e. has trivial kernel; false otherwise. 280*bf2c3715SXin Li * 281*bf2c3715SXin Li * \note This method has to determine which pivots should be considered nonzero. 282*bf2c3715SXin Li * For that, it uses the threshold value that you can control by calling 283*bf2c3715SXin Li * setThreshold(const RealScalar&). 284*bf2c3715SXin Li */ 285*bf2c3715SXin Li inline bool isInjective() const 286*bf2c3715SXin Li { 287*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 288*bf2c3715SXin Li return rank() == cols(); 289*bf2c3715SXin Li } 290*bf2c3715SXin Li 291*bf2c3715SXin Li /** \returns true if the matrix of which *this is the QR decomposition represents a surjective 292*bf2c3715SXin Li * linear map; false otherwise. 293*bf2c3715SXin Li * 294*bf2c3715SXin Li * \note This method has to determine which pivots should be considered nonzero. 295*bf2c3715SXin Li * For that, it uses the threshold value that you can control by calling 296*bf2c3715SXin Li * setThreshold(const RealScalar&). 297*bf2c3715SXin Li */ 298*bf2c3715SXin Li inline bool isSurjective() const 299*bf2c3715SXin Li { 300*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 301*bf2c3715SXin Li return rank() == rows(); 302*bf2c3715SXin Li } 303*bf2c3715SXin Li 304*bf2c3715SXin Li /** \returns true if the matrix of which *this is the QR decomposition is invertible. 305*bf2c3715SXin Li * 306*bf2c3715SXin Li * \note This method has to determine which pivots should be considered nonzero. 307*bf2c3715SXin Li * For that, it uses the threshold value that you can control by calling 308*bf2c3715SXin Li * setThreshold(const RealScalar&). 309*bf2c3715SXin Li */ 310*bf2c3715SXin Li inline bool isInvertible() const 311*bf2c3715SXin Li { 312*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 313*bf2c3715SXin Li return isInjective() && isSurjective(); 314*bf2c3715SXin Li } 315*bf2c3715SXin Li 316*bf2c3715SXin Li /** \returns the inverse of the matrix of which *this is the QR decomposition. 317*bf2c3715SXin Li * 318*bf2c3715SXin Li * \note If this matrix is not invertible, the returned matrix has undefined coefficients. 319*bf2c3715SXin Li * Use isInvertible() to first determine whether this matrix is invertible. 320*bf2c3715SXin Li */ 321*bf2c3715SXin Li inline const Inverse<ColPivHouseholderQR> inverse() const 322*bf2c3715SXin Li { 323*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 324*bf2c3715SXin Li return Inverse<ColPivHouseholderQR>(*this); 325*bf2c3715SXin Li } 326*bf2c3715SXin Li 327*bf2c3715SXin Li inline Index rows() const { return m_qr.rows(); } 328*bf2c3715SXin Li inline Index cols() const { return m_qr.cols(); } 329*bf2c3715SXin Li 330*bf2c3715SXin Li /** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q. 331*bf2c3715SXin Li * 332*bf2c3715SXin Li * For advanced uses only. 333*bf2c3715SXin Li */ 334*bf2c3715SXin Li const HCoeffsType& hCoeffs() const { return m_hCoeffs; } 335*bf2c3715SXin Li 336*bf2c3715SXin Li /** Allows to prescribe a threshold to be used by certain methods, such as rank(), 337*bf2c3715SXin Li * who need to determine when pivots are to be considered nonzero. This is not used for the 338*bf2c3715SXin Li * QR decomposition itself. 339*bf2c3715SXin Li * 340*bf2c3715SXin Li * When it needs to get the threshold value, Eigen calls threshold(). By default, this 341*bf2c3715SXin Li * uses a formula to automatically determine a reasonable threshold. 342*bf2c3715SXin Li * Once you have called the present method setThreshold(const RealScalar&), 343*bf2c3715SXin Li * your value is used instead. 344*bf2c3715SXin Li * 345*bf2c3715SXin Li * \param threshold The new value to use as the threshold. 346*bf2c3715SXin Li * 347*bf2c3715SXin Li * A pivot will be considered nonzero if its absolute value is strictly greater than 348*bf2c3715SXin Li * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$ 349*bf2c3715SXin Li * where maxpivot is the biggest pivot. 350*bf2c3715SXin Li * 351*bf2c3715SXin Li * If you want to come back to the default behavior, call setThreshold(Default_t) 352*bf2c3715SXin Li */ 353*bf2c3715SXin Li ColPivHouseholderQR& setThreshold(const RealScalar& threshold) 354*bf2c3715SXin Li { 355*bf2c3715SXin Li m_usePrescribedThreshold = true; 356*bf2c3715SXin Li m_prescribedThreshold = threshold; 357*bf2c3715SXin Li return *this; 358*bf2c3715SXin Li } 359*bf2c3715SXin Li 360*bf2c3715SXin Li /** Allows to come back to the default behavior, letting Eigen use its default formula for 361*bf2c3715SXin Li * determining the threshold. 362*bf2c3715SXin Li * 363*bf2c3715SXin Li * You should pass the special object Eigen::Default as parameter here. 364*bf2c3715SXin Li * \code qr.setThreshold(Eigen::Default); \endcode 365*bf2c3715SXin Li * 366*bf2c3715SXin Li * See the documentation of setThreshold(const RealScalar&). 367*bf2c3715SXin Li */ 368*bf2c3715SXin Li ColPivHouseholderQR& setThreshold(Default_t) 369*bf2c3715SXin Li { 370*bf2c3715SXin Li m_usePrescribedThreshold = false; 371*bf2c3715SXin Li return *this; 372*bf2c3715SXin Li } 373*bf2c3715SXin Li 374*bf2c3715SXin Li /** Returns the threshold that will be used by certain methods such as rank(). 375*bf2c3715SXin Li * 376*bf2c3715SXin Li * See the documentation of setThreshold(const RealScalar&). 377*bf2c3715SXin Li */ 378*bf2c3715SXin Li RealScalar threshold() const 379*bf2c3715SXin Li { 380*bf2c3715SXin Li eigen_assert(m_isInitialized || m_usePrescribedThreshold); 381*bf2c3715SXin Li return m_usePrescribedThreshold ? m_prescribedThreshold 382*bf2c3715SXin Li // this formula comes from experimenting (see "LU precision tuning" thread on the list) 383*bf2c3715SXin Li // and turns out to be identical to Higham's formula used already in LDLt. 384*bf2c3715SXin Li : NumTraits<Scalar>::epsilon() * RealScalar(m_qr.diagonalSize()); 385*bf2c3715SXin Li } 386*bf2c3715SXin Li 387*bf2c3715SXin Li /** \returns the number of nonzero pivots in the QR decomposition. 388*bf2c3715SXin Li * Here nonzero is meant in the exact sense, not in a fuzzy sense. 389*bf2c3715SXin Li * So that notion isn't really intrinsically interesting, but it is 390*bf2c3715SXin Li * still useful when implementing algorithms. 391*bf2c3715SXin Li * 392*bf2c3715SXin Li * \sa rank() 393*bf2c3715SXin Li */ 394*bf2c3715SXin Li inline Index nonzeroPivots() const 395*bf2c3715SXin Li { 396*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 397*bf2c3715SXin Li return m_nonzero_pivots; 398*bf2c3715SXin Li } 399*bf2c3715SXin Li 400*bf2c3715SXin Li /** \returns the absolute value of the biggest pivot, i.e. the biggest 401*bf2c3715SXin Li * diagonal coefficient of R. 402*bf2c3715SXin Li */ 403*bf2c3715SXin Li RealScalar maxPivot() const { return m_maxpivot; } 404*bf2c3715SXin Li 405*bf2c3715SXin Li /** \brief Reports whether the QR factorization was successful. 406*bf2c3715SXin Li * 407*bf2c3715SXin Li * \note This function always returns \c Success. It is provided for compatibility 408*bf2c3715SXin Li * with other factorization routines. 409*bf2c3715SXin Li * \returns \c Success 410*bf2c3715SXin Li */ 411*bf2c3715SXin Li ComputationInfo info() const 412*bf2c3715SXin Li { 413*bf2c3715SXin Li eigen_assert(m_isInitialized && "Decomposition is not initialized."); 414*bf2c3715SXin Li return Success; 415*bf2c3715SXin Li } 416*bf2c3715SXin Li 417*bf2c3715SXin Li #ifndef EIGEN_PARSED_BY_DOXYGEN 418*bf2c3715SXin Li template<typename RhsType, typename DstType> 419*bf2c3715SXin Li void _solve_impl(const RhsType &rhs, DstType &dst) const; 420*bf2c3715SXin Li 421*bf2c3715SXin Li template<bool Conjugate, typename RhsType, typename DstType> 422*bf2c3715SXin Li void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const; 423*bf2c3715SXin Li #endif 424*bf2c3715SXin Li 425*bf2c3715SXin Li protected: 426*bf2c3715SXin Li 427*bf2c3715SXin Li friend class CompleteOrthogonalDecomposition<MatrixType>; 428*bf2c3715SXin Li 429*bf2c3715SXin Li static void check_template_parameters() 430*bf2c3715SXin Li { 431*bf2c3715SXin Li EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar); 432*bf2c3715SXin Li } 433*bf2c3715SXin Li 434*bf2c3715SXin Li void computeInPlace(); 435*bf2c3715SXin Li 436*bf2c3715SXin Li MatrixType m_qr; 437*bf2c3715SXin Li HCoeffsType m_hCoeffs; 438*bf2c3715SXin Li PermutationType m_colsPermutation; 439*bf2c3715SXin Li IntRowVectorType m_colsTranspositions; 440*bf2c3715SXin Li RowVectorType m_temp; 441*bf2c3715SXin Li RealRowVectorType m_colNormsUpdated; 442*bf2c3715SXin Li RealRowVectorType m_colNormsDirect; 443*bf2c3715SXin Li bool m_isInitialized, m_usePrescribedThreshold; 444*bf2c3715SXin Li RealScalar m_prescribedThreshold, m_maxpivot; 445*bf2c3715SXin Li Index m_nonzero_pivots; 446*bf2c3715SXin Li Index m_det_pq; 447*bf2c3715SXin Li }; 448*bf2c3715SXin Li 449*bf2c3715SXin Li template<typename MatrixType> 450*bf2c3715SXin Li typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::absDeterminant() const 451*bf2c3715SXin Li { 452*bf2c3715SXin Li using std::abs; 453*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 454*bf2c3715SXin Li eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!"); 455*bf2c3715SXin Li return abs(m_qr.diagonal().prod()); 456*bf2c3715SXin Li } 457*bf2c3715SXin Li 458*bf2c3715SXin Li template<typename MatrixType> 459*bf2c3715SXin Li typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDeterminant() const 460*bf2c3715SXin Li { 461*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 462*bf2c3715SXin Li eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!"); 463*bf2c3715SXin Li return m_qr.diagonal().cwiseAbs().array().log().sum(); 464*bf2c3715SXin Li } 465*bf2c3715SXin Li 466*bf2c3715SXin Li /** Performs the QR factorization of the given matrix \a matrix. The result of 467*bf2c3715SXin Li * the factorization is stored into \c *this, and a reference to \c *this 468*bf2c3715SXin Li * is returned. 469*bf2c3715SXin Li * 470*bf2c3715SXin Li * \sa class ColPivHouseholderQR, ColPivHouseholderQR(const MatrixType&) 471*bf2c3715SXin Li */ 472*bf2c3715SXin Li template<typename MatrixType> 473*bf2c3715SXin Li template<typename InputType> 474*bf2c3715SXin Li ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const EigenBase<InputType>& matrix) 475*bf2c3715SXin Li { 476*bf2c3715SXin Li m_qr = matrix.derived(); 477*bf2c3715SXin Li computeInPlace(); 478*bf2c3715SXin Li return *this; 479*bf2c3715SXin Li } 480*bf2c3715SXin Li 481*bf2c3715SXin Li template<typename MatrixType> 482*bf2c3715SXin Li void ColPivHouseholderQR<MatrixType>::computeInPlace() 483*bf2c3715SXin Li { 484*bf2c3715SXin Li check_template_parameters(); 485*bf2c3715SXin Li 486*bf2c3715SXin Li // the column permutation is stored as int indices, so just to be sure: 487*bf2c3715SXin Li eigen_assert(m_qr.cols()<=NumTraits<int>::highest()); 488*bf2c3715SXin Li 489*bf2c3715SXin Li using std::abs; 490*bf2c3715SXin Li 491*bf2c3715SXin Li Index rows = m_qr.rows(); 492*bf2c3715SXin Li Index cols = m_qr.cols(); 493*bf2c3715SXin Li Index size = m_qr.diagonalSize(); 494*bf2c3715SXin Li 495*bf2c3715SXin Li m_hCoeffs.resize(size); 496*bf2c3715SXin Li 497*bf2c3715SXin Li m_temp.resize(cols); 498*bf2c3715SXin Li 499*bf2c3715SXin Li m_colsTranspositions.resize(m_qr.cols()); 500*bf2c3715SXin Li Index number_of_transpositions = 0; 501*bf2c3715SXin Li 502*bf2c3715SXin Li m_colNormsUpdated.resize(cols); 503*bf2c3715SXin Li m_colNormsDirect.resize(cols); 504*bf2c3715SXin Li for (Index k = 0; k < cols; ++k) { 505*bf2c3715SXin Li // colNormsDirect(k) caches the most recent directly computed norm of 506*bf2c3715SXin Li // column k. 507*bf2c3715SXin Li m_colNormsDirect.coeffRef(k) = m_qr.col(k).norm(); 508*bf2c3715SXin Li m_colNormsUpdated.coeffRef(k) = m_colNormsDirect.coeffRef(k); 509*bf2c3715SXin Li } 510*bf2c3715SXin Li 511*bf2c3715SXin Li RealScalar threshold_helper = numext::abs2<RealScalar>(m_colNormsUpdated.maxCoeff() * NumTraits<RealScalar>::epsilon()) / RealScalar(rows); 512*bf2c3715SXin Li RealScalar norm_downdate_threshold = numext::sqrt(NumTraits<RealScalar>::epsilon()); 513*bf2c3715SXin Li 514*bf2c3715SXin Li m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case) 515*bf2c3715SXin Li m_maxpivot = RealScalar(0); 516*bf2c3715SXin Li 517*bf2c3715SXin Li for(Index k = 0; k < size; ++k) 518*bf2c3715SXin Li { 519*bf2c3715SXin Li // first, we look up in our table m_colNormsUpdated which column has the biggest norm 520*bf2c3715SXin Li Index biggest_col_index; 521*bf2c3715SXin Li RealScalar biggest_col_sq_norm = numext::abs2(m_colNormsUpdated.tail(cols-k).maxCoeff(&biggest_col_index)); 522*bf2c3715SXin Li biggest_col_index += k; 523*bf2c3715SXin Li 524*bf2c3715SXin Li // Track the number of meaningful pivots but do not stop the decomposition to make 525*bf2c3715SXin Li // sure that the initial matrix is properly reproduced. See bug 941. 526*bf2c3715SXin Li if(m_nonzero_pivots==size && biggest_col_sq_norm < threshold_helper * RealScalar(rows-k)) 527*bf2c3715SXin Li m_nonzero_pivots = k; 528*bf2c3715SXin Li 529*bf2c3715SXin Li // apply the transposition to the columns 530*bf2c3715SXin Li m_colsTranspositions.coeffRef(k) = biggest_col_index; 531*bf2c3715SXin Li if(k != biggest_col_index) { 532*bf2c3715SXin Li m_qr.col(k).swap(m_qr.col(biggest_col_index)); 533*bf2c3715SXin Li std::swap(m_colNormsUpdated.coeffRef(k), m_colNormsUpdated.coeffRef(biggest_col_index)); 534*bf2c3715SXin Li std::swap(m_colNormsDirect.coeffRef(k), m_colNormsDirect.coeffRef(biggest_col_index)); 535*bf2c3715SXin Li ++number_of_transpositions; 536*bf2c3715SXin Li } 537*bf2c3715SXin Li 538*bf2c3715SXin Li // generate the householder vector, store it below the diagonal 539*bf2c3715SXin Li RealScalar beta; 540*bf2c3715SXin Li m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta); 541*bf2c3715SXin Li 542*bf2c3715SXin Li // apply the householder transformation to the diagonal coefficient 543*bf2c3715SXin Li m_qr.coeffRef(k,k) = beta; 544*bf2c3715SXin Li 545*bf2c3715SXin Li // remember the maximum absolute value of diagonal coefficients 546*bf2c3715SXin Li if(abs(beta) > m_maxpivot) m_maxpivot = abs(beta); 547*bf2c3715SXin Li 548*bf2c3715SXin Li // apply the householder transformation 549*bf2c3715SXin Li m_qr.bottomRightCorner(rows-k, cols-k-1) 550*bf2c3715SXin Li .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1)); 551*bf2c3715SXin Li 552*bf2c3715SXin Li // update our table of norms of the columns 553*bf2c3715SXin Li for (Index j = k + 1; j < cols; ++j) { 554*bf2c3715SXin Li // The following implements the stable norm downgrade step discussed in 555*bf2c3715SXin Li // http://www.netlib.org/lapack/lawnspdf/lawn176.pdf 556*bf2c3715SXin Li // and used in LAPACK routines xGEQPF and xGEQP3. 557*bf2c3715SXin Li // See lines 278-297 in http://www.netlib.org/lapack/explore-html/dc/df4/sgeqpf_8f_source.html 558*bf2c3715SXin Li if (m_colNormsUpdated.coeffRef(j) != RealScalar(0)) { 559*bf2c3715SXin Li RealScalar temp = abs(m_qr.coeffRef(k, j)) / m_colNormsUpdated.coeffRef(j); 560*bf2c3715SXin Li temp = (RealScalar(1) + temp) * (RealScalar(1) - temp); 561*bf2c3715SXin Li temp = temp < RealScalar(0) ? RealScalar(0) : temp; 562*bf2c3715SXin Li RealScalar temp2 = temp * numext::abs2<RealScalar>(m_colNormsUpdated.coeffRef(j) / 563*bf2c3715SXin Li m_colNormsDirect.coeffRef(j)); 564*bf2c3715SXin Li if (temp2 <= norm_downdate_threshold) { 565*bf2c3715SXin Li // The updated norm has become too inaccurate so re-compute the column 566*bf2c3715SXin Li // norm directly. 567*bf2c3715SXin Li m_colNormsDirect.coeffRef(j) = m_qr.col(j).tail(rows - k - 1).norm(); 568*bf2c3715SXin Li m_colNormsUpdated.coeffRef(j) = m_colNormsDirect.coeffRef(j); 569*bf2c3715SXin Li } else { 570*bf2c3715SXin Li m_colNormsUpdated.coeffRef(j) *= numext::sqrt(temp); 571*bf2c3715SXin Li } 572*bf2c3715SXin Li } 573*bf2c3715SXin Li } 574*bf2c3715SXin Li } 575*bf2c3715SXin Li 576*bf2c3715SXin Li m_colsPermutation.setIdentity(PermIndexType(cols)); 577*bf2c3715SXin Li for(PermIndexType k = 0; k < size/*m_nonzero_pivots*/; ++k) 578*bf2c3715SXin Li m_colsPermutation.applyTranspositionOnTheRight(k, PermIndexType(m_colsTranspositions.coeff(k))); 579*bf2c3715SXin Li 580*bf2c3715SXin Li m_det_pq = (number_of_transpositions%2) ? -1 : 1; 581*bf2c3715SXin Li m_isInitialized = true; 582*bf2c3715SXin Li } 583*bf2c3715SXin Li 584*bf2c3715SXin Li #ifndef EIGEN_PARSED_BY_DOXYGEN 585*bf2c3715SXin Li template<typename _MatrixType> 586*bf2c3715SXin Li template<typename RhsType, typename DstType> 587*bf2c3715SXin Li void ColPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const 588*bf2c3715SXin Li { 589*bf2c3715SXin Li const Index nonzero_pivots = nonzeroPivots(); 590*bf2c3715SXin Li 591*bf2c3715SXin Li if(nonzero_pivots == 0) 592*bf2c3715SXin Li { 593*bf2c3715SXin Li dst.setZero(); 594*bf2c3715SXin Li return; 595*bf2c3715SXin Li } 596*bf2c3715SXin Li 597*bf2c3715SXin Li typename RhsType::PlainObject c(rhs); 598*bf2c3715SXin Li 599*bf2c3715SXin Li c.applyOnTheLeft(householderQ().setLength(nonzero_pivots).adjoint() ); 600*bf2c3715SXin Li 601*bf2c3715SXin Li m_qr.topLeftCorner(nonzero_pivots, nonzero_pivots) 602*bf2c3715SXin Li .template triangularView<Upper>() 603*bf2c3715SXin Li .solveInPlace(c.topRows(nonzero_pivots)); 604*bf2c3715SXin Li 605*bf2c3715SXin Li for(Index i = 0; i < nonzero_pivots; ++i) dst.row(m_colsPermutation.indices().coeff(i)) = c.row(i); 606*bf2c3715SXin Li for(Index i = nonzero_pivots; i < cols(); ++i) dst.row(m_colsPermutation.indices().coeff(i)).setZero(); 607*bf2c3715SXin Li } 608*bf2c3715SXin Li 609*bf2c3715SXin Li template<typename _MatrixType> 610*bf2c3715SXin Li template<bool Conjugate, typename RhsType, typename DstType> 611*bf2c3715SXin Li void ColPivHouseholderQR<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const 612*bf2c3715SXin Li { 613*bf2c3715SXin Li const Index nonzero_pivots = nonzeroPivots(); 614*bf2c3715SXin Li 615*bf2c3715SXin Li if(nonzero_pivots == 0) 616*bf2c3715SXin Li { 617*bf2c3715SXin Li dst.setZero(); 618*bf2c3715SXin Li return; 619*bf2c3715SXin Li } 620*bf2c3715SXin Li 621*bf2c3715SXin Li typename RhsType::PlainObject c(m_colsPermutation.transpose()*rhs); 622*bf2c3715SXin Li 623*bf2c3715SXin Li m_qr.topLeftCorner(nonzero_pivots, nonzero_pivots) 624*bf2c3715SXin Li .template triangularView<Upper>() 625*bf2c3715SXin Li .transpose().template conjugateIf<Conjugate>() 626*bf2c3715SXin Li .solveInPlace(c.topRows(nonzero_pivots)); 627*bf2c3715SXin Li 628*bf2c3715SXin Li dst.topRows(nonzero_pivots) = c.topRows(nonzero_pivots); 629*bf2c3715SXin Li dst.bottomRows(rows()-nonzero_pivots).setZero(); 630*bf2c3715SXin Li 631*bf2c3715SXin Li dst.applyOnTheLeft(householderQ().setLength(nonzero_pivots).template conjugateIf<!Conjugate>() ); 632*bf2c3715SXin Li } 633*bf2c3715SXin Li #endif 634*bf2c3715SXin Li 635*bf2c3715SXin Li namespace internal { 636*bf2c3715SXin Li 637*bf2c3715SXin Li template<typename DstXprType, typename MatrixType> 638*bf2c3715SXin Li struct Assignment<DstXprType, Inverse<ColPivHouseholderQR<MatrixType> >, internal::assign_op<typename DstXprType::Scalar,typename ColPivHouseholderQR<MatrixType>::Scalar>, Dense2Dense> 639*bf2c3715SXin Li { 640*bf2c3715SXin Li typedef ColPivHouseholderQR<MatrixType> QrType; 641*bf2c3715SXin Li typedef Inverse<QrType> SrcXprType; 642*bf2c3715SXin Li static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename QrType::Scalar> &) 643*bf2c3715SXin Li { 644*bf2c3715SXin Li dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols())); 645*bf2c3715SXin Li } 646*bf2c3715SXin Li }; 647*bf2c3715SXin Li 648*bf2c3715SXin Li } // end namespace internal 649*bf2c3715SXin Li 650*bf2c3715SXin Li /** \returns the matrix Q as a sequence of householder transformations. 651*bf2c3715SXin Li * You can extract the meaningful part only by using: 652*bf2c3715SXin Li * \code qr.householderQ().setLength(qr.nonzeroPivots()) \endcode*/ 653*bf2c3715SXin Li template<typename MatrixType> 654*bf2c3715SXin Li typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHouseholderQR<MatrixType> 655*bf2c3715SXin Li ::householderQ() const 656*bf2c3715SXin Li { 657*bf2c3715SXin Li eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized."); 658*bf2c3715SXin Li return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate()); 659*bf2c3715SXin Li } 660*bf2c3715SXin Li 661*bf2c3715SXin Li /** \return the column-pivoting Householder QR decomposition of \c *this. 662*bf2c3715SXin Li * 663*bf2c3715SXin Li * \sa class ColPivHouseholderQR 664*bf2c3715SXin Li */ 665*bf2c3715SXin Li template<typename Derived> 666*bf2c3715SXin Li const ColPivHouseholderQR<typename MatrixBase<Derived>::PlainObject> 667*bf2c3715SXin Li MatrixBase<Derived>::colPivHouseholderQr() const 668*bf2c3715SXin Li { 669*bf2c3715SXin Li return ColPivHouseholderQR<PlainObject>(eval()); 670*bf2c3715SXin Li } 671*bf2c3715SXin Li 672*bf2c3715SXin Li } // end namespace Eigen 673*bf2c3715SXin Li 674*bf2c3715SXin Li #endif // EIGEN_COLPIVOTINGHOUSEHOLDERQR_H 675