Skip to content

Commit 9ca631f

Browse files
committed
Make unitary matrices in svd/eigen of Diagonal be unitless
1 parent 8d9b14f commit 9ca631f

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

src/diagonal.jl

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

934+
_ortho_eltype(T) = Base.promote_op(/, T, T)
935+
_ortho_eltype(T::Type{<:Number}) = typeof(one(T))
936+
934937
# TODO Docstrings for eigvals, eigvecs, eigen all mention permute, scale, sortby as keyword args
935938
# but not all of them below provide them. Do we need to fix that?
936939
#Eigensystem
937940
eigvals(D::Diagonal{<:Number}; permute::Bool=true, scale::Bool=true) = copy(D.diag)
938941
eigvals(D::Diagonal; permute::Bool=true, scale::Bool=true) =
939942
reduce(vcat, eigvals(x) for x in D.diag) #For block matrices, etc.
940-
function eigvecs(D::Diagonal{T}) where T<:AbstractMatrix
943+
function eigvecs(D::Diagonal{T}) where {T<:AbstractMatrix}
941944
diag_vecs = [ eigvecs(x) for x in D.diag ]
942-
matT = reduce((a,b) -> promote_type(typeof(a),typeof(b)), diag_vecs)
945+
matT = promote_type(map(typeof, diag_vecs)...)
943946
ncols_diag = [ size(x, 2) for x in D.diag ]
944947
nrows = size(D, 1)
945948
vecs = Matrix{Vector{eltype(matT)}}(undef, nrows, sum(ncols_diag))
@@ -961,7 +964,7 @@ function eigen(D::Diagonal; permute::Bool=true, scale::Bool=true, sortby::Union{
961964
if any(!isfinite, D.diag)
962965
throw(ArgumentError("matrix contains Infs or NaNs"))
963966
end
964-
Td = Base.promote_op(/, eltype(D), eltype(D))
967+
Td = _ortho_eltype(eltype(D))
965968
λ = eigvals(D)
966969
if !isnothing(sortby)
967970
p = sortperm(λ; alg=QuickSort, by=sortby)
@@ -1019,13 +1022,13 @@ function svd(D::Diagonal{T}) where {T<:Number}
10191022
s = abs.(d)
10201023
piv = sortperm(s, rev = true)
10211024
S = s[piv]
1022-
Td = typeof(oneunit(T)/oneunit(T))
1025+
Td = _ortho_eltype(T)
10231026
U = zeros(Td, size(D))
10241027
Vt = copy(U)
10251028
for i in 1:length(d)
10261029
j = piv[i]
1027-
U[j,i] = iszero(d[j]) ? oneunit(Td) : d[j] / S[i]
1028-
Vt[i,j] = oneunit(Td)
1030+
U[j,i] = iszero(d[j]) ? one(Td) : d[j] / S[i]
1031+
Vt[i,j] = one(Td)
10291032
end
10301033
return SVD(U, S, Vt)
10311034
end

test/diagonal.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,14 @@ Random.seed!(1)
478478
U, s, V = F
479479
@test map(x -> x.val, Matrix(F)) map(x -> x.val, Du)
480480
@test svdvals(Du) == s
481-
@test U isa AbstractMatrix{<:Furlong{0}}
482-
@test V isa AbstractMatrix{<:Furlong{0}}
481+
@test U isa AbstractMatrix{<:AbstractFloat}
482+
@test V isa AbstractMatrix{<:AbstractFloat}
483483
@test s isa AbstractVector{<:Furlong{1}}
484484
E = eigen(Du)
485485
vals, vecs = E
486486
@test Matrix(E) == Du
487487
@test vals isa AbstractVector{<:Furlong{1}}
488-
@test vecs isa AbstractMatrix{<:Furlong{0}}
488+
@test vecs isa AbstractMatrix{<:AbstractFloat}
489489
end
490490
end
491491

@@ -858,6 +858,10 @@ end
858858
@test eigD.values == evals
859859
@test eigD.vectors evecs
860860
@test D * eigD.vectors eigD.vectors * Diagonal(eigD.values)
861+
862+
# test concrete types
863+
D = Diagonal([I2 for _ in 1:4])
864+
@test eigen(D) isa Eigen{Vector{Float64}, Float64, Matrix{Vector{Float64}}, Vector{Float64}}
861865
end
862866

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

0 commit comments

Comments
 (0)