# HG changeset patch # User Rik # Date 1562884178 25200 # Node ID 67e5e997a3bfcb00035a538623dad5332d4037b6 # Parent d29a12e8b6d9322bacbf275d883332553b68398d setdiff.m: Accept a "legacy" flag for Matlab compatibility. * NEWS: Announce change to setdiff return values when given "rows" argument. Announce "legacy" flag. * setdiff.m Add new calling form and explanation of "legacy" option to docstring. Allow up to 4 inputs in input validation. Check for "legacy" in input options and set variable optlegacy. Set variable isrowvec based on optlegacy and orientation of inputs. Add BIST tests for "rows" and "legacy" inputs. diff -r d29a12e8b6d9 -r 67e5e997a3bf NEWS --- a/NEWS Thu Jul 11 15:05:30 2019 -0700 +++ b/NEWS Thu Jul 11 15:29:38 2019 -0700 @@ -53,9 +53,14 @@ behavior, or Matlab behavior from releases prior to R2012b, can be obtained by using the `"legacy"` flag. +- The function `setdiff` with the `"rows"` argument now returns Matlab + compatible results. The previous Octave behavior, or Matlab behavior + from releases prior to R2012b, can be obtained by using the `"legacy"` + flag. + - The functions `intersect`, `union` now accept a `"legacy"` flag which changes the index values (second and third outputs) as well as the - orientation of the outputs to match Matlab releases prior to R2012b. + orientation of all outputs to match Matlab releases prior to R2012b. - Complex RESTful web services can now be accessed by the `webread` and `webwrite` functions alongside with the `weboptions` structure. One diff -r d29a12e8b6d9 -r 67e5e997a3bf scripts/set/setdiff.m --- a/scripts/set/setdiff.m Thu Jul 11 15:05:30 2019 -0700 +++ b/scripts/set/setdiff.m Thu Jul 11 15:29:38 2019 -0700 @@ -20,6 +20,7 @@ ## -*- texinfo -*- ## @deftypefn {} {@var{c} =} setdiff (@var{a}, @var{b}) ## @deftypefnx {} {@var{c} =} setdiff (@var{a}, @var{b}, "rows") +## @deftypefnx {} {@var{c} =} setdiff (@dots{}, "legacy") ## @deftypefnx {} {[@var{c}, @var{ia}] =} setdiff (@dots{}) ## Return the unique elements in @var{a} that are not in @var{b} sorted in ## ascending order. @@ -33,6 +34,10 @@ ## ## If requested, return the index vector @var{ia} such that ## @code{@var{c} = @var{a}(@var{ia})}. +## +## Programming Note: The input flag @qcode{"legacy"} changes the algorithm +## to be compatible with @sc{matlab} releases prior to R2012b. +## ## @seealso{unique, union, intersect, setxor, ismember} ## @end deftypefn @@ -41,24 +46,30 @@ function [c, ia] = setdiff (a, b, varargin) - if (nargin < 2 || nargin > 3) + if (nargin < 2 || nargin > 4) print_usage (); endif [a, b] = validsetargs ("setdiff", a, b, varargin{:}); - by_rows = nargin == 3; - isrowvec = isrow (a); + by_rows = any (strcmp ("rows", varargin)); + optlegacy = any (strcmp ("legacy", varargin)); + + if (optlegacy) + isrowvec = ! iscolumn (a) || ! iscolumn (b); + else + isrowvec = isrow (a); + endif if (by_rows) if (nargout > 1) - [c, ia] = unique (a, "rows"); + [c, ia] = unique (a, varargin{:}); else - c = unique (a, "rows"); + c = unique (a, varargin{:}); endif if (! isempty (c) && ! isempty (b)) ## Form A and B into combined set. - b = unique (b, "rows"); + b = unique (b, varargin{:}); [tmp, idx] = sortrows ([c; b]); ## Eliminate those elements of A that are the same as in B. dups = find (all (tmp(1:end-1,:) == tmp(2:end,:), 2)); @@ -69,9 +80,9 @@ endif else if (nargout > 1) - [c, ia] = unique (a); + [c, ia] = unique (a, varargin{:}); else - c = unique (a); + c = unique (a, varargin{:}); endif if (! isempty (c) && ! isempty (b)) ## Form a and b into combined set. @@ -84,15 +95,18 @@ dups = find (tmp(1:end-1) == tmp(2:end)); endif c(idx(dups)) = []; - if (nargout > 1) - ia(idx(dups)) = []; - endif ## Reshape if necessary for Matlab compatibility. if (isrowvec) c = c(:).'; else c = c(:); endif + if (nargout > 1) + ia(idx(dups)) = []; + if (optlegacy && isrowvec) + ia = ia(:).'; + endif + endif endif endif @@ -126,3 +140,36 @@ %! a = rand (3,3,3); %! b = a(1); %! assert (setdiff (a, b), sort (a(2:end)')); + +## Test "rows" compatibility +%!test +%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5]; +%! b = [0 0 0; 5 5 5]; +%! [c, ia] = setdiff (a, b, "rows"); +%! assert (c, [1, 4 ,5; 7, 9 7]); +%! assert (ia, [5; 1]); + +## Test "legacy" option +%!test +%! a = [3, 6, 2, 1, 5, 1, 1]; +%! b = [2, 4, 6]; +%! [c, ia] = setdiff (a, b); +%! assert (c, [1, 3, 5]); +%! assert (ia, [4; 1; 5]); +%! [c, ia] = setdiff (a, b, "legacy"); +%! assert (c, [1, 3, 5]); +%! assert (ia, [7, 1, 5]); + +## "legacy" + "rows" compatibility +%!test +%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5]; +%! b = [0 0 0; 5 5 5]; +%! [c, ia] = setdiff (a, b, "rows", "legacy"); +%! assert (c, [1, 4 ,5; 7, 9 7]); +%! assert (ia, [5; 3]); + +## Output orientation with "legacy" option +%!assert (size (setdiff ([1:5], [2:3], "legacy")), [1, 3]) +%!assert (size (setdiff ([1:5]', [2:3], "legacy")), [1, 3]) +%!assert (size (setdiff ([1:5], [2:3]', "legacy")), [1, 3]) +%!assert (size (setdiff ([1:5]', [2:3]', "legacy")), [3, 1])