diff --git a/stdlib/LinearAlgebra/src/deprecated.jl b/stdlib/LinearAlgebra/src/deprecated.jl index 8889d5c8eaf94..b56241c2ab918 100644 --- a/stdlib/LinearAlgebra/src/deprecated.jl +++ b/stdlib/LinearAlgebra/src/deprecated.jl @@ -1,3 +1,4 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Base: @deprecate, depwarn +# To be deprecated in 2.0 +rank(A::AbstractMatrix, tol::Real) = rank(A,rtol=tol) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index f63eb1b78764c..7b22caeb6e299 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -712,13 +712,15 @@ end ########################################################################################### """ - rank(A[, tol::Real]) + rank(A::AbstractMatrix; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ) + rank(A::AbstractMatrix, rtol::Real) = rank(A; rtol=rtol) # to be deprecated in Julia 2.0 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 `max(atol, rtol*σ₁)` where `σ₁` is +`A`'s largest singular value. `atol` and `rtol` are the absolute and relative +tolerances, respectively. The default relative tolerance is `n*ϵ`, where `n` +is the size of the smallest dimension of `A`, and `ϵ` is the [`eps`](@ref) of +the element type of `A`. # Examples ```jldoctest @@ -728,16 +730,21 @@ 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=1.5) +1 ``` """ -function rank(A::AbstractMatrix, tol::Real = min(size(A)...)*eps(real(float(one(eltype(A)))))) +function rank(A::AbstractMatrix; atol::Real = 0.0, rtol::Real = (min(size(A)...)*eps(real(float(one(eltype(A))))))*iszero(atol)) + isempty(A) && return 0 # 0-dimensional case s = svdvals(A) - count(x -> x > tol*s[1], s) + tol = max(atol, rtol*s[1]) + count(x -> x > tol, s) end rank(x::Number) = x == 0 ? 0 : 1 diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 8591a07aa9f8f..ef53753bf491c 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -195,6 +195,9 @@ 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)==1 @test qr(big.([0 1; 0 0])).R == [0 1; 0 0] @test norm([2.4e-322, 4.4e-323]) ≈ 2.47e-322