function [B,varargout] = uniquewithequalnans(A,varargin)
%UNIQUEWITHEQUALNANS - Set unique, treating NaNs as equal
% B = UNIQUEWITHEQUALNANS(A) for the array A returns the same values as in A
% but with no repetitions. B will also be sorted (NaNs as last).
%
% UNIQUEWITHEQUALNANS(A,'rows') for the matrix A returns the unique rows
% of A, treating NaNs as equal.
%
% [B,I,J] = UNIQUEWITHEQUALNANS(...) also returns index vectors I and J such
% that B = A(I) and A = B(J) (or B = A(I,:) and A = B(J,:)).
%
% [B,I,J] = UNIQUEWITHEQUALNANS(...,'first') returns the vector I to
% index the first occurrence of each unique value in A.
% UNIQUEWITHEQUALNANS(...,'last'), the default, returns the vector I to
% index the last occurrence.
%
% Example:
% A = [1 2 NaN ; 1 2 NaN ; 1 2 NaN] ;
% unique(A,'rows')
% % -> [1 2 NaN ; 1 2 NaN ; 1 2 NaN] ;
% uniquewithequalnans(A,'rows')
% %-> [1 2 NaN]
%
% For a cell array of strings, this function behaves exactly like UNIQUE.
%
% See also UNIQUE, ISEQUALWITHNANS.
% for Matlab R13+
% version 2.0 (mar 2009)
% (c) Jos van der Geest
% email: jos@jasen.nl
% 1.0 (sep 2006) First release
% 2.0 (mar 2009) updated for recent ML releases that have a different
% syntax of unique
if nargin > 1,
try
% check the additional arguments that are passed to UNIQUE
unique(1,varargin{:}) ;
catch
msg = lasterr ;
error([upper(mfilename) ':ErrorUsingUnique'],msg) ;
end
end
if iscell(A) || ~any(isnan(A(:))),
% for cell arrays place a call to unique.
[B,varargout{1:nargout-1}] = unique(A,varargin{:}) ;
else
q = isnan(A(:)) ;
if sum(q) < 2,
% for 0 or 1 NaN, unique will do
[B,varargout{1:nargout-1}] = unique(A,varargin{:}) ;
else
% OK there are more than 1 NaNs
[C,C,C] = unique(A) ; % convert every element of A to a unique number C,
C(isnan(A)) = max(C)+1 ; % and give NaNs the same, but unique number
C = reshape(C,size(A)) ; % reshape back as A
% Now do unique on C (all NaNs are now the same number)
% and retrieve the index (and if requested, position as well)
[B,B,varargout{2:nargout-1}] = unique(C,varargin{:}) ;
if nargout > 1,
varargout{1} = B ; % index
% varargout{2} is the position
end
if any(strcmpi('rows',varargin))
B = A(B,:) ; % unique rows
else
B = A(B) ; % unique elements
end
end
end