function [dZ, dT] = internal_crossentropyBackward(dZ, X, T, weights, mask, normFactor, hasIndependentTargetCategories)
% This function is undocumented and will change in a future release.

%   Copyright 2019-2023 The MathWorks, Inc.

if ~isreal(dZ)
    error(message('deep:dlarray:ComplexGradientOutput', 'crossentropy'));
end

% Factors that are common to all outputs
dZ = -dZ.*weights;

if ~isempty(normFactor)
    % Use a normalization factor of 1 for 'Reduction' value 'none'.
    dZ = dZ./normFactor;
end

if hasIndependentTargetCategories
    OneMinusX = nnet.internal.cnn.util.boundAwayFromZero(1 - X);
    X = nnet.internal.cnn.util.boundAwayFromZero(X);
   
    if nargout>1
        dT = dZ.*(log(X)-log(OneMinusX));
    end
    dZ = dZ.*(T./X - (1-T)./OneMinusX);
else
    X = nnet.internal.cnn.util.boundAwayFromZero(X);

    if nargout>1
        dT = dZ.*log(X);
    end
    dZ = dZ.*T./X;
end

% Make sure gradients associated with masked out inputs are set to zero.
if nargout>1
    dT = internal_mask(dT, mask);
end
dZ = internal_mask(dZ, mask);

end
