diff --git a/NEWS.md b/NEWS.md index 0fe173063bc5d..9931f1ca56136 100644 --- a/NEWS.md +++ b/NEWS.md @@ -338,6 +338,8 @@ Deprecated or removed * `expm` has been deprecated in favor of `exp` ([#23233]). + * `logm` has been deprecated in favor of `log` ([#CATS]). + * Calling `union` with no arguments is deprecated; construct an empty set with an appropriate element type using `Set{T}()` instead ([#23144]). diff --git a/base/deprecated.jl b/base/deprecated.jl index 1cd9a22640d3c..a616b456c8d43 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -220,7 +220,7 @@ for f in (:sin, :sinh, :sind, :asin, :asinh, :asind, :tan, :tanh, :tand, :atan, :atanh, :atand, :sinpi, :cosc, :ceil, :floor, :trunc, :round, :log1p, :expm1, :abs, :abs2, - :log, :log2, :log10, :exp2, :exp10, :sinc, :cospi, + :log2, :log10, :exp2, :exp10, :sinc, :cospi, :cos, :cosh, :cosd, :acos, :acosd, :cot, :coth, :cotd, :acot, :acotd, :sec, :sech, :secd, :asech, @@ -247,13 +247,13 @@ for f in ( # base/special/trig.jl :sinpi, :cospi, :sinc, :cosc, # base/special/log.jl - :log, :log1p, + :log1p, # base/special/gamma.jl :gamma, :lfact, # base/math.jl :cbrt, :sinh, :cosh, :tanh, :atan, :asinh, :exp2, :expm1, :exp10, :sin, :cos, :tan, :asin, :acos, :acosh, :atanh, - #=:log,=# :log2, :log10, :lgamma, #=:log1p,=# :sqrt, + :log2, :log10, :lgamma, #=:log1p,=# :sqrt, # base/floatfuncs.jl :abs, :abs2, :angle, :isnan, :isinf, :isfinite, # base/complex.jl @@ -1664,6 +1664,9 @@ end @deprecate expm! exp! @deprecate expm exp +# deprecate logm in favor of log +@deprecate logm log + # PR #23092 @eval LibGit2 begin function prompt(msg::AbstractString; default::AbstractString="", password::Bool=false) diff --git a/base/exports.jl b/base/exports.jl index b1c77b26fb2b8..f3464d9677559 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -589,7 +589,6 @@ export linreg, logabsdet, logdet, - logm, lu, lufact!, lufact, diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 42228106ee3e5..e4af085b5c27c 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -426,7 +426,7 @@ function (^)(A::AbstractMatrix{T}, p::Real) where T # Otherwise, use Schur decomposition return schurpow(A, p) end -(^)(A::AbstractMatrix, p::Number) = exp(p*logm(A)) +(^)(A::AbstractMatrix, p::Number) = exp(p*log(A)) # Matrix exponential @@ -556,7 +556,7 @@ function rcswap!(i::Integer, j::Integer, X::StridedMatrix{<:Number}) end """ - logm(A{T}::StridedMatrix{T}) + log(A{T}::StridedMatrix{T}) If `A` has no negative real eigenvalue, compute the principal matrix logarithm of `A`, i.e. the unique matrix ``X`` such that ``e^X = A`` and ``-\\pi < Im(\\lambda) < \\pi`` for all @@ -580,25 +580,25 @@ julia> A = 2.7182818 * eye(2) 2.71828 0.0 0.0 2.71828 -julia> logm(A) +julia> log(A) 2×2 Symmetric{Float64,Array{Float64,2}}: 1.0 0.0 0.0 1.0 ``` """ -function logm(A::StridedMatrix{T}) where T +function log(A::StridedMatrix{T}) where T # If possible, use diagonalization if issymmetric(A) && T <: Real - return logm(Symmetric(A)) + return log(Symmetric(A)) end if ishermitian(A) - return logm(Hermitian(A)) + return log(Hermitian(A)) end # Use Schur decomposition n = checksquare(A) if istriu(A) - return full(logm(UpperTriangular(complex(A)))) + return full(log(UpperTriangular(complex(A)))) else if isreal(A) SchurF = schurfact(real(A)) @@ -607,19 +607,14 @@ function logm(A::StridedMatrix{T}) where T end if !istriu(SchurF.T) SchurS = schurfact(complex(SchurF.T)) - logT = SchurS.Z * logm(UpperTriangular(SchurS.T)) * SchurS.Z' + logT = SchurS.Z * log(UpperTriangular(SchurS.T)) * SchurS.Z' return SchurF.Z * logT * SchurF.Z' else - R = logm(UpperTriangular(complex(SchurF.T))) + R = log(UpperTriangular(complex(SchurF.T))) return SchurF.Z * R * SchurF.Z' end end end -function logm(a::Number) - b = log(complex(a)) - return imag(b) == 0 ? real(b) : b -end -logm(a::Complex) = log(a) """ sqrtm(A) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 7161d20450b6c..beac1cf844cbd 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -327,8 +327,7 @@ eye(::Type{Diagonal{T}}, n::Int) where {T} = Diagonal(ones(T,n)) # Matrix functions exp(D::Diagonal) = Diagonal(exp.(D.diag)) -logm(D::Diagonal) = Diagonal(log.(D.diag)) -logm(D::Diagonal{<:AbstractMatrix}) = Diagonal(logm.(D.diag)) +log(D::Diagonal) = Diagonal(log.(D.diag)) sqrtm(D::Diagonal) = Diagonal(sqrt.(D.diag)) sqrtm(D::Diagonal{<:AbstractMatrix}) = Diagonal(sqrtm.(D.diag)) diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index 6eaea00de1b4d..46025dd8d2999 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -7,7 +7,7 @@ import Base: A_mul_Bt, At_ldiv_Bt, A_rdiv_Bc, At_ldiv_B, Ac_mul_Bc, A_mul_Bc, Ac Ac_ldiv_B, Ac_ldiv_Bc, At_mul_Bt, A_rdiv_Bt, At_mul_B import Base: USE_BLAS64, abs, big, broadcast, ceil, conj, convert, copy, copy!, adjoint, eltype, exp, eye, findmax, findmin, fill!, floor, full, getindex, - hcat, imag, indices, inv, isapprox, isone, IndexStyle, kron, length, map, + hcat, imag, indices, inv, isapprox, isone, IndexStyle, kron, length, log, map, ndims, oneunit, parent, power_by_squaring, print_matrix, promote_rule, real, round, setindex!, show, similar, size, transpose, trunc, typed_hcat using Base: hvcat_fill, iszero, IndexLinear, _length, promote_op, promote_typeof, @@ -101,7 +101,6 @@ export linreg, logabsdet, logdet, - logm, lu, lufact, lufact!, diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 92fe036dbf94f..99d95ba112ab6 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -607,7 +607,7 @@ function exp(A::Hermitian{T}) where T end end -for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) +for (funm, func) in ([:sqrtm,:sqrt],) @eval begin function ($funm)(A::Symmetric{T}) where T<:Real F = eigfact(A) @@ -639,3 +639,36 @@ for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) end end end + +for func in (:log, #=:sqrtm=#) + @eval begin + function ($func)(A::Symmetric{T}) where T<:Real + F = eigfact(A) + if all(λ -> λ ≥ 0, F.values) + retmat = (F.vectors * Diagonal(($func).(F.values))) * F.vectors' + else + retmat = (F.vectors * Diagonal(($func).(complex.(F.values)))) * F.vectors' + end + return Symmetric(retmat) + end + + function ($func)(A::Hermitian{T}) where T + n = checksquare(A) + F = eigfact(A) + if all(λ -> λ ≥ 0, F.values) + retmat = (F.vectors * Diagonal(($func).(F.values))) * F.vectors' + if T <: Real + return Hermitian(retmat) + else + for i = 1:n + retmat[i,i] = real(retmat[i,i]) + end + return Hermitian(retmat) + end + else + retmat = (F.vectors * Diagonal(($func).(complex(F.values)))) * F.vectors' + return retmat + end + end + end +end diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index ccac60e9cfb7a..eb2af9ab869d5 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1789,7 +1789,7 @@ powm(A::LowerTriangular, p::Real) = powm(A.', p::Real).' # Based on the code available at http://eprints.ma.man.ac.uk/1851/02/logm.zip, # Copyright (c) 2011, Awad H. Al-Mohy and Nicholas J. Higham # Julia version relicensed with permission from original authors -function logm(A0::UpperTriangular{T}) where T<:Union{Float64,Complex{Float64}} +function log(A0::UpperTriangular{T}) where T<:Union{Float64,Complex{Float64}} maxsqrt = 100 theta = [1.586970738772063e-005, 2.313807884242979e-003, @@ -1961,9 +1961,9 @@ function logm(A0::UpperTriangular{T}) where T<:Union{Float64,Complex{Float64}} return UpperTriangular(Y) end -logm(A::LowerTriangular) = logm(A.').' +log(A::LowerTriangular) = log(A.').' -# Auxiliary functions for logm and matrix power +# Auxiliary functions for matrix logarithm and matrix power # Compute accurate diagonal of A = A0^s - I # Al-Mohy, "A more accurate Briggs method for the logarithm", @@ -2117,7 +2117,7 @@ end unw(x::Real) = 0 unw(x::Number) = ceil((imag(x) - pi) / (2 * pi)) -# End of auxiliary functions for logm and matrix power +# End of auxiliary functions for matrix logarithm and matrix power function sqrtm(A::UpperTriangular) realmatrix = false diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index 66dd343d3f195..99c8c2f3d3412 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -92,7 +92,6 @@ Base.repmat Base.kron Base.SparseArrays.blkdiag Base.LinAlg.linreg -Base.LinAlg.logm Base.LinAlg.sqrtm Base.LinAlg.lyap Base.LinAlg.sylvester diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index 30fcf9ace436c..1635b415dd92b 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -453,20 +453,20 @@ end 1/3 1/4 1/5 1/6; 1/4 1/5 1/6 1/7; 1/5 1/6 1/7 1/8]) - @test exp(logm(A4)) ≈ A4 + @test exp(log(A4)) ≈ A4 A5 = convert(Matrix{elty}, [1 1 0 1; 0 1 1 0; 0 0 1 1; 1 0 0 1]) - @test exp(logm(A5)) ≈ A5 + @test exp(log(A5)) ≈ A5 A6 = convert(Matrix{elty}, [-5 2 0 0 ; 1/2 -7 3 0; 0 1/3 -9 4; 0 0 1/4 -11]) - @test exp(logm(A6)) ≈ A6 + @test exp(log(A6)) ≈ A6 A7 = convert(Matrix{elty}, [1 0 0 1e-8; 0 1 0 0; 0 0 1 0; 0 0 0 1]) - @test exp(logm(A7)) ≈ A7 + @test exp(log(A7)) ≈ A7 end A8 = 100 * [-1+1im 0 0 1e-8; 0 1 0 0; 0 0 1 0; 0 0 0 1] - @test exp(logm(A8)) ≈ A8 + @test exp(log(A8)) ≈ A8 end @testset "issue 5116" begin @@ -487,28 +487,28 @@ end @testset "Additional matrix logarithm tests" for elty in (Float64, Complex{Float64}) A11 = convert(Matrix{elty}, [3 2; -5 -3]) - @test exp(logm(A11)) ≈ A11 + @test exp(log(A11)) ≈ A11 A12 = convert(Matrix{elty}, [1 -1; 1 -1]) - @test typeof(logm(A12)) == Array{Complex{Float64}, 2} + @test typeof(log(A12)) == Array{Complex{Float64}, 2} A1 = convert(Matrix{elty}, [4 2 0; 1 4 1; 1 1 4]) - logmA1 = convert(Matrix{elty}, [1.329661349 0.5302876358 -0.06818951543; + logA1 = convert(Matrix{elty}, [1.329661349 0.5302876358 -0.06818951543; 0.2310490602 1.295566591 0.2651438179; 0.2310490602 0.1969543025 1.363756107]) - @test logm(A1) ≈ logmA1 - @test exp(logm(A1)) ≈ A1 + @test log(A1) ≈ logA1 + @test exp(log(A1)) ≈ A1 A4 = convert(Matrix{elty}, [1/2 1/3 1/4 1/5+eps(); 1/3 1/4 1/5 1/6; 1/4 1/5 1/6 1/7; 1/5 1/6 1/7 1/8]) - logmA4 = convert(Matrix{elty}, [-1.73297159 1.857349738 0.4462766564 0.2414170219; + logA4 = convert(Matrix{elty}, [-1.73297159 1.857349738 0.4462766564 0.2414170219; 1.857349738 -5.335033737 2.994142974 0.5865285289; 0.4462766564 2.994142974 -7.351095988 3.318413247; 0.2414170219 0.5865285289 3.318413247 -5.444632124]) - @test logm(A4) ≈ logmA4 - @test exp(logm(A4)) ≈ A4 + @test log(A4) ≈ logA4 + @test exp(log(A4)) ≈ A4 end @testset "issue #7181" begin @@ -677,7 +677,7 @@ end @test exp(a) == exp(a) @test isposdef(one(elty)) @test sqrtm(a) == sqrt(a) - @test logm(a) ≈ log(a) + @test log(a) ≈ log(a) @test lyap(one(elty),a) == -a/2 end diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index 3ec850f125591..47b7eaf509194 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -63,7 +63,7 @@ srand(1) for func in (exp,) @test func(D) ≈ func(DM) atol=n^3*eps(relty) end - @test logm(Diagonal(abs.(D.diag))) ≈ logm(abs.(DM)) atol=n^3*eps(relty) + @test log(Diagonal(abs.(D.diag))) ≈ log(abs.(DM)) atol=n^3*eps(relty) end if elty <: BlasComplex for func in (logdet, sqrtm) @@ -382,7 +382,7 @@ end @test ishermitian(Dsym) == false @test exp(D) == Diagonal([exp([1 2; 3 4]), exp([1 2; 3 4])]) - @test logm(D) == Diagonal([logm([1 2; 3 4]), logm([1 2; 3 4])]) + @test log(D) == Diagonal([log([1 2; 3 4]), log([1 2; 3 4])]) @test sqrtm(D) == Diagonal([sqrtm([1 2; 3 4]), sqrtm([1 2; 3 4])]) end diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index 09b4370ed922c..d5d7164f80d63 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -13,17 +13,17 @@ end A1 = randn(4,4) + im*randn(4,4) A2 = A1 + A1' @test exp(A2) ≈ exp(Hermitian(A2)) - @test logm(A2) ≈ logm(Hermitian(A2)) + @test log(A2) ≈ log(Hermitian(A2)) A3 = A1 * A1' # posdef @test exp(A3) ≈ exp(Hermitian(A3)) - @test logm(A3) ≈ logm(Hermitian(A3)) + @test log(A3) ≈ log(Hermitian(A3)) A1 = randn(4,4) A3 = A1 * A1' A4 = A1 + A1.' @test exp(A4) ≈ exp(Symmetric(A4)) - @test logm(A3) ≈ logm(Symmetric(A3)) - @test logm(A3) ≈ logm(Hermitian(A3)) + @test log(A3) ≈ log(Symmetric(A3)) + @test log(A3) ≈ log(Hermitian(A3)) end @testset "Core functionality" begin diff --git a/test/linalg/triangular.jl b/test/linalg/triangular.jl index eb0fc7cd57717..8589b530160ff 100644 --- a/test/linalg/triangular.jl +++ b/test/linalg/triangular.jl @@ -174,9 +174,9 @@ for elty1 in (Float32, Float64, BigFloat, Complex64, Complex128, Complex{BigFloa @test B == viewA1.' end - #exp/logm + #exp/log if (elty1 == Float64 || elty1 == Complex128) && (t1 == UpperTriangular || t1 == LowerTriangular) - @test exp(full(logm(A1))) ≈ full(A1) + @test exp(full(log(A1))) ≈ full(A1) end # scale