function X = internal_dlconvrelu(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 followed by relu 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/G) x G array. G is the
%                     number of 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 2020-2022 The MathWorks, Inc.

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

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

% Call to the builtin. Note that X returned by the builtin has format
% 'CBS*S' and permXout gives the permutation vector w.r.t the 'S*SCB'
% dimension order.
[X, permXout] = builtin('_batchconvRelu', {X, permX}, {weights, permW}, [paddingStart, paddingEnd], stride, dilation, bias);

X = permuteConvOutput(X,permX,permXout,isPermXEmpty);
end
