function X = gelu(X, options)
%GELU   Apply gaussian error linear unit activation
%
%   Y = GELU(X) applies the GELU activation to the dlarray X. If X is a
%   formatted dlarray, then Y is a formatted dlarray with the same format
%   as X. If X is an unformatted dlarray, then Y is an unformatted dlarray.
%
%   Y = GELU(X,Approximation=METHOD) also specifies the approximation
%   method for the GELU operation, where METHOD is one of the following:
%     'none' - Do not use approximation.
%     'tanh' - Use tanh approximation.
%     The default value is 'none'.
%
%   Without approximation, the gelu operation is defined as:
%       Y = (X./2).*( 1 + erf(X./sqrt(2)) );
%   With tanh approximation, the gelu operation is defined as:
%       Y = (X./2).*( 1 + tanh(sqrt(2/pi)*(X+0.044715*(X.^3))) );
%
%   Example:
%       % Apply GELU activation to formatted dlarray.
%       X = dlarray(randn(8,8,3,16),'SSCB');
%       Y = gelu(X);
%
%   See also RELU, DLARRAY, LEAKYRELU

%   Copyright 2022 The MathWorks, Inc.

arguments
    X
    options.Approximation {mustBeMember(options.Approximation, ...
        ["none", "tanh"])} = "none"
end

% Extract the input data
fd = X.FormattedData;
X.FormattedData = [];
[fd,xdata] = extractData(fd);

% The dlarray methods should not accept logical x 
if islogical(xdata)
    error(message('deep:dlarray:LogicalDlarrayNotSupported'));
end

% Call the internal API
xdata = internal_gelu(xdata, options.Approximation);

% Format is guaranteed not to have changed
fd = insertData(fd, xdata);
X.FormattedData = fd;
end
