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

% Applies d-dimensional convolution on the GPU.
%
% 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/G) x G array. G is the number
%                 og groups and G must divide C and K.
%   bias        = 1  x 1  x...x 1  x K array.
%   permX       = 1 x d+2 array giving the data to view permutation of X
%                 or 1 x 0 if trivial.
%   permW       = 1 x d+3 array giving the data to view permutation of W
%                 or 1 x 0 if trivial.
%   stride      = [s1,...,sd] where si is stride in the ith dimension.
%   dilation    = [c1,...,cd] where ci is dilation in the ith dimension.
%   paddingSize = [L1,H1,...,Ld,Hd] where Li and Hi are the start and end
%                 padding sizes in the ith dimension.
%   paddingStrategy = strategy for padding the input array.
%   numGroups   = number of groups G.
%
% Outputs:
%   Z           = O1 x O2 x...x Od x  K  x N array.

%   Copyright 2019-2022 The MathWorks, Inc.

if ~isreal(X) || ~isreal(weights) || ~isreal(bias)
    error(message('deep:dlarray:ComplexNotSupported'))
end

[X, weights, bias, dilation, paddingStart] = ...
    prepareConvInputs(X,weights,bias,permX,permW,stride,dilation,paddingSize,paddingStrategy,numGroups);

% Call GPU built-in
X = nnet.internal.cnngpu.convolveForwardND( ...
    X, weights, ...
    paddingStart, [], ...
    stride, dilation, numGroups) + bias;

% Permute output data back into the original format
X = permuteConvOutput(X, permX);
end
