Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add relative and absolute tolerance for rank. #29926

Merged
merged 16 commits into from
Dec 6, 2018
18 changes: 10 additions & 8 deletions stdlib/LinearAlgebra/src/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -715,10 +715,9 @@ end
rank(A[, tol::Real])

Compute the rank of a matrix by counting how many singular
values of `A` have magnitude greater than `tol*σ₁` where `σ₁` is
`A`'s largest singular values. By default, the value of `tol` is the smallest
dimension of `A` multiplied by the [`eps`](@ref)
of the [`eltype`](@ref) of `A`.
values of `A` have magnitude greater than `rtol*σ₁ + atol` where `σ₁` is
`A`'s largest singular values, atol and rtol are the absolute and relative
sam0410 marked this conversation as resolved.
Show resolved Hide resolved
tolerance respectively.
sam0410 marked this conversation as resolved.
Show resolved Hide resolved

# Examples
```jldoctest
Expand All @@ -728,16 +727,19 @@ julia> rank(Matrix(I, 3, 3))
julia> rank(diagm(0 => [1, 0, 2]))
2

julia> rank(diagm(0 => [1, 0.001, 2]), 0.1)
julia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.1)
2

julia> rank(diagm(0 => [1, 0.001, 2]), 0.00001)
julia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.00001)
3

julia> rank(diagm(0 => [1, 0.001, 2]), atol=0.00001, rtol=0.00001)
sam0410 marked this conversation as resolved.
Show resolved Hide resolved
3
```
"""
function rank(A::AbstractMatrix, tol::Real = min(size(A)...)*eps(real(float(one(eltype(A))))))
function rank(A::AbstractMatrix; atol=0.0, rtol=0.0)
sam0410 marked this conversation as resolved.
Show resolved Hide resolved
s = svdvals(A)
count(x -> x > tol*s[1], s)
count(x -> x > (atol + rtol * s[1]), s)
sam0410 marked this conversation as resolved.
Show resolved Hide resolved
end
rank(x::Number) = x == 0 ? 0 : 1

Expand Down
4 changes: 3 additions & 1 deletion stdlib/LinearAlgebra/test/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ end
end

@test rank(fill(0, 0, 0)) == 0
@test rank([1.0 0.0; 0.0 0.9],0.95) == 1
@test rank([1.0 0.0; 0.0 0.9],rtol=0.95) == 1
@test rank([1.0 0.0; 0.0 0.9],atol=0.95) == 1
@test rank([1.0 0.0; 0.0 0.9],atol=0.95,rtol=0.95)==0
@test qr(big.([0 1; 0 0])).R == [0 1; 0 0]

@test norm([2.4e-322, 4.4e-323]) ≈ 2.47e-322
Expand Down