Skip to content

Commit e5da821

Browse files
authored
Add CHOLMOD error handler (JuliaLang#40589)
* Add CHOLMOD error handler * Remove some now-obsolete at-isok * Remove at-isok macro
1 parent e7a6805 commit e5da821

File tree

3 files changed

+56
-56
lines changed

3 files changed

+56
-56
lines changed

stdlib/SuiteSparse/src/cholmod.jl

Lines changed: 51 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ mutable struct Common
182182

183183
function Common()
184184
common = new()
185-
@isok ccall((@cholmod_name("start"), :libcholmod),
185+
ccall((@cholmod_name("start"), :libcholmod),
186186
Cint, (Ptr{Common},), common)
187187
finalizer(common) do common
188-
@isok ccall((@cholmod_name("finish"), :libcholmod),
189-
Cint, (Ptr{Common},), common)
188+
ccall((@cholmod_name("finish"), :libcholmod),
189+
Cint, (Ptr{Common},), common) == TRUE
190190
end
191191
end
192192
end
@@ -197,7 +197,7 @@ Base.unsafe_convert(::Type{Ptr{Common}},c::Common) =
197197
const common = Vector{Common}()
198198

199199
function defaults!(common)
200-
@isok ccall((@cholmod_name("defaults"), :libcholmod),
200+
ccall((@cholmod_name("defaults"), :libcholmod),
201201
Cint, (Ptr{Common},), common)
202202
return common
203203
end
@@ -274,9 +274,11 @@ function __init__()
274274
### to temporary memory. We need to manage a copy for each thread.
275275
nt = Threads.nthreads()
276276
resize!(common, nt)
277+
errorhandler = @cfunction(error_handler, Cvoid, (Cint, Cstring, Cint, Cstring))
277278
for i in 1:nt
278279
common[i] = Common()
279280
common[i].print = 0 # no printing from CHOLMOD by default
281+
common[i].error_handler = errorhandler
280282
end
281283

282284
# Register gc tracked allocator if CHOLMOD is new enough
@@ -518,9 +520,9 @@ function allocate_dense(m::Integer, n::Integer, d::Integer, ::Type{Tv}) where {T
518520
end
519521

520522
function free!(p::Ptr{C_Dense{Tv}}) where {Tv<:VTypes}
521-
@isok ccall((@cholmod_name("free_dense"), :libcholmod), Cint,
522-
(Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}),
523-
p, common[Threads.threadid()])
523+
ccall((@cholmod_name("free_dense"), :libcholmod), Cint,
524+
(Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}),
525+
p, common[Threads.threadid()]) == TRUE
524526
end
525527
function zeros(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes
526528
Dense(ccall((@cholmod_name("zeros"), :libcholmod), Ptr{C_Dense{Tv}},
@@ -551,9 +553,9 @@ function copy(A::Dense{Tv}) where Tv<:VTypes
551553
end
552554

553555
function sort!(S::Sparse{Tv}) where Tv<:VTypes
554-
@isok ccall((@cholmod_name("sort"), :libcholmod), Cint,
555-
(Ptr{C_Sparse{Tv}}, Ptr{Common}),
556-
S, common[Threads.threadid()])
556+
ccall((@cholmod_name("sort"), :libcholmod), Cint,
557+
(Ptr{C_Sparse{Tv}}, Ptr{Common}),
558+
S, common[Threads.threadid()])
557559
return S
558560
end
559561

@@ -592,16 +594,16 @@ function allocate_sparse(nrow::Integer, ncol::Integer, nzmax::Integer,
592594
end
593595

594596
function free!(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes
595-
@isok ccall((@cholmod_name("free_sparse"), :libcholmod), Cint,
596-
(Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}),
597-
ptr, common[Threads.threadid()])
597+
ccall((@cholmod_name("free_sparse"), :libcholmod), Cint,
598+
(Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}),
599+
ptr, common[Threads.threadid()]) == TRUE
598600
end
599601

600602
function free!(ptr::Ptr{C_Factor{Tv}}) where Tv<:VTypes
601603
# Warning! Important that finalizer doesn't modify the global Common struct.
602-
@isok ccall((@cholmod_name("free_factor"), :libcholmod), Cint,
603-
(Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}),
604-
ptr, common[Threads.threadid()])
604+
ccall((@cholmod_name("free_factor"), :libcholmod), Cint,
605+
(Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}),
606+
ptr, common[Threads.threadid()]) == TRUE
605607
end
606608

607609
function aat(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) where Tv<:VRealTypes
@@ -635,9 +637,9 @@ end
635637

636638
function change_factor!(F::Factor{Tv}, to_ll::Bool, to_super::Bool, to_packed::Bool,
637639
to_monotonic::Bool) where Tv<:VTypes
638-
@isok ccall((@cholmod_name("change_factor"),:libcholmod), Cint,
639-
(Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}),
640-
xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()])
640+
ccall((@cholmod_name("change_factor"),:libcholmod), Cint,
641+
(Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}),
642+
xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()]) == TRUE
641643
end
642644

