1%% Copyright (C) 2000, 2005, 2006, 2007 Paul Kienzle 2%% 3%% This file is part of Octave. 4%% 5%% Octave is free software; you can redistribute it and/or modify it 6%% under the terms of the GNU General Public License as published by 7%% the Free Software Foundation; either version 3 of the License, or (at 8%% your option) any later version. 9%% 10%% Octave is distributed in the hope that it will be useful, but 11%% WITHOUT ANY WARRANTY; without even the implied warranty of 12%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13%% General Public License for more details. 14%% 15%% You should have received a copy of the GNU General Public License 16%% along with Octave; see the file COPYING. If not, see 17%% <http://www.gnu.org/licenses/>. 18 19%% Undocumented internal function. 20 21%% -*- texinfo -*- 22%% @deftypefn {Function File} {} isequal3 (@var{nans_compare_equal}, @var{x1}, @var{x2}, @dots{}) 23%% Return true if @var{x1}, @var{x2}, @dots{} are all equal and 24%% @var{nans_compare_equal} evaluates to false. 25%% 26%% If @var{nans_compare_equal} evaluates to true, then assume NaN == NaN. 27%% @seealso{isequal, isequalwithequalnans} 28%% @end deftypefn 29 30%% Modified by: William Poetra Yoga Hadisoeseno 31%% modified by Alois Schloegl for the use with Matlab 32 33%% Algorithm: 34%% 35%% 1. Determine the class of x 36%% 2. If x is of the struct, cell, list or char class, for each 37%% argument after x, determine whether it has the same class 38%% and size as x. 39%% Otherwise, for each argument after x, verify that it is not 40%% of the struct, cell, list or char class, and that it has 41%% the same size as x. 42%% 3. For each argument after x, compare it for equality with x: 43%% a. struct compare each member by name, not by order (recursive) 44%% b. cell/list compare each member by order (recursive) 45%% c. char compare each member with strcmp 46%% d. <other> compare each nonzero member, and assume NaN == NaN 47%% if nans_compare_equal is nonzero. 48 49function t = isequal3(nans_compare_equal, x, varargin) 50 51 if (nargin < 2) 52 print_usage (); 53 end 54 55 l_v = nargin - 2; 56 57 %% Generic tests. 58 59 %% All arguments must either be of the same class or they must be 60 %% numeric values. 61 t = (all (strcmp (class(x), cellfun (@class, varargin, 'UniformOutput', false))) || (isnumeric (x) && all (cellfun (@isnumeric, varargin, 'UniformOutput', true)))); 62 63 if (t) 64 %% Test that everything has the same number of dimensions. 65 s_x = size (x); 66 s_v = cellfun (@size, varargin, 'UniformOutput', false); 67 t = all (length (s_x) == cellfun (@length, s_v)); 68 end 69 70 if (t) 71 %% Test that everything is the same size since it has the same 72 %% dimensionality. 73 l_x = length (s_x); 74 s_v = reshape ([s_v{:}], length (s_x), []); 75 idx = 0; 76 while (t && idx < l_x) 77 idx=idx+1; 78 t = all (s_x(idx) == s_v(idx, :)); 79 end 80 end 81 82 if (t) 83 %% Check individual classes. 84 if (isstruct (x)) 85 %% Test the number of fields. 86 fn_x = fieldnames (x); 87 l_fn_x = length (fn_x); 88 fn_v = cellfun (@fieldnames, varargin, 'UniformOutput', false); 89 t = all (l_fn_x == cellfun (@length, fn_v)); 90 91 %% Test that all the names are equal. 92 idx = 0; 93 s_fn_x = sort (fn_x); 94 while (t && idx < l_v) 95 idx=idx+1; 96 %% We'll allow the fieldnames to be in a different order. 97 t = all (strcmp (s_fn_x, sort (fn_v{idx}))); 98 end 99 100 idx = 0; 101 while (t && idx < l_fn_x) 102 %% Test that all field values are equal. 103 idx=idx+1; 104 args = {nans_compare_equal, {x.(fn_x{idx})}}; 105 for argn = 1:l_v 106 args{argn+2} = {varargin{argn}.(fn_x{idx})}; 107 end 108 %% Minimize function calls by calling for all the arguments at 109 %% once. 110 t = isequal3(args{:}); 111 end 112 113 elseif (iscell (x)) 114 %% Check that each element of a cell is equal. 115 l_x = numel (x); 116 idx = 0; 117 while (t && idx < l_x) 118 idx=idx+1; 119 args = {nans_compare_equal, x{idx}}; 120 for p = 1:l_v 121 args{p+2} = varargin{p}{idx}; 122 end 123 t = isequal3 (args{:}); 124 end 125 126 elseif (ischar (x)) 127 128 %% Sizes are equal already, so we can just make everything into a 129 %% row and test the rows. 130 for i = 1:l_v 131 strings{i} = reshape (varargin{i}, 1, []); 132 end 133 t = all (strcmp (reshape (x, 1, []), strings)); 134 135 else 136 %% Check the numeric types. 137 138 if (issparse (x)) 139 f_x = spfind (x); 140 else 141 f_x = find (x); 142 end 143 l_f_x = length (f_x); 144 x = x(f_x); 145 for argn = 1:l_v 146 y = varargin{argn}; 147 if (issparse (y)) 148 f_y = spfind (y); 149 else 150 f_y = find (y); 151 end 152 153 t = (l_f_x == length (f_y)) && all (f_x == f_y); 154 if (~t) 155 return; 156 end 157 158 y = y(f_y); 159 m = (x == y); 160 t = all (m); 161 162 if (~t) 163 if (nans_compare_equal) 164 t = isnan (x(~m)) && isnan (y(~m)); 165 else 166 return; 167 end 168 end 169 end 170 171 end 172 end 173 174end 175 176%% test size and shape 177%!assert(isequal3(0,[1,2,3,4],[1,2,3,4]), true) 178%!assert(isequal3(0,[1;2;3;4],[1;2;3;4]), true) 179%!assert(isequal3(0,[1,2,3,4],[1;2;3;4]), false) 180%!assert(isequal3(0,[1,2,3,4],[1,2;3,4]), false) 181%!assert(isequal3(0,[1,2,3,4],[1,3;2,4]), false) 182 183%!test 184%! A = 1:8; 185%! B = reshape (A, 2, 2, 2); 186%! assert (isequal3 (0, A, B), false); 187 188%!test 189%! A = reshape (1:8, 2, 2, 2); 190%! B = A; 191%! assert (isequal3 (0, A, B), true); 192 193%!test 194%! A = reshape (1:8, 2, 4); 195%! B = reshape (A, 2, 2, 2); 196%! assert (isequal3 (0, A, B), false); 197 198%% test for equality 199%!assert(isequal3(0,[1,2,3,4],[1,2,3,4]), true) 200%!assert(isequal3(1,{1,2,NaN,4},{1,2,NaN,4}), true) 201%!assert(isequal3(1,[1,2,NaN,4],[1,2,NaN,4]), true) 202%!assert(isequal3(0,['a','b','c','d'],['a','b','c','d']), true) 203%% Test multi-line strings 204%!assert(isequal3(0,["test";"strings"],["test";"strings"],["test";"strings"]), true) 205%% test for inequality 206%!assert(isequal3(0,[1,2,3,4],[1;2;3;4]),false) 207%!assert(isequal3(0,{1,2,3,4},[1,2,3,4]),false) 208%!assert(isequal3(0,[1,2,3,4],{1,2,3,4}),false) 209%!assert(isequal3(0,[1,2,NaN,4],[1,2,NaN,4]),false) 210%!assert(isequal3(1,[1,2,NaN,4],[1,NaN,3,4]),false) 211%!assert(isequal3(1,[1,2,NaN,4],[1,2,3,4]),false) 212%!assert(isequal3(0,['a','b','c','d'],['a';'b';'c';'d']),false) 213%!assert(isequal3(0,{'a','b','c','d'},{'a';'b';'c';'d'}),false) 214%% test for equality (struct) 215%!assert(isequal3(0,struct('a',1,'b',2),struct('a',1,'b',2)),true) 216%!assert(isequal3(0,struct('a',1,'b',2),struct('a',1,'b',2),struct('a',1,'b',2)),true) 217%!assert(isequal3(0,struct('a','abc','b',2),struct('a','abc','b',2)),true) 218%!assert(isequal3(1,struct('a',NaN,'b',2),struct('a',NaN,'b',2),struct('a',NaN,'b',2)),true) 219%% test for inequality (struct) 220%!assert(isequal3(0,struct('a',NaN,'b',2),struct('a',NaN,'b',2),struct('a',NaN,'b',2)),false) 221 222