Skip to content

Commit d99e79f

Browse files
dkarraschKristofferC
authored andcommitted
fix generic ldiv! for CholeskyPivoted (#32593)
* fix generic ldiv! for CholeskyPivoted * add back one empty line to make backport easier * don't interfere with previous tests (cherry picked from commit d0e11cf)
1 parent 31227f9 commit d99e79f

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

stdlib/LinearAlgebra/src/cholesky.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,21 +424,30 @@ end
424424
function ldiv!(C::CholeskyPivoted, B::StridedVector)
425425
if C.uplo == 'L'
426426
ldiv!(adjoint(LowerTriangular(C.factors)),
427-
ldiv!(LowerTriangular(C.factors), B[C.piv]))[invperm(C.piv)]
427+
ldiv!(LowerTriangular(C.factors), permute!(B, C.piv)))
428428
else
429429
ldiv!(UpperTriangular(C.factors),
430-
ldiv!(adjoint(UpperTriangular(C.factors)), B[C.piv]))[invperm(C.piv)]
430+
ldiv!(adjoint(UpperTriangular(C.factors)), permute!(B, C.piv)))
431431
end
432+
invpermute!(B, C.piv)
432433
end
433434

434435
function ldiv!(C::CholeskyPivoted, B::StridedMatrix)
436+
n = size(C, 1)
437+
for i in 1:size(B, 2)
438+
permute!(view(B, 1:n, i), C.piv)
439+
end
435440
if C.uplo == 'L'
436441
ldiv!(adjoint(LowerTriangular(C.factors)),
437-
ldiv!(LowerTriangular(C.factors), B[C.piv,:]))[invperm(C.piv),:]
442+
ldiv!(LowerTriangular(C.factors), B))
438443
else
439444
ldiv!(UpperTriangular(C.factors),
440-
ldiv!(adjoint(UpperTriangular(C.factors)), B[C.piv,:]))[invperm(C.piv),:]
445+
ldiv!(adjoint(UpperTriangular(C.factors)), B))
441446
end
447+
for i in 1:size(B, 2)
448+
invpermute!(view(B, 1:n, i), C.piv)
449+
end
450+
B
442451
end
443452

444453
isposdef(C::Union{Cholesky,CholeskyPivoted}) = C.info == 0

stdlib/LinearAlgebra/test/cholesky.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,31 @@ end
164164
lpapd = cholesky(apdhL, Val(true))
165165
@test norm(apd * (lpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit
166166
@test norm(apd * (lpapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n
167+
end
168+
end
169+
end
170+
171+
for eltyb in (Float64, ComplexF64)
172+
Breal = convert(Matrix{BigFloat}, randn(n,n)/2)
173+
Bimg = convert(Matrix{BigFloat}, randn(n,n)/2)
174+
B = (eltya <: Complex || eltyb <: Complex) ? complex.(Breal, Bimg) : Breal
175+
εb = eps(abs(float(one(eltyb))))
176+
ε = max(εa,εb)
177+
178+
for B in (B, view(B, 1:n, 1:n)) # Array and SubArray
167179

180+
# Test error bound on linear solver: LAWNS 14, Theorem 2.1
181+
# This is a surprisingly loose bound
182+
BB = copy(B)
183+
ldiv!(capd, BB)
184+
@test norm(apd \ B - BB, 1) / norm(BB, 1) <= (3n^2 + n + n^3*ε)*ε/(1-(n+1)*ε)*κ
185+
@test norm(apd * BB - B, 1) / norm(B, 1) <= (3n^2 + n + n^3*ε)*ε/(1-(n+1)*ε)*κ
186+
if eltya != BigFloat
187+
cpapd = cholesky(apdh, Val(true))
188+
BB = copy(B)
189+
ldiv!(cpapd, BB)
190+
@test norm(apd \ B - BB, 1) / norm(BB, 1) <= (3n^2 + n + n^3*ε)*ε/(1-(n+1)*ε)*κ
191+
@test norm(apd * BB - B, 1) / norm(B, 1) <= (3n^2 + n + n^3*ε)*ε/(1-(n+1)*ε)*κ
168192
end
169193
end
170194
end

0 commit comments

Comments
 (0)