Skip to content

Commit ce81f74

Browse files
authored
Fix bug in symtriLower/Upper! when diagonal contains non-real elements (#39)
Define a method to disambiguiate eigen(Hermitian) Fixes #35
1 parent 06e1d95 commit ce81f74

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

src/eigenSelfAdjoint.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,13 @@ function symtriLower!(AS::StridedMatrix{T},
438438
u = Vector{T}(undef, size(AS, 1))) where T
439439
n = size(AS, 1)
440440

441+
# We ignore any non-real components of the diagonal
442+
@inbounds for i in 1:n
443+
AS[i,i] = real(AS[i,i])
444+
end
445+
441446
@inbounds for k = 1:(n - 2 + !(T<:Real))
447+
442448
τk = LinearAlgebra.reflector!(view(AS, (k + 1):n, k))
443449
τ[k] = τk
444450

@@ -492,6 +498,11 @@ function symtriUpper!(AS::StridedMatrix{T},
492498
u = Vector{T}(undef, size(AS, 1))) where T
493499
n = LinearAlgebra.checksquare(AS)
494500

501+
# We ignore any non-real components of the diagonal
502+
@inbounds for i in 1:n
503+
AS[i,i] = real(AS[i,i])
504+
end
505+
495506
@inbounds for k = 1:(n - 2 + !(T<:Real))
496507
# This is a bit convoluted method to get the conjugated vector but conjugation is required for correctness of arrays of quaternions. Eventually, it should be sufficient to write vec(x') but it currently (July 10, 2018) hits a bug in LinearAlgebra
497508
τk = LinearAlgebra.reflector!(vec(transpose(view(AS, k, (k + 1):n)')))
@@ -618,6 +629,10 @@ function LinearAlgebra.eigvals(A::Hermitian{<:Real})
618629
T = typeof(sqrt(zero(eltype(A))))
619630
return eigvals!(LinearAlgebra.copy_oftype(A, T))
620631
end
632+
function LinearAlgebra.eigvals(A::Hermitian{<:Complex})
633+
T = typeof(sqrt(zero(eltype(A))))
634+
return eigvals!(LinearAlgebra.copy_oftype(A, T))
635+
end
621636
function LinearAlgebra.eigvals(A::Hermitian)
622637
T = typeof(sqrt(zero(eltype(A))))
623638
return eigvals!(LinearAlgebra.copy_oftype(A, T))
@@ -626,6 +641,10 @@ function LinearAlgebra.eigen(A::Hermitian{<:Real})
626641
T = typeof(sqrt(zero(eltype(A))))
627642
return eigen!(LinearAlgebra.copy_oftype(A, T))
628643
end
644+
function LinearAlgebra.eigen(A::Hermitian{<:Complex})
645+
T = typeof(sqrt(zero(eltype(A))))
646+
return eigen!(LinearAlgebra.copy_oftype(A, T))
647+
end
629648
function LinearAlgebra.eigen(A::Hermitian)
630649
T = typeof(sqrt(zero(eltype(A))))
631650
return eigen!(LinearAlgebra.copy_oftype(A, T))

test/eigenselfadjoint.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ Base.isreal(q::Quaternion) = q.v1 == q.v2 == q.v3 == 0
7171
end
7272
end
7373

74+
@testset "big Hermitian{<:Complex}" begin
75+
# This one used to cause an ambiguity error. See #35
76+
A = complex.(randn(4,4), randn(4,4))
77+
@test Float64.(eigen(Hermitian(big.(A))).values) eigen(Hermitian(copy(A))).values
78+
@test Float64.(eigvals(Hermitian(big.(A)))) eigvals(Hermitian(copy(A)))
79+
end
80+
7481
@testset "generic Givens" begin
7582
x, y = randn(2)
7683
c, s, r = invoke(LinearAlgebra.givensAlgorithm, Tuple{Real,Real}, x, y)

0 commit comments

Comments
 (0)