function A = pinv(A, tol)
%PINV   Pseudoinverse.
%   X = PINV(A) produces a matrix X of the same dimensions
%   as A' so that A*X*A = A, X*A*X = X and A*X and X*A
%   are Hermitian. The computation is based on SVD(A) and any
%   singular values less than a tolerance are treated as zero.
%
%   X = PINV(A,TOL) treats all singular values of A that are less than TOL
%   as zero. By default, TOL = max(size(A)) * eps(norm(A)).
%
%   Class support for input A:
%      float: double, single
%
%   See also SVD, RANK, PAGEPINV, DLARRAY.

%   Copyright 2023-2024 The MathWorks, Inc.

if ~isdlarray(A)
    % If only tol is a dlarray, we dispatch to a different pinv method.
    tol = extractdata(tol);
    A = pinv(A, tol);
    return
end

if ~isempty(dims(A))
    error(message('deep:dlarray:FormattedFirstArgument'))
end

if ~ismatrix(A)
    error(message('deep:dlarray:UnsupportedPinvDimensions'))
end

if nargin > 1
    [tol,A] = extractUnderlyingConstant(tol,A,{'deep:dlarray:AcceleratedTolNotSupported'});
end

[A, fdA, Adata] = extractUnaryElwiseData(A);

if nargin < 2
    Adata = pinv(Adata);
else
    Adata = pinv(Adata, tol);
end

A = restoreUnaryElwiseData(A, ...
    matlab.lang.internal.move(fdA), ...
    matlab.lang.internal.move(Adata));
end