Eigen  3.2.7
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
HouseholderQR.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2010 Gael Guennebaud <[email protected]>
5 // Copyright (C) 2009 Benoit Jacob <[email protected]>
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 
12 #ifndef EIGEN_QR_H
13 #define EIGEN_QR_H
14 
15 namespace Eigen {
16 
42 template<typename _MatrixType> class HouseholderQR
43 {
44  public:
45 
46  typedef _MatrixType MatrixType;
47  enum {
48  RowsAtCompileTime = MatrixType::RowsAtCompileTime,
49  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
50  Options = MatrixType::Options,
51  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
52  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
53  };
54  typedef typename MatrixType::Scalar Scalar;
55  typedef typename MatrixType::RealScalar RealScalar;
56  typedef typename MatrixType::Index Index;
57  typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
58  typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
59  typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
60  typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename HCoeffsType::ConjugateReturnType>::type> HouseholderSequenceType;
61 
68  HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
69 
76  HouseholderQR(Index rows, Index cols)
77  : m_qr(rows, cols),
78  m_hCoeffs((std::min)(rows,cols)),
79  m_temp(cols),
80  m_isInitialized(false) {}
81 
94  HouseholderQR(const MatrixType& matrix)
95  : m_qr(matrix.rows(), matrix.cols()),
96  m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
97  m_temp(matrix.cols()),
98  m_isInitialized(false)
99  {
100  compute(matrix);
101  }
102 
120  template<typename Rhs>
121  inline const internal::solve_retval<HouseholderQR, Rhs>
122  solve(const MatrixBase<Rhs>& b) const
123  {
124  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
125  return internal::solve_retval<HouseholderQR, Rhs>(*this, b.derived());
126  }
127 
137  {
138  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
139  return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
140  }
141 
145  const MatrixType& matrixQR() const
146  {
147  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
148  return m_qr;
149  }
150 
151  HouseholderQR& compute(const MatrixType& matrix);
152 
166  typename MatrixType::RealScalar absDeterminant() const;
167 
180  typename MatrixType::RealScalar logAbsDeterminant() const;
181 
182  inline Index rows() const { return m_qr.rows(); }
183  inline Index cols() const { return m_qr.cols(); }
184 
189  const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
190 
191  protected:
192 
193  static void check_template_parameters()
194  {
195  EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
196  }
197 
198  MatrixType m_qr;
199  HCoeffsType m_hCoeffs;
200  RowVectorType m_temp;
201  bool m_isInitialized;
202 };
203 
204 template<typename MatrixType>
205 typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const
206 {
207  using std::abs;
208  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
209  eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
210  return abs(m_qr.diagonal().prod());
211 }
212 
213 template<typename MatrixType>
214 typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const
215 {
216  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
217  eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
218  return m_qr.diagonal().cwiseAbs().array().log().sum();
219 }
220 
221 namespace internal {
222 
224 template<typename MatrixQR, typename HCoeffs>
225 void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0)
226 {
227  typedef typename MatrixQR::Index Index;
228  typedef typename MatrixQR::Scalar Scalar;
229  typedef typename MatrixQR::RealScalar RealScalar;
230  Index rows = mat.rows();
231  Index cols = mat.cols();
232  Index size = (std::min)(rows,cols);
233 
234  eigen_assert(hCoeffs.size() == size);
235 
237  TempType tempVector;
238  if(tempData==0)
239  {
240  tempVector.resize(cols);
241  tempData = tempVector.data();
242  }
243 
244  for(Index k = 0; k < size; ++k)
245  {
246  Index remainingRows = rows - k;
247  Index remainingCols = cols - k - 1;
248 
249  RealScalar beta;
250  mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
251  mat.coeffRef(k,k) = beta;
252 
253  // apply H to remaining part of m_qr from the left
254  mat.bottomRightCorner(remainingRows, remainingCols)
255  .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), hCoeffs.coeffRef(k), tempData+k+1);
256  }
257 }
258 
260 template<typename MatrixQR, typename HCoeffs,
261  typename MatrixQRScalar = typename MatrixQR::Scalar,
262  bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
263 struct householder_qr_inplace_blocked
264 {
265  // This is specialized for MKL-supported Scalar types in HouseholderQR_MKL.h
266  static void run(MatrixQR& mat, HCoeffs& hCoeffs,
267  typename MatrixQR::Index maxBlockSize=32,
268  typename MatrixQR::Scalar* tempData = 0)
269  {
270  typedef typename MatrixQR::Index Index;
271  typedef typename MatrixQR::Scalar Scalar;
272  typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
273 
274  Index rows = mat.rows();
275  Index cols = mat.cols();
276  Index size = (std::min)(rows, cols);
277 
278  typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
279  TempType tempVector;
280  if(tempData==0)
281  {
282  tempVector.resize(cols);
283  tempData = tempVector.data();
284  }
285 
286  Index blockSize = (std::min)(maxBlockSize,size);
287 
288  Index k = 0;
289  for (k = 0; k < size; k += blockSize)
290  {
291  Index bs = (std::min)(size-k,blockSize); // actual size of the block
292  Index tcols = cols - k - bs; // trailing columns
293  Index brows = rows-k; // rows of the block
294 
295  // partition the matrix:
296  // A00 | A01 | A02
297  // mat = A10 | A11 | A12
298  // A20 | A21 | A22
299  // and performs the qr dec of [A11^T A12^T]^T
300  // and update [A21^T A22^T]^T using level 3 operations.
301  // Finally, the algorithm continue on A22
302 
303  BlockType A11_21 = mat.block(k,k,brows,bs);
304  Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
305 
306  householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
307 
308  if(tcols)
309  {
310  BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
311  apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment.adjoint());
312  }
313  }
314  }
315 };
316 
317 template<typename _MatrixType, typename Rhs>
318 struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
319  : solve_retval_base<HouseholderQR<_MatrixType>, Rhs>
320 {
321  EIGEN_MAKE_SOLVE_HELPERS(HouseholderQR<_MatrixType>,Rhs)
322 
323  template<typename Dest> void evalTo(Dest& dst) const
324  {
325  const Index rows = dec().rows(), cols = dec().cols();
326  const Index rank = (std::min)(rows, cols);
327  eigen_assert(rhs().rows() == rows);
328 
329  typename Rhs::PlainObject c(rhs());
330 
331  // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
332  c.applyOnTheLeft(householderSequence(
333  dec().matrixQR().leftCols(rank),
334  dec().hCoeffs().head(rank)).transpose()
335  );
336 
337  dec().matrixQR()
338  .topLeftCorner(rank, rank)
339  .template triangularView<Upper>()
340  .solveInPlace(c.topRows(rank));
341 
342  dst.topRows(rank) = c.topRows(rank);
343  dst.bottomRows(cols-rank).setZero();
344  }
345 };
346 
347 } // end namespace internal
348 
355 template<typename MatrixType>
357 {
358  check_template_parameters();
359 
360  Index rows = matrix.rows();
361  Index cols = matrix.cols();
362  Index size = (std::min)(rows,cols);
363 
364  m_qr = matrix;
365  m_hCoeffs.resize(size);
366 
367  m_temp.resize(cols);
368 
369  internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, 48, m_temp.data());
370 
371  m_isInitialized = true;
372  return *this;
373 }
374 
379 template<typename Derived>
382 {
383  return HouseholderQR<PlainObject>(eval());
384 }
385 
386 } // end namespace Eigen
387 
388 #endif // EIGEN_QR_H
HouseholderQR(const MatrixType &matrix)
Constructs a QR factorization from a given matrix.
Definition: HouseholderQR.h:94
MatrixType::RealScalar logAbsDeterminant() const
Definition: HouseholderQR.h:214
HouseholderSequence< VectorsType, CoeffsType > householderSequence(const VectorsType &v, const CoeffsType &h)
Convenience function for constructing a Householder sequence.
Definition: HouseholderSequence.h:422
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition: ForwardDeclarations.h:227
HouseholderSequenceType householderQ() const
Definition: HouseholderQR.h:136
const HouseholderQR< PlainObject > householderQr() const
Definition: HouseholderQR.h:381
const internal::solve_retval< HouseholderQR, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: HouseholderQR.h:122
HouseholderQR()
Default Constructor.
Definition: HouseholderQR.h:68
MatrixType::RealScalar absDeterminant() const
Definition: HouseholderQR.h:205
const HCoeffsType & hCoeffs() const
Definition: HouseholderQR.h:189
HouseholderQR & compute(const MatrixType &matrix)
Definition: HouseholderQR.h:356
Householder QR decomposition of a matrix.
Definition: ForwardDeclarations.h:221
HouseholderQR(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition: HouseholderQR.h:76
void resize(Index nbRows, Index nbCols)
Definition: PlainObjectBase.h:235
const MatrixType & matrixQR() const
Definition: HouseholderQR.h:145
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:127
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48