changeset 20183:72ccbd36e23c

Return a column vector by default for Matlab compatibility (bug #44425, bug #44453). Document that only unique elements are returned from set functions. * NEWS: Announce change in default orientation of return values. * intersect.m, setdiff.m, setxor.m, union.m: Return a column vector by default unless the input is explicitly a row vector. Change docstring to note that only unique, non-duplicative elements are returned.
author Rik <rik@octave.org>
date Fri, 20 Mar 2015 18:23:01 -0700
parents 7aaf756b1532
children 0f2cbcb14a21
files NEWS scripts/set/intersect.m scripts/set/setdiff.m scripts/set/setxor.m scripts/set/union.m
diffstat 5 files changed, 43 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS
+++ b/NEWS
@@ -141,6 +141,10 @@
     There is still one difference:  Matlab switches to '%e' and Octave
     switches to '%g'.
 
+ ** The functions intersect, setdiff, setxor, and union now return a
+    column vector as output unless the input was a row vector.  This change
+    was made for Matlab compatibility.
+
  ** The archive family of functions (bzip2, gzip, zip, tar) and their
     unpacking routines (bunzip2, gunzip, unzip, untar, unpack) have
     been recoded.  Excepting unpack, the default is now to place files
--- a/scripts/set/intersect.m
+++ b/scripts/set/intersect.m
@@ -22,11 +22,11 @@
 ## @deftypefnx {Function File} {@var{c} =} intersect (@var{a}, @var{b}, "rows")
 ## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} intersect (@dots{})
 ##
-## Return the elements common to both @var{a} and @var{b} sorted in ascending
-## order.
+## Return the unique elements common to both @var{a} and @var{b} sorted in
+## ascending order.
 ##
-## If @var{a} and @var{b} are both column vectors then return a column vector;
-## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## If @var{a} and @var{b} are both row vectors then return a row vector;
+## Otherwise, return a column vector.  The inputs may also be cell arrays of
 ## strings.
 ##
 ## If the optional input @qcode{"rows"} is given then return the common rows of
@@ -50,7 +50,7 @@
     c = ia = ib = [];
   else
     by_rows = nargin == 3;
-    iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
+    isrowvec = isvector (a) && isvector (b) && isrow (a) && isrow (b);
 
     ## Form A and B into sets
     if (nargout > 1)
@@ -85,7 +85,7 @@
     endif
 
     ## Adjust output orientation for Matlab compatibility
-    if (! by_rows && ! iscol)
+    if (! by_rows && isrowvec)
       c = c.';
     endif
   endif
@@ -99,8 +99,8 @@
 %! b = 2:5;
 
 %!assert (size (intersect (a, b)), [1 3])
-%!assert (size (intersect (a', b)), [1 3])
-%!assert (size (intersect (a, b')), [1 3])
+%!assert (size (intersect (a', b)), [3 1])
+%!assert (size (intersect (a, b')), [3 1])
 %!assert (size (intersect (a', b')), [3 1])
 
 ## Test multi-dimensional arrays
@@ -108,7 +108,7 @@
 %! a = rand (3,3,3);
 %! b = a;
 %! b(1,1,1) = 2;
-%! assert (intersect (a, b), sort (a(2:end)));
+%! assert (intersect (a, b), sort (a(2:end)'));
 
 ## Test the routine for index vectors ia and ib
 %!test
--- a/scripts/set/setdiff.m
+++ b/scripts/set/setdiff.m
@@ -21,11 +21,11 @@
 ## @deftypefn  {Function File} {@var{c} =} setdiff (@var{a}, @var{b})
 ## @deftypefnx {Function File} {@var{c} =} setdiff (@var{a}, @var{b}, "rows")
 ## @deftypefnx {Function File} {[@var{c}, @var{ia}] =} setdiff (@dots{})
-## Return the elements in @var{a} that are not in @var{b} sorted in
+## Return the unique elements in @var{a} that are not in @var{b} sorted in
 ## ascending order.
 ##
-## If @var{a} and @var{b} are both column vectors return a column vector;
-## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## If @var{a} is a row vector return a column vector;
+## Otherwise, return a column vector.  The inputs may also be cell arrays of
 ## strings.
 ##
 ## If the optional input @qcode{"rows"} is given then return the rows in
@@ -49,7 +49,7 @@
   [a, b] = validsetargs ("setdiff", a, b, varargin{:});
 
   by_rows = nargin == 3;
-  iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
+  isrowvec = isvector (a) && isrow (a);
 
   if (by_rows)
     if (nargout > 1)
@@ -89,10 +89,10 @@
         ia(idx(dups)) = [];
       endif
       ## Reshape if necessary for Matlab compatibility.
-      if (iscol)
+      if (isrowvec)
+        c = c(:).';
+      else
         c = c(:);
-      else
-        c = c(:).';
       endif
     endif
   endif
@@ -120,11 +120,11 @@
 %!assert (setdiff ([1:5]', 2), [1;3;4;5])
 %!assert (setdiff ([1:5], [2:3]), [1,4,5])
 %!assert (setdiff ([1:5], [2:3]'), [1,4,5])
-%!assert (setdiff ([1:5]', [2:3]), [1,4,5])
+%!assert (setdiff ([1:5]', [2:3]), [1;4;5])
 %!assert (setdiff ([1:5]', [2:3]'), [1;4;5])
 
 %!test
 %! a = rand (3,3,3);
 %! b = a(1);
-%! assert (setdiff (a, b), sort (a(2:end)));
+%! assert (setdiff (a, b), sort (a(2:end)'));
 
--- a/scripts/set/setxor.m
+++ b/scripts/set/setxor.m
@@ -23,11 +23,11 @@
 ## @deftypefnx {Function File} {@var{c} =} setxor (@var{a}, @var{b}, "rows")
 ## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@dots{})
 ##
-## Return the elements exclusive to sets @var{a} or @var{b} sorted in
+## Return the unique elements exclusive to sets @var{a} or @var{b} sorted in
 ## ascending order.
 ##
-## If @var{a} and @var{b} are both column vectors return a column vector;
-## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## If @var{a} and @var{b} are both row vectors then return a row vector;
+## Otherwise, return a column vector.  The inputs may also be cell arrays of
 ## strings.
 ##
 ## If the optional input @qcode{"rows"} is given then return the rows exclusive
@@ -50,7 +50,7 @@
   [a, b] = validsetargs ("setxor", a, b, varargin{:});
 
   by_rows = nargin == 3;
-  iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
+  isrowvec = isvector (a) && isvector (b) && isrow (a) && isrow (b);
 
   ## Form A and B into sets.
   if (nargout > 1)
@@ -91,7 +91,7 @@
       endif
 
       ## Adjust output orientation for Matlab compatibility
-      if (! iscol)
+      if (isrowvec)
         c = c.';
       endif
     endif
@@ -112,8 +112,8 @@
 %! a = [3, 1, 4, 1, 5];
 %! b = [1, 2, 3, 4];
 %! [c, ia, ib] = setxor (a, b.');
-%! assert (c, [2, 5]);
-%! assert (c, sort ([a(ia), b(ib)]));
+%! assert (c, [2; 5]);
+%! assert (c, sort ([a(ia)'; b(ib)']));
 
 %!test
 %! a = [1 2; 4 5; 1 3];
@@ -156,8 +156,8 @@
 %! y = 2:5;
 
 %!assert (size (setxor (x, y)), [1 3])
-%!assert (size (setxor (x', y)), [1 3])
-%!assert (size (setxor (x, y')), [1 3])
+%!assert (size (setxor (x', y)), [3 1])
+%!assert (size (setxor (x, y')), [3 1])
 %!assert (size (setxor (x', y')), [3 1])
 
 ## Test multi-dimensional arrays
@@ -165,5 +165,5 @@
 %! a = rand (3,3,3);
 %! b = a;
 %! b(1,1,1) = 2;
-%! assert (intersect (a, b), sort (a(2:end)));
+%! assert (intersect (a, b), sort (a(2:end)'));
 
--- a/scripts/set/union.m
+++ b/scripts/set/union.m
@@ -22,11 +22,11 @@
 ## @deftypefnx {Function File} {@var{c} =} union (@var{a}, @var{b}, "rows")
 ## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} union (@dots{})
 ##
-## Return the elements that are in either @var{a} or @var{b} sorted in
-## ascending order with duplicates removed.
+## Return the unique elements that are in either @var{a} or @var{b} sorted in
+## ascending order.
 ##
-## If @var{a} and @var{b} are both column vectors return a column vector;
-## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## If @var{a} and @var{b} are both row vectors then return a row vector;
+## Otherwise, return a column vector.  The inputs may also be cell arrays of
 ## strings.
 ##
 ## If the optional input @qcode{"rows"} is given then return rows that are in
@@ -51,14 +51,14 @@
   [a, b] = validsetargs ("union", a, b, varargin{:});
 
   by_rows = nargin == 3;
-  iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
+  isrowvec = isvector (a) && isvector (b) && isrow (a) && isrow (b);
 
   if (by_rows)
     y = [a; b];
   else
     y = [a(:); b(:)];
     ## Adjust output orientation for Matlab compatibility
-    if (! iscol)
+    if (isrowvec)
       y = y.';
     endif
   endif
@@ -76,23 +76,23 @@
 
 
 %!assert (union ([1, 2, 4], [2, 3, 5]), [1, 2, 3, 4, 5])
-%!assert (union ([1; 2; 4], [2, 3, 5]), [1, 2, 3, 4, 5])
+%!assert (union ([1; 2; 4], [2, 3, 5]), [1; 2; 3; 4; 5])
 %!assert (union ([1; 2; 4], [2; 3; 5]), [1; 2; 3; 4; 5])
-%!assert (union ([1, 2, 3], [5; 7; 9]), [1, 2, 3, 5, 7, 9])
+%!assert (union ([1, 2, 3], [5; 7; 9]), [1; 2; 3; 5; 7; 9])
 
 ## Test multi-dimensional arrays
 %!test
 %! a = rand (3,3,3);
 %! b = a;
 %! b(1,1,1) = 2;
-%! assert (union (a, b), sort ([a(1:end), 2]));
+%! assert (union (a, b), sort ([a(1:end)'; 2]));
 
 %!test
 %! a = [3, 1, 4, 1, 5];
 %! b = [1, 2, 3, 4];
 %! [y, ia, ib] = union (a, b.');
-%! assert (y, [1, 2, 3, 4, 5]);
-%! assert (y, sort ([a(ia), b(ib)]));
+%! assert (y, [1; 2; 3; 4; 5]);
+%! assert (y, sort ([a(ia)'; b(ib)']));
 
 ## Test common input validation for set routines contained in validsetargs
 %!error <cell array of strings cannot be combined> union ({"a"}, 1)