function c = convDistRepl(A,B,convFcnHandle,outClass,isResultRow)
% Perform convolution of distributed array (A) with replicated array (B)
% with the appropriate shape. isResultRow is an optional parameter used by
% conv (1D convolution) to return a result with the right shape.  This
% function returns just the local part of conv(localA, B).

% Copyright 2016-2022 The MathWorks, Inc.

codistrA = getCodistributor(A);
partA = codistrA.Partition;
lpA = getLocalPart(A);

if isstruct(B)
    % Separated vectors hrow, hcol
    szB = [numel(B.hrow), numel(B.hcol)];
    paddingGsize = [];
else
    % Matrix B (if A has got higher dimensionality extend B)
    szB = [size(B) ones(1,ndims(A) - ndims(B))];
    paddingGsize = ones(1,ndims(B) - ndims(A));
end

isConv = isequal(convFcnHandle, @conv);

% If we are doing a 1D convolution, make sure B has the same shape
% of A (B is not distributed at this stage)
if isConv
    assert(nargin==5, "Expected 5 inputs to CONV")
    assert(~isstruct(B), "The second input to CONV should not be a struct")
    if all(size(A) ~= size(B))
        B = B.';
        szB = flip(szB);
    end
end

% Global size
gSize = codistrA.Cached.GlobalSize;
gSize = [gSize paddingGsize] + max(szB - 1,0);
dim = codistrA.Dimension;
if ~isscalar(A)
    if iscolumn(A)
        dim = 1;
    elseif isrow(A)
        dim = 2;
    end
end

if partA(spmdIndex) ~= 0
    % We must avoid zero-padding because it can turn Infs into NaNs (g1310295).
    % Instead do the 'full' convolution locally and then extract the region
    % we want to keep.
    if isstruct(B)
        c = convFcnHandle(B.hrow, B.hcol, lpA, 'full');
    else
        c = convFcnHandle(lpA, B, 'full');
    end
else
    % Handle the case where the local part is empty
    sz0 = gSize;
    sz0(dim) = 0;
    c = zeros(sz0,outClass);
end

if isConv && (isResultRow && iscolumn(A) || ~isResultRow && isrow(A))
    %Handle the particular case for 1D convolution
    c = c.';
end
end
