Skip to content

Commit cc3903d

Browse files
committed
Add bidiagonal cholesky version
1 parent 16f64e7 commit cc3903d

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

src/cholesky.jl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,32 @@ function _chol!(A::AbstractMatrix, ::Type{UpperTriangular})
220220
end
221221
return UpperTriangular(A), convert(BlasInt, 0)
222222
end
223+
function _chol!(A::Bidiagonal, ::Type{UpperTriangular})
224+
require_one_based_indexing(A)
225+
n = checksquare(A)
226+
realdiag = eltype(A) <: Complex
227+
dv = A.dv
228+
ev = A.ev
229+
@inbounds begin
230+
for k = 1:n
231+
Akk = realdiag ? real(dv[k]) : dv[k]
232+
if k > 1
233+
Akk -= realdiag ? abs2(ev[k-1]) : ev[k-1]'ev[k-1]
234+
end
235+
dv[k] = Akk
236+
Akk, info = _chol!(Akk, UpperTriangular)
237+
if info != 0
238+
return UpperTriangular(A), convert(BlasInt, k)
239+
end
240+
dv[k] = Akk
241+
AkkInv = inv(copy(Akk'))
242+
if k < n
243+
ev[k] = AkkInv*ev[k]
244+
end
245+
end
246+
end
247+
return UpperTriangular(A), convert(BlasInt, 0)
248+
end
223249
function _chol!(A::AbstractMatrix, ::Type{LowerTriangular})
224250
require_one_based_indexing(A)
225251
n = checksquare(A)
@@ -250,6 +276,32 @@ function _chol!(A::AbstractMatrix, ::Type{LowerTriangular})
250276
end
251277
return LowerTriangular(A), convert(BlasInt, 0)
252278
end
279+
function _chol!(A::Bidiagonal, ::Type{LowerTriangular})
280+
require_one_based_indexing(A)
281+
n = checksquare(A)
282+
realdiag = eltype(A) <: Complex
283+
dv = A.dv
284+
ev = A.ev
285+
@inbounds begin
286+
for k = 1:n
287+
Akk = realdiag ? real(dv[k]) : dv[k]
288+
if k > 1
289+
Akk -= realdiag ? abs2(ev[k-1]) : ev[k-1]*ev[k-1]'
290+
end
291+
dv[k] = Akk
292+
Akk, info = _chol!(Akk, LowerTriangular)
293+
if info != 0
294+
return LowerTriangular(A), convert(BlasInt, k)
295+
end
296+
dv[k] = Akk
297+
AkkInv = inv(copy(Akk'))
298+
if k < n
299+
ev[k] *= AkkInv
300+
end
301+
end
302+
end
303+
return LowerTriangular(A), convert(BlasInt, 0)
304+
end
253305

254306
## Numbers
255307
function _chol!(x::Number, _)

src/tridiag.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,7 @@ function dot(x::AbstractVector, A::Tridiagonal, y::AbstractVector)
10391039
return r
10401040
end
10411041

1042-
function cholesky(S::SymTridiagonal, ::NoPivot = NoPivot(); check::Bool = true)
1042+
function cholesky(S::Union{SymTridiagonal,Tridiagonal}, ::NoPivot = NoPivot(); check::Bool = true)
10431043
if !ishermitian(S)
10441044
check && checkpositivedefinite(-1)
10451045
return Cholesky(S, 'U', convert(BlasInt, -1))

test/cholesky.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,16 @@ end
492492
end
493493

494494
@testset "Cholesky for AbstractMatrix" begin
495-
S = SymTridiagonal(fill(2.0, 4), ones(3))
496-
C = cholesky(S)
497-
@test C.L * C.U S
495+
for M in (SymTridiagonal(fill(2.0, 4), ones(3)),
496+
Tridiagonal(ones(3), fill(2.0, 4), ones(3)),
497+
)
498+
C = cholesky(M)
499+
@test C.L * C.U M
500+
end
501+
# test LowerTriangular version
502+
M = Hermitian(Bidiagonal(fill(2.0, 4), ones(3), :L), :L)
503+
C = cholesky!(copy(M))
504+
@test C.L * C.U M
498505
end
499506

500507
@testset "constructor with non-BlasInt arguments" begin

0 commit comments

Comments
 (0)