643645
function check_sparse(A::Sparse{Tv}) where Tv<:VTypes
@@ -702,16 +704,16 @@ end
702704
function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes
703705
isascii(name) || error("non-ASCII name: $name")
704706
common[Threads.threadid()] = 3
705-
@isok ccall((@cholmod_name("print_sparse"),:libcholmod), Cint,
706-
(Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}),
707-
A, name, common[Threads.threadid()])
707+
ccall((@cholmod_name("print_sparse"),:libcholmod), Cint,
708+
(Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}),
709+
A, name, common[Threads.threadid()])
708710
nothing
709711
end
710712
function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes
711713
common[Threads.threadid()] = 3
712-
@isok ccall((@cholmod_name("print_factor"),:libcholmod), Cint,
713-
(Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}),
714-
F, name, common[Threads.threadid()])
714+
ccall((@cholmod_name("print_factor"),:libcholmod), Cint,
715+
(Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}),
716+
F, name, common[Threads.threadid()])
715717
nothing
716718
end
717719

@@ -771,9 +773,9 @@ function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealType
771773
end
772774

773775
sA = unsafe_load(pointer(A))
774-
@isok ccall((@cholmod_name("scale"),:libcholmod), Cint,
775-
(Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}),
776-
S, scale, A, common[Threads.threadid()])
776+
ccall((@cholmod_name("scale"),:libcholmod), Cint,
777+
(Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}),
778+
S, scale, A, common[Threads.threadid()])
777779
A
778780
end
779781

@@ -785,11 +787,11 @@ function sdmult!(A::Sparse{Tv}, transpose::Bool,
785787
if nc != size(X, 1)
786788
throw(DimensionMismatch("incompatible dimensions, $nc and $(size(X,1))"))
787789
end
788-
@isok ccall((@cholmod_name("sdmult"),:libcholmod), Cint,
789-
(Ptr{C_Sparse{Tv}}, Cint,
790-
Ref{ComplexF64}, Ref{ComplexF64},
791-
Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}),
792-
A, transpose, α, β, X, Y, common[Threads.threadid()])
790+
ccall((@cholmod_name("sdmult"),:libcholmod), Cint,
791+
(Ptr{C_Sparse{Tv}}, Cint,
792+
Ref{ComplexF64}, Ref{ComplexF64},
793+
Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}),
794+
A, transpose, α, β, X, Y, common[Threads.threadid()])
793795
Y
794796
end
795797

