@@ -38,23 +38,23 @@ bandwidths(A::SymmetricBandedToeplitzPlusHankel{T}) where T = (A.b, A.b)
38
38
39
39
#
40
40
# 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.
42
42
#
43
43
function compute_skew_generators (A:: SymmetricToeplitzPlusHankel{T} ) where T
44
44
v = A. v
45
45
n = size (A, 1 )
46
- J = [zero (T) one (T); - one (T) zero (T)]
47
46
G = zeros (T, n, 2 )
48
47
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
53
53
end
54
54
55
55
function cholesky (A:: SymmetricToeplitzPlusHankel{T} ) where T
56
56
n = size (A, 1 )
57
- G, J = compute_skew_generators (A)
57
+ G = compute_skew_generators (A)
58
58
L = zeros (T, n, n)
59
59
c = A[:, 1 ]
60
60
ĉ = zeros (T, n)
@@ -74,20 +74,29 @@ function STPHcholesky!(L::Matrix{T}, G, c, ĉ, l, v, row1, n) where T
74
74
for j in 1 : n- k+ 1
75
75
v[j] = G[j, 1 ]* G[1 , 2 ] - G[j, 2 ]* G[1 , 1 ]
76
76
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
81
95
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
83
96
cst = c[2 ]/ d
84
97
for j in 1 : n- k
85
98
c[j] = ĉ[j+ 1 ] - cst* l[j+ 1 ]
86
99
end
87
- cst = X21/ d
88
- for j in 1 : n- k
89
- row1[j] = - cst* l[j+ 1 ]
90
- end
91
100
gd1 = G[1 , 1 ]/ d
92
101
gd2 = G[1 , 2 ]/ d
93
102
for j in 1 : n- k
@@ -101,37 +110,106 @@ end
101
110
function cholesky (A:: SymmetricBandedToeplitzPlusHankel{T} ) where T
102
111
n = size (A, 1 )
103
112
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 ))
105
114
c = A[1 : b+ 2 , 1 ]
106
115
ĉ = zeros (T, b+ 3 )
107
116
l = zeros (T, b+ 3 )
108
117
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 )
111
120
end
112
121
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
114
123
@inbounds @simd for k in 1 : n
115
124
d = sqrt (c[1 ])
116
125
for j in 1 : b+ 1
117
126
l[j] = c[j]/ d
118
127
end
119
128
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]
121
130
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
126
149
end
127
- ĉ[b+ 2 ] = (c[b+ 1 ] + c[1 ]* row1[b+ 2 ] - row1[1 ]* c[b+ 2 ])/ X21
128
150
cst = c[2 ]/ d
129
151
for j in 1 : b+ 2
130
152
c[j] = ĉ[j+ 1 ] - cst* l[j+ 1 ]
131
153
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
135
212
end
136
213
end
214
+ L[n, n] = sqrt (c[n])
137
215
end
0 commit comments