function ourParts = stencilCommConv(dim, localPartC, cumPartitionC, cumPartitionA, szB, isCodB)
% STENCILCOMMCONV Communicate and sum local parts of distributed
% convolution C = CONV(A, B) among workers, returning the parts needed on
% this worker. The  communication pattern is optimized to avoid forwarding
% data.  The algorithm used here must be kept in-sync with the similar
% algorithm in stencilCommPad.

%   Copyright 2022 The MathWorks, Inc.

ourParts = cell(1, spmdSize);
needToRecv = false(1, spmdSize);
partitionA = diff(cumPartitionA);
% Figure out who is sending to us.
for spmdIx = 1:spmdSize
    if spmdIx == spmdIndex
        continue
    end
    offset = cumPartitionA(spmdIx);
    if (partitionA(spmdIx) == 0) && ((isCodB && 1 < dim && dim < numel(szB)) || ~isCodB)
        szlocalCInDim = 0;
    else
        szlocalCInDim = partitionA(spmdIx) + max(szB(dim)-1, 0);
    end
    startIndex = max(cumPartitionC(spmdIndex)+1 - offset, 1);
    endIndex = min(cumPartitionC(spmdIndex+1) - offset, szlocalCInDim);
    if endIndex >= startIndex
        needToRecv(spmdIx) = true;
    end
end

% Do the sends and receives.
offset = cumPartitionA(spmdIndex);
szlocalCInDim = size(localPartC, dim);
mwTag = 2^15 - mod(sum(mfilename),2^15);
for spmdIx = 1:spmdSize
    startIndex = max(cumPartitionC(spmdIx)+1 - offset, 1);
    endIndex = min(cumPartitionC(spmdIx+1) - offset, szlocalCInDim);
    needToSend = endIndex>=startIndex;
    if needToSend
        partToSend = extractSlices(localPartC, startIndex:endIndex, dim);
        if spmdIx == spmdIndex
            ourParts{spmdIx} = partToSend;
        elseif needToRecv(spmdIx)
            ourParts{spmdIx} = spmdSendReceive(spmdIx, spmdIx, partToSend, mwTag+spmdIndex+spmdIx+spmdSize);
        else
            spmdSend(partToSend, spmdIx, mwTag+spmdIndex);
        end
    elseif needToRecv(spmdIx)
        ourParts{spmdIx} = spmdReceive(spmdIx, mwTag+spmdIx);
    else
        % Here if nothing to send or receive.
    end
end
end
