@@ -80,7 +80,14 @@ function wilkinson(Hmm, t, d)
8080end
8181
8282# We currently absorb extra unsupported keywords in kwargs. These could e.g. be scale and permute. Do we want to check that these are false?
83- function _schur! (H:: HessenbergFactorization{T} ; tol = eps (real (T)), debug = false , shiftmethod = :Francis , maxiter = 100 * size (H, 1 ), kwargs... ) where T
83+ function _schur! (
84+ H:: HessenbergFactorization{T} ;
85+ tol = eps (real (T)),
86+ debug = false ,
87+ shiftmethod = :Francis ,
88+ maxiter = 100 * size (H, 1 ),
89+ kwargs... ) where T
90+
8491 n = size (H, 1 )
8592 istart = 1
8693 iend = n
@@ -99,14 +106,25 @@ function _schur!(H::HessenbergFactorization{T}; tol = eps(real(T)), debug = fals
99106 # Determine if the matrix splits. Find lowest positioned subdiagonal "zero"
100107 for _istart in iend - 1 : - 1 : 1
101108 if abs (HH[_istart + 1 , _istart]) <= tol* (abs (HH[_istart, _istart]) + abs (HH[_istart + 1 , _istart + 1 ]))
102- istart = _istart + 1
109+ # Check if subdiagonal element H[i+1,i] is "zero" such that we can split the matrix
110+
111+ # Set istart to the beginning of the second block
112+ istart = _istart + 1
113+
103114 debug && @printf (" Split! Subdiagonal element is: %10.3e and istart now %6d\n " , HH[istart, istart - 1 ], istart)
115+
116+ # Set the subdiagonal element to zero to signal that a split has taken place
117+ HH[istart, istart - 1 ] = 0
104118 break
105- elseif _istart > 1 && abs (HH[_istart, _istart - 1 ]) <= tol* (abs (HH[_istart - 1 , _istart - 1 ]) + abs (HH[_istart, _istart]))
106- debug && @printf (" Split! Next subdiagonal element is: %10.3e and istart now %6d\n " , HH[_istart, _istart - 1 ], _istart)
107- istart = _istart
108- break
119+ # elseif _istart > 1 && abs(HH[_istart, _istart - 1]) <= tol*(abs(HH[_istart - 1, _istart - 1]) + abs(HH[_istart, _istart]))
120+
121+ # debug && @printf("Split! Next subdiagonal element is: %10.3e and istart now %6d\n", HH[_istart, _istart - 1], _istart)
122+ # HH[_istart, _istart - 1]=0
123+ # istart = _istart
124+ # break
109125 end
126+
127+ # If no splits have taken place then we start from the top
110128 istart = 1
111129 end
112130
@@ -251,54 +269,63 @@ _eigvals!(H::HessenbergFactorization; kwargs...) = _eigvals!(_schur!(H; kwargs..
251269
252270# Overload methods from LinearAlgebra to make them work generically
253271if VERSION > v " 1.2.0-DEV.0"
254- function LinearAlgebra. eigvals! (A:: StridedMatrix ;
255- sortby:: Union{Function,Nothing} = LinearAlgebra. eigsortby,
256- kwargs... )
257- if ishermitian (A)
258- return LinearAlgebra. sorteig! (eigvals! (Hermitian (A)), sortby)
259- end
260- LinearAlgebra. sorteig! (_eigvals! (A; kwargs... ), sortby)
272+ function LinearAlgebra. eigvals! (
273+ A:: StridedMatrix ;
274+ sortby:: Union{Function,Nothing} = LinearAlgebra. eigsortby,
275+ kwargs... )
276+
277+ if ishermitian (A)
278+ return LinearAlgebra. sorteig! (eigvals! (Hermitian (A)), sortby)
279+ end
280+ LinearAlgebra. sorteig! (_eigvals! (A; kwargs... ), sortby)
261281 end
262282
263- LinearAlgebra. eigvals! (H:: HessenbergMatrix ;
264- sortby:: Union{Function,Nothing} = LinearAlgebra. eigsortby,
265- kwargs... ) = LinearAlgebra. sorteig! (_eigvals! (H; kwargs... ), sortby)
283+ LinearAlgebra. eigvals! (
284+ H:: HessenbergMatrix ;
285+ sortby:: Union{Function,Nothing} = LinearAlgebra. eigsortby,
286+ kwargs... ) = LinearAlgebra. sorteig! (_eigvals! (H; kwargs... ), sortby)
266287
267- LinearAlgebra. eigvals! (H:: HessenbergFactorization ;
268- sortby:: Union{Function,Nothing} = LinearAlgebra. eigsortby,
269- kwargs... ) = LinearAlgebra. sorteig! (_eigvals! (H; kwargs... ), sortby)
288+ LinearAlgebra. eigvals! (
289+ H:: HessenbergFactorization ;
290+ sortby:: Union{Function,Nothing} = LinearAlgebra. eigsortby,
291+ kwargs... ) = LinearAlgebra. sorteig! (_eigvals! (H; kwargs... ), sortby)
270292else
271-
272293 function LinearAlgebra. eigvals! (A:: StridedMatrix ; kwargs... )
273294 if ishermitian (A)
274295 return eigvals! (Hermitian (A))
296+ else
297+ return _eigvals! (A; kwargs... )
275298 end
276- _eigvals! (A; kwargs... )
277299 end
278300
279301 LinearAlgebra. eigvals! (H:: HessenbergMatrix ; kwargs... ) = _eigvals! (H; kwargs... )
280302
281303 LinearAlgebra. eigvals! (H:: HessenbergFactorization ; kwargs... ) = _eigvals! (H; kwargs... )
282304end
283305
284-
306+ # To compute the eigenvalue of the pseudo triangular Schur matrix we just return
307+ # the values of the 1x1 diagonal blocks and compute the eigenvalues of the 2x2
308+ # blocks on the fly. We can check for exact zeros in the subdiagonal because
309+ # the QR algorithm sets the elements to zero when a split happens
285310function _eigvals! (S:: Schur{T} ; tol = eps (real (T))) where T
286311 HH = S. data
287312 n = size (HH, 1 )
288313 vals = Vector {complex(T)} (undef, n)
289314 i = 1
290315 while i < n
291316 Hii = HH[i, i]
292- Hi1i1 = HH[i + 1 , i + 1 ]
293- if abs (HH[i + 1 , i]) <= tol * ( abs (Hi1i1) + abs (Hii))
317+ if iszero ( HH[i + 1 , i])
318+ # 1x1 block
294319 vals[i] = Hii
295320 i += 1
296321 else
322+ # 2x2 block
323+ Hi1i1 = HH[i + 1 , i + 1 ]
297324 d = Hii* Hi1i1 - HH[i, i + 1 ]* HH[i + 1 , i]
298325 t = Hii + Hi1i1
299326 x = 0.5 * t
300327 y = sqrt (complex (x* x - d))
301- vals[i] = x + y
328+ vals[i ] = x + y
302329 vals[i + 1 ] = x - y
303330 i += 2
304331 end
0 commit comments