702702# Symmetric eigvals #
703703# -------------------#
704704
705- function LinearAlgebra. eigvals (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
705+ # To be able to reuse this default definition in the StaticArrays extension
706+ # (has to be re-defined to avoid method ambiguity issues)
707+ # we forward the call to an internal method that can be shared and reused
708+ LinearAlgebra. eigvals (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N} = _eigvals (A)
709+ function _eigvals (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
706710 λ,Q = eigen (Symmetric (value .(parent (A))))
707711 parts = ntuple (j -> diag (Q' * getindex .(partials .(A), j) * Q), N)
708712 Dual {Tg} .(λ, tuple .(parts... ))
@@ -720,8 +724,19 @@ function LinearAlgebra.eigvals(A::SymTridiagonal{<:Dual{Tg,T,N}}) where {Tg,T<:R
720724 Dual {Tg} .(λ, tuple .(parts... ))
721725end
722726
723- # A ./ (λ - λ') but with diag special cased
724- function _lyap_div! (A, λ)
727+ # A ./ (λ' .- λ) but with diag special cased
728+ # Default out-of-place method
729+ function _lyap_div!! (A:: AbstractMatrix , λ:: AbstractVector )
730+ return map (
731+ (a, b, idx) -> a / (idx[1 ] == idx[2 ] ? oneunit (b) : b),
732+ A,
733+ λ' .- λ,
734+ CartesianIndices (A),
735+ )
736+ end
737+ # For `Matrix` (and e.g. `StaticArrays.MMatrix`) we can use an in-place method
738+ _lyap_div!! (A:: Matrix , λ:: AbstractVector ) = _lyap_div! (A, λ)
739+ function _lyap_div! (A:: AbstractMatrix , λ:: AbstractVector )
725740 for (j,μ) in enumerate (λ), (k,λ) in enumerate (λ)
726741 if k ≠ j
727742 A[k,j] /= μ - λ
@@ -730,17 +745,21 @@ function _lyap_div!(A, λ)
730745 A
731746end
732747
733- function LinearAlgebra. eigen (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
748+ # To be able to reuse this default definition in the StaticArrays extension
749+ # (has to be re-defined to avoid method ambiguity issues)
750+ # we forward the call to an internal method that can be shared and reused
751+ LinearAlgebra. eigen (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N} = _eigen (A)
752+ function _eigen (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
734753 λ = eigvals (A)
735754 _,Q = eigen (Symmetric (value .(parent (A))))
736- parts = ntuple (j -> Q* _lyap_div! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
755+ parts = ntuple (j -> Q* _lyap_div!! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
737756 Eigen (λ,Dual {Tg} .(Q, tuple .(parts... )))
738757end
739758
740759function LinearAlgebra. eigen (A:: SymTridiagonal{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
741760 λ = eigvals (A)
742761 _,Q = eigen (SymTridiagonal (value .(parent (A))))
743- parts = ntuple (j -> Q* _lyap_div! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
762+ parts = ntuple (j -> Q* _lyap_div!! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
744763 Eigen (λ,Dual {Tg} .(Q, tuple .(parts... )))
745764end
746765
0 commit comments