HouseholderQR.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
  6. // Copyright (C) 2010 Vincent Lejeune
  7. //
  8. // This Source Code Form is subject to the terms of the Mozilla
  9. // Public License v. 2.0. If a copy of the MPL was not distributed
  10. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  11. #ifndef EIGEN_QR_H
  12. #define EIGEN_QR_H
  13. namespace Eigen {
  14. namespace internal {
  15. template<typename _MatrixType> struct traits<HouseholderQR<_MatrixType> >
  16. : traits<_MatrixType>
  17. {
  18. typedef MatrixXpr XprKind;
  19. typedef SolverStorage StorageKind;
  20. typedef int StorageIndex;
  21. enum { Flags = 0 };
  22. };
  23. } // end namespace internal
  24. /** \ingroup QR_Module
  25. *
  26. *
  27. * \class HouseholderQR
  28. *
  29. * \brief Householder QR decomposition of a matrix
  30. *
  31. * \tparam _MatrixType the type of the matrix of which we are computing the QR decomposition
  32. *
  33. * This class performs a QR decomposition of a matrix \b A into matrices \b Q and \b R
  34. * such that
  35. * \f[
  36. * \mathbf{A} = \mathbf{Q} \, \mathbf{R}
  37. * \f]
  38. * by using Householder transformations. Here, \b Q a unitary matrix and \b R an upper triangular matrix.
  39. * The result is stored in a compact way compatible with LAPACK.
  40. *
  41. * Note that no pivoting is performed. This is \b not a rank-revealing decomposition.
  42. * If you want that feature, use FullPivHouseholderQR or ColPivHouseholderQR instead.
  43. *
  44. * This Householder QR decomposition is faster, but less numerically stable and less feature-full than
  45. * FullPivHouseholderQR or ColPivHouseholderQR.
  46. *
  47. * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
  48. *
  49. * \sa MatrixBase::householderQr()
  50. */
  51. template<typename _MatrixType> class HouseholderQR
  52. : public SolverBase<HouseholderQR<_MatrixType> >
  53. {
  54. public:
  55. typedef _MatrixType MatrixType;
  56. typedef SolverBase<HouseholderQR> Base;
  57. friend class SolverBase<HouseholderQR>;
  58. EIGEN_GENERIC_PUBLIC_INTERFACE(HouseholderQR)
  59. enum {
  60. MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
  61. MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
  62. };
  63. typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
  64. typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
  65. typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
  66. typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType;
  67. /**
  68. * \brief Default Constructor.
  69. *
  70. * The default constructor is useful in cases in which the user intends to
  71. * perform decompositions via HouseholderQR::compute(const MatrixType&).
  72. */
  73. HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
  74. /** \brief Default Constructor with memory preallocation
  75. *
  76. * Like the default constructor but with preallocation of the internal data
  77. * according to the specified problem \a size.
  78. * \sa HouseholderQR()
  79. */
  80. HouseholderQR(Index rows, Index cols)
  81. : m_qr(rows, cols),
  82. m_hCoeffs((std::min)(rows,cols)),
  83. m_temp(cols),
  84. m_isInitialized(false) {}
  85. /** \brief Constructs a QR factorization from a given matrix
  86. *
  87. * This constructor computes the QR factorization of the matrix \a matrix by calling
  88. * the method compute(). It is a short cut for:
  89. *
  90. * \code
  91. * HouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols());
  92. * qr.compute(matrix);
  93. * \endcode
  94. *
  95. * \sa compute()
  96. */
  97. template<typename InputType>
  98. explicit HouseholderQR(const EigenBase<InputType>& matrix)
  99. : m_qr(matrix.rows(), matrix.cols()),
  100. m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
  101. m_temp(matrix.cols()),
  102. m_isInitialized(false)
  103. {
  104. compute(matrix.derived());
  105. }
  106. /** \brief Constructs a QR factorization from a given matrix
  107. *
  108. * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when
  109. * \c MatrixType is a Eigen::Ref.
  110. *
  111. * \sa HouseholderQR(const EigenBase&)
  112. */
  113. template<typename InputType>
  114. explicit HouseholderQR(EigenBase<InputType>& matrix)
  115. : m_qr(matrix.derived()),
  116. m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
  117. m_temp(matrix.cols()),
  118. m_isInitialized(false)
  119. {
  120. computeInPlace();
  121. }
  122. #ifdef EIGEN_PARSED_BY_DOXYGEN
  123. /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
  124. * *this is the QR decomposition, if any exists.
  125. *
  126. * \param b the right-hand-side of the equation to solve.
  127. *
  128. * \returns a solution.
  129. *
  130. * \note_about_checking_solutions
  131. *
  132. * \note_about_arbitrary_choice_of_solution
  133. *
  134. * Example: \include HouseholderQR_solve.cpp
  135. * Output: \verbinclude HouseholderQR_solve.out
  136. */
  137. template<typename Rhs>
  138. inline const Solve<HouseholderQR, Rhs>
  139. solve(const MatrixBase<Rhs>& b) const;
  140. #endif
  141. /** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
  142. *
  143. * The returned expression can directly be used to perform matrix products. It can also be assigned to a dense Matrix object.
  144. * Here is an example showing how to recover the full or thin matrix Q, as well as how to perform matrix products using operator*:
  145. *
  146. * Example: \include HouseholderQR_householderQ.cpp
  147. * Output: \verbinclude HouseholderQR_householderQ.out
  148. */
  149. HouseholderSequenceType householderQ() const
  150. {
  151. eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
  152. return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
  153. }
  154. /** \returns a reference to the matrix where the Householder QR decomposition is stored
  155. * in a LAPACK-compatible way.
  156. */
  157. const MatrixType& matrixQR() const
  158. {
  159. eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
  160. return m_qr;
  161. }
  162. template<typename InputType>
  163. HouseholderQR& compute(const EigenBase<InputType>& matrix) {
  164. m_qr = matrix.derived();
  165. computeInPlace();
  166. return *this;
  167. }
  168. /** \returns the absolute value of the determinant of the matrix of which
  169. * *this is the QR decomposition. It has only linear complexity
  170. * (that is, O(n) where n is the dimension of the square matrix)
  171. * as the QR decomposition has already been computed.
  172. *
  173. * \note This is only for square matrices.
  174. *
  175. * \warning a determinant can be very big or small, so for matrices
  176. * of large enough dimension, there is a risk of overflow/underflow.
  177. * One way to work around that is to use logAbsDeterminant() instead.
  178. *
  179. * \sa logAbsDeterminant(), MatrixBase::determinant()
  180. */
  181. typename MatrixType::RealScalar absDeterminant() const;
  182. /** \returns the natural log of the absolute value of the determinant of the matrix of which
  183. * *this is the QR decomposition. It has only linear complexity
  184. * (that is, O(n) where n is the dimension of the square matrix)
  185. * as the QR decomposition has already been computed.
  186. *
  187. * \note This is only for square matrices.
  188. *
  189. * \note This method is useful to work around the risk of overflow/underflow that's inherent
  190. * to determinant computation.
  191. *
  192. * \sa absDeterminant(), MatrixBase::determinant()
  193. */
  194. typename MatrixType::RealScalar logAbsDeterminant() const;
  195. inline Index rows() const { return m_qr.rows(); }
  196. inline Index cols() const { return m_qr.cols(); }
  197. /** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q.
  198. *
  199. * For advanced uses only.
  200. */
  201. const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
  202. #ifndef EIGEN_PARSED_BY_DOXYGEN
  203. template<typename RhsType, typename DstType>
  204. void _solve_impl(const RhsType &rhs, DstType &dst) const;
  205. template<bool Conjugate, typename RhsType, typename DstType>
  206. void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
  207. #endif
  208. protected:
  209. static void check_template_parameters()
  210. {
  211. EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
  212. }
  213. void computeInPlace();
  214. MatrixType m_qr;
  215. HCoeffsType m_hCoeffs;
  216. RowVectorType m_temp;
  217. bool m_isInitialized;
  218. };
  219. template<typename MatrixType>
  220. typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const
  221. {
  222. using std::abs;
  223. eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
  224. eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
  225. return abs(m_qr.diagonal().prod());
  226. }
  227. template<typename MatrixType>
  228. typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const
  229. {
  230. eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
  231. eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
  232. return m_qr.diagonal().cwiseAbs().array().log().sum();
  233. }
  234. namespace internal {
  235. /** \internal */
  236. template<typename MatrixQR, typename HCoeffs>
  237. void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0)
  238. {
  239. typedef typename MatrixQR::Scalar Scalar;
  240. typedef typename MatrixQR::RealScalar RealScalar;
  241. Index rows = mat.rows();
  242. Index cols = mat.cols();
  243. Index size = (std::min)(rows,cols);
  244. eigen_assert(hCoeffs.size() == size);
  245. typedef Matrix<Scalar,MatrixQR::ColsAtCompileTime,1> TempType;
  246. TempType tempVector;
  247. if(tempData==0)
  248. {
  249. tempVector.resize(cols);
  250. tempData = tempVector.data();
  251. }
  252. for(Index k = 0; k < size; ++k)
  253. {
  254. Index remainingRows = rows - k;
  255. Index remainingCols = cols - k - 1;
  256. RealScalar beta;
  257. mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
  258. mat.coeffRef(k,k) = beta;
  259. // apply H to remaining part of m_qr from the left
  260. mat.bottomRightCorner(remainingRows, remainingCols)
  261. .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), hCoeffs.coeffRef(k), tempData+k+1);
  262. }
  263. }
  264. /** \internal */
  265. template<typename MatrixQR, typename HCoeffs,
  266. typename MatrixQRScalar = typename MatrixQR::Scalar,
  267. bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
  268. struct householder_qr_inplace_blocked
  269. {
  270. // This is specialized for LAPACK-supported Scalar types in HouseholderQR_LAPACKE.h
  271. static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index maxBlockSize=32,
  272. typename MatrixQR::Scalar* tempData = 0)
  273. {
  274. typedef typename MatrixQR::Scalar Scalar;
  275. typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
  276. Index rows = mat.rows();
  277. Index cols = mat.cols();
  278. Index size = (std::min)(rows, cols);
  279. typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
  280. TempType tempVector;
  281. if(tempData==0)
  282. {
  283. tempVector.resize(cols);
  284. tempData = tempVector.data();
  285. }
  286. Index blockSize = (std::min)(maxBlockSize,size);
  287. Index k = 0;
  288. for (k = 0; k < size; k += blockSize)
  289. {
  290. Index bs = (std::min)(size-k,blockSize); // actual size of the block
  291. Index tcols = cols - k - bs; // trailing columns
  292. Index brows = rows-k; // rows of the block
  293. // partition the matrix:
  294. // A00 | A01 | A02
  295. // mat = A10 | A11 | A12
  296. // A20 | A21 | A22
  297. // and performs the qr dec of [A11^T A12^T]^T
  298. // and update [A21^T A22^T]^T using level 3 operations.
  299. // Finally, the algorithm continue on A22
  300. BlockType A11_21 = mat.block(k,k,brows,bs);
  301. Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
  302. householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
  303. if(tcols)
  304. {
  305. BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
  306. apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment, false); // false == backward
  307. }
  308. }
  309. }
  310. };
  311. } // end namespace internal
  312. #ifndef EIGEN_PARSED_BY_DOXYGEN
  313. template<typename _MatrixType>
  314. template<typename RhsType, typename DstType>
  315. void HouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
  316. {
  317. const Index rank = (std::min)(rows(), cols());
  318. typename RhsType::PlainObject c(rhs);
  319. c.applyOnTheLeft(householderQ().setLength(rank).adjoint() );
  320. m_qr.topLeftCorner(rank, rank)
  321. .template triangularView<Upper>()
  322. .solveInPlace(c.topRows(rank));
  323. dst.topRows(rank) = c.topRows(rank);
  324. dst.bottomRows(cols()-rank).setZero();
  325. }
  326. template<typename _MatrixType>
  327. template<bool Conjugate, typename RhsType, typename DstType>
  328. void HouseholderQR<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
  329. {
  330. const Index rank = (std::min)(rows(), cols());
  331. typename RhsType::PlainObject c(rhs);
  332. m_qr.topLeftCorner(rank, rank)
  333. .template triangularView<Upper>()
  334. .transpose().template conjugateIf<Conjugate>()
  335. .solveInPlace(c.topRows(rank));
  336. dst.topRows(rank) = c.topRows(rank);
  337. dst.bottomRows(rows()-rank).setZero();
  338. dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
  339. }
  340. #endif
  341. /** Performs the QR factorization of the given matrix \a matrix. The result of
  342. * the factorization is stored into \c *this, and a reference to \c *this
  343. * is returned.
  344. *
  345. * \sa class HouseholderQR, HouseholderQR(const MatrixType&)
  346. */
  347. template<typename MatrixType>
  348. void HouseholderQR<MatrixType>::computeInPlace()
  349. {
  350. check_template_parameters();
  351. Index rows = m_qr.rows();
  352. Index cols = m_qr.cols();
  353. Index size = (std::min)(rows,cols);
  354. m_hCoeffs.resize(size);
  355. m_temp.resize(cols);
  356. internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, 48, m_temp.data());
  357. m_isInitialized = true;
  358. }
  359. /** \return the Householder QR decomposition of \c *this.
  360. *
  361. * \sa class HouseholderQR
  362. */
  363. template<typename Derived>
  364. const HouseholderQR<typename MatrixBase<Derived>::PlainObject>
  365. MatrixBase<Derived>::householderQr() const
  366. {
  367. return HouseholderQR<PlainObject>(eval());
  368. }
  369. } // end namespace Eigen
  370. #endif // EIGEN_QR_H