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 5124 2015-06-20 13:33:53Z bgrychtol $
0012 
0013 if ischar(in) && strcmp(in,'UNIT_TEST'); do_unit_test; return; end
0014 DEBUG = 0; % IF == ## then only this test
0015 
0016 if (~DEBUG && exist('uniquetol','builtin')) || (DEBUG == 1)
0017    if DEBUG;   disp('using builtin uniquetol'); end
0018    out = builtin('uniquetol',in, tol, varargin{:});
0019    return;
0020 end
0021 
0022 % Now we provide a backup, but only if byrows and Datascale
0023 if length(varargin)<4
0024    error('ByRows and DataScale must be provided')
0025 end
0026 for i=1:2:length(varargin);
0027    switch varargin{i}
0028      case 'ByRows'
0029        if ~varargin{i+1};   error('Only support the ByRows option'); end
0030      case 'DataScale'
0031        if varargin{i+1}~=1; error('DataScale must by 1'); end
0032      otherwise 
0033        error('Option %s not supported',varargin{i});
0034    end
0035 end
0036 
0037 if (~DEBUG && exist('_mergesimpts','builtin')) || (DEBUG == 2)
0038    if DEBUG;   disp('using _mergesimpts'); end
0039    out = builtin('_mergesimpts',in,tol,'first');
0040    return;
0041 end
0042 
0043 if DEBUG;   disp('using uniquetol_repl'); end
0044 % out = uniquetol_repl(in,tol,'rows','first');
0045 %   UNIQUETOL(...,'ROWS')
0046 out = eidors_uniquetol(in, tol);
0047 
0048 
0049 function out = eidors_uniquetol(in, tol)
0050 % first run unique
0051 out = unique(in,'rows');
0052 
0053 % all pairwise combinations
0054 nRows = size(out,1);
0055 if nRows <= 1
0056    return
0057 end
0058 idx = nchoosek(1:nRows,2);
0059 
0060 % compare each column individually
0061 d = out(idx(:,1),:) - out(idx(:,2),:);
0062 d = abs(d) <= tol;
0063 
0064 same = all(d,2);
0065 
0066 legacy = false; try unique([],'legacy'); catch, legacy = true; end
0067    
0068 % replace each equal row with the first match
0069 if legacy
0070    [~,ii] = unique(idx(same,2),'first');
0071 else
0072    [~,ii] = unique(idx(same,2));
0073 end
0074 jj = find(same);
0075 ii = jj(ii);
0076 
0077 out(idx(ii,2),:) = out(idx(ii,1),:);
0078 
0079 % run unique to eliminate the now exactly matching rows
0080 out = unique(out,'rows');
0081       
0082 
0083 
0084 
0085 
0086 function [z,ii,jj] = uniquetol_repl(x,tol,varargin)
0087 %UNIQUETOL Unique element within a tolerance.
0088 %   [Y,I,J] = UNIQUETOL(X,TOL) is very similar to UNIQUE, but allows an
0089 %   additional tolerance input, TOL. TOL can be taken as the total absolute
0090 %   difference between similar elements. TOL must be a none negative
0091 %   scalar. If not provided, TOL is assumed to be 0, which makes UNIQUETOL
0092 %   identical to UNIQUE.
0093 %
0094 %   UNIQUETOL(...,'ROWS')
0095 %   UNIQUETOL(...,'FIRST')
0096 %   UNIQUETOL(...,'LAST')
0097 %   These expressions are identical to the UNIQUE counterparts.
0098 %
0099 %   See also UNIQUE.
0100 
0101 % Siyi Deng; 03-19-2010; 05-15-2010; 10-29-2010;
0102 
0103 % Licence:
0104 % Copyright (c) 2010, Siyi Deng
0105 % All rights reserved.
0106 %
0107 % Redistribution and use in source and binary forms, with or without
0108 % modification, are permitted provided that the following conditions are
0109 % met:
0110 %
0111 %     * Redistributions of source code must retain the above copyright
0112 %       notice, this list of conditions and the following disclaimer.
0113 %     * Redistributions in binary form must reproduce the above copyright
0114 %       notice, this list of conditions and the following disclaimer in
0115 %       the documentation and/or other materials provided with the distribution
0116 %
0117 % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0118 % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0119 % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0120 % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0121 % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0122 % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0123 % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0124 % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0125 % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0126 % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0127 % POSSIBILITY OF SUCH DAMAGE.
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); % [n,bin] = histc(y,z);
0147 jj = bin(jj);
0148 ii = ii(isTol);
0149 
0150 % UNIQUETOL;
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 
0175 
0176    for i=1:length(testvec)
0177      eidors_msg('TEST%d============',i,1);
0178      x = testvec{i};
0179       for tol = logspace(-4,1,5);
0180          uu = uniquetol(x,tol,'ByRows',true,'DataScale',1);
0181          um = builtin('_mergesimpts',x,tol,'first');
0182          ur = uniquetol_repl(x,tol,'rows','first');
0183          ue = eidors_uniquetol(x,tol);
0184          unit_test_cmp(sprintf('um=uu %f',tol),uu,um);
0185          unit_test_cmp(sprintf('um=ur %f',tol),uu,ur);
0186          unit_test_cmp(sprintf('um=ue %f',tol),uu,ue);
0187       end
0188    end

Generated on Wed 21-Jun-2017 09:29:07 by m2html © 2005