12#ifndef EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
13#define EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
16#include "./InternalHeaderCheck.h"
22template <
typename MatrixType_,
typename PermutationIndex_>
23struct traits<FullPivHouseholderQR<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
24 using XprKind = MatrixXpr;
25 using StorageKind = SolverStorage;
26 using PermutationIndex = PermutationIndex_;
30template <
typename MatrixType,
typename PermutationIndex>
33template <
typename MatrixType,
typename PermutationIndex>
35 using ReturnType =
typename MatrixType::PlainObject;
64template <
typename MatrixType_,
typename PermutationIndex_>
66 public RankRevealingBase<FullPivHouseholderQR<MatrixType_, PermutationIndex_> > {
68 using MatrixType = MatrixType_;
70 using RankRevealingBase_ = RankRevealingBase<FullPivHouseholderQR>;
82 using PermutationIndex = PermutationIndex_;
86 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
87 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
90 using HCoeffsType =
typename internal::plain_diag_type<MatrixType>::type;
91 using IntDiagSizeVectorType =
92 Matrix<PermutationIndex, 1, internal::min_size_prefer_dynamic(ColsAtCompileTime, RowsAtCompileTime),
RowMajor, 1,
93 internal::min_size_prefer_fixed(MaxColsAtCompileTime, MaxRowsAtCompileTime)>;
95 using RowVectorType =
typename internal::plain_row_type<MatrixType>::type;
96 using ColVectorType =
typename internal::plain_col_type<MatrixType>::type;
97 using PlainObject =
typename MatrixType::PlainObject;
106 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
118 m_rows_transpositions(),
119 m_cols_transpositions(),
120 m_cols_permutation(),
122 m_isInitialized(false) {}
132 m_hCoeffs((std::min)(rows, cols)),
133 m_rows_transpositions((std::min)(rows, cols)),
134 m_cols_transpositions((std::min)(rows, cols)),
135 m_cols_permutation(cols),
137 m_isInitialized(false) {}
151 template <
typename InputType>
153 : m_qr(matrix.rows(), matrix.cols()),
154 m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
155 m_rows_transpositions((std::min)(matrix.rows(), matrix.cols())),
156 m_cols_transpositions((std::min)(matrix.rows(), matrix.cols())),
157 m_cols_permutation(matrix.cols()),
158 m_temp(matrix.cols()),
159 m_isInitialized(false) {
170 template <
typename InputType>
173 m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
174 m_rows_transpositions((std::min)(matrix.rows(), matrix.cols())),
175 m_cols_transpositions((std::min)(matrix.rows(), matrix.cols())),
176 m_cols_permutation(matrix.cols()),
177 m_temp(matrix.cols()),
178 m_isInitialized(false) {
182#ifdef EIGEN_PARSED_BY_DOXYGEN
201 template <
typename Rhs>
212 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
216 template <
typename InputType>
221 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
222 return m_cols_permutation;
227 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
228 return m_rows_transpositions;
292 return abs(m_qr.coeff(i, i));
301 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
305 inline Index rows()
const {
return m_qr.rows(); }
306 inline Index cols()
const {
return m_qr.cols(); }
312 const HCoeffsType&
hCoeffs()
const {
return m_hCoeffs; }
314#ifndef EIGEN_PARSED_BY_DOXYGEN
315 template <
typename RhsType,
typename DstType>
316 void _solve_impl(
const RhsType& rhs, DstType& dst)
const;
318 template <
bool Conjugate,
typename RhsType,
typename DstType>
319 void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const;
323 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
325 void computeInPlace();
328 HCoeffsType m_hCoeffs;
329 IntDiagSizeVectorType m_rows_transpositions;
330 IntDiagSizeVectorType m_cols_transpositions;
331 PermutationType m_cols_permutation;
332 RowVectorType m_temp;
333 bool m_isInitialized;
334 RealScalar m_precision;
338template <
typename MatrixType,
typename PermutationIndex>
340 eigen_assert(m_isInitialized &&
"HouseholderQR is not initialized.");
341 eigen_assert(m_qr.rows() == m_qr.cols() &&
"You can't take the determinant of a non-square matrix!");
343 internal::householder_determinant<HCoeffsType, Scalar, NumTraits<Scalar>::IsComplex>::run(m_hCoeffs, detQ);
344 return isInjective() ? (detQ * Scalar(m_det_p)) * m_qr.diagonal().prod() : Scalar(0);
347template <
typename MatrixType,
typename PermutationIndex>
350 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
351 eigen_assert(m_qr.rows() == m_qr.cols() &&
"You can't take the determinant of a non-square matrix!");
352 return isInjective() ? abs(m_qr.diagonal().prod()) : RealScalar(0);
355template <
typename MatrixType,
typename PermutationIndex>
357 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
358 eigen_assert(m_qr.rows() == m_qr.cols() &&
"You can't take the determinant of a non-square matrix!");
359 return isInjective() ? m_qr.diagonal().cwiseAbs().array().log().sum() : -NumTraits<RealScalar>::infinity();
362template <
typename MatrixType,
typename PermutationIndex>
364 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
365 eigen_assert(m_qr.rows() == m_qr.cols() &&
"You can't take the determinant of a non-square matrix!");
367 internal::householder_determinant<HCoeffsType, Scalar, NumTraits<Scalar>::IsComplex>::run(m_hCoeffs, detQ);
368 return isInjective() ? (detQ * Scalar(m_det_p)) * m_qr.diagonal().array().sign().prod() : Scalar(0);
377template <
typename MatrixType,
typename PermutationIndex>
378template <
typename InputType>
386template <
typename MatrixType,
typename PermutationIndex>
387void FullPivHouseholderQR<MatrixType, PermutationIndex>::computeInPlace() {
388 eigen_assert(m_qr.cols() <= NumTraits<PermutationIndex>::highest());
390 Index rows = m_qr.rows();
391 Index cols = m_qr.cols();
392 Index size = (std::min)(rows, cols);
394 m_hCoeffs.resize(size);
398 m_precision = NumTraits<Scalar>::epsilon() * RealScalar(size);
400 m_rows_transpositions.resize(size);
401 m_cols_transpositions.resize(size);
402 Index number_of_transpositions = 0;
404 RealScalar biggest(0);
406 this->m_nonzero_pivots = size;
407 this->m_maxpivot = RealScalar(0);
409 for (Index k = 0; k < size; ++k) {
410 Index row_of_biggest_in_corner, col_of_biggest_in_corner;
411 using Scoring = internal::scalar_score_coeff_op<Scalar>;
412 using Score =
typename Scoring::result_type;
414 Score score = m_qr.bottomRightCorner(rows - k, cols - k)
415 .unaryExpr(Scoring())
416 .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
417 row_of_biggest_in_corner += k;
418 col_of_biggest_in_corner += k;
419 RealScalar biggest_in_corner =
420 internal::abs_knowing_score<Scalar>()(m_qr(row_of_biggest_in_corner, col_of_biggest_in_corner), score);
421 if (k == 0) biggest = biggest_in_corner;
424 if (internal::isMuchSmallerThan(biggest_in_corner, biggest, m_precision)) {
425 this->m_nonzero_pivots = k;
426 for (Index i = k; i < size; i++) {
427 m_rows_transpositions.coeffRef(i) = internal::convert_index<PermutationIndex>(i);
428 m_cols_transpositions.coeffRef(i) = internal::convert_index<PermutationIndex>(i);
429 m_hCoeffs.coeffRef(i) = Scalar(0);
434 m_rows_transpositions.coeffRef(k) = internal::convert_index<PermutationIndex>(row_of_biggest_in_corner);
435 m_cols_transpositions.coeffRef(k) = internal::convert_index<PermutationIndex>(col_of_biggest_in_corner);
436 if (k != row_of_biggest_in_corner) {
437 m_qr.row(k).tail(cols - k).swap(m_qr.row(row_of_biggest_in_corner).tail(cols - k));
438 ++number_of_transpositions;
440 if (k != col_of_biggest_in_corner) {
441 m_qr.col(k).swap(m_qr.col(col_of_biggest_in_corner));
442 ++number_of_transpositions;
446 m_qr.col(k).tail(rows - k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta);
447 m_qr.coeffRef(k, k) = beta;
450 if (abs(beta) > this->m_maxpivot) this->m_maxpivot = abs(beta);
452 m_qr.bottomRightCorner(rows - k, cols - k - 1)
453 .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows - k - 1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k + 1));
456 m_cols_permutation.setIdentity(cols);
457 for (Index k = 0; k < size; ++k) m_cols_permutation.applyTranspositionOnTheRight(k, m_cols_transpositions.coeff(k));
459 m_det_p = (number_of_transpositions % 2) ? -1 : 1;
460 m_isInitialized =
true;
463#ifndef EIGEN_PARSED_BY_DOXYGEN
464template <
typename MatrixType_,
typename PermutationIndex_>
465template <
typename RhsType,
typename DstType>
467 const Index l_rank = rank();
475 typename RhsType::PlainObject c(rhs);
478 for (Index k = 0; k < l_rank; ++k) {
479 Index remainingSize = rows() - k;
480 c.row(k).swap(c.row(m_rows_transpositions.coeff(k)));
481 c.bottomRightCorner(remainingSize, rhs.cols())
482 .applyHouseholderOnTheLeft(m_qr.col(k).tail(remainingSize - 1), m_hCoeffs.coeff(k), &temp.coeffRef(0));
485 m_qr.topLeftCorner(l_rank, l_rank).template triangularView<Upper>().solveInPlace(c.topRows(l_rank));
487 for (Index i = 0; i < l_rank; ++i) dst.row(m_cols_permutation.indices().coeff(i)) = c.row(i);
488 for (Index i = l_rank; i < cols(); ++i) dst.row(m_cols_permutation.indices().coeff(i)).setZero();
491template <
typename MatrixType_,
typename PermutationIndex_>
492template <
bool Conjugate,
typename RhsType,
typename DstType>
494 DstType& dst)
const {
495 const Index l_rank = rank();
502 typename RhsType::PlainObject c(m_cols_permutation.transpose() * rhs);
504 m_qr.topLeftCorner(l_rank, l_rank)
505 .template triangularView<Upper>()
507 .template conjugateIf<Conjugate>()
508 .solveInPlace(c.topRows(l_rank));
510 dst.topRows(l_rank) = c.topRows(l_rank);
511 dst.bottomRows(rows() - l_rank).setZero();
514 const Index size = (std::min)(rows(), cols());
515 for (Index k = size - 1; k >= 0; --k) {
516 Index remainingSize = rows() - k;
518 dst.bottomRightCorner(remainingSize, dst.cols())
519 .applyHouseholderOnTheLeft(m_qr.col(k).tail(remainingSize - 1).template conjugateIf<!Conjugate>(),
520 m_hCoeffs.template conjugateIf<Conjugate>().coeff(k), &temp.coeffRef(0));
522 dst.row(k).swap(dst.row(m_rows_transpositions.coeff(k)));
529template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
530struct Assignment<DstXprType, Inverse<FullPivHouseholderQR<MatrixType, PermutationIndex> >,
531 internal::assign_op<typename DstXprType::Scalar,
532 typename FullPivHouseholderQR<MatrixType, PermutationIndex>::Scalar>,
534 using QrType = FullPivHouseholderQR<MatrixType, PermutationIndex>;
535 using SrcXprType = Inverse<QrType>;
536 static void run(DstXprType& dst,
const SrcXprType& src,
537 const internal::assign_op<typename DstXprType::Scalar, typename QrType::Scalar>&) {
538 dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
548template <
typename MatrixType,
typename PermutationIndex>
549struct FullPivHouseholderQRMatrixQReturnType
550 :
public ReturnByValue<FullPivHouseholderQRMatrixQReturnType<MatrixType, PermutationIndex> > {
552 using IntDiagSizeVectorType =
typename FullPivHouseholderQR<MatrixType, PermutationIndex>::IntDiagSizeVectorType;
553 using HCoeffsType =
typename internal::plain_diag_type<MatrixType>::type;
554 using WorkVectorType =
Matrix<
typename MatrixType::Scalar, 1, MatrixType::RowsAtCompileTime,
RowMajor, 1,
555 MatrixType::MaxRowsAtCompileTime>;
557 FullPivHouseholderQRMatrixQReturnType(
const MatrixType& qr,
const HCoeffsType& hCoeffs,
558 const IntDiagSizeVectorType& rowsTranspositions)
559 : m_qr(qr), m_hCoeffs(hCoeffs), m_rowsTranspositions(rowsTranspositions) {}
561 template <
typename ResultType>
562 void evalTo(ResultType& result)
const {
563 const Index rows = m_qr.rows();
564 WorkVectorType workspace(rows);
565 evalTo(result, workspace);
568 template <
typename ResultType>
569 void evalTo(ResultType& result, WorkVectorType& workspace)
const {
574 const Index rows = m_qr.rows();
575 const Index cols = m_qr.cols();
576 const Index size = (std::min)(rows, cols);
578 result.setIdentity(rows, rows);
579 for (Index k = size - 1; k >= 0; k--) {
580 result.block(k, k, rows - k, rows - k)
581 .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows - k - 1), conj(m_hCoeffs.coeff(k)), &workspace.
coeffRef(k));
582 result.row(k).swap(result.row(m_rowsTranspositions.coeff(k)));
586 Index rows()
const {
return m_qr.rows(); }
587 Index cols()
const {
return m_qr.rows(); }
590 typename MatrixType::Nested m_qr;
591 typename HCoeffsType::Nested m_hCoeffs;
592 typename IntDiagSizeVectorType::Nested m_rowsTranspositions;
597template <
typename MatrixType,
typename PermutationIndex>
598inline typename FullPivHouseholderQR<MatrixType, PermutationIndex>::MatrixQReturnType
600 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
601 return MatrixQReturnType(m_qr, m_hCoeffs, m_rows_transpositions);
608template <
typename Derived>
609template <
typename PermutationIndex>
611MatrixBase<Derived>::fullPivHouseholderQr()
const {
EvalReturnType eval() const
Definition DenseBase.h:385
Householder rank-revealing QR decomposition of a matrix with full pivoting.
Definition FullPivHouseholderQR.h:66
const MatrixType & matrixQR() const
Definition FullPivHouseholderQR.h:211
ComputationInfo info() const
Reports whether the QR factorization was successful.
Definition FullPivHouseholderQR.h:105
MatrixQReturnType matrixQ(void) const
Definition FullPivHouseholderQR.h:599
Inverse< FullPivHouseholderQR > inverse() const
Definition FullPivHouseholderQR.h:300
Solve< FullPivHouseholderQR, Rhs > solve(const MatrixBase< Rhs > &b) const
MatrixType::RealScalar logAbsDeterminant() const
Definition FullPivHouseholderQR.h:356
const PermutationType & colsPermutation() const
Definition FullPivHouseholderQR.h:220
const IntDiagSizeVectorType & rowsTranspositions() const
Definition FullPivHouseholderQR.h:226
MatrixType::Scalar determinant() const
Definition FullPivHouseholderQR.h:339
FullPivHouseholderQR()
Default Constructor.
Definition FullPivHouseholderQR.h:115
const HCoeffsType & hCoeffs() const
Definition FullPivHouseholderQR.h:312
MatrixType::RealScalar absDeterminant() const
Definition FullPivHouseholderQR.h:348
FullPivHouseholderQR(Index rows, Index cols)
Default Constructor with memory preallocation.
Definition FullPivHouseholderQR.h:130
bool isInjective() const
Definition RankRevealingBase.h:122
FullPivHouseholderQR(const EigenBase< InputType > &matrix)
Constructs a QR factorization from a given matrix.
Definition FullPivHouseholderQR.h:152
RealScalar pivotCoeff(Index i) const
Definition FullPivHouseholderQR.h:290
FullPivHouseholderQR(EigenBase< InputType > &matrix)
Constructs a QR factorization from a given matrix.
Definition FullPivHouseholderQR.h:171
MatrixType::Scalar signDeterminant() const
Definition FullPivHouseholderQR.h:363
Expression of the inverse of another expression.
Definition Inverse.h:44
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
constexpr Scalar & coeffRef(Index rowId, Index colId)
Definition PlainObjectBase.h:205
Permutation matrix.
Definition PermutationMatrix.h:346
constexpr void resize(Index rows, Index cols)
Definition PlainObjectBase.h:282
Index dimensionOfKernel() const
Definition RankRevealingBase.h:110
bool isInjective() const
Definition RankRevealingBase.h:122
bool isSurjective() const
Definition RankRevealingBase.h:134
FullPivHouseholderQR & setThreshold(const RealScalar &threshold)
Definition RankRevealingBase.h:57
Index nonzeroPivots() const
Definition RankRevealingBase.h:157
RealScalar threshold() const
Definition RankRevealingBase.h:80
RealScalar maxPivot() const
Definition RankRevealingBase.h:165
Index rank() const
Definition RankRevealingBase.h:95
bool isInvertible() const
Definition RankRevealingBase.h:145
Pseudo expression representing a solving operation.
Definition Solve.h:63
constexpr Derived & derived()
Definition EigenBase.h:50
ComputationInfo
Definition Constants.h:455
@ Success
Definition Constants.h:457
@ RowMajor
Definition Constants.h:321
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Eigen::Index Index
The interface type of indices.
Definition EigenBase.h:44
Expression type for return value of FullPivHouseholderQR::matrixQ()
Definition FullPivHouseholderQR.h:550