changeset 24326:a35bceb4b519

isequal.m, isequaln.m: Fix comparsion of struct arrays (bug #51403). * isequal.m, isequaln.m: For scalar structs, pass each field directly to recursive isequalX. For struct arrays, each element for a given field may have a different class of value. In this case, wrap results of field in to a cell array and pass cell array to isequalX.
author Rik <rik@octave.org>
date Tue, 28 Nov 2017 12:57:51 -0800
parents bc65aa8a5ff1
children f38165f34ff1
files scripts/general/isequal.m scripts/general/isequaln.m
diffstat 2 files changed, 99 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/general/isequal.m	Mon Nov 27 23:52:54 2017 -0500
+++ b/scripts/general/isequal.m	Tue Nov 28 12:57:51 2017 -0800
@@ -119,12 +119,23 @@
 
         ## Test that all field values are equal.  Slow because of recursion.
         if (t)
-          for fldnm = s_fnm_x.'
-            t = isequal (x.(fldnm{1}), y.(fldnm{1}));
-            if (! t)
-              break;
-            endif
-          endfor
+          if (isscalar (x))
+            for fldnm = s_fnm_x.'
+              t = isequal (x.(fldnm{1}), y.(fldnm{1}));
+              if (! t)
+                break;
+              endif
+            endfor
+          else
+            ## struct arrays have to have the contents of each field wrapped
+            ## in a cell since it expands to a collection of values.
+            for fldnm = s_fnm_x.'
+              t = isequal ({x.(fldnm{1})}, {y.(fldnm{1})});
+              if (! t)
+                break;
+              endif
+            endfor
+          endif
         endif
 
       elseif (iscellstr (x) && iscellstr (y))
@@ -197,18 +208,35 @@
         ## Test that all field values are equal.  Slow because of recursion.
         if (t)
           args = cell (1, 1 + nvarargin);
-          for fldnm = fnm_x.'
-            args(1) = x.(fldnm{1});
-            for argn = 1:nvarargin
-              args(argn+1) = varargin{argn}.(fldnm{1});
-            endfor
+          if (isscalar (x))
+            for fldnm = fnm_x.'
+              args{1} = x.(fldnm{1});
+              for argn = 1:nvarargin
+                args{argn+1} = varargin{argn}.(fldnm{1});
+              endfor
+
+              t = isequal (args{:});
 
-            t = isequal (args{:});
+              if (! t)
+                break;
+              endif
+            endfor
+          else
+            ## struct arrays have to have the contents of each field wrapped
+            ## in a cell since it expands to a collection of values.
+            for fldnm = fnm_x.'
+              args{1} = { x.(fldnm{1}) };
+              for argn = 1:nvarargin
+                args{argn+1} = { varargin{argn}.(fldnm{1}) };
+              endfor
 
-            if (! t)
-              break;
-            endif
-          endfor
+              t = isequal (args{:});
+
+              if (! t)
+                break;
+              endif
+            endfor
+          endif
         endif
 
       elseif (iscellstr (x) && all (cellfun (@iscellstr, varargin)))
@@ -367,6 +395,17 @@
 %! assert (isequal (x, y), false);
 %! assert (isequal (x, x, y), false);
 
+## struct array
+%!test
+%! x(1).a = 'A';
+%! x(2).a = magic (3);
+%! assert (isequal (x, x), true);
+%! assert (isequal (x, x, x), true);
+%! y = x;
+%! y(2).a = { magic(3) };
+%! assert (isequal (x, y), false);
+%! assert (isequal (x, x, y), false);
+
 ## test cellstr
 %!assert (isequal (cell (1,1), cell (1,1)), true)
 %!assert (isequal (cell (1,1), cell (1,2)), false)
--- a/scripts/general/isequaln.m	Mon Nov 27 23:52:54 2017 -0500
+++ b/scripts/general/isequaln.m	Tue Nov 28 12:57:51 2017 -0800
@@ -125,12 +125,23 @@
 
         ## Test that all field values are equal.  Slow because of recursion.
         if (t)
-          for fldnm = s_fnm_x.'
-            t = isequaln (x.(fldnm{1}), y.(fldnm{1}));
-            if (! t)
-              break;
-            endif
-          endfor
+          if (isscalar (x))
+            for fldnm = s_fnm_x.'
+              t = isequaln (x.(fldnm{1}), y.(fldnm{1}));
+              if (! t)
+                break;
+              endif
+            endfor
+          else
+            ## struct arrays have to have the contents of each field wrapped
+            ## in a cell since it expands to a collection of values.
+            for fldnm = s_fnm_x.'
+              t = isequaln ({x.(fldnm{1})}, {y.(fldnm{1})});
+              if (! t)
+                break;
+              endif
+            endfor
+          endif
         endif
 
       elseif (iscellstr (x) && iscellstr (y))
@@ -207,18 +218,35 @@
         ## Test that all field values are equal.  Slow because of recursion.
         if (t)
           args = cell (1, 1 + nvarargin);
-          for fldnm = fnm_x.'
-            args(1) = x.(fldnm{1});
-            for argn = 1:nvarargin
-              args(argn+1) = varargin{argn}.(fldnm{1});
-            endfor
+          if (isscalar (x))
+            for fldnm = fnm_x.'
+              args{1} = x.(fldnm{1});
+              for argn = 1:nvarargin
+                args{argn+1} = varargin{argn}.(fldnm{1});
+              endfor
+
+              t = isequaln (args{:});
 
-            t = isequaln (args{:});
+              if (! t)
+                break;
+              endif
+            endfor
+          else
+            ## struct arrays have to have the contents of each field wrapped
+            ## in a cell since it expands to a collection of values.
+            for fldnm = fnm_x.'
+              args{1} = { x.(fldnm{1}) };
+              for argn = 1:nvarargin
+                args{argn+1} = { varargin{argn}.(fldnm{1}) };
+              endfor
 
-            if (! t)
-              break;
-            endif
-          endfor
+              t = isequaln (args{:});
+
+              if (! t)
+                break;
+              endif
+            endfor
+          endif
         endif
 
       elseif (iscellstr (x) && all (cellfun (@iscellstr, varargin)))