aboutsummaryrefslogtreecommitdiffhomepage
path: root/unsupported/Eigen
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2011-09-17 10:54:14 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2011-09-17 10:54:14 +0200
commit9053729d68b681abc2190eb27e174e3c88dcff83 (patch)
treef22cde5bc63b8040dddfa12d2ef6412f2db036d2 /unsupported/Eigen
parentf4122e9f94795ce768dd67269f821b9664585aca (diff)
add a bi conjugate gradient stabilized solver
Diffstat (limited to 'unsupported/Eigen')
-rw-r--r--unsupported/Eigen/IterativeSolvers2
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/BiCGSTAB.h275
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/ConjugateGradient.h144
-rw-r--r--unsupported/Eigen/src/IterativeSolvers/IterativeSolverBase.h176
4 files changed, 480 insertions, 117 deletions
diff --git a/unsupported/Eigen/IterativeSolvers b/unsupported/Eigen/IterativeSolvers
index e690b0300..2a06ded1a 100644
--- a/unsupported/Eigen/IterativeSolvers
+++ b/unsupported/Eigen/IterativeSolvers
@@ -43,10 +43,12 @@ namespace Eigen {
#include "../../Eigen/src/misc/Solve.h"
+#include "src/IterativeSolvers/IterativeSolverBase.h"
#include "src/IterativeSolvers/IterationController.h"
#include "src/IterativeSolvers/ConstrainedConjGrad.h"
#include "src/IterativeSolvers/BasicPreconditioners.h"
#include "src/IterativeSolvers/ConjugateGradient.h"
+#include "src/IterativeSolvers/BiCGSTAB.h"
//@}
diff --git a/unsupported/Eigen/src/IterativeSolvers/BiCGSTAB.h b/unsupported/Eigen/src/IterativeSolvers/BiCGSTAB.h
new file mode 100644
index 000000000..4f365bd96
--- /dev/null
+++ b/unsupported/Eigen/src/IterativeSolvers/BiCGSTAB.h
@@ -0,0 +1,275 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_BICGSTAB_H
+#define EIGEN_BICGSTAB_H
+
+namespace internal {
+
+/** \internal Low-level bi conjugate gradient stabilized algorithm
+ * \param mat The matrix A
+ * \param rhs The right hand side vector b
+ * \param x On input and initial solution, on output the computed solution.
+ * \param precond A preconditioner being able to efficiently solve for an
+ * approximation of Ax=b (regardless of b)
+ * \param iters On input the max number of iteration, on output the number of performed iterations.
+ * \param tol_error On input the tolerance error, on output an estimation of the relative error.
+ */
+template<typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
+void bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
+ const Preconditioner& precond, int& iters,
+ typename Dest::RealScalar& tol_error)
+{
+ using std::sqrt;
+ using std::abs;
+ typedef typename Dest::RealScalar RealScalar;
+ typedef typename Dest::Scalar Scalar;
+ typedef Dest VectorType;
+
+ RealScalar tol = tol_error;
+ int maxIters = iters;
+
+ int n = mat.cols();
+ VectorType r = rhs - mat * x;
+ VectorType r0 = r;
+ RealScalar r0_sqnorm = r0.squaredNorm();
+ Scalar rho = 1;
+ Scalar alpha = 1;
+ Scalar w = 1;
+
+ VectorType v = VectorType::Zero(n), p = VectorType::Zero(n);
+ VectorType y(n), z(n);
+ VectorType kt(n), ks(n);
+
+ VectorType s(n), t(n);
+
+ RealScalar tol2 = tol*tol;
+ int i = 0;
+
+ do
+ {
+ Scalar rho_old = rho;
+
+ rho = r0.dot(r);
+ Scalar beta = (rho/rho_old) * (alpha / w);
+ p = r + beta * (p - w * v);
+
+ y = precond.solve(p);
+ v.noalias() = mat * y;
+
+ alpha = rho / r0.dot(v);
+ s = r - alpha * v;
+
+ z = precond.solve(s);
+ t.noalias() = mat * z;
+
+ kt = precond.solve(t);
+ ks = precond.solve(s);
+
+ w = kt.dot(ks) / kt.squaredNorm();
+ x += alpha * y + w * z;
+ r = s - w * t;
+ ++i;
+ } while ( r.squaredNorm()/r0_sqnorm > tol2 && i<maxIters );
+
+ tol_error = sqrt(r.squaredNorm()/r0_sqnorm);
+ //tol_error = sqrt(abs(absNew / absInit));
+ iters = i;
+}
+
+}
+
+template< typename _MatrixType,
+ typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> >
+class BiCGSTAB;
+
+namespace internal {
+
+template<typename CG, typename Rhs, typename Guess>
+class bicgstab_solve_retval_with_guess;
+
+template< typename _MatrixType, typename _Preconditioner>
+struct traits<BiCGSTAB<_MatrixType,_Preconditioner> >
+{
+ typedef _MatrixType MatrixType;
+ typedef _Preconditioner Preconditioner;
+};
+
+}
+
+/** \brief A bi conjugate gradient stabilized solver for sparse square problems
+ *
+ * This class allows to solve for A.x = b sparse linear problems using a bi conjugate gradient
+ * stabilized algorithm. The vectors x and b can be either dense or sparse.
+ *
+ * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
+ * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
+ *
+ * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
+ * and setTolerance() methods. The default are 1000 max iterations and NumTraits<Scalar>::epsilon()
+ * for the tolerance.
+ *
+ * This class can be used as the direct solver classes. Here is a typical usage example:
+ * \code
+ * int n = 10000;
+ * VectorXd x(n), b(n);
+ * SparseMatrix<double> A(n,n);
+ * // fill A and b
+ * BiCGSTAB<SparseMatrix<double> > solver;
+ * solver(A);
+ * x = solver.solve(b);
+ * std::cout << "#iterations: " << solver.iterations() << std::endl;
+ * std::cout << "estimated error: " << solver.error() << std::endl;
+ * // update b, and solve again
+ * x = solver.solve(b);
+ * \endcode
+ *
+ * By default the iterations start with x=0 as an initial guess of the solution.
+ * One can control the start using the solveWithGuess() method. Here is a step by
+ * step execution example starting with a random guess and printing the evolution
+ * of the estimated error:
+ * * \code
+ * x = VectorXd::Random(n);
+ * solver.setMaxIterations(1);
+ * int i = 0;
+ * do {
+ * x = solver.solveWithGuess(b,x);
+ * std::cout << i << " : " << solver.error() << std::endl;
+ * ++i;
+ * } while (solver.info()!=Success && i<100);
+ * \endcode
+ * Note that such a step by step excution is slightly slower.
+ *
+ * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
+ */
+template< typename _MatrixType, typename _Preconditioner>
+class BiCGSTAB : public IterativeSolverBase<BiCGSTAB<_MatrixType,_Preconditioner> >
+{
+ typedef IterativeSolverBase<BiCGSTAB> Base;
+ using Base::mp_matrix;
+ using Base::m_error;
+ using Base::m_iterations;
+ using Base::m_info;
+ using Base::m_isInitialized;
+public:
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef _Preconditioner Preconditioner;
+
+public:
+
+ /** Default constructor. */
+ BiCGSTAB() : Base() {}
+
+ /** Initialize the solver with matrix \a A for further \c Ax=b solving.
+ *
+ * This constructor is a shortcut for the default constructor followed
+ * by a call to compute().
+ *
+ * \warning this class stores a reference to the matrix A as well as some
+ * precomputed values that depend on it. Therefore, if \a A is changed
+ * this class becomes invalid. Call compute() to update it with the new
+ * matrix A, or modify a copy of A.
+ */
+ BiCGSTAB(const MatrixType& A) : Base(A) {}
+
+ ~BiCGSTAB() {}
+
+ /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
+ * \a x0 as an initial solution.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs,typename Guess>
+ inline const internal::bicgstab_solve_retval_with_guess<BiCGSTAB, Rhs, Guess>
+ solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const
+ {
+ eigen_assert(m_isInitialized && "BiCGSTAB is not initialized.");
+ eigen_assert(Base::rows()==b.rows()
+ && "BiCGSTAB::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::bicgstab_solve_retval_with_guess
+ <BiCGSTAB, Rhs, Guess>(*this, b.derived(), x0);
+ }
+
+ /** \internal */
+ template<typename Rhs,typename Dest>
+ void _solve(const Rhs& b, Dest& x) const
+ {
+ m_iterations = Base::m_maxIterations;
+ m_error = Base::m_tolerance;
+
+ internal::bicgstab(*mp_matrix, b, x, Base::m_preconditioner, m_iterations, m_error);
+
+ m_isInitialized = true;
+ m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
+ }
+
+protected:
+
+};
+
+
+namespace internal {
+
+ template<typename _MatrixType, typename _Preconditioner, typename Rhs>
+struct solve_retval<BiCGSTAB<_MatrixType, _Preconditioner>, Rhs>
+ : solve_retval_base<BiCGSTAB<_MatrixType, _Preconditioner>, Rhs>
+{
+ typedef BiCGSTAB<_MatrixType, _Preconditioner> Dec;
+ EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dst.setZero();
+ dec()._solve(rhs(),dst);
+ }
+};
+
+template<typename CG, typename Rhs, typename Guess>
+class bicgstab_solve_retval_with_guess
+ : public solve_retval_base<CG, Rhs>
+{
+ typedef Eigen::internal::solve_retval_base<CG,Rhs> Base;
+ using Base::dec;
+ using Base::rhs;
+ public:
+ bicgstab_solve_retval_with_guess(const CG& cg, const Rhs& rhs, const Guess& guess)
+ : Base(cg, rhs), m_guess(guess)
+ {}
+
+ template<typename Dest> void evalTo(Dest& dst) const
+ {
+ dst = m_guess;
+ dec()._solve(rhs(), dst);
+ }
+ protected:
+ const Guess& m_guess;
+
+};
+
+}
+
+#endif // EIGEN_BICGSTAB_H
diff --git a/unsupported/Eigen/src/IterativeSolvers/ConjugateGradient.h b/unsupported/Eigen/src/IterativeSolvers/ConjugateGradient.h
index f1bed1116..0b0b4955b 100644
--- a/unsupported/Eigen/src/IterativeSolvers/ConjugateGradient.h
+++ b/unsupported/Eigen/src/IterativeSolvers/ConjugateGradient.h
@@ -83,11 +83,22 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x,
}
+template< typename _MatrixType, int _UpLo=Lower,
+ typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> >
+class ConjugateGradient;
+
namespace internal {
template<typename CG, typename Rhs, typename Guess>
class conjugate_gradient_solve_retval_with_guess;
+template< typename _MatrixType, int _UpLo, typename _Preconditioner>
+struct traits<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
+{
+ typedef _MatrixType MatrixType;
+ typedef _Preconditioner Preconditioner;
+};
+
}
/** \brief A conjugate gradient solver for sparse self-adjoint problems
@@ -137,10 +148,15 @@ class conjugate_gradient_solve_retval_with_guess;
*
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
*/
-template< typename _MatrixType, int _UpLo=Lower,
- typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> >
-class ConjugateGradient
+template< typename _MatrixType, int _UpLo, typename _Preconditioner>
+class ConjugateGradient : public IterativeSolverBase<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
{
+ typedef IterativeSolverBase<ConjugateGradient> Base;
+ using Base::mp_matrix;
+ using Base::m_error;
+ using Base::m_iterations;
+ using Base::m_info;
+ using Base::m_isInitialized;
public:
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
@@ -155,11 +171,7 @@ public:
public:
/** Default constructor. */
- ConjugateGradient()
- : mp_matrix(0)
- {
- init();
- }
+ ConjugateGradient() : Base() {}
/** Initialize the solver with matrix \a A for further \c Ax=b solving.
*
@@ -171,90 +183,10 @@ public:
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
- ConjugateGradient(const MatrixType& A)
- {
- init();
- compute(A);
- }
+ ConjugateGradient(const MatrixType& A) : Base(A) {}
~ConjugateGradient() {}
-
- /** Initializes the iterative solver with the matrix \a A for further solving \c Ax=b problems.
- *
- * Currently, this function mostly initialized/compute the preconditioner. In the future
- * we might, for instance, implement column reodering for faster matrix vector products.
- *
- * \warning this class stores a reference to the matrix A as well as some
- * precomputed values that depend on it. Therefore, if \a A is changed
- * this class becomes invalid. Call compute() to update it with the new
- * matrix A, or modify a copy of A.
- */
- ConjugateGradient& compute(const MatrixType& A)
- {
- mp_matrix = &A;
- m_preconditioner.compute(A);
- m_isInitialized = true;
- return *this;
- }
-
- /** \internal */
- Index rows() const { return mp_matrix->rows(); }
- /** \internal */
- Index cols() const { return mp_matrix->cols(); }
-
- /** \returns the tolerance threshold used by the stopping criteria */
- RealScalar tolerance() const { return m_tolerance; }
- /** Sets the tolerance threshold used by the stopping criteria */
- ConjugateGradient& setTolerance(RealScalar tolerance)
- {
- m_tolerance = tolerance;
- return *this;
- }
-
- /** \returns a read-write reference to the preconditioner for custom configuration. */
- Preconditioner& preconditioner() { return m_preconditioner; }
-
- /** \returns a read-only reference to the preconditioner. */
- const Preconditioner& preconditioner() const { return m_preconditioner; }
-
- /** \returns the max number of iterations */
- int maxIterations() const { return m_maxIterations; }
-
- /** Sets the max number of iterations */
- ConjugateGradient& setMaxIterations(int maxIters)
- {
- m_maxIterations = maxIters;
- return *this;
- }
-
- /** \returns the number of iterations performed during the last solve */
- int iterations() const
- {
- eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
- return m_iterations;
- }
-
- /** \returns the tolerance error reached during the last solve */
- RealScalar error() const
- {
- eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
- return m_error;
- }
-
- /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
- *
- * \sa compute()
- */
- template<typename Rhs> inline const internal::solve_retval<ConjugateGradient, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
- eigen_assert(rows()==b.rows()
- && "ConjugateGradient::solve(): invalid number of rows of the right hand side matrix b");
- return internal::solve_retval<ConjugateGradient, Rhs>(*this, b.derived());
- }
-
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
* \a x0 as an initial solution.
*
@@ -265,50 +197,28 @@ public:
solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const
{
eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
- eigen_assert(rows()==b.rows()
+ eigen_assert(Base::rows()==b.rows()
&& "ConjugateGradient::solve(): invalid number of rows of the right hand side matrix b");
return internal::conjugate_gradient_solve_retval_with_guess
<ConjugateGradient, Rhs, Guess>(*this, b.derived(), x0);
}
-
- /** \returns Success if the iterations converged, and NoConvergence otherwise. */
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
- return m_info;
- }
-
+
/** \internal */
template<typename Rhs,typename Dest>
void _solve(const Rhs& b, Dest& x) const
{
- m_iterations = m_maxIterations;
- m_error = m_tolerance;
+ m_iterations = Base::m_maxIterations;
+ m_error = Base::m_tolerance;
internal::conjugate_gradient(mp_matrix->template selfadjointView<UpLo>(), b, x,
- m_preconditioner, m_iterations, m_error);
+ Base::m_preconditioner, m_iterations, m_error);
m_isInitialized = true;
- m_info = m_error <= m_tolerance ? Success : NoConvergence;
+ m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
}
protected:
- void init()
- {
- m_isInitialized = false;
- m_maxIterations = 1000;
- m_tolerance = NumTraits<Scalar>::epsilon();
- }
- const MatrixType* mp_matrix;
- Preconditioner m_preconditioner;
- int m_maxIterations;
- RealScalar m_tolerance;
-
- mutable RealScalar m_error;
- mutable int m_iterations;
- mutable ComputationInfo m_info;
- mutable bool m_isInitialized;
};
diff --git a/unsupported/Eigen/src/IterativeSolvers/IterativeSolverBase.h b/unsupported/Eigen/src/IterativeSolvers/IterativeSolverBase.h
new file mode 100644
index 000000000..6d25f5aea
--- /dev/null
+++ b/unsupported/Eigen/src/IterativeSolvers/IterativeSolverBase.h
@@ -0,0 +1,176 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ITERATIVE_SOLVER_BASE_H
+#define EIGEN_ITERATIVE_SOLVER_BASE_H
+
+
+/** \brief Base class for linear iterative solvers
+ *
+ * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
+ */
+template< typename Derived>
+class IterativeSolverBase
+{
+public:
+ typedef typename internal::traits<Derived>::MatrixType MatrixType;
+ typedef typename internal::traits<Derived>::Preconditioner Preconditioner;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ typedef typename MatrixType::RealScalar RealScalar;
+
+public:
+
+ Derived& derived() { return *static_cast<Derived*>(this); }
+ const Derived& derived() const { return *static_cast<const Derived*>(this); }
+
+ /** Default constructor. */
+ IterativeSolverBase()
+ : mp_matrix(0)
+ {
+ init();
+ }
+
+ /** Initialize the solver with matrix \a A for further \c Ax=b solving.
+ *
+ * This constructor is a shortcut for the default constructor followed
+ * by a call to compute().
+ *
+ * \warning this class stores a reference to the matrix A as well as some
+ * precomputed values that depend on it. Therefore, if \a A is changed
+ * this class becomes invalid. Call compute() to update it with the new
+ * matrix A, or modify a copy of A.
+ */
+ IterativeSolverBase(const MatrixType& A)
+ {
+ init();
+ compute(A);
+ }
+
+ ~IterativeSolverBase() {}
+
+ /** Initializes the iterative solver with the matrix \a A for further solving \c Ax=b problems.
+ *
+ * Currently, this function mostly initialized/compute the preconditioner. In the future
+ * we might, for instance, implement column reodering for faster matrix vector products.
+ *
+ * \warning this class stores a reference to the matrix A as well as some
+ * precomputed values that depend on it. Therefore, if \a A is changed
+ * this class becomes invalid. Call compute() to update it with the new
+ * matrix A, or modify a copy of A.
+ */
+ Derived& compute(const MatrixType& A)
+ {
+ mp_matrix = &A;
+ m_preconditioner.compute(A);
+ m_isInitialized = true;
+ return derived();
+ }
+
+ /** \internal */
+ Index rows() const { return mp_matrix->rows(); }
+ /** \internal */
+ Index cols() const { return mp_matrix->cols(); }
+
+ /** \returns the tolerance threshold used by the stopping criteria */
+ RealScalar tolerance() const { return m_tolerance; }
+
+ /** Sets the tolerance threshold used by the stopping criteria */
+ Derived& setTolerance(RealScalar tolerance)
+ {
+ m_tolerance = tolerance;
+ return derived();
+ }
+
+ /** \returns a read-write reference to the preconditioner for custom configuration. */
+ Preconditioner& preconditioner() { return m_preconditioner; }
+
+ /** \returns a read-only reference to the preconditioner. */
+ const Preconditioner& preconditioner() const { return m_preconditioner; }
+
+ /** \returns the max number of iterations */
+ int maxIterations() const { return m_maxIterations; }
+
+ /** Sets the max number of iterations */
+ Derived& setMaxIterations(int maxIters)
+ {
+ m_maxIterations = maxIters;
+ return derived();
+ }
+
+ /** \returns the number of iterations performed during the last solve */
+ int iterations() const
+ {
+ eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
+ return m_iterations;
+ }
+
+ /** \returns the tolerance error reached during the last solve */
+ RealScalar error() const
+ {
+ eigen_assert(m_isInitialized && "ConjugateGradient is not initialized.");
+ return m_error;
+ }
+
+ /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
+ *
+ * \sa compute()
+ */
+ template<typename Rhs> inline const internal::solve_retval<Derived, Rhs>
+ solve(const MatrixBase<Rhs>& b) const
+ {
+ eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized.");
+ eigen_assert(rows()==b.rows()
+ && "IterativeSolverBase::solve(): invalid number of rows of the right hand side matrix b");
+ return internal::solve_retval<Derived, Rhs>(derived(), b.derived());
+ }
+
+ /** \returns Success if the iterations converged, and NoConvergence otherwise. */
+ ComputationInfo info() const
+ {
+ eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized.");
+ return m_info;
+ }
+
+protected:
+ void init()
+ {
+ m_isInitialized = false;
+ m_maxIterations = 1000;
+ m_tolerance = NumTraits<Scalar>::epsilon();
+ }
+ const MatrixType* mp_matrix;
+ Preconditioner m_preconditioner;
+
+ int m_maxIterations;
+ RealScalar m_tolerance;
+
+ mutable RealScalar m_error;
+ mutable int m_iterations;
+ mutable ComputationInfo m_info;
+ mutable bool m_isInitialized;
+};
+
+
+#endif // EIGEN_ITERATIVE_SOLVER_BASE_H