Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
SparseQR.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2012-2013 Desire Nuentsa <[email protected]>
5// Copyright (C) 2012-2014 Gael Guennebaud <[email protected]>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11#ifndef EIGEN_SPARSE_QR_H
12#define EIGEN_SPARSE_QR_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19template <typename MatrixType, typename OrderingType>
20class SparseQR;
21template <typename SparseQRType>
22struct SparseQRMatrixQReturnType;
23template <typename SparseQRType>
24struct SparseQRMatrixQTransposeReturnType;
25template <typename SparseQRType, typename Derived>
26struct SparseQR_QProduct;
27namespace internal {
28template <typename SparseQRType>
29struct traits<SparseQRMatrixQReturnType<SparseQRType> > {
30 typedef typename SparseQRType::MatrixType ReturnType;
31 typedef typename ReturnType::StorageIndex StorageIndex;
32 typedef typename ReturnType::StorageKind StorageKind;
33 enum { RowsAtCompileTime = Dynamic, ColsAtCompileTime = Dynamic };
34};
35template <typename SparseQRType>
36struct traits<SparseQRMatrixQTransposeReturnType<SparseQRType> > {
37 typedef typename SparseQRType::MatrixType ReturnType;
38};
39template <typename SparseQRType, typename Derived>
40struct traits<SparseQR_QProduct<SparseQRType, Derived> > {
41 typedef typename Derived::PlainObject ReturnType;
42};
43} // End namespace internal
44
87template <typename MatrixType_, typename OrderingType_>
88class SparseQR : public SparseSolverBase<SparseQR<MatrixType_, OrderingType_> > {
89 protected:
91 using Base::m_isInitialized;
92
93 public:
94 using Base::_solve_impl;
95 typedef MatrixType_ MatrixType;
96 typedef OrderingType_ OrderingType;
97 typedef typename MatrixType::Scalar Scalar;
98 typedef typename MatrixType::RealScalar RealScalar;
99 typedef typename MatrixType::StorageIndex StorageIndex;
104
105 enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };
106
107 public:
108 SparseQR()
109 : m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true), m_isQSorted(false), m_isEtreeOk(false) {}
110
117 explicit SparseQR(const MatrixType& mat)
118 : m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true), m_isQSorted(false), m_isEtreeOk(false) {
119 compute(mat);
120 }
121
128 void compute(const MatrixType& mat) {
129 analyzePattern(mat);
130 factorize(mat);
131 }
132 void analyzePattern(const MatrixType& mat);
133 void factorize(const MatrixType& mat);
134
137 inline Index rows() const { return m_pmat.rows(); }
138
141 inline Index cols() const { return m_pmat.cols(); }
142
156 const QRMatrixType& matrixR() const { return m_R; }
157
162 Index rank() const {
163 eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
164 return m_nonzeropivots;
165 }
166
185 SparseQRMatrixQReturnType<SparseQR> matrixQ() const { return SparseQRMatrixQReturnType<SparseQR>(*this); }
186
191 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
192 return m_outputPerm_c;
193 }
194
198 std::string lastErrorMessage() const { return m_lastError; }
199
201 template <typename Rhs, typename Dest>
202 bool _solve_impl(const MatrixBase<Rhs>& B, MatrixBase<Dest>& dest) const {
203 eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
204 eigen_assert(this->rows() == B.rows() &&
205 "SparseQR::solve() : invalid number of rows in the right hand side matrix");
206
207 Index rank = this->rank();
208
209 // Compute Q^* * b;
210 typename Dest::PlainObject y, b;
211 y = this->matrixQ().adjoint() * B;
212 b = y;
213
214 // Solve with the triangular matrix R
215 y.resize((std::max<Index>)(cols(), y.rows()), y.cols());
216 y.topRows(rank) = this->matrixR().topLeftCorner(rank, rank).template triangularView<Upper>().solve(b.topRows(rank));
217 y.bottomRows(y.rows() - rank).setZero();
218
219 // Apply the column permutation
220 if (m_perm_c.size())
221 dest = colsPermutation() * y.topRows(cols());
222 else
223 dest = y.topRows(cols());
224
225 m_info = Success;
226 return true;
227 }
228
234 void setPivotThreshold(const RealScalar& threshold) {
235 m_useDefaultThreshold = false;
236 m_threshold = threshold;
237 }
238
243 template <typename Rhs>
244 inline const Solve<SparseQR, Rhs> solve(const MatrixBase<Rhs>& B) const {
245 eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
246 eigen_assert(this->rows() == B.rows() &&
247 "SparseQR::solve() : invalid number of rows in the right hand side matrix");
248 return Solve<SparseQR, Rhs>(*this, B.derived());
249 }
250 template <typename Rhs>
251 inline const Solve<SparseQR, Rhs> solve(const SparseMatrixBase<Rhs>& B) const {
252 eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
253 eigen_assert(this->rows() == B.rows() &&
254 "SparseQR::solve() : invalid number of rows in the right hand side matrix");
255 return Solve<SparseQR, Rhs>(*this, B.derived());
256 }
257
267 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
268 return m_info;
269 }
270
272 inline void _sort_matrix_Q() {
273 if (this->m_isQSorted) return;
274 // The matrix Q is sorted during the transposition
276 this->m_Q = mQrm;
277 this->m_isQSorted = true;
278 }
279
280 protected:
281 bool m_analysisIsok;
282 bool m_factorizationIsok;
283 mutable ComputationInfo m_info;
284 std::string m_lastError;
285 QRMatrixType m_pmat; // Temporary matrix
286 QRMatrixType m_R; // The triangular factor matrix
287 QRMatrixType m_Q; // The orthogonal reflectors
288 ScalarVector m_hcoeffs; // The Householder coefficients
289 PermutationType m_perm_c; // Fill-reducing Column permutation
290 PermutationType m_pivotperm; // The permutation for rank revealing
291 PermutationType m_outputPerm_c; // The final column permutation
292 RealScalar m_threshold; // Threshold to determine null Householder reflections
293 bool m_useDefaultThreshold; // Use default threshold
294 Index m_nonzeropivots; // Number of non zero pivots found
295 IndexVector m_etree; // Column elimination tree
296 IndexVector m_firstRowElt; // First element in each row
297 bool m_isQSorted; // whether Q is sorted or not
298 bool m_isEtreeOk; // whether the elimination tree match the initial input matrix
299
300 template <typename, typename>
301 friend struct SparseQR_QProduct;
302};
303
313template <typename MatrixType, typename OrderingType>
315 eigen_assert(
316 mat.isCompressed() &&
317 "SparseQR requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to SparseQR");
318 // Copy to a column major matrix if the input is rowmajor
319 std::conditional_t<MatrixType::IsRowMajor, QRMatrixType, const MatrixType&> matCpy(mat);
320 // Compute the column fill reducing ordering
321 OrderingType ord;
322 ord(matCpy, m_perm_c);
323 Index n = mat.cols();
324 Index m = mat.rows();
325 Index diagSize = (std::min)(m, n);
326
327 if (!m_perm_c.size()) {
328 m_perm_c.resize(n);
329 m_perm_c.indices().setLinSpaced(n, 0, StorageIndex(n - 1));
330 }
331
332 // Compute the column elimination tree of the permuted matrix
333 m_outputPerm_c = m_perm_c.inverse();
334 internal::coletree(matCpy, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
335 m_isEtreeOk = true;
336
337 m_R.resize(m, n);
338 m_Q.resize(m, diagSize);
339
340 // Allocate space for nonzero elements: rough estimation
341 m_R.reserve(2 * mat.nonZeros()); // FIXME Get a more accurate estimation through symbolic factorization with the
342 // etree
343 m_Q.reserve(2 * mat.nonZeros());
344 m_hcoeffs.resize(diagSize);
345 m_analysisIsok = true;
346}
347
355template <typename MatrixType, typename OrderingType>
357 using std::abs;
358
359 eigen_assert(m_analysisIsok && "analyzePattern() should be called before this step");
360 StorageIndex m = StorageIndex(mat.rows());
361 StorageIndex n = StorageIndex(mat.cols());
362 StorageIndex diagSize = (std::min)(m, n);
363 IndexVector mark((std::max)(m, n));
364 mark.setConstant(-1); // Record the visited nodes
365 IndexVector Ridx(n), Qidx(m); // Store temporarily the row indexes for the current column of R and Q
366 Index nzcolR, nzcolQ; // Number of nonzero for the current column of R and Q
367 ScalarVector tval(m); // The dense vector used to compute the current column
368 RealScalar pivotThreshold = m_threshold;
369
370 m_R.setZero();
371 m_Q.setZero();
372 m_pmat = mat;
373 if (!m_isEtreeOk) {
374 m_outputPerm_c = m_perm_c.inverse();
375 internal::coletree(m_pmat, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
376 m_isEtreeOk = true;
377 }
378
379 m_pmat.uncompress(); // To have the innerNonZeroPtr allocated
380
381 // Apply the fill-in reducing permutation lazily:
382 {
383 // If the input is row major, copy the original column indices,
384 // otherwise directly use the input matrix
385 //
386 IndexVector originalOuterIndicesCpy;
387 const StorageIndex* originalOuterIndices = mat.outerIndexPtr();
388 if (MatrixType::IsRowMajor) {
389 originalOuterIndicesCpy = IndexVector::Map(m_pmat.outerIndexPtr(), n + 1);
390 originalOuterIndices = originalOuterIndicesCpy.data();
391 }
392
393 for (int i = 0; i < n; i++) {
394 Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
395 m_pmat.outerIndexPtr()[p] = originalOuterIndices[i];
396 m_pmat.innerNonZeroPtr()[p] = originalOuterIndices[i + 1] - originalOuterIndices[i];
397 }
398 }
399
400 /* Compute the default threshold as in MatLab, see:
401 * Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
402 * Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
403 */
404 if (m_useDefaultThreshold) {
405 RealScalar max2Norm = 0.0;
406 for (int j = 0; j < n; j++) max2Norm = numext::maxi(max2Norm, m_pmat.col(j).norm());
407 if (max2Norm == RealScalar(0)) max2Norm = RealScalar(1);
408 pivotThreshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
409 }
410
411 // Initialize the numerical permutation
412 m_pivotperm.setIdentity(n);
413
414 StorageIndex nonzeroCol = 0; // Record the number of valid pivots
415 m_Q.startVec(0);
416
417 // Left looking rank-revealing QR factorization: compute a column of R and Q at a time
418 for (StorageIndex col = 0; col < n; ++col) {
419 mark.setConstant(-1);
420 m_R.startVec(col);
421 mark(nonzeroCol) = col;
422 Qidx(0) = nonzeroCol;
423 nzcolR = 0;
424 nzcolQ = 1;
425 bool found_diag = nonzeroCol >= m;
426 tval.setZero();
427
428 // Symbolic factorization: find the nonzero locations of the column k of the factors R and Q, i.e.,
429 // all the nodes (with indexes lower than rank) reachable through the column elimination tree (etree) rooted at node
430 // k. Note: if the diagonal entry does not exist, then its contribution must be explicitly added, thus the trick
431 // with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
432 for (typename QRMatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp) {
433 StorageIndex curIdx = nonzeroCol;
434 if (itp) curIdx = StorageIndex(itp.row());
435 if (curIdx == nonzeroCol) found_diag = true;
436
437 // Get the nonzeros indexes of the current column of R
438 StorageIndex st = m_firstRowElt(curIdx); // The traversal of the etree starts here
439 if (st < 0) {
440 m_lastError = "Empty row found during numerical factorization";
441 m_info = InvalidInput;
442 return;
443 }
444
445 // Traverse the etree
446 Index bi = nzcolR;
447 for (; mark(st) != col; st = m_etree(st)) {
448 Ridx(nzcolR) = st; // Add this row to the list,
449 mark(st) = col; // and mark this row as visited
450 nzcolR++;
451 }
452
453 // Reverse the list to get the topological ordering
454 Index nt = nzcolR - bi;
455 for (Index i = 0; i < nt / 2; i++) std::swap(Ridx(bi + i), Ridx(nzcolR - i - 1));
456
457 // Copy the current (curIdx,pcol) value of the input matrix
458 if (itp)
459 tval(curIdx) = itp.value();
460 else
461 tval(curIdx) = Scalar(0);
462
463 // Compute the pattern of Q(:,k)
464 if (curIdx > nonzeroCol && mark(curIdx) != col) {
465 Qidx(nzcolQ) = curIdx; // Add this row to the pattern of Q,
466 mark(curIdx) = col; // and mark it as visited
467 nzcolQ++;
468 }
469 }
470
471 // Browse all the indexes of R(:,col) in reverse order
472 for (Index i = nzcolR - 1; i >= 0; i--) {
473 Index curIdx = Ridx(i);
474
475 // Apply the curIdx-th householder vector to the current column (temporarily stored into tval)
476 Scalar tdot(0);
477
478 // First compute q' * tval
479 tdot = m_Q.col(curIdx).dot(tval);
480
481 tdot *= m_hcoeffs(curIdx);
482
483 // Then update tval = tval - q * tau
484 tval -= tdot * m_Q.col(curIdx);
485
486 // Detect fill-in for the current column of Q
487 if (m_etree(Ridx(i)) == nonzeroCol) {
488 for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq) {
489 StorageIndex iQ = StorageIndex(itq.row());
490 if (mark(iQ) != col) {
491 Qidx(nzcolQ++) = iQ; // Add this row to the pattern of Q,
492 mark(iQ) = col; // and mark it as visited
493 }
494 }
495 }
496 } // End update current column
497
498 Scalar tau = RealScalar(0);
499 RealScalar beta = 0;
500
501 if (nonzeroCol < diagSize) {
502 // Compute the Householder reflection that eliminate the current column
503 // FIXME this step should call the Householder module.
504 Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
505
506 // First, the squared norm of Q((col+1):m, col)
507 RealScalar sqrNorm = 0.;
508 for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
509 if (sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0)) {
510 beta = numext::real(c0);
511 tval(Qidx(0)) = 1;
512 } else {
513 using std::sqrt;
514 beta = sqrt(numext::abs2(c0) + sqrNorm);
515 if (numext::real(c0) >= RealScalar(0)) beta = -beta;
516 tval(Qidx(0)) = 1;
517 for (Index itq = 1; itq < nzcolQ; ++itq) tval(Qidx(itq)) /= (c0 - beta);
518 tau = numext::conj((beta - c0) / beta);
519 }
520 }
521
522 // Insert values in R
523 for (Index i = nzcolR - 1; i >= 0; i--) {
524 Index curIdx = Ridx(i);
525 if (curIdx < nonzeroCol) {
526 m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
527 tval(curIdx) = Scalar(0.);
528 }
529 }
530
531 if (nonzeroCol < diagSize && abs(beta) >= pivotThreshold) {
532 m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
533 // The householder coefficient
534 m_hcoeffs(nonzeroCol) = tau;
535 // Record the householder reflections
536 for (Index itq = 0; itq < nzcolQ; ++itq) {
537 Index iQ = Qidx(itq);
538 m_Q.insertBackByOuterInnerUnordered(nonzeroCol, iQ) = tval(iQ);
539 tval(iQ) = Scalar(0.);
540 }
541 nonzeroCol++;
542 if (nonzeroCol < diagSize) m_Q.startVec(nonzeroCol);
543 } else {
544 // Zero pivot found: move implicitly this column to the end
545 for (Index j = nonzeroCol; j < n - 1; j++) std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j + 1]);
546
547 // Recompute the column elimination tree
548 internal::coletree(m_pmat, m_etree, m_firstRowElt, m_pivotperm.indices().data());
549 m_isEtreeOk = false;
550 }
551 }
552
553 m_hcoeffs.tail(diagSize - nonzeroCol).setZero();
554
555 // Finalize the column pointers of the sparse matrices R and Q
556 m_Q.finalize();
557 m_Q.makeCompressed();
558 m_R.finalize();
559 m_R.makeCompressed();
560 m_isQSorted = false;
561
562 m_nonzeropivots = nonzeroCol;
563
564 if (nonzeroCol < n) {
565 // Permute the triangular factor to put the 'dead' columns to the end
566 QRMatrixType tempR(m_R);
567 m_R = tempR * m_pivotperm;
568
569 // Update the column permutation
570 m_outputPerm_c = m_outputPerm_c * m_pivotperm;
571 }
572
573 m_isInitialized = true;
574 m_factorizationIsok = true;
575 m_info = Success;
576}
577
578template <typename SparseQRType, typename Derived>
579struct SparseQR_QProduct : ReturnByValue<SparseQR_QProduct<SparseQRType, Derived> > {
580 typedef typename SparseQRType::QRMatrixType MatrixType;
581 typedef typename SparseQRType::Scalar Scalar;
582 // Get the references
583 SparseQR_QProduct(const SparseQRType& qr, const Derived& other, bool transpose)
584 : m_qr(qr), m_other(other), m_transpose(transpose) {}
585 inline Index rows() const { return m_qr.matrixQ().rows(); }
586 inline Index cols() const { return m_other.cols(); }
587
588 // Assign to a vector
589 template <typename DesType>
590 void evalTo(DesType& res) const {
591 Index m = m_qr.rows();
592 Index n = m_qr.cols();
593 Index diagSize = (std::min)(m, n);
594 res = m_other;
595 if (m_transpose) {
596 eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
597 // Compute res = Q' * other column by column
598 for (Index j = 0; j < res.cols(); j++) {
599 for (Index k = 0; k < diagSize; k++) {
600 Scalar tau = Scalar(0);
601 tau = m_qr.m_Q.col(k).dot(res.col(j));
602 if (tau == Scalar(0)) continue;
603 tau = tau * m_qr.m_hcoeffs(k);
604 res.col(j) -= tau * m_qr.m_Q.col(k);
605 }
606 }
607 } else {
608 eigen_assert(m_qr.matrixQ().cols() == m_other.rows() && "Non conforming object sizes");
609
610 res.conservativeResize(rows(), cols());
611
612 // Compute res = Q * other column by column
613 for (Index j = 0; j < res.cols(); j++) {
614 Index start_k = internal::is_identity<Derived>::value ? numext::mini(j, diagSize - 1) : diagSize - 1;
615 for (Index k = start_k; k >= 0; k--) {
616 Scalar tau = Scalar(0);
617 tau = m_qr.m_Q.col(k).dot(res.col(j));
618 if (tau == Scalar(0)) continue;
619 tau = tau * numext::conj(m_qr.m_hcoeffs(k));
620 res.col(j) -= tau * m_qr.m_Q.col(k);
621 }
622 }
623 }
624 }
625
626 const SparseQRType& m_qr;
627 const Derived& m_other;
628 bool m_transpose; // TODO this actually means adjoint
629};
630
631template <typename SparseQRType>
632struct SparseQRMatrixQReturnType : public EigenBase<SparseQRMatrixQReturnType<SparseQRType> > {
633 typedef typename SparseQRType::Scalar Scalar;
634 typedef Matrix<Scalar, Dynamic, Dynamic> DenseMatrix;
635 enum { RowsAtCompileTime = Dynamic, ColsAtCompileTime = Dynamic };
636 explicit SparseQRMatrixQReturnType(const SparseQRType& qr) : m_qr(qr) {}
637 template <typename Derived>
638 SparseQR_QProduct<SparseQRType, Derived> operator*(const MatrixBase<Derived>& other) {
639 return SparseQR_QProduct<SparseQRType, Derived>(m_qr, other.derived(), false);
640 }
641 // To use for operations with the adjoint of Q
642 SparseQRMatrixQTransposeReturnType<SparseQRType> adjoint() const {
643 return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
644 }
645 inline Index rows() const { return m_qr.rows(); }
646 inline Index cols() const { return m_qr.rows(); }
647 // To use for operations with the transpose of Q FIXME this is the same as adjoint at the moment
648 SparseQRMatrixQTransposeReturnType<SparseQRType> transpose() const {
649 return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
650 }
651 const SparseQRType& m_qr;
652};
653
654// TODO this actually represents the adjoint of Q
655template <typename SparseQRType>
656struct SparseQRMatrixQTransposeReturnType {
657 explicit SparseQRMatrixQTransposeReturnType(const SparseQRType& qr) : m_qr(qr) {}
658 template <typename Derived>
659 SparseQR_QProduct<SparseQRType, Derived> operator*(const MatrixBase<Derived>& other) {
660 return SparseQR_QProduct<SparseQRType, Derived>(m_qr, other.derived(), true);
661 }
662 const SparseQRType& m_qr;
663};
664
665namespace internal {
666
667template <typename SparseQRType>
668struct evaluator_traits<SparseQRMatrixQReturnType<SparseQRType> > {
669 typedef typename SparseQRType::MatrixType MatrixType;
670 typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind;
671 typedef SparseShape Shape;
672};
673
674template <typename DstXprType, typename SparseQRType>
675struct Assignment<DstXprType, SparseQRMatrixQReturnType<SparseQRType>,
676 internal::assign_op<typename DstXprType::Scalar, typename DstXprType::Scalar>, Sparse2Sparse> {
677 typedef SparseQRMatrixQReturnType<SparseQRType> SrcXprType;
678 typedef typename DstXprType::Scalar Scalar;
679 typedef typename DstXprType::StorageIndex StorageIndex;
680 static void run(DstXprType& dst, const SrcXprType& src, const internal::assign_op<Scalar, Scalar>& /*func*/) {
681 typename DstXprType::PlainObject idMat(src.rows(), src.cols());
682 idMat.setIdentity();
683 // Sort the sparse householder reflectors if needed
684 const_cast<SparseQRType*>(&src.m_qr)->_sort_matrix_Q();
685 dst = SparseQR_QProduct<SparseQRType, DstXprType>(src.m_qr, idMat, false);
686 }
687};
688
689template <typename DstXprType, typename SparseQRType>
690struct Assignment<DstXprType, SparseQRMatrixQReturnType<SparseQRType>,
691 internal::assign_op<typename DstXprType::Scalar, typename DstXprType::Scalar>, Sparse2Dense> {
692 typedef SparseQRMatrixQReturnType<SparseQRType> SrcXprType;
693 typedef typename DstXprType::Scalar Scalar;
694 typedef typename DstXprType::StorageIndex StorageIndex;
695 static void run(DstXprType& dst, const SrcXprType& src, const internal::assign_op<Scalar, Scalar>& /*func*/) {
696 dst = src.m_qr.matrixQ() * DstXprType::Identity(src.m_qr.rows(), src.m_qr.rows());
697 }
698};
699
700} // end namespace internal
701
702} // end namespace Eigen
703
704#endif
Derived & derived()
Definition EigenBase.h:49
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition EigenBase.h:59
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
Index size() const
Definition PermutationMatrix.h:96
Permutation matrix.
Definition PermutationMatrix.h:280
Derived & setConstant(Index size, const Scalar &val)
Definition CwiseNullaryOp.h:360
Derived & setZero(Index size)
Definition CwiseNullaryOp.h:563
const Scalar * data() const
Definition PlainObjectBase.h:273
Pseudo expression representing a solving operation.
Definition Solve.h:62
Base class of any sparse matrices or sparse expressions.
Definition SparseMatrixBase.h:30
Index rows() const
Definition SparseMatrixBase.h:182
A versatible sparse matrix representation.
Definition SparseUtil.h:47
Index cols() const
Definition SparseMatrix.h:161
Index rows() const
Definition SparseMatrix.h:159
Sparse left-looking QR factorization with numerical column pivoting.
Definition SparseQR.h:88
const PermutationType & colsPermutation() const
Definition SparseQR.h:190
void setPivotThreshold(const RealScalar &threshold)
Definition SparseQR.h:234
void analyzePattern(const MatrixType &mat)
Preprocessing step of a QR factorization.
Definition SparseQR.h:314
void factorize(const MatrixType &mat)
Performs the numerical QR factorization of the input matrix.
Definition SparseQR.h:356
SparseQR(const MatrixType &mat)
Definition SparseQR.h:117
Index cols() const
Definition SparseQR.h:141
const QRMatrixType & matrixR() const
Definition SparseQR.h:156
SparseQRMatrixQReturnType< SparseQR > matrixQ() const
Definition SparseQR.h:185
const Solve< SparseQR, Rhs > solve(const MatrixBase< Rhs > &B) const
Definition SparseQR.h:244
Index rows() const
Definition SparseQR.h:137
std::string lastErrorMessage() const
Definition SparseQR.h:198
void compute(const MatrixType &mat)
Definition SparseQR.h:128
ComputationInfo info() const
Reports whether previous computation was successful.
Definition SparseQR.h:266
Index rank() const
Definition SparseQR.h:162
A base class for sparse solvers.
Definition SparseSolverBase.h:67
ComputationInfo
Definition Constants.h:438
@ InvalidInput
Definition Constants.h:447
@ Success
Definition Constants.h:440
Namespace containing all symbols from the Eigen library.
Definition Core:137
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25
Derived & derived()
Definition EigenBase.h:49
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition Meta.h:523