Skip to content

Commit cb57b9d

Browse files
committed
Make it easier to dispatch to symmetric eigensolver methods defined
in GenericLinearAlgebra by prefixing the computational methods with underscores.
1 parent 5838094 commit cb57b9d

File tree

2 files changed

+39
-31
lines changed

2 files changed

+39
-31
lines changed

src/eigenSelfAdjoint.jl

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ using Printf
22
using LinearAlgebra
33
using LinearAlgebra: givensAlgorithm
44

5-
import LinearAlgebra: eigen, eigen!, eigvals, eigvals!, mul!
6-
75
struct SymmetricTridiagonalFactorization{T} <: Factorization{T}
86
uplo::Char
97
factors::Matrix{T}
@@ -19,7 +17,7 @@ struct EigenQ{T} <: AbstractMatrix{T}
1917
τ::Vector{T}
2018
end
2119

22-
getq(S::SymmetricTridiagonalFactorization) = EigenQ(S.uplo, S.factors, S.τ)
20+
LinearAlgebra.getq(S::SymmetricTridiagonalFactorization) = EigenQ(S.uplo, S.factors, S.τ)
2321

2422
Base.size(Q::EigenQ) = (size(Q.factors, 1), size(Q.factors, 1))
2523
function Base.size(Q::EigenQ, i::Integer)
@@ -32,7 +30,7 @@ function Base.size(Q::EigenQ, i::Integer)
3230
end
3331
end
3432

35-
function mul!(Q::EigenQ, B::StridedVecOrMat)
33+
function LinearAlgebra.lmul!(Q::EigenQ, B::StridedVecOrMat)
3634
m, n = size(B)
3735
if size(Q, 1) != m
3836
throw(DimensionMismatch(""))
@@ -73,7 +71,7 @@ function mul!(Q::EigenQ, B::StridedVecOrMat)
7371
return B
7472
end
7573

76-
function mul!(A::StridedMatrix, Q::EigenQ)
74+
function LinearAlgebra.rmul!(A::StridedMatrix, Q::EigenQ)
7775
m, n = size(A)
7876
if size(Q, 1) != n
7977
throw(DimensionMismatch(""))
@@ -114,7 +112,7 @@ function mul!(A::StridedMatrix, Q::EigenQ)
114112
return A
115113
end
116114

117-
Base.Array(Q::EigenQ) = mul!(Q, Matrix{eltype(Q)}(I, size(Q, 1), size(Q, 1)))
115+
Base.Array(Q::EigenQ) = lmul!(Q, Matrix{eltype(Q)}(I, size(Q, 1), size(Q, 1)))
118116

