1
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2
2
3
+ # preserve HermOrSym wrapper
4
+ eigencopy_oftype (A:: Hermitian , S) = Hermitian (copy_similar (A, S), sym_uplo (A. uplo))
5
+ eigencopy_oftype (A:: Symmetric , S) = Symmetric (copy_similar (A, S), sym_uplo (A. uplo))
6
+
3
7
# Eigensolvers for symmetric and Hermitian matrices
4
8
eigen! (A:: RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix} ; sortby:: Union{Function,Nothing} = nothing ) =
5
9
Eigen (sorteig! (LAPACK. syevr! (' V' , ' A' , A. uplo, A. data, 0.0 , 0.0 , 0 , 0 , - 1.0 )... , sortby)... )
6
10
7
11
function eigen (A:: RealHermSymComplexHerm ; sortby:: Union{Function,Nothing} = nothing )
8
- T = eltype (A)
9
- S = eigtype (T)
10
- eigen! (S != T ? convert (AbstractMatrix{S}, A) : copy (A), sortby= sortby)
12
+ S = eigtype (eltype (A))
13
+ eigen! (eigencopy_oftype (A, S), sortby= sortby)
11
14
end
12
15
13
16
eigen! (A:: RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix} , irange:: UnitRange ) =
@@ -31,9 +34,8 @@ The [`UnitRange`](@ref) `irange` specifies indices of the sorted eigenvalues to
31
34
will be a *truncated* factorization.
32
35
"""
33
36
function eigen (A:: RealHermSymComplexHerm , irange:: UnitRange )
34
- T = eltype (A)
35
- S = eigtype (T)
36
- eigen! (S != T ? convert (AbstractMatrix{S}, A) : copy (A), irange)
37
+ S = eigtype (eltype (A))
38
+ eigen! (eigencopy_oftype (A, S), irange)
37
39
end
38
40
39
41
eigen! (A:: RealHermSymComplexHerm{T,<:StridedMatrix} , vl:: Real , vh:: Real ) where {T<: BlasReal } =
@@ -57,9 +59,8 @@ The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`
57
59
will be a *truncated* factorization.
58
60
"""
59
61
function eigen (A:: RealHermSymComplexHerm , vl:: Real , vh:: Real )
60
- T = eltype (A)
61
- S = eigtype (T)
62
- eigen! (S != T ? convert (AbstractMatrix{S}, A) : copy (A), vl, vh)
62
+ S = eigtype (eltype (A))
63
+ eigen! (eigencopy_oftype (A, S), vl, vh)
63
64
end
64
65
65
66
function eigvals! (A:: RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix} ; sortby:: Union{Function,Nothing} = nothing )
@@ -69,9 +70,8 @@ function eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby:
69
70
end
70
71
71
72
function eigvals (A:: RealHermSymComplexHerm ; sortby:: Union{Function,Nothing} = nothing )
72
- T = eltype (A)
73
- S = eigtype (T)
74
- eigvals! (S != T ? convert (AbstractMatrix{S}, A) : copy (A), sortby= sortby)
73
+ S = eigtype (eltype (A))
74
+ eigvals! (eigencopy_oftype (A, S), sortby= sortby)
75
75
end
76
76
77
77
"""
@@ -110,9 +110,8 @@ julia> eigvals(A)
110
110
```
111
111
"""
112
112
function eigvals (A:: RealHermSymComplexHerm , irange:: UnitRange )
113
- T = eltype (A)
114
- S = eigtype (T)
115
- eigvals! (S != T ? convert (AbstractMatrix{S}, A) : copy (A), irange)
113
+ S = eigtype (eltype (A))
114
+ eigvals! (eigencopy_oftype (A, S), irange)
116
115
end
117
116
118
117
"""
@@ -150,9 +149,8 @@ julia> eigvals(A)
150
149
```
151
150
"""
152
151
function eigvals (A:: RealHermSymComplexHerm , vl:: Real , vh:: Real )
153
- T = eltype (A)
154
- S = eigtype (T)
155
- eigvals! (S != T ? convert (AbstractMatrix{S}, A) : copy (A), vl, vh)
152
+ S = eigtype (eltype (A))
153
+ eigvals! (eigencopy_oftype (A, S), vl, vh)
156
154
end
157
155
158
156
eigmax (A:: RealHermSymComplexHerm{<:Real,<:StridedMatrix} ) = eigvals (A, size (A, 1 ): size (A, 1 ))[1 ]
@@ -166,107 +164,25 @@ function eigen!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Not
166
164
vals, vecs, _ = LAPACK. sygvd! (1 , ' V' , A. uplo, A. data, B. uplo == A. uplo ? B. data : copy (B. data' ))
167
165
GeneralizedEigen (sorteig! (vals, vecs, sortby)... )
168
166
end
169
-
170
167
function eigen! (A:: RealHermSymComplexHerm{T,S} , B:: AbstractMatrix{T} ; sortby:: Union{Function,Nothing} = nothing ) where {T<: Number ,S<: StridedMatrix }
168
+ return _choleigen! (A, B, sortby)
169
+ end
170
+ function eigen! (A:: StridedMatrix{T} , B:: Union{RealHermSymComplexHerm{T},Diagonal{T}} ; sortby:: Union{Function,Nothing} = nothing ) where {T<: Number }
171
+ return _choleigen! (A, B, sortby)
172
+ end
173
+ function _choleigen! (A, B, sortby)
171
174
U = cholesky (B). U
172
175
vals, w = eigen! (UtiAUi! (A, U))
173
176
vecs = U \ w
174
177
GeneralizedEigen (sorteig! (vals, vecs, sortby)... )
175
178
end
176
179
177
- # Perform U' \ A / U in-place.
178
- UtiAUi! (As:: Symmetric , Utr:: UpperTriangular ) = Symmetric (_UtiAsymUi! (As. uplo, parent (As), parent (Utr)), sym_uplo (As. uplo))
179
- UtiAUi! (As:: Hermitian , Utr:: UpperTriangular ) = Hermitian (_UtiAsymUi! (As. uplo, parent (As), parent (Utr)), sym_uplo (As. uplo))
180
- UtiAUi! (As:: Symmetric , Udi:: Diagonal ) = Symmetric (_UtiAsymUi_diag! (As. uplo, parent (As), Udi), sym_uplo (As. uplo))
181
- UtiAUi! (As:: Hermitian , Udi:: Diagonal ) = Hermitian (_UtiAsymUi_diag! (As. uplo, parent (As), Udi), sym_uplo (As. uplo))
182
-
183
- # U is upper triangular
184
- function _UtiAsymUi! (uplo, A, U)
185
- n = size (A, 1 )
186
- μ⁻¹ = 1 / U[1 , 1 ]
187
- αμ⁻² = A[1 , 1 ] * μ⁻¹' * μ⁻¹
188
-
189
- # Update (1, 1) element
190
- A[1 , 1 ] = αμ⁻²
191
- if n > 1
192
- Unext = view (U, 2 : n, 2 : n)
193
-
194
- if uplo === ' U'
195
- # Update submatrix
196
- for j in 2 : n, i in 2 : j
197
- A[i, j] = (
198
- A[i, j]
199
- - μ⁻¹' * U[1 , j] * A[1 , i]'
200
- - μ⁻¹ * A[1 , j] * U[1 , i]'
201
- + αμ⁻² * U[1 , j] * U[1 , i]'
202
- )
203
- end
204
-
205
- # Update vector
206
- for j in 2 : n
207
- A[1 , j] = A[1 , j] * μ⁻¹' - U[1 , j] * αμ⁻²
208
- end
209
- ldiv! (view (A' , 2 : n, 1 ), UpperTriangular (Unext)' , view (A' , 2 : n, 1 ))
210
- else
211
- # Update submatrix
212
- for j in 2 : n, i in 2 : j
213
- A[j, i] = (
214
- A[j, i]
215
- - μ⁻¹ * A[i, 1 ]' * U[1 , j]'
216
- - μ⁻¹' * U[1 , i] * A[j, 1 ]
217
- + αμ⁻² * U[1 , i] * U[1 , j]'
218
- )
219
- end
220
-
221
- # Update vector
222
- for j in 2 : n
223
- A[j, 1 ] = A[j, 1 ] * μ⁻¹ - U[1 , j]' * αμ⁻²
224
- end
225
- ldiv! (view (A, 2 : n, 1 ), UpperTriangular (Unext)' , view (A, 2 : n, 1 ))
226
- end
227
-
228
- # Recurse
229
- _UtiAsymUi! (uplo, view (A, 2 : n, 2 : n), Unext)
230
- end
231
-
232
- return A
233
- end
180
+ # Perform U' \ A / U in-place, where U::Union{UpperTriangular,Diagonal}
181
+ UtiAUi! (A:: StridedMatrix , U) = _UtiAUi! (A, U)
182
+ UtiAUi! (A:: Symmetric , U) = Symmetric (_UtiAUi! (copytri! (parent (A), A. uplo), U), sym_uplo (A. uplo))
183
+ UtiAUi! (A:: Hermitian , U) = Hermitian (_UtiAUi! (copytri! (parent (A), A. uplo, true ), U), sym_uplo (A. uplo))
234
184
235
- # U is diagonal
236
- function _UtiAsymUi_diag! (uplo, A, U)
237
- n = size (A, 1 )
238
- μ⁻¹ = 1 / U[1 , 1 ]
239
- αμ⁻² = A[1 , 1 ] * μ⁻¹' * μ⁻¹
240
-
241
- # Update (1, 1) element
242
- A[1 , 1 ] = αμ⁻²
243
- if n > 1
244
- Unext = view (U, 2 : n, 2 : n)
245
-
246
- if uplo === ' U'
247
- # No need to update any submatrix when U is diagonal
248
-
249
- # Update vector
250
- for j in 2 : n
251
- A[1 , j] = A[1 , j] * μ⁻¹'
252
- end
253
- ldiv! (view (A' , 2 : n, 1 ), Diagonal (Unext)' , view (A' , 2 : n, 1 ))
254
- else
255
- # No need to update any submatrix when U is diagonal
256
-
257
- # Update vector
258
- for j in 2 : n
259
- A[j, 1 ] = A[j, 1 ] * μ⁻¹
260
- end
261
- ldiv! (view (A, 2 : n, 1 ), Diagonal (Unext)' , view (A, 2 : n, 1 ))
262
- end
263
-
264
- # Recurse
265
- _UtiAsymUi! (uplo, view (A, 2 : n, 2 : n), Unext)
266
- end
267
-
268
- return A
269
- end
185
+ _UtiAUi! (A, U) = rdiv! (ldiv! (U' , A), U)
270
186
271
187
function eigvals! (A:: HermOrSym{T,S} , B:: HermOrSym{T,S} ; sortby:: Union{Function,Nothing} = nothing ) where {T<: BlasReal ,S<: StridedMatrix }
272
188
vals = LAPACK. sygvd! (1 , ' N' , A. uplo, A. data, B. uplo == A. uplo ? B. data : copy (B. data' ))[1 ]
0 commit comments