File indexing completed on 2025-04-19 09:06:42
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