Skip to content

Commit

Permalink
Deprecate eig to eigen and destructuring via iteration.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sacha0 committed May 23, 2018
1 parent 6e5d700 commit aa65388
Show file tree
Hide file tree
Showing 16 changed files with 82 additions and 98 deletions.
15 changes: 15 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,21 @@ Deprecated or removed
`lu!`, `schur!`, `lq!`, `qr!`, `ldlt!`, `svd!`, `bunchkaufman!`,
`hessenberg!`, and `eigen!` ([#27159]).

* `eig(A[, args...])` has been deprecated in favor of `eigen(A[, args...])`.
Whereas the former returns a tuple of arrays, the latter returns an `Eigen` object.
So for a direct replacement, use `(eigen(A[, args...])...,)`. But going forward,
consider using the direct result of `eigen(A[, args...])` instead, either
destructured into its components (`vals, vecs = eigen(A[, args...])`) or
as an `Eigen` object (`X = eigen(A[, args...])`) ([#26997], [#27159], [#27212]).

* `eig(A::AbstractMatrix, B::AbstractMatrix)` and `eig(A::Number, B::Number)`
have been deprecated in favor of `eigen(A, B)`. Whereas the former each return
a tuple of arrays, the latter returns a `GeneralizedEigen` object. So for a direct
replacement, use `(eigen(A, B)...,)`. But going forward, consider using the
direct result of `eigen(A, B)` instead, either destructured into its components
(`vals, vecs = eigen(A, B)`), or as a `GeneralizedEigen` object
(`X = eigen(A, B)`) ([#26997], [#27159], [#27212]).

* Indexing into multidimensional arrays with more than one index but fewer indices than there are
dimensions is no longer permitted when those trailing dimensions have lengths greater than 1.
Instead, reshape the array or add trailing indices so the dimensionality and number of indices
Expand Down
3 changes: 1 addition & 2 deletions stdlib/LinearAlgebra/docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Legend:

### Matrix factorizations

| Matrix type | LAPACK | [`eig`](@ref) | [`eigvals`](@ref) | [`eigvecs`](@ref) | [`svd`](@ref) | [`svdvals`](@ref) |
| Matrix type | LAPACK | [`eigen`](@ref) | [`eigvals`](@ref) | [`eigvecs`](@ref) | [`svd`](@ref) | [`svdvals`](@ref) |
|:------------------------- |:------ |:------------- |:----------------- |:----------------- |:------------- |:----------------- |
| [`Symmetric`](@ref) | SY | | ARI | | | |
| [`Hermitian`](@ref) | HE | | ARI | | | |
Expand Down Expand Up @@ -331,7 +331,6 @@ LinearAlgebra.lq!
LinearAlgebra.lq
LinearAlgebra.bunchkaufman
LinearAlgebra.bunchkaufman!
LinearAlgebra.eig
LinearAlgebra.eigvals
LinearAlgebra.eigvals!
LinearAlgebra.eigmax
Expand Down
1 change: 0 additions & 1 deletion stdlib/LinearAlgebra/src/LinearAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export
diagind,
diagm,
dot,
eig,
eigen,
eigen!,
eigmax,
Expand Down
41 changes: 41 additions & 0 deletions stdlib/LinearAlgebra/src/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1410,3 +1410,44 @@ export eigfact!
@deprecate(cholfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, ::Val{true}; tol = 0.0), cholesky!(A, Val(true); tol=tol))
@deprecate(cholfact!(A::RealHermSymComplexHerm{<:Real}, ::Val{true}; tol = 0.0), cholesky!(A, Val(true); tol=tol))
@deprecate(cholfact!(A::StridedMatrix, ::Val{true}; tol = 0.0), cholesky!(A, Val(true); tol=tol))

# deprecate eig in favor of eigen and destructuring via iteration
# deprecate eig(...) in favor of eigfact and factorization destructuring
export eig
function eig(A::Union{Number, StridedMatrix}; permute::Bool=true, scale::Bool=true)
depwarn(string("`eig(A[, permute, scale])` has been deprecated in favor of ",
"`eigen(A[, permute, scale])`. Whereas `eig(A[, permute, scale])` ",
"returns a tuple of arrays, `eigen(A[, permute, scale])` returns ",
"an `Eigen` object. So for a direct replacement, use ",
"`(eigen(A[, permute, scale])...,)`. But going forward, consider ",
"using the direct result of `eigen(A[, permute, scale])` instead, ",
"either destructured into its components ",
"(`vals, vecs = eigen(A[, permute, scale])`) ",
"or as an `Eigen` object (`X = eigen(A[, permute, scale])`)."), :eig)
return (eigen(A; permute=permute, scale=scale)...,)
end
function eig(A::AbstractMatrix, args...)
depwarn(string("`eig(A, args...)` has been deprecated in favor of ",
"`eigen(A, args...)`. Whereas `eig(A, args....)` ",
"returns a tuple of arrays, `eigen(A, args...)` returns ",
"an `Eigen` object. So for a direct replacement, use ",
"`(eigen(A, args...)...,)`. But going forward, consider ",
"using the direct result of `eigen(A, args...)` instead, ",
"either destructured into its components ",
"(`vals, vecs = eigen(A, args...)`) ",
"or as an `Eigen` object (`X = eigen(A, args...)`)."), :eig)
return (eigen(A, args...)...,)
end
eig(A::AbstractMatrix, B::AbstractMatrix) = _geneig(A, B)
eig(A::Number, B::Number) = _geneig(A, B)
function _geneig(A, B)
depwarn(string("`eig(A::AbstractMatrix, B::AbstractMatrix)` and ",
"`eig(A::Number, B::Number)` have been deprecated in favor of ",
"`eigen(A, B)`. Whereas the former each return a tuple of arrays, ",
"the latter returns a `GeneralizedEigen` object. So for a direct ",
"replacement, use `(eigen(A, B)...,)`. But going forward, consider ",
"using the direct result of `eigen(A, B)` instead, either ",
"destructured into its components (`vals, vecs = eigen(A, B)`), ",
"or as a `GeneralizedEigen` object (`X = eigen(A, B)`)."), :eig)
return (eigen(A, B)...,)
end
65 changes: 0 additions & 65 deletions stdlib/LinearAlgebra/src/eigen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,38 +126,6 @@ function eigen(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) where
end
eigen(x::Number) = Eigen([x], fill(one(x), 1, 1))

function eig(A::Union{Number, StridedMatrix}; permute::Bool=true, scale::Bool=true)
F = eigen(A, permute=permute, scale=scale)
F.values, F.vectors
end

"""
eig(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> D, V
eig(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> D, V
eig(A, permute::Bool=true, scale::Bool=true) -> D, V
Computes eigenvalues (`D`) and eigenvectors (`V`) of `A`.
See [`eigen`](@ref) for details on the
`irange`, `vl`, and `vu` arguments
(for [`SymTridiagonal`](@ref), [`Hermitian`](@ref), and
[`Symmetric`](@ref) matrices)
and the `permute` and `scale` keyword arguments.
The eigenvectors are returned columnwise.
# Examples
```jldoctest
julia> eig([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])
([1.0, 3.0, 18.0], [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0])
```
`eig` is a wrapper around [`eigen`](@ref), extracting all parts of the
factorization to a tuple; where possible, using [`eigen`](@ref) is recommended.
"""
function eig(A::AbstractMatrix, args...)
F = eigen(A, args...)
F.values, F.vectors
end

"""
eigvecs(A; permute::Bool=true, scale::Bool=true) -> Matrix
Expand Down Expand Up @@ -416,39 +384,6 @@ end

eigen(A::Number, B::Number) = eigen(fill(A,1,1), fill(B,1,1))

"""
eig(A, B) -> D, V
Computes generalized eigenvalues (`D`) and vectors (`V`) of `A` with respect to `B`.
`eig` is a wrapper around [`eigen`](@ref), extracting all parts of the
factorization to a tuple; where possible, using [`eigen`](@ref) is recommended.
# Examples
```jldoctest
julia> A = [1 0; 0 -1]
2×2 Array{Int64,2}:
1 0
0 -1
julia> B = [0 1; 1 0]
2×2 Array{Int64,2}:
0 1
1 0
julia> eig(A, B)
(Complex{Float64}[0.0+1.0im, 0.0-1.0im], Complex{Float64}[0.0-1.0im 0.0+1.0im; -1.0-0.0im -1.0+0.0im])
```
"""
function eig(A::AbstractMatrix, B::AbstractMatrix)
F = eigen(A,B)
F.values, F.vectors
end
function eig(A::Number, B::Number)
F = eigen(A,B)
F.values, F.vectors
end

"""
eigvals!(A, B) -> values
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/src/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2156,7 +2156,7 @@ function log(A0::UpperTriangular{T}) where T<:BlasFloat
R[i,i+1] = i / sqrt((2 * i)^2 - 1)
R[i+1,i] = R[i,i+1]
end
x,V = eig(R)
x,V = eigen(R)
w = Vector{Float64}(undef, m)
for i = 1:m
x[i] = (x[i] + 1) / 2
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/test/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ srand(1)

@testset "Eigensystems" begin
if relty <: AbstractFloat
d1, v1 = eig(T)
d2, v2 = eig(map(elty<:Complex ? ComplexF64 : Float64,Tfull))
d1, v1 = eigen(T)
d2, v2 = eigen(map(elty<:Complex ? ComplexF64 : Float64,Tfull))
@test (uplo == :U ? d1 : reverse(d1)) d2
if elty <: Real
test_approx_eq_modphase(v1, uplo == :U ? v2 : v2[:,n:-1:1])
Expand Down
18 changes: 9 additions & 9 deletions stdlib/LinearAlgebra/test/eigen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ aimg = randn(n,n)/2

α = rand(eltya)
β = rand(eltya)
eab = eig(α,β)
@test eab[1] == eigvals(fill(α,1,1),fill(β,1,1))
@test eab[2] == eigvecs(fill(α,1,1),fill(β,1,1))
eab = eigen(α,β)
@test eab.values == eigvals(fill(α,1,1),fill(β,1,1))
@test eab.vectors == eigvecs(fill(α,1,1),fill(β,1,1))

@testset "non-symmetric eigen decomposition" begin
d, v = eig(a)
d, v = eigen(a)
for i in 1:size(a,2)
@test a*v[:,i] d[i]*v[:,i]
end
Expand Down Expand Up @@ -70,7 +70,7 @@ aimg = randn(n,n)/2
@test eigvecs(f) === f.vectors
@test_throws ErrorException f.Z

d,v = eig(asym_sg, a_sg'a_sg)
d,v = eigen(asym_sg, a_sg'a_sg)
@test d == f.values
@test v == f.vectors
end
Expand All @@ -89,7 +89,7 @@ aimg = randn(n,n)/2
@test eigvecs(a1_nsg, a2_nsg) == f.vectors
@test_throws ErrorException f.Z

d,v = eig(a1_nsg, a2_nsg)
d,v = eigen(a1_nsg, a2_nsg)
@test d == f.values
@test v == f.vectors
end
Expand All @@ -98,11 +98,11 @@ end

@testset "eigenvalue computations with NaNs" begin
for eltya in (NaN16, NaN32, NaN)
@test_throws(ArgumentError, eig(fill(eltya, 1, 1)))
@test_throws(ArgumentError, eig(fill(eltya, 2, 2)))
@test_throws(ArgumentError, eigen(fill(eltya, 1, 1)))
@test_throws(ArgumentError, eigen(fill(eltya, 2, 2)))
test_matrix = rand(typeof(eltya),3,3)
test_matrix[2,2] = eltya
@test_throws(ArgumentError, eig(test_matrix))
@test_throws(ArgumentError, eigen(test_matrix))
end
end

Expand Down
1 change: 0 additions & 1 deletion stdlib/LinearAlgebra/test/lu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ dimg = randn(n)/2
-eps(real(one(eltya)))/4 eps(real(one(eltya)))/2 -1.0 0;
-0.5 -0.5 0.1 1.0])
F = eigen(A, permute=false, scale=false)
eig(A, permute=false, scale=false)
@test F.vectors*Diagonal(F.values)/F.vectors A
F = eigen(A)
# @test norm(F.vectors*Diagonal(F.values)/F.vectors - A) > 0.01
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/test/schur.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ aimg = randn(n,n)/2
view(apd, 1:n, 1:n)))
ε = εa = eps(abs(float(one(eltya))))

d,v = eig(a)
d,v = eigen(a)
f = schur(a)
@test f.vectors*f.Schur*f.vectors' a
@test sort(real(f.values)) sort(real(d))
Expand Down
10 changes: 3 additions & 7 deletions stdlib/LinearAlgebra/test/symmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,29 +218,25 @@ end

@testset "symmetric eigendecomposition" begin
if eltya <: Real # the eigenvalues are only real and ordered for Hermitian matrices
d, v = eig(asym)
d, v = eigen(asym)
@test asym*v[:,1] d[1]*v[:,1]
@test v*Diagonal(d)*transpose(v) asym
@test isequal(eigvals(asym[1]), eigvals(asym[1:1,1:1]))
@test abs.(eigen(Symmetric(asym), 1:2).vectors'v[:,1:2]) Matrix(I, 2, 2)
eig(Symmetric(asym), 1:2) # same result, but checks that method works
@test abs.(eigen(Symmetric(asym), d[1] - 1, (d[2] + d[3])/2).vectors'v[:,1:2]) Matrix(I, 2, 2)
eig(Symmetric(asym), d[1] - 1, (d[2] + d[3])/2) # same result, but checks that method works
@test eigvals(Symmetric(asym), 1:2) d[1:2]
@test eigvals(Symmetric(asym), d[1] - 1, (d[2] + d[3])/2) d[1:2]
# eigen doesn't support Symmetric{Complex}
@test Matrix(eigen(asym)) asym
@test eigvecs(Symmetric(asym)) eigvecs(asym)
end

d, v = eig(aherm)
d, v = eigen(aherm)
@test aherm*v[:,1] d[1]*v[:,1]
@test v*Diagonal(d)*v' aherm
@test isequal(eigvals(aherm[1]), eigvals(aherm[1:1,1:1]))
@test abs.(eigen(Hermitian(aherm), 1:2).vectors'v[:,1:2]) Matrix(I, 2, 2)
eig(Hermitian(aherm), 1:2) # same result, but checks that method works
@test abs.(eigen(Hermitian(aherm), d[1] - 1, (d[2] + d[3])/2).vectors'v[:,1:2]) Matrix(I, 2, 2)
eig(Hermitian(aherm), d[1] - 1, (d[2] + d[3])/2) # same result, but checks that method works
@test eigvals(Hermitian(aherm), 1:2) d[1:2]
@test eigvals(Hermitian(aherm), d[1] - 1, (d[2] + d[3])/2) d[1:2]
@test Matrix(eigen(aherm)) aherm
Expand Down Expand Up @@ -365,7 +361,7 @@ end
end

@testset "Issues #8057 and #8058. f=$f, A=$A" for f in
(eigen, eigvals, eig),
(eigen, eigvals),
A in (Symmetric([0 1; 1 0]), Hermitian([0 im; -im 0]))
@test_throws ArgumentError f(A, 3, 2)
@test_throws ArgumentError f(A, 1:4)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/LinearAlgebra/test/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFlo

# eigenproblems
if !(elty1 in (BigFloat, Complex{BigFloat})) # Not handled yet
vals, vecs = eig(A1)
vals, vecs = eigen(A1)
if (t1 == UpperTriangular || t1 == LowerTriangular) && elty1 != Int # Cannot really handle degenerate eigen space and Int matrices will probably have repeated eigenvalues.
@test vecs*diagm(0 => vals)/vecs A1 atol=sqrt(eps(float(real(one(vals[1])))))*(norm(A1,Inf)*n)^2
end
Expand Down
10 changes: 5 additions & 5 deletions stdlib/LinearAlgebra/test/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ end
w, iblock, isplit = LAPACK.stebz!('V', 'B', -infinity, infinity, 0, 0, zero, b, a)
evecs = LAPACK.stein!(b, a, w)

(e, v) = eig(SymTridiagonal(b, a))
(e, v) = eigen(SymTridiagonal(b, a))
@test e w
test_approx_eq_vecs(v, evecs)
end
Expand All @@ -266,10 +266,10 @@ end
end
@testset "eigenvalues/eigenvectors of symmetric tridiagonal" begin
if elty === Float32 || elty === Float64
DT, VT = @inferred eig(A)
@inferred eig(A, 2:4)
@inferred eig(A, 1.0, 2.0)
D, Vecs = eig(fA)
DT, VT = @inferred eigen(A)
@inferred eigen(A, 2:4)
@inferred eigen(A, 1.0, 2.0)
D, Vecs = eigen(fA)
@test DT D
@test abs.(VT'Vecs) Matrix(elty(1)I, n, n)
test_approx_eq_modphase(eigvecs(A), eigvecs(fA))
Expand Down
2 changes: 1 addition & 1 deletion stdlib/SparseArrays/src/SparseArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ using Base.Sort: Forward
using LinearAlgebra

import Base: +, -, *, \, /, &, |, xor, ==
import LinearAlgebra: mul!, ldiv!, rdiv!, chol, adjoint!, diag, dot, eig,
import LinearAlgebra: mul!, ldiv!, rdiv!, chol, adjoint!, diag, dot, eigen,
issymmetric, istril, istriu, lu, tr, transpose!, tril!, triu!,
vecnorm, cond, diagm, factorize, ishermitian, norm, lmul!, rmul!, tril, triu

Expand Down
2 changes: 1 addition & 1 deletion stdlib/SparseArrays/src/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ function factorize(A::LinearAlgebra.RealHermSymComplexHerm{Float64,<:SparseMatri
end

chol(A::SparseMatrixCSC) = error("Use cholesky() instead of chol() for sparse matrices.")
eig(A::SparseMatrixCSC) = error("Use IterativeEigensolvers.eigs() instead of eig() for sparse matrices.")
eigen(A::SparseMatrixCSC) = error("Use IterativeEigensolvers.eigs() instead of eigen() for sparse matrices.")

function Base.cov(X::SparseMatrixCSC; dims::Int=1, corrected::Bool=true)
vardim = dims
Expand Down
2 changes: 1 addition & 1 deletion stdlib/SparseArrays/test/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1780,7 +1780,7 @@ end
C, b = A[:, 1:4], fill(1., size(A, 1))
@test !Base.USE_GPL_LIBS || factorize(C)\b Array(C)\b
@test_throws ErrorException chol(A)
@test_throws ErrorException eig(A)
@test_throws ErrorException eigen(A)
@test_throws ErrorException inv(A)
end

Expand Down

0 comments on commit aa65388

Please sign in to comment.