def matrix_rank_impl(A, tol=None):
    """
    Computes rank for matrices and vectors.
    The only issue that may arise is that because numpy uses double
    precision lapack calls whereas numba uses type specific lapack
    calls, some singular values may differ and therefore counting the
    number of them above a tolerance may lead to different counts,
    and therefore rank, in some cases.
    """
    ensure_lapack()

    _check_linalg_1_or_2d_matrix(A, "matrix_rank")

    def _2d_matrix_rank_impl(A, tol):

        # handle the tol==None case separately for type inference to work
        if tol in (None, types.none):
            nb_type = getattr(A.dtype, "underlying_float", A.dtype)
            np_type = np_support.as_dtype(nb_type)
            eps_val = np.finfo(np_type).eps

            def _2d_tol_none_impl(A, tol=None):
                s = _compute_singular_values(A)
                # replicate numpy default tolerance calculation
                r = A.shape[0]
                c = A.shape[1]
                l = max(r, c)
                t = s[0] * l * eps_val
                return _get_rank_from_singular_values(s, t)
            return _2d_tol_none_impl
        else:
            def _2d_tol_not_none_impl(A, tol=None):
                s = _compute_singular_values(A)
                return _get_rank_from_singular_values(s, tol)
            return _2d_tol_not_none_impl

    def _get_matrix_rank_impl(A, tol):
        ndim = A.ndim
        if ndim == 1:
            # NOTE: Technically, the numpy implementation could be argued as
            # incorrect for the case of a vector (1D matrix). If a tolerance
            # is provided and a vector with a singular value below tolerance is
            # encountered this should report a rank of zero, the numpy
            # implementation does not do this and instead elects to report that
            # if any value in the vector is nonzero then the rank is 1.
            # An example would be [0, 1e-15, 0, 2e-15] which numpy reports as
            # rank 1 invariant of `tol`. The singular value for this vector is
            # obviously sqrt(5)*1e-15 and so a tol of e.g. sqrt(6)*1e-15 should
            # lead to a reported rank of 0 whereas a tol of 1e-15 should lead
            # to a reported rank of 1, numpy reports 1 regardless.
            # The code below replicates the numpy behaviour.
            def _1d_matrix_rank_impl(A, tol=None):
                for k in range(len(A)):
                    if A[k] != 0.:
                        return 1
                return 0
            return _1d_matrix_rank_impl
        elif ndim == 2:
            return _2d_matrix_rank_impl(A, tol)
        else:
            assert 0  # unreachable

    return _get_matrix_rank_impl(A, tol)

    Computes rank for matrices and vectors.
    The only issue that may arise is that because numpy uses double
    precision lapack calls whereas numba uses type specific lapack
    calls, some singular values may differ and therefore counting the
    number of them above a tolerance may lead to different counts,
    and therefore rank, in some cases.
    
numba/np/linalg.py