Skip to content

Commit ff5648a

Browse files
authored
Make unitary matrices in svd/eigen of Diagonal be unitless (#1155)
1 parent e096a03 commit ff5648a

File tree

3 files changed

+16
-9
lines changed

3 files changed

+16
-9
lines changed

src/diagonal.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -911,15 +911,18 @@ function pinv(D::Diagonal{T}, tol::Real) where T
911911
Diagonal(Di)
912912
end
913913

914+
_ortho_eltype(T) = Base.promote_op(/, T, T)
915+
_ortho_eltype(T::Type{<:Number}) = typeof(one(T)/one(T))
916+
914917
# TODO Docstrings for eigvals, eigvecs, eigen all mention permute, scale, sortby as keyword args
915918
# but not all of them below provide them. Do we need to fix that?
916919
#Eigensystem
917920
eigvals(D::Diagonal{<:Number}; permute::Bool=true, scale::Bool=true) = copy(D.diag)
918921
eigvals(D::Diagonal; permute::Bool=true, scale::Bool=true) =
919922
reduce(vcat, eigvals(x) for x in D.diag) #For block matrices, etc.
920-
function eigvecs(D::Diagonal{T}) where T<:AbstractMatrix
923+
function eigvecs(D::Diagonal{T}) where {T<:AbstractMatrix}
921924
diag_vecs = [ eigvecs(x) for x in D.diag ]
922-
matT = reduce((a,b) -> promote_type(typeof(a),typeof(b)), diag_vecs)
925+
matT = promote_type(map(typeof, diag_vecs)...)
923926
ncols_diag = [ size(x, 2) for x in D.diag ]
924927
nrows = size(D, 1)
925928
vecs = Matrix{Vector{eltype(matT)}}(undef, nrows, sum(ncols_diag))
@@ -941,7 +944,7 @@ function eigen(D::Diagonal; permute::Bool=true, scale::Bool=true, sortby::Union{
941944
if any(!isfinite, D.diag)
942945
throw(ArgumentError("matrix contains Infs or NaNs"))
943946
end
944-
Td = Base.promote_op(/, eltype(D), eltype(D))
947+
Td = _ortho_eltype(eltype(D))
945948
λ = eigvals(D)
946949
if !isnothing(sortby)
947950
p = sortperm(λ; alg=QuickSort, by=sortby)
@@ -999,13 +1002,13 @@ function svd(D::Diagonal{T}) where {T<:Number}
9991002
s = abs.(d)
10001003
piv = sortperm(s, rev = true)
10011004
S = s[piv]
1002-
Td = typeof(oneunit(T)/oneunit(T))
1005+
Td = _ortho_eltype(T)
10031006
U = zeros(Td, size(D))
10041007
Vt = copy(U)
10051008
for i in 1:length(d)
10061009
j = piv[i]
1007-
U[j,i] = iszero(d[j]) ? oneunit(Td) : d[j] / S[i]
1008-
Vt[i,j] = oneunit(Td)
1010+
U[j,i] = iszero(d[j]) ? one(Td) : d[j] / S[i]
1011+
Vt[i,j] = one(Td)
10091012
end
10101013
return SVD(U, S, Vt)
10111014
end

test/diagonal.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,10 @@ end
839839
@test eigD.values == evals
840840
@test eigD.vectors evecs
841841
@test D * eigD.vectors eigD.vectors * Diagonal(eigD.values)
842+
843+
# test concrete types
844+
D = Diagonal([I2 for _ in 1:4])
845+
@test eigen(D) isa Eigen{Vector{Float64}, Float64, Matrix{Vector{Float64}}, Vector{Float64}}
842846
end
843847

844848
@testset "linear solve for block diagonal matrices" begin

test/unitful.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ end
7979
U, s, V = F
8080
@test map(getval, Matrix(F)) map(getval, Du)
8181
@test svdvals(Du) == s
82-
@test U isa AbstractMatrix{<:Furlong{0}}
83-
@test V isa AbstractMatrix{<:Furlong{0}}
82+
@test U isa AbstractMatrix{<:Union{Real,Complex}}
83+
@test V isa AbstractMatrix{<:Union{Real,Complex}}
8484
@test s isa AbstractVector{<:Furlong{1}}
8585
E = eigen(Du)
8686
vals, vecs = E
8787
@test Matrix(E) == Du
8888
@test vals isa AbstractVector{<:Furlong{1}}
89-
@test vecs isa AbstractMatrix{<:Furlong{0}}
89+
@test vecs isa AbstractMatrix{<:Union{Real,Complex}}
9090
end
9191
end
9292

0 commit comments

Comments
 (0)