Mercurial > octave
diff scripts/set/setdiff.m @ 27237:67e5e997a3bf
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.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 11 Jul 2019 15:29:38 -0700 |
parents | 00f796120a6d |
children | 6525b3fe3cf9 |
line wrap: on
line diff
--- 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])