function [c, xm, xc] = nancov(x, flag);
%NANCOV Sample covariance matrix of available data, ignoring NaNs.
%
% NANCOV(X) returns the covariance matrix of X estimated from all
% available data in X, ignoring NaN-elements that indicate missing
% values. If X is a vector, NANCOV(X) returns the variance. For
% matrices, where each row is an observation and each column a
% variable, NANCOV(X) is the covariance matrix estimate from all
% available data.
%
% NANCOV(X) normalizes each covariance matrix element by (Nt-1)
% where Nt is the number of available product terms contributing to
% the covariance matrix element.
%
% NANCOV(X,0) normalizes by Nt and produces the second moment
% matrix of the observations about their mean. NANCOV(X,1) is the
% same as NANCOV(X).
%
% If all terms in the sum of the product and/or cross-product terms
% contributing to a covariance matrix element are missing, the
% covariance matrix element is set to zero.
%
% Because the covariance matrix elements are normalized with
% different normalization factors, depending on how many terms
% contribute to them, the covariance matrix is not necessarily
% positive semidefinite.
%
% [C, M, XC] = NANCOV(X) returns the covariance matrix estimate
% C from all available data, the mean M of the available data,
% and the centered data matrix XC with the mean removed from
% each column.
%
% See also COV, CENTER, NANSTD, NANMEAN, NANSUM.
error(nargchk(1,2,nargin)) % check number of input arguments
if isempty(x) % check for empty input.
sx = NaN;
return
end
if ndims(x) > 2, error('Data must be vector or 2-D array.'); end
if nargin < 2, flag = 1; end % default: normalize by nt-1
if length(x)==prod(size(x)) % if x is vector, make sure
x = x(:); % it is a row vector
end
% center data
[xc,xm] = center(x);
[m,n] = size(xc);
% replace NaNs with zeros.
inan = find(isnan(xc));
xc(inan)= zeros(size(inan));
nonnan = ones(m,n); % indicator matrix showing where there
nonnan(inan) = zeros(size(inan)); % are non-missing elements in xc
nt = nonnan' * nonnan - flag; % normalization factor for each
% covariance matrix element
% set covariance to 0 when there are no terms to form sum
k = find(nt < 1);
nt(k) = 1;
c = xc' * xc ./ nt;