function [p, q, w, b, t, u, x, y, l] = pls(a, c, maxrank)
% PLS   Calculate factors and coefficients for Partial Least Squares regression.
%
%         PLS calculates the factors and coefficents for the Partial
%         Least Squares regression analysis in latent variables.
%
%  [p, q, w, b] = pls(a, c, maxrank)    or,
%
%  [p, q, w, b, t, u, x, y, l] = pls(a, c, maxrank)
%
% Where:
%
%  p        is the matrix of spectral factors
%  q        is the matrix of concentration factors
%  w        is the matrix of weights
%  b        is the vector containing the inner relationships
%  t        is the matrix of spectral loadings
%  u        is the matrix of concentration loadings
%  x        is the matrix of spectral residuals
%  y        is the matrix of concentration residuals
%  l        is the vector containing the numbers of iterations required
%  a        is the training set absorbance matrix
%  c        is the training set concentration matrix
%  maxrank  is optional limit to the number of factors tested
%

% Copyright (c) 1989-92 by The MathWorks, Inc.

[i,j] = size(a);
k = 0;
x = a';
y = c';
if nargin == 3, i = maxrank; end
for h = 1:i,
	u(:,h) = y(:,1);
	told(:,h) = zeros(j,1);
	t(:,h) = ones(j,1);
	while (sum(abs(told(:,h)-t(:,h)))) > (1e-15) & k < 100
		told(:,h) = t(:,h);
		k = k + 1;
		w(h,:)  = u(:,h)' * x / (u(:,h)' * u(:,h));
		w(h,:)  =  w(h,:) / sqrt(sum(w(h,:) .* w(h,:)));
		t(:,h)  = x * w(h,:)' / (w(h,:) * w(h,:)');
		q(h,:) = t(:,h)' * y / (t(:,h)' * t(:,h));
		u(:,h)  = y * q(h,:)'/ (q(h,:) * q(h,:)');
	end
        l(h) = k;
	k = 0;
p(h,:) = t(:,h)' * x / (t(:,h)' * t(:,h));
p(h,:) = p(h,:) / sqrt(sum(p(h,:) .* p(h,:)));
t(:,h)  = t(:,h) /  sqrt(sum(p(h,:) .* p(h,:)));
w(h,:)  = w(h,:) /  sqrt(sum(p(h,:) .* p(h,:)));
b(h) = (u(:,h)' * t(:,h)) / (t(:,h)' * t(:,h));
x = x - (t(:,h) * p(h,:));
y = y - (b(h) * t(:,h) * q(h,:));
end
