Eigen  3.2.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 <desire.nuentsa_wakam@inria.fr>
5 // Copyright (C) 2012-2013 Gael Guennebaud <gael.guennebaud@inria.fr>
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 namespace Eigen {
15 
16 template<typename MatrixType, typename OrderingType> class SparseQR;
17 template<typename SparseQRType> struct SparseQRMatrixQReturnType;
18 template<typename SparseQRType> struct SparseQRMatrixQTransposeReturnType;
19 template<typename SparseQRType, typename Derived> struct SparseQR_QProduct;
20 namespace internal {
21  template <typename SparseQRType> struct traits<SparseQRMatrixQReturnType<SparseQRType> >
22  {
23  typedef typename SparseQRType::MatrixType ReturnType;
24  typedef typename ReturnType::Index Index;
25  typedef typename ReturnType::StorageKind StorageKind;
26  };
27  template <typename SparseQRType> struct traits<SparseQRMatrixQTransposeReturnType<SparseQRType> >
28  {
29  typedef typename SparseQRType::MatrixType ReturnType;
30  };
31  template <typename SparseQRType, typename Derived> struct traits<SparseQR_QProduct<SparseQRType, Derived> >
32  {
33  typedef typename Derived::PlainObject ReturnType;
34  };
35 } // End namespace internal
36 
63 template<typename _MatrixType, typename _OrderingType>
64 class SparseQR
65 {
66  public:
67  typedef _MatrixType MatrixType;
68  typedef _OrderingType OrderingType;
69  typedef typename MatrixType::Scalar Scalar;
70  typedef typename MatrixType::RealScalar RealScalar;
71  typedef typename MatrixType::Index Index;
72  typedef SparseMatrix<Scalar,ColMajor,Index> QRMatrixType;
73  typedef Matrix<Index, Dynamic, 1> IndexVector;
74  typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
75  typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
76  public:
77  SparseQR () : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false)
78  { }
79 
80  SparseQR(const MatrixType& mat) : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false)
81  {
82  compute(mat);
83  }
84  void compute(const MatrixType& mat)
85  {
86  analyzePattern(mat);
87  factorize(mat);
88  }
89  void analyzePattern(const MatrixType& mat);
90  void factorize(const MatrixType& mat);
91 
94  inline Index rows() const { return m_pmat.rows(); }
95 
98  inline Index cols() const { return m_pmat.cols();}
99 
102  const QRMatrixType& matrixR() const { return m_R; }
103 
108  Index rank() const
109  {
110  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
111  return m_nonzeropivots;
112  }
113 
132  SparseQRMatrixQReturnType<SparseQR> matrixQ() const
133  { return SparseQRMatrixQReturnType<SparseQR>(*this); }
134 
139  {
140  eigen_assert(m_isInitialized && "Decomposition is not initialized.");
141  return m_outputPerm_c;
142  }
143 
147  std::string lastErrorMessage() const { return m_lastError; }
148 
150  template<typename Rhs, typename Dest>
151  bool _solve(const MatrixBase<Rhs> &B, MatrixBase<Dest> &dest) const
152  {
153  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
154  eigen_assert(this->rows() == B.rows() && "SparseQR::solve() : invalid number of rows in the right hand side matrix");
155 
156  Index rank = this->rank();
157 
158  // Compute Q^T * b;
159  typename Dest::PlainObject y, b;
160  y = this->matrixQ().transpose() * B;
161  b = y;
162 
163  // Solve with the triangular matrix R
164  y.resize((std::max)(cols(),Index(y.rows())),y.cols());
165  y.topRows(rank) = this->matrixR().topLeftCorner(rank, rank).template triangularView<Upper>().solve(b.topRows(rank));
166  y.bottomRows(y.rows()-rank).setZero();
167 
168  // Apply the column permutation
169  if (m_perm_c.size()) dest.topRows(cols()) = colsPermutation() * y.topRows(cols());
170  else dest = y.topRows(cols());
171 
172  m_info = Success;
173  return true;
174  }
175 
176 
182  void setPivotThreshold(const RealScalar& threshold)
183  {
184  m_useDefaultThreshold = false;
185  m_threshold = threshold;
186  }
187 
192  template<typename Rhs>
193  inline const internal::solve_retval<SparseQR, Rhs> solve(const MatrixBase<Rhs>& B) const
194  {
195  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
196  eigen_assert(this->rows() == B.rows() && "SparseQR::solve() : invalid number of rows in the right hand side matrix");
197  return internal::solve_retval<SparseQR, Rhs>(*this, B.derived());
198  }
199  template<typename Rhs>
200  inline const internal::sparse_solve_retval<SparseQR, Rhs> solve(const SparseMatrixBase<Rhs>& B) const
201  {
202  eigen_assert(m_isInitialized && "The factorization should be called first, use compute()");
203  eigen_assert(this->rows() == B.rows() && "SparseQR::solve() : invalid number of rows in the right hand side matrix");
204  return internal::sparse_solve_retval<SparseQR, Rhs>(*this, B.derived());
205  }
206 
216  {
217  eigen_assert(m_isInitialized && "Decomposition is not initialized.");
218  return m_info;
219  }
220 
221  protected:
222  inline void sort_matrix_Q()
223  {
224  if(this->m_isQSorted) return;
225  // The matrix Q is sorted during the transposition
227  this->m_Q = mQrm;
228  this->m_isQSorted = true;
229  }
230 
231 
232  protected:
233  bool m_isInitialized;
234  bool m_analysisIsok;
235  bool m_factorizationIsok;
236  mutable ComputationInfo m_info;
237  std::string m_lastError;
238  QRMatrixType m_pmat; // Temporary matrix
239  QRMatrixType m_R; // The triangular factor matrix
240  QRMatrixType m_Q; // The orthogonal reflectors
241  ScalarVector m_hcoeffs; // The Householder coefficients
242  PermutationType m_perm_c; // Fill-reducing Column permutation
243  PermutationType m_pivotperm; // The permutation for rank revealing
244  PermutationType m_outputPerm_c; // The final column permutation
245  RealScalar m_threshold; // Threshold to determine null Householder reflections
246  bool m_useDefaultThreshold; // Use default threshold
247  Index m_nonzeropivots; // Number of non zero pivots found
248  IndexVector m_etree; // Column elimination tree
249  IndexVector m_firstRowElt; // First element in each row
250  bool m_isQSorted; // whether Q is sorted or not
251 
252  template <typename, typename > friend struct SparseQR_QProduct;
253  template <typename > friend struct SparseQRMatrixQReturnType;
254 
255 };
256 
264 template <typename MatrixType, typename OrderingType>
266 {
267  // Compute the column fill reducing ordering
268  OrderingType ord;
269  ord(mat, m_perm_c);
270  Index n = mat.cols();
271  Index m = mat.rows();
272 
273  if (!m_perm_c.size())
274  {
275  m_perm_c.resize(n);
276  m_perm_c.indices().setLinSpaced(n, 0,n-1);
277  }
278 
279  // Compute the column elimination tree of the permuted matrix
280  m_outputPerm_c = m_perm_c.inverse();
281  internal::coletree(mat, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
282 
283  m_R.resize(n, n);
284  m_Q.resize(m, n);
285 
286  // Allocate space for nonzero elements : rough estimation
287  m_R.reserve(2*mat.nonZeros()); //FIXME Get a more accurate estimation through symbolic factorization with the etree
288  m_Q.reserve(2*mat.nonZeros());
289  m_hcoeffs.resize(n);
290  m_analysisIsok = true;
291 }
292 
300 template <typename MatrixType, typename OrderingType>
302 {
303  using std::abs;
304  using std::max;
305 
306  eigen_assert(m_analysisIsok && "analyzePattern() should be called before this step");
307  Index m = mat.rows();
308  Index n = mat.cols();
309  IndexVector mark(m); mark.setConstant(-1); // Record the visited nodes
310  IndexVector Ridx(n), Qidx(m); // Store temporarily the row indexes for the current column of R and Q
311  Index nzcolR, nzcolQ; // Number of nonzero for the current column of R and Q
312  ScalarVector tval(m); // The dense vector used to compute the current column
313  bool found_diag;
314 
315  m_pmat = mat;
316  m_pmat.uncompress(); // To have the innerNonZeroPtr allocated
317  // Apply the fill-in reducing permutation lazily:
318  for (int i = 0; i < n; i++)
319  {
320  Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
321  m_pmat.outerIndexPtr()[p] = mat.outerIndexPtr()[i];
322  m_pmat.innerNonZeroPtr()[p] = mat.outerIndexPtr()[i+1] - mat.outerIndexPtr()[i];
323  }
324 
325  /* Compute the default threshold, see :
326  * Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
327  * Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
328  */
329  if(m_useDefaultThreshold)
330  {
331  RealScalar max2Norm = 0.0;
332  for (int j = 0; j < n; j++) max2Norm = (max)(max2Norm, m_pmat.col(j).norm());
333  m_threshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
334  }
335 
336  // Initialize the numerical permutation
337  m_pivotperm.setIdentity(n);
338 
339  Index nonzeroCol = 0; // Record the number of valid pivots
340 
341  // Left looking rank-revealing QR factorization: compute a column of R and Q at a time
342  for (Index col = 0; col < (std::min)(n,m); ++col)
343  {
344  mark.setConstant(-1);
345  m_R.startVec(col);
346  m_Q.startVec(col);
347  mark(nonzeroCol) = col;
348  Qidx(0) = nonzeroCol;
349  nzcolR = 0; nzcolQ = 1;
350  found_diag = col>=m;
351  tval.setZero();
352 
353  // Symbolic factorization: find the nonzero locations of the column k of the factors R and Q, i.e.,
354  // all the nodes (with indexes lower than rank) reachable through the column elimination tree (etree) rooted at node k.
355  // Note: if the diagonal entry does not exist, then its contribution must be explicitly added,
356  // thus the trick with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
357  for (typename MatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
358  {
359  Index curIdx = nonzeroCol ;
360  if(itp) curIdx = itp.row();
361  if(curIdx == nonzeroCol) found_diag = true;
362 
363  // Get the nonzeros indexes of the current column of R
364  Index st = m_firstRowElt(curIdx); // The traversal of the etree starts here
365  if (st < 0 )
366  {
367  m_lastError = "Empty row found during numerical factorization";
368  m_info = InvalidInput;
369  return;
370  }
371 
372  // Traverse the etree
373  Index bi = nzcolR;
374  for (; mark(st) != col; st = m_etree(st))
375  {
376  Ridx(nzcolR) = st; // Add this row to the list,
377  mark(st) = col; // and mark this row as visited
378  nzcolR++;
379  }
380 
381  // Reverse the list to get the topological ordering
382  Index nt = nzcolR-bi;
383  for(Index i = 0; i < nt/2; i++) std::swap(Ridx(bi+i), Ridx(nzcolR-i-1));
384 
385  // Copy the current (curIdx,pcol) value of the input matrix
386  if(itp) tval(curIdx) = itp.value();
387  else tval(curIdx) = Scalar(0);
388 
389  // Compute the pattern of Q(:,k)
390  if(curIdx > nonzeroCol && mark(curIdx) != col )
391  {
392  Qidx(nzcolQ) = curIdx; // Add this row to the pattern of Q,
393  mark(curIdx) = col; // and mark it as visited
394  nzcolQ++;
395  }
396  }
397 
398  // Browse all the indexes of R(:,col) in reverse order
399  for (Index i = nzcolR-1; i >= 0; i--)
400  {
401  Index curIdx = m_pivotperm.indices()(Ridx(i));
402 
403  // Apply the curIdx-th householder vector to the current column (temporarily stored into tval)
404  Scalar tdot(0);
405 
406  // First compute q' * tval
407  tdot = m_Q.col(curIdx).dot(tval);
408 
409  tdot *= m_hcoeffs(curIdx);
410 
411  // Then update tval = tval - q * tau
412  // FIXME: tval -= tdot * m_Q.col(curIdx) should amount to the same (need to check/add support for efficient "dense ?= sparse")
413  for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
414  tval(itq.row()) -= itq.value() * tdot;
415 
416  // Detect fill-in for the current column of Q
417  if(m_etree(Ridx(i)) == nonzeroCol)
418  {
419  for (typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
420  {
421  Index iQ = itq.row();
422  if (mark(iQ) != col)
423  {
424  Qidx(nzcolQ++) = iQ; // Add this row to the pattern of Q,
425  mark(iQ) = col; // and mark it as visited
426  }
427  }
428  }
429  } // End update current column
430 
431  // Compute the Householder reflection that eliminate the current column
432  // FIXME this step should call the Householder module.
433  Scalar tau;
434  RealScalar beta;
435  Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
436 
437  // First, the squared norm of Q((col+1):m, col)
438  RealScalar sqrNorm = 0.;
439  for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
440 
441  if(sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0))
442  {
443  tau = RealScalar(0);
444  beta = numext::real(c0);
445  tval(Qidx(0)) = 1;
446  }
447  else
448  {
449  beta = std::sqrt(numext::abs2(c0) + sqrNorm);
450  if(numext::real(c0) >= RealScalar(0))
451  beta = -beta;
452  tval(Qidx(0)) = 1;
453  for (Index itq = 1; itq < nzcolQ; ++itq)
454  tval(Qidx(itq)) /= (c0 - beta);
455  tau = numext::conj((beta-c0) / beta);
456 
457  }
458 
459  // Insert values in R
460  for (Index i = nzcolR-1; i >= 0; i--)
461  {
462  Index curIdx = Ridx(i);
463  if(curIdx < nonzeroCol)
464  {
465  m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
466  tval(curIdx) = Scalar(0.);
467  }
468  }
469 
470  if(abs(beta) >= m_threshold)
471  {
472  m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
473  nonzeroCol++;
474  // The householder coefficient
475  m_hcoeffs(col) = tau;
476  // Record the householder reflections
477  for (Index itq = 0; itq < nzcolQ; ++itq)
478  {
479  Index iQ = Qidx(itq);
480  m_Q.insertBackByOuterInnerUnordered(col,iQ) = tval(iQ);
481  tval(iQ) = Scalar(0.);
482  }
483  }
484  else
485  {
486  // Zero pivot found: move implicitly this column to the end
487  m_hcoeffs(col) = Scalar(0);
488  for (Index j = nonzeroCol; j < n-1; j++)
489  std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j+1]);
490 
491  // Recompute the column elimination tree
492  internal::coletree(m_pmat, m_etree, m_firstRowElt, m_pivotperm.indices().data());
493  }
494  }
495 
496  // Finalize the column pointers of the sparse matrices R and Q
497  m_Q.finalize();
498  m_Q.makeCompressed();
499  m_R.finalize();
500  m_R.makeCompressed();
501  m_isQSorted = false;
502 
503  m_nonzeropivots = nonzeroCol;
504 
505  if(nonzeroCol<n)
506  {
507  // Permute the triangular factor to put the 'dead' columns to the end
508  MatrixType tempR(m_R);
509  m_R = tempR * m_pivotperm;
510 
511  // Update the column permutation
512  m_outputPerm_c = m_outputPerm_c * m_pivotperm;
513  }
514 
515  m_isInitialized = true;
516  m_factorizationIsok = true;
517  m_info = Success;
518 }
519 
520 namespace internal {
521 
522 template<typename _MatrixType, typename OrderingType, typename Rhs>
523 struct solve_retval<SparseQR<_MatrixType,OrderingType>, Rhs>
524  : solve_retval_base<SparseQR<_MatrixType,OrderingType>, Rhs>
525 {
527  EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
528 
529  template<typename Dest> void evalTo(Dest& dst) const
530  {
531  dec()._solve(rhs(),dst);
532  }
533 };
534 template<typename _MatrixType, typename OrderingType, typename Rhs>
535 struct sparse_solve_retval<SparseQR<_MatrixType, OrderingType>, Rhs>
536  : sparse_solve_retval_base<SparseQR<_MatrixType, OrderingType>, Rhs>
537 {
538  typedef SparseQR<_MatrixType, OrderingType> Dec;
539  EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec, Rhs)
540 
541  template<typename Dest> void evalTo(Dest& dst) const
542  {
543  this->defaultEvalTo(dst);
544  }
545 };
546 } // end namespace internal
547 
548 template <typename SparseQRType, typename Derived>
549 struct SparseQR_QProduct : ReturnByValue<SparseQR_QProduct<SparseQRType, Derived> >
550 {
551  typedef typename SparseQRType::QRMatrixType MatrixType;
552  typedef typename SparseQRType::Scalar Scalar;
553  typedef typename SparseQRType::Index Index;
554  // Get the references
555  SparseQR_QProduct(const SparseQRType& qr, const Derived& other, bool transpose) :
556  m_qr(qr),m_other(other),m_transpose(transpose) {}
557  inline Index rows() const { return m_transpose ? m_qr.rows() : m_qr.cols(); }
558  inline Index cols() const { return m_other.cols(); }
559 
560  // Assign to a vector
561  template<typename DesType>
562  void evalTo(DesType& res) const
563  {
564  Index n = m_qr.cols();
565  res = m_other;
566  if (m_transpose)
567  {
568  eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
569  //Compute res = Q' * other column by column
570  for(Index j = 0; j < res.cols(); j++){
571  for (Index k = 0; k < n; k++)
572  {
573  Scalar tau = Scalar(0);
574  tau = m_qr.m_Q.col(k).dot(res.col(j));
575  if(tau==Scalar(0)) continue;
576  tau = tau * m_qr.m_hcoeffs(k);
577  res.col(j) -= tau * m_qr.m_Q.col(k);
578  }
579  }
580  }
581  else
582  {
583  eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
584  // Compute res = Q' * other column by column
585  for(Index j = 0; j < res.cols(); j++)
586  {
587  for (Index k = n-1; k >=0; k--)
588  {
589  Scalar tau = Scalar(0);
590  tau = m_qr.m_Q.col(k).dot(res.col(j));
591  if(tau==Scalar(0)) continue;
592  tau = tau * m_qr.m_hcoeffs(k);
593  res.col(j) -= tau * m_qr.m_Q.col(k);
594  }
595  }
596  }
597  }
598 
599  const SparseQRType& m_qr;
600  const Derived& m_other;
601  bool m_transpose;
602 };
603 
604 template<typename SparseQRType>
605 struct SparseQRMatrixQReturnType : public EigenBase<SparseQRMatrixQReturnType<SparseQRType> >
606 {
607  typedef typename SparseQRType::Index Index;
608  typedef typename SparseQRType::Scalar Scalar;
609  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
610  SparseQRMatrixQReturnType(const SparseQRType& qr) : m_qr(qr) {}
611  template<typename Derived>
612  SparseQR_QProduct<SparseQRType, Derived> operator*(const MatrixBase<Derived>& other)
613  {
614  return SparseQR_QProduct<SparseQRType,Derived>(m_qr,other.derived(),false);
615  }
616  SparseQRMatrixQTransposeReturnType<SparseQRType> adjoint() const
617  {
618  return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
619  }
620  inline Index rows() const { return m_qr.rows(); }
621  inline Index cols() const { return m_qr.cols(); }
622  // To use for operations with the transpose of Q
623  SparseQRMatrixQTransposeReturnType<SparseQRType> transpose() const
624  {
625  return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
626  }
627  template<typename Dest> void evalTo(MatrixBase<Dest>& dest) const
628  {
629  dest.derived() = m_qr.matrixQ() * Dest::Identity(m_qr.rows(), m_qr.rows());
630  }
631  template<typename Dest> void evalTo(SparseMatrixBase<Dest>& dest) const
632  {
633  Dest idMat(m_qr.rows(), m_qr.rows());
634  idMat.setIdentity();
635  // Sort the sparse householder reflectors if needed
636  const_cast<SparseQRType *>(&m_qr)->sort_matrix_Q();
637  dest.derived() = SparseQR_QProduct<SparseQRType, Dest>(m_qr, idMat, false);
638  }
639 
640  const SparseQRType& m_qr;
641 };
642 
643 template<typename SparseQRType>
644 struct SparseQRMatrixQTransposeReturnType
645 {
646  SparseQRMatrixQTransposeReturnType(const SparseQRType& qr) : m_qr(qr) {}
647  template<typename Derived>
648  SparseQR_QProduct<SparseQRType,Derived> operator*(const MatrixBase<Derived>& other)
649  {
650  return SparseQR_QProduct<SparseQRType,Derived>(m_qr,other.derived(), true);
651  }
652  const SparseQRType& m_qr;
653 };
654 
655 } // end namespace Eigen
656 
657 #endif
Index rows() const
Definition: SparseMatrix.h:119
void resize(Index newSize)
Definition: DenseBase.h:217
std::string lastErrorMessage() const
Definition: SparseQR.h:147
Index cols() const
Definition: SparseMatrix.h:121
Index rank() const
Definition: SparseQR.h:108
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:88
const internal::permut_matrix_product_retval< PermutationDerived, Derived, OnTheRight > operator*(const MatrixBase< Derived > &matrix, const PermutationBase< PermutationDerived > &permutation)
Definition: PermutationMatrix.h:510
void factorize(const MatrixType &mat)
Performs the numerical QR factorization of the input matrix.
Definition: SparseQR.h:301
SparseQRMatrixQReturnType< SparseQR > matrixQ() const
Definition: SparseQR.h:132
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::Index *perm=0)
Definition: SparseColEtree.h:61
Sparse left-looking rank-revealing QR factorization.
Definition: SparseQR.h:16
Index size() const
Definition: PermutationMatrix.h:114
Base class of any sparse matrices or sparse expressions.
Definition: SparseMatrixBase.h:26
Index rows() const
Definition: SparseQR.h:94
Derived & derived()
Definition: EigenBase.h:34
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: SparseQR.h:215
Index cols() const
Definition: SparseQR.h:98
Derived & setConstant(Index size, const Scalar &value)
Definition: CwiseNullaryOp.h:348
RowsBlockXpr topRows(Index n)
Definition: DenseBase.h:381
Definition: Constants.h:383
void setPivotThreshold(const RealScalar &threshold)
Definition: SparseQR.h:182
const PermutationType & colsPermutation() const
Definition: SparseQR.h:138
const internal::solve_retval< SparseQR, Rhs > solve(const MatrixBase< Rhs > &B) const
Definition: SparseQR.h:193
const QRMatrixType & matrixR() const
Definition: SparseQR.h:102
void analyzePattern(const MatrixType &mat)
Preprocessing step of a QR factorization.
Definition: SparseQR.h:265
Definition: Constants.h:376
Block< Derived > topLeftCorner(Index cRows, Index cCols)
Definition: SparseMatrixBase.h:157
Index rows() const
Definition: SparseMatrixBase.h:150
ComputationInfo
Definition: Constants.h:374
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
Derived & setZero(Index size)
Definition: CwiseNullaryOp.h:515