@@ -70,75 +70,81 @@ module EigenGeneral
70
70
R:: Rotation
71
71
end
72
72
73
- function schurfact! {T<:Real} (H:: HessenbergFactorization{T} ; tol = eps (T), debug = false )
73
+ function wilkinson (Hmm, t, d)
74
+ λ1 = (t + sqrt (t* t - 4 d))/ 2
75
+ λ2 = (t - sqrt (t* t - 4 d))/ 2
76
+ return ifelse (abs (Hmm - λ1) < abs (Hmm - λ2), λ1, λ2)
77
+ end
78
+
79
+
80
+ function schurfact! {T<:Real} (H:: HessenbergFactorization{T} ; tol = eps (T), debug = false , shiftmethod = :Wilkinson , maxiter = 100 * size (H, 1 ))
74
81
n = size (H, 1 )
75
82
istart = 1
76
83
iend = n
77
84
HH = H. data
78
85
τ = Rotation (Givens{T}[])
79
86
87
+ # iteration count
88
+ i = 0
89
+
80
90
@inbounds while true
91
+ i += 1
92
+ if i > maxiter
93
+ throw (ArgumentError (" iteration limit $maxiter reached" ))
94
+ end
95
+
81
96
# Determine if the matrix splits. Find lowest positioned subdiagonal "zero"
82
97
for istart = iend - 1 : - 1 : 1
83
- # debug && @printf("istart: %6d, iend %6d\n", istart, iend)
84
- # istart == minstart && break
85
98
if abs (HH[istart + 1 , istart]) < tol* (abs (HH[istart, istart]) + abs (HH[istart + 1 , istart + 1 ]))
86
99
istart += 1
87
- debug && @printf (" Top deflation ! Subdiagonal element is: %10.3e and istart now %6d\n " , HH[istart, istart - 1 ], istart)
100
+ debug && @printf (" Split ! Subdiagonal element is: %10.3e and istart now %6d\n " , HH[istart, istart - 1 ], istart)
88
101
break
89
102
elseif istart > 1 && abs (HH[istart, istart - 1 ]) < tol* (abs (HH[istart - 1 , istart - 1 ]) + abs (HH[istart, istart]))
90
- debug && @printf (" Top deflation ! Next subdiagonal element is: %10.3e and istart now %6d\n " , HH[istart, istart - 1 ], istart)
103
+ debug && @printf (" Split ! Next subdiagonal element is: %10.3e and istart now %6d\n " , HH[istart, istart - 1 ], istart)
91
104
break
92
105
end
93
106
end
94
107
95
108
# if block size is one we deflate
96
109
if istart >= iend
110
+ debug && @printf (" Bottom deflation! Block size is one. New iend is %6d\n " , iend - 1 )
97
111
iend -= 1
98
112
99
113
# and the same for a 2x2 block
100
114
elseif istart + 1 == iend
115
+ debug && @printf (" Bottom deflation! Block size is two. New iend is %6d\n " , iend - 2 )
101
116
iend -= 2
102
117
103
- # if we don't deflate we'll run either a single or double shift bulge chase
118
+ # run a QR iteration
119
+ # shift method is specified with shiftmethod kw argument
104
120
else
105
121
Hmm = HH[iend, iend]
106
122
Hm1m1 = HH[iend - 1 , iend - 1 ]
107
123
d = Hm1m1* Hmm - HH[iend, iend - 1 ]* HH[iend - 1 , iend]
108
124
t = Hm1m1 + Hmm
125
+ t = iszero (t) ? eps (one (t)) : t # introduce a small pertubation for zero shifts
109
126
debug && @printf (" block start is: %6d, block end is: %6d, d: %10.3e, t: %10.3e\n " , istart, iend, d, t)
110
127
111
- # For small (sub) problems use Raleigh quotion shift and single shift
112
- if iend <= istart + 2
113
- σ = HH[iend, iend]
128
+ if shiftmethod == :Wilkinson
129
+ debug && @printf (" Double shift with Wilkinson shift! Subdiagonal is: %10.3e, last subdiagonal is: %10.3e\n " , HH[iend, iend - 1 ], HH[iend - 1 , iend - 2 ])
114
130
115
131
# Run a bulge chase
116
- singleShiftQR! (HH, τ, σ, istart, iend)
117
-
118
- # If the eigenvales of the 2x2 block are real use single shift
119
- elseif t* t > 4 d
120
- debug && @printf (" Single shift! subdiagonal is: %10.3e\n " , HH[iend, iend - 1 ])
121
-
122
- # Calculate the Wilkinson shift
123
- λ1 = (t + sqrt (t* t - 4 d))/ 2
124
- λ2 = (t - sqrt (t* t - 4 d))/ 2
125
- σ = abs (Hmm - λ1) < abs (Hmm - λ2) ? λ1 : λ2
132
+ doubleShiftQR! (HH, τ, t, d, istart, iend)
133
+ elseif shiftmethod == :Rayleigh
134
+ debug && @printf (" Single shift with Rayleigh shift! Subdiagonal is: %10.3e\n " , HH[iend, iend - 1 ])
126
135
127
136
# Run a bulge chase
128
- singleShiftQR! (HH, τ, σ, istart, iend)
129
-
130
- # else use double shift
137
+ singleShiftQR! (HH, τ, Hmm, istart, iend)
131
138
else
132
- debug && @printf (" Double shift! subdiagonal is: %10.3e, last subdiagonal is: %10.3e\n " , HH[iend, iend - 1 ], HH[iend - 1 , iend - 2 ])
133
- doubleShiftQR! (HH, τ, t, d, istart, iend)
139
+ throw (ArgumentError (" only support supported shift methods are :Wilkinson (default) and :Rayleigh. You supplied $shiftmethod " ))
134
140
end
135
141
end
136
142
if iend <= 2 break end
137
143
end
138
144
139
145
return Schur {T,typeof(HH)} (HH, τ)
140
146
end
141
- schurfact! (A:: StridedMatrix ; tol = eps ( float ( real ( eltype (A)))), debug = false ) = schurfact! (hessfact! (A), tol = tol, debug = debug )
147
+ schurfact! (A:: StridedMatrix ; kwargs ... ) = schurfact! (hessfact! (A); kwargs ... )
142
148
143
149
function singleShiftQR! (HH:: StridedMatrix , τ:: Rotation , shift:: Number , istart:: Integer , iend:: Integer )
144
150
m = size (HH, 1 )
@@ -172,16 +178,21 @@ module EigenGeneral
172
178
H21 = HH[istart + 1 , istart]
173
179
Htmp11 = HH[istart + 2 , istart]
174
180
HH[istart + 2 , istart] = 0
175
- Htmp21 = HH[istart + 3 , istart]
176
- HH[istart + 3 , istart] = 0
177
- Htmp22 = HH[istart + 3 , istart + 1 ]
178
- HH[istart + 3 , istart + 1 ] = 0
181
+ if istart + 3 <= m
182
+ Htmp21 = HH[istart + 3 , istart]
183
+ HH[istart + 3 , istart] = 0
184
+ Htmp22 = HH[istart + 3 , istart + 1 ]
185
+ HH[istart + 3 , istart + 1 ] = 0
186
+ else
187
+ # values doen't matter in this case but variables should be initialized
188
+ Htmp21 = Htmp22 = Htmp11
189
+ end
179
190
G1, r = givens (H11* H11 + HH[istart, istart + 1 ]* H21 - shiftTrace* H11 + shiftDeterminant, H21* (H11 + HH[istart + 1 , istart + 1 ] - shiftTrace), istart, istart + 1 )
180
191
G2, _ = givens (r, H21* HH[istart + 2 , istart + 1 ], istart, istart + 2 )
181
192
vHH = view (HH, :, istart: m)
182
193
A_mul_B! (G1, vHH)
183
194
A_mul_B! (G2, vHH)
184
- vHH = view (HH, 1 : istart + 3 , :)
195
+ vHH = view (HH, 1 : min ( istart + 3 , m) , :)
185
196
A_mul_Bc! (vHH, G1)
186
197
A_mul_Bc! (vHH, G2)
187
198
A_mul_B! (G1, τ)
@@ -209,9 +220,9 @@ module EigenGeneral
209
220
return HH
210
221
end
211
222
212
- eigvals! (A:: StridedMatrix ; tol = eps ( one (A[ 1 ])), debug = false ) = eigvals! (schurfact! (A, tol = tol, debug = debug ))
213
- eigvals! (H:: HessenbergMatrix ; tol = eps ( one (A[ 1 ])), debug = false ) = eigvals! (schurfact! (H, tol = tol, debug = debug ))
214
- eigvals! (H:: HessenbergFactorization ; tol = eps ( one (A[ 1 ])), debug = false ) = eigvals! (schurfact! (H, tol = tol, debug = debug ))
223
+ eigvals! (A:: StridedMatrix ; kwargs ... ) = eigvals! (schurfact! (A; kwargs ... ))
224
+ eigvals! (H:: HessenbergMatrix ; kwargs ... ) = eigvals! (schurfact! (H, kwargs ... ))
225
+ eigvals! (H:: HessenbergFactorization ; kwargs ... ) = eigvals! (schurfact! (H, kwargs ... ))
215
226
216
227
function eigvals! {T} (S:: Schur{T} ; tol = eps (T))
217
228
HH = S. data
0 commit comments