comparison m-toolbox/classes/@ltpda_obj/eq.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f0afece42f48
1 % EQ overloads the == operator for ltpda objects.
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % DESCRIPTION: EQ overloads the == operator for ltpda objects.
5 %
6 % All fields are checked.
7 %
8 % CALL: result = eq(obj1,obj2)
9 % result = eq(obj1,obj2, exc_list)
10 % result = eq(obj1,obj2, 'property1', 'property2')
11 % result = eq(obj1,obj2, '<class>/property', '<class>/property')
12 %
13 % With a PLIST
14 %
15 % r = eq(obj1, obj2, plist('Exceptions', {'prop1', 'prop2'}))
16 % r = eq(obj1, obj2, plist('Tol', eps(1)))
17 % r = eq(obj1, obj2, plist('Exceptions', 'prop', 'Tol', 1e-14))
18 %
19 % EXAMPLES: result = eq(obj1,obj2, 'name', 'created')
20 % result = eq(obj1,obj2, '<class>/name')
21 %
22 % INPUTS: obj1, obj2 - Input objects
23 % exc_list - Exception list
24 % List of properties which are not checked.
25 %
26 % OUTPUTS: If the two objects are considered equal, result == true,
27 % otherwise, result == false.
28 %
29 % <a href="matlab:utils.helper.displayMethodInfo('ltpda_obj', 'eq')">Parameters Description</a>
30 %
31 % VERSION: $Id: eq.m,v 1.35 2011/05/13 10:05:42 hewitson Exp $
32 %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34
35 function varargout = eq(obj1, obj2, varargin)
36
37 % Check if this is a call for parameters
38 hh = [{obj1}, {obj2}, varargin];
39 if utils.helper.isinfocall(hh{:})
40 varargout{1} = getInfo(varargin{1});
41 return
42 end
43
44 import utils.const.*
45
46 message = '';
47
48 %%%%% Check class
49 if ~strcmp(class(obj1), class(obj2))
50 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2));
51 varargout = setOutputs(nargout, false, message);
52 return
53 end
54
55 %%%%% Check length of obj1 and obj2
56 if ~all(size(obj1) == size(obj2))
57 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%dx%d] <-> [%dx%d]', class(obj1), size(obj1), size(obj2));
58 varargout = setOutputs(nargout, false, message);
59 return
60 end
61
62 plin = [];
63 exception_list = varargin;
64 if ~isempty(varargin) && isa(varargin{1}, 'plist')
65 plin = varargin{1};
66 end
67
68 %%%%% Get the tolerance from a potential existing plist
69 if ~isempty(plin) && plin.isparam('tol')
70 tol = plin.find('tol');
71 else
72 dpl = getDefaultPlist();
73 tol = dpl.find('tol');
74 end
75
76 %%%%% Convert a potential existing plist into a exception
77 if ~isempty(plin) && plin.isparam('exceptions')
78 exception_list = find(plin, 'exceptions');
79 if isempty(exception_list)
80 exception_list = cell(0);
81 elseif ~iscell(exception_list)
82 exception_list = cellstr(exception_list);
83 end
84 end
85
86 result = true;
87
88 %%%%% for each element in obj1 and obj2
89 for jj = 1:numel(obj1)
90
91 if isa(obj1, 'ltpda_uoh')
92 utils.helper.msg(msg.PROC1, 'testing %s against %s', obj1(jj).name, obj2(jj).name);
93 end
94
95 fields = fieldnames(obj1(jj));
96
97 for ii = 1:length(fields)
98 field = fields{ii};
99
100 %%%%% Creates the exception list for the current field.
101 %%%%% For example: {'name', 'ao/name'}
102 ck_field = {field, sprintf('%s/%s', class(obj1), field)};
103
104 % Special case (for the ao- and history-class):
105 % Is the field = 'hist', 'inhists' then add 'history' to the exception list.
106 %%%%% For example: {'history', 'ao/history'}
107 if utils.helper.ismember(field, {'hist', 'inhists'})
108 ck_field{end+1} = 'history';
109 ck_field{end+1} = sprintf('%s/history', class(obj1));
110 elseif strcmp(field, 'val')
111 ck_field{end+1} = 'value';
112 ck_field{end+1} = sprintf('%s/value', class(obj1));
113 end
114
115 %%%%% Check field if it is not in the exception list
116 if ~(any(utils.helper.ismember(ck_field, exception_list)))
117
118 if isa(obj1(jj).(field), 'sym')
119 %%%%%%%%%% The property is a sym-object %%%%%%%%%%
120 if ~eq(obj1(jj).(field), obj2(jj).(field))
121 result = false;
122 message = display_msg(obj1, jj, field);
123 varargout = setOutputs(nargout, result, message);
124 return
125 end
126
127 elseif isa(obj1(jj).(field), 'ltpda_obj')
128 %%%%%%%%%% The property is a ltpda-object %%%%%%%%%%
129
130 %%%%% Check the length of the property
131 if length(obj1(jj).(field)) ~= length(obj2(jj).(field))
132 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The property [%s] of the object [%s] have not the same size.', field, class(obj1));
133 result = false;
134 varargout = setOutputs(nargout, result, message);
135 return
136 end
137
138 %%%%% For each element of the property
139 for kk = 1:numel(obj1(jj).(field))
140
141 if isempty(plin)
142 % Command with a list of exceptions
143 res = eq(obj1(jj).(field)(kk), obj2(jj).(field)(kk), exception_list{:});
144 else
145 % Command with a PLIST
146 res = eq(obj1(jj).(field)(kk), obj2(jj).(field)(kk), plin);
147 end
148
149 if ~res
150 result = false;
151 message = display_msg(obj1, jj, field);
152 varargout = setOutputs(nargout, result, message);
153 return
154 end
155 end
156
157 elseif isstruct(obj1(jj).(field))
158 %%%%%%%%%% The property is a structure %%%%%%%%%%
159
160 if ~eqstruct(obj1(jj).(field), obj2(jj).(field), exception_list, tol)
161 result = false;
162 message = display_msg(obj1, jj, field);
163 varargout = setOutputs(nargout, result, message);
164 return
165 end
166
167 elseif iscell(obj1(jj).(field))
168 %%%%%%%%%% The property is a cell array %%%%%%%%%%
169
170 if ~eqcell(obj1(jj).(field), obj2(jj).(field), exception_list, tol)
171 result = false;
172 message = display_msg(obj1, jj, field);
173 varargout = setOutputs(nargout, result, message);
174 return
175 end
176
177 elseif isnumeric(obj1(jj).(field))
178 %%%%%%%%%% The property is an elemental MATLAB datatype %%%%%%%%%%
179 res = utils.math.isequal(obj1(jj).(field), obj2(jj).(field), tol);
180 if ~res
181 result = false;
182 message = display_msg(obj1, jj, field);
183 varargout = setOutputs(nargout, result, message);
184 return
185 end
186
187 else
188 %%%%%%%%%% The property is an elemental MATLAB datatype %%%%%%%%%%
189 if ~isequal(obj1(jj).(field), obj2(jj).(field))
190 result = false;
191 message = display_msg(obj1, jj, field);
192 varargout = setOutputs(nargout, result, message);
193 return
194 end
195 end
196
197 end
198 end
199
200 end % End loop over objects
201
202 varargout = setOutputs(nargout, result, message);
203
204 end % End eq()
205
206 function out = setOutputs(nout, result, message)
207 if nout == 0
208 out = {result};
209 elseif nout == 1
210 out = {result};
211 elseif nout == 2
212 out = {result, message};
213 else
214 error('Incorrect outputs for eq()');
215 end
216
217 end
218
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220 % Local Functions %
221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222
223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 %
225 % FUNCTION: display_msg
226 %
227 % DESCRIPTION: Diesplay a message if the objects are not equal
228 %
229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230
231 function message = display_msg(obj, obj_no, field)
232 import utils.const.*
233 if numel(obj) > 1
234 message = sprintf('NOT EQUAL: %s.%s (%d. object)', class(obj(obj_no)), field, obj_no);
235 % utils.helper.msg(msg.PROC1, message);
236 else
237 message = sprintf('NOT EQUAL: %s.%s', class(obj(obj_no)), field);
238 % utils.helper.msg(msg.PROC1, message);
239 end
240 % bt = warning('query', 'backtrace');
241 % warning('backtrace', 'off');
242 % warning('LTPDA:eq:ObjectsNotEqual', message);
243 % warning('backtrace', bt.state);
244 end
245
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 %
248 % FUNCTION: eqstruct
249 %
250 % DESCRIPTION: Equal method to compare structures
251 %
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253
254 function [result, message] = eqstruct(obj1, obj2, exception_list, tol)
255
256 import utils.const.*
257
258 message = '';
259
260 %%%%% Check class
261 if ~strcmp(class(obj1), class(obj2))
262 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2));
263 result = false;
264 return
265 end
266
267 %%%%% Check length of obj1 and obj2
268 fieldsA = fieldnames(obj1);
269 fieldsB = fieldnames(obj2);
270 if numel(fieldsA) ~= numel(fieldsB)
271 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%d] <-> [%d]', class(obj1), numel(obj1), numel(obj2));
272 result = false;
273 return
274 end
275
276 result = true;
277
278 for oo = 1:numel(obj1)
279 for ii = 1:numel(fieldsA)
280
281 if isa(obj1(oo).(fieldsA{ii}), 'ltpda_obj')
282 %%%%%%%%%%%%% LTPDA objects
283 if ~eq(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), plist('exceptions', exception_list, 'tol', tol))
284 result = false;
285 message = display_msg(obj1, oo, fieldsA{ii});
286 return
287 end
288
289 elseif isstruct(obj1(oo).(fieldsA{ii}))
290 %%%%%%%%%%%%% STRUCTURE
291 if ~eqstruct(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), exception_list, tol)
292 result = false;
293 message = display_msg(obj1, oo, fieldsA{ii});
294 return
295 end
296
297 elseif iscell(obj1(oo).(fieldsA{ii}))
298 %%%%%%%%%%%%% STRUCTURE
299 if ~eqcell(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), exception_list, tol)
300 result = false;
301 message = display_msg(obj1, oo, fieldsA{ii});
302 return
303 end
304 elseif isnumeric(obj1(oo).(fieldsA{ii}))
305 %%%%%%%%%%%%% Numeric
306 res = utils.math.isequal(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), tol);
307 if ~res
308 result = false;
309 message = display_msg(obj1, ii, 'cell-object');
310 return
311 end
312
313 else
314 if ~isequal(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}))
315 result = false;
316 message = display_msg(obj1, oo, fieldsA{ii});
317 return
318 end
319 end
320
321 end % over all fields
322 end % over all objects
323
324 end
325
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 %
328 % FUNCTION: eqcell
329 %
330 % DESCRIPTION: Equal method to compare structures
331 %
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333
334 function [result, message] = eqcell(obj1, obj2, exception_list, tol)
335
336 import utils.const.*
337 message = '';
338
339 %%%%% Check class
340 if ~strcmp(class(obj1), class(obj2))
341 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2));
342 result = false;
343 return
344 end
345
346 %%%%% Check length of obj1 and obj2
347 if ~all(size(obj1) == size(obj2))
348 utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%dx%d] <-> [%dx%d]', class(obj1), size(obj1), size(obj2));
349 result = false;
350 return
351 end
352
353 result = true;
354
355 for ii = 1:numel(obj1)
356
357 if isa(obj1{ii}, 'ltpda_obj')
358 %%%%%%%%%%%%% LTPDA objects
359 if ~eq(obj1{ii}, obj2{ii}, plist('exceptions', exception_list, 'tol', tol))
360 result = false;
361 message = display_msg(obj1, ii, 'cell-object');
362 return
363 end
364
365 elseif isstruct(obj1{ii})
366 %%%%%%%%%%%%% STRUCTURE
367 if ~eqstruct(obj1{ii}, obj2{ii}, exception_list, tol)
368 result = false;
369 message = display_msg(obj1, ii, 'cell-object');
370 return
371 end
372
373 elseif iscell(obj1{ii})
374 %%%%%%%%%%%%% CELL
375 if ~eqcell(obj1{ii}, obj2{ii}, exception_list, tol)
376 result = false;
377 message = display_msg(obj1, ii, 'cell-object');
378 return
379 end
380 elseif isnumeric(obj1{ii})
381 %%%%%%%%%%%%% Numeric
382 res = utils.math.isequal(obj1{ii}, obj2{ii}, tol);
383 if ~res
384 result = false;
385 message = display_msg(obj1, ii, 'cell-object');
386 return
387 end
388
389 else
390 if ~isequal(obj1{ii}, obj2{ii})
391 result = false;
392 message = display_msg(obj1, ii, 'cell-object');
393 return
394 end
395 end
396 end
397 end
398
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 %
401 % FUNCTION: getInfo
402 %
403 % DESCRIPTION: Get Info Object
404 %
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406
407 function ii = getInfo(varargin)
408 if nargin == 1 && strcmpi(varargin{1}, 'None')
409 sets = {};
410 pl = [];
411 else
412 sets = {'Default'};
413 pl = getDefaultPlist;
414 end
415 % Build info object
416 ii = minfo(mfilename, 'ltpda_obj', 'ltpda', utils.const.categories.relop, '$Id: eq.m,v 1.35 2011/05/13 10:05:42 hewitson Exp $', sets, pl);
417 ii.setModifier(false);
418 ii.setArgsmin(2);
419 end
420
421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422 %
423 % FUNCTION: getDefaultPlist
424 %
425 % DESCRIPTION: Get Default Plist
426 %
427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428
429 function plout = getDefaultPlist()
430 persistent pl;
431 if exist('pl', 'var')==0 || isempty(pl)
432 pl = buildplist();
433 end
434 plout = pl;
435 end
436
437 function plo = buildplist()
438 plo = plist();
439
440 % Exceptions
441 p = param({'Exceptions', 'Test the objects without the given property names'}, paramValue.EMPTY_CELL);
442 plo.append(p);
443
444 % Tolerance
445 p = param({'Tol', 'Test double values with the given tolerance'}, paramValue.DOUBLE_VALUE(eps(1)));
446 plo.append(p);
447
448 end
449