Skip to content

Commit 060d1bf

Browse files
sam0410simonbyrne
authored andcommitted
Add relative and absolute tolerance for rank. (#29926)
1 parent 0894208 commit 060d1bf

File tree

3 files changed

+21
-10
lines changed

3 files changed

+21
-10
lines changed
+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
using Base: @deprecate, depwarn
3+
# To be deprecated in 2.0
4+
rank(A::AbstractMatrix, tol::Real) = rank(A,rtol=tol)

stdlib/LinearAlgebra/src/generic.jl

+16-9
Original file line numberDiff line numberDiff line change
@@ -712,13 +712,15 @@ end
712712
###########################################################################################
713713

714714
"""
715-
rank(A[, tol::Real])
715+
rank(A::AbstractMatrix; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)
716+
rank(A::AbstractMatrix, rtol::Real) = rank(A; rtol=rtol) # to be deprecated in Julia 2.0
716717
717718
Compute the rank of a matrix by counting how many singular
718-
values of `A` have magnitude greater than `tol*σ₁` where `σ₁` is
719-
`A`'s largest singular values. By default, the value of `tol` is the smallest
720-
dimension of `A` multiplied by the [`eps`](@ref)
721-
of the [`eltype`](@ref) of `A`.
719+
values of `A` have magnitude greater than `max(atol, rtol*σ₁)` where `σ₁` is
720+
`A`'s largest singular value. `atol` and `rtol` are the absolute and relative
721+
tolerances, respectively. The default relative tolerance is `n*ϵ`, where `n`
722+
is the size of the smallest dimension of `A`, and `ϵ` is the [`eps`](@ref) of
723+
the element type of `A`.
722724
723725
# Examples
724726
```jldoctest
@@ -728,16 +730,21 @@ julia> rank(Matrix(I, 3, 3))
728730
julia> rank(diagm(0 => [1, 0, 2]))
729731
2
730732
731-
julia> rank(diagm(0 => [1, 0.001, 2]), 0.1)
733+
julia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.1)
732734
2
733735
734-
julia> rank(diagm(0 => [1, 0.001, 2]), 0.00001)
736+
julia> rank(diagm(0 => [1, 0.001, 2]), rtol=0.00001)
735737
3
738+
739+
julia> rank(diagm(0 => [1, 0.001, 2]), atol=1.5)
740+
1
736741
```
737742
"""
738-
function rank(A::AbstractMatrix, tol::Real = min(size(A)...)*eps(real(float(one(eltype(A))))))
743+
function rank(A::AbstractMatrix; atol::Real = 0.0, rtol::Real = (min(size(A)...)*eps(real(float(one(eltype(A))))))*iszero(atol))
744+
isempty(A) && return 0 # 0-dimensional case
739745
s = svdvals(A)
740-
count(x -> x > tol*s[1], s)
746+
tol = max(atol, rtol*s[1])
747+
count(x -> x > tol, s)
741748
end
742749
rank(x::Number) = x == 0 ? 0 : 1
743750

stdlib/LinearAlgebra/test/generic.jl

+3
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ end
195195

196196
@test rank(fill(0, 0, 0)) == 0
197197
@test rank([1.0 0.0; 0.0 0.9],0.95) == 1
198+
@test rank([1.0 0.0; 0.0 0.9],rtol=0.95) == 1
199+
@test rank([1.0 0.0; 0.0 0.9],atol=0.95) == 1
200+
@test rank([1.0 0.0; 0.0 0.9],atol=0.95,rtol=0.95)==1
198201
@test qr(big.([0 1; 0 0])).R == [0 1; 0 0]
199202

200203
@test norm([2.4e-322, 4.4e-323]) 2.47e-322

0 commit comments

Comments
 (0)