11 #ifndef EIGEN_SPARSE_QR_H
12 #define EIGEN_SPARSE_QR_H
18 template<
typename MatrixType,
typename OrderingType>
class SparseQR;
19 template<
typename SparseQRType>
struct SparseQRMatrixQReturnType;
20 template<
typename SparseQRType>
struct SparseQRMatrixQTransposeReturnType;
21 template<
typename SparseQRType,
typename Derived>
struct SparseQR_QProduct;
23 template <
typename SparseQRType>
struct traits<SparseQRMatrixQReturnType<SparseQRType> >
26 typedef typename ReturnType::StorageIndex StorageIndex;
27 typedef typename ReturnType::StorageKind StorageKind;
33 template <
typename SparseQRType>
struct traits<SparseQRMatrixQTransposeReturnType<SparseQRType> >
37 template <
typename SparseQRType,
typename Derived>
struct traits<SparseQR_QProduct<SparseQRType, Derived> >
39 typedef typename Derived::PlainObject ReturnType;
85 template<
typename MatrixType_,
typename OrderingType_>
92 using Base::_solve_impl;
206 template<
typename Rhs,
typename Dest>
210 eigen_assert(this->
rows() == B.
rows() &&
"SparseQR::solve() : invalid number of rows in the right hand side matrix");
215 typename Dest::PlainObject
y,
b;
220 y.resize((std::max<Index>)(
cols(),
y.rows()),
y.cols());
221 y.topRows(
rank) = this->
matrixR().topLeftCorner(rank,
rank).template triangularView<Upper>().solve(
b.topRows(
rank));
222 y.bottomRows(
y.rows()-
rank).setZero();
226 else dest =
y.topRows(
cols());
247 template<
typename Rhs>
251 eigen_assert(this->
rows() == B.
rows() &&
"SparseQR::solve() : invalid number of rows in the right hand side matrix");
254 template<
typename Rhs>
258 eigen_assert(this->
rows() == B.
rows() &&
"SparseQR::solve() : invalid number of rows in the right hand side matrix");
321 template <
typename MatrixType,
typename OrderingType>
324 eigen_assert(
mat.isCompressed() &&
"SparseQR requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to SparseQR");
326 std::conditional_t<MatrixType::IsRowMajor,QRMatrixType,const MatrixType&> matCpy(
mat);
329 ord(matCpy, m_perm_c);
334 if (!m_perm_c.size())
341 m_outputPerm_c = m_perm_c.inverse();
346 m_Q.resize(
m, diagSize);
349 m_R.reserve(2*
mat.nonZeros());
350 m_Q.reserve(2*
mat.nonZeros());
351 m_hcoeffs.resize(diagSize);
352 m_analysisIsok =
true;
362 template <
typename MatrixType,
typename OrderingType>
367 eigen_assert(m_analysisIsok &&
"analyzePattern() should be called before this step");
373 Index nzcolR, nzcolQ;
382 m_outputPerm_c = m_perm_c.
inverse();
396 if(MatrixType::IsRowMajor)
398 originalOuterIndicesCpy = IndexVector::Map(m_pmat.outerIndexPtr(),
n+1);
399 originalOuterIndices = originalOuterIndicesCpy.
data();
402 for (
int i = 0;
i <
n;
i++)
404 Index p = m_perm_c.size() ? m_perm_c.indices()(
i) :
i;
405 m_pmat.outerIndexPtr()[
p] = originalOuterIndices[
i];
406 m_pmat.innerNonZeroPtr()[
p] = originalOuterIndices[
i+1] - originalOuterIndices[
i];
414 if(m_useDefaultThreshold)
417 for (
int j = 0;
j <
n;
j++) max2Norm =
numext::maxi(max2Norm, m_pmat.col(
j).norm());
424 m_pivotperm.setIdentity(
n);
434 mark(nonzeroCol) =
col;
435 Qidx(0) = nonzeroCol;
436 nzcolR = 0; nzcolQ = 1;
437 bool found_diag = nonzeroCol>=
m;
444 for (
typename QRMatrixType::InnerIterator itp(m_pmat,
col); itp || !found_diag; ++itp)
448 if(curIdx == nonzeroCol) found_diag =
true;
454 m_lastError =
"Empty row found during numerical factorization";
461 for (; mark(st) !=
col; st = m_etree(st))
469 Index nt = nzcolR-bi;
473 if(itp) tval(curIdx) = itp.value();
474 else tval(curIdx) =
Scalar(0);
477 if(curIdx > nonzeroCol && mark(curIdx) !=
col )
479 Qidx(nzcolQ) = curIdx;
486 for (
Index i = nzcolR-1;
i >= 0;
i--)
494 tdot = m_Q.col(curIdx).dot(tval);
496 tdot *= m_hcoeffs(curIdx);
500 for (
typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
501 tval(itq.row()) -= itq.value() * tdot;
504 if(m_etree(Ridx(
i)) == nonzeroCol)
506 for (
typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
521 if(nonzeroCol < diagSize)
529 for (
Index itq = 1; itq < nzcolQ; ++itq) sqrNorm +=
numext::abs2(tval(Qidx(itq)));
542 for (
Index itq = 1; itq < nzcolQ; ++itq)
543 tval(Qidx(itq)) /= (c0 - beta);
550 for (
Index i = nzcolR-1;
i >= 0;
i--)
553 if(curIdx < nonzeroCol)
555 m_R.insertBackByOuterInnerUnordered(
col, curIdx) = tval(curIdx);
556 tval(curIdx) =
Scalar(0.);
560 if(nonzeroCol < diagSize &&
abs(beta) >= pivotThreshold)
562 m_R.insertBackByOuterInner(
col, nonzeroCol) = beta;
564 m_hcoeffs(nonzeroCol) = tau;
566 for (
Index itq = 0; itq < nzcolQ; ++itq)
568 Index iQ = Qidx(itq);
569 m_Q.insertBackByOuterInnerUnordered(nonzeroCol,iQ) = tval(iQ);
573 if(nonzeroCol<diagSize)
574 m_Q.startVec(nonzeroCol);
580 std::swap(m_pivotperm.indices()(
j), m_pivotperm.indices()[
j+1]);
588 m_hcoeffs.tail(diagSize-nonzeroCol).setZero();
592 m_Q.makeCompressed();
594 m_R.makeCompressed();
597 m_nonzeropivots = nonzeroCol;
603 m_R = tempR * m_pivotperm;
606 m_outputPerm_c = m_outputPerm_c * m_pivotperm;
609 m_isInitialized =
true;
610 m_factorizationIsok =
true;
614 template <
typename SparseQRType,
typename Derived>
618 typedef typename SparseQRType::Scalar
Scalar;
626 template<
typename DesType>
638 for (
Index k = 0; k < diagSize; k++)
641 tau =
m_qr.m_Q.col(k).dot(
res.col(
j));
642 if(tau==
Scalar(0))
continue;
643 tau = tau *
m_qr.m_hcoeffs(k);
644 res.col(
j) -= tau *
m_qr.m_Q.col(k);
657 Index start_k = internal::is_identity<Derived>::value ?
numext::mini(
j,diagSize-1) : diagSize-1;
658 for (
Index k = start_k; k >=0; k--)
661 tau =
m_qr.m_Q.col(k).dot(
res.col(
j));
662 if(tau==
Scalar(0))
continue;
664 res.col(
j) -= tau *
m_qr.m_Q.col(k);
675 template<
typename SparseQRType>
678 typedef typename SparseQRType::Scalar
Scalar;
685 template<
typename Derived>
706 template<
typename SparseQRType>
710 template<
typename Derived>
720 template<
typename SparseQRType>
724 typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind;
728 template<
typename DstXprType,
typename SparseQRType>
729 struct Assignment<DstXprType, SparseQRMatrixQReturnType<SparseQRType>,
internal::assign_op<typename DstXprType::Scalar,typename DstXprType::Scalar>, Sparse2Sparse>
731 typedef SparseQRMatrixQReturnType<SparseQRType> SrcXprType;
732 typedef typename DstXprType::Scalar Scalar;
733 typedef typename DstXprType::StorageIndex StorageIndex;
734 static void run(DstXprType &dst,
const SrcXprType &src,
const internal::assign_op<Scalar,Scalar> &)
736 typename DstXprType::PlainObject idMat(src.rows(), src.cols());
739 const_cast<SparseQRType *
>(&src.m_qr)->_sort_matrix_Q();
740 dst = SparseQR_QProduct<SparseQRType, DstXprType>(src.m_qr, idMat,
false);
744 template<
typename DstXprType,
typename SparseQRType>
745 struct Assignment<DstXprType, SparseQRMatrixQReturnType<SparseQRType>,
internal::assign_op<typename DstXprType::Scalar,typename DstXprType::Scalar>, Sparse2Dense>
747 typedef SparseQRMatrixQReturnType<SparseQRType> SrcXprType;
748 typedef typename DstXprType::Scalar Scalar;
749 typedef typename DstXprType::StorageIndex StorageIndex;
750 static void run(DstXprType &dst,
const SrcXprType &src,
const internal::assign_op<Scalar,Scalar> &)
752 dst = src.m_qr.matrixQ() * DstXprType::Identity(src.m_qr.rows(), src.m_qr.rows());
const AbsReturnType abs() const
const SqrtReturnType sqrt() const
ColXpr col(Index i)
This is the const version of col().
const ImagReturnType imag() const
RealReturnType real() const
HouseholderQR< MatrixXf > qr(A)
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
Matrix< float, 1, Dynamic > MatrixType
NumTraits< Scalar >::Real RealScalar
internal::traits< Derived >::StorageIndex StorageIndex
The type used to store indices.
internal::traits< Derived >::Scalar Scalar
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Base class for all dense matrices, vectors, and expressions.
const Inverse< Derived > inverse() const
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Derived & setConstant(Index size, const Scalar &val)
const Scalar * data() const
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Derived & setZero(Index size)
Pseudo expression representing a solving operation.
Base class of any sparse matrices or sparse expressions.
Sparse left-looking QR factorization with numerical column pivoting.
void setPivotThreshold(const RealScalar &threshold)
PermutationType m_outputPerm_c
void analyzePattern(const MatrixType &mat)
Preprocessing step of a QR factorization.
IndexVector m_firstRowElt
const Solve< SparseQR, Rhs > solve(const SparseMatrixBase< Rhs > &B) const
MatrixType::Scalar Scalar
void factorize(const MatrixType &mat)
Performs the numerical QR factorization of the input matrix.
SparseQR(const MatrixType &mat)
const QRMatrixType & matrixR() const
Matrix< StorageIndex, Dynamic, 1 > IndexVector
Matrix< Scalar, Dynamic, 1 > ScalarVector
OrderingType_ OrderingType
SparseSolverBase< SparseQR< MatrixType_, OrderingType_ > > Base
const PermutationType & colsPermutation() const
SparseQRMatrixQReturnType< SparseQR > matrixQ() const
bool _solve_impl(const MatrixBase< Rhs > &B, MatrixBase< Dest > &dest) const
const Solve< SparseQR, Rhs > solve(const MatrixBase< Rhs > &B) const
PermutationType m_pivotperm
std::string lastErrorMessage() const
void compute(const MatrixType &mat)
MatrixType::RealScalar RealScalar
MatrixType::StorageIndex StorageIndex
SparseMatrix< Scalar, ColMajor, StorageIndex > QRMatrixType
bool m_useDefaultThreshold
ComputationInfo info() const
Reports whether previous computation was successful.
PermutationMatrix< Dynamic, Dynamic, StorageIndex > PermutationType
A base class for sparse solvers.
bfloat16() max(const bfloat16 &a, const bfloat16 &b)
bfloat16() min(const bfloat16 &a, const bfloat16 &b)
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::StorageIndex *perm=0)
void swap(scoped_array< T > &a, scoped_array< T > &b)
EIGEN_ALWAYS_INLINE T maxi(const T &x, const T &y)
EIGEN_ALWAYS_INLINE T mini(const T &x, const T &y)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
Eigen::Index Index
The interface type of indices.
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
SparseQRMatrixQTransposeReturnType< SparseQRType > adjoint() const
SparseQR_QProduct< SparseQRType, Derived > operator*(const MatrixBase< Derived > &other)
SparseQRMatrixQTransposeReturnType< SparseQRType > transpose() const
SparseQRMatrixQReturnType(const SparseQRType &qr)
Matrix< Scalar, Dynamic, Dynamic > DenseMatrix
const SparseQRType & m_qr
SparseQRType::Scalar Scalar
SparseQR_QProduct< SparseQRType, Derived > operator*(const MatrixBase< Derived > &other)
const SparseQRType & m_qr
SparseQRMatrixQTransposeReturnType(const SparseQRType &qr)
const SparseQRType & m_qr
void evalTo(DesType &res) const
SparseQRType::QRMatrixType MatrixType
SparseQR_QProduct(const SparseQRType &qr, const Derived &other, bool transpose)
SparseQRType::Scalar Scalar