function [C, ia] = setdiff(A, B, varargin)
%SETDIFF Set difference for codistributed array data.
%   C = setdiff(A,B)    
%   C = setdiff(A,B,'rows')    
%   [C,IA] = setdiff(A,B)    
%   [C,IA] = setdiff(A,B,'rows')    
%   [C,IA] = setdiff(A,B,'stable') 
%   [C,IA] = setdiff(A,B,'rows','stable') 
%   [C,IA] = setdiff(A,B,'sorted') 
%   [C,IA] = setdiff(A,B,'rows','sorted') 
%   
%   Limitations:
%   The 'legacy' flag is not supported.
%   1. Table, timetable, categorical, datetime and duration inputs are not supported.
%   2. Char and string inputs are not supported when A or B is a cell array of char vectors. Convert cell array of char vectors input arguments to string instead.
%   
%   See also setdiff, codistributed.


%   Copyright 2015-2023 The MathWorks, Inc.

% Allow 5 inputs so the right error can be thrown for the "legacy" flag"
narginchk(2, 5)
nargoutchk(0, 2)

% Default output
ia = [];

try
    [flags, A, B] = setfunCheckArgs(@setdiff, A, B, varargin{:});
catch ME
    throwAsCaller(ME)
end

isRows = false;
if ~isempty(flags)
    isRows = any(contains(flags, "rows"));
end

% We only support 1D distributions right now. Convert rather than error.
A = pForce1DDistribution(A);
B = pForce1DDistribution(B);

localLia = ismemberImpl(A, B, isRows, "none");

[fullC, lia] = setfunExtractMatch(A, ~localLia, isRows);

if isempty(fullC)
    if isRows
        fullC = codistributed.zeros(0, size(A, 2));
    else
        fullC = codistributed.zeros(1, 0);
    end
    if isstring(A) || isstring(B)
        fullC = codistributed(string.empty(size(fullC)));
    elseif iscell(A) || iscell(B)
        fullC = cell.empty(1, 0);
    else
        fullC = cast(fullC, underlyingType(A));
    end
end

if isrow(fullC) && ~isRows  % C must be a column vector unless isRows.
    fullC = fullC.';
end

if nargout < 2
    C = unique(fullC, flags{:});
else
    [C, cia] = unique(fullC, flags{:});
    ia = setfunGetIndices(cia, lia);
end

% Output should be row if both inputs are rows.
if isrow(A) && iscolumn(C) && ~isRows
    C = C.';
end

% Finally restore correct sparsity if needed.
if issparse(A)
    C = sparse(C);
end
if issparse(ia)
    ia = full(ia);
end


if ~iscodistributed(C)
    C = codistributed.pConstructFromReplicated(C);
end
end
