Skip to content

Commit 91c297b

Browse files
Support for using matrices of different types in generalized eigendecomposition (#39301)
1 parent beeb6d7 commit 91c297b

File tree

4 files changed

+298
-169
lines changed

4 files changed

+298
-169
lines changed

stdlib/LinearAlgebra/src/LinearAlgebra.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ include("cholesky.jl")
374374
include("lu.jl")
375375
include("bunchkaufman.jl")
376376
include("diagonal.jl")
377+
include("symmetriceigen.jl")
377378
include("bidiag.jl")
378379
include("uniformscaling.jl")
379380
include("hessenberg.jl")

stdlib/LinearAlgebra/src/symmetric.jl

Lines changed: 0 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -676,174 +676,6 @@ end
676676
inv(A::Hermitian{<:Any,<:StridedMatrix}) = Hermitian(_inv(A), sym_uplo(A.uplo))
677677
inv(A::Symmetric{<:Any,<:StridedMatrix}) = Symmetric(_inv(A), sym_uplo(A.uplo))
678678

679-
eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing) = Eigen(sorteig!(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)..., sortby)...)
680-
681-
function eigen(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing)
682-
T = eltype(A)
683-
S = eigtype(T)
684-
eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), sortby=sortby)
685-
end
686-
687-
eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = Eigen(LAPACK.syevr!('V', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)...)
688-
689-
"""
690-
eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen
691-
692-
Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F`
693-
which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the
694-
matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.)
695-
696-
Iterating the decomposition produces the components `F.values` and `F.vectors`.
697-
698-
The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref).
699-
700-
The [`UnitRange`](@ref) `irange` specifies indices of the sorted eigenvalues to search for.
701-
702-
!!! note
703-
If `irange` is not `1:n`, where `n` is the dimension of `A`, then the returned factorization
704-
will be a *truncated* factorization.
705-
"""
706-
function eigen(A::RealHermSymComplexHerm, irange::UnitRange)
707-
T = eltype(A)
708-
S = eigtype(T)
709-
eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange)
710-
end
711-
712-
eigen!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} =
713-
Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...)
714-
715-
"""
716-
eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen
717-
718-
Computes the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F`
719-
which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the
720-
matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.)
721-
722-
Iterating the decomposition produces the components `F.values` and `F.vectors`.
723-
724-
The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref).
725-
726-
`vl` is the lower bound of the window of eigenvalues to search for, and `vu` is the upper bound.
727-
728-
!!! note
729-
If [`vl`, `vu`] does not contain all eigenvalues of `A`, then the returned factorization
730-
will be a *truncated* factorization.
731-
"""
732-
function eigen(A::RealHermSymComplexHerm, vl::Real, vh::Real)
733-
T = eltype(A)
734-
S = eigtype(T)
735-
eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh)
736-
end
737-
738-
eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) =
739-
LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1]
740-
741-
function eigvals(A::RealHermSymComplexHerm)
742-
T = eltype(A)
743-
S = eigtype(T)
744-
eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A))
745-
end
746-
747-
"""
748-
eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values
749-
750-
Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy.
751-
`irange` is a range of eigenvalue *indices* to search for - for instance, the 2nd to 8th eigenvalues.
752-
"""
753-
eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) =
754-
LAPACK.syevr!('N', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)[1]
755-
756-
"""
757-
eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values
758-
759-
Returns the eigenvalues of `A`. It is possible to calculate only a subset of the
760-
eigenvalues by specifying a [`UnitRange`](@ref) `irange` covering indices of the sorted eigenvalues,
761-
e.g. the 2nd to 8th eigenvalues.
762-
763-
# Examples
764-
```jldoctest
765-
julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])
766-
3×3 SymTridiagonal{Float64, Vector{Float64}}:
767-
1.0 2.0 ⋅
768-
2.0 2.0 3.0
769-
⋅ 3.0 1.0
770-
771-
julia> eigvals(A, 2:2)
772-
1-element Vector{Float64}:
773-
0.9999999999999996
774-
775-
julia> eigvals(A)
776-
3-element Vector{Float64}:
777-
-2.1400549446402604
778-
1.0000000000000002
779-
5.140054944640259
780-
```
781-
"""
782-
function eigvals(A::RealHermSymComplexHerm, irange::UnitRange)
783-
T = eltype(A)
784-
S = eigtype(T)
785-
eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange)
786-
end
787-
788-
"""
789-
eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values
790-
791-
Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy.
792-
`vl` is the lower bound of the interval to search for eigenvalues, and `vu` is the upper bound.
793-
"""
794-
eigvals!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} =
795-
LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1]
796-
797-
"""
798-
eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values
799-
800-
Returns the eigenvalues of `A`. It is possible to calculate only a subset of the eigenvalues
801-
by specifying a pair `vl` and `vu` for the lower and upper boundaries of the eigenvalues.
802-
803-
# Examples
804-
```jldoctest
805-
julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])
806-
3×3 SymTridiagonal{Float64, Vector{Float64}}:
807-
1.0 2.0 ⋅
808-
2.0 2.0 3.0
809-
⋅ 3.0 1.0
810-
811-
julia> eigvals(A, -1, 2)
812-
1-element Vector{Float64}:
813-
1.0000000000000009
814-
815-
julia> eigvals(A)
816-
3-element Vector{Float64}:
817-
-2.1400549446402604
818-
1.0000000000000002
819-
5.140054944640259
820-
```
821-
"""
822-
function eigvals(A::RealHermSymComplexHerm, vl::Real, vh::Real)
823-
T = eltype(A)
824-
S = eigtype(T)
825-
eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh)
826-
end
827-
828-
eigmax(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, size(A, 1):size(A, 1))[1]
829-
eigmin(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, 1:1)[1]
830-
831-
function eigen!(A::HermOrSym{T,S}, B::HermOrSym{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasReal,S<:StridedMatrix}
832-
vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))
833-
GeneralizedEigen(sorteig!(vals, vecs, sortby)...)
834-
end
835-
function eigen!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasComplex,S<:StridedMatrix}
836-
vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))
837-
GeneralizedEigen(sorteig!(vals, vecs, sortby)...)
838-
end
839-
840-
eigvals!(A::HermOrSym{T,S}, B::HermOrSym{T,S}) where {T<:BlasReal,S<:StridedMatrix} =
841-
LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1]
842-
eigvals!(A::Hermitian{T,S}, B::Hermitian{T,S}) where {T<:BlasComplex,S<:StridedMatrix} =
843-
LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1]
844-
845-
eigvecs(A::HermOrSym) = eigvecs(eigen(A))
846-
847679
function svd(A::RealHermSymComplexHerm, full::Bool=false)
848680
vals, vecs = eigen(A)
849681
I = sortperm(vals; by=abs, rev=true)

0 commit comments

Comments
 (0)