function localRow = hGetRow(codistr, LP, globalRowIndex)
% hGetRow Return the row of a 2D matrix with global index
% globalRowIndex

%   Copyright 2017-2022 The MathWorks, Inc.

localRowIndex = codistr.hGlobalToLocalIndices(globalRowIndex, 1, spmdIndex);

% Extract data and determine map for sending data on workers that have
% non-zero local subscripts
if localRowIndex~=0
    localRow = LP(localRowIndex, :);
    leadToSendMap = [pDetermineLeadingWorker(codistr, spmdIndex, 1), spmdIndex];
else
    leadToSendMap = zeros(0,2);
    localRow = LP([]);
end

% Communicate leading and contributing workers
leadToSendMap = spmdReduce(@vertcat, leadToSendMap);

% Set up sending workers
senderIndex = find(leadToSendMap(:,2)==spmdIndex);
isSender = ~isempty(senderIndex);

if isSender
    workerTo = leadToSendMap(senderIndex,1);
    workerFrom = [];
end
% Set up receiving workers
receiverIndex = find(leadToSendMap(:,1)==spmdIndex);
isReceiver = ~isempty(receiverIndex);

if isReceiver
    workerTo = [];
    workerFrom = leadToSendMap(receiverIndex,2);
end

% Communicate data if worker is sender or receiver but not both. The latter
% one would mean the worker has data to send but would also receive it.
% Since we only deal with single rows here, this means we don't need to do
% anything.
if isSender ~= isReceiver
    localRow = spmdSendReceive(workerTo, workerFrom, localRow);
end

% Adjust size of data of empty workers
if isempty(localRow)
    % To get the right size for the empty parts, create a codistributor for
    % a single row of the input and determine the local size.
    codistrOut = codistributor2dbc(codistr.WorkerGrid, codistr.BlockSize, ...
        codistr.Orientation, [1, codistr.Cached.GlobalSize(2)]);
    localSize = codistrOut.hLocalSize(spmdIndex);
    
    % We create the empty part by subsref-ing with zeros of the correct
    % size. This will also work for non-numeric data.
    localRow = LP(zeros(localSize));
end
end
