StatProfilerHTML.jl report
Generated on Thu, 21 Dec 2023 13:06:16
File source code
Line Exclusive Inclusive Code
1 # This file is a part of Julia. License is MIT: https://julialang.org/license
2
3 # preserve HermOrSym wrapper
4 eigencopy_oftype(A::Hermitian, S) = Hermitian(copy_similar(A, S), sym_uplo(A.uplo))
5 29 (11 %)
29 (11 %) samples spent in eigencopy_oftype
29 (100 %) (incl.) when called from cholcopy line 182
29 (100 %) samples spent calling copy_similar
eigencopy_oftype(A::Symmetric, S) = Symmetric(copy_similar(A, S), sym_uplo(A.uplo))
6
7 # Eigensolvers for symmetric and Hermitian matrices
8 eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing) =
9 Eigen(sorteig!(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)..., sortby)...)
10
11 function eigen(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing)
12 S = eigtype(eltype(A))
13 eigen!(eigencopy_oftype(A, S), sortby=sortby)
14 end
15
16 eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) =
17 Eigen(LAPACK.syevr!('V', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)...)
18
19 """
20 eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen
21
22 Compute the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F`
23 which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the
24 matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.)
25
26 Iterating the decomposition produces the components `F.values` and `F.vectors`.
27
28 The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref).
29
30 The [`UnitRange`](@ref) `irange` specifies indices of the sorted eigenvalues to search for.
31
32 !!! note
33 If `irange` is not `1:n`, where `n` is the dimension of `A`, then the returned factorization
34 will be a *truncated* factorization.
35 """
36 function eigen(A::RealHermSymComplexHerm, irange::UnitRange)
37 S = eigtype(eltype(A))
38 eigen!(eigencopy_oftype(A, S), irange)
39 end
40
41 eigen!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} =
42 Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...)
43
44 """
45 eigen(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen
46
47 Compute the eigenvalue decomposition of `A`, returning an [`Eigen`](@ref) factorization object `F`
48 which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the
49 matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.)
50
51 Iterating the decomposition produces the components `F.values` and `F.vectors`.
52
53 The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref).
54
55 `vl` is the lower bound of the window of eigenvalues to search for, and `vu` is the upper bound.
56
57 !!! note
58 If [`vl`, `vu`] does not contain all eigenvalues of `A`, then the returned factorization
59 will be a *truncated* factorization.
60 """
61 function eigen(A::RealHermSymComplexHerm, vl::Real, vh::Real)
62 S = eigtype(eltype(A))
63 eigen!(eigencopy_oftype(A, S), vl, vh)
64 end
65
66 function eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing)
67 vals = LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1]
68 !isnothing(sortby) && sort!(vals, by=sortby)
69 return vals
70 end
71
72 function eigvals(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing)
73 S = eigtype(eltype(A))
74 eigvals!(eigencopy_oftype(A, S), sortby=sortby)
75 end
76
77 """
78 eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values
79
80 Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy.
81 `irange` is a range of eigenvalue *indices* to search for - for instance, the 2nd to 8th eigenvalues.
82 """
83 eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) =
84 LAPACK.syevr!('N', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)[1]
85
86 """
87 eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values
88
89 Return the eigenvalues of `A`. It is possible to calculate only a subset of the
90 eigenvalues by specifying a [`UnitRange`](@ref) `irange` covering indices of the sorted eigenvalues,
91 e.g. the 2nd to 8th eigenvalues.
92
93 # Examples
94 ```jldoctest
95 julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])
96 3×3 SymTridiagonal{Float64, Vector{Float64}}:
97 1.0 2.0 ⋅
98 2.0 2.0 3.0
99 ⋅ 3.0 1.0
100
101 julia> eigvals(A, 2:2)
102 1-element Vector{Float64}:
103 0.9999999999999996
104
105 julia> eigvals(A)
106 3-element Vector{Float64}:
107 -2.1400549446402604
108 1.0000000000000002
109 5.140054944640259
110 ```
111 """
112 function eigvals(A::RealHermSymComplexHerm, irange::UnitRange)
113 S = eigtype(eltype(A))
114 eigvals!(eigencopy_oftype(A, S), irange)
115 end
116
117 """
118 eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values
119
120 Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy.
121 `vl` is the lower bound of the interval to search for eigenvalues, and `vu` is the upper bound.
122 """
123 eigvals!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} =
124 LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1]
125
126 """
127 eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values
128
129 Return the eigenvalues of `A`. It is possible to calculate only a subset of the eigenvalues
130 by specifying a pair `vl` and `vu` for the lower and upper boundaries of the eigenvalues.
131
132 # Examples
133 ```jldoctest
134 julia> A = SymTridiagonal([1.; 2.; 1.], [2.; 3.])
135 3×3 SymTridiagonal{Float64, Vector{Float64}}:
136 1.0 2.0 ⋅
137 2.0 2.0 3.0
138 ⋅ 3.0 1.0
139
140 julia> eigvals(A, -1, 2)
141 1-element Vector{Float64}:
142 1.0000000000000009
143
144 julia> eigvals(A)
145 3-element Vector{Float64}:
146 -2.1400549446402604
147 1.0000000000000002
148 5.140054944640259
149 ```
150 """
151 function eigvals(A::RealHermSymComplexHerm, vl::Real, vh::Real)
152 S = eigtype(eltype(A))
153 eigvals!(eigencopy_oftype(A, S), vl, vh)
154 end
155
156 eigmax(A::RealHermSymComplexHerm{<:Real}) = eigvals(A, size(A, 1):size(A, 1))[1]
157 eigmin(A::RealHermSymComplexHerm{<:Real}) = eigvals(A, 1:1)[1]
158
159 function eigen(A::HermOrSym{TA}, B::HermOrSym{TB}; kws...) where {TA,TB}
160 S = promote_type(eigtype(TA), TB)
161 return eigen!(eigencopy_oftype(A, S), eigencopy_oftype(B, S); kws...)
162 end
163
164 function eigen!(A::HermOrSym{T,S}, B::HermOrSym{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasReal,S<:StridedMatrix}
165 vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))
166 GeneralizedEigen(sorteig!(vals, vecs, sortby)...)
167 end
168 function eigen!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasComplex,S<:StridedMatrix}
169 vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))
170 GeneralizedEigen(sorteig!(vals, vecs, sortby)...)
171 end
172
173 function eigen(A::AbstractMatrix, C::Cholesky; sortby::Union{Function,Nothing}=nothing)
174 if ishermitian(A)
175 eigen!(eigencopy_oftype(Hermitian(A), eigtype(eltype(A))), C; sortby)
176 else
177 eigen!(copy_similar(A, eigtype(eltype(A))), C; sortby)
178 end
179 end
180 function eigen!(A::AbstractMatrix, C::Cholesky; sortby::Union{Function,Nothing}=nothing)
181 # Cholesky decomposition based eigenvalues and eigenvectors
182 vals, w = eigen!(UtiAUi!(A, C.U))
183 vecs = C.U \ w
184 GeneralizedEigen(sorteig!(vals, vecs, sortby)...)
185 end
186
187 # Perform U' \ A / U in-place, where U::Union{UpperTriangular,Diagonal}
188 UtiAUi!(A, U) = _UtiAUi!(A, U)
189 UtiAUi!(A::Symmetric, U) = Symmetric(_UtiAUi!(copytri!(parent(A), A.uplo), U), sym_uplo(A.uplo))
190 UtiAUi!(A::Hermitian, U) = Hermitian(_UtiAUi!(copytri!(parent(A), A.uplo, true), U), sym_uplo(A.uplo))
191 _UtiAUi!(A, U) = rdiv!(ldiv!(U', A), U)
192
193 function eigvals(A::HermOrSym{TA}, B::HermOrSym{TB}; kws...) where {TA,TB}
194 S = promote_type(eigtype(TA), TB)
195 return eigvals!(eigencopy_oftype(A, S), eigencopy_oftype(B, S); kws...)
196 end
197
198 function eigvals!(A::HermOrSym{T,S}, B::HermOrSym{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasReal,S<:StridedMatrix}
199 vals = LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1]
200 isnothing(sortby) || sort!(vals, by=sortby)
201 return vals
202 end
203 function eigvals!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasComplex,S<:StridedMatrix}
204 vals = LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1]
205 isnothing(sortby) || sort!(vals, by=sortby)
206 return vals
207 end
208 eigvecs(A::HermOrSym) = eigvecs(eigen(A))
209
210 function eigvals(A::AbstractMatrix, C::Cholesky; sortby::Union{Function,Nothing}=nothing)
211 if ishermitian(A)
212 eigvals!(eigencopy_oftype(Hermitian(A), eigtype(eltype(A))), C; sortby)
213 else
214 eigvals!(copy_similar(A, eigtype(eltype(A))), C; sortby)
215 end
216 end
217 function eigvals!(A::AbstractMatrix{T}, C::Cholesky{T, <:AbstractMatrix}; sortby::Union{Function,Nothing}=nothing) where {T<:Number}
218 # Cholesky decomposition based eigenvalues
219 return eigvals!(UtiAUi!(A, C.U); sortby)
220 end