function varargout = gather(varargin)
%GATHER Retrieve contents of a distributed array to a single array on the client
%   X = GATHER(D) is a regular array formed from the contents
%   of the distributed array D.
%   
%   [X1,X2,...,Xn] = GATHER(D1,D2,...,Dn) gathers multiple arrays
%   D1,D2,...,Dn into the corresponding outputs X1,X2,...,Xn. The number of
%   input arguments and output arguments must match.
%   
%   Example:
%   N = 1000;
%   D = distributed(magic(N));
%   M = gather(D);
%   
%   retrieves M = magic(N) on the client
%   
%   See also DISTRIBUTED.


%   Copyright 2006-2022 The MathWorks, Inc.

if nargout > nargin
    error(message("MATLAB:bigdata:array:GatherInsufficientInputs"));
end

if nargin==1
    % Short-cut for single input since we know it must be distributed and
    % don't need to re-call gather to process other arguments.
    varargout = {iGatherOne(varargin{1})};
    return
end

isArgDistributed = cellfun(@isdistributed, varargin);
varargin(isArgDistributed) = cellfun(@iGatherOne, varargin(isArgDistributed), ...
                                     'UniformOutput', false);
% Now that the distributed arrays are gathered, redispatch.
[varargout{1:max(1, nargout)}] = gather(varargin{:});
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function x = iGatherOne(obj)
% Protect against broken distributed.
errorIfInvalid( obj );

% Generate the range structure - 1..size in each dimension
range =  struct( 'start', ones( ndims( obj ), 1 ), ...
                 'end', size( obj ).' );
% Use transferPortion to do the real work.
x = transferPortion( obj, range );
end
