function [X, H, Ws] = internal_gru_recurrentBiasAfterMultiplication(X, h0, W, R, b, stateActivation, gateActivation, ~)
% This function is undocumented and will change in a future release.

%   [X,H,Ws] = internal_gru_recurrentBiasAfterMultiplication(X,h0,W,R,b,stateActivation,gateActivation,isTraining) 
%   computes the Gated Recurrent Unit operation using input data X, initial
%   hidden units h0, input weights W, recurrent weights R and bias term b,
%   activation functions stateActivation and gateActivation, and an
%   isTraining flag. isTraining is unused in this function.
%
%   Definitions:
%   nF := Number of features of the input data
%   N := Number of input observations (mini-batch size)
%   nS := Sequence length
%   nH := Hidden units size
%
%   Inputs:
%   X - Input data                  (nF)x(N)x(nS) array
%   W - Input weights               (3*nH)x(nF) matrix
%   R - Recurrent weights           (3*nH)x(nH) matrix
%   b - Bias                        (2*3*nH)x(1) vector
%   h0 - Initial hidden units       (nH)x(N) matrix
%   stateActivation                 'tanh' or 'softsign'
%   gateActivation                  'sigmoid' or 'hard-sigmoid'
%   isTraining                      Unused in this function
%
%   Outputs:
%   Z  - Output                      (nH)x(N)x(nS) array
%   H  - Hidden state                (nH)x(N) matrix
%   Ws - Workspace

%   Copyright 2022-2023 The MathWorks, Inc.

if ~isreal(X) || ~isreal(h0) || ~isreal(W) || ~isreal(R) || ~isreal(b)
    error(message('deep:dlarray:ComplexNotSupported'))
end

% Cast inputs to common type
[X, h0, W, R, b] = nnet.internal.cnnhost.castToSuperiorFloat(X, h0, W, R, b);

% Prepare the inputs for cnnhost implementation
learnable.W = W;
learnable.R = R;
learnable.b = b;
state.h0 = h0;
options.ReturnLast = false; % Always return the full output
options.GateActivationFunction = gateActivation;
options.StateActivationFunction = stateActivation;
% Call cnnhost implementation
[X, H] = nnet.internal.cnnhost.gruForwardResetAfterMultiplicationRecurrentBiasGeneral(X,learnable,state,options);

% This output is required for the GPU implementation. Set to empty for CPU.
Ws = [];

end
