@@ -850,6 +850,38 @@ function LinearAlgebra.eigen(A::SymTridiagonal{<:Dual{Tg,T,N}}) where {Tg,T<:Rea
850850 Eigen(λ,Dual{Tg}.(Q, tuple.(parts...)))
851851end
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