Warning, file /include/eigen3/Eigen/src/QR/CompleteOrthogonalDecomposition.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H
0011 #define EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H
0012
0013 namespace Eigen {
0014
0015 namespace internal {
0016 template <typename _MatrixType>
0017 struct traits<CompleteOrthogonalDecomposition<_MatrixType> >
0018 : traits<_MatrixType> {
0019 typedef MatrixXpr XprKind;
0020 typedef SolverStorage StorageKind;
0021 typedef int StorageIndex;
0022 enum { Flags = 0 };
0023 };
0024
0025 }
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 template <typename _MatrixType> class CompleteOrthogonalDecomposition
0051 : public SolverBase<CompleteOrthogonalDecomposition<_MatrixType> >
0052 {
0053 public:
0054 typedef _MatrixType MatrixType;
0055 typedef SolverBase<CompleteOrthogonalDecomposition> Base;
0056
0057 template<typename Derived>
0058 friend struct internal::solve_assertion;
0059
0060 EIGEN_GENERIC_PUBLIC_INTERFACE(CompleteOrthogonalDecomposition)
0061 enum {
0062 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
0063 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0064 };
0065 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
0066 typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime>
0067 PermutationType;
0068 typedef typename internal::plain_row_type<MatrixType, Index>::type
0069 IntRowVectorType;
0070 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
0071 typedef typename internal::plain_row_type<MatrixType, RealScalar>::type
0072 RealRowVectorType;
0073 typedef HouseholderSequence<
0074 MatrixType, typename internal::remove_all<
0075 typename HCoeffsType::ConjugateReturnType>::type>
0076 HouseholderSequenceType;
0077 typedef typename MatrixType::PlainObject PlainObject;
0078
0079 private:
0080 typedef typename PermutationType::Index PermIndexType;
0081
0082 public:
0083
0084
0085
0086
0087
0088
0089
0090 CompleteOrthogonalDecomposition() : m_cpqr(), m_zCoeffs(), m_temp() {}
0091
0092
0093
0094
0095
0096
0097
0098 CompleteOrthogonalDecomposition(Index rows, Index cols)
0099 : m_cpqr(rows, cols), m_zCoeffs((std::min)(rows, cols)), m_temp(cols) {}
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 template <typename InputType>
0118 explicit CompleteOrthogonalDecomposition(const EigenBase<InputType>& matrix)
0119 : m_cpqr(matrix.rows(), matrix.cols()),
0120 m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
0121 m_temp(matrix.cols())
0122 {
0123 compute(matrix.derived());
0124 }
0125
0126
0127
0128
0129
0130
0131
0132 template<typename InputType>
0133 explicit CompleteOrthogonalDecomposition(EigenBase<InputType>& matrix)
0134 : m_cpqr(matrix.derived()),
0135 m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
0136 m_temp(matrix.cols())
0137 {
0138 computeInPlace();
0139 }
0140
0141 #ifdef EIGEN_PARSED_BY_DOXYGEN
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 template <typename Rhs>
0152 inline const Solve<CompleteOrthogonalDecomposition, Rhs> solve(
0153 const MatrixBase<Rhs>& b) const;
0154 #endif
0155
0156 HouseholderSequenceType householderQ(void) const;
0157 HouseholderSequenceType matrixQ(void) const { return m_cpqr.householderQ(); }
0158
0159
0160
0161 MatrixType matrixZ() const {
0162 MatrixType Z = MatrixType::Identity(m_cpqr.cols(), m_cpqr.cols());
0163 applyZOnTheLeftInPlace<false>(Z);
0164 return Z;
0165 }
0166
0167
0168
0169
0170 const MatrixType& matrixQTZ() const { return m_cpqr.matrixQR(); }
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 const MatrixType& matrixT() const { return m_cpqr.matrixQR(); }
0184
0185 template <typename InputType>
0186 CompleteOrthogonalDecomposition& compute(const EigenBase<InputType>& matrix) {
0187
0188 m_cpqr.compute(matrix);
0189 computeInPlace();
0190 return *this;
0191 }
0192
0193
0194 const PermutationType& colsPermutation() const {
0195 return m_cpqr.colsPermutation();
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 typename MatrixType::RealScalar absDeterminant() const;
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 typename MatrixType::RealScalar logAbsDeterminant() const;
0227
0228
0229
0230
0231
0232
0233
0234
0235 inline Index rank() const { return m_cpqr.rank(); }
0236
0237
0238
0239
0240
0241
0242
0243
0244 inline Index dimensionOfKernel() const { return m_cpqr.dimensionOfKernel(); }
0245
0246
0247
0248
0249
0250
0251
0252
0253 inline bool isInjective() const { return m_cpqr.isInjective(); }
0254
0255
0256
0257
0258
0259
0260
0261
0262 inline bool isSurjective() const { return m_cpqr.isSurjective(); }
0263
0264
0265
0266
0267
0268
0269
0270
0271 inline bool isInvertible() const { return m_cpqr.isInvertible(); }
0272
0273
0274
0275
0276
0277
0278 inline const Inverse<CompleteOrthogonalDecomposition> pseudoInverse() const
0279 {
0280 eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
0281 return Inverse<CompleteOrthogonalDecomposition>(*this);
0282 }
0283
0284 inline Index rows() const { return m_cpqr.rows(); }
0285 inline Index cols() const { return m_cpqr.cols(); }
0286
0287
0288
0289
0290
0291
0292 inline const HCoeffsType& hCoeffs() const { return m_cpqr.hCoeffs(); }
0293
0294
0295
0296
0297
0298
0299 const HCoeffsType& zCoeffs() const { return m_zCoeffs; }
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 CompleteOrthogonalDecomposition& setThreshold(const RealScalar& threshold) {
0321 m_cpqr.setThreshold(threshold);
0322 return *this;
0323 }
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 CompleteOrthogonalDecomposition& setThreshold(Default_t) {
0334 m_cpqr.setThreshold(Default);
0335 return *this;
0336 }
0337
0338
0339
0340
0341
0342 RealScalar threshold() const { return m_cpqr.threshold(); }
0343
0344
0345
0346
0347
0348
0349
0350
0351 inline Index nonzeroPivots() const { return m_cpqr.nonzeroPivots(); }
0352
0353
0354
0355
0356 inline RealScalar maxPivot() const { return m_cpqr.maxPivot(); }
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 ComputationInfo info() const {
0367 eigen_assert(m_cpqr.m_isInitialized && "Decomposition is not initialized.");
0368 return Success;
0369 }
0370
0371 #ifndef EIGEN_PARSED_BY_DOXYGEN
0372 template <typename RhsType, typename DstType>
0373 void _solve_impl(const RhsType& rhs, DstType& dst) const;
0374
0375 template<bool Conjugate, typename RhsType, typename DstType>
0376 void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
0377 #endif
0378
0379 protected:
0380 static void check_template_parameters() {
0381 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
0382 }
0383
0384 template<bool Transpose_, typename Rhs>
0385 void _check_solve_assertion(const Rhs& b) const {
0386 EIGEN_ONLY_USED_FOR_DEBUG(b);
0387 eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
0388 eigen_assert((Transpose_?derived().cols():derived().rows())==b.rows() && "CompleteOrthogonalDecomposition::solve(): invalid number of rows of the right hand side matrix b");
0389 }
0390
0391 void computeInPlace();
0392
0393
0394
0395
0396
0397 template <bool Conjugate, typename Rhs>
0398 void applyZOnTheLeftInPlace(Rhs& rhs) const;
0399
0400
0401
0402 template <typename Rhs>
0403 void applyZAdjointOnTheLeftInPlace(Rhs& rhs) const;
0404
0405 ColPivHouseholderQR<MatrixType> m_cpqr;
0406 HCoeffsType m_zCoeffs;
0407 RowVectorType m_temp;
0408 };
0409
0410 template <typename MatrixType>
0411 typename MatrixType::RealScalar
0412 CompleteOrthogonalDecomposition<MatrixType>::absDeterminant() const {
0413 return m_cpqr.absDeterminant();
0414 }
0415
0416 template <typename MatrixType>
0417 typename MatrixType::RealScalar
0418 CompleteOrthogonalDecomposition<MatrixType>::logAbsDeterminant() const {
0419 return m_cpqr.logAbsDeterminant();
0420 }
0421
0422
0423
0424
0425
0426
0427
0428
0429 template <typename MatrixType>
0430 void CompleteOrthogonalDecomposition<MatrixType>::computeInPlace()
0431 {
0432 check_template_parameters();
0433
0434
0435 eigen_assert(m_cpqr.cols() <= NumTraits<int>::highest());
0436
0437 const Index rank = m_cpqr.rank();
0438 const Index cols = m_cpqr.cols();
0439 const Index rows = m_cpqr.rows();
0440 m_zCoeffs.resize((std::min)(rows, cols));
0441 m_temp.resize(cols);
0442
0443 if (rank < cols) {
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 for (Index k = rank - 1; k >= 0; --k) {
0456 if (k != rank - 1) {
0457
0458
0459
0460 m_cpqr.m_qr.col(k).head(k + 1).swap(
0461 m_cpqr.m_qr.col(rank - 1).head(k + 1));
0462 }
0463
0464
0465
0466 RealScalar beta;
0467 m_cpqr.m_qr.row(k)
0468 .tail(cols - rank + 1)
0469 .makeHouseholderInPlace(m_zCoeffs(k), beta);
0470 m_cpqr.m_qr(k, rank - 1) = beta;
0471 if (k > 0) {
0472
0473 m_cpqr.m_qr.topRightCorner(k, cols - rank + 1)
0474 .applyHouseholderOnTheRight(
0475 m_cpqr.m_qr.row(k).tail(cols - rank).adjoint(), m_zCoeffs(k),
0476 &m_temp(0));
0477 }
0478 if (k != rank - 1) {
0479
0480 m_cpqr.m_qr.col(k).head(k + 1).swap(
0481 m_cpqr.m_qr.col(rank - 1).head(k + 1));
0482 }
0483 }
0484 }
0485 }
0486
0487 template <typename MatrixType>
0488 template <bool Conjugate, typename Rhs>
0489 void CompleteOrthogonalDecomposition<MatrixType>::applyZOnTheLeftInPlace(
0490 Rhs& rhs) const {
0491 const Index cols = this->cols();
0492 const Index nrhs = rhs.cols();
0493 const Index rank = this->rank();
0494 Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
0495 for (Index k = rank-1; k >= 0; --k) {
0496 if (k != rank - 1) {
0497 rhs.row(k).swap(rhs.row(rank - 1));
0498 }
0499 rhs.middleRows(rank - 1, cols - rank + 1)
0500 .applyHouseholderOnTheLeft(
0501 matrixQTZ().row(k).tail(cols - rank).transpose().template conjugateIf<!Conjugate>(), zCoeffs().template conjugateIf<Conjugate>()(k),
0502 &temp(0));
0503 if (k != rank - 1) {
0504 rhs.row(k).swap(rhs.row(rank - 1));
0505 }
0506 }
0507 }
0508
0509 template <typename MatrixType>
0510 template <typename Rhs>
0511 void CompleteOrthogonalDecomposition<MatrixType>::applyZAdjointOnTheLeftInPlace(
0512 Rhs& rhs) const {
0513 const Index cols = this->cols();
0514 const Index nrhs = rhs.cols();
0515 const Index rank = this->rank();
0516 Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
0517 for (Index k = 0; k < rank; ++k) {
0518 if (k != rank - 1) {
0519 rhs.row(k).swap(rhs.row(rank - 1));
0520 }
0521 rhs.middleRows(rank - 1, cols - rank + 1)
0522 .applyHouseholderOnTheLeft(
0523 matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k),
0524 &temp(0));
0525 if (k != rank - 1) {
0526 rhs.row(k).swap(rhs.row(rank - 1));
0527 }
0528 }
0529 }
0530
0531 #ifndef EIGEN_PARSED_BY_DOXYGEN
0532 template <typename _MatrixType>
0533 template <typename RhsType, typename DstType>
0534 void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl(
0535 const RhsType& rhs, DstType& dst) const {
0536 const Index rank = this->rank();
0537 if (rank == 0) {
0538 dst.setZero();
0539 return;
0540 }
0541
0542
0543 typename RhsType::PlainObject c(rhs);
0544 c.applyOnTheLeft(matrixQ().setLength(rank).adjoint());
0545
0546
0547 dst.topRows(rank) = matrixT()
0548 .topLeftCorner(rank, rank)
0549 .template triangularView<Upper>()
0550 .solve(c.topRows(rank));
0551
0552 const Index cols = this->cols();
0553 if (rank < cols) {
0554
0555
0556 dst.bottomRows(cols - rank).setZero();
0557 applyZAdjointOnTheLeftInPlace(dst);
0558 }
0559
0560
0561 dst = colsPermutation() * dst;
0562 }
0563
0564 template<typename _MatrixType>
0565 template<bool Conjugate, typename RhsType, typename DstType>
0566 void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
0567 {
0568 const Index rank = this->rank();
0569
0570 if (rank == 0) {
0571 dst.setZero();
0572 return;
0573 }
0574
0575 typename RhsType::PlainObject c(colsPermutation().transpose()*rhs);
0576
0577 if (rank < cols()) {
0578 applyZOnTheLeftInPlace<!Conjugate>(c);
0579 }
0580
0581 matrixT().topLeftCorner(rank, rank)
0582 .template triangularView<Upper>()
0583 .transpose().template conjugateIf<Conjugate>()
0584 .solveInPlace(c.topRows(rank));
0585
0586 dst.topRows(rank) = c.topRows(rank);
0587 dst.bottomRows(rows()-rank).setZero();
0588
0589 dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
0590 }
0591 #endif
0592
0593 namespace internal {
0594
0595 template<typename MatrixType>
0596 struct traits<Inverse<CompleteOrthogonalDecomposition<MatrixType> > >
0597 : traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject>
0598 {
0599 enum { Flags = 0 };
0600 };
0601
0602 template<typename DstXprType, typename MatrixType>
0603 struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType> >, internal::assign_op<typename DstXprType::Scalar,typename CompleteOrthogonalDecomposition<MatrixType>::Scalar>, Dense2Dense>
0604 {
0605 typedef CompleteOrthogonalDecomposition<MatrixType> CodType;
0606 typedef Inverse<CodType> SrcXprType;
0607 static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename CodType::Scalar> &)
0608 {
0609 typedef Matrix<typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime, 0, CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime> IdentityMatrixType;
0610 dst = src.nestedExpression().solve(IdentityMatrixType::Identity(src.cols(), src.cols()));
0611 }
0612 };
0613
0614 }
0615
0616
0617 template <typename MatrixType>
0618 typename CompleteOrthogonalDecomposition<MatrixType>::HouseholderSequenceType
0619 CompleteOrthogonalDecomposition<MatrixType>::householderQ() const {
0620 return m_cpqr.householderQ();
0621 }
0622
0623
0624
0625
0626
0627 template <typename Derived>
0628 const CompleteOrthogonalDecomposition<typename MatrixBase<Derived>::PlainObject>
0629 MatrixBase<Derived>::completeOrthogonalDecomposition() const {
0630 return CompleteOrthogonalDecomposition<PlainObject>(eval());
0631 }
0632
0633 }
0634
0635 #endif