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
+