function Z = null(A, tol)
%NULL   Null space.
%   Z = NULL(A)
%   Z = NULL(A,tol)
%   
%   Limitation:
%   1. The 'r' syntax or "rational" basis is not supported.
%   
%   See also NULL, CODISTRIBUTED.


%   Copyright 2013-2023 The MathWorks, Inc.

narginchk(1, 2);

if nargin > 1
    % Argument checking by calling in-memory.
    try
        null(1, tol);
    catch ME
        throw(ME)
    end
    
    % "rational" basis is not supported.
    if matlab.internal.datatypes.isScalarText(tol) ...
            && strncmpi(tol, "rational", max(strlength(tol), 1))
        error(message("parallel:array:NullNotRat", "distributed"));
    end
end

[m, n] = size(A);
if m >= n
    % In this case "econ" is equivalent to full for 2-output syntax.
    [V, s] = svd(A', "econ", "vector");
else % m < n
    Actrans = A';
    % We must use the SVD to compute s properly.
    s = svd(Actrans, "econ", "vector");
    % We can't use the full SVD, hence we compute V as follows:
    %   [V, R] = qr(Actrans);
    %   [V1, ~] = svd(R(1:m, 1:m), "econ", "vector");
    %   Q1 = V(:, 1:m);
    %   V(:, 1:m) = Q1*V1;
    [V, R] = qr(Actrans);
    Q1 = subsref(V, substruct('()', {':', 1:m}));
    R1 = subsref(R, substruct('()', {1:m, 1:m}));
    [V1, ~] = svd(R1, "econ", "vector");
    V = subsasgn(V, substruct('()', {':', 1:m}), Q1*V1);
end

if isnan(s(1))
    error(message("MATLAB:null:matrixWithNaNInf"));
end

if nargin == 1
    tol = matlab.internal.math.getTolToCompareSVs(s, max(size(A)));
end

if isempty(A)
    Z = V;
else
    r = nnz(s > tol);
    % Z = V(:, r+1:n)
    Z = subsref(V, substruct('()', {':', r+1:n}));
end
end
