% centroid.m
% Moody T. Chu
%
% Slightly modified by Jason R. Blevins
%
% $Id: centroid.m,v 1.3 2004/07/15 19:21:56 jrblevin Exp $


function [B,V,Z] = centroid(A);

num_iteration = 100;

[n,m] = size(A);

Aold = A;
B = [];
V = [];
Cv = [];
Z = [];

p = rank(A);
%% p = 100;

%% flops(0)

for i = 1:min(p,num_iteration)
   [A_next,z,b,v,npmu] = new_decom(A);
   B = [B,b];
   Z = [Z,z];
   V = [V,v];
   Cv = [Cv,npmu];
   A = A_next;
end
%% disp('Total flops used = '),flops

% Note that Rold = R_next + Z*inv(diag(S))*Z';
%
% Note also that S/n is the approximate singular value

function [A_next,z,b,v,npmu] = new_decom(A);
%
% This code is for Algorithm 8.1
%
% Input:
%
%		A = indexing matrix (n-by-m)
%
% Output:
%
%		npmu = n*(centroid values)
%		v = centroid factors
%		b = loadings
%

[n,m] = size(A);
tol = eps*max([n,m]);

for i = 1:n
   d(i,1) = norm(A(i,:))^2;				% diagonal of AA'
end

% this is the start value

z = ones(n,1);
k = 1;
w = A'*z;

while ~isempty(k)
   
   e = d - sign(z).*(A*w);				% Step 1
   [y,k] = max(e);					% Step 2
   
   if y > 0 & abs(y) > tol    
      z(k) = -z(k);					% Step 3
      if z(k) == 1					% Step 4
         w = w + 2*A(k,:)';
      else
         w = w - 2*A(k,:)';
      end
   else
      k = [];
   end
end

npmu = w'*w;
v = w/sqrt(npmu);					% Centroid factors
b = A*v;						% Loadings
A_next = A - b*v';
