uniquetol

PURPOSE ^

C = uniquetol(A,TOL): unique values in A using tolerance TOL.

SYNOPSIS ^

function out = uniquetol(in, tol, varargin)

DESCRIPTION ^

 C = uniquetol(A,TOL):  unique values in A using tolerance TOL.
 For recent versions (>=2015a) call built in function. Otherwise
 find a alternate solve, using either different matlab builtin
 functions, or the uniquetol provided by code (C) Siyi Deng 2010.

 Only provides the functions of 
   C = uniquetol(A,tol,'ByRows',true,'DataScale',1);

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function out = uniquetol(in, tol, varargin)
0002 % C = uniquetol(A,TOL):  unique values in A using tolerance TOL.
0003 % For recent versions (>=2015a) call built in function. Otherwise
0004 % find a alternate solve, using either different matlab builtin
0005 % functions, or the uniquetol provided by code (C) Siyi Deng 2010.
0006 %
0007 % Only provides the functions of
0008 %   C = uniquetol(A,tol,'ByRows',true,'DataScale',1);
0009 
0010 % (C) Andy Adler 2015 Licenced under GPL v2 or v3
0011 % $Id: uniquetol.m 6127 2021-09-02 11:56:08Z bgrychtol $
0012 
0013 if ischar(in) && strcmp(in,'UNIT_TEST'); do_unit_test; return; end
0014 
0015 DEBUG = eidors_debug('query','eidors:uniquetol');
0016 
0017 if DEBUG==1 || exist('uniquetol','builtin')
0018    if DEBUG;   disp('using builtin uniquetol'); end
0019    out = builtin('uniquetol',in, tol, varargin{:});
0020    return;
0021 end
0022 
0023 % Now we provide a backup, but only if byrows and Datascale
0024 if length(varargin)<4
0025    error('ByRows and DataScale must be provided')
0026 end
0027 for i=1:2:length(varargin);
0028    switch varargin{i}
0029      case 'ByRows'
0030        if ~varargin{i+1};   error('Only support the ByRows option'); end
0031      case 'DataScale'
0032        if varargin{i+1}~=1; error('DataScale must by 1'); end
0033      otherwise 
0034        error('Option %s not supported',varargin{i});
0035    end
0036 end
0037 
0038 out = eidors_uniquetol(in, tol);
0039 
0040 
0041 %Fom code by
0042 % Siyi Deng; 03-19-2010; 05-15-2010; 10-29-2010;
0043 
0044 % Licence:
0045 % Copyright (c) 2010, Siyi Deng
0046 % All rights reserved.
0047 %
0048 % Redistribution and use in source and binary forms, with or without
0049 % modification, are permitted provided that the following conditions are
0050 % met:
0051 %
0052 %     * Redistributions of source code must retain the above copyright
0053 %       notice, this list of conditions and the following disclaimer.
0054 %     * Redistributions in binary form must reproduce the above copyright
0055 %       notice, this list of conditions and the following disclaimer in
0056 %       the documentation and/or other materials provided with the distribution
0057 %
0058 % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0059 % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0060 % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0061 % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0062 % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0063 % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0064 % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0065 % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0066 % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0067 % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0068 % POSSIBILITY OF SUCH DAMAGE.
0069 function out = eidors_uniquetol(in, tol)
0070 % first run unique
0071 out = unique(in,'rows');
0072 
0073 % all pairwise combinations
0074 nRows = size(out,1);
0075 if nRows <= 1
0076    return
0077 end
0078 idx = nchoosek(1:nRows,2);
0079 
0080 % compare each column individually
0081 d = out(idx(:,1),:) - out(idx(:,2),:);
0082 d = abs(d) <= tol;
0083 
0084 same = all(d,2);
0085 
0086 legacy = false; try unique([],'legacy'); catch, legacy = true; end
0087    
0088 % replace each equal row with the first match
0089 if legacy
0090    [~,ii] = unique(idx(same,2),'first');
0091 else
0092    [~,ii] = unique(idx(same,2));
0093 end
0094 jj = find(same);
0095 ii = jj(ii);
0096 
0097 out(idx(ii,2),:) = out(idx(ii,1),:);
0098 
0099 % run unique to eliminate the now exactly matching rows
0100 out = unique(out,'rows');
0101       
0102 
0103 
0104 
0105 
0106 function [z,ii,jj] = uniquetol_repl(x,tol,varargin)
0107 %UNIQUETOL Unique element within a tolerance.
0108 %   [Y,I,J] = UNIQUETOL(X,TOL) is very similar to UNIQUE, but allows an
0109 %   additional tolerance input, TOL. TOL can be taken as the total absolute
0110 %   difference between similar elements. TOL must be a none negative
0111 %   scalar. If not provided, TOL is assumed to be 0, which makes UNIQUETOL
0112 %   identical to UNIQUE.
0113 %
0114 %   UNIQUETOL(...,'ROWS')
0115 %   UNIQUETOL(...,'FIRST')
0116 %   UNIQUETOL(...,'LAST')
0117 %   These expressions are identical to the UNIQUE counterparts.
0118 %
0119 %   See also UNIQUE.
0120 
0121 
0122 if size(x,1) == 1, x = x(:); end
0123 if nargin < 2 || isempty(tol) || tol == 0
0124     [z,ii,jj] = unique(x,varargin{:});
0125     return;
0126 end
0127 [y,ii,jj] = unique(x,varargin{:});
0128 if size(x,2) > 1
0129     [~,ord] = sort(sum(x.^2,1),2,'descend');
0130     [y,io] = sortrows(y,ord);
0131     [~,jo] = sort(io);
0132     ii = ii(io);
0133     jj = jo(jj);
0134 end
0135 d = sum(abs(diff(y,1,1)),2);
0136 
0137 isTol = [true;d > tol];
0138 z = y(isTol,:);
0139 bin = cumsum(isTol); % [n,bin] = histc(y,z);
0140 jj = bin(jj);
0141 ii = ii(isTol);
0142 
0143 % UNIQUETOL;
0144    
0145 function do_unit_test
0146    testvec{1} = [1 2; 1.06 2; 1.1 2; 1.1 2.03];
0147    testvec{2} = [ ...
0148    -0.488223373148967243473350663407, ...
0149    -0.488223373148967243473350663407, ...
0150    -0.488223373148967243473350663407, ...
0151    -0.488223373148967243473350663407, ...
0152    -0.488223373148967243473350663407, ...
0153    -0.488223373148967243473350663407;
0154    -0.999999999999999666933092612453, ...
0155    -0.999999999999999888977697537484, ...
0156    -0.999999999999999888977697537484, ...
0157    -0.999999999999999888977697537484, ...
0158    -0.999999999999999888977697537484, ...
0159    -0.905678339894304240687006313237;
0160    -0.232963663178817920185181833403, ...
0161    -0.232963663178818003451908680290, ...
0162    -0.116481831589409029481529955774, ...
0163    -0.232963663178818086718635527177, ...
0164    -0.116481831589409043359317763588, ...
0165    -0.156131398552380479261003642932]';
0166    testvec{3} = testvec{2}';
0167 
0168 
0169    for i=1:length(testvec)
0170      eidors_msg('TEST%d============',i,1);
0171      x = testvec{i};
0172       for tol = logspace(-4,1,6);
0173          uu = uniquetol(x,tol,'ByRows',true,'DataScale',1);
0174          ur = uniquetol_repl(x,tol,'rows','first');
0175          ue = eidors_uniquetol(x,tol);
0176          fprintf('Testing for tol=%f\n',tol);
0177          unit_test_cmp('uu=ur (not used)',uu,ur);
0178          unit_test_cmp('um=ue           ',uu,ue);
0179       end
0180    end

Generated on Fri 30-Dec-2022 19:44:54 by m2html © 2005