SparseSolverBase.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2014 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. #ifndef EIGEN_SPARSESOLVERBASE_H
  10. #define EIGEN_SPARSESOLVERBASE_H
  11. namespace Eigen {
  12. namespace internal {
  13. /** \internal
  14. * Helper functions to solve with a sparse right-hand-side and result.
  15. * The rhs is decomposed into small vertical panels which are solved through dense temporaries.
  16. */
  17. template<typename Decomposition, typename Rhs, typename Dest>
  18. typename enable_if<Rhs::ColsAtCompileTime!=1 && Dest::ColsAtCompileTime!=1>::type
  19. solve_sparse_through_dense_panels(const Decomposition &dec, const Rhs& rhs, Dest &dest)
  20. {
  21. EIGEN_STATIC_ASSERT((Dest::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
  22. typedef typename Dest::Scalar DestScalar;
  23. // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
  24. static const Index NbColsAtOnce = 4;
  25. Index rhsCols = rhs.cols();
  26. Index size = rhs.rows();
  27. // the temporary matrices do not need more columns than NbColsAtOnce:
  28. Index tmpCols = (std::min)(rhsCols, NbColsAtOnce);
  29. Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmp(size,tmpCols);
  30. Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmpX(size,tmpCols);
  31. for(Index k=0; k<rhsCols; k+=NbColsAtOnce)
  32. {
  33. Index actualCols = std::min<Index>(rhsCols-k, NbColsAtOnce);
  34. tmp.leftCols(actualCols) = rhs.middleCols(k,actualCols);
  35. tmpX.leftCols(actualCols) = dec.solve(tmp.leftCols(actualCols));
  36. dest.middleCols(k,actualCols) = tmpX.leftCols(actualCols).sparseView();
  37. }
  38. }
  39. // Overload for vector as rhs
  40. template<typename Decomposition, typename Rhs, typename Dest>
  41. typename enable_if<Rhs::ColsAtCompileTime==1 || Dest::ColsAtCompileTime==1>::type
  42. solve_sparse_through_dense_panels(const Decomposition &dec, const Rhs& rhs, Dest &dest)
  43. {
  44. typedef typename Dest::Scalar DestScalar;
  45. Index size = rhs.rows();
  46. Eigen::Matrix<DestScalar,Dynamic,1> rhs_dense(rhs);
  47. Eigen::Matrix<DestScalar,Dynamic,1> dest_dense(size);
  48. dest_dense = dec.solve(rhs_dense);
  49. dest = dest_dense.sparseView();
  50. }
  51. } // end namespace internal
  52. /** \class SparseSolverBase
  53. * \ingroup SparseCore_Module
  54. * \brief A base class for sparse solvers
  55. *
  56. * \tparam Derived the actual type of the solver.
  57. *
  58. */
  59. template<typename Derived>
  60. class SparseSolverBase : internal::noncopyable
  61. {
  62. public:
  63. /** Default constructor */
  64. SparseSolverBase()
  65. : m_isInitialized(false)
  66. {}
  67. ~SparseSolverBase()
  68. {}
  69. Derived& derived() { return *static_cast<Derived*>(this); }
  70. const Derived& derived() const { return *static_cast<const Derived*>(this); }
  71. /** \returns an expression of the solution x of \f$ A x = b \f$ using the current decomposition of A.
  72. *
  73. * \sa compute()
  74. */
  75. template<typename Rhs>
  76. inline const Solve<Derived, Rhs>
  77. solve(const MatrixBase<Rhs>& b) const
  78. {
  79. eigen_assert(m_isInitialized && "Solver is not initialized.");
  80. eigen_assert(derived().rows()==b.rows() && "solve(): invalid number of rows of the right hand side matrix b");
  81. return Solve<Derived, Rhs>(derived(), b.derived());
  82. }
  83. /** \returns an expression of the solution x of \f$ A x = b \f$ using the current decomposition of A.
  84. *
  85. * \sa compute()
  86. */
  87. template<typename Rhs>
  88. inline const Solve<Derived, Rhs>
  89. solve(const SparseMatrixBase<Rhs>& b) const
  90. {
  91. eigen_assert(m_isInitialized && "Solver is not initialized.");
  92. eigen_assert(derived().rows()==b.rows() && "solve(): invalid number of rows of the right hand side matrix b");
  93. return Solve<Derived, Rhs>(derived(), b.derived());
  94. }
  95. #ifndef EIGEN_PARSED_BY_DOXYGEN
  96. /** \internal default implementation of solving with a sparse rhs */
  97. template<typename Rhs,typename Dest>
  98. void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
  99. {
  100. internal::solve_sparse_through_dense_panels(derived(), b.derived(), dest.derived());
  101. }
  102. #endif // EIGEN_PARSED_BY_DOXYGEN
  103. protected:
  104. mutable bool m_isInitialized;
  105. };
  106. } // end namespace Eigen
  107. #endif // EIGEN_SPARSESOLVERBASE_H