function tf = hIsGlobalIndexOnWorker(codistr, dim, gIndexInDim, worker)
%hIsGlobalIndexOnWorker  Implementation for codistributor2dbc.

%   Copyright 2009-2022 The MathWorks, Inc.

if dim > 2
    tf = (gIndexInDim == 1);
    return;
end

% The trivial implementation of this function would be: tf =
% ismember(gIndexInDim, codistr.hGlobalIndicesImpl(dim, worker)) but that is much
% too slow.  Rather, we map worker to the processor row/column in the worker grid, and
% we map the indices in gIndexInDim to the processor row/column in the worker grid.
if dim == 1
    proc = codistr.pSpmdIndexToProcessorRow(worker);
else
    proc = codistr.pSpmdIndexToProcessorCol(worker);
end

% Use the block nature of 2DBC and map the global indices into the
% corresponding block.  For example, with a block size of 64, the global
% indices [1, 2, 3, 65, 129, 193, 257, 258] correspond to blocks [1, 1, 1,
% 2, 3, 4, 5, 5]
blocksInDim = floor((gIndexInDim - 1)/codistr.BlockSize) + 1;
% Use the cyclic nature of 2DBC and find the processor row/column that
% stores the blocks.  For example, if dim is 1 and WorkerGrid is [2, 3], then
% the blocks above correspond to procsInDim of [1, 1, 1, 2, 1, 2, 1, 1].
procsInDim = mod(blocksInDim - 1, codistr.WorkerGrid(dim)) + 1;
% The worker in question stores the global indices where the processor indices
% match and the global indices are within the overall matrix bounds.
tf = (procsInDim == proc ...
      & gIndexInDim >= 1 ...
      & gIndexInDim <= codistr.Cached.GlobalSize(dim));

end % End of hIsGlobalIndexOnWorker.
