function globalInd = hLocalToGlobalIndices(codistr, localInd, dim, workerIdx)
; %#ok<NOSEM> % Undocumented

%   Implementation of hLocalToGlobalIndices for codistributor2dbc.

%   Copyright 2011-2022 The MathWorks, Inc.

    if nargin < 4
        workerIdx = spmdIndex;
    end
    
    if ~distributedutil.CodistParser.isValidSPMDIndex(workerIdx)
        error(message('parallel:codistributors:InvalidSpmdIndex'));
    end
    
    if ~isPositiveIntegerValuedNumeric(dim) || ...
            dim > length(codistr.Cached.GlobalSize)
        error(message('parallel:codistributors:InvalidDimInput'));
    end
    
    localSize = codistr.hLocalSize();
    if  any(~isPositiveIntegerValuedNumeric(localInd) | ...
            localInd < 1 | localInd > localSize(dim))
        error(message('parallel:codistributors:InvalidLocalIndex'));
    end
    
    if dim == 1
        proc = codistr.pSpmdIndexToProcessorRow(workerIdx);
    else
        proc = codistr.pSpmdIndexToProcessorCol(workerIdx);
    end
    
    blockSize = codistr.BlockSize;
    % blockInDim is the block in the local part that contains lInd
    blockInDim = floor((localInd - 1)/blockSize) + 1;
    offsetInBlock = mod(localInd - 1, blockSize) + 1;
    procsInDim = codistr.WorkerGrid(dim);
    % The global index is the sum of three parts
    %  (1) The number of elements in complete blocks on this dimension
    %  (2) The number of elements in blocks in earlier workers on this dim
    %  (3) The index of this element in this block on this worker
    globalInd = (blockInDim - 1)*procsInDim*blockSize + (proc - 1)*blockSize +...
        offsetInBlock;
end

