function [Z, W] = sphere2(X)
% SPHERE2: transforms the original data such that the mean is 0
% and the covariance is identity (de-correlates the variables).
% This function is designed for the case when then number of
% variables (columns of X) is higher than the number of samples.
%
% [Z,W] = sphere2(X)
%
% X - [n x m] matrix of n observations, each with m variables
% Z - [n x m] the transformed matrix
% W - [m x m] transformation matrix: Z = X * W

my_eps = 1e-8;

[n, m] = size(X); 
Xm = X - repmat(mean(X,1), [n, 1]);
Sg = Xm * Xm';
[V, L] = eig(Sg);        % eigenvectors by columns in V
d = diag(L);
[d, k] = sort(d, 'descend'); % from largest to smaller eigenvalue
V = V(:,k);

% recreate the values corresponding to eig(cov(X)):
V = Xm' * V;
d = d / (n-1);           

nv = sum(d > my_eps);    % number of large enough eigenvalues
for k=1:nv               % eigen-values/vectors are ordered
    V(:,k) = V(:,k) ./ norm(V(:,k),2);
end

% keep only the first nv vectors
V = V(:,1:nv);
d = d(1:nv);

d = 1 ./ sqrt(d);
W = V * diag(d); % by formula: (diag(d) * V')';
Z = X * W;

return
