00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef EIGEN_QR_H
00028 #define EIGEN_QR_H
00029
00055 template<typename _MatrixType> class HouseholderQR
00056 {
00057 public:
00058
00059 typedef _MatrixType MatrixType;
00060 enum {
00061 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
00062 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
00063 Options = MatrixType::Options,
00064 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
00065 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
00066 };
00067 typedef typename MatrixType::Scalar Scalar;
00068 typedef typename MatrixType::RealScalar RealScalar;
00069 typedef typename MatrixType::Index Index;
00070 typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
00071 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
00072 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
00073 typedef typename HouseholderSequence<MatrixType,HCoeffsType>::ConjugateReturnType HouseholderSequenceType;
00074
00081 HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
00082
00089 HouseholderQR(Index rows, Index cols)
00090 : m_qr(rows, cols),
00091 m_hCoeffs(std::min(rows,cols)),
00092 m_temp(cols),
00093 m_isInitialized(false) {}
00094
00095 HouseholderQR(const MatrixType& matrix)
00096 : m_qr(matrix.rows(), matrix.cols()),
00097 m_hCoeffs(std::min(matrix.rows(),matrix.cols())),
00098 m_temp(matrix.cols()),
00099 m_isInitialized(false)
00100 {
00101 compute(matrix);
00102 }
00103
00121 template<typename Rhs>
00122 inline const internal::solve_retval<HouseholderQR, Rhs>
00123 solve(const MatrixBase<Rhs>& b) const
00124 {
00125 eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
00126 return internal::solve_retval<HouseholderQR, Rhs>(*this, b.derived());
00127 }
00128
00129 HouseholderSequenceType householderQ() const
00130 {
00131 eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
00132 return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
00133 }
00134
00138 const MatrixType& matrixQR() const
00139 {
00140 eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
00141 return m_qr;
00142 }
00143
00144 HouseholderQR& compute(const MatrixType& matrix);
00145
00159 typename MatrixType::RealScalar absDeterminant() const;
00160
00173 typename MatrixType::RealScalar logAbsDeterminant() const;
00174
00175 inline Index rows() const { return m_qr.rows(); }
00176 inline Index cols() const { return m_qr.cols(); }
00177 const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
00178
00179 protected:
00180 MatrixType m_qr;
00181 HCoeffsType m_hCoeffs;
00182 RowVectorType m_temp;
00183 bool m_isInitialized;
00184 };
00185
00186 template<typename MatrixType>
00187 typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const
00188 {
00189 eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
00190 eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
00191 return internal::abs(m_qr.diagonal().prod());
00192 }
00193
00194 template<typename MatrixType>
00195 typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const
00196 {
00197 eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
00198 eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
00199 return m_qr.diagonal().cwiseAbs().array().log().sum();
00200 }
00201
00202 namespace internal {
00203
00205 template<typename MatrixQR, typename HCoeffs>
00206 void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0)
00207 {
00208 typedef typename MatrixQR::Index Index;
00209 typedef typename MatrixQR::Scalar Scalar;
00210 typedef typename MatrixQR::RealScalar RealScalar;
00211 Index rows = mat.rows();
00212 Index cols = mat.cols();
00213 Index size = std::min(rows,cols);
00214
00215 eigen_assert(hCoeffs.size() == size);
00216
00217 typedef Matrix<Scalar,MatrixQR::ColsAtCompileTime,1> TempType;
00218 TempType tempVector;
00219 if(tempData==0)
00220 {
00221 tempVector.resize(cols);
00222 tempData = tempVector.data();
00223 }
00224
00225 for(Index k = 0; k < size; ++k)
00226 {
00227 Index remainingRows = rows - k;
00228 Index remainingCols = cols - k - 1;
00229
00230 RealScalar beta;
00231 mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
00232 mat.coeffRef(k,k) = beta;
00233
00234
00235 mat.bottomRightCorner(remainingRows, remainingCols)
00236 .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), hCoeffs.coeffRef(k), tempData+k+1);
00237 }
00238 }
00239
00241 template<typename MatrixQR, typename HCoeffs>
00242 void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs,
00243 typename MatrixQR::Index maxBlockSize=32,
00244 typename MatrixQR::Scalar* tempData = 0)
00245 {
00246 typedef typename MatrixQR::Index Index;
00247 typedef typename MatrixQR::Scalar Scalar;
00248 typedef typename MatrixQR::RealScalar RealScalar;
00249 typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
00250
00251 Index rows = mat.rows();
00252 Index cols = mat.cols();
00253 Index size = std::min(rows, cols);
00254
00255 typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
00256 TempType tempVector;
00257 if(tempData==0)
00258 {
00259 tempVector.resize(cols);
00260 tempData = tempVector.data();
00261 }
00262
00263 Index blockSize = std::min(maxBlockSize,size);
00264
00265 int k = 0;
00266 for (k = 0; k < size; k += blockSize)
00267 {
00268 Index bs = std::min(size-k,blockSize);
00269 Index tcols = cols - k - bs;
00270 Index brows = rows-k;
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 BlockType A11_21 = mat.block(k,k,brows,bs);
00281 Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
00282
00283 householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
00284
00285 if(tcols)
00286 {
00287 BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
00288 apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment.adjoint());
00289 }
00290 }
00291 }
00292
00293 template<typename _MatrixType, typename Rhs>
00294 struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
00295 : solve_retval_base<HouseholderQR<_MatrixType>, Rhs>
00296 {
00297 EIGEN_MAKE_SOLVE_HELPERS(HouseholderQR<_MatrixType>,Rhs)
00298
00299 template<typename Dest> void evalTo(Dest& dst) const
00300 {
00301 const Index rows = dec().rows(), cols = dec().cols();
00302 const Index rank = std::min(rows, cols);
00303 eigen_assert(rhs().rows() == rows);
00304
00305 typename Rhs::PlainObject c(rhs());
00306
00307
00308 c.applyOnTheLeft(householderSequence(
00309 dec().matrixQR().leftCols(rank),
00310 dec().hCoeffs().head(rank)).transpose()
00311 );
00312
00313 dec().matrixQR()
00314 .topLeftCorner(rank, rank)
00315 .template triangularView<Upper>()
00316 .solveInPlace(c.topRows(rank));
00317
00318 dst.topRows(rank) = c.topRows(rank);
00319 dst.bottomRows(cols-rank).setZero();
00320 }
00321 };
00322
00323 }
00324
00325 template<typename MatrixType>
00326 HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& matrix)
00327 {
00328 Index rows = matrix.rows();
00329 Index cols = matrix.cols();
00330 Index size = std::min(rows,cols);
00331
00332 m_qr = matrix;
00333 m_hCoeffs.resize(size);
00334
00335 m_temp.resize(cols);
00336
00337 internal::householder_qr_inplace_blocked(m_qr, m_hCoeffs, 48, m_temp.data());
00338
00339 m_isInitialized = true;
00340 return *this;
00341 }
00342
00347 template<typename Derived>
00348 const HouseholderQR<typename MatrixBase<Derived>::PlainObject>
00349 MatrixBase<Derived>::householderQr() const
00350 {
00351 return HouseholderQR<PlainObject>(eval());
00352 }
00353
00354
00355 #endif // EIGEN_QR_H