Skip to content

Commit 9f754fd

Browse files
ElOceanografodkarrasch
authored andcommitted
Add logabsdet method for UmfpackLU (JuliaLang#40716)
Co-authored-by: Daniel Karrasch <[email protected]>
1 parent 4d0f94f commit 9f754fd

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

stdlib/SuiteSparse/src/umfpack.jl

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export UmfpackLU
66

77
import Base: (\), getproperty, show, size
88
using LinearAlgebra
9-
import LinearAlgebra: Factorization, det, lu, lu!, ldiv!
9+
import LinearAlgebra: Factorization, checksquare, det, logabsdet, lu, lu!, ldiv!
1010

1111
using SparseArrays
1212
using SparseArrays: getcolptr
@@ -279,6 +279,26 @@ function deserialize(s::AbstractSerializer, t::Type{UmfpackLU{Tv,Ti}}) where {Tv
279279
return obj
280280
end
281281

282+
# compute the sign/parity of a permutation
283+
function _signperm(p)
284+
n = length(p)
285+
result = 0
286+
todo = trues(n)
287+
while any(todo)
288+
k = findfirst(todo)
289+
todo[k] = false
290+
result += 1 # increment element count
291+
j = p[k]
292+
while j != k
293+
result += 1 # increment element count
294+
todo[j] = false
295+
j = p[j]
296+
end
297+
result += 1 # increment cycle count
298+
end
299+
return ifelse(isodd(result), -1, 1)
300+
end
301+
282302
## Wrappers for UMFPACK functions
283303

284304
# generate the name of the C function according to the value and integer types
@@ -406,6 +426,23 @@ for itype in UmfpackIndexTypes
406426
mx, mz, C_NULL, lu.numeric, umf_info)
407427
complex(mx[], mz[])
408428
end
429+
function logabsdet(F::UmfpackLU{T, $itype}) where {T<:Union{Float64,ComplexF64}} # return log(abs(det)) and sign(det)
430+
n = checksquare(F)
431+
issuccess(F) || return log(zero(real(T))), zero(T)
432+
U = F.U
433+
Rs = F.Rs
434+
p = F.p
435+
q = F.q
436+
s = _signperm(p)*_signperm(q)*one(real(T))
437+
P = one(T)
438+
abs_det = zero(real(T))
439+
@inbounds for i in 1:n
440+
dg_ii = U[i, i] / Rs[i]
441+
P *= sign(dg_ii)
442+
abs_det += log(abs(dg_ii))
443+
end
444+
return abs_det, s * P
445+
end
409446
function umf_lunz(lu::UmfpackLU{Float64,$itype})
410447
lnz = Ref{$itype}()
411448
unz = Ref{$itype}()

stdlib/SuiteSparse/test/umfpack.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ using SparseArrays: nnz, sparse, sprand, sprandn, SparseMatrixCSC
3434
@test Rs == lua.Rs
3535
@test (Diagonal(Rs) * A)[p,q] L * U
3636

37-
det(lua) det(Array(A))
37+
@test det(lua) det(Array(A))
38+
logdet_lua, sign_lua = logabsdet(lua)
39+
logdet_A, sign_A = logabsdet(Array(A))
40+
@test logdet_lua logdet_A
41+
@test sign_lua sign_A
3842

3943
b = [8., 45., -3., 3., 19.]
4044
x = lua\b

0 commit comments

Comments
 (0)