this function compares the structure and contents of multi-dimensional and nested cells this function has been modeled after compare_structs.m (S. Tomic) cell1 and cell2 are the only required arguments the rest of the arguments are maintained for compatibility with compar_struct, and are passed onto compare_struct in the event that cell contents are of class 'struct'. tag,value pairs that specify how the structs will be compared. supported tags and values: 'values' (true or false): specifies whether field values will be compared or not. 'substruct' (true or false): specifies whether to check only whether struct1 is contained in struct2 (struct2 simply has more fields and values than struct1 but otherwise are equal). Otherwise the structs will be compared for an exact match. 'types' (true or false): specifies whether or not to check the type (class) of the fields for a positive match. This can only be set to false if 'values' is also false. Otherwise, types will automatically be checked. this function first checks to see if both inputs are cells, and then compares the structure (# dimensions and size in each dimension) of the provided cells. Any inequality in # of dimensions or size in any dimension will be viewed as a cell inequality. If cells are of identical structure, they will be converted to a vector [new_vect = cellN(:)], and then each element from both cells will be compared on variable class and then content. OUTPUTS cellsAreEqual - 1 or 0, whether or not cell equality is true firstViolation - the index in the vector-transformed cells where the first inequality of content or variable class was found. In the case of cells within cells, this function is called recursively. when recursing on self, upon finding an error, the index in the topmost parent cell where the inequality was found is returned in firstViolation. In the case that the structure of the cells differs, or the case that either or both of the inputs are not cells, firstViolation = 0; violationReason - provides a concise descriptor of the type of violation that occurred. NOTE: if one cell is a transposition of the other, they will be found unequal, either by size, or by contents
0001 function [cellsAreEqual,firstViolation,violationReason] = compare_cells(cell1,cell2) 0002 0003 % this function compares the structure and contents of multi-dimensional and nested cells 0004 % 0005 % this function has been modeled after compare_structs.m (S. Tomic) 0006 % 0007 % cell1 and cell2 are the only required arguments 0008 % 0009 % the rest of the arguments are maintained for compatibility with 0010 % compar_struct, and are passed onto compare_struct in the event that cell 0011 % contents are of class 'struct'. tag,value pairs that specify how the 0012 % structs will be compared. 0013 % supported tags and values: 0014 % 0015 % 'values' (true or false): specifies whether field values will be 0016 % compared or not. 0017 % 'substruct' (true or false): specifies whether to check only whether 0018 % struct1 is contained in struct2 (struct2 simply has more fields and 0019 % values than struct1 but otherwise are equal). Otherwise the structs 0020 % will be compared for an exact match. 0021 % 'types' (true or false): specifies whether or not to check the type 0022 % (class) of the fields for a positive match. This can only be set to 0023 % false if 'values' is also false. Otherwise, types will 0024 % automatically be checked. 0025 % 0026 % this function first checks to see if both inputs are cells, and then 0027 % compares the structure (# dimensions and size in each dimension) of the 0028 % provided cells. Any inequality in # of dimensions or size in any 0029 % dimension will be viewed as a cell inequality. If cells are of identical 0030 % structure, they will be converted to a vector [new_vect = cellN(:)], and 0031 % then each element from both cells will be compared on variable class and 0032 % then content. 0033 % 0034 % OUTPUTS 0035 % cellsAreEqual - 1 or 0, whether or not cell equality is true 0036 % firstViolation - the index in the vector-transformed cells where the 0037 % first inequality of content or variable class was found. In the 0038 % case of cells within cells, this function is called recursively. 0039 % when recursing on self, upon finding an error, the index in the 0040 % topmost parent cell where the inequality was found is returned in 0041 % firstViolation. In the case that the structure of the cells 0042 % differs, or the case that either or both of the inputs are not 0043 % cells, firstViolation = 0; 0044 % violationReason - provides a concise descriptor of the type of 0045 % violation that occurred. 0046 % 0047 % NOTE: if one cell is a transposition of the other, they will be found 0048 % unequal, either by size, or by contents 0049 0050 % Copyright (c) 2009-2012 The Regents of the University of California 0051 % All Rights Reserved. 0052 % 0053 % FB 2009.02.24 0054 % PJ 29Dec2014 - added check to see if both cells are empty 0055 0056 % 0057 % initialize variables 0058 % 0059 cellsAreEqual = 0; 0060 firstViolation = 0; 0061 violationReason = ''; 0062 0063 numberTypes = {'int8','uint8','int16','uint16','int32','uint32','int64',... 0064 'uint64','double'}; 0065 0066 if (nargin > 2) 0067 for iarg = 1:nargin-2 0068 switch(varargin{iarg}) 0069 case 'values' 0070 checkValues = varargin{iarg+1}; 0071 case 'substruct' 0072 checkSubstruct = varargin{iarg+1}; 0073 case 'types' 0074 checkTypes = varargin{iarg+1}; 0075 end 0076 end 0077 end 0078 0079 if ~exist('checkValues','var'), checkValues = true; end 0080 if ~exist('checkSubstruct','var'), checkSubstruct = true; end 0081 if ~exist('checkTypes','var'), checkTypes = true; end 0082 0083 % 0084 % check to see if inputs are cells 0085 % 0086 if ~iscell(cell1) && ~iscell(cell2) 0087 violationReason = 'neither input is of type ''cell'''; 0088 return 0089 elseif ~iscell(cell1) 0090 violationReason = 'cell1 is not of type ''cell'''; 0091 return 0092 elseif ~iscell(cell2) 0093 violationReason = 'cell2 is not of type ''cell'''; 0094 return 0095 end 0096 0097 % 0098 % Check to see if they are both empty 0099 % It turns out that empty cells can have different sizes, e.g. 0x0 or 1x0 0100 % 0101 % Both are empty, return equality 0102 if isempty(cell1) && isempty(cell2) 0103 cellsAreEqual = 1; 0104 return 0105 end 0106 0107 % 0108 % compare sizes of cells 0109 % 0110 s1 = size(cell1); 0111 s2 = size(cell2); 0112 0113 % if cells are not the same exact size, they will be treated as unequal 0114 % NOTE: transposed cell arrays will not be treated as equal 0115 if length(s1) ~= length(s2) 0116 violationReason = 'cells have different number of dimensions'; 0117 return 0118 end 0119 0120 sm = (s1 == s2); 0121 if ~all(sm) 0122 violationReason = 'cells have different sizes in one or more dimension'; 0123 return 0124 end 0125 0126 % convert cells to vectors 0127 v1 = cell1(:); 0128 v2 = cell2(:); 0129 nv1 = length(v1); 0130 nv2 = length(v2); 0131 if nv1 ~= nv1 0132 violationReason = 'vectors (converted cells) have different sizes'; 0133 return 0134 end 0135 0136 % step through cells, compare at each index 0137 for i=1:nv1 0138 0139 % compare cell class 0140 c1 = class(v1{i}); 0141 c2 = class(v2{i}); 0142 if isempty(strmatch(c1,c2,'exact')) 0143 firstViolation = i; 0144 violationReason = sprintf(['cell contents have different class at '... 0145 'index %d'],i); 0146 return 0147 end 0148 0149 % compare cell contents 0150 same = 1; 0151 switch c1 0152 case numberTypes 0153 if any(size(v1{i}) ~= size(v2{i})) || ~all(v1{i} == v2{i}) 0154 same = 0; 0155 subVioReason = sprintf('%s differed',c1); 0156 end 0157 case 'char' 0158 if ~strcmp(v1{i},v2{i}) 0159 same = 0; 0160 subVioReason = 'strings differed'; 0161 end 0162 case 'struct' 0163 [structsAreEqual,subStructVio,subVioReason] = compare_structs(... 0164 v1{i},v2{i},'values',checkValues,'substruct',checkSubstruct,... 0165 'types',checkTypes); 0166 if ~structsAreEqual, same = 0; end 0167 case 'cell' 0168 [subCellsEqual,subCellVio,subVioReason] = compare_cells(v1{i},v2{i}); 0169 if ~subCellsEqual, same = 0; end 0170 case 'logical' 0171 if v1{i} ~= v2{i} 0172 same = 0; 0173 subVioReason = sprintf('logical vars differed'); 0174 end 0175 otherwise 0176 same = 0; 0177 subVioReason = sprintf('class %s not supported',c1); 0178 end 0179 0180 if ~same 0181 firstViolation = i; 0182 violationReason = sprintf('cell contents differed (%s)',subVioReason); 0183 return 0184 end 0185 end % for i=1:nv1 0186 0187 % no differences found, return equality 0188 cellsAreEqual = 1;