function X = internal_dlconv(X,weights,bias,paddingSize,stride,dilation,numGroups)
% This function is undocumented and will change in a future release.

% Applies d-dimensional convolution on the CPU.
%
% Inputs:
%   X           = N1 x N2 x...x Nd x  C  x N array.
%   weights     = M1 x M2 x...x Md x(C/G)x K array. G is the number of
%                 groups and G must divide C and K.
%   bias        = 1  x 1  x...x 1  x  K      array.
%   paddingSize = [L1,H1,...,Ld,Hd] where Li and Hi are the start and end
%                 padding sizes in the ith dimension.
%   stride      = [s1,...,sd] where si is stride in the ith dimension.
%   dilation    = [c1,...,cd] where ci is dilation in the ith dimension.
%   numGroups   = number of groups G.
%
% Outputs:
%   Z           = O1 x O2 x...x Od x  K  x N array.

%   Copyright 2019 The MathWorks, Inc.

% Mixed precision is not supported by builtin.
[X, weights, bias] = nnet.internal.cnnhost.castToSuperiorFloat(X, weights, bias);

d = numel(stride);
[paddingStart, paddingEnd] = iConvertPaddingToHostAPIformat(paddingSize);
numFilters = size(weights,d+2);
filterGrouping = iConvertNumGroupsToHostAPIformat(numFilters,numGroups);

X = builtin('_batchconv', ...
    X, weights, ...
    [paddingStart paddingEnd], ...
    stride, dilation, [], filterGrouping) + bias;
end

function filterGrouping = iConvertNumGroupsToHostAPIformat(numFilters,numGroups)
filterGrouping = repmat(numFilters/numGroups,1,numGroups);
end

function [paddingStart, paddingEnd] = iConvertPaddingToHostAPIformat(paddingSize)
n = numel(paddingSize);
paddingStart = paddingSize(1:2:n);
paddingEnd = paddingSize(2:2:n);
end