@@ -101,124 +101,6 @@ using LazyArrays: LazyLayout
101101end
102102
103103
104- """
105- upper_mul_tri_triview(U, X) == Tridiagonal(U*X) where U is Upper triangular BandedMatrix and X is Tridiagonal
106- """
107- function upper_mul_tri_triview (U:: BandedMatrix , X:: Tridiagonal )
108- T = promote_type (eltype (U), eltype (X))
109- n = size (U,1 )
110- upper_mul_tri_triview! (Tridiagonal (Vector {T} (undef, n- 1 ), Vector {T} (undef, n), Vector {T} (undef, n- 1 )), U, X)
111- end
112-
113- function upper_mul_tri_triview! (UX:: Tridiagonal , U:: BandedMatrix , X:: Tridiagonal )
114- n = size (U,1 )
115-
116- j = 1
117- Xⱼⱼ, Xⱼ₊₁ⱼ = X. d[1 ], X. dl[1 ]
118- Uⱼⱼ, Uⱼⱼ₊₁, Uⱼⱼ₊₂ = U. data[3 ,1 ], U. data[2 ,2 ], U. data[1 ,3 ] # U[j,j], U[j,j+1], U[j,j+2]
119- UX. d[1 ] = Uⱼⱼ* Xⱼⱼ + Uⱼⱼ₊₁* Xⱼ₊₁ⱼ # UX[j,j] = U[j,j]*X[j,j] + U[j,j+1]*X[j+1,j]
120- Xⱼⱼ₊₁, Xⱼⱼ, Xⱼ₊₁ⱼ, Xⱼⱼ₋₁ = X. du[1 ], X. d[2 ], X. dl[2 ], Xⱼ₊₁ⱼ # X[j,j+1], X[j+1,j+1], X[j+2,j+1], X[j+1,j]
121- UX. du[1 ] = Uⱼⱼ* Xⱼⱼ₊₁ + Uⱼⱼ₊₁* Xⱼⱼ + Uⱼⱼ₊₂* Xⱼ₊₁ⱼ # UX[j,j+1] = U[j,j]*X[j,j+1] + U[j,j+1]*X[j+1,j+1] + U[j,j+1]*X[j+1,j]
122-
123- @inbounds for j = 2 : n- 2
124- Uⱼⱼ, Uⱼⱼ₊₁, Uⱼⱼ₊₂ = U. data[3 ,j], U. data[2 ,j+ 1 ], U. data[1 ,j+ 2 ] # U[j,j], U[j,j+1], U[j,j+2]
125- UX. dl[j- 1 ] = Uⱼⱼ* Xⱼⱼ₋₁ # UX[j,j-1] = U[j,j]*X[j,j-1]
126- UX. d[j] = Uⱼⱼ* Xⱼⱼ + Uⱼⱼ₊₁* Xⱼ₊₁ⱼ # UX[j,j] = U[j,j]*X[j,j] + U[j,j+1]*X[j+1,j]
127- Xⱼⱼ₊₁, Xⱼⱼ, Xⱼ₊₁ⱼ, Xⱼⱼ₋₁ = X. du[j], X. d[j+ 1 ], X. dl[j+ 1 ], Xⱼ₊₁ⱼ # X[j,j+1], X[j+1,j+1], X[j+2,j+1], X[j+1,j]
128- UX. du[j] = Uⱼⱼ* Xⱼⱼ₊₁ + Uⱼⱼ₊₁* Xⱼⱼ + Uⱼⱼ₊₂* Xⱼ₊₁ⱼ # UX[j,j+1] = U[j,j]*X[j,j+1] + U[j,j+1]*X[j+1,j+1] + U[j,j+2]*X[j+2,j+1]
129- end
130-
131- j = n- 1
132- Uⱼⱼ, Uⱼⱼ₊₁ = U. data[3 ,j], U. data[2 ,j+ 1 ] # U[j,j], U[j,j+1]
133- UX. dl[j- 1 ] = Uⱼⱼ* Xⱼⱼ₋₁ # UX[j,j-1] = U[j,j]*X[j,j-1]
134- UX. d[j] = Uⱼⱼ* Xⱼⱼ + Uⱼⱼ₊₁* Xⱼ₊₁ⱼ # UX[j,j] = U[j,j]*X[j,j] + U[j,j+1]*X[j+1,j]
135- Xⱼⱼ₊₁, Xⱼⱼ, Xⱼⱼ₋₁ = X. du[j], X. d[j+ 1 ], Xⱼ₊₁ⱼ # X[j,j+1], X[j+1,j+1], X[j+2,j+1], X[j+1,j]
136- UX. du[j] = Uⱼⱼ* Xⱼⱼ₊₁ + Uⱼⱼ₊₁* Xⱼⱼ # UX[j,j+1] = U[j,j]*X[j,j+1] + U[j,j+1]*X[j+1,j+1] + U[j,j+2]*X[j+2,j+1]
137-
138- j = n
139- Uⱼⱼ = U. data[3 ,j] # U[j,j]
140- UX. dl[j- 1 ] = Uⱼⱼ* Xⱼⱼ₋₁ # UX[j,j-1] = U[j,j]*X[j,j-1]
141- UX. d[j] = Uⱼⱼ* Xⱼⱼ # UX[j,j] = U[j,j]*X[j,j] + U[j,j+1]*X[j+1,j]
142-
143- UX
144- end
145-
146-
147- # X*R^{-1} = X*[1/R₁₁ -R₁₂/(R₁₁R₂₂) -R₁₃/R₂₂ …
148- # 0 1/R₂₂ -R₂₃/R₃₃
149- # 1/R₃₃
150-
151- tri_mul_invupper_triview (X:: Tridiagonal , R:: BandedMatrix ) = tri_mul_invupper_triview! (similar (X, promote_type (eltype (X), eltype (R))), X, R)
152-
153- function tri_mul_invupper_triview! (Y, X, R)
154- n = size (X,1 )
155- k = 1
156- Xₖₖ,Xₖₖ₊₁ = X. d[k], X. du[k]
157- Rₖₖ,Rₖₖ₊₁ = R. data[3 ,k], R. data[2 ,k+ 1 ] # R[1,1], R[1,2]
158- Y. d[k] = Xₖₖ/ Rₖₖ
159- Y. du[k] = Xₖₖ₊₁ - Xₖₖ * Rₖₖ₊₁/ Rₖₖ
160-
161- @inbounds for k = 2 : n- 1
162- Xₖₖ₋₁,Xₖₖ,Xₖₖ₊₁ = X. dl[k- 1 ], X. d[k], X. du[k]
163- Y. dl[k- 1 ] = Xₖₖ₋₁/ Rₖₖ
164- Y. d[k] = Xₖₖ- Xₖₖ₋₁* Rₖₖ₊₁/ Rₖₖ
165- Y. du[k] = Xₖₖ₋₁/ Rₖₖ
166- Rₖₖ,Rₖₖ₊₁,Rₖ₋₁ₖ₊₁,Rₖ₋₁ₖ = R. data[3 ,k], R. data[2 ,k+ 1 ],R. data[1 ,k+ 1 ],Rₖₖ₊₁ # R[2,2], R[2,3], R[1,3]
167- Y. d[k] /= Rₖₖ
168- Y. du[k- 1 ] /= Rₖₖ
169- Y. du[k] *= Rₖ₋₁ₖ* Rₖₖ₊₁/ Rₖₖ - Rₖ₋₁ₖ₊₁
170- Y. du[k] += Xₖₖ₊₁ - Xₖₖ * Rₖₖ₊₁ / Rₖₖ
171- end
172-
173- k = n
174- Xₖₖ₋₁,Xₖₖ = X. dl[k- 1 ], X. d[k]
175- Y. dl[k- 1 ] = Xₖₖ₋₁/ Rₖₖ
176- Y. d[k] = Xₖₖ- Xₖₖ₋₁* Rₖₖ₊₁/ Rₖₖ
177- Rₖₖ = R. data[3 ,k] # R[2,2], R[2,3], R[1,3]
178- Y. d[k] /= Rₖₖ
179- Y. du[k- 1 ] /= Rₖₖ
180-
181- Y
182- end
183- """
184- TridiagonalConjugationData(U, X, V, Y)
185-
186- caches the infinite dimensional Tridiagonal(U*X/V)
187- in the tridiagonal matrix `Y`
188- """
189-
190- mutable struct TridiagonalConjugationData{T}
191- const U:: AbstractMatrix{T}
192- const X:: AbstractMatrix{T}
193- const V:: AbstractMatrix{T}
194-
195- const UX:: Tridiagonal{T,Vector{T}} # cache Tridiagonal(U*X)
196- const Y:: Tridiagonal{T,Vector{T}} # cache Tridiagonal(U*X/V)
197-
198- datasize:: Int
199- end
200-
201- function TridiagonalConjugationData (U, X, V, uplo:: Char )
202- T = promote_type (typeof (inv (V[1 , 1 ])), eltype (U), eltype (C)) # include inv so that we can't get Ints
203- return BidiagonalConjugationData (U, X, V, Tridiagonal (T[], T[], T[]), Tridiagonal (T[], T[], T[]), 0 )
204- end
205-
206- copy (data:: TridiagonalConjugationData ) = TridiagonalConjugationData (copy (data. U), copy (data. X), copy (data. V), copy (data. UX), copy (data. Y), data. datasize)
207-
208-
209- function resizedata! (data:: TridiagonalConjugationData , n)
210- n ≤ 0 && return data
211- n = max (v, n)
212- dv, ev = data. dv, data. ev
213- if n > length (ev) # Avoid O(n²) growing. Note min(length(dv), length(ev)) == length(ev)
214- resize! (dv, 2 n + 1 )
215- resize! (ev, 2 n)
216- end
217-
218-
219- end
220-
221-
222104@testset " TridiagonalConjugation" begin
223105 @testset " T -> U" begin
224106 R = BandedMatrices. _BandedMatrix (Vcat (- Ones (1 ,∞)/ 2 ,
@@ -228,10 +110,10 @@ end
228110 n = 1000
229111 @time U = V = R[1 : n,1 : n];
230112 @time X = Tridiagonal (Vector (X_T. dl[1 : n- 1 ]), Vector (X_T. d[1 : n]), Vector (X_T. du[1 : n- 1 ]));
231- @time UX = upper_mul_tri_triview (U, X)
113+ @time UX = InfiniteLinearAlgebra . upper_mul_tri_triview (U, X)
232114 @test Tridiagonal (U* X) ≈ UX
233115 # U*X*inv(U) only depends on Tridiagonal(U*X)
234- @time Y = tri_mul_invupper_triview (UX, U)
116+ @time Y = InfiniteLinearAlgebra . tri_mul_invupper_triview (UX, U)
235117 @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ Y
236118 end
237119 @testset " P -> Ultraspherical(3/2)" begin
@@ -242,10 +124,40 @@ end
242124 n = 1000
243125 @time U = V = R[1 : n,1 : n]
244126 @time X = Tridiagonal (Vector (X_P. dl[1 : n- 1 ]), Vector (X_P. d[1 : n]), Vector (X_P. du[1 : n- 1 ]))
245- @time UX = upper_mul_tri_triview (U, X)
127+ @time UX = InfiniteLinearAlgebra. upper_mul_tri_triview (U, X)
128+ @test Tridiagonal (U* X) ≈ UX
129+ # U*X*inv(U) only depends on Tridiagonal(U*X)
130+ @time Y = InfiniteLinearAlgebra. tri_mul_invupper_triview (UX, U)
131+ @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ Y
132+ end
133+
134+ @testset " Jacobi(1,0) -> Jacobi(2,0)" begin
135+ R = BandedMatrices. _BandedMatrix (Vcat (Zeros (1 ,∞), # extra band since code assumes two bands
136+ (- (0 : ∞) ./ (2 : 2 : ∞))' ,
137+ ((2 : ∞) ./ (2 : 2 : ∞))' ), ℵ₀, 0 ,2 )
138+ X_P = LazyBandedMatrices. Tridiagonal ((2 : ∞) ./ (3 : 2 : ∞), - 1 ./ ((1 : 2 : ∞) .* (3 : 2 : ∞)), (1 : ∞) ./ (3 : 2 : ∞))
139+ n = 1000
140+ @time U = V = R[1 : n,1 : n]
141+ @time X = Tridiagonal (Vector (X_P. dl[1 : n- 1 ]), Vector (X_P. d[1 : n]), Vector (X_P. du[1 : n- 1 ]))
142+ @time UX = InfiniteLinearAlgebra. upper_mul_tri_triview (U, X)
143+ @test Tridiagonal (U* X) ≈ UX
144+ # U*X*inv(U) only depends on Tridiagonal(U*X)
145+ @time Y = InfiniteLinearAlgebra. tri_mul_invupper_triview (UX, U)
146+ @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ Y
147+ end
148+
149+ @testset " Legendre() -> Jacobi(5/2)" begin
150+ R = BandedMatrices. _BandedMatrix (Vcat ((- 3 ./ (3 : 2 : ∞))' , Zeros (1 ,∞), (3 ./ (3 : 2 : ∞))' ), ℵ₀, 0 ,2 ) *
151+ BandedMatrices. _BandedMatrix (Vcat ((- 1 ./ (1 : 2 : ∞))' , Zeros (1 ,∞), (1 ./ (1 : 2 : ∞))' ), ℵ₀, 0 ,2 )
152+ X_P = LazyBandedMatrices. Tridiagonal ((1 : ∞) ./ (1 : 2 : ∞), Zeros (∞), (1 : ∞) ./ (3 : 2 : ∞))
153+
154+ n = 1000
155+ @time U = V = R[1 : n,1 : n]
156+ @time X = Tridiagonal (Vector (X_P. dl[1 : n- 1 ]), Vector (X_P. d[1 : n]), Vector (X_P. du[1 : n- 1 ]))
157+ @time UX = InfiniteLinearAlgebra. upper_mul_tri_triview (U, X)
246158 @test Tridiagonal (U* X) ≈ UX
247159 # U*X*inv(U) only depends on Tridiagonal(U*X)
248- @time Y = tri_mul_invupper_triview (UX, U)
160+ @time Y = InfiniteLinearAlgebra . tri_mul_invupper_triview (UX, U)
249161 @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ Y
250162 end
251163end
0 commit comments