1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_CHOLMODSUPPORT_H
11#define EIGEN_CHOLMODSUPPORT_H
12
13namespace Eigen {
14
15namespace internal {
16
17template<typename Scalar> struct cholmod_configure_matrix;
18
19template<> struct cholmod_configure_matrix<double> {
20  template<typename CholmodType>
21  static void run(CholmodType& mat) {
22    mat.xtype = CHOLMOD_REAL;
23    mat.dtype = CHOLMOD_DOUBLE;
24  }
25};
26
27template<> struct cholmod_configure_matrix<std::complex<double> > {
28  template<typename CholmodType>
29  static void run(CholmodType& mat) {
30    mat.xtype = CHOLMOD_COMPLEX;
31    mat.dtype = CHOLMOD_DOUBLE;
32  }
33};
34
35// Other scalar types are not yet suppotred by Cholmod
36// template<> struct cholmod_configure_matrix<float> {
37//   template<typename CholmodType>
38//   static void run(CholmodType& mat) {
39//     mat.xtype = CHOLMOD_REAL;
40//     mat.dtype = CHOLMOD_SINGLE;
41//   }
42// };
43//
44// template<> struct cholmod_configure_matrix<std::complex<float> > {
45//   template<typename CholmodType>
46//   static void run(CholmodType& mat) {
47//     mat.xtype = CHOLMOD_COMPLEX;
48//     mat.dtype = CHOLMOD_SINGLE;
49//   }
50// };
51
52} // namespace internal
53
54/** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object.
55  * Note that the data are shared.
56  */
57template<typename _Scalar, int _Options, typename _StorageIndex>
58cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> > mat)
59{
60  cholmod_sparse res;
61  res.nzmax   = mat.nonZeros();
62  res.nrow    = mat.rows();
63  res.ncol    = mat.cols();
64  res.p       = mat.outerIndexPtr();
65  res.i       = mat.innerIndexPtr();
66  res.x       = mat.valuePtr();
67  res.z       = 0;
68  res.sorted  = 1;
69  if(mat.isCompressed())
70  {
71    res.packed  = 1;
72    res.nz = 0;
73  }
74  else
75  {
76    res.packed  = 0;
77    res.nz = mat.innerNonZeroPtr();
78  }
79
80  res.dtype   = 0;
81  res.stype   = -1;
82
83  if (internal::is_same<_StorageIndex,int>::value)
84  {
85    res.itype = CHOLMOD_INT;
86  }
87  else if (internal::is_same<_StorageIndex,long>::value)
88  {
89    res.itype = CHOLMOD_LONG;
90  }
91  else
92  {
93    eigen_assert(false && "Index type not supported yet");
94  }
95
96  // setup res.xtype
97  internal::cholmod_configure_matrix<_Scalar>::run(res);
98
99  res.stype = 0;
100
101  return res;
102}
103
104template<typename _Scalar, int _Options, typename _Index>
105const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
106{
107  cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
108  return res;
109}
110
111template<typename _Scalar, int _Options, typename _Index>
112const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat)
113{
114  cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
115  return res;
116}
117
118/** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix.
119  * The data are not copied but shared. */
120template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
121cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
122{
123  cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
124
125  if(UpLo==Upper) res.stype =  1;
126  if(UpLo==Lower) res.stype = -1;
127
128  return res;
129}
130
131/** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix.
132  * The data are not copied but shared. */
133template<typename Derived>
134cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
135{
136  EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
137  typedef typename Derived::Scalar Scalar;
138
139  cholmod_dense res;
140  res.nrow   = mat.rows();
141  res.ncol   = mat.cols();
142  res.nzmax  = res.nrow * res.ncol;
143  res.d      = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
144  res.x      = (void*)(mat.derived().data());
145  res.z      = 0;
146
147  internal::cholmod_configure_matrix<Scalar>::run(res);
148
149  return res;
150}
151
152/** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix.
153  * The data are not copied but shared. */
154template<typename Scalar, int Flags, typename StorageIndex>
155MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm)
156{
157  return MappedSparseMatrix<Scalar,Flags,StorageIndex>
158         (cm.nrow, cm.ncol, static_cast<StorageIndex*>(cm.p)[cm.ncol],
159          static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
160}
161
162enum CholmodMode {
163  CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
164};
165
166
167/** \ingroup CholmodSupport_Module
168  * \class CholmodBase
169  * \brief The base class for the direct Cholesky factorization of Cholmod
170  * \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT
171  */
172template<typename _MatrixType, int _UpLo, typename Derived>
173class CholmodBase : public SparseSolverBase<Derived>
174{
175  protected:
176    typedef SparseSolverBase<Derived> Base;
177    using Base::derived;
178    using Base::m_isInitialized;
179  public:
180    typedef _MatrixType MatrixType;
181    enum { UpLo = _UpLo };
182    typedef typename MatrixType::Scalar Scalar;
183    typedef typename MatrixType::RealScalar RealScalar;
184    typedef MatrixType CholMatrixType;
185    typedef typename MatrixType::StorageIndex StorageIndex;
186    enum {
187      ColsAtCompileTime = MatrixType::ColsAtCompileTime,
188      MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
189    };
190
191  public:
192
193    CholmodBase()
194      : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
195    {
196      EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
197      m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
198      cholmod_start(&m_cholmod);
199    }
200
201    explicit CholmodBase(const MatrixType& matrix)
202      : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
203    {
204      EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
205      m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
206      cholmod_start(&m_cholmod);
207      compute(matrix);
208    }
209
210    ~CholmodBase()
211    {
212      if(m_cholmodFactor)
213        cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
214      cholmod_finish(&m_cholmod);
215    }
216
217    inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
218    inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
219
220    /** \brief Reports whether previous computation was successful.
221      *
222      * \returns \c Success if computation was succesful,
223      *          \c NumericalIssue if the matrix.appears to be negative.
224      */
225    ComputationInfo info() const
226    {
227      eigen_assert(m_isInitialized && "Decomposition is not initialized.");
228      return m_info;
229    }
230
231    /** Computes the sparse Cholesky decomposition of \a matrix */
232    Derived& compute(const MatrixType& matrix)
233    {
234      analyzePattern(matrix);
235      factorize(matrix);
236      return derived();
237    }
238
239    /** Performs a symbolic decomposition on the sparsity pattern of \a matrix.
240      *
241      * This function is particularly useful when solving for several problems having the same structure.
242      *
243      * \sa factorize()
244      */
245    void analyzePattern(const MatrixType& matrix)
246    {
247      if(m_cholmodFactor)
248      {
249        cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
250        m_cholmodFactor = 0;
251      }
252      cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
253      m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
254
255      this->m_isInitialized = true;
256      this->m_info = Success;
257      m_analysisIsOk = true;
258      m_factorizationIsOk = false;
259    }
260
261    /** Performs a numeric decomposition of \a matrix
262      *
263      * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed.
264      *
265      * \sa analyzePattern()
266      */
267    void factorize(const MatrixType& matrix)
268    {
269      eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
270      cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
271      cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
272
273      // If the factorization failed, minor is the column at which it did. On success minor == n.
274      this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
275      m_factorizationIsOk = true;
276    }
277
278    /** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations.
279     *  See the Cholmod user guide for details. */
280    cholmod_common& cholmod() { return m_cholmod; }
281
282    #ifndef EIGEN_PARSED_BY_DOXYGEN
283    /** \internal */
284    template<typename Rhs,typename Dest>
285    void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
286    {
287      eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
288      const Index size = m_cholmodFactor->n;
289      EIGEN_UNUSED_VARIABLE(size);
290      eigen_assert(size==b.rows());
291
292      // Cholmod needs column-major stoarge without inner-stride, which corresponds to the default behavior of Ref.
293      Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.derived());
294
295      cholmod_dense b_cd = viewAsCholmod(b_ref);
296      cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
297      if(!x_cd)
298      {
299        this->m_info = NumericalIssue;
300        return;
301      }
302      // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
303      dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
304      cholmod_free_dense(&x_cd, &m_cholmod);
305    }
306
307    /** \internal */
308    template<typename RhsDerived, typename DestDerived>
309    void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const
310    {
311      eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
312      const Index size = m_cholmodFactor->n;
313      EIGEN_UNUSED_VARIABLE(size);
314      eigen_assert(size==b.rows());
315
316      // note: cs stands for Cholmod Sparse
317      Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
318      cholmod_sparse b_cs = viewAsCholmod(b_ref);
319      cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
320      if(!x_cs)
321      {
322        this->m_info = NumericalIssue;
323        return;
324      }
325      // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
326      dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
327      cholmod_free_sparse(&x_cs, &m_cholmod);
328    }
329    #endif // EIGEN_PARSED_BY_DOXYGEN
330
331
332    /** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization.
333      *
334      * During the numerical factorization, an offset term is added to the diagonal coefficients:\n
335      * \c d_ii = \a offset + \c d_ii
336      *
337      * The default is \a offset=0.
338      *
339      * \returns a reference to \c *this.
340      */
341    Derived& setShift(const RealScalar& offset)
342    {
343      m_shiftOffset[0] = double(offset);
344      return derived();
345    }
346
347    /** \returns the determinant of the underlying matrix from the current factorization */
348    Scalar determinant() const
349    {
350      using std::exp;
351      return exp(logDeterminant());
352    }
353
354    /** \returns the log determinant of the underlying matrix from the current factorization */
355    Scalar logDeterminant() const
356    {
357      using std::log;
358      using numext::real;
359      eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
360
361      RealScalar logDet = 0;
362      Scalar *x = static_cast<Scalar*>(m_cholmodFactor->x);
363      if (m_cholmodFactor->is_super)
364      {
365        // Supernodal factorization stored as a packed list of dense column-major blocs,
366        // as described by the following structure:
367
368        // super[k] == index of the first column of the j-th super node
369        StorageIndex *super = static_cast<StorageIndex*>(m_cholmodFactor->super);
370        // pi[k] == offset to the description of row indices
371        StorageIndex *pi = static_cast<StorageIndex*>(m_cholmodFactor->pi);
372        // px[k] == offset to the respective dense block
373        StorageIndex *px = static_cast<StorageIndex*>(m_cholmodFactor->px);
374
375        Index nb_super_nodes = m_cholmodFactor->nsuper;
376        for (Index k=0; k < nb_super_nodes; ++k)
377        {
378          StorageIndex ncols = super[k + 1] - super[k];
379          StorageIndex nrows = pi[k + 1] - pi[k];
380
381          Map<const Array<Scalar,1,Dynamic>, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows+1));
382          logDet += sk.real().log().sum();
383        }
384      }
385      else
386      {
387        // Simplicial factorization stored as standard CSC matrix.
388        StorageIndex *p = static_cast<StorageIndex*>(m_cholmodFactor->p);
389        Index size = m_cholmodFactor->n;
390        for (Index k=0; k<size; ++k)
391          logDet += log(real( x[p[k]] ));
392      }
393      if (m_cholmodFactor->is_ll)
394        logDet *= 2.0;
395      return logDet;
396    };
397
398    template<typename Stream>
399    void dumpMemory(Stream& /*s*/)
400    {}
401
402  protected:
403    mutable cholmod_common m_cholmod;
404    cholmod_factor* m_cholmodFactor;
405    double m_shiftOffset[2];
406    mutable ComputationInfo m_info;
407    int m_factorizationIsOk;
408    int m_analysisIsOk;
409};
410
411/** \ingroup CholmodSupport_Module
412  * \class CholmodSimplicialLLT
413  * \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod
414  *
415  * This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization
416  * using the Cholmod library.
417  * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical interest.
418  * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
419  * X and B can be either dense or sparse.
420  *
421  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
422  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
423  *               or Upper. Default is Lower.
424  *
425  * \implsparsesolverconcept
426  *
427  * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
428  *
429  * \warning Only double precision real and complex scalar types are supported by Cholmod.
430  *
431  * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT
432  */
433template<typename _MatrixType, int _UpLo = Lower>
434class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> >
435{
436    typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base;
437    using Base::m_cholmod;
438
439  public:
440
441    typedef _MatrixType MatrixType;
442
443    CholmodSimplicialLLT() : Base() { init(); }
444
445    CholmodSimplicialLLT(const MatrixType& matrix) : Base()
446    {
447      init();
448      this->compute(matrix);
449    }
450
451    ~CholmodSimplicialLLT() {}
452  protected:
453    void init()
454    {
455      m_cholmod.final_asis = 0;
456      m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
457      m_cholmod.final_ll = 1;
458    }
459};
460
461
462/** \ingroup CholmodSupport_Module
463  * \class CholmodSimplicialLDLT
464  * \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod
465  *
466  * This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization
467  * using the Cholmod library.
468  * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical interest.
469  * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
470  * X and B can be either dense or sparse.
471  *
472  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
473  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
474  *               or Upper. Default is Lower.
475  *
476  * \implsparsesolverconcept
477  *
478  * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
479  *
480  * \warning Only double precision real and complex scalar types are supported by Cholmod.
481  *
482  * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT
483  */
484template<typename _MatrixType, int _UpLo = Lower>
485class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> >
486{
487    typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base;
488    using Base::m_cholmod;
489
490  public:
491
492    typedef _MatrixType MatrixType;
493
494    CholmodSimplicialLDLT() : Base() { init(); }
495
496    CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
497    {
498      init();
499      this->compute(matrix);
500    }
501
502    ~CholmodSimplicialLDLT() {}
503  protected:
504    void init()
505    {
506      m_cholmod.final_asis = 1;
507      m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
508    }
509};
510
511/** \ingroup CholmodSupport_Module
512  * \class CholmodSupernodalLLT
513  * \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod
514  *
515  * This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization
516  * using the Cholmod library.
517  * This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM.
518  * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
519  * X and B can be either dense or sparse.
520  *
521  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
522  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
523  *               or Upper. Default is Lower.
524  *
525  * \implsparsesolverconcept
526  *
527  * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
528  *
529  * \warning Only double precision real and complex scalar types are supported by Cholmod.
530  *
531  * \sa \ref TutorialSparseSolverConcept
532  */
533template<typename _MatrixType, int _UpLo = Lower>
534class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> >
535{
536    typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base;
537    using Base::m_cholmod;
538
539  public:
540
541    typedef _MatrixType MatrixType;
542
543    CholmodSupernodalLLT() : Base() { init(); }
544
545    CholmodSupernodalLLT(const MatrixType& matrix) : Base()
546    {
547      init();
548      this->compute(matrix);
549    }
550
551    ~CholmodSupernodalLLT() {}
552  protected:
553    void init()
554    {
555      m_cholmod.final_asis = 1;
556      m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
557    }
558};
559
560/** \ingroup CholmodSupport_Module
561  * \class CholmodDecomposition
562  * \brief A general Cholesky factorization and solver based on Cholmod
563  *
564  * This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization
565  * using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
566  * X and B can be either dense or sparse.
567  *
568  * This variant permits to change the underlying Cholesky method at runtime.
569  * On the other hand, it does not provide access to the result of the factorization.
570  * The default is to let Cholmod automatically choose between a simplicial and supernodal factorization.
571  *
572  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
573  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
574  *               or Upper. Default is Lower.
575  *
576  * \implsparsesolverconcept
577  *
578  * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
579  *
580  * \warning Only double precision real and complex scalar types are supported by Cholmod.
581  *
582  * \sa \ref TutorialSparseSolverConcept
583  */
584template<typename _MatrixType, int _UpLo = Lower>
585class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> >
586{
587    typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base;
588    using Base::m_cholmod;
589
590  public:
591
592    typedef _MatrixType MatrixType;
593
594    CholmodDecomposition() : Base() { init(); }
595
596    CholmodDecomposition(const MatrixType& matrix) : Base()
597    {
598      init();
599      this->compute(matrix);
600    }
601
602    ~CholmodDecomposition() {}
603
604    void setMode(CholmodMode mode)
605    {
606      switch(mode)
607      {
608        case CholmodAuto:
609          m_cholmod.final_asis = 1;
610          m_cholmod.supernodal = CHOLMOD_AUTO;
611          break;
612        case CholmodSimplicialLLt:
613          m_cholmod.final_asis = 0;
614          m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
615          m_cholmod.final_ll = 1;
616          break;
617        case CholmodSupernodalLLt:
618          m_cholmod.final_asis = 1;
619          m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
620          break;
621        case CholmodLDLt:
622          m_cholmod.final_asis = 1;
623          m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
624          break;
625        default:
626          break;
627      }
628    }
629  protected:
630    void init()
631    {
632      m_cholmod.final_asis = 1;
633      m_cholmod.supernodal = CHOLMOD_AUTO;
634    }
635};
636
637} // end namespace Eigen
638
639#endif // EIGEN_CHOLMODSUPPORT_H
640