function [x,k,res,negCurv] = cg(A,b,optTol,maxIter,verbose,precFunc,precArgs,matrixVectFunc,matrixVectArgs) % [x,k,res,negCurv] = % cg(A,b,optTol,maxIter,verbose,precFunc,precArgs,matrixVectFunc,matrixVect % Args) % Linear Conjugate Gradient, where optionally we use % - preconditioner on vector v with precFunc(v,precArgs{:}) % - matrix multipled by vector with matrixVectFunc(v,matrixVectArgs{:}) if nargin <= 4 verbose = 0; end x = zeros(size(b)); r = -b; % Apply preconditioner (if supplied) if nargin >= 7 && ~isempty(precFunc) y = precFunc(r,precArgs{:}); else y = r; end ry = r'*y; p = -y; k = 0; res = norm(r); done = 0; negCurv = []; while res > optTol & k < maxIter & ~done % Compute Matrix-vector product if nargin >= 9 Ap = matrixVectFunc(p,matrixVectArgs{:}); else Ap = A*p; end pAp = p'*Ap; % Check for negative Curvature if pAp <= 1e-16 if verbose fprintf('Negative Curvature Detected!\n'); end if nargout == 4 if pAp < 0 negCurv = p; return end end if k == 0 if verbose fprintf('First-Iter, Proceeding...\n'); end done = 1; else if verbose fprintf('Stopping\n'); end break; end end % Conjugate Gradient alpha = ry/(pAp); x = x + alpha*p; r = r + alpha*Ap; % If supplied, apply preconditioner if nargin >= 7 && ~isempty(precFunc) y = precFunc(r,precArgs{:}); else y = r; end ry_new = r'*y; beta = ry_new/ry; p = -y + beta*p; k = k + 1; % Update variables ry = ry_new; res = norm(r); end end