10#ifndef EIGEN_CHOLMODSUPPORT_H
11#define EIGEN_CHOLMODSUPPORT_H
14#include "./InternalHeaderCheck.h"
20template <
typename Scalar>
21struct cholmod_configure_matrix;
24struct cholmod_configure_matrix<double> {
25 template <
typename CholmodType>
26 static void run(CholmodType& mat) {
27 mat.xtype = CHOLMOD_REAL;
28 mat.dtype = CHOLMOD_DOUBLE;
33struct cholmod_configure_matrix<std::complex<double> > {
34 template <
typename CholmodType>
35 static void run(CholmodType& mat) {
36 mat.xtype = CHOLMOD_COMPLEX;
37 mat.dtype = CHOLMOD_DOUBLE;
63template <
typename Scalar_,
int Options_,
typename StorageIndex_>
66 res.nzmax = mat.nonZeros();
67 res.nrow = mat.rows();
68 res.ncol = mat.cols();
69 res.p = mat.outerIndexPtr();
70 res.i = mat.innerIndexPtr();
71 res.x = mat.valuePtr();
74 if (mat.isCompressed()) {
79 res.nz = mat.innerNonZeroPtr();
85 if (internal::is_same<StorageIndex_, int>::value) {
86 res.itype = CHOLMOD_INT;
87 }
else if (internal::is_same<StorageIndex_, SuiteSparse_long>::value) {
88 res.itype = CHOLMOD_LONG;
90 eigen_assert(
false &&
"Index type not supported yet");
94 internal::cholmod_configure_matrix<Scalar_>::run(res);
101template <
typename Scalar_,
int Options_,
typename Index_>
102const cholmod_sparse viewAsCholmod(
const SparseMatrix<Scalar_, Options_, Index_>& mat) {
103 cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<Scalar_, Options_, Index_> >(mat.const_cast_derived()));
107template <
typename Scalar_,
int Options_,
typename Index_>
108const cholmod_sparse
viewAsCholmod(
const SparseVector<Scalar_, Options_, Index_>& mat) {
109 cholmod_sparse res =
viewAsCholmod(Ref<SparseMatrix<Scalar_, Options_, Index_> >(mat.const_cast_derived()));
115template <
typename Scalar_,
int Options_,
typename Index_,
unsigned int UpLo>
119 if (UpLo ==
Upper) res.stype = 1;
120 if (UpLo ==
Lower) res.stype = -1;
123 THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
131template <
typename Derived>
133 EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags &
RowMajorBit) == 0,
134 THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
135 typedef typename Derived::Scalar Scalar;
138 res.nrow = mat.
rows();
139 res.ncol = mat.
cols();
140 res.nzmax = res.nrow * res.ncol;
141 res.d = Derived::IsVectorAtCompileTime ? mat.
derived().size() : mat.
derived().outerStride();
142 res.x = (
void*)(mat.
derived().data());
145 internal::cholmod_configure_matrix<Scalar>::run(res);
152template <
typename Scalar,
typename StorageIndex>
155 cm.nrow, cm.ncol,
static_cast<StorageIndex*
>(cm.p)[cm.ncol],
static_cast<StorageIndex*
>(cm.p),
156 static_cast<StorageIndex*
>(cm.i),
static_cast<Scalar*
>(cm.x));
161template <
typename Scalar,
typename StorageIndex>
164 cm.n, cm.n,
static_cast<StorageIndex*
>(cm.p)[cm.n],
static_cast<StorageIndex*
>(cm.p),
165 static_cast<StorageIndex*
>(cm.i),
static_cast<Scalar*
>(cm.x));
172#define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \
173 template <typename StorageIndex_> \
174 inline ret cm_##name(cholmod_common& Common) { \
175 return cholmod_##name(&Common); \
178 inline ret cm_##name<SuiteSparse_long>(cholmod_common & Common) { \
179 return cholmod_l_##name(&Common); \
182#define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \
183 template <typename StorageIndex_> \
184 inline ret cm_##name(t1& a1, cholmod_common& Common) { \
185 return cholmod_##name(&a1, &Common); \
188 inline ret cm_##name<SuiteSparse_long>(t1 & a1, cholmod_common & Common) { \
189 return cholmod_l_##name(&a1, &Common); \
192EIGEN_CHOLMOD_SPECIALIZE0(
int, start)
193EIGEN_CHOLMOD_SPECIALIZE0(
int, finish)
195EIGEN_CHOLMOD_SPECIALIZE1(
int, free_factor, cholmod_factor*, L)
196EIGEN_CHOLMOD_SPECIALIZE1(
int, free_dense, cholmod_dense*, X)
197EIGEN_CHOLMOD_SPECIALIZE1(
int, free_sparse, cholmod_sparse*, A)
199EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A)
200EIGEN_CHOLMOD_SPECIALIZE1(cholmod_sparse*, factor_to_sparse, cholmod_factor, L)
202template <
typename StorageIndex_>
203inline cholmod_dense* cm_solve(
int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common& Common) {
204 return cholmod_solve(sys, &L, &B, &Common);
207inline cholmod_dense* cm_solve<SuiteSparse_long>(
int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common& Common) {
208 return cholmod_l_solve(sys, &L, &B, &Common);
211template <
typename StorageIndex_>
212inline cholmod_sparse* cm_spsolve(
int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common& Common) {
213 return cholmod_spsolve(sys, &L, &B, &Common);
216inline cholmod_sparse* cm_spsolve<SuiteSparse_long>(
int sys, cholmod_factor& L, cholmod_sparse& B,
217 cholmod_common& Common) {
218 return cholmod_l_spsolve(sys, &L, &B, &Common);
221template <
typename StorageIndex_>
222inline int cm_factorize_p(cholmod_sparse* A,
double beta[2], StorageIndex_* fset, std::size_t fsize, cholmod_factor* L,
223 cholmod_common& Common) {
224 return cholmod_factorize_p(A, beta, fset, fsize, L, &Common);
227inline int cm_factorize_p<SuiteSparse_long>(cholmod_sparse* A,
double beta[2], SuiteSparse_long* fset,
228 std::size_t fsize, cholmod_factor* L, cholmod_common& Common) {
229 return cholmod_l_factorize_p(A, beta, fset, fsize, L, &Common);
232#undef EIGEN_CHOLMOD_SPECIALIZE0
233#undef EIGEN_CHOLMOD_SPECIALIZE1
237enum CholmodMode { CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt };
244template <
typename MatrixType_,
int UpLo_,
typename Derived>
249 using Base::m_isInitialized;
252 typedef MatrixType_ MatrixType;
253 enum { UpLo = UpLo_ };
254 typedef typename MatrixType::Scalar Scalar;
255 typedef typename MatrixType::RealScalar RealScalar;
256 typedef MatrixType CholMatrixType;
257 typedef typename MatrixType::StorageIndex StorageIndex;
258 enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };
261 CholmodBase() : m_cholmodFactor(0), m_info(
Success), m_factorizationIsOk(
false), m_analysisIsOk(
false) {
262 EIGEN_STATIC_ASSERT((internal::is_same<double, RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
263 m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
264 internal::cm_start<StorageIndex>(m_cholmod);
268 : m_cholmodFactor(0), m_info(
Success), m_factorizationIsOk(
false), m_analysisIsOk(
false) {
269 EIGEN_STATIC_ASSERT((internal::is_same<double, RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
270 m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
271 internal::cm_start<StorageIndex>(m_cholmod);
276 if (m_cholmodFactor) internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
277 internal::cm_finish<StorageIndex>(m_cholmod);
280 inline StorageIndex cols()
const {
return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
281 inline StorageIndex rows()
const {
return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
289 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
307 if (m_cholmodFactor) {
308 internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
311 cholmod_sparse A =
viewAsCholmod(matrix.template selfadjointView<UpLo>());
312 m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod);
314 this->m_isInitialized =
true;
316 m_analysisIsOk =
true;
317 m_factorizationIsOk =
false;
328 eigen_assert(m_analysisIsOk &&
"You must first call analyzePattern()");
329 cholmod_sparse A =
viewAsCholmod(matrix.template selfadjointView<UpLo>());
330 internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod);
335 (m_cholmodFactor !=
nullptr && m_cholmodFactor->minor == m_cholmodFactor->n ?
Success :
NumericalIssue);
336 m_factorizationIsOk =
true;
341 cholmod_common&
cholmod() {
return m_cholmod; }
343#ifndef EIGEN_PARSED_BY_DOXYGEN
345 template <
typename Rhs,
typename Dest>
347 eigen_assert(m_factorizationIsOk &&
348 "The decomposition is not in a valid state for solving, you must first call either compute() or "
349 "symbolic()/numeric()");
350 const Index size = m_cholmodFactor->n;
351 EIGEN_UNUSED_VARIABLE(size);
352 eigen_assert(size == b.
rows());
358 cholmod_dense* x_cd = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod);
365 dest = Matrix<Scalar, Dest::RowsAtCompileTime, Dest::ColsAtCompileTime>::Map(
reinterpret_cast<Scalar*
>(x_cd->x),
367 internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod);
371 template <
typename RhsDerived,
typename DestDerived>
372 void _solve_impl(
const SparseMatrixBase<RhsDerived>& b, SparseMatrixBase<DestDerived>& dest)
const {
373 eigen_assert(m_factorizationIsOk &&
374 "The decomposition is not in a valid state for solving, you must first call either compute() or "
375 "symbolic()/numeric()");
376 const Index size = m_cholmodFactor->n;
377 EIGEN_UNUSED_VARIABLE(size);
378 eigen_assert(size == b.rows());
381 Ref<SparseMatrix<typename RhsDerived::Scalar, ColMajor, typename RhsDerived::StorageIndex> > b_ref(
382 b.const_cast_derived());
384 cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod);
393 internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod);
407 m_shiftOffset[0] = double(offset);
421 eigen_assert(m_factorizationIsOk &&
422 "The decomposition is not in a valid state for solving, you must first call either compute() or "
423 "symbolic()/numeric()");
425 RealScalar logDet = 0;
426 Scalar* x =
static_cast<Scalar*
>(m_cholmodFactor->x);
427 if (m_cholmodFactor->is_super) {
432 StorageIndex* super =
static_cast<StorageIndex*
>(m_cholmodFactor->super);
434 StorageIndex* pi =
static_cast<StorageIndex*
>(m_cholmodFactor->pi);
436 StorageIndex* px =
static_cast<StorageIndex*
>(m_cholmodFactor->px);
438 Index nb_super_nodes = m_cholmodFactor->nsuper;
439 for (
Index k = 0; k < nb_super_nodes; ++k) {
440 StorageIndex ncols = super[k + 1] - super[k];
441 StorageIndex nrows = pi[k + 1] - pi[k];
444 logDet += sk.real().log().sum();
448 StorageIndex* p =
static_cast<StorageIndex*
>(m_cholmodFactor->p);
449 Index size = m_cholmodFactor->n;
450 for (
Index k = 0; k < size; ++k) logDet +=
log(
real(x[p[k]]));
452 if (m_cholmodFactor->is_ll) logDet *= 2.0;
456 template <
typename Stream>
457 void dumpMemory(Stream& ) {}
460 mutable cholmod_common m_cholmod;
461 cholmod_factor* m_cholmodFactor;
462 double m_shiftOffset[2];
463 mutable ComputationInfo m_info;
464 int m_factorizationIsOk;
491template <
typename MatrixType_,
int UpLo_ = Lower>
494 using Base::m_cholmod;
497 typedef MatrixType_ MatrixType;
498 typedef typename MatrixType::Scalar Scalar;
499 typedef typename MatrixType::RealScalar RealScalar;
500 typedef typename MatrixType::StorageIndex StorageIndex;
521 m_cholmod.final_asis = 0;
522 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
523 m_cholmod.final_ll = 1;
550template <
typename MatrixType_,
int UpLo_ = Lower>
553 using Base::m_cholmod;
556 typedef MatrixType_ MatrixType;
557 typedef typename MatrixType::Scalar Scalar;
558 typedef typename MatrixType::RealScalar RealScalar;
559 typedef typename MatrixType::StorageIndex StorageIndex;
579 for (
Index k = 0; k < cholmodL.outerSize(); ++k) {
580 typename decltype(cholmodL)::InnerIterator it{cholmodL, k};
595 m_cholmod.final_asis = 1;
596 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
623template <
typename MatrixType_,
int UpLo_ = Lower>
626 using Base::m_cholmod;
629 typedef MatrixType_ MatrixType;
630 typedef typename MatrixType::Scalar Scalar;
631 typedef typename MatrixType::RealScalar RealScalar;
632 typedef typename MatrixType::StorageIndex StorageIndex;
646 cholmod_sparse* cholmodL = internal::cm_factor_to_sparse(*Base::m_cholmodFactor, m_cholmod);
648 internal::cm_free_sparse<StorageIndex>(cholmodL, m_cholmod);
658 m_cholmod.final_asis = 1;
659 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
688template <
typename MatrixType_,
int UpLo_ = Lower>
691 using Base::m_cholmod;
694 typedef MatrixType_ MatrixType;
705 void setMode(CholmodMode mode) {
708 m_cholmod.final_asis = 1;
709 m_cholmod.supernodal = CHOLMOD_AUTO;
711 case CholmodSimplicialLLt:
712 m_cholmod.final_asis = 0;
713 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
714 m_cholmod.final_ll = 1;
716 case CholmodSupernodalLLt:
717 m_cholmod.final_asis = 1;
718 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
721 m_cholmod.final_asis = 1;
722 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
731 m_cholmod.final_asis = 1;
732 m_cholmod.supernodal = CHOLMOD_AUTO;
The base class for the direct Cholesky factorization of Cholmod.
Definition CholmodSupport.h:245
void factorize(const MatrixType &matrix)
Definition CholmodSupport.h:327
ComputationInfo info() const
Reports whether previous computation was successful.
Definition CholmodSupport.h:288
Scalar determinant() const
Definition CholmodSupport.h:412
Derived & setShift(const RealScalar &offset)
Definition CholmodSupport.h:406
Derived & compute(const MatrixType &matrix)
Definition CholmodSupport.h:294
Scalar logDeterminant() const
Definition CholmodSupport.h:418
cholmod_common & cholmod()
Definition CholmodSupport.h:341
void analyzePattern(const MatrixType &matrix)
Definition CholmodSupport.h:306
A general Cholesky factorization and solver based on Cholmod.
Definition CholmodSupport.h:689
A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod.
Definition CholmodSupport.h:551
MatrixU matrixU() const
Definition CholmodSupport.h:591
VectorType vectorD() const
Definition CholmodSupport.h:574
MatrixL matrixL() const
Definition CholmodSupport.h:588
A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod.
Definition CholmodSupport.h:492
MatrixL matrixL() const
Definition CholmodSupport.h:514
MatrixU matrixU() const
Definition CholmodSupport.h:517
A supernodal Cholesky (LLT) factorization and solver based on Cholmod.
Definition CholmodSupport.h:624
MatrixType matrixU() const
Definition CholmodSupport.h:654
MatrixType matrixL() const
Definition CholmodSupport.h:644
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition EigenBase.h:61
Derived & derived()
Definition EigenBase.h:49
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition EigenBase.h:59
Convenience specialization of Stride to specify only an inner stride See class Map for some examples.
Definition Stride.h:86
A matrix or vector expression mapping an existing array of data.
Definition Map.h:96
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
A matrix or vector expression mapping an existing expression.
Definition Ref.h:264
A versatible sparse matrix representation.
Definition SparseUtil.h:47
Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
Definition SparseUtil.h:52
A base class for sparse solvers.
Definition SparseSolverBase.h:67
Expression of a triangular part in a matrix.
Definition TriangularMatrix.h:167
const AdjointReturnType adjoint() const
Definition TriangularMatrix.h:224
ComputationInfo
Definition Constants.h:438
@ Lower
Definition Constants.h:211
@ Upper
Definition Constants.h:213
@ NumericalIssue
Definition Constants.h:442
@ Success
Definition Constants.h:440
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition Core:137
Map< const SparseMatrix< Scalar, ColMajor, StorageIndex > > viewAsEigen(cholmod_sparse &cm)
Definition CholmodSupport.h:153
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_exp_op< typename Derived::Scalar >, const Derived > exp(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
cholmod_sparse viewAsCholmod(Ref< SparseMatrix< Scalar_, Options_, StorageIndex_ > > mat)
Definition CholmodSupport.h:64
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_log_op< typename Derived::Scalar >, const Derived > log(const Eigen::ArrayBase< Derived > &x)
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition Meta.h:523