Home > eidors > overloads > uniquetol.m

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 5598 2017-06-22 02:13:40Z aadler $
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 out = eidors_uniquetol(in, tol);
0044 
0045 
0046 function out = eidors_uniquetol(in, tol)
0047 % first run unique
0048 out = unique(in,'rows');
0049 
0050 % all pairwise combinations
0051 nRows = size(out,1);
0052 if nRows <= 1
0053    return
0054 end
0055 idx = nchoosek(1:nRows,2);
0056 
0057 % compare each column individually
0058 d = out(idx(:,1),:) - out(idx(:,2),:);
0059 d = abs(d) <= tol;
0060 
0061 same = all(d,2);
0062 
0063 legacy = false; try unique([],'legacy'); catch, legacy = true; end
0064    
0065 % replace each equal row with the first match
0066 if legacy
0067    [~,ii] = unique(idx(same,2),'first');
0068 else
0069    [~,ii] = unique(idx(same,2));
0070 end
0071 jj = find(same);
0072 ii = jj(ii);
0073 
0074 out(idx(ii,2),:) = out(idx(ii,1),:);
0075 
0076 % run unique to eliminate the now exactly matching rows
0077 out = unique(out,'rows');
0078       
0079 
0080 
0081 
0082 
0083 function [z,ii,jj] = uniquetol_repl(x,tol,varargin)
0084 %UNIQUETOL Unique element within a tolerance.
0085 %   [Y,I,J] = UNIQUETOL(X,TOL) is very similar to UNIQUE, but allows an
0086 %   additional tolerance input, TOL. TOL can be taken as the total absolute
0087 %   difference between similar elements. TOL must be a none negative
0088 %   scalar. If not provided, TOL is assumed to be 0, which makes UNIQUETOL
0089 %   identical to UNIQUE.
0090 %
0091 %   UNIQUETOL(...,'ROWS')
0092 %   UNIQUETOL(...,'FIRST')
0093 %   UNIQUETOL(...,'LAST')
0094 %   These expressions are identical to the UNIQUE counterparts.
0095 %
0096 %   See also UNIQUE.
0097 
0098 % Siyi Deng; 03-19-2010; 05-15-2010; 10-29-2010;
0099 
0100 % Licence:
0101 % Copyright (c) 2010, Siyi Deng
0102 % All rights reserved.
0103 %
0104 % Redistribution and use in source and binary forms, with or without
0105 % modification, are permitted provided that the following conditions are
0106 % met:
0107 %
0108 %     * Redistributions of source code must retain the above copyright
0109 %       notice, this list of conditions and the following disclaimer.
0110 %     * Redistributions in binary form must reproduce the above copyright
0111 %       notice, this list of conditions and the following disclaimer in
0112 %       the documentation and/or other materials provided with the distribution
0113 %
0114 % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0115 % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0116 % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0117 % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0118 % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0119 % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0120 % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0121 % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0122 % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0123 % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0124 % POSSIBILITY OF SUCH DAMAGE.
0125 
0126 if size(x,1) == 1, x = x(:); end
0127 if nargin < 2 || isempty(tol) || tol == 0
0128     [z,ii,jj] = unique(x,varargin{:});
0129     return;
0130 end
0131 [y,ii,jj] = unique(x,varargin{:});
0132 if size(x,2) > 1
0133     [~,ord] = sort(sum(x.^2,1),2,'descend');
0134     [y,io] = sortrows(y,ord);
0135     [~,jo] = sort(io);
0136     ii = ii(io);
0137     jj = jo(jj);
0138 end
0139 d = sum(abs(diff(y,1,1)),2);
0140 
0141 isTol = [true;d > tol];
0142 z = y(isTol,:);
0143 bin = cumsum(isTol); % [n,bin] = histc(y,z);
0144 jj = bin(jj);
0145 ii = ii(isTol);
0146 
0147 % UNIQUETOL;
0148    
0149 function do_unit_test
0150    testvec{1} = [1 2; 1.06 2; 1.1 2; 1.1 2.03];
0151    testvec{2} = [ ...
0152    -0.488223373148967243473350663407, ...
0153    -0.488223373148967243473350663407, ...
0154    -0.488223373148967243473350663407, ...
0155    -0.488223373148967243473350663407, ...
0156    -0.488223373148967243473350663407, ...
0157    -0.488223373148967243473350663407;
0158    -0.999999999999999666933092612453, ...
0159    -0.999999999999999888977697537484, ...
0160    -0.999999999999999888977697537484, ...
0161    -0.999999999999999888977697537484, ...
0162    -0.999999999999999888977697537484, ...
0163    -0.905678339894304240687006313237;
0164    -0.232963663178817920185181833403, ...
0165    -0.232963663178818003451908680290, ...
0166    -0.116481831589409029481529955774, ...
0167    -0.232963663178818086718635527177, ...
0168    -0.116481831589409043359317763588, ...
0169    -0.156131398552380479261003642932]';
0170    testvec{3} = testvec{2}';
0171 
0172 
0173    for i=1:length(testvec)
0174      eidors_msg('TEST%d============',i,1);
0175      x = testvec{i};
0176       for tol = logspace(-4,1,6);
0177          uu = uniquetol(x,tol,'ByRows',true,'DataScale',1);
0178          um = builtin('_mergesimpts',x,tol,'first');
0179          ur = uniquetol_repl(x,tol,'rows','first');
0180          ue = eidors_uniquetol(x,tol);
0181          fprintf('Testing for tol=%f\n',tol);
0182          unit_test_cmp('um=uu           ',uu,um);
0183          unit_test_cmp('um=ur (not used)',uu,ur);
0184          unit_test_cmp('um=ue           ',uu,ue);
0185       end
0186    end

Generated on Fri 01-Jun-2018 15:59:55 by m2html © 2005