0001 function out = uniquetol(in, tol, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 if ischar(in) && strcmp(in,'UNIT_TEST'); do_unit_test; return; end
0021
0022 DEBUG = eidors_debug('query','eidors:uniquetol');
0023
0024 if DEBUG==1 || exist('uniquetol','builtin')
0025 if DEBUG; disp('using builtin uniquetol'); end
0026 out = builtin('uniquetol',in, tol, varargin{:});
0027 return;
0028 end
0029
0030
0031 if length(varargin)<4
0032 error('ByRows and DataScale must be provided')
0033 end
0034 for i=1:2:length(varargin);
0035 switch varargin{i}
0036 case 'ByRows'
0037 if ~varargin{i+1}; error('Only support the ByRows option'); end
0038 case 'DataScale'
0039 if varargin{i+1}~=1; error('DataScale must by 1'); end
0040 otherwise
0041 error('Option %s not supported',varargin{i});
0042 end
0043 end
0044
0045 out = eidors_uniquetol(in, tol);
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 function out = eidors_uniquetol(in, tol)
0077
0078 out = unique(in,'rows');
0079
0080
0081 nRows = size(out,1);
0082 if nRows <= 1
0083 return
0084 end
0085 idx = nchoosek(1:nRows,2);
0086
0087
0088 d = out(idx(:,1),:) - out(idx(:,2),:);
0089 d = abs(d) <= tol;
0090
0091 same = all(d,2);
0092
0093 legacy = false; try unique([],'legacy'); catch, legacy = true; end
0094
0095
0096 if legacy
0097 [~,ii] = unique(idx(same,2),'first');
0098 else
0099 [~,ii] = unique(idx(same,2));
0100 end
0101 jj = find(same);
0102 ii = jj(ii);
0103
0104 out(idx(ii,2),:) = out(idx(ii,1),:);
0105
0106
0107 out = unique(out,'rows');
0108
0109
0110
0111
0112
0113 function [z,ii,jj] = uniquetol_repl(x,tol,varargin)
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 if size(x,1) == 1, x = x(:); end
0130 if nargin < 2 || isempty(tol) || tol == 0
0131 [z,ii,jj] = unique(x,varargin{:});
0132 return;
0133 end
0134 [y,ii,jj] = unique(x,varargin{:});
0135 if size(x,2) > 1
0136 [~,ord] = sort(sum(x.^2,1),2,'descend');
0137 [y,io] = sortrows(y,ord);
0138 [~,jo] = sort(io);
0139 ii = ii(io);
0140 jj = jo(jj);
0141 end
0142 d = sum(abs(diff(y,1,1)),2);
0143
0144 isTol = [true;d > tol];
0145 z = y(isTol,:);
0146 bin = cumsum(isTol);
0147 jj = bin(jj);
0148 ii = ii(isTol);
0149
0150
0151
0152 function do_unit_test
0153 testvec{1} = [1 2; 1.06 2; 1.1 2; 1.1 2.03];
0154 testvec{2} = [ ...
0155 -0.488223373148967243473350663407, ...
0156 -0.488223373148967243473350663407, ...
0157 -0.488223373148967243473350663407, ...
0158 -0.488223373148967243473350663407, ...
0159 -0.488223373148967243473350663407, ...
0160 -0.488223373148967243473350663407;
0161 -0.999999999999999666933092612453, ...
0162 -0.999999999999999888977697537484, ...
0163 -0.999999999999999888977697537484, ...
0164 -0.999999999999999888977697537484, ...
0165 -0.999999999999999888977697537484, ...
0166 -0.905678339894304240687006313237;
0167 -0.232963663178817920185181833403, ...
0168 -0.232963663178818003451908680290, ...
0169 -0.116481831589409029481529955774, ...
0170 -0.232963663178818086718635527177, ...
0171 -0.116481831589409043359317763588, ...
0172 -0.156131398552380479261003642932]';
0173 testvec{3} = testvec{2}';
0174 testvec{4} = [100,200;106,200;112,202;113,205;113,200;113,201;113,204;113,204;110,200;110,203]/100;
0175
0176
0177 for i=1:length(testvec)
0178 eidors_msg('TEST%d============',i,1);
0179 x = testvec{i};
0180 for tol = logspace(-4,1,6);
0181 uu = uniquetol(x,tol,'ByRows',true,'DataScale',1);
0182 ur = uniquetol_repl(x,tol,'rows','first');
0183 ue = eidors_uniquetol(x,tol);
0184 fprintf('Testing for tol=%f\n',tol);
0185
0186 unit_test_cmp('um=ue ',uu,ue,tol/2);
0187 end
0188 end