function [latency, fpDelays] = getscmLatency(~, hC, constMatrix, sharingFactor, nfpCustomLatency)
%

%   Copyright 2016-2022 The MathWorks, Inc.

% get the nonzero linear row indices in 'constMatrix'
[~, activeRowPositions, ~] = sschdloptimizations.getActiveElements(constMatrix, sharingFactor);

% there will be numel(activeRowPositions) rows in 'constMatrix'. we need to
% find the size of the largest row
maxRowElements = 0;
for ii = 1:numel(activeRowPositions)
    rowElements = activeRowPositions{ii};
    if (numel(rowElements) > maxRowElements)
        maxRowElements = numel(rowElements);
    end
end

% the largest row determines the largest number of stages in the adder tree
maxAdderTreeStages = 0;
if (maxRowElements > 0)
    maxAdderTreeStages = ceil(log2(maxRowElements));
end

% the latency depends on the floating-point data type
outSignals = hC.PirOutputSignals;
outSignalsType = getPirSignalLeafType(outSignals.Type);
if outSignalsType.isSingleType
    targetCompDataType = 'SINGLE';
elseif outSignalsType.isHalfType
    targetCompDataType = 'HALF';
else
    targetCompDataType = 'DOUBLE';
end

% get the latency for an individual floating-point operator
mulLatency = resolveLatencyForIPType(hC, targetCompDataType, 'MUL');
addLatency = resolveLatencyForIPType(hC, targetCompDataType, 'ADDSUB');

if nfpCustomLatency >= 0
    mulLatency = nfpCustomLatency;
    addLatency = nfpCustomLatency;
end

if ((mulLatency == -1) || (addLatency == -1))
    latency = -1;
    return;
end

% latency equals one multiplier latency and the adder tree latency. double
% cast is required
latency = double(mulLatency + maxAdderTreeStages * addLatency);

% floating-point delays = latency for a fully parallel implementation
fpDelays = latency;

% adjust the latency for the sharing factor
if sharingFactor > 1
    latency = ceil(latency./sharingFactor) + 2;
end
end

function latency = resolveLatencyForIPType(hC, targetCompDataType, targetIPType)
% Evaluate latency early for add/sub and mul comps

hDriver = hdlcurrentdriver;

p = pir(hC.Owner.getCtxName);
targetDriver = hDriver.getTargetCodeGenDriver(p);

if isempty(targetDriver) || ~strcmpi(class(targetDriver), 'targetcodegen.nfpdriver')
    latency = -1; % Error if native floating-point library is not selected
else
    latency = targetDriver.getDefaultLatency(targetIPType, targetCompDataType, [], []);
end
end
