Mercurial > hg > ltpda
diff m-toolbox/classes/@plist/eq.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/@plist/eq.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,519 @@ +% EQ overloads the == operator for ltpda plist objects. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: EQ overloads the == operator for ltpda plist objects. +% +% Two plists are considered equal if each has the same name, +% created time, version, creator and parameter objects. The +% order of the param-objects doesn't matter. +% +% CALL: result = eq(u1,u2) +% +% With a PLIST +% +% r = eq(obj1, obj2, plist('Exceptions', {'prop1', 'prop2'})) +% r = eq(obj1, obj2, plist('Tol', eps(1))) +% r = eq(obj1, obj2, plist('Exceptions', 'prop', 'Tol', 1e-14)) +% +% INPUTS: pl1, pl2 - Input objects +% +% OUTPUTS: If the two objects are considered equal, result == true, +% otherwise, result == false. +% +% <a href="matlab:utils.helper.displayMethodInfo('plist', 'eq')">Parameters Description</a> +% +% VERSION: $Id: eq.m,v 1.27 2011/04/08 08:56:21 hewitson Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function result = eq(obj1, obj2, varargin) + + % Check if this is a call for parameters + hh = [{obj1}, {obj2}, varargin]; + if utils.helper.isinfocall(hh{:}) + result = getInfo(varargin{1}); + return + end + + import utils.const.* + + %%%%% Check class + if ~strcmp(class(obj1), class(obj2)) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2)); + result = false; + return + end + + %%%%% Check length of obj1 and obj2 + if numel(obj1) ~= numel(obj2) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%d] <-> [%d]', class(obj1), numel(obj1), numel(obj2)); + result = false; + return + end + + plin = []; + exception_list = varargin; + if ~isempty(varargin) && isa(varargin{1}, 'plist') + plin = varargin{1}; + end + + %%%%% Get the tolerance from a potential existing plist + if ~isempty(plin) && plin.isparam('tol') + tol = plin.find('tol'); + else + dpl = getDefaultPlist(); + tol = dpl.find('tol'); + end + + %%%%% Convert a potential existing plist into a exception + if ~isempty(plin) && plin.isparam('exceptions') + exception_list = find(plin, 'Exceptions'); + if isempty(exception_list) + exception_list = cell(0); + elseif ~iscell(exception_list) + exception_list = cellstr(exception_list); + end + end + + result = true; + + %%%%% for each element in obj1 and obj2 + for jj = 1:numel(obj1) + + if isa(obj1, 'ltpda_uoh') + utils.helper.msg(msg.PROC1, 'testing %s against %s', obj1.name, obj2.name); + end + + fields = fieldnames(obj1(jj)); + + for ii = 1:length(fields) + field = fields{ii}; + + %%%%% Creates the exception list for the current field. + %%%%% For example: {'name', 'ao/name'} + ck_field = {field, sprintf('%s/%s', class(obj1), field)}; + + % Special case (for the ao- and history-class): + % Is the field = 'hist', 'inhists' then add 'history' to the exception list. + %%%%% For example: {'history', 'ao/history'} + if utils.helper.ismember(field, {'hist', 'inhists'}) + ck_field{end+1} = 'history'; + ck_field{end+1} = sprintf('%s/history', class(obj1)); + elseif strcmp(field, 'val') + ck_field{end+1} = 'value'; + ck_field{end+1} = sprintf('%s/value', class(obj1)); + end + + %%%%% Check field if it is not in the exception list + if ~(any(utils.helper.ismember(ck_field, exception_list))) + + if isa(obj1(jj).(field), 'sym') + %%%%%%%%%% The property is a sym-object %%%%%%%%%% + if ~eq(obj1(jj).(field), obj2(jj).(field)) + result = false; + disaply_msg(obj1, jj, field) + return + end + + elseif isa(obj1(jj).(field), 'ltpda_obj') + %%%%%%%%%% The property is a ltpda-object %%%%%%%%%% + + %%%%% Check the length of the property + if length(obj1(jj).(field)) ~= length(obj2(jj).(field)) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The property [%s] of the object [%s] have not the same size %d <-> %d.', field, class(obj1), length(obj1(jj).(field)), length(obj2(jj).(field))); + result = false; + return + end + + %%%%% Special case for param-objects because the order shouldn't matter + if isa(obj1(jj).(field), 'param') + + if ~eqparam(obj1(jj).(field), obj2(jj).(field), exception_list, tol) + result = false; + disaply_msg(obj1, jj, field) + return + end + + else + %%%%% For each element of the property + for kk = 1:numel(obj1(jj).(field)) + if isempty(plin) + % Command with a list of exceptions + res = eq(obj1(jj).(field)(kk), obj2(jj).(field)(kk), exception_list{:}); + else + % Command with a PLIST + res = eq(obj1(jj).(field)(kk), obj2(jj).(field)(kk), plin); + end + if ~res + result = false; + disaply_msg(obj1, jj, field) + return + end + end + end + + elseif isstruct(obj1(jj).(field)) + %%%%%%%%%% The property is a structure %%%%%%%%%% + + if ~eqstruct(obj1(jj).(field), obj2(jj).(field), exception_list, tol) + result = false; + disaply_msg(obj1, jj, field) + return + end + + elseif iscell(obj1(jj).(field)) + %%%%%%%%%% The property is a cell array %%%%%%%%%% + + if ~eqcell(obj1(jj).(field), obj2(jj).(field), exception_list, tol) + result = false; + disaply_msg(obj1, jj, field) + return + end + + elseif isnumeric(obj1(jj).(field)) + %%%%%%%%%% The property is an elemental MATLAB datatype %%%%%%%%%% + if ~utils.math.isequal(obj1(jj).(field), obj2(jj).(field), tol) + result = false; + disaply_msg(obj1, jj, field) + return + end + else + %%%%%%%%%% The property is an elemental MATLAB datatype %%%%%%%%%% + if ~isequal(obj1(jj).(field), obj2(jj).(field)) + result = false; + disaply_msg(obj1, jj, field) + return + end + end + + end + end + + end +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Local Functions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: disaply_msg +% +% DESCRIPTION: Diesplay a message if the objects are not equal +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function disaply_msg(obj, obj_no, field) + import utils.const.* + if numel(obj) > 1 + utils.helper.msg(msg.PROC1, 'NOT EQUAL: %s.%s (%d. object)', class(obj(obj_no)), field, obj_no); + else + utils.helper.msg(msg.PROC1, 'NOT EQUAL: %s.%s', class(obj(obj_no)), field); + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: eqstruct +% +% DESCRIPTION: Equal method to compare structures +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function result = eqstruct(obj1, obj2, exception_list, tol) + + import utils.const.* + + %%%%% Check class + if ~strcmp(class(obj1), class(obj2)) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2)); + result = false; + return + end + + %%%%% Check length of obj1 and obj2 + fieldsA = fieldnames(obj1); + fieldsB = fieldnames(obj2); + if numel(fieldsA) ~= numel(fieldsB) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%d] <-> [%d]', class(obj1), numel(obj1), numel(obj2)); + result = false; + return + end + + result = true; + + for oo = 1:numel(obj1) + for ii = 1:numel(fieldsA) + + if isa(obj1(oo).(fieldsA{ii}), 'ltpda_obj') + %%%%%%%%%%%%% LTPDA objects + if ~eq(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), plist('exceptions', exception_list, 'tol', tol)) + result = false; + disaply_msg(obj1, oo, fieldsA{ii}) + return + end + + elseif isstruct(obj1(oo).(fieldsA{ii})) + %%%%%%%%%%%%% STRUCTURE + if ~eqstruct(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), exception_list, tol) + result = false; + disaply_msg(obj1, oo, fieldsA{ii}) + return + end + + elseif iscell(obj1(oo).(fieldsA{ii})) + %%%%%%%%%%%%% STRUCTURE + if ~eqcell(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), exception_list, tol) + result = false; + disaply_msg(obj1, oo, fieldsA{ii}) + return + end + elseif isnumeric(obj1(oo).(fieldsA{ii})) + if ~utils.math.isequal(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii}), tol) + result = false; + disaply_msg(obj1, oo, fieldsA{ii}) + return + end + + else + if ~isequal(obj1(oo).(fieldsA{ii}), obj2(oo).(fieldsA{ii})) + result = false; + disaply_msg(obj1, oo, fieldsA{ii}) + return + end + end + + end % over all fields + end % over all objects + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: eqcell +% +% DESCRIPTION: Equal method to compare structures +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function result = eqcell(obj1, obj2, exception_list, tol) + + import utils.const.* + + %%%%% Check class + if ~strcmp(class(obj1), class(obj2)) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2)); + result = false; + return + end + + %%%%% Check length of obj1 and obj2 + if numel(obj1) ~= numel(obj2) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%d] <-> [%d]', class(obj1), numel(obj1), numel(obj2)); + result = false; + return + end + + result = true; + + for ii = 1:numel(obj1) + + if isa(obj1{ii}, 'ltpda_obj') + %%%%%%%%%%%%% LTPDA objects + if ~eq(obj1{ii}, obj2{ii}, plist('exceptions', exception_list, 'tol', tol)) + result = false; + disaply_msg(obj1, ii, 'cell-object') + return + end + + elseif isstruct(obj1{ii}) + %%%%%%%%%%%%% STRUCTURE + if ~eqstruct(obj1{ii}, obj2{ii}, exception_list, tol) + result = false; + disaply_msg(obj1, ii, 'cell-object') + return + end + + elseif iscell(obj1{ii}) + %%%%%%%%%%%%% CELL + if ~eqcell(obj1{ii}, obj2{ii}, exception_list, tol) + result = false; + disaply_msg(obj1, ii, 'cell-object') + return + end + + elseif isnumeric(obj1{ii}) + %%%%%%%%%%%%% Numberic + if ~utils.math.isequal(obj1{ii}, obj2{ii}, tol) + result = false; + disaply_msg(obj1, ii, 'cell-object') + return + end + + else + if ~isequal(obj1{ii}, obj2{ii}) + result = false; + disaply_msg(obj1, ii, 'cell-object') + return + end + end + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: eqparam +% +% DESCRIPTION: Equal method to compare param-objects. The order of the +% param-objects doesn't matter. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function result = eqparam(obj1, obj2, exception_list, tol) + + import utils.const.* + + %%%%% Check class + if ~strcmp(class(obj1), class(obj2)) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The objects are not from the same class. [%s] <-> [%s]', class(obj1), class(obj2)); + result = false; + return + end + + %%%%% Check length of obj1 and obj2 + if numel(obj1) ~= numel(obj2) + utils.helper.msg(msg.PROC1, 'NOT EQUAL: The size of the %s-object''s. [%d] <-> [%d]', class(obj1), numel(obj1), numel(obj2)); + result = false; + return + end + + result = true; + + for oo = 1:numel(obj1) + + found = false; + for ii = 1:numel(obj2) + + if strcmp(obj1(oo).key, obj2(ii).key) + allparts = true; + fields = fieldnames(obj1(oo)); + for ff = 1:numel(fields) + field = fields{ff}; + + ck_field = {field, sprintf('%s/%s', class(obj1), field)}; + if ~(any(utils.helper.ismember(ck_field, exception_list))) + + if strcmp(field, 'val') + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% Compare only the current value + val1 = obj1(oo).getVal(); + val2 = obj2(ii).getVal(); + if isa(val1, 'ltpda_obj') + %%%%%%%%%%%%% LTPDA objects + allparts = allparts && eq(val1, val2, plist('exceptions', exception_list, 'tol', tol)); + + elseif isstruct(val1) + %%%%%%%%%%%%% STRUCTURE + allparts = allparts && eqstruct(val1, val2, exception_list, tol); + + elseif iscell(val1) + %%%%%%%%%%%%% CELL + allparts = allparts && eqcell(val1, val2, exception_list, tol); + elseif isnumeric(val1) + %%%%%%%%%%%%% Numeric + allparts = allparts && utils.math.isequal(val1, val2, tol); + else + allparts = allparts && isequal(val1, val2); + end + + %%%%% Check the properties of the paramValue Object + if isa(obj1(oo).val, 'paramValue') + allparts = allparts && eqstruct(obj1(oo).val.property, obj2(ii).val.property, exception_list, tol); + end + + continue; + end + + if isa(obj1(oo).(field), 'ltpda_obj') + %%%%%%%%%%%%% LTPDA objects + allparts = allparts && eq(obj1(oo).(field), obj2(ii).(field), plist('exceptions', exception_list, 'tol', tol)); + + elseif isstruct(obj1(oo).(field)) + %%%%%%%%%%%%% STRUCTURE + allparts = allparts && eqstruct(obj1(oo).(field), obj2(ii).(field), exception_list, tol); + + elseif iscell(obj1(oo).(field)) + %%%%%%%%%%%%% CELL + allparts = allparts && eqcell(obj1(oo).(field), obj2(ii).(field), exception_list, tol); + + elseif isnumeric(obj1(oo).(field)) + %%%%%%%%%%%%% Numeric + allparts = allparts && utils.math.isequal(obj1(oo).(field), obj2(ii).(field), tol); + else + allparts = allparts && isequal(obj1(oo).(field), obj2(ii).(field)); + end + + end + + end + if allparts + found = true; + end + end + + end % inner-loop + + if ~found + result = false; + disaply_msg(obj1, oo, ['key: ''' obj1(oo).key '''']) + return + end + + end % outer-loop + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: getInfo +% +% DESCRIPTION: Get Info Object +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function ii = getInfo(varargin) + if nargin == 1 && strcmpi(varargin{1}, 'None') + sets = {}; + pl = []; + else + sets = {'Default'}; + pl = getDefaultPlist; + end + % Build info object + ii = minfo(mfilename, 'plist', 'ltpda', utils.const.categories.relop, '$Id: eq.m,v 1.27 2011/04/08 08:56:21 hewitson Exp $', sets, pl); + ii.setModifier(false); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: getDefaultPlist +% +% DESCRIPTION: Get Default Plist +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function plo = getDefaultPlist() + plo = plist(); + + % Exceptions + p = param({'Exceptions', 'Test the objects without the given property names'}, paramValue.EMPTY_CELL); + plo.append(p); + + % Tolerance + p = param({'Tol', 'Test double values with the given tolerance'}, paramValue.DOUBLE_VALUE(eps(1))); + plo.append(p); + +end +