function [RV,NR,POS,IR]=repval(varargin)
%REPVAL Repeated Values
% repval(X) finds all repeated values for input X, and their attributes.
% The input may be vector, matrix, char string, or cell of strings
%
% Y=repval(X) returns the repeated values of X
%
% [RV, NR, POS, IR]=repval(X) returns the following outputs
% RV : Repeated Values (sorted)
% NR : Number of times each RV was repeated
% POS : Position vector of X of RV entries
% IR : Index of repetition
%
% Example:
% X=[1 5 5 9 5 5 1];
% [RV,NR,POS,IR]=repval(X)
% Output:
% RV = [1 5]; %Numbers '1' and '5' are repeated values
% NR = [2 4]; %Respectively repeated 2 and 4 times
% POS = [1 7 2 3 5 6]; %Position index of X for repeated values
% IR = [1 1 2 2 2 2]; %Corresponding to which index of RV
%
% Vectors
% [RV,NR,POS,IR]=repval([1 2 2 3 2 2 1])
%
% Matrix (repeated rows)
% [RV,NR,POS,IR]=repval([1 2; 3 4; 1 2; 1 3; 3 4])
%
% Char String
% [RV,NR,POS,IR]=repval('abracadabra')
%
% Cell of Strings
% [RV,NR,POS,IR]=repval({'bat','cat','car','bar','bat','car'})
%
% Mike Sheppard
% Last Modified: 13-Dec-2010
%Initialize in case empty set
RV=[]; NR=[]; IR=[]; POS=[];
v=varargin{:};
if ~isempty(v)
if all(size(v)>1)
[B,ignore,J]=unique(v,'rows'); %matrix, sort by rows
else
[B,ignore,J]=unique(v);
end
[Y,I]=sort(J);
I2=find(diff(Y)==0);
B2=unique([I2(:)',I2(:)'+1]);
[B3,ignore,IR]=unique(Y(B2));
if ~isempty(IR)
NR=hist(IR,IR(end));
POS=I(B2);
if all(size(v)>1)
RV=B(B3,:); %matrix, sort by rows
else
RV=B(B3);
end
end
end
%Turn output into column vector
NR=NR(:); IR=IR(:); POS=POS(:);
if ~all(size(v)>1), RV=RV(:); end %Non-matrices
end
%Credit:
%Basic concept of code by J.S. on 7 Dec, 2001 for vectors
%http://www.mathworks.com/matlabcentral/newsreader/view_thread/30051
%Expanded code to include matrices, chars, and cell of strings