11#ifndef EIGEN_CHOLMODSUPPORT_H
12#define EIGEN_CHOLMODSUPPORT_H
15#include "./InternalHeaderCheck.h"
21template <
typename Scalar>
22struct cholmod_configure_matrix;
25struct cholmod_configure_matrix<double> {
26 template <
typename CholmodType>
27 static void run(CholmodType& mat) {
28 mat.xtype = CHOLMOD_REAL;
29 mat.dtype = CHOLMOD_DOUBLE;
34struct cholmod_configure_matrix<std::complex<double> > {
35 template <
typename CholmodType>
36 static void run(CholmodType& mat) {
37 mat.xtype = CHOLMOD_COMPLEX;
38 mat.dtype = CHOLMOD_DOUBLE;
64template <
typename Scalar_,
int Options_,
typename StorageIndex_>
67 res.nzmax = mat.nonZeros();
68 res.nrow = mat.rows();
69 res.ncol = mat.cols();
70 res.p = mat.outerIndexPtr();
71 res.i = mat.innerIndexPtr();
72 res.x = mat.valuePtr();
75 if (mat.isCompressed()) {
80 res.nz = mat.innerNonZeroPtr();
86 EIGEN_IF_CONSTEXPR ((std::is_same<StorageIndex_, int>::value)) {
87 res.itype = CHOLMOD_INT;
88 }
else EIGEN_IF_CONSTEXPR ((std::is_same<StorageIndex_, SuiteSparse_long>::value)) {
89 res.itype = CHOLMOD_LONG;
91 eigen_assert(
false &&
"Index type not supported yet");
95 internal::cholmod_configure_matrix<Scalar_>::run(res);
102template <
typename Scalar_,
int Options_,
typename Index_>
108template <
typename Scalar_,
int Options_,
typename Index_>
116template <
typename Scalar_,
int Options_,
typename Index_,
unsigned int UpLo>
120 EIGEN_IF_CONSTEXPR (UpLo ==
Upper) res.stype = 1;
121 EIGEN_IF_CONSTEXPR (UpLo ==
Lower) res.stype = -1;
123 EIGEN_STATIC_ASSERT((Options_ &
RowMajorBit) == 0 || NumTraits<Scalar_>::IsComplex == 0,
124 THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
125 EIGEN_IF_CONSTEXPR (Options_ &
RowMajorBit) res.stype *= -1;
132template <
typename Derived>
134 EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags &
RowMajorBit) == 0,
135 THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
136 typedef typename Derived::Scalar Scalar;
139 res.nrow = mat.rows();
140 res.ncol = mat.cols();
141 res.nzmax = res.nrow * res.ncol;
142 res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
143 res.x = (
void*)(mat.derived().data());
146 internal::cholmod_configure_matrix<Scalar>::run(res);
153template <
typename Scalar,
typename StorageIndex>
156 cm.nrow, cm.ncol,
static_cast<StorageIndex*
>(cm.p)[cm.ncol],
static_cast<StorageIndex*
>(cm.p),
157 static_cast<StorageIndex*
>(cm.i),
static_cast<Scalar*
>(cm.x));
162template <
typename Scalar,
typename StorageIndex>
165 cm.n, cm.n,
static_cast<StorageIndex*
>(cm.p)[cm.n],
static_cast<StorageIndex*
>(cm.p),
166 static_cast<StorageIndex*
>(cm.i),
static_cast<Scalar*
>(cm.x));
173#define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \
174 template <typename StorageIndex_> \
175 inline ret cm_##name(cholmod_common& Common) { \
176 return cholmod_##name(&Common); \
179 inline ret cm_##name<SuiteSparse_long>(cholmod_common & Common) { \
180 return cholmod_l_##name(&Common); \
183#define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \
184 template <typename StorageIndex_> \
185 inline ret cm_##name(t1& a1, cholmod_common& Common) { \
186 return cholmod_##name(&a1, &Common); \
189 inline ret cm_##name<SuiteSparse_long>(t1 & a1, cholmod_common & Common) { \
190 return cholmod_l_##name(&a1, &Common); \
193EIGEN_CHOLMOD_SPECIALIZE0(
int, start)
194EIGEN_CHOLMOD_SPECIALIZE0(
int, finish)
196EIGEN_CHOLMOD_SPECIALIZE1(
int, free_factor, cholmod_factor*, L)
197EIGEN_CHOLMOD_SPECIALIZE1(
int, free_dense, cholmod_dense*, X)
198EIGEN_CHOLMOD_SPECIALIZE1(
int, free_sparse, cholmod_sparse*, A)
200EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A)
201EIGEN_CHOLMOD_SPECIALIZE1(cholmod_sparse*, factor_to_sparse, cholmod_factor, L)
203template <
typename StorageIndex_>
204inline cholmod_dense* cm_solve(
int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common& Common) {
205 return cholmod_solve(sys, &L, &B, &Common);
208inline cholmod_dense* cm_solve<SuiteSparse_long>(
int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common& Common) {
209 return cholmod_l_solve(sys, &L, &B, &Common);
212template <
typename StorageIndex_>
213inline cholmod_sparse* cm_spsolve(
int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common& Common) {
214 return cholmod_spsolve(sys, &L, &B, &Common);
217inline cholmod_sparse* cm_spsolve<SuiteSparse_long>(
int sys, cholmod_factor& L, cholmod_sparse& B,
218 cholmod_common& Common) {
219 return cholmod_l_spsolve(sys, &L, &B, &Common);
222template <
typename StorageIndex_>
223inline int cm_factorize_p(cholmod_sparse* A,
double beta[2], StorageIndex_* fset, std::size_t fsize, cholmod_factor* L,
224 cholmod_common& Common) {
225 return cholmod_factorize_p(A, beta, fset, fsize, L, &Common);
228inline int cm_factorize_p<SuiteSparse_long>(cholmod_sparse* A,
double beta[2], SuiteSparse_long* fset,
229 std::size_t fsize, cholmod_factor* L, cholmod_common& Common) {
230 return cholmod_l_factorize_p(A, beta, fset, fsize, L, &Common);
233#undef EIGEN_CHOLMOD_SPECIALIZE0
234#undef EIGEN_CHOLMOD_SPECIALIZE1
238enum CholmodMode { CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt };
245template <
typename MatrixType_,
int UpLo_,
typename Derived>
250 using Base::m_isInitialized;
253 typedef MatrixType_ MatrixType;
254 enum { UpLo = UpLo_ };
255 typedef typename MatrixType::Scalar Scalar;
256 typedef typename MatrixType::RealScalar RealScalar;
257 typedef MatrixType CholMatrixType;
258 typedef typename MatrixType::StorageIndex StorageIndex;
259 enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };
262 CholmodBase() : m_cholmodFactor(0), m_info(
Success), m_factorizationIsOk(
false), m_analysisIsOk(
false) {
263 EIGEN_STATIC_ASSERT((std::is_same<double, RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
264 m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
265 internal::cm_start<StorageIndex>(m_cholmod);
268 explicit CholmodBase(
const MatrixType& matrix)
269 : m_cholmodFactor(0), m_info(
Success), m_factorizationIsOk(
false), m_analysisIsOk(
false) {
270 EIGEN_STATIC_ASSERT((std::is_same<double, RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
271 m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
272 internal::cm_start<StorageIndex>(m_cholmod);
277 if (m_cholmodFactor) internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
278 internal::cm_finish<StorageIndex>(m_cholmod);
281 inline StorageIndex cols()
const {
return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
282 inline StorageIndex rows()
const {
return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
290 eigen_assert(m_isInitialized &&
"Decomposition is not initialized.");
308 if (m_cholmodFactor) {
309 internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
312 cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
313 m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod);
315 this->m_isInitialized =
true;
317 m_analysisIsOk =
true;
318 m_factorizationIsOk =
false;
329 eigen_assert(m_analysisIsOk &&
"You must first call analyzePattern()");
330 cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
331 internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod);
336 (m_cholmodFactor !=
nullptr && m_cholmodFactor->minor == m_cholmodFactor->n ?
Success :
NumericalIssue);
337 m_factorizationIsOk =
true;
342 cholmod_common&
cholmod() {
return m_cholmod; }
344#ifndef EIGEN_PARSED_BY_DOXYGEN
346 template <
typename Rhs,
typename Dest>
348 eigen_assert(m_factorizationIsOk &&
349 "The decomposition is not in a valid state for solving, you must first call either compute() or "
350 "symbolic()/numeric()");
351 const Index size = m_cholmodFactor->n;
352 EIGEN_UNUSED_VARIABLE(size);
353 eigen_assert(size == b.rows());
358 cholmod_dense b_cd = viewAsCholmod(b_ref);
359 cholmod_dense* x_cd = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod);
366 dest = Matrix<Scalar, Dest::RowsAtCompileTime, Dest::ColsAtCompileTime>::Map(
reinterpret_cast<Scalar*
>(x_cd->x),
368 internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod);
372 template <
typename RhsDerived,
typename DestDerived>
373 void _solve_impl(
const SparseMatrixBase<RhsDerived>& b, SparseMatrixBase<DestDerived>& dest)
const {
374 eigen_assert(m_factorizationIsOk &&
375 "The decomposition is not in a valid state for solving, you must first call either compute() or "
376 "symbolic()/numeric()");
377 const Index size = m_cholmodFactor->n;
378 EIGEN_UNUSED_VARIABLE(size);
379 eigen_assert(size == b.rows());
382 Ref<SparseMatrix<typename RhsDerived::Scalar, ColMajor, typename RhsDerived::StorageIndex> > b_ref(
383 b.const_cast_derived());
384 cholmod_sparse b_cs = viewAsCholmod(b_ref);
385 cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod);
393 dest.derived() = viewAsEigen<typename DestDerived::Scalar, typename DestDerived::StorageIndex>(*x_cs);
394 internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod);
408 m_shiftOffset[0] = double(offset);
422 eigen_assert(m_factorizationIsOk &&
423 "The decomposition is not in a valid state for solving, you must first call either compute() or "
424 "symbolic()/numeric()");
426 RealScalar logDet = 0;
427 Scalar* x =
static_cast<Scalar*
>(m_cholmodFactor->x);
428 if (m_cholmodFactor->is_super) {
433 StorageIndex* super =
static_cast<StorageIndex*
>(m_cholmodFactor->super);
435 StorageIndex* pi =
static_cast<StorageIndex*
>(m_cholmodFactor->pi);
437 StorageIndex* px =
static_cast<StorageIndex*
>(m_cholmodFactor->px);
439 Index nb_super_nodes = m_cholmodFactor->nsuper;
440 for (Index k = 0; k < nb_super_nodes; ++k) {
441 StorageIndex ncols = super[k + 1] - super[k];
442 StorageIndex nrows = pi[k + 1] - pi[k];
445 logDet += sk.real().log().sum();
449 StorageIndex* p =
static_cast<StorageIndex*
>(m_cholmodFactor->p);
450 Index size = m_cholmodFactor->n;
451 for (Index k = 0; k < size; ++k) logDet += log(real(x[p[k]]));
453 if (m_cholmodFactor->is_ll) logDet *= 2.0;
457 template <
typename Stream>
458 void dumpMemory(Stream& ) {}
461 mutable cholmod_common m_cholmod;
462 cholmod_factor* m_cholmodFactor;
463 double m_shiftOffset[2];
464 mutable ComputationInfo m_info;
465 int m_factorizationIsOk;
492template <
typename MatrixType_,
int UpLo_ = Lower>
493class CholmodSimplicialLLT :
public CholmodBase<MatrixType_, UpLo_, CholmodSimplicialLLT<MatrixType_, UpLo_> > {
494 typedef CholmodBase<MatrixType_, UpLo_, CholmodSimplicialLLT> Base;
495 using Base::m_cholmod;
498 typedef MatrixType_ MatrixType;
499 typedef typename MatrixType::Scalar Scalar;
500 typedef typename MatrixType::RealScalar RealScalar;
501 typedef typename MatrixType::StorageIndex StorageIndex;
505 CholmodSimplicialLLT() : Base() { init(); }
507 CholmodSimplicialLLT(
const MatrixType& matrix) : Base() {
513 inline MatrixL
matrixL()
const {
return viewAsEigen<Scalar, StorageIndex>(*Base::m_cholmodFactor); }
520 m_cholmod.final_asis = 0;
521 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
522 m_cholmod.final_ll = 1;
549template <
typename MatrixType_,
int UpLo_ = Lower>
550class CholmodSimplicialLDLT :
public CholmodBase<MatrixType_, UpLo_, CholmodSimplicialLDLT<MatrixType_, UpLo_> > {
551 typedef CholmodBase<MatrixType_, UpLo_, CholmodSimplicialLDLT> Base;
552 using Base::m_cholmod;
555 typedef MatrixType_ MatrixType;
556 typedef typename MatrixType::Scalar Scalar;
557 typedef typename MatrixType::RealScalar RealScalar;
558 typedef typename MatrixType::StorageIndex StorageIndex;
563 CholmodSimplicialLDLT() : Base() { init(); }
565 CholmodSimplicialLDLT(
const MatrixType& matrix) : Base() {
572 auto cholmodL = viewAsEigen<Scalar, StorageIndex>(*Base::m_cholmodFactor);
574 VectorType D{cholmodL.rows()};
576 for (Index k = 0; k < cholmodL.outerSize(); ++k) {
585 inline MatrixL
matrixL()
const {
return viewAsEigen<Scalar, StorageIndex>(*Base::m_cholmodFactor); }
592 m_cholmod.final_asis = 1;
593 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
620template <
typename MatrixType_,
int UpLo_ = Lower>
621class CholmodSupernodalLLT :
public CholmodBase<MatrixType_, UpLo_, CholmodSupernodalLLT<MatrixType_, UpLo_> > {
622 typedef CholmodBase<MatrixType_, UpLo_, CholmodSupernodalLLT> Base;
623 using Base::m_cholmod;
626 typedef MatrixType_ MatrixType;
627 typedef typename MatrixType::Scalar Scalar;
628 typedef typename MatrixType::RealScalar RealScalar;
629 typedef typename MatrixType::StorageIndex StorageIndex;
631 CholmodSupernodalLLT() : Base() { init(); }
633 CholmodSupernodalLLT(
const MatrixType& matrix) : Base() {
641 cholmod_sparse* cholmodL = internal::cm_factor_to_sparse(*Base::m_cholmodFactor, m_cholmod);
642 MatrixType L = viewAsEigen<Scalar, StorageIndex>(*cholmodL);
643 internal::cm_free_sparse<StorageIndex>(cholmodL, m_cholmod);
653 m_cholmod.final_asis = 1;
654 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
683template <
typename MatrixType_,
int UpLo_ = Lower>
684class CholmodDecomposition :
public CholmodBase<MatrixType_, UpLo_, CholmodDecomposition<MatrixType_, UpLo_> > {
685 typedef CholmodBase<MatrixType_, UpLo_, CholmodDecomposition> Base;
686 using Base::m_cholmod;
689 typedef MatrixType_ MatrixType;
691 CholmodDecomposition() : Base() { init(); }
693 CholmodDecomposition(
const MatrixType& matrix) : Base() {
698 void setMode(CholmodMode mode) {
701 m_cholmod.final_asis = 1;
702 m_cholmod.supernodal = CHOLMOD_AUTO;
704 case CholmodSimplicialLLt:
705 m_cholmod.final_asis = 0;
706 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
707 m_cholmod.final_ll = 1;
709 case CholmodSupernodalLLt:
710 m_cholmod.final_asis = 1;
711 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
714 m_cholmod.final_asis = 1;
715 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
724 m_cholmod.final_asis = 1;
725 m_cholmod.supernodal = CHOLMOD_AUTO;
void factorize(const MatrixType &matrix)
Definition CholmodSupport.h:328
ComputationInfo info() const
Reports whether previous computation was successful.
Definition CholmodSupport.h:289
Scalar determinant() const
Definition CholmodSupport.h:413
Derived & setShift(const RealScalar &offset)
Definition CholmodSupport.h:407
Derived & compute(const MatrixType &matrix)
Definition CholmodSupport.h:295
Scalar logDeterminant() const
Definition CholmodSupport.h:419
cholmod_common & cholmod()
Definition CholmodSupport.h:342
void analyzePattern(const MatrixType &matrix)
Definition CholmodSupport.h:307
MatrixU matrixU() const
Definition CholmodSupport.h:588
VectorType vectorD() const
Definition CholmodSupport.h:571
MatrixL matrixL() const
Definition CholmodSupport.h:585
MatrixL matrixL() const
Definition CholmodSupport.h:513
MatrixU matrixU() const
Definition CholmodSupport.h:516
MatrixType matrixU() const
Definition CholmodSupport.h:649
MatrixType matrixL() const
Definition CholmodSupport.h:639
An InnerIterator allows to loop over the element of any matrix expression.
Definition CoreIterators.h:38
Scalar value() const
Definition CoreIterators.h:49
Convenience specialization of Stride to specify only an inner stride See class Map for some examples.
Definition Stride.h:93
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
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
A matrix or vector expression mapping an existing expression.
Definition Ref.h:262
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
Definition SparseSelfAdjointView.h:53
SparseSolverBase()=default
a sparse vector class
Definition SparseVector.h:63
Expression of a triangular part in a matrix.
Definition TriangularMatrix.h:426
ComputationInfo
Definition Constants.h:455
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ NumericalIssue
Definition Constants.h:459
@ Success
Definition Constants.h:457
constexpr unsigned int RowMajorBit
Definition Constants.h:71