@@ -831,18 +833,18 @@ function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}) where Tv<:VTyp
831833
A, perm, C_NULL, 0, common[Threads.threadid()]))
832834
end
833835
function factorize!(A::Sparse{Tv}, F::Factor{Tv}) where Tv<:VTypes
834-
@isok ccall((@cholmod_name("factorize"),:libcholmod), Cint,
835-
(Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}),
836-
A, F, common[Threads.threadid()])
836+
ccall((@cholmod_name("factorize"),:libcholmod), Cint,
837+
(Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}),
838+
A, F, common[Threads.threadid()])
837839
F
838840
end
839841
function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}) where Tv<:VTypes
840842
# note that β is passed as a complex number (double beta[2]),
841843
# but the CHOLMOD manual says that only beta[0] (real part) is used
842-
@isok ccall((@cholmod_name("factorize_p"),:libcholmod), Cint,
843-
(Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t,
844-
Ptr{C_Factor{Tv}}, Ptr{Common}),
845-
A, β, C_NULL, 0, F, common[Threads.threadid()])
844+
ccall((@cholmod_name("factorize_p"),:libcholmod), Cint,
845+
(Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t,
846+
Ptr{C_Factor{Tv}}, Ptr{Common}),
847+
A, β, C_NULL, 0, F, common[Threads.threadid()])
846848
F
847849
end
848850

@@ -877,14 +879,10 @@ end
877879

878880
# Autodetects the types
879881
function read_sparse(file::Libc.FILE, ::Type{SuiteSparse_long})
880-
ptr = ccall((@cholmod_name("read_sparse"), :libcholmod),
881-
Ptr{C_Sparse{Cvoid}},
882-
(Ptr{Cvoid}, Ptr{Common}),
883-
file.ptr, common[Threads.threadid()])
884-
if ptr == C_NULL
885-
throw(ArgumentError("sparse matrix construction failed. Check that input file is valid."))
886-
end
887-
Sparse(ptr)
882+
Sparse(ccall((@cholmod_name("read_sparse"), :libcholmod),
883+
Ptr{C_Sparse{Cvoid}},
884+
(Ptr{Cvoid}, Ptr{Common}),
885+
file.ptr, common[Threads.threadid()]))
888886
end
889887

890888
function read_sparse(file::IO, T)
@@ -963,7 +961,7 @@ function Sparse(m::Integer, n::Integer,
963961
unsafe_copyto!(s.i, pointer(rowval0), colptr0[n + 1])
964962
unsafe_copyto!(s.x, pointer(nzval) , colptr0[n + 1])
965963

966-
@isok check_sparse(o)
964+
check_sparse(o)
967965

968966
return o
969967
end
@@ -1022,7 +1020,7 @@ function Sparse{Tv}(A::SparseMatrixCSC, stype::Integer) where Tv<:VTypes
10221020
end
10231021
end
10241022

1025-
@isok check_sparse(o)
1023+
check_sparse(o)
10261024

10271025
return o
10281026
end
@@ -1677,9 +1675,9 @@ function lowrankupdowndate!(F::Factor{Tv}, C::Sparse{Tv}, update::Cint) where Tv
16771675
if lF.n != lC.nrow
16781676
throw(DimensionMismatch("matrix dimensions do not fit"))
16791677
end
1680-
@isok ccall((@cholmod_name("updown"), :libcholmod), Cint,
1681-
(Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}),
1682-
update, C, F, common[Threads.threadid()])
1678+
ccall((@cholmod_name("updown"), :libcholmod), Cint,
1679+
(Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}),
1680+
update, C, F, common[Threads.threadid()])
16831681
F
16841682
end
16851683

stdlib/SuiteSparse/src/cholmod_h.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct CHOLMODException <: Exception
7474
msg::String
7575
end
7676

77-
macro isok(A)
78-
:($(esc(A)) == TRUE || throw(CHOLMODException("")))
77+
function error_handler(status::Cint, file::Cstring, line::Cint, message::Cstring)::Cvoid
78+
status < 0 && throw(CHOLMODException(unsafe_string(message)))
79+
nothing
7980
end

stdlib/SuiteSparse/test/cholmod.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,9 @@ end
238238
@test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5-0.5im;0 0.5+0.5im 1]
239239
rm(testfile)
240240

241+
# this also tests that the error message is correctly retrieved from the library
241242
writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","%3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"])
242-
@test_throws ArgumentError sparse(CHOLMOD.Sparse(testfile))
243+
@test_throws CHOLMOD.CHOLMODException("indices out of range") sparse(CHOLMOD.Sparse(testfile))
243244
rm(testfile)
244245
end
245246
end

0 commit comments

Comments
 (0)