12#ifndef EIGEN_SUITESPARSEQRSUPPORT_H
13#define EIGEN_SUITESPARSEQRSUPPORT_H
16#include "./InternalHeaderCheck.h"
20template <
typename MatrixType>
22template <
typename SPQRType>
23struct SPQRMatrixQReturnType;
24template <
typename SPQRType>
25struct SPQRMatrixQTransposeReturnType;
26template <
typename SPQRType,
typename Derived>
29template <
typename SPQRType>
30struct traits<SPQRMatrixQReturnType<SPQRType> > {
31 typedef typename SPQRType::MatrixType ReturnType;
32 typedef typename ReturnType::Scalar Scalar;
33 typedef typename ReturnType::StorageIndex StorageIndex;
34 typedef typename ReturnType::StorageKind StorageKind;
35 static constexpr int RowsAtCompileTime = Dynamic;
36 static constexpr int ColsAtCompileTime = Dynamic;
38template <
typename SPQRType>
39struct traits<SPQRMatrixQTransposeReturnType<SPQRType> > {
40 typedef typename SPQRType::MatrixType ReturnType;
42template <
typename SPQRType,
typename Derived>
43struct traits<SPQR_QProduct<SPQRType, Derived> > {
44 typedef typename Derived::PlainObject ReturnType;
72template <
typename MatrixType_>
76 using Base::m_isInitialized;
79 typedef typename MatrixType_::Scalar Scalar;
80 typedef typename MatrixType_::RealScalar RealScalar;
81 typedef SuiteSparse_long StorageIndex;
84 enum { ColsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic };
88 : m_analysisIsOk(
false),
89 m_factorizationIsOk(
false),
91 m_ordering(SPQR_ORDERING_DEFAULT),
92 m_allow_tol(SPQR_DEFAULT_TOL),
93 m_tolerance(NumTraits<Scalar>::epsilon()),
99 m_useDefaultThreshold(
true) {
100 cholmod_l_start(&m_cc);
103 explicit SPQR(
const MatrixType_& matrix)
104 : m_analysisIsOk(
false),
105 m_factorizationIsOk(
false),
106 m_isRUpToDate(
false),
107 m_ordering(SPQR_ORDERING_DEFAULT),
108 m_allow_tol(SPQR_DEFAULT_TOL),
109 m_tolerance(NumTraits<Scalar>::epsilon()),
115 m_useDefaultThreshold(
true) {
116 cholmod_l_start(&m_cc);
122 cholmod_l_finish(&m_cc);
125 cholmod_l_free_sparse(&m_H, &m_cc);
126 cholmod_l_free_sparse(&m_cR, &m_cc);
127 cholmod_l_free_dense(&m_HTau, &m_cc);
134 void compute(
const MatrixType_& matrix) {
135 if (m_isInitialized) SPQR_free();
137 MatrixType mat(matrix);
143 RealScalar pivotThreshold = m_tolerance;
144 if (m_useDefaultThreshold) {
145 RealScalar max2Norm = 0.0;
146 for (
int j = 0; j < mat.
cols(); j++) max2Norm = numext::maxi(max2Norm, mat.
col(j).norm());
147 if (numext::is_exactly_zero(max2Norm)) max2Norm = RealScalar(1);
148 pivotThreshold = 20 * (mat.
rows() + mat.
cols()) * max2Norm * NumTraits<RealScalar>::epsilon();
151 A = viewAsCholmod(mat);
152 m_rows = matrix.rows();
153 m_rank = SuiteSparseQR<Scalar>(m_ordering, pivotThreshold, internal::convert_index<StorageIndex>(matrix.cols()), &A,
154 &m_cR, &m_E, &m_H, &m_HPinv, &m_HTau, &m_cc);
158 m_isInitialized =
false;
161 if (!m_E && !initIdentityPermutation(m_cR->ncol)) {
164 m_isInitialized =
false;
168 m_isInitialized =
true;
169 m_isRUpToDate =
false;
174 inline Index
rows()
const {
return m_rows; }
179 inline Index
cols()
const {
return m_cR->ncol; }
181 template <
typename Rhs,
typename Dest>
183 eigen_assert(m_isInitialized &&
" The QR factorization should be computed first, call compute()");
184 eigen_assert(b.cols() == 1 &&
"This method is for vectors only");
187 typename Dest::PlainObject y, y2;
191 Index rk = this->
rank();
193 y.resize((std::max)(
cols(), Index(y.rows())), y.cols());
194 y.topRows(rk) = this->
matrixR().
topLeftCorner(rk, rk).template triangularView<Upper>().solve(y2.topRows(rk));
199 for (Index i = 0; i < rk; ++i) dest.
row(m_E[i]) = y.row(i);
200 for (Index i = rk; i <
cols(); ++i) dest.
row(m_E[i]).setZero();
208 eigen_assert(m_isInitialized &&
" The QR factorization should be computed first, call compute()");
209 if (!m_isRUpToDate) {
210 m_R = viewAsEigen<Scalar, StorageIndex>(*m_cR);
211 m_isRUpToDate =
true;
216 SPQRMatrixQReturnType<SPQR>
matrixQ()
const {
return SPQRMatrixQReturnType<SPQR>(*
this); }
219 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
220 return PermutationType(m_E, m_cR->ncol);
228 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
229 return m_cc.SPQR_istat[4];
235 m_useDefaultThreshold =
false;
248 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
254 bool m_factorizationIsOk;
255 mutable bool m_isRUpToDate;
259 RealScalar m_tolerance;
260 mutable cholmod_sparse* m_cR =
nullptr;
261 mutable MatrixType m_R;
262 mutable StorageIndex* m_E =
nullptr;
263 mutable cholmod_sparse* m_H =
nullptr;
264 mutable StorageIndex* m_HPinv =
nullptr;
265 mutable cholmod_dense* m_HTau =
nullptr;
266 mutable Index m_rank;
267 mutable cholmod_common m_cc;
268 bool m_useDefaultThreshold;
271 bool initIdentityPermutation(StorageIndex size) {
272 if (m_E || size == 0)
return true;
274 m_E =
static_cast<StorageIndex*
>(std::malloc(
sizeof(StorageIndex) * size));
275 if (!m_E)
return false;
276 for (StorageIndex i = 0; i < size; ++i) m_E[i] = i;
280 template <
typename,
typename>
281 friend struct SPQR_QProduct;
284template <
typename SPQRType,
typename Derived>
285struct SPQR_QProduct : ReturnByValue<SPQR_QProduct<SPQRType, Derived> > {
286 typedef typename SPQRType::Scalar Scalar;
287 typedef typename SPQRType::StorageIndex StorageIndex;
289 SPQR_QProduct(
const SPQRType& spqr,
const Derived& other,
bool transpose)
290 : m_spqr(spqr), m_other(other), m_transpose(transpose) {}
292 inline Index rows()
const {
return m_spqr.rows(); }
293 inline Index cols()
const {
return m_other.cols(); }
295 template <
typename ResType>
296 void evalTo(ResType& res)
const {
297 evalToImpl(res, m_other);
301 template <
typename ResType,
typename OtherDerived,
303 void evalToImpl(ResType& res,
const MatrixBase<OtherDerived>& otherExpr)
const {
306 int method = m_transpose ? SPQR_QTX : SPQR_QX;
307 cholmod_common* cc = m_spqr.cholmodCommon();
308 y_cd = viewAsCholmod(otherExpr.const_cast_derived());
309 x_cd = SuiteSparseQR_qmult<Scalar>(method, m_spqr.m_H, m_spqr.m_HTau, m_spqr.m_HPinv, &y_cd, cc);
310 res = Matrix<Scalar, ResType::RowsAtCompileTime, ResType::ColsAtCompileTime>::Map(
311 reinterpret_cast<Scalar*
>(x_cd->x), x_cd->nrow, x_cd->ncol);
312 cholmod_l_free_dense(&x_cd, cc);
315 template <
typename ResType,
typename OtherDerived,
316 std::enable_if_t<(int(OtherDerived::Flags) &
DirectAccessBit) == 0,
int> = 0>
317 void evalToImpl(ResType& res,
const MatrixBase<OtherDerived>& otherExpr)
const {
320 int method = m_transpose ? SPQR_QTX : SPQR_QX;
321 cholmod_common* cc = m_spqr.cholmodCommon();
322 typename OtherDerived::PlainObject other = otherExpr;
323 y_cd = viewAsCholmod(other);
324 x_cd = SuiteSparseQR_qmult<Scalar>(method, m_spqr.m_H, m_spqr.m_HTau, m_spqr.m_HPinv, &y_cd, cc);
325 res = Matrix<Scalar, ResType::RowsAtCompileTime, ResType::ColsAtCompileTime>::Map(
326 reinterpret_cast<Scalar*
>(x_cd->x), x_cd->nrow, x_cd->ncol);
327 cholmod_l_free_dense(&x_cd, cc);
330 template <
typename ResType,
typename OtherDerived>
331 void evalToImpl(ResType& res,
const SparseMatrixBase<OtherDerived>& otherExpr)
const {
333 cholmod_sparse* x_cs;
334 int method = m_transpose ? SPQR_QTX : SPQR_QX;
335 cholmod_common* cc = m_spqr.cholmodCommon();
336 typename OtherDerived::PlainObject other = otherExpr;
337 other.makeCompressed();
338 y_cs = viewAsCholmod(other);
339 x_cs = SuiteSparseQR_qmult<Scalar>(method, m_spqr.m_H, m_spqr.m_HTau, m_spqr.m_HPinv, &y_cs, cc);
340 res = viewAsEigen<Scalar, StorageIndex>(*x_cs);
341 cholmod_l_free_sparse(&x_cs, cc);
344 template <
typename ResType,
typename OtherScalar,
int OtherOptions,
typename OtherStorageIndex,
345 std::enable_if_t<std::is_same<OtherStorageIndex, StorageIndex>::value,
int> = 0>
346 void evalToImpl(ResType& res,
const SparseMatrix<OtherScalar, OtherOptions, OtherStorageIndex>& otherExpr)
const {
348 cholmod_sparse* x_cs;
349 int method = m_transpose ? SPQR_QTX : SPQR_QX;
350 cholmod_common* cc = m_spqr.cholmodCommon();
351 const SparseMatrix<OtherScalar, OtherOptions, OtherStorageIndex>* otherPtr = &otherExpr;
352 SparseMatrix<OtherScalar, OtherOptions, OtherStorageIndex> other;
354 if (!otherExpr.isCompressed()) {
356 other.makeCompressed();
360 y_cs = viewAsCholmod(*otherPtr);
361 x_cs = SuiteSparseQR_qmult<Scalar>(method, m_spqr.m_H, m_spqr.m_HTau, m_spqr.m_HPinv, &y_cs, cc);
362 res = viewAsEigen<Scalar, StorageIndex>(*x_cs);
363 cholmod_l_free_sparse(&x_cs, cc);
367 const SPQRType& m_spqr;
368 const Derived& m_other;
371template <
typename SPQRType>
372struct SPQRMatrixQReturnType :
public EigenBase<SPQRMatrixQReturnType<SPQRType> > {
373 typedef typename SPQRType::Scalar Scalar;
374 static constexpr int RowsAtCompileTime = Dynamic;
375 static constexpr int ColsAtCompileTime = Dynamic;
376 SPQRMatrixQReturnType(
const SPQRType& spqr) : m_spqr(spqr) {}
377 template <
typename Derived>
378 SPQR_QProduct<SPQRType, Derived> operator*(
const MatrixBase<Derived>& other) {
379 return SPQR_QProduct<SPQRType, Derived>(m_spqr, other.derived(),
false);
381 template <
typename Derived>
382 SPQR_QProduct<SPQRType, Derived> operator*(
const SparseMatrixBase<Derived>& other) {
383 return SPQR_QProduct<SPQRType, Derived>(m_spqr, other.derived(),
false);
385 SPQRMatrixQTransposeReturnType<SPQRType> adjoint()
const {
return SPQRMatrixQTransposeReturnType<SPQRType>(m_spqr); }
386 inline Index rows()
const {
return m_spqr.rows(); }
387 inline Index cols()
const {
return m_spqr.rows(); }
389 SPQRMatrixQTransposeReturnType<SPQRType> transpose()
const {
390 return SPQRMatrixQTransposeReturnType<SPQRType>(m_spqr);
392 const SPQRType& m_spqr;
395template <
typename SPQRType>
396struct SPQRMatrixQTransposeReturnType {
397 SPQRMatrixQTransposeReturnType(
const SPQRType& spqr) : m_spqr(spqr) {}
398 template <
typename Derived>
399 SPQR_QProduct<SPQRType, Derived> operator*(
const MatrixBase<Derived>& other) {
400 return SPQR_QProduct<SPQRType, Derived>(m_spqr, other.derived(),
true);
402 template <
typename Derived>
403 SPQR_QProduct<SPQRType, Derived> operator*(
const SparseMatrixBase<Derived>& other) {
404 return SPQR_QProduct<SPQRType, Derived>(m_spqr, other.derived(),
true);
406 const SPQRType& m_spqr;
411template <
typename SPQRType>
412struct evaluator_traits<SPQRMatrixQReturnType<SPQRType> > {
413 typedef typename SPQRType::MatrixType MatrixType;
414 typedef typename storage_kind_to_evaluator_kind<typename MatrixType::StorageKind>::Kind Kind;
415 typedef SparseShape Shape;
418template <
typename DstXprType,
typename SPQRType>
419struct Assignment<DstXprType, SPQRMatrixQReturnType<SPQRType>,
420 internal::assign_op<typename DstXprType::Scalar, typename DstXprType::Scalar>, Sparse2Sparse> {
421 typedef SPQRMatrixQReturnType<SPQRType> SrcXprType;
422 typedef typename DstXprType::Scalar Scalar;
424 static void run(DstXprType& dst,
const SrcXprType& src,
const internal::assign_op<Scalar, Scalar>& ) {
425 typename DstXprType::PlainObject idMat(src.rows(), src.cols());
427 dst = src.m_spqr.matrixQ() * idMat;
431template <
typename DstXprType,
typename SPQRType>
432struct Assignment<DstXprType, SPQRMatrixQReturnType<SPQRType>,
433 internal::assign_op<typename DstXprType::Scalar, typename DstXprType::Scalar>, Sparse2Dense> {
434 typedef SPQRMatrixQReturnType<SPQRType> SrcXprType;
435 typedef typename DstXprType::Scalar Scalar;
437 static void run(DstXprType& dst,
const SrcXprType& src,
const internal::assign_op<Scalar, Scalar>& ) {
438 dst = src.m_spqr.matrixQ() * DstXprType::Identity(src.rows(), src.cols());
constexpr RowXpr row(Index i)
Definition DenseBase.h:1094
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
Sparse QR factorization based on SuiteSparseQR library.
Definition SuiteSparseQRSupport.h:73
void setPivotThreshold(const RealScalar &tol)
Set the tolerance tol to treat columns with 2-norm <= tol as zero.
Definition SuiteSparseQRSupport.h:234
Index rank() const
Definition SuiteSparseQRSupport.h:227
cholmod_common * cholmodCommon() const
Definition SuiteSparseQRSupport.h:240
SPQRMatrixQReturnType< SPQR > matrixQ() const
Get an expression of the matrix Q.
Definition SuiteSparseQRSupport.h:216
ComputationInfo info() const
Reports whether previous computation was successful.
Definition SuiteSparseQRSupport.h:247
Index rows() const
Definition SuiteSparseQRSupport.h:174
Index cols() const
Definition SuiteSparseQRSupport.h:179
const MatrixType & matrixR() const
Definition SuiteSparseQRSupport.h:207
PermutationType colsPermutation() const
Get the permutation that was applied to columns of A.
Definition SuiteSparseQRSupport.h:218
void setSPQROrdering(int ord)
Set the fill-reducing ordering method to be used.
Definition SuiteSparseQRSupport.h:232
constexpr FixedBlockXpr<...,... >::Type topLeftCorner(NRowsType cRows, NColsType cCols)
Definition SparseMatrixBase.h:287
constexpr ColXpr col(Index i)
Definition SparseMatrixBase.h:1081
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
Index cols() const
Definition SparseMatrix.h:162
Index rows() const
Definition SparseMatrix.h:160
SparseSolverBase()=default
ComputationInfo
Definition Constants.h:455
@ NumericalIssue
Definition Constants.h:459
@ Success
Definition Constants.h:457
constexpr unsigned int DirectAccessBit
Definition Constants.h:160
Definition EigenBase.h:34
Eigen::Index Index
Definition EigenBase.h:44