Skip to content

Commit c0d7c5e

Browse files
CarpeNecopinumc42f
authored andcommitted
Handle non-hermitian matrices in eigen
1 parent 57eab2f commit c0d7c5e

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

src/eigen.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,14 @@ end
124124
end
125125

126126

127-
@inline function _eig(s::Size, A::StaticMatrix, permute, scale)
128-
# Only cover the hermitian branch, for now at least
129-
# This also solves some type-stability issues that arise in Base
127+
@inline function _eig(s::Size, A::T, permute, scale) where {T <: StaticMatrix}
128+
# For the non-hermitian branch, fall back to LinearAlgebra
130129
if ishermitian(A)
131-
return _eig(s, Hermitian(A), permute, scale)
130+
eivals, eivecs = _eig(s, Hermitian(A), permute, scale)
131+
return eivals, eivecs
132132
else
133-
error("Only hermitian matrices are diagonalizable by *StaticArrays*. Non-Hermitian matrices should be converted to `Array` first.")
133+
eivals, eivecs = eigen(Array(A); permute = permute, scale = scale)
134+
return SVector{s[1]}(eivals), SMatrix{s[1],s[2]}(eivecs)
134135
end
135136
end
136137

test/eigen.jl

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,6 @@ using StaticArrays, Test, LinearAlgebra
232232
@test vals::SVector sort(m_d)
233233
@test eigvals(m) sort(m_d)
234234
@test eigvals(Hermitian(m)) sort(m_d)
235-
236-
# not Hermitian
237-
@test_throws Exception eigen(@SMatrix randn(4,4))
238235
end
239236

240237
@testset "complex" begin
@@ -248,4 +245,45 @@ using StaticArrays, Test, LinearAlgebra
248245
@test V'*A*V diagm(Val(0) => D)
249246
end
250247
end
248+
249+
@testset "hermitian type stability" begin
250+
for n=1:4
251+
m = @SMatrix randn(n,n)
252+
m += m'
253+
254+
@inferred eigen(Hermitian(m))
255+
@inferred eigen(Symmetric(m))
256+
257+
mc = @SMatrix randn(ComplexF64, n, n)
258+
@inferred eigen(Hermitian(mc + mc'))
259+
end
260+
end
261+
262+
@testset "non-hermitian 2d" begin
263+
for n=1:5
264+
angle = 2π * rand()
265+
rot = @SMatrix [cos(angle) -sin(angle); sin(angle) cos(angle)]
266+
267+
vals, vecs = eigen(rot)
268+
269+
@test norm(vals[1]) 1.0
270+
@test norm(vals[2]) 1.0
271+
272+
@test vecs[:,1] conj.(vecs[:,2])
273+
end
274+
end
275+
276+
@testset "non-hermitian 3d" begin
277+
for n=1:5
278+
angle = 2π * rand()
279+
rot = @SMatrix [cos(angle) 0.0 -sin(angle); 0.0 1.0 0.0; sin(angle) 0.0 cos(angle)]
280+
281+
vals, vecs = eigen(rot)
282+
283+
@test norm(vals[1]) 1.0
284+
@test norm(vals[2]) 1.0
285+
286+
@test vecs[:,1] conj.(vecs[:,2])
287+
end
288+
end
251289
end

0 commit comments

Comments
 (0)