719719# Symmetric eigvals #
720720# -------------------#
721721
722- function LinearAlgebra. eigvals (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
722+ # To be able to reuse this default definition in the StaticArrays extension
723+ # (has to be re-defined to avoid method ambiguity issues)
724+ # we forward the call to an internal method that can be shared and reused
725+ LinearAlgebra. eigvals (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N} = _eigvals (A)
726+ function _eigvals (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
723727 λ,Q = eigen (Symmetric (value .(parent (A))))
724728 parts = ntuple (j -> diag (Q' * getindex .(partials .(A), j) * Q), N)
725729 Dual {Tg} .(λ, tuple .(parts... ))
@@ -737,8 +741,19 @@ function LinearAlgebra.eigvals(A::SymTridiagonal{<:Dual{Tg,T,N}}) where {Tg,T<:R
737741 Dual {Tg} .(λ, tuple .(parts... ))
738742end
739743
740- # A ./ (λ - λ') but with diag special cased
741- function _lyap_div! (A, λ)
744+ # A ./ (λ' .- λ) but with diag special cased
745+ # Default out-of-place method
746+ function _lyap_div!! (A:: AbstractMatrix , λ:: AbstractVector )
747+ return map (
748+ (a, b, idx) -> a / (idx[1 ] == idx[2 ] ? oneunit (b) : b),
749+ A,
750+ λ' .- λ,
751+ CartesianIndices (A),
752+ )
753+ end
754+ # For `Matrix` (and e.g. `StaticArrays.MMatrix`) we can use an in-place method
755+ _lyap_div!! (A:: Matrix , λ:: AbstractVector ) = _lyap_div! (A, λ)
756+ function _lyap_div! (A:: AbstractMatrix , λ:: AbstractVector )
742757 for (j,μ) in enumerate (λ), (k,λ) in enumerate (λ)
743758 if k ≠ j
744759 A[k,j] /= μ - λ
@@ -747,17 +762,21 @@ function _lyap_div!(A, λ)
747762 A
748763end
749764
750- function LinearAlgebra. eigen (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
765+ # To be able to reuse this default definition in the StaticArrays extension
766+ # (has to be re-defined to avoid method ambiguity issues)
767+ # we forward the call to an internal method that can be shared and reused
768+ LinearAlgebra. eigen (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N} = _eigen (A)
769+ function _eigen (A:: Symmetric{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
751770 λ = eigvals (A)
752771 _,Q = eigen (Symmetric (value .(parent (A))))
753- parts = ntuple (j -> Q* _lyap_div! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
772+ parts = ntuple (j -> Q* _lyap_div!! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
754773 Eigen (λ,Dual {Tg} .(Q, tuple .(parts... )))
755774end
756775
757776function LinearAlgebra. eigen (A:: SymTridiagonal{<:Dual{Tg,T,N}} ) where {Tg,T<: Real ,N}
758777 λ = eigvals (A)
759778 _,Q = eigen (SymTridiagonal (value .(parent (A))))
760- parts = ntuple (j -> Q* _lyap_div! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
779+ parts = ntuple (j -> Q* _lyap_div!! (Q' * getindex .(partials .(A), j) * Q - Diagonal (getindex .(partials .(λ), j)), value .(λ)), N)
761780 Eigen (λ,Dual {Tg} .(Q, tuple .(parts... )))
762781end
763782
0 commit comments