12b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This file is part of Eigen, a lightweight C++ template library 22b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// for linear algebra. 32b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// 42b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr> 52b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// 62b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This Source Code Form is subject to the terms of the Mozilla 72b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Public License v. 2.0. If a copy of the MPL was not distributed 82b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 92b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#ifndef EIGEN_LEAST_SQUARE_CONJUGATE_GRADIENT_H 112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#define EIGEN_LEAST_SQUARE_CONJUGATE_GRADIENT_H 122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangnamespace Eigen { 142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangnamespace internal { 162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang/** \internal Low-level conjugate gradient algorithm for least-square problems 182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \param mat The matrix A 192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \param rhs The right hand side vector b 202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \param x On input and initial solution, on output the computed solution. 212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \param precond A preconditioner being able to efficiently solve for an 222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * approximation of A'Ax=b (regardless of b) 232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \param iters On input the max number of iteration, on output the number of performed iterations. 242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \param tol_error On input the tolerance error, on output an estimation of the relative error. 252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang */ 262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate<typename MatrixType, typename Rhs, typename Dest, typename Preconditioner> 272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao WangEIGEN_DONT_INLINE 282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangvoid least_square_conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, 292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang const Preconditioner& precond, Index& iters, 302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typename Dest::RealScalar& tol_error) 312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{ 322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using std::sqrt; 332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using std::abs; 342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef typename Dest::RealScalar RealScalar; 352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef typename Dest::Scalar Scalar; 362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef Matrix<Scalar,Dynamic,1> VectorType; 372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar tol = tol_error; 392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang Index maxIters = iters; 402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang Index m = mat.rows(), n = mat.cols(); 422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang VectorType residual = rhs - mat * x; 442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang VectorType normal_residual = mat.adjoint() * residual; 452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar rhsNorm2 = (mat.adjoint()*rhs).squaredNorm(); 472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang if(rhsNorm2 == 0) 482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang { 492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang x.setZero(); 502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang iters = 0; 512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang tol_error = 0; 522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang return; 532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang } 542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar threshold = tol*tol*rhsNorm2; 552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar residualNorm2 = normal_residual.squaredNorm(); 562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang if (residualNorm2 < threshold) 572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang { 582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang iters = 0; 592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang tol_error = sqrt(residualNorm2 / rhsNorm2); 602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang return; 612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang } 622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang VectorType p(n); 642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang p = precond.solve(normal_residual); // initial search direction 652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang VectorType z(n), tmp(m); 672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar absNew = numext::real(normal_residual.dot(p)); // the square of the absolute value of r scaled by invM 682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang Index i = 0; 692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang while(i < maxIters) 702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang { 712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang tmp.noalias() = mat * p; 722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang Scalar alpha = absNew / tmp.squaredNorm(); // the amount we travel on dir 742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang x += alpha * p; // update solution 752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang residual -= alpha * tmp; // update residual 762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang normal_residual = mat.adjoint() * residual; // update residual of the normal equation 772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang residualNorm2 = normal_residual.squaredNorm(); 792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang if(residualNorm2 < threshold) 802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang break; 812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang z = precond.solve(normal_residual); // approximately solve for "A'A z = normal_residual" 832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar absOld = absNew; 852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang absNew = numext::real(normal_residual.dot(z)); // update the absolute value of r 862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang RealScalar beta = absNew / absOld; // calculate the Gram-Schmidt value used to create the new search direction 872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang p = z + beta * p; // update search direction 882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang i++; 892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang } 902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang tol_error = sqrt(residualNorm2 / rhsNorm2); 912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang iters = i; 922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} 932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} 952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate< typename _MatrixType, 972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typename _Preconditioner = LeastSquareDiagonalPreconditioner<typename _MatrixType::Scalar> > 982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangclass LeastSquaresConjugateGradient; 992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangnamespace internal { 1012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate< typename _MatrixType, typename _Preconditioner> 1032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstruct traits<LeastSquaresConjugateGradient<_MatrixType,_Preconditioner> > 1042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{ 1052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef _MatrixType MatrixType; 1062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef _Preconditioner Preconditioner; 1072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}; 1082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} 1102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang/** \ingroup IterativeLinearSolvers_Module 1122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \brief A conjugate gradient solver for sparse (or dense) least-square problems 1132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * This class allows to solve for A x = b linear problems using an iterative conjugate gradient algorithm. 1152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * The matrix A can be non symmetric and rectangular, but the matrix A' A should be positive-definite to guaranty stability. 1162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * Otherwise, the SparseLU or SparseQR classes might be preferable. 1172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * The matrix A and the vectors x and b can be either dense or sparse. 1182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \tparam _MatrixType the type of the matrix A, can be a dense or a sparse matrix. 1202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \tparam _Preconditioner the type of the preconditioner. Default is LeastSquareDiagonalPreconditioner 1212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \implsparsesolverconcept 1232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations() 1252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations 1262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * and NumTraits<Scalar>::epsilon() for the tolerance. 1272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * This class can be used as the direct solver classes. Here is a typical usage example: 1292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang \code 1302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang int m=1000000, n = 10000; 1312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang VectorXd x(n), b(m); 1322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang SparseMatrix<double> A(m,n); 1332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang // fill A and b 1342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang LeastSquaresConjugateGradient<SparseMatrix<double> > lscg; 1352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang lscg.compute(A); 1362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang x = lscg.solve(b); 1372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang std::cout << "#iterations: " << lscg.iterations() << std::endl; 1382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang std::cout << "estimated error: " << lscg.error() << std::endl; 1392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang // update b, and solve again 1402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang x = lscg.solve(b); 1412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang \endcode 1422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * By default the iterations start with x=0 as an initial guess of the solution. 1442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * One can control the start using the solveWithGuess() method. 1452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \sa class ConjugateGradient, SparseLU, SparseQR 1472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang */ 1482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate< typename _MatrixType, typename _Preconditioner> 1492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangclass LeastSquaresConjugateGradient : public IterativeSolverBase<LeastSquaresConjugateGradient<_MatrixType,_Preconditioner> > 1502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{ 1512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef IterativeSolverBase<LeastSquaresConjugateGradient> Base; 1522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using Base::matrix; 1532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using Base::m_error; 1542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using Base::m_iterations; 1552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using Base::m_info; 1562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using Base::m_isInitialized; 1572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangpublic: 1582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef _MatrixType MatrixType; 1592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef typename MatrixType::Scalar Scalar; 1602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef typename MatrixType::RealScalar RealScalar; 1612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typedef _Preconditioner Preconditioner; 1622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangpublic: 1642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang /** Default constructor. */ 1662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang LeastSquaresConjugateGradient() : Base() {} 1672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang /** Initialize the solver with matrix \a A for further \c Ax=b solving. 1692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * This constructor is a shortcut for the default constructor followed 1712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * by a call to compute(). 1722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * 1732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * \warning this class stores a reference to the matrix A as well as some 1742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * precomputed values that depend on it. Therefore, if \a A is changed 1752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * this class becomes invalid. Call compute() to update it with the new 1762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * matrix A, or modify a copy of A. 1772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang */ 1782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang template<typename MatrixDerived> 1792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang explicit LeastSquaresConjugateGradient(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {} 1802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang ~LeastSquaresConjugateGradient() {} 1822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang /** \internal */ 1842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang template<typename Rhs,typename Dest> 1852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang void _solve_with_guess_impl(const Rhs& b, Dest& x) const 1862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang { 1872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang m_iterations = Base::maxIterations(); 1882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang m_error = Base::m_tolerance; 1892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang for(Index j=0; j<b.cols(); ++j) 1912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang { 1922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang m_iterations = Base::maxIterations(); 1932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang m_error = Base::m_tolerance; 1942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang typename Dest::ColXpr xj(x,j); 1962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang internal::least_square_conjugate_gradient(matrix(), b.col(j), xj, Base::m_preconditioner, m_iterations, m_error); 1972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang } 1982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 1992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang m_isInitialized = true; 2002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang m_info = m_error <= Base::m_tolerance ? Success : NoConvergence; 2012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang } 2022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 2032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang /** \internal */ 2042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang using Base::_solve_impl; 2052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang template<typename Rhs,typename Dest> 2062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang void _solve_impl(const MatrixBase<Rhs>& b, Dest& x) const 2072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang { 2082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang x.setZero(); 2092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang _solve_with_guess_impl(b.derived(),x); 2102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang } 2112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 2122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}; 2132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 2142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} // end namespace Eigen 2152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang 2162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif // EIGEN_LEAST_SQUARE_CONJUGATE_GRADIENT_H 217