@@ -38,23 +38,23 @@ bandwidths(A::SymmetricBandedToeplitzPlusHankel{T}) where T = (A.b, A.b)
3838
3939#
4040# X'W-W*X = G*J*G'
41- # This returns G and J , where J = [0 I ; -I 0], respecting the skew-symmetry of the right-hand side.
41+ # This returns G, where J = [0 1 ; -1 0], respecting the skew-symmetry of the right-hand side.
4242#
4343function compute_skew_generators (A:: SymmetricToeplitzPlusHankel{T} ) where T
4444 v = A. v
4545 n = size (A, 1 )
46- J = [zero (T) one (T); - one (T) zero (T)]
4746 G = zeros (T, n, 2 )
4847 G[n, 1 ] = one (T)
49- u2 = reverse (v[2 : n+ 1 ])
50- u2[1 : n- 1 ] .+ = v[n+ 1 : 2 n- 1 ]
51- G[:, 2 ] .= - u2
52- G, J
48+ @inbounds @simd for j in 1 : n- 1
49+ G[j, 2 ] = - (v[n+ 2 - j] + v[n+ j])
50+ end
51+ G[n, 2 ] = - v[2 ]
52+ G
5353end
5454
5555function cholesky (A:: SymmetricToeplitzPlusHankel{T} ) where T
5656 n = size (A, 1 )
57- G, J = compute_skew_generators (A)
57+ G = compute_skew_generators (A)
5858 L = zeros (T, n, n)
5959 c = A[:, 1 ]
6060 ĉ = zeros (T, n)
@@ -74,20 +74,29 @@ function STPHcholesky!(L::Matrix{T}, G, c, ĉ, l, v, row1, n) where T
7474 for j in 1 : n- k+ 1
7575 v[j] = G[j, 1 ]* G[1 , 2 ] - G[j, 2 ]* G[1 , 1 ]
7676 end
77- X21 = k == 1 ? T (2 ) : T (1 )
78- ĉ[1 ] = (c[2 ] - v[1 ])/ X21
79- for j in 2 : n- k
80- ĉ[j] = (c[j+ 1 ] + c[j- 1 ] + c[1 ]* row1[j] - row1[1 ]* c[j] - v[j])/ X21
77+ if k == 1
78+ for j in 2 : n- k
79+ ĉ[j] = (c[j+ 1 ] + c[j- 1 ] + c[1 ]* row1[j] - row1[1 ]* c[j] - v[j])/ 2
80+ end
81+ ĉ[n- k+ 1 ] = (c[n- k] + c[1 ]* row1[n- k+ 1 ] - row1[1 ]* c[n- k+ 1 ] - v[n- k+ 1 ])/ 2
82+ cst = 2 / d
83+ for j in 1 : n- k
84+ row1[j] = - cst* l[j+ 1 ]
85+ end
86+ else
87+ for j in 2 : n- k
88+ ĉ[j] = c[j+ 1 ] + c[j- 1 ] + c[1 ]* row1[j] - row1[1 ]* c[j] - v[j]
89+ end
90+ ĉ[n- k+ 1 ] = c[n- k] + c[1 ]* row1[n- k+ 1 ] - row1[1 ]* c[n- k+ 1 ] - v[n- k+ 1 ]
91+ cst = 1 / d
92+ for j in 1 : n- k
93+ row1[j] = - cst* l[j+ 1 ]
94+ end
8195 end
82- ĉ[n- k+ 1 ] = (c[n- k] + c[1 ]* row1[n- k+ 1 ] - row1[1 ]* c[n- k+ 1 ] - v[n- k+ 1 ])/ X21
8396 cst = c[2 ]/ d
8497 for j in 1 : n- k
8598 c[j] = ĉ[j+ 1 ] - cst* l[j+ 1 ]
8699 end
87- cst = X21/ d
88- for j in 1 : n- k
89- row1[j] = - cst* l[j+ 1 ]
90- end
91100 gd1 = G[1 , 1 ]/ d
92101 gd2 = G[1 , 2 ]/ d
93102 for j in 1 : n- k
@@ -101,37 +110,106 @@ end
101110function cholesky (A:: SymmetricBandedToeplitzPlusHankel{T} ) where T
102111 n = size (A, 1 )
103112 b = A. b
104- R = BandedMatrix {T} (undef, (n, n), (0 , bandwidth (A, 2 ) ))
113+ L = BandedMatrix {T} (undef, (n, n), (bandwidth (A, 1 ), 0 ))
105114 c = A[1 : b+ 2 , 1 ]
106115 ĉ = zeros (T, b+ 3 )
107116 l = zeros (T, b+ 3 )
108117 row1 = zeros (T, b+ 2 )
109- SBTPHcholesky! (R , c, ĉ, l, row1, n, b)
110- return Cholesky (R , ' U ' , 0 )
118+ SBTPHcholesky! (L , c, ĉ, l, row1, n, b)
119+ return Cholesky (L , ' L ' , 0 )
111120end
112121
113- function SBTPHcholesky! (R :: BandedMatrix{T} , c, ĉ, l, row1, n, b) where T
122+ function SBTPHcholesky! (L :: BandedMatrix{T} , c, ĉ, l, row1, n, b) where T
114123 @inbounds @simd for k in 1 : n
115124 d = sqrt (c[1 ])
116125 for j in 1 : b+ 1
117126 l[j] = c[j]/ d
118127 end
119128 for j in 1 : min (n- k+ 1 , b+ 1 )
120- R[k, j+ k- 1 ] = l[j]
129+ L[ j+ k- 1 , k ] = l[j]
121130 end
122- X21 = k == 1 ? T (2 ) : T (1 )
123- ĉ[1 ] = c[2 ]/ X21
124- for j in 2 : b+ 1
125- ĉ[j] = (c[j+ 1 ] + c[j- 1 ] + c[1 ]* row1[j] - row1[1 ]* c[j])/ X21
131+ if k == 1
132+ for j in 2 : b+ 1
133+ ĉ[j] = (c[j+ 1 ] + c[j- 1 ] + c[1 ]* row1[j] - row1[1 ]* c[j])/ 2
134+ end
135+ ĉ[b+ 2 ] = (c[b+ 1 ] + c[1 ]* row1[b+ 2 ] - row1[1 ]* c[b+ 2 ])/ 2
136+ cst = 2 / d
137+ for j in 1 : b+ 2
138+ row1[j] = - cst* l[j+ 1 ]
139+ end
140+ else
141+ for j in 2 : b+ 1
142+ ĉ[j] = (c[j+ 1 ] + c[j- 1 ] + c[1 ]* row1[j] - row1[1 ]* c[j])
143+ end
144+ ĉ[b+ 2 ] = (c[b+ 1 ] + c[1 ]* row1[b+ 2 ] - row1[1 ]* c[b+ 2 ])
145+ cst = 1 / d
146+ for j in 1 : b+ 2
147+ row1[j] = - cst* l[j+ 1 ]
148+ end
126149 end
127- ĉ[b+ 2 ] = (c[b+ 1 ] + c[1 ]* row1[b+ 2 ] - row1[1 ]* c[b+ 2 ])/ X21
128150 cst = c[2 ]/ d
129151 for j in 1 : b+ 2
130152 c[j] = ĉ[j+ 1 ] - cst* l[j+ 1 ]
131153 end
132- cst = X21/ d
133- for j in 1 : b+ 2
134- row1[j] = - cst* l[j+ 1 ]
154+ end
155+ end
156+
157+
158+
159+ #
160+ # X'W-W*X = G*J*G'
161+ # This returns G, where J = [0 1; -1 0], respecting the skew-symmetry of the right-hand side.
162+ #
163+ function compute_skew_generators (W:: Symmetric{T, <: AbstractMatrix{T}} , X:: Tridiagonal{T, Vector{T}} ) where T
164+ @assert size (W) == size (X)
165+ m, n = size (W)
166+ G = zeros (T, n, 2 )
167+ G[n, 1 ] = one (T)
168+ G[:, 2 ] .= W[n- 1 , :]* X[n- 1 , n] - X' W[:, n]
169+ return G
170+ end
171+
172+ function fastcholesky (W:: Symmetric{T, <: AbstractMatrix{T}} , X:: Tridiagonal{T, Vector{T}} ) where T
173+ n = size (W, 1 )
174+ G = compute_skew_generators (W, X)
175+ L = zeros (T, n, n)
176+ c = W[:, 1 ]
177+ ĉ = zeros (T, n)
178+ l = zeros (T, n)
179+ v = zeros (T, n)
180+ row1 = zeros (T, n)
181+ fastcholesky! (L, X, G, c, ĉ, l, v, row1, n)
182+ return Cholesky (L, ' L' , 0 )
183+ end
184+
185+
186+ function fastcholesky! (L:: Matrix{T} , X:: Tridiagonal{T, Vector{T}} , G, c, ĉ, l, v, row1, n) where T
187+ @inbounds @simd for k in 1 : n- 1
188+ d = sqrt (c[k])
189+ for j in k: n
190+ L[j, k] = l[j] = c[j]/ d
191+ end
192+ for j in k: n
193+ v[j] = G[j, 1 ]* G[k, 2 ] - G[j, 2 ]* G[k, 1 ]
194+ end
195+ for j in k+ 1 : n- 1
196+ ĉ[j] = (X[j- 1 , j]* c[j- 1 ] + (X[j, j]- X[k, k])* c[j] + X[j+ 1 , j]* c[j+ 1 ] + c[k]* row1[j] - row1[k]* c[j] - v[j])/ X[k+ 1 , k]
197+ end
198+ ĉ[n] = (X[n- 1 , n]* c[n- 1 ] + (X[n, n]- X[k, k])* c[n] + c[k]* row1[n] - row1[k]* c[n] - v[n])/ X[k+ 1 , k]
199+ cst = X[k+ 1 , k]/ d
200+ for j in k+ 1 : n
201+ row1[j] = - cst* l[j]
202+ end
203+ cst = c[k+ 1 ]/ d
204+ for j in k: n
205+ c[j] = ĉ[j] - cst* l[j]
206+ end
207+ gd1 = G[k, 1 ]/ d
208+ gd2 = G[k, 2 ]/ d
209+ for j in k: n
210+ G[j, 1 ] -= l[j]* gd1
211+ G[j, 2 ] -= l[j]* gd2
135212 end
136213 end
214+ L[n, n] = sqrt (c[n])
137215end
0 commit comments