Mercurial > hg > octave-lyh
annotate scripts/general/__isequal__.m @ 9674:4cf195710ae8
simplify arrayfun
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 30 Sep 2009 21:59:44 +0200 |
parents | eb63fbe60fab |
children | 6f1ea8241c99 |
rev | line source |
---|---|
8920 | 1 ## Copyright (C) 2000, 2005, 2006, 2007, 2009 Paul Kienzle |
5549 | 2 ## |
7016 | 3 ## This file is part of Octave. |
5549 | 4 ## |
7016 | 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. | |
5549 | 14 ## |
15 ## You should have received a copy of the GNU General Public License | |
7016 | 16 ## along with Octave; see the file COPYING. If not, see |
17 ## <http://www.gnu.org/licenses/>. | |
5549 | 18 |
6945 | 19 ## Undocumented internal function. |
20 | |
5549 | 21 ## -*- texinfo -*- |
5550 | 22 ## @deftypefn {Function File} {} __isequal__ (@var{nans_compare_equal}, @var{x1}, @var{x2}, @dots{}) |
8812
7d48766c21a5
use consistent format for doc strings of internal functions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
23 ## Undocumented internal function. |
7d48766c21a5
use consistent format for doc strings of internal functions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
24 ## @end deftypefn |
7d48766c21a5
use consistent format for doc strings of internal functions
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
25 |
5550 | 26 ## Return true if @var{x1}, @var{x2}, @dots{} are all equal and |
5549 | 27 ## @var{nans_compare_equal} evaluates to false. |
28 ## | |
29 ## If @var{nans_compare_equal} evaluates to true, then assume NaN == NaN. | |
30 | |
31 ## Modified by: William Poetra Yoga Hadisoeseno | |
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 | |
49 function t = __isequal__ (nans_compare_equal, x, varargin) | |
50 | |
51 if (nargin < 3) | |
6046 | 52 print_usage (); |
5549 | 53 endif |
54 | |
55 l_v = nargin - 2; | |
56 | |
6130 | 57 ## Generic tests. |
5549 | 58 |
6130 | 59 ## Give an error for a list (that will make the code simpler and lists |
60 ## are deprecated anyway. | |
61 if (islist (x)) | |
62 error ("__isequal__: list objects are deprecated and cannot be tested for equality here; use cell arrays instead"); | |
63 endif | |
5549 | 64 |
6609 | 65 ## All arguments must either be of the same class or they must be |
66 ## numeric values. | |
67 t = (all (strcmp (class(x), | |
68 cellfun (@class, varargin, "UniformOutput", false))) | |
69 || (isnumeric (x) | |
70 && all (cellfun (@isnumeric, varargin, "UniformOutput", true)))); | |
71 | |
6130 | 72 if (t) |
73 ## Test that everything has the same number of dimensions. | |
74 s_x = size (x); | |
75 s_v = cellfun (@size, varargin, "UniformOutput", false); | |
76 t = all (length (s_x) == cellfun (@length, s_v)); | |
77 endif | |
5549 | 78 |
6130 | 79 if (t) |
80 ## Test that everything is the same size since it has the same | |
81 ## dimensionality. | |
82 l_x = length (s_x); | |
83 s_v = reshape ([s_v{:}], length (s_x), []); | |
84 idx = 0; | |
85 while (t && idx < l_x) | |
86 idx++; | |
87 t = all (s_x(idx) == s_v(idx, :)); | |
88 endwhile | |
89 endif | |
5549 | 90 |
6130 | 91 if (t) |
92 ## Check individual classes. | |
93 if (isstruct (x)) | |
94 ## Test the number of fields. | |
95 fn_x = fieldnames (x); | |
96 l_fn_x = length (fn_x); | |
97 fn_v = cellfun (@fieldnames, varargin, "UniformOutput", false); | |
98 t = all (l_fn_x == cellfun (@length, fn_v)); | |
5549 | 99 |
6130 | 100 ## Test that all the names are equal. |
101 idx = 0; | |
102 s_fn_x = sort (fn_x); | |
103 while (t && idx < l_v) | |
104 idx++; | |
105 ## We'll allow the fieldnames to be in a different order. | |
106 t = all (strcmp (s_fn_x, sort (fn_v{idx}))); | |
107 endwhile | |
5549 | 108 |
6130 | 109 idx = 0; |
110 while (t && idx < l_fn_x) | |
111 ## Test that all field values are equal. | |
112 idx++; | |
6157 | 113 args = {nans_compare_equal, {x.(fn_x{idx})}}; |
6130 | 114 for argn = 1:l_v |
6157 | 115 args{argn+2} = {varargin{argn}.(fn_x{idx})}; |
6130 | 116 endfor |
117 ## Minimize function calls by calling for all the arguments at | |
118 ## once. | |
119 t = __isequal__ (args{:}); | |
120 endwhile | |
5549 | 121 |
6130 | 122 elseif (iscell (x)) |
123 ## Check that each element of a cell is equal. | |
124 l_x = numel (x); | |
125 idx = 0; | |
126 while (t && idx < l_x) | |
127 idx++; | |
128 args = {nans_compare_equal, x{idx}}; | |
129 for p = 1:l_v | |
130 args{p+2} = varargin{p}{idx}; | |
131 endfor | |
132 t = __isequal__ (args{:}); | |
133 endwhile | |
5549 | 134 |
6130 | 135 elseif (ischar (x)) |
5549 | 136 |
6130 | 137 ## Sizes are equal already, so we can just make everything into a |
138 ## row and test the rows. | |
139 for i = 1:l_v | |
140 strings{i} = reshape (varargin{i}, 1, []); | |
141 endfor | |
142 t = all (strcmp (reshape (x, 1, []), strings)); | |
5549 | 143 |
144 else | |
6130 | 145 ## Check the numeric types. |
146 | |
147 if (issparse (x)) | |
148 f_x = spfind (x); | |
5549 | 149 else |
6130 | 150 f_x = find (x); |
5549 | 151 endif |
6130 | 152 l_f_x = length (f_x); |
153 x = x(f_x); | |
154 for argn = 1:l_v | |
155 y = varargin{argn}; | |
156 if (issparse (y)) | |
157 f_y = spfind (y); | |
158 else | |
159 f_y = find (y); | |
160 endif | |
5549 | 161 |
6130 | 162 t = (l_f_x == length (f_y)) && all (f_x == f_y); |
163 if (!t) | |
164 return; | |
165 endif | |
5549 | 166 |
6130 | 167 y = y(f_y); |
168 m = (x == y); | |
169 t = all (m); | |
5549 | 170 |
6130 | 171 if (!t) |
172 if (nans_compare_equal) | |
173 t = isnan (x(!m)) && isnan (y(!m)); | |
174 else | |
175 return; | |
176 endif | |
177 endif | |
178 endfor | |
5549 | 179 |
6130 | 180 endif |
5549 | 181 endif |
182 | |
183 endfunction | |
184 | |
6130 | 185 ## test size and shape |
186 %!assert(__isequal__(0,[1,2,3,4],[1,2,3,4]), true) | |
187 %!assert(__isequal__(0,[1;2;3;4],[1;2;3;4]), true) | |
188 %!assert(__isequal__(0,[1,2,3,4],[1;2;3;4]), false) | |
189 %!assert(__isequal__(0,[1,2,3,4],[1,2;3,4]), false) | |
190 %!assert(__isequal__(0,[1,2,3,4],[1,3;2,4]), false) | |
191 | |
192 %!test | |
193 %! A = 1:8; | |
194 %! B = reshape (A, 2, 2, 2); | |
195 %! assert (__isequal__ (0, A, B), false); | |
196 | |
197 %!test | |
198 %! A = reshape (1:8, 2, 2, 2); | |
199 %! B = A; | |
200 %! assert (__isequal__ (0, A, B), true); | |
201 | |
202 %!test | |
203 %! A = reshape (1:8, 2, 4); | |
204 %! B = reshape (A, 2, 2, 2); | |
205 %! assert (__isequal__ (0, A, B), false); | |
206 | |
207 ## test for equality | |
208 %!assert(__isequal__(0,[1,2,3,4],[1,2,3,4]), true) | |
209 %!assert(__isequal__(1,{1,2,NaN,4},{1,2,NaN,4}), true) | |
210 %!assert(__isequal__(1,[1,2,NaN,4],[1,2,NaN,4]), true) | |
211 %!assert(__isequal__(0,['a','b','c','d'],['a','b','c','d']), true) | |
212 ## Test multi-line strings | |
213 %!assert(__isequal__(0,["test";"strings"],["test";"strings"],["test";"strings"]), true) | |
214 ## test for inequality | |
5549 | 215 %!assert(__isequal__(0,[1,2,3,4],[1;2;3;4]),false) |
216 %!assert(__isequal__(0,{1,2,3,4},[1,2,3,4]),false) | |
217 %!assert(__isequal__(0,[1,2,3,4],{1,2,3,4}),false) | |
218 %!assert(__isequal__(0,[1,2,NaN,4],[1,2,NaN,4]),false) | |
219 %!assert(__isequal__(1,[1,2,NaN,4],[1,NaN,3,4]),false) | |
220 %!assert(__isequal__(1,[1,2,NaN,4],[1,2,3,4]),false) | |
221 %!assert(__isequal__(0,['a','b','c','d'],['a';'b';'c';'d']),false) | |
6130 | 222 %!assert(__isequal__(0,{'a','b','c','d'},{'a';'b';'c';'d'}),false) |
223 ## test for equality (struct) | |
224 %!assert(__isequal__(0,struct('a',1,'b',2),struct('a',1,'b',2)),true) | |
225 %!assert(__isequal__(0,struct('a',1,'b',2),struct('a',1,'b',2),struct('a',1,'b',2)),true) | |
226 %!assert(__isequal__(0,struct('a','abc','b',2),struct('a','abc','b',2)),true) | |
227 %!assert(__isequal__(1,struct('a',NaN,'b',2),struct('a',NaN,'b',2),struct('a',NaN,'b',2)),true) | |
228 ## test for inequality (struct) | |
229 %!assert(__isequal__(0,struct('a',NaN,'b',2),struct('a',NaN,'b',2),struct('a',NaN,'b',2)),false) | |
230 |