1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_ITERATIVE_SOLVER_BASE_H
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_ITERATIVE_SOLVER_BASE_H
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \ingroup IterativeLinearSolvers_Module
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \brief Base class for linear iterative solvers
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate< typename Derived>
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass IterativeSolverBase : internal::noncopyable
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic:
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename internal::traits<Derived>::MatrixType MatrixType;
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename internal::traits<Derived>::Preconditioner Preconditioner;
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Scalar Scalar;
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Index Index;
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::RealScalar RealScalar;
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathpublic:
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Derived& derived() { return *static_cast<Derived*>(this); }
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  const Derived& derived() const { return *static_cast<const Derived*>(this); }
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Default constructor. */
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  IterativeSolverBase()
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    : mp_matrix(0)
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    init();
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Initialize the solver with matrix \a A for further \c Ax=b solving.
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * This constructor is a shortcut for the default constructor followed
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * by a call to compute().
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * \warning this class stores a reference to the matrix A as well as some
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * precomputed values that depend on it. Therefore, if \a A is changed
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * this class becomes invalid. Call compute() to update it with the new
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * matrix A, or modify a copy of A.
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    */
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  IterativeSolverBase(const MatrixType& A)
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    init();
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    compute(A);
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ~IterativeSolverBase() {}
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Initializes the iterative solver for the sparcity pattern of the matrix \a A for further solving \c Ax=b problems.
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * Currently, this function mostly call analyzePattern on the preconditioner. In the future
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * we might, for instance, implement column reodering for faster matrix vector products.
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    */
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Derived& analyzePattern(const MatrixType& A)
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_preconditioner.analyzePattern(A);
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_isInitialized = true;
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_analysisIsOk = true;
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_info = Success;
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return derived();
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Initializes the iterative solver with the numerical values of the matrix \a A for further solving \c Ax=b problems.
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * Currently, this function mostly call factorize on the preconditioner.
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * \warning this class stores a reference to the matrix A as well as some
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * precomputed values that depend on it. Therefore, if \a A is changed
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * this class becomes invalid. Call compute() to update it with the new
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * matrix A, or modify a copy of A.
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    */
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Derived& factorize(const MatrixType& A)
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    mp_matrix = &A;
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_preconditioner.factorize(A);
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_factorizationIsOk = true;
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_info = Success;
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return derived();
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Initializes the iterative solver with the matrix \a A for further solving \c Ax=b problems.
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * Currently, this function mostly initialized/compute the preconditioner. In the future
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * we might, for instance, implement column reodering for faster matrix vector products.
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * \warning this class stores a reference to the matrix A as well as some
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * precomputed values that depend on it. Therefore, if \a A is changed
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * this class becomes invalid. Call compute() to update it with the new
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * matrix A, or modify a copy of A.
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    */
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Derived& compute(const MatrixType& A)
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    mp_matrix = &A;
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_preconditioner.compute(A);
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_isInitialized = true;
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_analysisIsOk = true;
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_factorizationIsOk = true;
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_info = Success;
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return derived();
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \internal */
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index rows() const { return mp_matrix ? mp_matrix->rows() : 0; }
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \internal */
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index cols() const { return mp_matrix ? mp_matrix->cols() : 0; }
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns the tolerance threshold used by the stopping criteria */
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  RealScalar tolerance() const { return m_tolerance; }
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Sets the tolerance threshold used by the stopping criteria */
1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Derived& setTolerance(const RealScalar& tolerance)
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_tolerance = tolerance;
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return derived();
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns a read-write reference to the preconditioner for custom configuration. */
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Preconditioner& preconditioner() { return m_preconditioner; }
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns a read-only reference to the preconditioner. */
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  const Preconditioner& preconditioner() const { return m_preconditioner; }
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns the max number of iterations */
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int maxIterations() const
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return (mp_matrix && m_maxIterations<0) ? mp_matrix->cols() : m_maxIterations;
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** Sets the max number of iterations */
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Derived& setMaxIterations(int maxIters)
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_maxIterations = maxIters;
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return derived();
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns the number of iterations performed during the last solve */
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int iterations() const
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_iterations;
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns the tolerance error reached during the last solve */
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  RealScalar error() const
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_error;
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * \sa compute()
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    */
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  template<typename Rhs> inline const internal::solve_retval<Derived, Rhs>
167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  solve(const MatrixBase<Rhs>& b) const
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized.");
170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(rows()==b.rows()
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              && "IterativeSolverBase::solve(): invalid number of rows of the right hand side matrix b");
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return internal::solve_retval<Derived, Rhs>(derived(), b.derived());
173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    *
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    * \sa compute()
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    */
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  template<typename Rhs>
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  inline const internal::sparse_solve_retval<IterativeSolverBase, Rhs>
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  solve(const SparseMatrixBase<Rhs>& b) const
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized.");
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(rows()==b.rows()
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath              && "IterativeSolverBase::solve(): invalid number of rows of the right hand side matrix b");
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return internal::sparse_solve_retval<IterativeSolverBase, Rhs>(*this, b.derived());
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \returns Success if the iterations converged, and NoConvergence otherwise. */
190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  ComputationInfo info() const
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized.");
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_info;
194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /** \internal */
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  template<typename Rhs, typename DestScalar, int DestOptions, typename DestIndex>
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  void _solve_sparse(const Rhs& b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(rows()==b.rows());
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int rhsCols = b.cols();
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int size = b.rows();
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Eigen::Matrix<DestScalar,Dynamic,1> tb(size);
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Eigen::Matrix<DestScalar,Dynamic,1> tx(size);
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for(int k=0; k<rhsCols; ++k)
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      tb = b.col(k);
209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      tx = derived().solve(tb);
210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      dest.col(k) = tx.sparseView(0);
211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathprotected:
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  void init()
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_isInitialized = false;
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_analysisIsOk = false;
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_factorizationIsOk = false;
220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_maxIterations = -1;
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_tolerance = NumTraits<Scalar>::epsilon();
222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  const MatrixType* mp_matrix;
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Preconditioner m_preconditioner;
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int m_maxIterations;
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  RealScalar m_tolerance;
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mutable RealScalar m_error;
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mutable int m_iterations;
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mutable ComputationInfo m_info;
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mutable bool m_isInitialized, m_analysisIsOk, m_factorizationIsOk;
233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Derived, typename Rhs>
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstruct sparse_solve_retval<IterativeSolverBase<Derived>, Rhs>
239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  : sparse_solve_retval_base<IterativeSolverBase<Derived>, Rhs>
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef IterativeSolverBase<Derived> Dec;
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs)
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  template<typename Dest> void evalTo(Dest& dst) const
245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    dec().derived()._solve_sparse(rhs(),dst);
247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace internal
251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_ITERATIVE_SOLVER_BASE_H
255