11#ifndef EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H
12#define EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H
15#include "./InternalHeaderCheck.h"
21template <
typename MatrixType_,
typename PermutationIndex_,
template <
typename,
typename>
class RankRevealingQR_>
22class CompleteOrthogonalDecompositionImpl;
24template <
typename MatrixType_,
typename PermutationIndex_,
template <
typename,
typename>
class RankRevealingQR_>
25struct traits<CompleteOrthogonalDecompositionImpl<MatrixType_, PermutationIndex_, RankRevealingQR_>>
26 : traits<MatrixType_> {
27 using XprKind = MatrixXpr;
28 using StorageKind = SolverStorage;
29 using PermutationIndex = PermutationIndex_;
33template <
typename MatrixType_,
typename PermutationIndex_>
34struct traits<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>> : traits<MatrixType_> {
35 using XprKind = MatrixXpr;
36 using StorageKind = SolverStorage;
37 using PermutationIndex = PermutationIndex_;
41template <
typename MatrixType_,
typename PermutationIndex_>
42struct traits<RandCompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>> : traits<MatrixType_> {
43 using XprKind = MatrixXpr;
44 using StorageKind = SolverStorage;
45 using PermutationIndex = PermutationIndex_;
66template <
typename MatrixType_,
typename PermutationIndex_,
template <
typename,
typename>
class RankRevealingQR_>
67class CompleteOrthogonalDecompositionImpl
68 :
public SolverBase<CompleteOrthogonalDecompositionImpl<MatrixType_, PermutationIndex_, RankRevealingQR_>> {
70 using MatrixType = MatrixType_;
73 template <
typename Derived>
74 friend struct internal::solve_assertion;
75 using PermutationIndex = PermutationIndex_;
76 EIGEN_GENERIC_PUBLIC_INTERFACE(CompleteOrthogonalDecompositionImpl)
78 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
79 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
81 using HCoeffsType =
typename internal::plain_diag_type<MatrixType>::type;
82 using PermutationType = PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime, PermutationIndex>;
83 using IntRowVectorType =
typename internal::plain_row_type<MatrixType, Index>::type;
84 using RowVectorType =
typename internal::plain_row_type<MatrixType>::type;
85 using RealRowVectorType =
typename internal::plain_row_type<MatrixType, RealScalar>::type;
86 using HouseholderSequenceType =
87 HouseholderSequence<MatrixType, internal::remove_all_t<typename HCoeffsType::ConjugateReturnType>>;
88 using PlainObject =
typename MatrixType::PlainObject;
89 using RankRevealingQRType = RankRevealingQR_<MatrixType, PermutationIndex>;
92 CompleteOrthogonalDecompositionImpl() : m_cpqr(), m_zCoeffs(), m_temp() {}
94 CompleteOrthogonalDecompositionImpl(
Index rows,
Index cols)
95 : m_cpqr(rows, cols), m_zCoeffs((std::min)(rows, cols)), m_temp(cols) {}
97 template <
typename InputType>
98 explicit CompleteOrthogonalDecompositionImpl(
const EigenBase<InputType>& matrix)
99 : m_cpqr(matrix.rows(), matrix.cols()),
100 m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
101 m_temp(matrix.cols()) {
102 compute(matrix.derived());
105 template <
typename InputType>
106 explicit CompleteOrthogonalDecompositionImpl(EigenBase<InputType>& matrix)
107 : m_cpqr(matrix.
derived()), m_zCoeffs((std::min)(matrix.rows(), matrix.cols())), m_temp(matrix.cols()) {
111 HouseholderSequenceType householderQ()
const;
112 HouseholderSequenceType matrixQ()
const {
return m_cpqr.householderQ(); }
114 using MatrixZType = Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime, plain_object_options<MatrixType>::value,
115 MaxColsAtCompileTime, MaxColsAtCompileTime>;
117 MatrixZType matrixZ()
const {
118 MatrixZType Z = MatrixZType::Identity(m_cpqr.cols(), m_cpqr.cols());
119 if (rank() < cols()) applyZOnTheLeftInPlace<false>(Z);
123 const MatrixType& matrixQTZ()
const {
return m_cpqr.matrixQR(); }
124 const MatrixType& matrixT()
const {
return m_cpqr.matrixQR(); }
126 template <
typename InputType>
127 CompleteOrthogonalDecompositionImpl& compute(
const EigenBase<InputType>& matrix) {
128 m_cpqr.compute(matrix);
133 const PermutationType& colsPermutation()
const {
return m_cpqr.colsPermutation(); }
135 typename MatrixType::Scalar determinant()
const;
136 typename MatrixType::RealScalar absDeterminant()
const;
137 typename MatrixType::RealScalar logAbsDeterminant()
const;
138 typename MatrixType::Scalar signDeterminant()
const;
140 inline Index rank()
const {
return m_cpqr.rank(); }
141 inline Index dimensionOfKernel()
const {
return m_cpqr.dimensionOfKernel(); }
142 inline bool isInjective()
const {
return m_cpqr.isInjective(); }
143 inline bool isSurjective()
const {
return m_cpqr.isSurjective(); }
144 inline bool isInvertible()
const {
return m_cpqr.isInvertible(); }
146 inline Index rows()
const {
return m_cpqr.rows(); }
147 inline Index cols()
const {
return m_cpqr.cols(); }
149 inline const HCoeffsType& hCoeffs()
const {
return m_cpqr.hCoeffs(); }
150 const HCoeffsType& zCoeffs()
const {
return m_zCoeffs; }
152 CompleteOrthogonalDecompositionImpl& setThreshold(
const RealScalar& threshold) {
153 m_cpqr.setThreshold(threshold);
157 CompleteOrthogonalDecompositionImpl& setThreshold(Default_t) {
158 m_cpqr.setThreshold(Default);
162 RealScalar threshold()
const {
return m_cpqr.threshold(); }
164 inline Index nonzeroPivots()
const {
return m_cpqr.nonzeroPivots(); }
165 inline RealScalar maxPivot()
const {
return m_cpqr.maxPivot(); }
168 eigen_assert(m_cpqr.m_isInitialized &&
"Decomposition is not initialized.");
173 void check_initialized()
const {
174 eigen_assert(m_cpqr.m_isInitialized &&
"CompleteOrthogonalDecomposition is not initialized.");
177#ifndef EIGEN_PARSED_BY_DOXYGEN
178 template <
typename RhsType,
typename DstType>
179 void _solve_impl(
const RhsType& rhs, DstType& dst)
const;
181 template <
bool Conjugate,
typename RhsType,
typename DstType>
182 void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const;
186 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
188 template <
bool Transpose_,
typename Rhs>
189 void _check_solve_assertion(
const Rhs& b)
const {
190 EIGEN_ONLY_USED_FOR_DEBUG(b);
191 eigen_assert(m_cpqr.m_isInitialized &&
"CompleteOrthogonalDecomposition is not initialized.");
192 eigen_assert((Transpose_ ? this->cols() : this->rows()) == b.rows() &&
193 "CompleteOrthogonalDecomposition::solve(): invalid number of rows of the right hand side matrix b");
196 void computeInPlace();
198 template <
bool Conjugate,
typename Rhs>
199 void applyZOnTheLeftInPlace(Rhs& rhs)
const;
201 template <
typename Rhs>
202 void applyZAdjointOnTheLeftInPlace(Rhs& rhs)
const;
204 RankRevealingQRType m_cpqr;
205 HCoeffsType m_zCoeffs;
206 RowVectorType m_temp;
209template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
210typename MatrixType::Scalar
211CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::determinant()
const {
212 return m_cpqr.determinant();
215template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
216typename MatrixType::RealScalar
217CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::absDeterminant()
const {
218 return m_cpqr.absDeterminant();
221template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
222typename MatrixType::RealScalar
223CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::logAbsDeterminant()
const {
224 return m_cpqr.logAbsDeterminant();
227template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
228typename MatrixType::Scalar
229CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::signDeterminant()
const {
230 return m_cpqr.signDeterminant();
233template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
234void CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::computeInPlace() {
235 eigen_assert(m_cpqr.cols() <= NumTraits<PermutationIndex>::highest());
237 const Index rank = m_cpqr.rank();
238 const Index cols = m_cpqr.cols();
239 const Index rows = m_cpqr.rows();
240 m_zCoeffs.resize((std::min)(rows, cols));
255 for (Index k = rank - 1; k >= 0; --k) {
260 m_cpqr.m_qr.col(k).head(k + 1).swap(m_cpqr.m_qr.col(rank - 1).head(k + 1));
266 m_cpqr.m_qr.row(k).tail(cols - rank + 1).makeHouseholderInPlace(m_zCoeffs(k), beta);
267 m_cpqr.m_qr(k, rank - 1) = beta;
270 m_cpqr.m_qr.topRightCorner(k, cols - rank + 1)
271 .applyHouseholderOnTheRight(m_cpqr.m_qr.row(k).tail(cols - rank).adjoint(), m_zCoeffs(k), &m_temp(0));
275 m_cpqr.m_qr.col(k).head(k + 1).swap(m_cpqr.m_qr.col(rank - 1).head(k + 1));
281template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
282template <
bool Conjugate,
typename Rhs>
283void CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::applyZOnTheLeftInPlace(
285 const Index cols = this->cols();
286 const Index nrhs = rhs.cols();
287 const Index rank = this->rank();
288 Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
289 for (Index k = rank - 1; k >= 0; --k) {
291 rhs.row(k).swap(rhs.row(rank - 1));
293 rhs.middleRows(rank - 1, cols - rank + 1)
294 .applyHouseholderOnTheLeft(matrixQTZ().row(k).tail(cols - rank).transpose().
template conjugateIf<!Conjugate>(),
295 zCoeffs().
template conjugateIf<Conjugate>()(k), &temp(0));
297 rhs.row(k).swap(rhs.row(rank - 1));
302template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
303template <
typename Rhs>
304void CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::applyZAdjointOnTheLeftInPlace(
306 const Index cols = this->cols();
307 const Index nrhs = rhs.cols();
308 const Index rank = this->rank();
309 Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
310 for (Index k = 0; k < rank; ++k) {
312 rhs.row(k).swap(rhs.row(rank - 1));
314 rhs.middleRows(rank - 1, cols - rank + 1)
315 .applyHouseholderOnTheLeft(matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k), &temp(0));
317 rhs.row(k).swap(rhs.row(rank - 1));
322#ifndef EIGEN_PARSED_BY_DOXYGEN
323template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
324template <
typename RhsType,
typename DstType>
325void CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::_solve_impl(
326 const RhsType& rhs, DstType& dst)
const {
327 const Index rank = this->rank();
334 typename RhsType::PlainObject c(rhs);
335 c.applyOnTheLeft(matrixQ().setLength(rank).adjoint());
338 dst.topRows(rank) = matrixT().topLeftCorner(rank, rank).template triangularView<Upper>().solve(c.topRows(rank));
340 const Index cols = this->cols();
344 dst.bottomRows(cols - rank).setZero();
345 applyZAdjointOnTheLeftInPlace(dst);
349 dst = colsPermutation() * dst;
352template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
353template <
bool Conjugate,
typename RhsType,
typename DstType>
354void CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::_solve_impl_transposed(
355 const RhsType& rhs, DstType& dst)
const {
356 const Index rank = this->rank();
363 typename RhsType::PlainObject c(colsPermutation().transpose() * rhs);
366 applyZOnTheLeftInPlace<!Conjugate>(c);
370 .topLeftCorner(rank, rank)
371 .template triangularView<Upper>()
373 .template conjugateIf<Conjugate>()
374 .solveInPlace(c.topRows(rank));
376 dst.topRows(rank) = c.topRows(rank);
377 dst.bottomRows(rows() - rank).setZero();
379 dst.applyOnTheLeft(householderQ().setLength(rank).
template conjugateIf<!Conjugate>());
383template <
typename MatrixType,
typename PermutationIndex,
template <
typename,
typename>
class RankRevealingQR_>
384typename CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::HouseholderSequenceType
385CompleteOrthogonalDecompositionImpl<MatrixType, PermutationIndex, RankRevealingQR_>::householderQ()
const {
386 return m_cpqr.householderQ();
418template <
typename MatrixType_,
typename PermutationIndex_>
419class CompleteOrthogonalDecomposition
420 :
public internal::CompleteOrthogonalDecompositionImpl<MatrixType_, PermutationIndex_, ColPivHouseholderQR> {
423 internal::CompleteOrthogonalDecompositionImpl<MatrixType_, PermutationIndex_, Eigen::ColPivHouseholderQR>;
424 using typename Base::RealScalar;
426 CompleteOrthogonalDecomposition() : Base() {}
427 CompleteOrthogonalDecomposition(Index rows, Index cols) : Base(rows, cols) {}
429 template <
typename InputType>
432 template <
typename InputType>
436 template <
typename InputType>
438 Base::compute(matrix);
443 Base::setThreshold(threshold);
447 CompleteOrthogonalDecomposition& setThreshold(Default_t) {
448 Base::setThreshold(Default);
458 this->check_initialized();
486template <
typename MatrixType_,
typename PermutationIndex_>
487class RandCompleteOrthogonalDecomposition
488 :
public internal::CompleteOrthogonalDecompositionImpl<MatrixType_, PermutationIndex_, RandColPivHouseholderQR> {
491 internal::CompleteOrthogonalDecompositionImpl<MatrixType_, PermutationIndex_, Eigen::RandColPivHouseholderQR>;
492 using typename Base::RealScalar;
494 RandCompleteOrthogonalDecomposition() : Base() {}
495 RandCompleteOrthogonalDecomposition(Index rows, Index cols) : Base(rows, cols) {}
497 template <
typename InputType>
500 template <
typename InputType>
503 template <
typename InputType>
505 Base::compute(matrix);
509 RandCompleteOrthogonalDecomposition& setThreshold(
const RealScalar& threshold) {
510 Base::setThreshold(threshold);
514 RandCompleteOrthogonalDecomposition& setThreshold(Default_t) {
515 Base::setThreshold(Default);
530 RandCompleteOrthogonalDecomposition&
setSeed(uint64_t seed) {
536 this->check_initialized();
543template <
typename MatrixType,
typename PermutationIndex>
544struct traits<Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>>
545 : traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject> {
549template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
550struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>,
551 internal::assign_op<typename DstXprType::Scalar,
552 typename CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::Scalar>,
554 using CodType = CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>;
555 using SrcXprType = Inverse<CodType>;
556 static void run(DstXprType& dst,
const SrcXprType& src,
557 const internal::assign_op<typename DstXprType::Scalar, typename CodType::Scalar>&) {
558 using IdentityMatrixType = Matrix<
typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime,
559 0, CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime>;
560 dst = src.nestedExpression().solve(IdentityMatrixType::Identity(src.cols(), src.cols()));
564template <
typename MatrixType,
typename PermutationIndex>
565struct traits<Inverse<RandCompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>>
566 : traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject> {
570template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
571struct Assignment<DstXprType, Inverse<RandCompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>,
572 internal::assign_op<typename DstXprType::Scalar, typename RandCompleteOrthogonalDecomposition<
573 MatrixType, PermutationIndex>::Scalar>,
575 using CodType = RandCompleteOrthogonalDecomposition<MatrixType, PermutationIndex>;
576 using SrcXprType = Inverse<CodType>;
577 static void run(DstXprType& dst,
const SrcXprType& src,
578 const internal::assign_op<typename DstXprType::Scalar, typename CodType::Scalar>&) {
579 using IdentityMatrixType = Matrix<
typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime,
580 0, CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime>;
581 dst = src.nestedExpression().solve(IdentityMatrixType::Identity(src.cols(), src.cols()));
591template <
typename Derived>
592template <
typename PermutationIndex>
594MatrixBase<Derived>::completeOrthogonalDecomposition()
const {
602template <
typename Derived>
603template <
typename PermutationIndex>
605MatrixBase<Derived>::randCompleteOrthogonalDecomposition()
const {
Complete orthogonal decomposition (COD) of a matrix.
Definition CompleteOrthogonalDecomposition.h:420
CompleteOrthogonalDecomposition & compute(const EigenBase< InputType > &matrix)
Computes the COD of matrix.
Definition CompleteOrthogonalDecomposition.h:437
Inverse< CompleteOrthogonalDecomposition > pseudoInverse() const
Definition CompleteOrthogonalDecomposition.h:457
EvalReturnType eval() const
Definition DenseBase.h:385
Expression of the inverse of another expression.
Definition Inverse.h:44
Complete orthogonal decomposition (COD) of a matrix, backed by RandColPivHouseholderQR.
Definition CompleteOrthogonalDecomposition.h:488
RandCompleteOrthogonalDecomposition & setBlockSize(Index b)
Sets the panel block size of the underlying randomized QR.
Definition CompleteOrthogonalDecomposition.h:522
RandCompleteOrthogonalDecomposition & setSeed(uint64_t seed)
Fixes the RNG seed of the underlying randomized QR.
Definition CompleteOrthogonalDecomposition.h:530
constexpr CompleteOrthogonalDecompositionImpl< MatrixType_, PermutationIndex_, RankRevealingQR_ > & derived()
ComputationInfo
Definition Constants.h:455
@ Success
Definition Constants.h:457
Definition EigenBase.h:34
constexpr Derived & derived()
Definition EigenBase.h:50
Eigen::Index Index
Definition EigenBase.h:44