MatrixBerryCore
structcomparevec.m
Go to the documentation of this file.
1 function [isEqualVec,reportStr]= structcomparevec(SX,SY,absTol,relTol)
2 if nargin<3
3  absTol=0;
4 end
5 if nargin<4
6  relTol=[];
7 end
8 %
9 if ~isequal(size(SX),size(SY))
10  isEqualVec=false;
11  reportStr={'sizes are different'};
12  return;
13 end
14 [isEqualVec,reportStrList]=structcompare1darray(SX(:),SY(:),absTol,relTol);
15 nReports=length(reportStrList);
16 if nReports>1
17  reportStrList(1:end-1)=cellfun(@(x)horzcat(x,sprintf('\n')),...
18  reportStrList(1:end-1),'UniformOutput',false);
19 end
20 if nReports>0
21  reportStr=[reportStrList{:}];
22 else
23  reportStr='';
24 end
25 end
26 %
27 function [isEqualVec,reportStrList]= structcompare1darray(SX,SY,absTol,relTol)
28 nElem=numel(SX);
29 [isEqualList,reportStrList]=arrayfun(@(x,y)structcomparescalar(x,y,absTol,relTol),SX,SY,'UniformOutput',false);
30 nReportsList=num2cell(cellfun('prodofsize',reportStrList));
31 isEqualVec=[isEqualList{:}];
32 isEqualList=cellfun(@(x,y)repmat(x,1,y),isEqualList,nReportsList,'UniformOutput',false);
33 itemIndList=cellfun(@(x,y)repmat(x,1,y),num2cell(1:nElem).',nReportsList,'UniformOutput',false);
34 nReports=sum([nReportsList{:}]);
35 reportStrList=[reportStrList{:}];
36 itemIndVec=[itemIndList{:}];
37 isnEqualVec=~[isEqualList{:}];
38 for iReport=1:nReports
39  if isnEqualVec(iReport)
40  reportStrList{iReport}=sprintf('(%d)%s',itemIndVec(iReport),reportStrList{iReport});
41  end
42 end
43 %
44 end
45 %
46 function [isEqual,reportStrList]= structcomparescalar(SX,SY,absTol,relTol)
47 import mxberry.core.cell.cell2tablestr;
48 import mxberry.core.throwerror;
49 if ~mxberry.core.checksize(SX,SY,[1 1])
50  throwerror('wrongInput','both inputs are expected to be of size [1,1]');
51 end
52 %
53 if ~(isstruct(SX)&&isstruct(SY))
54  throwerror('wrongInput','both inputs are expected to be structures');
55 end
56 %
57 reportStrList={};
58 fieldXList=sort(fieldnames(SX).');
59 fieldYList=sort(fieldnames(SY).');
60 isEqual=isequal(fieldXList,fieldYList);
61 if ~isEqual
62  %
63  fieldXMinusYList=setdiff(fieldXList,fieldYList);
64  fieldYMinusXList=setdiff(fieldYList,fieldXList);
65  %
66  reportStrList={['Field names are different, left-right:',...
67  cell2tablestr('',fieldXMinusYList,'|'),...
68  ', right-left: ',cell2tablestr('',fieldYMinusXList,'|')]};
69  return;
70 end
71 %
72 nFields=length(fieldXList);
73 reportAddList=cell(1,nFields);
74 for iField=1:nFields
75  fieldName=fieldXList{iField};
76  [isEqualCur,reportStrCurList]=compfun(SX.(fieldName),SY.(fieldName),absTol,relTol);
77  isEqual=isEqual&&isEqualCur;
78  if ~isEqualCur
79  if ~isstruct(SX.(fieldName))
80  reportStrCurList=strcat('--> ',reportStrCurList);
81  end
82  reportStrCurList=strcat('.',fieldName,reportStrCurList);
83  reportAddList{iField}=reportStrCurList;
84  end
85 end
86 reportStrList=[reportStrList,reportAddList{:}];
87 end
88 
89 function [isEqual,reportStr]=compfun(x,y,absTol,relTol)
90 import mxberry.core.absrelcompare;
91 %
92 reportStr='';
93 isEqual=false;
94 xClass=class(x);
95 yClass=class(y);
96 %
97 if ~isequal(xClass,yClass)
98  reportStr='Different types';
99  return;
100 end
101 %
102 if isnumeric(x)
103  xSizeVec=size(x);
104  ySizeVec=size(y);
105  if ~isequal(xSizeVec,ySizeVec)
106  reportStr=sprintf('Different sizes (left: %s, right: %s)',...
107  mat2str(xSizeVec),mat2str(ySizeVec));
108  return;
109  end
110  x=toNumericSupportingMinus(x);
111  y=toNumericSupportingMinus(y);
112  if ismember(xClass,{'double','single'})
113  isNanX=isnan(x);
114  isNanY=isnan(y);
115  if ~isequal(isNanX,isNanY)
116  reportStr='Nans are on the different places';
117  return;
118  end
119  isMinusInfX=x==-Inf;
120  isMinusInfY=y==-Inf;
121  if ~isequal(isMinusInfX,isMinusInfY)
122  reportStr='-Infs are on the different places';
123  return;
124  end
125  isInfX=x==Inf;
126  isInfY=y==Inf;
127  if ~isequal(isInfX,isInfY)
128  reportStr='-Inf are on the different places';
129  return;
130  end
131  isCompX=~(isNanX|isMinusInfX|isInfX);
132  isCompY=~(isNanY|isMinusInfY|isInfY);
133  else
134  isCompX=true(size(x));
135  isCompY=true(size(y));
136  end
137  %
138  [isEqual, ~, ~, ~, ~, reportStr] = absrelcompare(x(isCompX), ...
139  y(isCompY), absTol, relTol, @abs);
140  %
141  if ~isEqual
142  reportStr = horzcat('Max. ', reportStr);
143  return;
144  end
145 elseif isstruct(x)
146  [isEqual,reportStr]=mxberry.core.struct.structcompare(x,y,absTol,relTol);
147  if ~isEqual
148  return;
149  end
150 elseif iscell(x)&&~iscellstr(x)
151  nElems=numel(x);
152  if nElems==0
153  isEqual=true;
154  return;
155  end
156  for iElem=1:nElems
157  [isEqual,reportStr]=compfun(x{iElem},y{iElem},absTol,relTol);
158  if ~isEqual
159  break;
160  end
161  end
162  if ~isEqual
163  reportStr=strcat('{',num2str(iElem),'}',reportStr);
164  return;
165  end
166 elseif isa(x,'function_handle')
167  isEqual=isequal(func2str(x),func2str(y));
168  if ~isEqual
169  reportStr='values are different';
170  return;
171  end
172 elseif ~isequal(x,y)
173  reportStr='values are different';
174  return;
175 end
176 isEqual=true;
177 end
178 function x=toNumericSupportingMinus(x)
179 if isa(x,'uint64')||isa(x,'int64')
180  x=double(x);
181 end
182 end
function num2cell(in inpArray, in varargin)
NUM2CELL is an extension of Matlab built-in function "num2cell" designed to work correctly with empty...
function structcompare1darray(in SX, in SY, in absTol, in relTol)
STRUCTCOMPARE1D compares 1-dimentional structural arrays.
function repmat(in inpArray, in varargin)
function structcomparescalar(in SX, in SY, in absTol, in relTol)
STRUCTCOMPARE1D compares the scalar structures.
function structcomparevec(in SX, in SY, in absTol, in relTol)
STRUCTCOMPARE compares two structures using the specified tolerance.