You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# The generated Jacobi operators are symmetric tridiagonal, so we store their data in two cached bands which are generated in tandem but can be accessed separately.
@@ -143,141 +74,14 @@ The resulting polynomials are orthonormal on the same domain as `P`. The supplie
143
74
144
75
The underlying QR approach allows two methods, one which uses the Q matrix and one which uses the R matrix. To change between methods, an optional argument :Q or :R may be supplied. The default is to use the Q method.
functionqr_jacobimatrix(sqrtW::AbstractMatrix{T}, Q, method =:Q) where T
154
-
isnormalized(Q) ||error("Polynomials must be orthonormal")
155
-
F =qr(sqrtW)
156
-
QRJD =QRJacobiData{method,T}(F,Q)
157
-
SymTridiagonal(view(QRJD,:,1),view(QRJD,:,2))
82
+
returnqr_jacobimatrix(sqrtW, jacobimatrix(Q))
158
83
end
159
-
160
-
# The generated Jacobi operators are symmetric tridiagonal, so we store their data in two cached bands which are generated in tandem but can be accessed separately.
ev[1] = M[1,2]*sign(F.R[1,1]*F.R[2,2]) # includes possible correction for sign (only needed in off-diagonal case), since the QR decomposition does not guarantee positive diagonal on R
193
-
K =Matrix(X[2:b+1,2:b+1])
194
-
K[1:end-1,1:end-1] .=view(M,2:b,2:b)
195
-
returnQRJacobiData{:Q,T}(dv, ev, F, K, P, 1)
196
-
end
197
-
functionQRJacobiData{:R,T}(F, P) where T
198
-
U = F.R
199
-
U =ApplyArray(*,Diagonal(sign.(view(U,band(0)))),U) # QR decomposition does not force positive diagonals on R by default
200
-
X =jacobimatrix(P)
201
-
UX =view(U,1:3,1:3)*X[1:3,1:3]
202
-
# compute a length 2 vector on first go and circumvent BigFloat issue
203
-
dv =zeros(T,2)
204
-
ev =zeros(T,2)
205
-
dv[1] = UX[1,1]/U[1,1] # this is dot(view(UX,1,1), U[1,1] \ [one(T)])
206
-
dv[2] =-U[1,2]*UX[2,1]/(U[1,1]*U[2,2])+UX[2,2]/U[2,2] # this is dot(view(UX,2,1:2), U[1:2,1:2] \ [zero(T); one(T)])
207
-
ev[1] =-UX[1,1]*U[1,2]/(U[1,1]*U[2,2])+UX[1,2]/U[2,2] # this is dot(view(UX,1,1:2), U[1:2,1:2] \ [zero(T); one(T)])
208
-
ev[2] = UX[2,1]/U[3,3]*(-U[1,3]/U[1,1]+U[1,2]*U[2,3]/(U[1,1]*U[2,2]))+UX[2,2]/U[3,3]*(-U[2,3]/U[2,2])+UX[2,3]/U[3,3] # this is dot(view(UX,2,1:3), U[1:3,1:3] \ [zeros(T,2); one(T)])
209
-
returnQRJacobiData{:R,T}(dv, ev, U, X, P, 2)
210
-
end
211
-
212
-
213
-
size(::QRJacobiData) = (ℵ₀,2) # Stored as two infinite cached bands
ev[n] = K[1,2]*D[n] # contains sign correction from QR not forcing positive diagonals
265
-
M .=view(X,n+1:n+b+3,n+1:n+b+3)
266
-
M[1:end-1,1:end-1] .=view(K,2:b+3,2:b+3)
267
-
K .= M
268
-
end
269
-
end
270
-
271
-
function_fillqrbanddata!(J::QRJacobiData{:R,T}, inds::UnitRange{Int}) where T
272
-
# pre-fill U and UX to prevent expensive step-by-step filling in of cached U and UX in the loop
273
-
m = inds[end]+1
274
-
resizedata!(J.U,m,m)
275
-
dv, ev, X, U = J.dv, J.ev, J.UX, J.U
276
-
277
-
UX =view(U,1:m,1:m)*X[1:m,1:m]
278
-
279
-
@inboundsfor k in inds
280
-
dv[k] =-U[k-1,k]*UX[k,k-1]/(U[k-1,k-1]*U[k,k])+UX[k,k]./U[k,k] # this is dot(view(UX,k,k-1:k), U[k-1:k,k-1:k] \ ek)
281
-
ev[k] = UX[k,k-1]/U[k+1,k+1]*(-U[k-1,k+1]/U[k-1,k-1]+U[k-1,k]*U[k,k+1]/(U[k-1,k-1]*U[k,k]))+UX[k,k]/U[k+1,k+1]*(-U[k,k+1]/U[k,k])+UX[k,k+1]/U[k+1,k+1] # this is dot(view(UX,k,k-1:k+1), U[k-1:k+1,k-1:k+1] \ ek)
282
-
end
84
+
functionqr_jacobimatrix(sqrtW::AbstractMatrix{T}, X::AbstractMatrix) where T
0 commit comments