@@ -22,7 +22,7 @@ using LazyArrays: LazyLayout
2222 V2 = brand (∞, 0 , 1 )
2323 A2 = LazyBandedMatrices. Bidiagonal (Fill (0.2 , ∞), 2.0 ./ (1.0 .+ (1 : ∞)), ' L' ) # LinearAlgebra.Bidiagonal not playing nice for this case
2424 X2 = InfRandBidiagonal (' L' )
25- U2 = X2 * V2 * ApplyArray (inv, A2)
25+ U2 = X2 * V2 * ApplyArray (inv, A2)
2626 B2 = BidiagonalConjugation (U2, X2, V2, :L );
2727
2828 for (A, B, uplo) in ((A1, B1, ' U' ), (A2, B2, ' L' ))
@@ -54,12 +54,12 @@ using LazyArrays: LazyLayout
5454 @test LazyBandedMatrices. Bidiagonal (B) === LazyBandedMatrices. Bidiagonal (B. dv, B. ev, Symbol (uplo))
5555 @test B[1 : 10 , 1 : 10 ] ≈ A[1 : 10 , 1 : 10 ]
5656 @test B[230 , 230 ] ≈ A[230 , 230 ]
57- @test B[102 , 102 ] ≈ A[102 , 102 ] # make sure we compute intermediate columns correctly when skipping
57+ @test B[102 , 102 ] ≈ A[102 , 102 ] # make sure we compute intermediate columns correctly when skipping
5858 @test B[band (0 )][1 : 100 ] == B. dv[1 : 100 ]
5959 if uplo == ' U'
6060 @test B[band (1 )][1 : 100 ] == B. ev[1 : 100 ]
61- # @test B[band(-1)][1:100] == zeros(100) # This test requires that we define a
62- # convert(::Type{BidiagonalConjugationBand{T}}, ::Zeros{V, 1, Tuple{OneToInf{Int}}}) where {T, V} method,
61+ # @test B[band(-1)][1:100] == zeros(100) # This test requires that we define a
62+ # convert(::Type{BidiagonalConjugationBand{T}}, ::Zeros{V, 1, Tuple{OneToInf{Int}}}) where {T, V} method,
6363 # which we probably don't need beyond this test
6464 else
6565 @test B[band (- 1 )][1 : 100 ] == B. ev[1 : 100 ]
@@ -74,7 +74,7 @@ using LazyArrays: LazyLayout
7474 @test (B* I)[1 : 100 , 1 : 100 ] ≈ B[1 : 100 , 1 : 100 ]
7575 # @test (B*Diagonal(1:∞))[1:100, 1:100] ≈ B[1:100, 1:100] * Diagonal(1:100) # Uncomment once https://github.com/JuliaLinearAlgebra/ArrayLayouts.jl/pull/241 is registered
7676
77- # Pointwise tests
77+ # Pointwise tests
7878 for i in 1 : 10
7979 for j in 1 : 10
8080 @test B[i, j] ≈ A[i, j]
@@ -92,7 +92,7 @@ using LazyArrays: LazyLayout
9292 R0 = BandedMatrices. _BandedMatrix (Vcat (- Ones (1 ,∞)/ 2 ,
9393 Zeros (1 ,∞),
9494 Hcat (Ones (1 ,1 ),Ones (1 ,∞)/ 2 )), ℵ₀, 0 ,2 )
95-
95+
9696 D0 = BandedMatrix (1 => 1 : ∞)
9797 R1 = BandedMatrix (0 => 1 ./ (1 : ∞), 2 => - 1 ./ (3 : ∞))
9898
112112
113113function upper_mul_tri_triview! (UX:: Tridiagonal , U:: BandedMatrix , X:: Tridiagonal )
114114 n = size (U,1 )
115-
115+
116116 j = 1
117117 Xⱼⱼ, Xⱼ₊₁ⱼ = X. d[1 ], X. dl[1 ]
118118 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]
@@ -157,7 +157,7 @@ function tri_mul_invupper_triview!(Y, X, R)
157157 Rₖₖ,Rₖₖ₊₁ = R. data[3 ,k], R. data[2 ,k+ 1 ] # R[1,1], R[1,2]
158158 Y. d[k] = Xₖₖ/ Rₖₖ
159159 Y. du[k] = Xₖₖ₊₁ - Xₖₖ * Rₖₖ₊₁/ Rₖₖ
160-
160+
161161 @inbounds for k = 2 : n- 1
162162 Xₖₖ₋₁,Xₖₖ,Xₖₖ₊₁ = X. dl[k- 1 ], X. d[k], X. du[k]
163163 Y. dl[k- 1 ] = Xₖₖ₋₁/ Rₖₖ
@@ -180,18 +180,72 @@ function tri_mul_invupper_triview!(Y, X, R)
180180
181181 Y
182182end
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
183220
184221
185222@testset " TridiagonalConjugation" begin
186- R0 = BandedMatrices. _BandedMatrix (Vcat (- Ones (1 ,∞)/ 2 ,
187- Zeros (1 ,∞),
188- Hcat (Ones (1 ,1 ),Ones (1 ,∞)/ 2 )), ℵ₀, 0 ,2 )
189- X_T = LazyBandedMatrices. Tridiagonal (Vcat (1.0 , Fill (1 / 2 ,∞)), Zeros (∞), Fill (1 / 2 ,∞))
190-
191- n = 1000 ; @time U = V = R0[1 : n,1 : n];
192- @time X = Tridiagonal (Vector (X_T. dl[1 : n- 1 ]), Vector (X_T. d[1 : n]), Vector (X_T. du[1 : n- 1 ]));
193- @time UX = upper_mul_tri_triview (U, X)
194- @test Tridiagonal (U* X) ≈ UX
195- # U*X*inv(U) only depends on Tridiagonal(U*X)
196- @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ tri_mul_invupper_triview (UX, U)
223+ @testset " T -> U" begin
224+ R = BandedMatrices. _BandedMatrix (Vcat (- Ones (1 ,∞)/ 2 ,
225+ Zeros (1 ,∞),
226+ Hcat (Ones (1 ,1 ),Ones (1 ,∞)/ 2 )), ℵ₀, 0 ,2 )
227+ X_T = LazyBandedMatrices. Tridiagonal (Vcat (1.0 , Fill (1 / 2 ,∞)), Zeros (∞), Fill (1 / 2 ,∞))
228+ n = 1000
229+ @time U = V = R[1 : n,1 : n];
230+ @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)
232+ @test Tridiagonal (U* X) ≈ UX
233+ # U*X*inv(U) only depends on Tridiagonal(U*X)
234+ @time Y = tri_mul_invupper_triview (UX, U)
235+ @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ Y
236+ end
237+ @testset " P -> Ultraspherical(3/2)" begin
238+ R = BandedMatrices. _BandedMatrix (Vcat ((- 1 ./ (1 : 2 : ∞))' ,
239+ Zeros (1 ,∞),
240+ (1 ./ (1 : 2 : ∞))' ), ℵ₀, 0 ,2 )
241+ X_P = LazyBandedMatrices. Tridiagonal ((1 : ∞) ./ (1 : 2 : ∞), Zeros (∞), (1 : ∞) ./ (3 : 2 : ∞))
242+ n = 1000
243+ @time U = V = R[1 : n,1 : n]
244+ @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)
246+ @test Tridiagonal (U* X) ≈ UX
247+ # U*X*inv(U) only depends on Tridiagonal(U*X)
248+ @time Y = tri_mul_invupper_triview (UX, U)
249+ @test Tridiagonal (U* X / U) ≈ Tridiagonal (UX / U) ≈ Y
250+ end
197251end
0 commit comments