function varargout = globalIndices(D, dim, workerIdx)
%globalIndices Global indices for the local part of a codistributed array
%   The global indices for the local part of a codistributed array is the
%   index range in a given dimension for the associated codistributed array on
%   a particular worker.  It is important to understand the underlying
%   distribution scheme of the codistributed array before calling the
%   globalIndices method for the following reasons:
%   
%   - If an array uses the '1d' distribution, one can get a complete
%     understanding of which workers store which elements of the array by calling
%     globalIndices for the distribution dimension of the array.
%   
%   - If an array uses the '2dbc' distribution, one needs to call
%     globalIndices for both the 1st and 2nd dimension to be able to deduce
%     which elements reside on which worker.
%   
%   - Although the globalIndices method is supported both for '1d' and '2dbc'
%     distribution schemes, it is possible that future distribution schemes
%     may not be able to support this method.
%   
%   With one output argument, K = globalIndices(D, DIM, WORKERIDX) returns a vector
%   K such that the specified worker stores information about some or all of the
%   elements with index K in the DIM-th dimension, i.e.  D(...,K, ...).  The
%   third argument of WORKERIDX is optional, and it defaults to spmdIndex.
%   
%   With two output arguments, [E,F] = globalIndices(D, DIM, WORKERIDX) returns two
%   integers E and F such that the specified worker stores information about some
%   or all of the elements with index in the range E:F in the DIM-th
%   dimension, i.e.  D(...,E:F,...).  The third argument of WORKERIDX is optional, 
%   and it defaults to spmdIndex.
%   
%   Example: 
%   % with spmdSize = 4
%   spmd
%      D = codistributed.zeros(2, 22, codistributor('1d',2,[6 6 5 5]));
%      if spmdIndex == 1
%         KWorker1 = globalIndices(D, 2);     % returns KWorker1 = 1:6.
%      elseif spmdIndex == 2
%         [EWorker2, FWorker2] = globalIndices(D, 2); % returns EWorker2 = 7, FWorker2 = 12.
%      end
%      KWorker3 = globalIndices(D, 2, 3);     % returns KWorker3 = 13:17.
%      [EWorker4, FWorker4] = globalIndices(D, 2, 4); % returns EWorker4 = 18, FWorker4 = 22.
%   end
%   
%   On exiting the example spmd block above, KWorker1, EWorker2, and FWorker2 
%   are variant arrays, while KWorker3, EWorker4, and FWorker4 are replicated.    
%   
%   See also codistributed/getLocalPart, codistributed/getCodistributor.


%   Copyright 2007-2022 The MathWorks, Inc.

narginchk(2, 3);

if nargin == 2
    distributedutil.CodistParser.verifyNonCodistributedInputs({D, dim});
elseif nargin == 3
    distributedutil.CodistParser.verifyNonCodistributedInputs({D, dim, workerIdx});
end

if ~isa(D, 'codistributed')
    error(message('parallel:distributed:GlobalIndicesFirstInput'))
end

if nargin < 3
    workerIdx = spmdIndex;
end

% Defer everything to the codistributor, including the error checking of the
% arguments.
dist = getCodistributor(D);
[varargout{1:nargout}] = dist.globalIndices(dim, workerIdx);

end % End of globalIndices.
