function [LPC, codistrC] = hMtimesImpl(~, codistrA, LPA, transA, codistrB, LPB, transB)
% hMtimesImpl:  Implementation of mtimes for codistributor2dbc when both 
% matrices are codistributed2dbc

%   Copyright 2010-2022 The MathWorks, Inc.

% If inputs are of different types, convert the double one to single
if isa(LPA,'single') && isa(LPB,'double')
    LPB = single(LPB);
end

if isa(LPA,'double') && isa(LPB,'single')
    LPA = single(LPA);
end

szA = codistrA.Cached.GlobalSize;
szB = codistrB.Cached.GlobalSize;

%check consistency of A&B and redistribute if necessary
if ~all(codistrA.WorkerGrid == codistrB.WorkerGrid) || ...
        ~all(codistrA.BlockSize == codistrB.BlockSize) || ...
        ~strcmpi(codistrA.Orientation, codistrB.Orientation)
    if prod(szA) > prod(szB)
        [LPB, codistrB] = distributedutil.Redistributor.redistribute(codistrB, ...
            LPB, codistributor2dbc(codistrA.WorkerGrid, codistrA.BlockSize, ...
            codistrA.Orientation, szB));
    else
        [LPA, codistrA] = distributedutil.Redistributor.redistribute(codistrA, ...
            LPA, codistributor2dbc(codistrB.WorkerGrid, codistrB.BlockSize, ...
            codistrB.Orientation, szA));
    end        
end
lbgrid = codistrA.WorkerGrid;
orient = codistrA.Orientation;

% Define dimension of solution depending on transpose flags
if transA
    szC(1) = szA(2);
else
    szC(1) = szA(1);
end
if transB
    szC(2) = szB(1);
else
    szC(2) = szB(2);
end
codistrC = codistrA.hGetNewForSize([szC(1) szC(2)]);
szC = codistrC.hLocalSize();

descA = pArrayDescriptor(codistrA);
descB = pArrayDescriptor(codistrB);
descC = pArrayDescriptor(codistrC);

isRealA = codistrA.hIsrealImpl(LPA);
if ~isRealA && isreal(LPA)
    LPA = complex(LPA);
end
isRealB = codistrB.hIsrealImpl(LPB);
if ~isRealB && isreal(LPB)
    LPB = complex(LPB);
end

LPC = parallel.internal.codistextern.denseMtimes(LPA, descA, LPB, descB, ...
                                                 szC, descC, ...
                                                 lbgrid(1), lbgrid(2), ...
                                                 orient, transA, transB, ...
                                                 isRealA, isRealB);

end  % End of hMtimesImpl
