%% Using Function Handle Instead of Numeric Matrix
% Solve a linear system by providing pcg with a function handle that computes A*x in place of the coefficient matrix A.
%
% Use gallery to generate a 20-by-20 positive definite tridiagonal matrix. The super- and subdiagonals have ones, while the main diagonal elements count down from 20 to 1. Preview the matrix.

n = 20;
A = gallery('tridiag',ones(n-1,1),n:-1:1,ones(n-1,1));
full(A)

%
% Since this tridiagonal matrix has a special structure, you can represent the operation A*x with a function handle. When A multiplies a vector, most of the elements in the resulting vector are zeros. The nonzero elements in the result correspond with the nonzero tridiagonal elements of A. Moreover, only the main diagonal has nonzeros that are not equal to 1.
% The expression \textrm{Ax} becomes:
% \left\lbrack \begin{array}{cccccccccc}
% 20 & 1 & 0 & \cdots  &  & \cdots  &  & \cdots  & 0 & 0\\
% 1 & 19 & 1 & 0 &  &  &  &  &  & 0\\
% 0 & 1 & 18 & 1 & 0 &  &  &  &  & \vdots \\
% \vdots  & 0 & 1 & 17 & 1 & 0 &  &  &  & \\
%  &  & 0 & 1 & 16 & 1 & 0 &  &  & \vdots \\
% \vdots  &  &  & 0 & 1 & 15 & 1 & 0 &  & \\
%  &  &  &  & 0 & 1 & 14 & 1 & 0 & \vdots \\
% \vdots  &  &  &  &  & 0 & 1 & 13 & \ddots  & 0\\
% 0 &  &  &  &  &  & 0 & \ddots  & \ddots  & 1\\
% 0 & 0 & \cdots  &  & \cdots  &  & \cdots  & 0 & 1 & 1
% \end{array}\right\rbrack \left\lbrack \begin{array}{c}
% x_1 \\
% x_2 \\
% x_3 \\
% x_4 \\
% x_5 \\
% \vdots \\
% \\
% \vdots \\
% \\
% x_{20}
% \end{array}\right\rbrack =\left\lbrack \begin{array}{c}
% 2{0x}_1 +x_2 \\
% x_1 +19x_2 +x_3 \\
% x_2 +18x_3 +x_4 \\
% \vdots \\
% x_{18} +2x_{19} +x_{20} \\
% x_{19} +x_{20\;}
% \end{array}\right\rbrack.
% The resulting vector can be written as the sum of three vectors:
% \left\lbrack \begin{array}{c}
% 2{0x}_1 +x_2 \\
% x_1 +19x_2 +x_3 \\
% x_2 +18x_3 +x_4 \\
% \vdots \\
% x_{18} +2x_{19} +x_{20} \\
% x_{19} +x_{20\;}
% \end{array}\right\rbrack=\left\lbrack \begin{array}{c}
% 0\\
% x_1 \\
% \vdots \\
% x_{19}
% \end{array}\right\rbrack +\left\lbrack \begin{array}{c}
% 20x_1 \\
% 19x_2 \\
% \vdots \\
% x_{20}
% \end{array}\right\rbrack +\left\lbrack \begin{array}{c}
% x_2 \\
% \vdots \\
% x_{20} \\
% 0
% \end{array}\right\rbrack.
% In MATLAB®, write a function that creates these vectors and adds them together, thus giving the value of A*x:
% function y = afun(x)
% y = [0; x(1:19)] + ...
%     [(20:-1:1)'].*x + ...
%     [x(2:20); 0];
% end
% (This function is saved as a local function at the end of the example.)
%
% Now, solve the linear system \textrm{Ax}=b by providing pcg with the function handle that calculates A*x. Use a tolerance of 1e-12 and 50 iterations.

b = ones(20,1);
tol = 1e-12;  
maxit = 50;
x1 = pcg(@afun,b,tol,maxit)

%
% Check that afun(x1) produces a vector of ones.

afun(x1)

%
%% Local Functions

function y = afun(x)
y = [0; x(1:19)] + ...
    [(20:-1:1)'].*x + ...
    [x(2:20); 0];
end

% Copyright 2019 The MathWorks, Inc.
%
%
%
%
%