function [x, p, f]=numunique(x)
%NUMUNIQUE Numerical set unique.
% [B P F]=numunique(A) for the array A returns the same values as in A but
% with no repetitions. B will also be sorted. A can only be numerical, 
% as the name of the function suggests.
%
% The second output, P, is a row of cells, containing the indices of A, 
% such that, A(p{n})=B(n) is true. P has the same number of cells as the 
% number of elements in B.
%
% Note that each cell of P lists all the indices of A, not only the first 
% or last occurrence, which have the repetitious values. It is this nature
% of the second output makes this function different to the Mathwork's
% function UNIQUE. Sometimes we need to know all the indices of which A 
% have the same values. 
% 
% The third optional output, F, is for the indices of the first occurrences
% of repetitious values, so that B==A(F) is true.
%
% Example, let  A = [1 1 5 6 2 3 3 9 8 6 2 4], then
%            [B P F]=numunique(A)
% results in 
%            B =[1 2 3 4 5 6 8 9],
% P = 
%  [1x2 double] [1x2 double] [1x2 double]  [12]  [3]  [1x2 double] [9] [8]
% and
% F =
%    1     5     6    12     3     4     9     8
%
% Check for the second element B for example, P{2}=[5 11],
% A([5 11])=[2 2], which are all equal to B(2). And of course, B-A(F) 
% gives all 0's.
% 
% Note that the first output can be a row or column vector depends on the
% input is a row vector or otherwise (column or matrix). However the second
% output P is always a row of cells. To force P in a row order has an
% advantage, so that you can get A sorted with a shortcut of A([P{:}]).
%
% See also UNIQUE
%
% Zhigang Xu. 02-Sep-2009. Updated on 05-Sep-2009.

isrowvec=size(x,1)==1;

if nargout<=1
	x=sort(x(:));
	n=[true; diff(x)~=0];
	x=x(n);
	if isrowvec, x=x.'; end
	return
end

[x s]=sort(x(:));
s=s.';
N=numel(x);
n=find([true; diff(x)~=0]);
x=x(n);
K=numel(x);
if isrowvec, x=x.'; end

switch(nargout)
	case{2}
		if K==1
			p{1}=s;
		else
			p{K}=s(n(K):N);
			for k=1:K-1
				p{k}=s(n(k):n(k+1)-1);
			end
		end
	case{3}
		if K==1
			p{1}=s;
			f(1)=p{1}(1);
		else
			p{K}=s(n(K):N);
			f(K)=p{K}(1);
			for k=1:K-1
				p{k}=s(n(k):n(k+1)-1);
				f(k)=p{k}(1);
			end
		end
	otherwise
		error('More than 3 outputs are not allowed!')
end
end
