File indexing completed on 2025-10-30 08:54:04
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 #ifndef EIGEN_SPARSE_LU_H
0013 #define EIGEN_SPARSE_LU_H
0014 
0015 namespace RivetEigen {
0016 
0017 template <typename _MatrixType, typename _OrderingType = COLAMDOrdering<typename _MatrixType::StorageIndex> > class SparseLU;
0018 template <typename MappedSparseMatrixType> struct SparseLUMatrixLReturnType;
0019 template <typename MatrixLType, typename MatrixUType> struct SparseLUMatrixUReturnType;
0020 
0021 template <bool Conjugate,class SparseLUType>
0022 class SparseLUTransposeView : public SparseSolverBase<SparseLUTransposeView<Conjugate,SparseLUType> >
0023 {
0024 protected:
0025   typedef SparseSolverBase<SparseLUTransposeView<Conjugate,SparseLUType> > APIBase;
0026   using APIBase::m_isInitialized;
0027 public:
0028   typedef typename SparseLUType::Scalar Scalar;
0029   typedef typename SparseLUType::StorageIndex StorageIndex;
0030   typedef typename SparseLUType::MatrixType MatrixType;
0031   typedef typename SparseLUType::OrderingType OrderingType;
0032 
0033   enum {
0034     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0035     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0036   };
0037 
0038   SparseLUTransposeView() : m_sparseLU(NULL) {}
0039   SparseLUTransposeView(const SparseLUTransposeView& view) {
0040     this->m_sparseLU = view.m_sparseLU;
0041   }
0042   void setIsInitialized(const bool isInitialized) {this->m_isInitialized = isInitialized;}
0043   void setSparseLU(SparseLUType* sparseLU) {m_sparseLU = sparseLU;}
0044   using APIBase::_solve_impl;
0045   template<typename Rhs, typename Dest>
0046   bool _solve_impl(const MatrixBase<Rhs> &B, MatrixBase<Dest> &X_base) const
0047   {
0048     Dest& X(X_base.derived());
0049     eigen_assert(m_sparseLU->info() == Success && "The matrix should be factorized first");
0050     EIGEN_STATIC_ASSERT((Dest::Flags&RowMajorBit)==0,
0051                         THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0052 
0053 
0054     
0055     for(Index j = 0; j < B.cols(); ++j){
0056       X.col(j) = m_sparseLU->colsPermutation() * B.const_cast_derived().col(j);
0057     }
0058     
0059     m_sparseLU->matrixU().template solveTransposedInPlace<Conjugate>(X);
0060 
0061     
0062     m_sparseLU->matrixL().template solveTransposedInPlace<Conjugate>(X);
0063 
0064     
0065     for (Index j = 0; j < B.cols(); ++j)
0066       X.col(j) = m_sparseLU->rowsPermutation().transpose() * X.col(j);
0067     return true;
0068   }
0069   inline Index rows() const { return m_sparseLU->rows(); }
0070   inline Index cols() const { return m_sparseLU->cols(); }
0071 
0072 private:
0073   SparseLUType *m_sparseLU;
0074   SparseLUTransposeView& operator=(const SparseLUTransposeView&);
0075 };
0076 
0077 
0078 
0079 
0080 
0081 
0082 
0083 
0084 
0085 
0086 
0087 
0088 
0089 
0090 
0091 
0092 
0093 
0094 
0095 
0096 
0097 
0098 
0099 
0100 
0101 
0102 
0103 
0104 
0105 
0106 
0107 
0108 
0109 
0110 
0111 
0112 
0113 
0114 
0115 
0116 
0117 
0118 
0119 
0120 
0121 
0122 
0123 
0124 
0125 
0126 
0127 
0128 
0129 
0130 template <typename _MatrixType, typename _OrderingType>
0131 class SparseLU : public SparseSolverBase<SparseLU<_MatrixType,_OrderingType> >, public internal::SparseLUImpl<typename _MatrixType::Scalar, typename _MatrixType::StorageIndex>
0132 {
0133   protected:
0134     typedef SparseSolverBase<SparseLU<_MatrixType,_OrderingType> > APIBase;
0135     using APIBase::m_isInitialized;
0136   public:
0137     using APIBase::_solve_impl;
0138     
0139     typedef _MatrixType MatrixType; 
0140     typedef _OrderingType OrderingType;
0141     typedef typename MatrixType::Scalar Scalar; 
0142     typedef typename MatrixType::RealScalar RealScalar; 
0143     typedef typename MatrixType::StorageIndex StorageIndex;
0144     typedef SparseMatrix<Scalar,ColMajor,StorageIndex> NCMatrix;
0145     typedef internal::MappedSuperNodalMatrix<Scalar, StorageIndex> SCMatrix;
0146     typedef Matrix<Scalar,Dynamic,1> ScalarVector;
0147     typedef Matrix<StorageIndex,Dynamic,1> IndexVector;
0148     typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> PermutationType;
0149     typedef internal::SparseLUImpl<Scalar, StorageIndex> Base;
0150 
0151     enum {
0152       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0153       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0154     };
0155     
0156   public:
0157 
0158     SparseLU():m_lastError(""),m_Ustore(0,0,0,0,0,0),m_symmetricmode(false),m_diagpivotthresh(1.0),m_detPermR(1)
0159     {
0160       initperfvalues(); 
0161     }
0162     explicit SparseLU(const MatrixType& matrix)
0163       : m_lastError(""),m_Ustore(0,0,0,0,0,0),m_symmetricmode(false),m_diagpivotthresh(1.0),m_detPermR(1)
0164     {
0165       initperfvalues(); 
0166       compute(matrix);
0167     }
0168     
0169     ~SparseLU()
0170     {
0171       
0172     }
0173     
0174     void analyzePattern (const MatrixType& matrix);
0175     void factorize (const MatrixType& matrix);
0176     void simplicialfactorize(const MatrixType& matrix);
0177     
0178     
0179 
0180 
0181 
0182     void compute (const MatrixType& matrix)
0183     {
0184       
0185       analyzePattern(matrix); 
0186       
0187       factorize(matrix);
0188     } 
0189 
0190     
0191 
0192 
0193 
0194 
0195 
0196 
0197 
0198 
0199 
0200     const SparseLUTransposeView<false,SparseLU<_MatrixType,_OrderingType> > transpose()
0201     {
0202       SparseLUTransposeView<false,  SparseLU<_MatrixType,_OrderingType> > transposeView;
0203       transposeView.setSparseLU(this);
0204       transposeView.setIsInitialized(this->m_isInitialized);
0205       return transposeView;
0206     }
0207 
0208 
0209     
0210 
0211 
0212 
0213 
0214 
0215 
0216 
0217 
0218 
0219 
0220 
0221     const SparseLUTransposeView<true, SparseLU<_MatrixType,_OrderingType> > adjoint()
0222     {
0223       SparseLUTransposeView<true,  SparseLU<_MatrixType,_OrderingType> > adjointView;
0224       adjointView.setSparseLU(this);
0225       adjointView.setIsInitialized(this->m_isInitialized);
0226       return adjointView;
0227     }
0228     
0229     inline Index rows() const { return m_mat.rows(); }
0230     inline Index cols() const { return m_mat.cols(); }
0231     
0232     void isSymmetric(bool sym)
0233     {
0234       m_symmetricmode = sym;
0235     }
0236     
0237     
0238 
0239 
0240 
0241 
0242 
0243     SparseLUMatrixLReturnType<SCMatrix> matrixL() const
0244     {
0245       return SparseLUMatrixLReturnType<SCMatrix>(m_Lstore);
0246     }
0247     
0248 
0249 
0250 
0251 
0252 
0253     SparseLUMatrixUReturnType<SCMatrix,MappedSparseMatrix<Scalar,ColMajor,StorageIndex> > matrixU() const
0254     {
0255       return SparseLUMatrixUReturnType<SCMatrix, MappedSparseMatrix<Scalar,ColMajor,StorageIndex> >(m_Lstore, m_Ustore);
0256     }
0257 
0258     
0259 
0260 
0261 
0262     inline const PermutationType& rowsPermutation() const
0263     {
0264       return m_perm_r;
0265     }
0266     
0267 
0268 
0269 
0270     inline const PermutationType& colsPermutation() const
0271     {
0272       return m_perm_c;
0273     }
0274     
0275     void setPivotThreshold(const RealScalar& thresh)
0276     {
0277       m_diagpivotthresh = thresh; 
0278     }
0279 
0280 #ifdef EIGEN_PARSED_BY_DOXYGEN
0281     
0282 
0283 
0284 
0285 
0286 
0287     template<typename Rhs>
0288     inline const Solve<SparseLU, Rhs> solve(const MatrixBase<Rhs>& B) const;
0289 #endif 
0290     
0291     
0292 
0293 
0294 
0295 
0296 
0297 
0298 
0299     ComputationInfo info() const
0300     {
0301       eigen_assert(m_isInitialized && "Decomposition is not initialized.");
0302       return m_info;
0303     }
0304     
0305     
0306 
0307 
0308     std::string lastErrorMessage() const
0309     {
0310       return m_lastError; 
0311     }
0312 
0313     template<typename Rhs, typename Dest>
0314     bool _solve_impl(const MatrixBase<Rhs> &B, MatrixBase<Dest> &X_base) const
0315     {
0316       Dest& X(X_base.derived());
0317       eigen_assert(m_factorizationIsOk && "The matrix should be factorized first");
0318       EIGEN_STATIC_ASSERT((Dest::Flags&RowMajorBit)==0,
0319                         THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0320       
0321       
0322       
0323       X.resize(B.rows(),B.cols());
0324 
0325       
0326       for(Index j = 0; j < B.cols(); ++j)
0327         X.col(j) = rowsPermutation() * B.const_cast_derived().col(j);
0328       
0329       
0330       this->matrixL().solveInPlace(X);
0331       this->matrixU().solveInPlace(X);
0332       
0333       
0334       for (Index j = 0; j < B.cols(); ++j)
0335         X.col(j) = colsPermutation().inverse() * X.col(j);
0336       
0337       return true; 
0338     }
0339     
0340     
0341 
0342 
0343 
0344 
0345 
0346 
0347 
0348 
0349 
0350     Scalar absDeterminant()
0351     {
0352       using std::abs;
0353       eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
0354       
0355       Scalar det = Scalar(1.);
0356       
0357       
0358       for (Index j = 0; j < this->cols(); ++j)
0359       {
0360         for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
0361         {
0362           if(it.index() == j)
0363           {
0364             det *= abs(it.value());
0365             break;
0366           }
0367         }
0368       }
0369       return det;
0370     }
0371 
0372     
0373 
0374 
0375 
0376 
0377 
0378 
0379 
0380     Scalar logAbsDeterminant() const
0381     {
0382       using std::log;
0383       using std::abs;
0384 
0385       eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
0386       Scalar det = Scalar(0.);
0387       for (Index j = 0; j < this->cols(); ++j)
0388       {
0389         for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
0390         {
0391           if(it.row() < j) continue;
0392           if(it.row() == j)
0393           {
0394             det += log(abs(it.value()));
0395             break;
0396           }
0397         }
0398       }
0399       return det;
0400     }
0401 
0402     
0403 
0404 
0405 
0406     Scalar signDeterminant()
0407     {
0408       eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
0409       
0410       Index det = 1;
0411       
0412       
0413       for (Index j = 0; j < this->cols(); ++j)
0414       {
0415         for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
0416         {
0417           if(it.index() == j)
0418           {
0419             if(it.value()<0)
0420               det = -det;
0421             else if(it.value()==0)
0422               return 0;
0423             break;
0424           }
0425         }
0426       }
0427       return det * m_detPermR * m_detPermC;
0428     }
0429     
0430     
0431 
0432 
0433 
0434     Scalar determinant()
0435     {
0436       eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
0437       
0438       Scalar det = Scalar(1.);
0439       
0440       
0441       for (Index j = 0; j < this->cols(); ++j)
0442       {
0443         for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
0444         {
0445           if(it.index() == j)
0446           {
0447             det *= it.value();
0448             break;
0449           }
0450         }
0451       }
0452       return (m_detPermR * m_detPermC) > 0 ? det : -det;
0453     }
0454 
0455     Index nnzL() const { return m_nnzL; };
0456     Index nnzU() const { return m_nnzU; };
0457 
0458   protected:
0459     
0460     void initperfvalues()
0461     {
0462       m_perfv.panel_size = 16;
0463       m_perfv.relax = 1; 
0464       m_perfv.maxsuper = 128; 
0465       m_perfv.rowblk = 16; 
0466       m_perfv.colblk = 8; 
0467       m_perfv.fillfactor = 20;  
0468     }
0469       
0470     
0471     mutable ComputationInfo m_info;
0472     bool m_factorizationIsOk;
0473     bool m_analysisIsOk;
0474     std::string m_lastError;
0475     NCMatrix m_mat; 
0476     SCMatrix m_Lstore; 
0477     MappedSparseMatrix<Scalar,ColMajor,StorageIndex> m_Ustore; 
0478     PermutationType m_perm_c; 
0479     PermutationType m_perm_r ; 
0480     IndexVector m_etree; 
0481     
0482     typename Base::GlobalLU_t m_glu; 
0483                                
0484     
0485     bool m_symmetricmode;
0486     
0487     internal::perfvalues m_perfv;
0488     RealScalar m_diagpivotthresh; 
0489     Index m_nnzL, m_nnzU; 
0490     Index m_detPermR, m_detPermC; 
0491   private:
0492     
0493     SparseLU (const SparseLU& );
0494 }; 
0495 
0496 
0497 
0498 
0499 
0500 
0501 
0502 
0503 
0504 
0505 
0506 
0507 
0508 
0509 template <typename MatrixType, typename OrderingType>
0510 void SparseLU<MatrixType, OrderingType>::analyzePattern(const MatrixType& mat)
0511 {
0512   
0513   
0514   
0515   
0516   m_mat = mat;
0517   
0518   
0519   OrderingType ord; 
0520   ord(m_mat,m_perm_c);
0521   
0522   
0523   if (m_perm_c.size())
0524   {
0525     m_mat.uncompress(); 
0526     
0527     ei_declare_aligned_stack_constructed_variable(StorageIndex,outerIndexPtr,mat.cols()+1,mat.isCompressed()?const_cast<StorageIndex*>(mat.outerIndexPtr()):0);
0528     
0529     
0530     if(!mat.isCompressed()) 
0531       IndexVector::Map(outerIndexPtr, mat.cols()+1) = IndexVector::Map(m_mat.outerIndexPtr(),mat.cols()+1);
0532     
0533     
0534     for (Index i = 0; i < mat.cols(); i++)
0535     {
0536       m_mat.outerIndexPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i];
0537       m_mat.innerNonZeroPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i+1] - outerIndexPtr[i];
0538     }
0539   }
0540   
0541   
0542   IndexVector firstRowElt;
0543   internal::coletree(m_mat, m_etree,firstRowElt); 
0544      
0545   
0546   if (!m_symmetricmode) {
0547     IndexVector post, iwork; 
0548     
0549     internal::treePostorder(StorageIndex(m_mat.cols()), m_etree, post); 
0550       
0551    
0552     
0553     Index m = m_mat.cols(); 
0554     iwork.resize(m+1);
0555     for (Index i = 0; i < m; ++i) iwork(post(i)) = post(m_etree(i));
0556     m_etree = iwork;
0557     
0558     
0559     PermutationType post_perm(m); 
0560     for (Index i = 0; i < m; i++) 
0561       post_perm.indices()(i) = post(i); 
0562         
0563     
0564     if(m_perm_c.size()) {
0565       m_perm_c = post_perm * m_perm_c;
0566     }
0567     
0568   } 
0569   
0570   m_analysisIsOk = true; 
0571 }
0572 
0573 
0574 
0575 
0576 
0577 
0578 
0579 
0580 
0581 
0582 
0583 
0584 
0585 
0586 
0587 
0588 
0589 
0590 
0591 
0592 
0593 
0594 template <typename MatrixType, typename OrderingType>
0595 void SparseLU<MatrixType, OrderingType>::factorize(const MatrixType& matrix)
0596 {
0597   using internal::emptyIdxLU;
0598   eigen_assert(m_analysisIsOk && "analyzePattern() should be called first"); 
0599   eigen_assert((matrix.rows() == matrix.cols()) && "Only for squared matrices");
0600   
0601   m_isInitialized = true;
0602   
0603   
0604   
0605   m_mat = matrix;
0606   if (m_perm_c.size()) 
0607   {
0608     m_mat.uncompress(); 
0609     
0610     const StorageIndex * outerIndexPtr;
0611     if (matrix.isCompressed()) outerIndexPtr = matrix.outerIndexPtr();
0612     else
0613     {
0614       StorageIndex* outerIndexPtr_t = new StorageIndex[matrix.cols()+1];
0615       for(Index i = 0; i <= matrix.cols(); i++) outerIndexPtr_t[i] = m_mat.outerIndexPtr()[i];
0616       outerIndexPtr = outerIndexPtr_t;
0617     }
0618     for (Index i = 0; i < matrix.cols(); i++)
0619     {
0620       m_mat.outerIndexPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i];
0621       m_mat.innerNonZeroPtr()[m_perm_c.indices()(i)] = outerIndexPtr[i+1] - outerIndexPtr[i];
0622     }
0623     if(!matrix.isCompressed()) delete[] outerIndexPtr;
0624   } 
0625   else 
0626   { 
0627     m_perm_c.resize(matrix.cols());
0628     for(StorageIndex i = 0; i < matrix.cols(); ++i) m_perm_c.indices()(i) = i;
0629   }
0630   
0631   Index m = m_mat.rows();
0632   Index n = m_mat.cols();
0633   Index nnz = m_mat.nonZeros();
0634   Index maxpanel = m_perfv.panel_size * m;
0635   
0636   Index lwork = 0;
0637   Index info = Base::memInit(m, n, nnz, lwork, m_perfv.fillfactor, m_perfv.panel_size, m_glu); 
0638   if (info) 
0639   {
0640     m_lastError = "UNABLE TO ALLOCATE WORKING MEMORY\n\n" ;
0641     m_factorizationIsOk = false;
0642     return ; 
0643   }
0644   
0645   
0646   IndexVector segrep(m); segrep.setZero();
0647   IndexVector parent(m); parent.setZero();
0648   IndexVector xplore(m); xplore.setZero();
0649   IndexVector repfnz(maxpanel);
0650   IndexVector panel_lsub(maxpanel);
0651   IndexVector xprune(n); xprune.setZero();
0652   IndexVector marker(m*internal::LUNoMarker); marker.setZero();
0653   
0654   repfnz.setConstant(-1); 
0655   panel_lsub.setConstant(-1);
0656   
0657   
0658   ScalarVector dense; 
0659   dense.setZero(maxpanel);
0660   ScalarVector tempv; 
0661   tempv.setZero(internal::LUnumTempV(m, m_perfv.panel_size, m_perfv.maxsuper, m) );
0662   
0663   
0664   PermutationType iperm_c(m_perm_c.inverse()); 
0665   
0666   
0667   IndexVector relax_end(n);
0668   if ( m_symmetricmode == true ) 
0669     Base::heap_relax_snode(n, m_etree, m_perfv.relax, marker, relax_end);
0670   else
0671     Base::relax_snode(n, m_etree, m_perfv.relax, marker, relax_end);
0672   
0673   
0674   m_perm_r.resize(m); 
0675   m_perm_r.indices().setConstant(-1);
0676   marker.setConstant(-1);
0677   m_detPermR = 1; 
0678   
0679   m_glu.supno(0) = emptyIdxLU; m_glu.xsup.setConstant(0);
0680   m_glu.xsup(0) = m_glu.xlsub(0) = m_glu.xusub(0) = m_glu.xlusup(0) = Index(0);
0681   
0682   
0683   
0684   
0685   Index jcol; 
0686   Index pivrow; 
0687   Index nseg1; 
0688   Index nseg; 
0689   Index irep; 
0690   Index i, k, jj; 
0691   for (jcol = 0; jcol < n; )
0692   {
0693     
0694     Index panel_size = m_perfv.panel_size; 
0695     for (k = jcol + 1; k < (std::min)(jcol+panel_size, n); k++)
0696     {
0697       if (relax_end(k) != emptyIdxLU) 
0698       {
0699         panel_size = k - jcol; 
0700         break; 
0701       }
0702     }
0703     if (k == n) 
0704       panel_size = n - jcol; 
0705       
0706     
0707     Base::panel_dfs(m, panel_size, jcol, m_mat, m_perm_r.indices(), nseg1, dense, panel_lsub, segrep, repfnz, xprune, marker, parent, xplore, m_glu); 
0708     
0709     
0710     Base::panel_bmod(m, panel_size, jcol, nseg1, dense, tempv, segrep, repfnz, m_glu); 
0711     
0712     
0713     for ( jj = jcol; jj< jcol + panel_size; jj++) 
0714     {
0715       k = (jj - jcol) * m; 
0716       
0717       nseg = nseg1; 
0718       
0719       VectorBlock<IndexVector> panel_lsubk(panel_lsub, k, m);
0720       VectorBlock<IndexVector> repfnz_k(repfnz, k, m); 
0721       info = Base::column_dfs(m, jj, m_perm_r.indices(), m_perfv.maxsuper, nseg, panel_lsubk, segrep, repfnz_k, xprune, marker, parent, xplore, m_glu); 
0722       if ( info ) 
0723       {
0724         m_lastError =  "UNABLE TO EXPAND MEMORY IN COLUMN_DFS() ";
0725         m_info = NumericalIssue; 
0726         m_factorizationIsOk = false; 
0727         return; 
0728       }
0729       
0730       VectorBlock<ScalarVector> dense_k(dense, k, m); 
0731       VectorBlock<IndexVector> segrep_k(segrep, nseg1, m-nseg1); 
0732       info = Base::column_bmod(jj, (nseg - nseg1), dense_k, tempv, segrep_k, repfnz_k, jcol, m_glu); 
0733       if ( info ) 
0734       {
0735         m_lastError = "UNABLE TO EXPAND MEMORY IN COLUMN_BMOD() ";
0736         m_info = NumericalIssue; 
0737         m_factorizationIsOk = false; 
0738         return; 
0739       }
0740       
0741       
0742       info = Base::copy_to_ucol(jj, nseg, segrep, repfnz_k ,m_perm_r.indices(), dense_k, m_glu); 
0743       if ( info ) 
0744       {
0745         m_lastError = "UNABLE TO EXPAND MEMORY IN COPY_TO_UCOL() ";
0746         m_info = NumericalIssue; 
0747         m_factorizationIsOk = false; 
0748         return; 
0749       }
0750       
0751       
0752       info = Base::pivotL(jj, m_diagpivotthresh, m_perm_r.indices(), iperm_c.indices(), pivrow, m_glu);
0753       if ( info ) 
0754       {
0755         m_lastError = "THE MATRIX IS STRUCTURALLY SINGULAR ... ZERO COLUMN AT ";
0756         std::ostringstream returnInfo;
0757         returnInfo << info; 
0758         m_lastError += returnInfo.str();
0759         m_info = NumericalIssue; 
0760         m_factorizationIsOk = false; 
0761         return; 
0762       }
0763       
0764       
0765       
0766       if (pivrow != jj) m_detPermR = -m_detPermR;
0767 
0768       
0769       Base::pruneL(jj, m_perm_r.indices(), pivrow, nseg, segrep, repfnz_k, xprune, m_glu); 
0770       
0771       
0772       for (i = 0; i < nseg; i++)
0773       {
0774         irep = segrep(i); 
0775         repfnz_k(irep) = emptyIdxLU; 
0776       }
0777     } 
0778     jcol += panel_size;  
0779   } 
0780   
0781   m_detPermR = m_perm_r.determinant();
0782   m_detPermC = m_perm_c.determinant();
0783   
0784   
0785   Base::countnz(n, m_nnzL, m_nnzU, m_glu); 
0786   
0787   Base::fixupL(n, m_perm_r.indices(), m_glu);
0788   
0789   
0790   m_Lstore.setInfos(m, n, m_glu.lusup, m_glu.xlusup, m_glu.lsub, m_glu.xlsub, m_glu.supno, m_glu.xsup); 
0791   
0792   new (&m_Ustore) MappedSparseMatrix<Scalar, ColMajor, StorageIndex> ( m, n, m_nnzU, m_glu.xusub.data(), m_glu.usub.data(), m_glu.ucol.data() );
0793   
0794   m_info = Success;
0795   m_factorizationIsOk = true;
0796 }
0797 
0798 template<typename MappedSupernodalType>
0799 struct SparseLUMatrixLReturnType : internal::no_assignment_operator
0800 {
0801   typedef typename MappedSupernodalType::Scalar Scalar;
0802   explicit SparseLUMatrixLReturnType(const MappedSupernodalType& mapL) : m_mapL(mapL)
0803   { }
0804   Index rows() const { return m_mapL.rows(); }
0805   Index cols() const { return m_mapL.cols(); }
0806   template<typename Dest>
0807   void solveInPlace( MatrixBase<Dest> &X) const
0808   {
0809     m_mapL.solveInPlace(X);
0810   }
0811   template<bool Conjugate, typename Dest>
0812   void solveTransposedInPlace( MatrixBase<Dest> &X) const
0813   {
0814     m_mapL.template solveTransposedInPlace<Conjugate>(X);
0815   }
0816 
0817   const MappedSupernodalType& m_mapL;
0818 };
0819 
0820 template<typename MatrixLType, typename MatrixUType>
0821 struct SparseLUMatrixUReturnType : internal::no_assignment_operator
0822 {
0823   typedef typename MatrixLType::Scalar Scalar;
0824   SparseLUMatrixUReturnType(const MatrixLType& mapL, const MatrixUType& mapU)
0825   : m_mapL(mapL),m_mapU(mapU)
0826   { }
0827   Index rows() const { return m_mapL.rows(); }
0828   Index cols() const { return m_mapL.cols(); }
0829 
0830   template<typename Dest>   void solveInPlace(MatrixBase<Dest> &X) const
0831   {
0832     Index nrhs = X.cols();
0833     Index n    = X.rows();
0834     
0835     for (Index k = m_mapL.nsuper(); k >= 0; k--)
0836     {
0837       Index fsupc = m_mapL.supToCol()[k];
0838       Index lda = m_mapL.colIndexPtr()[fsupc+1] - m_mapL.colIndexPtr()[fsupc]; 
0839       Index nsupc = m_mapL.supToCol()[k+1] - fsupc;
0840       Index luptr = m_mapL.colIndexPtr()[fsupc];
0841 
0842       if (nsupc == 1)
0843       {
0844         for (Index j = 0; j < nrhs; j++)
0845         {
0846           X(fsupc, j) /= m_mapL.valuePtr()[luptr];
0847         }
0848       }
0849       else
0850       {
0851         
0852         Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
0853         Map< Matrix<Scalar,Dynamic,Dest::ColsAtCompileTime, ColMajor>, 0, OuterStride<> > U (&(X.coeffRef(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
0854         U = A.template triangularView<Upper>().solve(U);
0855       }
0856 
0857       for (Index j = 0; j < nrhs; ++j)
0858       {
0859         for (Index jcol = fsupc; jcol < fsupc + nsupc; jcol++)
0860         {
0861           typename MatrixUType::InnerIterator it(m_mapU, jcol);
0862           for ( ; it; ++it)
0863           {
0864             Index irow = it.index();
0865             X(irow, j) -= X(jcol, j) * it.value();
0866           }
0867         }
0868       }
0869     } 
0870   }
0871 
0872   template<bool Conjugate, typename Dest>   void solveTransposedInPlace(MatrixBase<Dest> &X) const
0873   {
0874     using numext::conj;
0875     Index nrhs = X.cols();
0876     Index n    = X.rows();
0877     
0878     for (Index k = 0; k <=  m_mapL.nsuper(); k++)
0879     {
0880       Index fsupc = m_mapL.supToCol()[k];
0881       Index lda = m_mapL.colIndexPtr()[fsupc+1] - m_mapL.colIndexPtr()[fsupc]; 
0882       Index nsupc = m_mapL.supToCol()[k+1] - fsupc;
0883       Index luptr = m_mapL.colIndexPtr()[fsupc];
0884 
0885       for (Index j = 0; j < nrhs; ++j)
0886       {
0887         for (Index jcol = fsupc; jcol < fsupc + nsupc; jcol++)
0888         {
0889           typename MatrixUType::InnerIterator it(m_mapU, jcol);
0890           for ( ; it; ++it)
0891           {
0892             Index irow = it.index();
0893             X(jcol, j) -= X(irow, j) * (Conjugate? conj(it.value()): it.value());
0894           }
0895         }
0896       }
0897       if (nsupc == 1)
0898       {
0899         for (Index j = 0; j < nrhs; j++)
0900         {
0901           X(fsupc, j) /= (Conjugate? conj(m_mapL.valuePtr()[luptr]) : m_mapL.valuePtr()[luptr]);
0902         }
0903       }
0904       else
0905       {
0906         Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
0907         Map< Matrix<Scalar,Dynamic,Dest::ColsAtCompileTime, ColMajor>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
0908         if(Conjugate)
0909           U = A.adjoint().template triangularView<Lower>().solve(U);
0910         else
0911           U = A.transpose().template triangularView<Lower>().solve(U);
0912       }
0913     }
0914   }
0915 
0916 
0917   const MatrixLType& m_mapL;
0918   const MatrixUType& m_mapU;
0919 };
0920 
0921 } 
0922 
0923 #endif