Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/eigen3/Eigen/src/CholmodSupport/CholmodSupport.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // This file is part of Eigen, a lightweight C++ template library
0002 // for linear algebra.
0003 //
0004 // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
0005 //
0006 // This Source Code Form is subject to the terms of the Mozilla
0007 // Public License v. 2.0. If a copy of the MPL was not distributed
0008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
0009 
0010 #ifndef EIGEN_CHOLMODSUPPORT_H
0011 #define EIGEN_CHOLMODSUPPORT_H
0012 
0013 namespace Eigen {
0014 
0015 namespace internal {
0016 
0017 template<typename Scalar> struct cholmod_configure_matrix;
0018 
0019 template<> struct cholmod_configure_matrix<double> {
0020   template<typename CholmodType>
0021   static void run(CholmodType& mat) {
0022     mat.xtype = CHOLMOD_REAL;
0023     mat.dtype = CHOLMOD_DOUBLE;
0024   }
0025 };
0026 
0027 template<> struct cholmod_configure_matrix<std::complex<double> > {
0028   template<typename CholmodType>
0029   static void run(CholmodType& mat) {
0030     mat.xtype = CHOLMOD_COMPLEX;
0031     mat.dtype = CHOLMOD_DOUBLE;
0032   }
0033 };
0034 
0035 // Other scalar types are not yet supported by Cholmod
0036 // template<> struct cholmod_configure_matrix<float> {
0037 //   template<typename CholmodType>
0038 //   static void run(CholmodType& mat) {
0039 //     mat.xtype = CHOLMOD_REAL;
0040 //     mat.dtype = CHOLMOD_SINGLE;
0041 //   }
0042 // };
0043 //
0044 // template<> struct cholmod_configure_matrix<std::complex<float> > {
0045 //   template<typename CholmodType>
0046 //   static void run(CholmodType& mat) {
0047 //     mat.xtype = CHOLMOD_COMPLEX;
0048 //     mat.dtype = CHOLMOD_SINGLE;
0049 //   }
0050 // };
0051 
0052 } // namespace internal
0053 
0054 /** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object.
0055   * Note that the data are shared.
0056   */
0057 template<typename _Scalar, int _Options, typename _StorageIndex>
0058 cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> > mat)
0059 {
0060   cholmod_sparse res;
0061   res.nzmax   = mat.nonZeros();
0062   res.nrow    = mat.rows();
0063   res.ncol    = mat.cols();
0064   res.p       = mat.outerIndexPtr();
0065   res.i       = mat.innerIndexPtr();
0066   res.x       = mat.valuePtr();
0067   res.z       = 0;
0068   res.sorted  = 1;
0069   if(mat.isCompressed())
0070   {
0071     res.packed  = 1;
0072     res.nz = 0;
0073   }
0074   else
0075   {
0076     res.packed  = 0;
0077     res.nz = mat.innerNonZeroPtr();
0078   }
0079 
0080   res.dtype   = 0;
0081   res.stype   = -1;
0082 
0083   if (internal::is_same<_StorageIndex,int>::value)
0084   {
0085     res.itype = CHOLMOD_INT;
0086   }
0087   else if (internal::is_same<_StorageIndex,SuiteSparse_long>::value)
0088   {
0089     res.itype = CHOLMOD_LONG;
0090   }
0091   else
0092   {
0093     eigen_assert(false && "Index type not supported yet");
0094   }
0095 
0096   // setup res.xtype
0097   internal::cholmod_configure_matrix<_Scalar>::run(res);
0098 
0099   res.stype = 0;
0100 
0101   return res;
0102 }
0103 
0104 template<typename _Scalar, int _Options, typename _Index>
0105 const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
0106 {
0107   cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
0108   return res;
0109 }
0110 
0111 template<typename _Scalar, int _Options, typename _Index>
0112 const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat)
0113 {
0114   cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
0115   return res;
0116 }
0117 
0118 /** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix.
0119   * The data are not copied but shared. */
0120 template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
0121 cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
0122 {
0123   cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
0124 
0125   if(UpLo==Upper) res.stype =  1;
0126   if(UpLo==Lower) res.stype = -1;
0127   // swap stype for rowmajor matrices (only works for real matrices)
0128   EIGEN_STATIC_ASSERT((_Options & RowMajorBit) == 0 || NumTraits<_Scalar>::IsComplex == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0129   if(_Options & RowMajorBit) res.stype *=-1;
0130 
0131   return res;
0132 }
0133 
0134 /** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix.
0135   * The data are not copied but shared. */
0136 template<typename Derived>
0137 cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
0138 {
0139   EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0140   typedef typename Derived::Scalar Scalar;
0141 
0142   cholmod_dense res;
0143   res.nrow   = mat.rows();
0144   res.ncol   = mat.cols();
0145   res.nzmax  = res.nrow * res.ncol;
0146   res.d      = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
0147   res.x      = (void*)(mat.derived().data());
0148   res.z      = 0;
0149 
0150   internal::cholmod_configure_matrix<Scalar>::run(res);
0151 
0152   return res;
0153 }
0154 
0155 /** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix.
0156   * The data are not copied but shared. */
0157 template<typename Scalar, int Flags, typename StorageIndex>
0158 MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm)
0159 {
0160   return MappedSparseMatrix<Scalar,Flags,StorageIndex>
0161          (cm.nrow, cm.ncol, static_cast<StorageIndex*>(cm.p)[cm.ncol],
0162           static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
0163 }
0164 
0165 namespace internal {
0166 
0167 // template specializations for int and long that call the correct cholmod method
0168 
0169 #define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \
0170     template<typename _StorageIndex> inline ret cm_ ## name       (cholmod_common &Common) { return cholmod_ ## name   (&Common); } \
0171     template<>                       inline ret cm_ ## name<SuiteSparse_long> (cholmod_common &Common) { return cholmod_l_ ## name (&Common); }
0172 
0173 #define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \
0174     template<typename _StorageIndex> inline ret cm_ ## name       (t1& a1, cholmod_common &Common) { return cholmod_ ## name   (&a1, &Common); } \
0175     template<>                       inline ret cm_ ## name<SuiteSparse_long> (t1& a1, cholmod_common &Common) { return cholmod_l_ ## name (&a1, &Common); }
0176 
0177 EIGEN_CHOLMOD_SPECIALIZE0(int, start)
0178 EIGEN_CHOLMOD_SPECIALIZE0(int, finish)
0179 
0180 EIGEN_CHOLMOD_SPECIALIZE1(int, free_factor, cholmod_factor*, L)
0181 EIGEN_CHOLMOD_SPECIALIZE1(int, free_dense,  cholmod_dense*,  X)
0182 EIGEN_CHOLMOD_SPECIALIZE1(int, free_sparse, cholmod_sparse*, A)
0183 
0184 EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A)
0185 
0186 template<typename _StorageIndex> inline cholmod_dense*  cm_solve         (int sys, cholmod_factor& L, cholmod_dense&  B, cholmod_common &Common) { return cholmod_solve     (sys, &L, &B, &Common); }
0187 template<>                       inline cholmod_dense*  cm_solve<SuiteSparse_long>   (int sys, cholmod_factor& L, cholmod_dense&  B, cholmod_common &Common) { return cholmod_l_solve   (sys, &L, &B, &Common); }
0188 
0189 template<typename _StorageIndex> inline cholmod_sparse* cm_spsolve       (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_spsolve   (sys, &L, &B, &Common); }
0190 template<>                       inline cholmod_sparse* cm_spsolve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_l_spsolve (sys, &L, &B, &Common); }
0191 
0192 template<typename _StorageIndex>
0193 inline int  cm_factorize_p       (cholmod_sparse*  A, double beta[2], _StorageIndex* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_factorize_p   (A, beta, fset, fsize, L, &Common); }
0194 template<>
0195 inline int  cm_factorize_p<SuiteSparse_long> (cholmod_sparse*  A, double beta[2], SuiteSparse_long* fset,          std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_l_factorize_p (A, beta, fset, fsize, L, &Common); }
0196 
0197 #undef EIGEN_CHOLMOD_SPECIALIZE0
0198 #undef EIGEN_CHOLMOD_SPECIALIZE1
0199 
0200 }  // namespace internal
0201 
0202 
0203 enum CholmodMode {
0204   CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
0205 };
0206 
0207 
0208 /** \ingroup CholmodSupport_Module
0209   * \class CholmodBase
0210   * \brief The base class for the direct Cholesky factorization of Cholmod
0211   * \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT
0212   */
0213 template<typename _MatrixType, int _UpLo, typename Derived>
0214 class CholmodBase : public SparseSolverBase<Derived>
0215 {
0216   protected:
0217     typedef SparseSolverBase<Derived> Base;
0218     using Base::derived;
0219     using Base::m_isInitialized;
0220   public:
0221     typedef _MatrixType MatrixType;
0222     enum { UpLo = _UpLo };
0223     typedef typename MatrixType::Scalar Scalar;
0224     typedef typename MatrixType::RealScalar RealScalar;
0225     typedef MatrixType CholMatrixType;
0226     typedef typename MatrixType::StorageIndex StorageIndex;
0227     enum {
0228       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0229       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0230     };
0231 
0232   public:
0233 
0234     CholmodBase()
0235       : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
0236     {
0237       EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
0238       m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
0239       internal::cm_start<StorageIndex>(m_cholmod);
0240     }
0241 
0242     explicit CholmodBase(const MatrixType& matrix)
0243       : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
0244     {
0245       EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
0246       m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
0247       internal::cm_start<StorageIndex>(m_cholmod);
0248       compute(matrix);
0249     }
0250 
0251     ~CholmodBase()
0252     {
0253       if(m_cholmodFactor)
0254         internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
0255       internal::cm_finish<StorageIndex>(m_cholmod);
0256     }
0257 
0258     inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
0259     inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
0260 
0261     /** \brief Reports whether previous computation was successful.
0262       *
0263       * \returns \c Success if computation was successful,
0264       *          \c NumericalIssue if the matrix.appears to be negative.
0265       */
0266     ComputationInfo info() const
0267     {
0268       eigen_assert(m_isInitialized && "Decomposition is not initialized.");
0269       return m_info;
0270     }
0271 
0272     /** Computes the sparse Cholesky decomposition of \a matrix */
0273     Derived& compute(const MatrixType& matrix)
0274     {
0275       analyzePattern(matrix);
0276       factorize(matrix);
0277       return derived();
0278     }
0279 
0280     /** Performs a symbolic decomposition on the sparsity pattern of \a matrix.
0281       *
0282       * This function is particularly useful when solving for several problems having the same structure.
0283       *
0284       * \sa factorize()
0285       */
0286     void analyzePattern(const MatrixType& matrix)
0287     {
0288       if(m_cholmodFactor)
0289       {
0290         internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
0291         m_cholmodFactor = 0;
0292       }
0293       cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
0294       m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod);
0295 
0296       this->m_isInitialized = true;
0297       this->m_info = Success;
0298       m_analysisIsOk = true;
0299       m_factorizationIsOk = false;
0300     }
0301 
0302     /** Performs a numeric decomposition of \a matrix
0303       *
0304       * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed.
0305       *
0306       * \sa analyzePattern()
0307       */
0308     void factorize(const MatrixType& matrix)
0309     {
0310       eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
0311       cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
0312       internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod);
0313 
0314       // If the factorization failed, minor is the column at which it did. On success minor == n.
0315       this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
0316       m_factorizationIsOk = true;
0317     }
0318 
0319     /** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations.
0320      *  See the Cholmod user guide for details. */
0321     cholmod_common& cholmod() { return m_cholmod; }
0322 
0323     #ifndef EIGEN_PARSED_BY_DOXYGEN
0324     /** \internal */
0325     template<typename Rhs,typename Dest>
0326     void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
0327     {
0328       eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0329       const Index size = m_cholmodFactor->n;
0330       EIGEN_UNUSED_VARIABLE(size);
0331       eigen_assert(size==b.rows());
0332 
0333       // Cholmod needs column-major storage without inner-stride, which corresponds to the default behavior of Ref.
0334       Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.derived());
0335 
0336       cholmod_dense b_cd = viewAsCholmod(b_ref);
0337       cholmod_dense* x_cd = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod);
0338       if(!x_cd)
0339       {
0340         this->m_info = NumericalIssue;
0341         return;
0342       }
0343       // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
0344       // NOTE Actually, the copy can be avoided by calling cholmod_solve2 instead of cholmod_solve
0345       dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
0346       internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod);
0347     }
0348 
0349     /** \internal */
0350     template<typename RhsDerived, typename DestDerived>
0351     void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const
0352     {
0353       eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0354       const Index size = m_cholmodFactor->n;
0355       EIGEN_UNUSED_VARIABLE(size);
0356       eigen_assert(size==b.rows());
0357 
0358       // note: cs stands for Cholmod Sparse
0359       Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
0360       cholmod_sparse b_cs = viewAsCholmod(b_ref);
0361       cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod);
0362       if(!x_cs)
0363       {
0364         this->m_info = NumericalIssue;
0365         return;
0366       }
0367       // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
0368       // NOTE cholmod_spsolve in fact just calls the dense solver for blocks of 4 columns at a time (similar to Eigen's sparse solver)
0369       dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
0370       internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod);
0371     }
0372     #endif // EIGEN_PARSED_BY_DOXYGEN
0373 
0374 
0375     /** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization.
0376       *
0377       * During the numerical factorization, an offset term is added to the diagonal coefficients:\n
0378       * \c d_ii = \a offset + \c d_ii
0379       *
0380       * The default is \a offset=0.
0381       *
0382       * \returns a reference to \c *this.
0383       */
0384     Derived& setShift(const RealScalar& offset)
0385     {
0386       m_shiftOffset[0] = double(offset);
0387       return derived();
0388     }
0389 
0390     /** \returns the determinant of the underlying matrix from the current factorization */
0391     Scalar determinant() const
0392     {
0393       using std::exp;
0394       return exp(logDeterminant());
0395     }
0396 
0397     /** \returns the log determinant of the underlying matrix from the current factorization */
0398     Scalar logDeterminant() const
0399     {
0400       using std::log;
0401       using numext::real;
0402       eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0403 
0404       RealScalar logDet = 0;
0405       Scalar *x = static_cast<Scalar*>(m_cholmodFactor->x);
0406       if (m_cholmodFactor->is_super)
0407       {
0408         // Supernodal factorization stored as a packed list of dense column-major blocs,
0409         // as described by the following structure:
0410 
0411         // super[k] == index of the first column of the j-th super node
0412         StorageIndex *super = static_cast<StorageIndex*>(m_cholmodFactor->super);
0413         // pi[k] == offset to the description of row indices
0414         StorageIndex *pi = static_cast<StorageIndex*>(m_cholmodFactor->pi);
0415         // px[k] == offset to the respective dense block
0416         StorageIndex *px = static_cast<StorageIndex*>(m_cholmodFactor->px);
0417 
0418         Index nb_super_nodes = m_cholmodFactor->nsuper;
0419         for (Index k=0; k < nb_super_nodes; ++k)
0420         {
0421           StorageIndex ncols = super[k + 1] - super[k];
0422           StorageIndex nrows = pi[k + 1] - pi[k];
0423 
0424           Map<const Array<Scalar,1,Dynamic>, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows+1));
0425           logDet += sk.real().log().sum();
0426         }
0427       }
0428       else
0429       {
0430         // Simplicial factorization stored as standard CSC matrix.
0431         StorageIndex *p = static_cast<StorageIndex*>(m_cholmodFactor->p);
0432         Index size = m_cholmodFactor->n;
0433         for (Index k=0; k<size; ++k)
0434           logDet += log(real( x[p[k]] ));
0435       }
0436       if (m_cholmodFactor->is_ll)
0437         logDet *= 2.0;
0438       return logDet;
0439     };
0440 
0441     template<typename Stream>
0442     void dumpMemory(Stream& /*s*/)
0443     {}
0444 
0445   protected:
0446     mutable cholmod_common m_cholmod;
0447     cholmod_factor* m_cholmodFactor;
0448     double m_shiftOffset[2];
0449     mutable ComputationInfo m_info;
0450     int m_factorizationIsOk;
0451     int m_analysisIsOk;
0452 };
0453 
0454 /** \ingroup CholmodSupport_Module
0455   * \class CholmodSimplicialLLT
0456   * \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod
0457   *
0458   * This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization
0459   * using the Cholmod library.
0460   * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical interest.
0461   * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
0462   * X and B can be either dense or sparse.
0463   *
0464   * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
0465   * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
0466   *               or Upper. Default is Lower.
0467   *
0468   * \implsparsesolverconcept
0469   *
0470   * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
0471   *
0472   * \warning Only double precision real and complex scalar types are supported by Cholmod.
0473   *
0474   * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT
0475   */
0476 template<typename _MatrixType, int _UpLo = Lower>
0477 class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> >
0478 {
0479     typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base;
0480     using Base::m_cholmod;
0481 
0482   public:
0483 
0484     typedef _MatrixType MatrixType;
0485 
0486     CholmodSimplicialLLT() : Base() { init(); }
0487 
0488     CholmodSimplicialLLT(const MatrixType& matrix) : Base()
0489     {
0490       init();
0491       this->compute(matrix);
0492     }
0493 
0494     ~CholmodSimplicialLLT() {}
0495   protected:
0496     void init()
0497     {
0498       m_cholmod.final_asis = 0;
0499       m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0500       m_cholmod.final_ll = 1;
0501     }
0502 };
0503 
0504 
0505 /** \ingroup CholmodSupport_Module
0506   * \class CholmodSimplicialLDLT
0507   * \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod
0508   *
0509   * This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization
0510   * using the Cholmod library.
0511   * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical interest.
0512   * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
0513   * X and B can be either dense or sparse.
0514   *
0515   * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
0516   * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
0517   *               or Upper. Default is Lower.
0518   *
0519   * \implsparsesolverconcept
0520   *
0521   * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
0522   *
0523   * \warning Only double precision real and complex scalar types are supported by Cholmod.
0524   *
0525   * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT
0526   */
0527 template<typename _MatrixType, int _UpLo = Lower>
0528 class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> >
0529 {
0530     typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base;
0531     using Base::m_cholmod;
0532 
0533   public:
0534 
0535     typedef _MatrixType MatrixType;
0536 
0537     CholmodSimplicialLDLT() : Base() { init(); }
0538 
0539     CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
0540     {
0541       init();
0542       this->compute(matrix);
0543     }
0544 
0545     ~CholmodSimplicialLDLT() {}
0546   protected:
0547     void init()
0548     {
0549       m_cholmod.final_asis = 1;
0550       m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0551     }
0552 };
0553 
0554 /** \ingroup CholmodSupport_Module
0555   * \class CholmodSupernodalLLT
0556   * \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod
0557   *
0558   * This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization
0559   * using the Cholmod library.
0560   * This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM.
0561   * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
0562   * X and B can be either dense or sparse.
0563   *
0564   * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
0565   * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
0566   *               or Upper. Default is Lower.
0567   *
0568   * \implsparsesolverconcept
0569   *
0570   * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
0571   *
0572   * \warning Only double precision real and complex scalar types are supported by Cholmod.
0573   *
0574   * \sa \ref TutorialSparseSolverConcept
0575   */
0576 template<typename _MatrixType, int _UpLo = Lower>
0577 class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> >
0578 {
0579     typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base;
0580     using Base::m_cholmod;
0581 
0582   public:
0583 
0584     typedef _MatrixType MatrixType;
0585 
0586     CholmodSupernodalLLT() : Base() { init(); }
0587 
0588     CholmodSupernodalLLT(const MatrixType& matrix) : Base()
0589     {
0590       init();
0591       this->compute(matrix);
0592     }
0593 
0594     ~CholmodSupernodalLLT() {}
0595   protected:
0596     void init()
0597     {
0598       m_cholmod.final_asis = 1;
0599       m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
0600     }
0601 };
0602 
0603 /** \ingroup CholmodSupport_Module
0604   * \class CholmodDecomposition
0605   * \brief A general Cholesky factorization and solver based on Cholmod
0606   *
0607   * This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization
0608   * using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
0609   * X and B can be either dense or sparse.
0610   *
0611   * This variant permits to change the underlying Cholesky method at runtime.
0612   * On the other hand, it does not provide access to the result of the factorization.
0613   * The default is to let Cholmod automatically choose between a simplicial and supernodal factorization.
0614   *
0615   * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
0616   * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
0617   *               or Upper. Default is Lower.
0618   *
0619   * \implsparsesolverconcept
0620   *
0621   * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
0622   *
0623   * \warning Only double precision real and complex scalar types are supported by Cholmod.
0624   *
0625   * \sa \ref TutorialSparseSolverConcept
0626   */
0627 template<typename _MatrixType, int _UpLo = Lower>
0628 class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> >
0629 {
0630     typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base;
0631     using Base::m_cholmod;
0632 
0633   public:
0634 
0635     typedef _MatrixType MatrixType;
0636 
0637     CholmodDecomposition() : Base() { init(); }
0638 
0639     CholmodDecomposition(const MatrixType& matrix) : Base()
0640     {
0641       init();
0642       this->compute(matrix);
0643     }
0644 
0645     ~CholmodDecomposition() {}
0646 
0647     void setMode(CholmodMode mode)
0648     {
0649       switch(mode)
0650       {
0651         case CholmodAuto:
0652           m_cholmod.final_asis = 1;
0653           m_cholmod.supernodal = CHOLMOD_AUTO;
0654           break;
0655         case CholmodSimplicialLLt:
0656           m_cholmod.final_asis = 0;
0657           m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0658           m_cholmod.final_ll = 1;
0659           break;
0660         case CholmodSupernodalLLt:
0661           m_cholmod.final_asis = 1;
0662           m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
0663           break;
0664         case CholmodLDLt:
0665           m_cholmod.final_asis = 1;
0666           m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0667           break;
0668         default:
0669           break;
0670       }
0671     }
0672   protected:
0673     void init()
0674     {
0675       m_cholmod.final_asis = 1;
0676       m_cholmod.supernodal = CHOLMOD_AUTO;
0677     }
0678 };
0679 
0680 } // end namespace Eigen
0681 
0682 #endif // EIGEN_CHOLMODSUPPORT_H