@@ -245,6 +245,37 @@ svdvals(A::AbstractVector{T}) where {T} = [convert(eigtype(T), norm(A))]
245245svdvals (x:: Number ) = abs (x)
246246svdvals (S:: SVD{<:Any,T} ) where {T} = (S. S):: Vector{T}
247247
248+ """
249+ rank(S::SVD{<:Any, T}; atol::Real=0, rtol::Real=min(n,m)*ϵ) where {T}
250+
251+ Compute the numerical rank of a `n × m` matrix by counting how many singular values are greater
252+ than `max(atol, rtol*σ₁)` where `σ₁` is `A`'s largest calculated singular value.
253+ `atol` and `rtol` are the absolute and relative tolerances, respectively.
254+ The default relative tolerance is `n*ϵ`,
255+ where `n` is the size of the smallest dimension of `A`,
256+ and `ϵ` is the [`eps`](@ref) of the element type of `A`.
257+ !!! note
258+ Numerical rank can be a sensitive and imprecise characterization of
259+ ill-conditioned matrices with singular values that are close to the threshold
260+ tolerance `max(atol, rtol*σ₁)`. In such cases, slight perturbations to the
261+ singular-value computation or to the matrix can change the result of `rank`
262+ by pushing one or more singular values across the threshold. These variations
263+ can even occur due to changes in floating-point errors between different Julia
264+ versions, architectures, compilers, or operating systems.
265+
266+ !!! compat "Julia 1.1"
267+ The `atol` and `rtol` keyword arguments requires at least Julia 1.1.
268+ In Julia 1.0 `rtol` is available as a positional argument, but this
269+ will be deprecated in Julia 2.0.
270+
271+ """
272+
273+ function rank (S:: SVD{<:Any,T} ; atol:: Real = 0.0 , rtol:: Real = (min (size (S)... )* eps (real (float (one (eltype (S))))))) where {T}
274+ svals = getfield (S, :S )
275+ tol = max (atol, rtol* svals[1 ])
276+ count (> (tol), svals)
277+ end
278+
248279# ## SVD least squares ###
249280function ldiv! (A:: SVD{T} , B:: AbstractVecOrMat ) where T
250281 m, n = size (A)
0 commit comments