HouseholderQR.h
Go to the documentation of this file.
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 
12 #ifndef EIGEN_QR_H
13 #define EIGEN_QR_H
14 
15 // IWYU pragma: private
16 #include "./InternalHeaderCheck.h"
17 
18 namespace Eigen {
19 
20 namespace internal {
21 template <typename MatrixType_>
22 struct traits<HouseholderQR<MatrixType_>> : traits<MatrixType_> {
23  typedef MatrixXpr XprKind;
25  typedef int StorageIndex;
26  enum { Flags = 0 };
27 };
28 
29 } // end namespace internal
30 
58 template <typename MatrixType_>
59 class HouseholderQR : public SolverBase<HouseholderQR<MatrixType_>> {
60  public:
61  typedef MatrixType_ MatrixType;
63  friend class SolverBase<HouseholderQR>;
64 
66  enum {
67  MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
68  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
69  };
70  typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags & RowMajorBit) ? RowMajor : ColMajor,
77 
85 
93  : m_qr(rows, cols), m_hCoeffs((std::min)(rows, cols)), m_temp(cols), m_isInitialized(false) {}
94 
107  template <typename InputType>
109  : m_qr(matrix.rows(), matrix.cols()),
110  m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
111  m_temp(matrix.cols()),
112  m_isInitialized(false) {
113  compute(matrix.derived());
114  }
115 
123  template <typename InputType>
125  : m_qr(matrix.derived()),
126  m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
127  m_temp(matrix.cols()),
128  m_isInitialized(false) {
129  computeInPlace();
130  }
131 
132 #ifdef EIGEN_PARSED_BY_DOXYGEN
147  template <typename Rhs>
148  inline const Solve<HouseholderQR, Rhs> solve(const MatrixBase<Rhs>& b) const;
149 #endif
150 
161  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
162  return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
163  }
164 
168  const MatrixType& matrixQR() const {
169  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
170  return m_qr;
171  }
172 
173  template <typename InputType>
175  m_qr = matrix.derived();
176  computeInPlace();
177  return *this;
178  }
179 
195  typename MatrixType::Scalar determinant() const;
196 
213 
230 
247 
248  inline Index rows() const { return m_qr.rows(); }
249  inline Index cols() const { return m_qr.cols(); }
250 
255  const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
256 
257 #ifndef EIGEN_PARSED_BY_DOXYGEN
258  template <typename RhsType, typename DstType>
259  void _solve_impl(const RhsType& rhs, DstType& dst) const;
260 
261  template <bool Conjugate, typename RhsType, typename DstType>
262  void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
263 #endif
264 
265  protected:
267 
269 
274 };
275 
276 namespace internal {
277 
279 template <typename HCoeffs, typename Scalar, bool IsComplex>
281  static void run(const HCoeffs& hCoeffs, Scalar& out_det) {
282  out_det = Scalar(1);
283  Index size = hCoeffs.rows();
284  for (Index i = 0; i < size; i++) {
285  // For each valid reflection Q_n,
286  // det(Q_n) = - conj(h_n) / h_n
287  // where h_n is the Householder coefficient.
288  if (hCoeffs(i) != Scalar(0)) out_det *= -numext::conj(hCoeffs(i)) / hCoeffs(i);
289  }
290  }
291 };
292 
294 template <typename HCoeffs, typename Scalar>
295 struct householder_determinant<HCoeffs, Scalar, false> {
296  static void run(const HCoeffs& hCoeffs, Scalar& out_det) {
297  bool negated = false;
298  Index size = hCoeffs.rows();
299  for (Index i = 0; i < size; i++) {
300  // Each valid reflection negates the determinant.
301  if (hCoeffs(i) != Scalar(0)) negated ^= true;
302  }
303  out_det = negated ? Scalar(-1) : Scalar(1);
304  }
305 };
306 
307 } // end namespace internal
308 
309 template <typename MatrixType>
311  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
312  eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
313  Scalar detQ;
315  return m_qr.diagonal().prod() * detQ;
316 }
317 
318 template <typename MatrixType>
320  using std::abs;
321  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
322  eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
323  return abs(m_qr.diagonal().prod());
324 }
325 
326 template <typename MatrixType>
328  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
329  eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
330  return m_qr.diagonal().cwiseAbs().array().log().sum();
331 }
332 
333 template <typename MatrixType>
335  eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
336  eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
337  Scalar detQ;
339  return detQ * m_qr.diagonal().array().sign().prod();
340 }
341 
342 namespace internal {
343 
345 template <typename MatrixQR, typename HCoeffs>
346 void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0) {
347  typedef typename MatrixQR::Scalar Scalar;
348  typedef typename MatrixQR::RealScalar RealScalar;
349  Index rows = mat.rows();
350  Index cols = mat.cols();
351  Index size = (std::min)(rows, cols);
352 
353  eigen_assert(hCoeffs.size() == size);
354 
356  TempType tempVector;
357  if (tempData == 0) {
358  tempVector.resize(cols);
359  tempData = tempVector.data();
360  }
361 
362  for (Index k = 0; k < size; ++k) {
363  Index remainingRows = rows - k;
364  Index remainingCols = cols - k - 1;
365 
367  mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
368  mat.coeffRef(k, k) = beta;
369 
370  // apply H to remaining part of m_qr from the left
371  mat.bottomRightCorner(remainingRows, remainingCols)
372  .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows - 1), hCoeffs.coeffRef(k), tempData + k + 1);
373  }
374 }
375 
376 // TODO: add a corresponding public API for updating a QR factorization
385 template <typename MatrixQR, typename HCoeffs, typename VectorQR>
386 void householder_qr_inplace_update(MatrixQR& mat, HCoeffs& hCoeffs, const VectorQR& newColumn,
387  typename MatrixQR::Index k, typename MatrixQR::Scalar* tempData) {
388  typedef typename MatrixQR::Index Index;
389  typedef typename MatrixQR::RealScalar RealScalar;
390  Index rows = mat.rows();
391 
392  eigen_assert(k < mat.cols());
393  eigen_assert(k < rows);
394  eigen_assert(hCoeffs.size() == mat.cols());
395  eigen_assert(newColumn.size() == rows);
396  eigen_assert(tempData);
397 
398  // Store new column in mat at column k
399  mat.col(k) = newColumn;
400  // Apply H = H_1...H_{k-1} on newColumn (skip if k=0)
401  for (Index i = 0; i < k; ++i) {
402  Index remainingRows = rows - i;
403  mat.col(k)
404  .tail(remainingRows)
405  .applyHouseholderOnTheLeft(mat.col(i).tail(remainingRows - 1), hCoeffs.coeffRef(i), tempData + i + 1);
406  }
407  // Construct Householder projector in-place in column k
409  mat.col(k).tail(rows - k).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
410  mat.coeffRef(k, k) = beta;
411 }
412 
414 template <typename MatrixQR, typename HCoeffs, typename MatrixQRScalar = typename MatrixQR::Scalar,
415  bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
417  // This is specialized for LAPACK-supported Scalar types in HouseholderQR_LAPACKE.h
418  static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index maxBlockSize = 32, typename MatrixQR::Scalar* tempData = 0) {
419  typedef typename MatrixQR::Scalar Scalar;
420  typedef Block<MatrixQR, Dynamic, Dynamic> BlockType;
421 
422  Index rows = mat.rows();
423  Index cols = mat.cols();
424  Index size = (std::min)(rows, cols);
425 
427  TempType tempVector;
428  if (tempData == 0) {
429  tempVector.resize(cols);
430  tempData = tempVector.data();
431  }
432 
433  Index blockSize = (std::min)(maxBlockSize, size);
434 
435  Index k = 0;
436  for (k = 0; k < size; k += blockSize) {
437  Index bs = (std::min)(size - k, blockSize); // actual size of the block
438  Index tcols = cols - k - bs; // trailing columns
439  Index brows = rows - k; // rows of the block
440 
441  // partition the matrix:
442  // A00 | A01 | A02
443  // mat = A10 | A11 | A12
444  // A20 | A21 | A22
445  // and performs the qr dec of [A11^T A12^T]^T
446  // and update [A21^T A22^T]^T using level 3 operations.
447  // Finally, the algorithm continue on A22
448 
449  BlockType A11_21 = mat.block(k, k, brows, bs);
450  Block<HCoeffs, Dynamic, 1> hCoeffsSegment = hCoeffs.segment(k, bs);
451 
452  householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
453 
454  if (tcols) {
455  BlockType A21_22 = mat.block(k, k + bs, brows, tcols);
456  apply_block_householder_on_the_left(A21_22, A11_21, hCoeffsSegment, false); // false == backward
457  }
458  }
459  }
460 };
461 
462 } // end namespace internal
463 
464 #ifndef EIGEN_PARSED_BY_DOXYGEN
465 template <typename MatrixType_>
466 template <typename RhsType, typename DstType>
467 void HouseholderQR<MatrixType_>::_solve_impl(const RhsType& rhs, DstType& dst) const {
468  const Index rank = (std::min)(rows(), cols());
469 
470  typename RhsType::PlainObject c(rhs);
471 
472  c.applyOnTheLeft(householderQ().setLength(rank).adjoint());
473 
474  m_qr.topLeftCorner(rank, rank).template triangularView<Upper>().solveInPlace(c.topRows(rank));
475 
476  dst.topRows(rank) = c.topRows(rank);
477  dst.bottomRows(cols() - rank).setZero();
478 }
479 
480 template <typename MatrixType_>
481 template <bool Conjugate, typename RhsType, typename DstType>
482 void HouseholderQR<MatrixType_>::_solve_impl_transposed(const RhsType& rhs, DstType& dst) const {
483  const Index rank = (std::min)(rows(), cols());
484 
485  typename RhsType::PlainObject c(rhs);
486 
487  m_qr.topLeftCorner(rank, rank)
488  .template triangularView<Upper>()
489  .transpose()
490  .template conjugateIf<Conjugate>()
491  .solveInPlace(c.topRows(rank));
492 
493  dst.topRows(rank) = c.topRows(rank);
494  dst.bottomRows(rows() - rank).setZero();
495 
496  dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>());
497 }
498 #endif
499 
506 template <typename MatrixType>
508  Index rows = m_qr.rows();
509  Index cols = m_qr.cols();
510  Index size = (std::min)(rows, cols);
511 
512  m_hCoeffs.resize(size);
513 
514  m_temp.resize(cols);
515 
517 
518  m_isInitialized = true;
519 }
520 
525 template <typename Derived>
528 }
529 
530 } // end namespace Eigen
531 
532 #endif // EIGEN_QR_H
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
AnnoyingScalar conj(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:133
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived)
Definition: Macros.h:1149
#define eigen_assert(x)
Definition: Macros.h:910
#define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE)
Definition: StaticAssert.h:74
Scalar * b
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
Expression of a fixed-size or dynamic-size block.
Definition: Block.h:110
Householder QR decomposition of a matrix.
Definition: HouseholderQR.h:59
MatrixType::Scalar signDeterminant() const
Definition: HouseholderQR.h:334
HouseholderQR(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition: HouseholderQR.h:92
HouseholderQR(EigenBase< InputType > &matrix)
Constructs a QR factorization from a given matrix.
Definition: HouseholderQR.h:124
void computeInPlace()
Definition: HouseholderQR.h:507
HouseholderQR(const EigenBase< InputType > &matrix)
Constructs a QR factorization from a given matrix.
Definition: HouseholderQR.h:108
HouseholderSequence< MatrixType, internal::remove_all_t< typename HCoeffsType::ConjugateReturnType > > HouseholderSequenceType
Definition: HouseholderQR.h:76
MatrixType_ MatrixType
Definition: HouseholderQR.h:61
Index rows() const
Definition: HouseholderQR.h:248
MatrixType::Scalar determinant() const
Definition: HouseholderQR.h:310
MatrixType m_qr
Definition: HouseholderQR.h:270
const HCoeffsType & hCoeffs() const
Definition: HouseholderQR.h:255
internal::plain_diag_type< MatrixType >::type HCoeffsType
Definition: HouseholderQR.h:73
HouseholderSequenceType householderQ() const
Definition: HouseholderQR.h:160
HouseholderQR()
Default Constructor.
Definition: HouseholderQR.h:84
HCoeffsType m_hCoeffs
Definition: HouseholderQR.h:271
@ MaxRowsAtCompileTime
Definition: HouseholderQR.h:67
@ MaxColsAtCompileTime
Definition: HouseholderQR.h:68
MatrixType::RealScalar absDeterminant() const
Definition: HouseholderQR.h:319
const MatrixType & matrixQR() const
Definition: HouseholderQR.h:168
bool m_isInitialized
Definition: HouseholderQR.h:273
HouseholderQR & compute(const EigenBase< InputType > &matrix)
Definition: HouseholderQR.h:174
Index cols() const
Definition: HouseholderQR.h:249
SolverBase< HouseholderQR > Base
Definition: HouseholderQR.h:62
internal::plain_row_type< MatrixType >::type RowVectorType
Definition: HouseholderQR.h:74
void _solve_impl(const RhsType &rhs, DstType &dst) const
Definition: HouseholderQR.h:467
RowVectorType m_temp
Definition: HouseholderQR.h:272
MatrixType::RealScalar logAbsDeterminant() const
Definition: HouseholderQR.h:327
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const
Definition: HouseholderQR.h:482
Sequence of Householder reflections acting on subspaces with decreasing size.
Definition: HouseholderSequence.h:117
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:52
const HouseholderQR< PlainObject > householderQr() const
Definition: HouseholderQR.h:526
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
Pseudo expression representing a solving operation.
Definition: Solve.h:62
A base class for matrix decomposition and solvers.
Definition: SolverBase.h:72
internal::traits< HouseholderQR< MatrixType_ > >::Scalar Scalar
Definition: SolverBase.h:75
constexpr EIGEN_DEVICE_FUNC HouseholderQR< MatrixType_ > & derived()
Definition: EigenBase.h:49
const Solve< HouseholderQR< MatrixType_ >, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: SolverBase.h:106
@ RowsAtCompileTime
Definition: SolverBase.h:82
const AdjointReturnType adjoint() const
Definition: SolverBase.h:136
Index cols() const
Definition: SparseMatrix.h:161
Scalar & coeffRef(Index row, Index col)
Definition: SparseMatrix.h:275
Index rows() const
Definition: SparseMatrix.h:159
Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor >, 0, Eigen::OuterStride<> > matrix(T *data, int rows, int cols, int stride)
Definition: common.h:85
#define min(a, b)
Definition: datatypes.h:22
@ ColMajor
Definition: Constants.h:318
@ RowMajor
Definition: Constants.h:320
const unsigned int RowMajorBit
Definition: Constants.h:70
Scalar beta
Definition: level2_cplx_impl.h:36
char char char int int * k
Definition: level2_impl.h:374
void householder_qr_inplace_unblocked(MatrixQR &mat, HCoeffs &hCoeffs, typename MatrixQR::Scalar *tempData=0)
Definition: HouseholderQR.h:346
void householder_qr_inplace_update(MatrixQR &mat, HCoeffs &hCoeffs, const VectorQR &newColumn, typename MatrixQR::Index k, typename MatrixQR::Scalar *tempData)
Definition: HouseholderQR.h:386
void apply_block_householder_on_the_left(MatrixType &mat, const VectorsType &vectors, const CoeffsType &hCoeffs, bool forward)
Definition: BlockHouseholder.h:86
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
auto run(Kernel kernel, Args &&... args) -> decltype(kernel(args...))
Definition: gpu_test_helper.h:414
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
CleanedUpDerType< DerType >::type() min(const AutoDiffScalar< DerType > &x, const T &y)
Definition: AutoDiffScalar.h:494
Extend namespace for flags.
Definition: fsi_chan_precond_driver.cc:56
int c
Definition: calibrate.py:100
Definition: Eigen_Colamd.h:49
internal::nested_eval< T, 1 >::type eval(const T &xpr)
Definition: sparse_permutations.cpp:47
Definition: EigenBase.h:33
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:43
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
Definition: EigenBase.h:64
Definition: Constants.h:534
Definition: Constants.h:525
static void run(const HCoeffs &hCoeffs, Scalar &out_det)
Definition: HouseholderQR.h:296
Definition: HouseholderQR.h:280
static void run(const HCoeffs &hCoeffs, Scalar &out_det)
Definition: HouseholderQR.h:281
static void run(MatrixQR &mat, HCoeffs &hCoeffs, Index maxBlockSize=32, typename MatrixQR::Scalar *tempData=0)
Definition: HouseholderQR.h:418
std::conditional_t< is_same< typename traits< ExpressionType >::XprKind, MatrixXpr >::value, MatrixDiagType, ArrayDiagType > type
Definition: XprHelper.h:797
std::conditional_t< is_same< typename traits< ExpressionType >::XprKind, MatrixXpr >::value, MatrixRowType, ArrayRowType > type
Definition: XprHelper.h:768
MatrixXpr XprKind
Definition: HouseholderQR.h:23
int StorageIndex
Definition: HouseholderQR.h:25
SolverStorage StorageKind
Definition: HouseholderQR.h:24
Definition: ForwardDeclarations.h:21