119117
function _updateVectors!(c, s, j, vectors)
120118
@inbounds for i = 1:size(vectors, 1)
@@ -523,49 +521,56 @@ function symtriUpper!(AS::StridedMatrix{T},
523521
SymmetricTridiagonalFactorization('U', AS, τ, SymTridiagonal(real(diag(AS)), real(diag(AS, 1))))
524522
end
525523

526-
eigvals!(A::SymmetricTridiagonalFactorization) = eigvalsPWK!(A.diagonals, eps(eltype(A.diagonals)), false)
527-
eigvals!(A::SymTridiagonal ) = eigvalsPWK!(A, eps(eltype(A)) , false)
528-
eigvals!(A::Hermitian ) = eigvals!(symtri!(A))
524+
_eigvals!(A::SymmetricTridiagonalFactorization) = eigvalsPWK!(A.diagonals, eps(eltype(A.diagonals)), false)
525+
_eigvals!(A::SymTridiagonal ) = eigvalsPWK!(A, eps(eltype(A)) , false)
526+
_eigvals!(A::Hermitian ) = eigvals!(symtri!(A))
527+
528+
LinearAlgebra.eigvals!(A::SymmetricTridiagonalFactorization) = _eigvals!(A)
529+
LinearAlgebra.eigvals!(A::SymTridiagonal ) = _eigvals!(A)
530+
LinearAlgebra.eigvals!(A::Hermitian ) = _eigvals!(A)
529531

530-
eig!(A::SymmetricTridiagonalFactorization) = eigQL!(A.diagonals, Array(getq(A)), eps(eltype(A.diagonals)), false)
531-
eig!(A::SymTridiagonal) = eigQL!(A, Matrix{eltype(A)}(I, size(A, 1), size(A, 1)), eps(eltype(A)), false)
532-
eig!(A::Hermitian) = eig!(symtri!(A))
532+
_eigen!(A::SymmetricTridiagonalFactorization) =
533+
LinearAlgebra.Eigen(eigQL!(A.diagonals, Array(getq(A)), eps(eltype(A.diagonals)), false)...)
534+
_eigen!(A::SymTridiagonal) =
535+
LinearAlgebra.Eigen(eigQL!(A, Matrix{eltype(A)}(I, size(A, 1), size(A, 1)), eps(eltype(A)), false)...)
536+
_eigen!(A::Hermitian) = _eigen!(symtri!(A))
533537

534-
function eig2!(A::SymmetricTridiagonalFactorization, tol = eps(real(float(one(eltype(A))))), debug = false)
538+
LinearAlgebra.eigen!(A::SymmetricTridiagonalFactorization) = _eigen!(A)
539+
LinearAlgebra.eigen!(A::SymTridiagonal ) = _eigen!(A)
540+
LinearAlgebra.eigen!(A::Hermitian ) = _eigen!(A)
541+
542+
function eigen2!(A::SymmetricTridiagonalFactorization, tol = eps(real(float(one(eltype(A))))), debug = false)
535543
V = zeros(eltype(A), 2, size(A, 1))
536544
V[1] = 1
537545
V[end] = 1
538-
eigQL!(A.diagonals, mul!(V, getq(A)), tol, debug)
546+
eigQL!(A.diagonals, rmul!(V, getq(A)), tol, debug)
539547
end
540-
function eig2!(A::SymTridiagonal, tol = eps(real(float(one(eltype(A))))), debug = false)
548+
function eigen2!(A::SymTridiagonal, tol = eps(real(float(one(eltype(A))))), debug = false)
541549
V = zeros(eltype(A), 2, size(A, 1))
542550
V[1] = 1
543551
V[end] = 1
544552
eigQL!(A, V, tol, debug)
545553
end
546-
eig2!(A::Hermitian, tol = eps(float(real(one(eltype(A))))), debug = false) = eig2!(symtri!(A), tol, debug)
547-
548-
eigen!(A::SymTridiagonal) = LinearAlgebra.Eigen(eig!(A)...)
549-
eigen!(A::LinearAlgebra.Hermitian) = LinearAlgebra.Eigen(eig!(A)...)
554+
eigen2!(A::Hermitian, tol = eps(float(real(one(eltype(A))))), debug = false) = eigen2!(symtri!(A), tol, debug)
550555

551-
eig2(A::SymTridiagonal, tol = eps(float(real(one(eltype(A))))), debug = false) = eig2!(copy(A), tol, debug)
552-
eig2(A::Hermitian , tol = eps(float(real(one(eltype(A))))), debug = false) = eig2!(copy(A), tol, debug)
556+
eigen2(A::SymTridiagonal, tol = eps(float(real(one(eltype(A))))), debug = false) = eigen2!(copy(A), tol, debug)
557+
eigen2(A::Hermitian , tol = eps(float(real(one(eltype(A))))), debug = false) = eigen2!(copy(A), tol, debug)
553558

554559
# First method of each type here is identical to the method defined in
555560
# LinearAlgebra but is needed for disambiguation
556-
function eigvals(A::Hermitian{<:Real})
561+
function LinearAlgebra.eigvals(A::Hermitian{<:Real})
557562
T = typeof(sqrt(zero(eltype(A))))
558563
return eigvals!(LinearAlgebra.copy_oftype(A, T))
559564
end
560-
function eigvals(A::Hermitian)
565+
function LinearAlgebra.eigvals(A::Hermitian)
561566
T = typeof(sqrt(zero(eltype(A))))
562567
return eigvals!(LinearAlgebra.copy_oftype(A, T))
563568
end
564-
function eigen(A::Hermitian{<:Real})
569+
function LinearAlgebra.eigen(A::Hermitian{<:Real})
565570
T = typeof(sqrt(zero(eltype(A))))
566571
return eigen!(LinearAlgebra.copy_oftype(A, T))
567572
end
568-
function eigen(A::Hermitian)
573+
function LinearAlgebra.eigen(A::Hermitian)
569574
T = typeof(sqrt(zero(eltype(A))))
570575
return eigen!(LinearAlgebra.copy_oftype(A, T))
571576
end

test/eigenselfadjoint.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0
44
@testset "The selfadjoint eigen problem" begin
55
n = 50
66
@testset "SymTridiagonal" begin
7+
# Should automatically dispatch to method defined in this
8+
# package since a BigFloat methods isn't defined in
9+
# LinearAlgebra
710
T = SymTridiagonal(big.(randn(n)), big.(randn(n - 1)))
811
vals, vecs = eigen(T)
912
@testset "default" begin
@@ -12,8 +15,8 @@ Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0
1215
@test vecs'vecs Matrix(I, n, n)
1316
end
1417

15-
@testset "eig2" begin
16-
vals2, vecs2 = GenericLinearAlgebra.eig2(T)
18+
@testset "eigen2" begin
19+
vals2, vecs2 = GenericLinearAlgebra.eigen2(T)
1720
@test vals vals2
1821
@test vecs[[1,n],:] == vecs2
1922
@test vecs2*vecs2' Matrix(I, 2, 2)
@@ -36,8 +39,8 @@ Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0
3639
@test vecs'vecs Matrix(I, n, n)
3740
end
3841

39-
@testset "eig2" begin
40-
vals2, vecs2 = GenericLinearAlgebra.eig2(A)
42+
@testset "eigen2" begin
43+
vals2, vecs2 = GenericLinearAlgebra.eigen2(A)
4144
@test vals vals2
4245
@test vecs[[1,n],:] vecs2
4346
@test vecs2*vecs2' Matrix(I, 2, 2)
@@ -60,8 +63,8 @@ Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0
6063
@test vecs'vecs Matrix(I, n, n)
6164
end
6265

63-
@testset "eig2" begin
64-
vals2, vecs2 = GenericLinearAlgebra.eig2(A)
66+
@testset "eigen2" begin
67+
vals2, vecs2 = GenericLinearAlgebra.eigen2(A)
6568
@test vals vals2
6669
@test vecs[[1,n],:] vecs2
6770
@test vecs2*vecs2' Matrix(I, 2, 2)

0 commit comments

Comments
 (0)