Skip to content

Commit a4aa531

Browse files
committed
differentiate general eigen and eigvals
1 parent e8eb009 commit a4aa531

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

src/dual.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,38 @@ function LinearAlgebra.eigen(A::SymTridiagonal{<:Dual{Tg,T,N}}) where {Tg,T<:Rea
850850
Eigen(λ,Dual{Tg}.(Q, tuple.(parts...)))
851851
end
852852
853+
# General eigvals #
854+
function make_eigen_dual(val::Real, partial)
855+
Dual{tagtype(partial)}(val, partial.partials)
856+
end
857+
858+
function make_eigen_dual(val::Complex, partial::Complex)
859+
Complex(Dual{tagtype(real(partial))}(real(val), real(partial).partials),
860+
Dual{tagtype(imag(partial))}(imag(val), imag(partial).partials))
861+
end
862+
863+
function LinearAlgebra.eigen(A::StridedMatrix{<:Dual})
864+
A_values = map(d -> d.value, A)
865+
A_values_eig = eigen(A_values)
866+
UinvAU = A_values_eig.vectors \ A * A_values_eig.vectors
867+
vals_diff = diag(UinvAU)
868+
F = similar(A_values, eltype(A_values_eig.values))
869+
for i in axes(A_values, 1), j in axes(A_values, 2)
870+
if i == j
871+
F[i, j] = 0
872+
else
873+
F[i, j] = inv(A_values_eig.values[j] - A_values_eig.values[i])
874+
end
875+
end
876+
vectors_diff = A_values_eig.vectors * (F .* UinvAU)
877+
for i in eachindex(vectors_diff)
878+
vectors_diff[i] = make_eigen_dual(A_values_eig.vectors[i], vectors_diff[i])
879+
end
880+
Eigen(vals_diff, vectors_diff)
881+
end
882+
883+
LinearAlgebra.eigvals(A::StridedMatrix{<:Dual}) = eigen(A).values
884+
853885
# Functions in SpecialFunctions which return tuples #
854886
# Their derivatives are not defined in DiffRules #
855887
#---------------------------------------------------#

0 commit comments

Comments
 (0)