diff --git a/deps/SuiteSparse_wrapper.c b/deps/SuiteSparse_wrapper.c index fc8b612d7671b..63204ac80a665 100644 --- a/deps/SuiteSparse_wrapper.c +++ b/deps/SuiteSparse_wrapper.c @@ -7,10 +7,6 @@ #include #include -extern size_t jl_cholmod_common_size(void) { - return sizeof(cholmod_common); -} - extern size_t jl_cholmod_sizeof_long(void) { return sizeof(SuiteSparse_long); } @@ -24,24 +20,137 @@ extern int jl_cholmod_version(int *ver) { return CHOLMOD_VERSION; } -extern void jl_cholmod_common_offsets(size_t *vv) { - vv[0] = offsetof(cholmod_common, dbound); - vv[1] = offsetof(cholmod_common, maxrank); - vv[2] = offsetof(cholmod_common, supernodal_switch); - vv[3] = offsetof(cholmod_common, supernodal); - vv[4] = offsetof(cholmod_common, final_asis); - vv[5] = offsetof(cholmod_common, final_super); - vv[6] = offsetof(cholmod_common, final_ll); - vv[7] = offsetof(cholmod_common, final_pack); - vv[8] = offsetof(cholmod_common, final_monotonic); - vv[9] = offsetof(cholmod_common, final_resymbol); - vv[10] = offsetof(cholmod_common, prefer_zomplex); - vv[11] = offsetof(cholmod_common, prefer_upper); - vv[12] = offsetof(cholmod_common, print); - vv[13] = offsetof(cholmod_common, precise); - vv[14] = offsetof(cholmod_common, nmethods); - vv[15] = offsetof(cholmod_common, selected); - vv[16] = offsetof(cholmod_common, postorder); - vv[17] = offsetof(cholmod_common, itype); - vv[18] = offsetof(cholmod_common, dtype); +// Keep this synchronized with https://github.com/JuliaLang/julia/blob/master/stdlib/SuiteSparse/src/cholmod.jl +extern void jl_cholmod_method_offsets(size_t *v) { + size_t offset = offsetof(cholmod_common, method[0]); + v[ 0] = offsetof(cholmod_common, method[0].lnz) - offset; + v[ 1] = offsetof(cholmod_common, method[0].fl) - offset; + v[ 2] = offsetof(cholmod_common, method[0].prune_dense) - offset; + v[ 3] = offsetof(cholmod_common, method[0].prune_dense2) - offset; + v[ 4] = offsetof(cholmod_common, method[0].nd_oksep) - offset; + v[ 5] = offsetof(cholmod_common, method[0].other_1) - offset; + v[ 6] = offsetof(cholmod_common, method[0].nd_small) - offset; + v[ 7] = offsetof(cholmod_common, method[0].other_2) - offset; + v[ 8] = offsetof(cholmod_common, method[0].aggressive) - offset; + v[ 9] = offsetof(cholmod_common, method[0].order_for_lu) - offset; + v[10] = offsetof(cholmod_common, method[0].nd_compress) - offset; + v[11] = offsetof(cholmod_common, method[0].nd_camd) - offset; + v[12] = offsetof(cholmod_common, method[0].nd_components) - offset; + v[13] = offsetof(cholmod_common, method[0].ordering) - offset; + v[14] = offsetof(cholmod_common, method[0].other_3) - offset; +} + +// Keep this synchronized with https://github.com/JuliaLang/julia/blob/master/stdlib/SuiteSparse/src/cholmod.jl +extern void jl_cholmod_common_offsets(size_t *v) { + v[ 0] = offsetof(cholmod_common, dbound); + v[ 1] = offsetof(cholmod_common, grow0); + v[ 2] = offsetof(cholmod_common, grow1); + v[ 3] = offsetof(cholmod_common, grow2); + v[ 4] = offsetof(cholmod_common, maxrank); + v[ 5] = offsetof(cholmod_common, supernodal_switch); + v[ 6] = offsetof(cholmod_common, supernodal); + v[ 7] = offsetof(cholmod_common, final_asis); + v[ 8] = offsetof(cholmod_common, final_super); + v[ 9] = offsetof(cholmod_common, final_ll); + v[ 10] = offsetof(cholmod_common, final_pack); + v[ 11] = offsetof(cholmod_common, final_monotonic); + v[ 12] = offsetof(cholmod_common, final_resymbol); + v[ 13] = offsetof(cholmod_common, zrelax); + v[ 14] = offsetof(cholmod_common, nrelax); + v[ 15] = offsetof(cholmod_common, prefer_zomplex); + v[ 16] = offsetof(cholmod_common, prefer_upper); + v[ 17] = offsetof(cholmod_common, quick_return_if_not_posdef); + v[ 18] = offsetof(cholmod_common, prefer_binary); + v[ 19] = offsetof(cholmod_common, print); + v[ 20] = offsetof(cholmod_common, precise); + v[ 21] = offsetof(cholmod_common, try_catch); + v[ 22] = offsetof(cholmod_common, error_handler); + v[ 23] = offsetof(cholmod_common, nmethods); + v[ 24] = offsetof(cholmod_common, current); + v[ 25] = offsetof(cholmod_common, selected); + v[ 26] = offsetof(cholmod_common, method); + v[ 27] = offsetof(cholmod_common, postorder); + v[ 28] = offsetof(cholmod_common, default_nesdis); + v[ 29] = offsetof(cholmod_common, metis_memory); + v[ 30] = offsetof(cholmod_common, metis_dswitch); + v[ 31] = offsetof(cholmod_common, metis_nswitch); + v[ 32] = offsetof(cholmod_common, nrow); + v[ 33] = offsetof(cholmod_common, mark); + v[ 34] = offsetof(cholmod_common, iworksize); + v[ 35] = offsetof(cholmod_common, xworksize); + v[ 36] = offsetof(cholmod_common, Flag); + v[ 37] = offsetof(cholmod_common, Head); + v[ 38] = offsetof(cholmod_common, Xwork); + v[ 39] = offsetof(cholmod_common, Iwork); + v[ 40] = offsetof(cholmod_common, itype); + v[ 41] = offsetof(cholmod_common, dtype); + v[ 42] = offsetof(cholmod_common, no_workspace_reallocate); + v[ 43] = offsetof(cholmod_common, status); + v[ 44] = offsetof(cholmod_common, fl); + v[ 45] = offsetof(cholmod_common, lnz); + v[ 46] = offsetof(cholmod_common, anz); + v[ 47] = offsetof(cholmod_common, modfl); + v[ 48] = offsetof(cholmod_common, malloc_count); + v[ 49] = offsetof(cholmod_common, memory_usage); + v[ 50] = offsetof(cholmod_common, memory_inuse); + v[ 51] = offsetof(cholmod_common, nrealloc_col); + v[ 52] = offsetof(cholmod_common, nrealloc_factor); + v[ 53] = offsetof(cholmod_common, ndbounds_hit); + v[ 54] = offsetof(cholmod_common, rowfacfl); + v[ 55] = offsetof(cholmod_common, aatfl); + v[ 56] = offsetof(cholmod_common, called_nd); + v[ 57] = offsetof(cholmod_common, blas_ok); + v[ 58] = offsetof(cholmod_common, SPQR_grain); + v[ 59] = offsetof(cholmod_common, SPQR_small); + v[ 60] = offsetof(cholmod_common, SPQR_shrink); + v[ 61] = offsetof(cholmod_common, SPQR_nthreads); + v[ 62] = offsetof(cholmod_common, SPQR_flopcount); + v[ 63] = offsetof(cholmod_common, SPQR_analyze_time); + v[ 64] = offsetof(cholmod_common, SPQR_factorize_time); + v[ 65] = offsetof(cholmod_common, SPQR_solve_time); + v[ 66] = offsetof(cholmod_common, SPQR_flopcount_bound); + v[ 67] = offsetof(cholmod_common, SPQR_tol_used); + v[ 68] = offsetof(cholmod_common, SPQR_norm_E_fro); + v[ 69] = offsetof(cholmod_common, SPQR_istat); + v[ 70] = offsetof(cholmod_common, useGPU); + v[ 71] = offsetof(cholmod_common, maxGpuMemBytes); + v[ 72] = offsetof(cholmod_common, maxGpuMemFraction); + v[ 73] = offsetof(cholmod_common, gpuMemorySize); + v[ 74] = offsetof(cholmod_common, gpuKernelTime); + v[ 75] = offsetof(cholmod_common, gpuFlops); + v[ 76] = offsetof(cholmod_common, gpuNumKernelLaunches); + v[ 77] = offsetof(cholmod_common, cublasHandle); + v[ 78] = offsetof(cholmod_common, gpuStream); + v[ 79] = offsetof(cholmod_common, cublasEventPotrf); + v[ 80] = offsetof(cholmod_common, updateCKernelsComplete); + v[ 81] = offsetof(cholmod_common, updateCBuffersFree); + v[ 82] = offsetof(cholmod_common, dev_mempool); + v[ 83] = offsetof(cholmod_common, dev_mempool_size); + v[ 84] = offsetof(cholmod_common, host_pinned_mempool); + v[ 85] = offsetof(cholmod_common, host_pinned_mempool_size); + v[ 86] = offsetof(cholmod_common, devBuffSize); + v[ 87] = offsetof(cholmod_common, ibuffer); + v[ 88] = offsetof(cholmod_common, syrkStart); + v[ 89] = offsetof(cholmod_common, cholmod_cpu_gemm_time); + v[ 90] = offsetof(cholmod_common, cholmod_cpu_syrk_time); + v[ 91] = offsetof(cholmod_common, cholmod_cpu_trsm_time); + v[ 92] = offsetof(cholmod_common, cholmod_cpu_potrf_time); + v[ 93] = offsetof(cholmod_common, cholmod_gpu_gemm_time); + v[ 94] = offsetof(cholmod_common, cholmod_gpu_syrk_time); + v[ 95] = offsetof(cholmod_common, cholmod_gpu_trsm_time); + v[ 96] = offsetof(cholmod_common, cholmod_gpu_potrf_time); + v[ 97] = offsetof(cholmod_common, cholmod_assemble_time); + v[ 98] = offsetof(cholmod_common, cholmod_assemble_time2); + v[ 99] = offsetof(cholmod_common, cholmod_cpu_gemm_calls); + v[100] = offsetof(cholmod_common, cholmod_cpu_syrk_calls); + v[101] = offsetof(cholmod_common, cholmod_cpu_trsm_calls); + v[102] = offsetof(cholmod_common, cholmod_cpu_potrf_calls); + v[103] = offsetof(cholmod_common, cholmod_gpu_gemm_calls); + v[104] = offsetof(cholmod_common, cholmod_gpu_syrk_calls); + v[105] = offsetof(cholmod_common, cholmod_gpu_trsm_calls); + v[106] = offsetof(cholmod_common, cholmod_gpu_potrf_calls); +} + +extern size_t jl_cholmod_common_size() { + return sizeof(cholmod_common); } diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index cbfee4a30cb41..ef14709eb076c 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -40,44 +40,166 @@ include("cholmod_h.jl") const CHOLMOD_MIN_VERSION = v"2.1.1" -const common_struct = Vector{Vector{UInt8}}() - -const common_supernodal = Vector{Ptr{Cint}}() -const common_final_ll = Vector{Ptr{Cint}}() -const common_print = Vector{Ptr{Cint}}() -const common_itype = Vector{Ptr{Cint}}() -const common_dtype = Vector{Ptr{Cint}}() -const common_nmethods = Vector{Ptr{Cint}}() -const common_postorder = Vector{Ptr{Cint}}() - -### These offsets are defined in SuiteSparse_wrapper.c -const common_size = ccall((:jl_cholmod_common_size,:libsuitesparse_wrapper),Int,()) - -const cholmod_com_offsets = Vector{Csize_t}(undef, 19) -ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), - Nothing, (Ptr{Csize_t},), cholmod_com_offsets) - ## macro to generate the name of the C function according to the integer type macro cholmod_name(nm) string("cholmod_l_", nm) end -function start(a::Vector{UInt8}) - @isok ccall((@cholmod_name("start"), :libcholmod), - Cint, (Ptr{UInt8},), a) - return a +# Julia copy of the cholmod_method_struct +# https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L655 +# Keep this synchronized with __init__() below and jl_cholmod_method_offsets in +# https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c +struct Method + lnz::Cdouble + fl::Cdouble + prune_dense::Cdouble + prune_dense2::Cdouble + nd_oksep::Cdouble + other_1::NTuple{4,Cdouble} + nd_small::Csize_t + other_2::NTuple{4,Csize_t} + aggressive::Cint + order_for_lu::Cint + nd_compress::Cint + nd_camd::Cint + nd_components::Cint + ordering::Cint + other_3::NTuple{4,Csize_t} +end + +# Julia copy of the cholmod_common_struct +# https://github.com/DrTimothyAldenDavis/SuiteSparse/blob/master/CHOLMOD/Include/cholmod_core.h#L414 +# Keep this synchronized with __init__() below and jl_cholmod_common_offsets in +# https://github.com/JuliaLang/julia/blob/master/deps/SuiteSparse_wrapper.c +mutable struct Common + dbound::Cdouble + grow0::Cdouble + grow1::Cdouble + grow2::Csize_t + maxrank::Csize_t + supernodal_switch::Cdouble + supernodal::Cint + final_asis::Cint + final_super::Cint + final_ll::Cint + final_pack::Cint + final_monotonic::Cint + final_resymbol::Cint + zrelax::NTuple{3,Cdouble} + nrelax::NTuple{3,Csize_t} + prefer_zomplex::Cint + prefer_upper::Cint + quick_return_if_not_posdef::Cint + prefer_binary::Cint + print::Cint + precise::Cint + try_catch::Cint + error_handler::Ptr{Nothing} + nmethods::Cint + current::Cint + selected::Cint + method::NTuple{10,Method} + postorder::Cint + default_nesdis::Cint + metis_memory::Cdouble + metis_dswitch::Cdouble + metis_nswitch::Csize_t + nrow::Csize_t + mark::SuiteSparse_long + iworksize::Csize_t + xworksize::Csize_t + Flag::Ptr{Nothing} + Head::Ptr{Nothing} + Xwork::Ptr{Nothing} + Iwork::Ptr{Nothing} + itype::Cint + dtype::Cint + no_workspace_reallocate::Cint + status::Cint + fl::Cdouble + lnz::Cdouble + anz::Cdouble + modfl::Cdouble + malloc_count::Csize_t + memory_usage::Csize_t + memory_inuse::Csize_t + nrealloc_col::Cdouble + nrealloc_factor::Cdouble + ndbounds_hit::Cdouble + rowfacfl::Cdouble + aatfl::Cdouble + called_nd::Cint + blas_ok::Cint + SPQR_grain::Cdouble + SPQR_small::Cdouble + SPQR_shrink::Cint + SPQR_nthreads::Cint + SPQR_flopcount::Cdouble + SPQR_analyze_time::Cdouble + SPQR_factorize_time::Cdouble + SPQR_solve_time::Cdouble + SPQR_flopcount_bound::Cdouble + SPQR_tol_used::Cdouble + SPQR_norm_E_fro::Cdouble + SPQR_istat::NTuple{10,SuiteSparse_long} + useGPU::Cint + maxGpuMemBytes::Csize_t + maxGpuMemFraction::Cdouble + gpuMemorySize::Csize_t + gpuKernelTime::Cdouble + gpuFlops::SuiteSparse_long + gpuNumKernelLaunches::Cint + cublasHandle::Ptr{Nothing} + gpuStream::NTuple{8,Ptr{Nothing}} + cublasEventPotrf::NTuple{3,Ptr{Nothing}} + updateCKernelsComplete::Ptr{Nothing} + updateCBuffersFree::NTuple{8,Ptr{Nothing}} + dev_mempool::Ptr{Nothing} + dev_mempool_size::Csize_t + host_pinned_mempool::Ptr{Nothing} + host_pinned_mempool_size::Csize_t + devBuffSize::Csize_t + ibuffer::Cint + syrkStart::Cdouble + cholmod_cpu_gemm_time::Cdouble + cholmod_cpu_syrk_time::Cdouble + cholmod_cpu_trsm_time::Cdouble + cholmod_cpu_potrf_time::Cdouble + cholmod_gpu_gemm_time::Cdouble + cholmod_gpu_syrk_time::Cdouble + cholmod_gpu_trsm_time::Cdouble + cholmod_gpu_potrf_time::Cdouble + cholmod_assemble_time::Cdouble + cholmod_assemble_time2::Cdouble + cholmod_cpu_gemm_calls::Csize_t + cholmod_cpu_syrk_calls::Csize_t + cholmod_cpu_trsm_calls::Csize_t + cholmod_cpu_potrf_calls::Csize_t + cholmod_gpu_gemm_calls::Csize_t + cholmod_gpu_syrk_calls::Csize_t + cholmod_gpu_trsm_calls::Csize_t + cholmod_gpu_potrf_calls::Csize_t + + function Common() + common = new() + @isok ccall((@cholmod_name("start"), :libcholmod), + Cint, (Ptr{Common},), common) + finalizer(common) do common + @isok ccall((@cholmod_name("finish"), :libcholmod), + Cint, (Ptr{Common},), common) + end + end end -function finish(a::Vector{UInt8}) - @isok ccall((@cholmod_name("finish"), :libcholmod), - Cint, (Ptr{UInt8},), a) - return a -end +Base.unsafe_convert(::Type{Ptr{Common}},c::Common) = + reinterpret(Ptr{Common}, pointer_from_objref(c)) + +const common = Vector{Common}() -function defaults(a::Vector{UInt8}) +function defaults!(common) @isok ccall((@cholmod_name("defaults"), :libcholmod), - Cint, (Ptr{UInt8},), a) - return a + Cint, (Ptr{Common},), common) + return common end const build_version_array = Vector{Cint}(undef, 3) @@ -111,7 +233,7 @@ function __init__() from www.julialang.org, which ship with the correct versions of all dependencies. """ - elseif build_version_array[1] != current_version_array[1] + elseif build_version != current_version @warn """ CHOLMOD version incompatibility @@ -148,30 +270,13 @@ function __init__() end ### Initiate CHOLMOD - ### common_struct controls the type of factorization and keeps pointers + ### common controls the type of factorization and keeps pointers ### to temporary memory. We need to manage a copy for each thread. nt = Threads.nthreads() - resize!(common_struct , nt) - resize!(common_supernodal, nt) - resize!(common_final_ll , nt) - resize!(common_print , nt) - resize!(common_itype , nt) - resize!(common_dtype , nt) - resize!(common_nmethods , nt) - resize!(common_postorder , nt) + resize!(common, nt) for i in 1:nt - common_struct[i] = fill(0xff, common_size) - - common_supernodal[i] = pointer(common_struct[i], cholmod_com_offsets[4] + 1) - common_final_ll[i] = pointer(common_struct[i], cholmod_com_offsets[7] + 1) - common_print[i] = pointer(common_struct[i], cholmod_com_offsets[13] + 1) - common_itype[i] = pointer(common_struct[i], cholmod_com_offsets[18] + 1) - common_dtype[i] = pointer(common_struct[i], cholmod_com_offsets[19] + 1) - common_nmethods[i] = pointer(common_struct[i], cholmod_com_offsets[15] + 1) - common_postorder[i] = pointer(common_struct[i], cholmod_com_offsets[17] + 1) - - start(common_struct[i]) # initializes CHOLMOD - set_print_level(common_struct[i], 0) # no printing from CHOLMOD by default + common[i] = Common() + common[i].print = 0 # no printing from CHOLMOD by default end # Register gc tracked allocator if CHOLMOD is new enough @@ -188,10 +293,6 @@ function __init__() end end -function set_print_level(cm::Vector{UInt8}, lev::Integer) - unsafe_store!(common_print[Threads.threadid()], lev) -end - #################### # Type definitions # #################### @@ -412,47 +513,47 @@ Factor(FC::FactorComponent) = Factor(FC.F) ### cholmod_core_h ### function allocate_dense(m::Integer, n::Integer, d::Integer, ::Type{Tv}) where {Tv<:VTypes} Dense(ccall((@cholmod_name("allocate_dense"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, Ptr{Cvoid}), - m, n, d, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, d, xtyp(Tv), common[Threads.threadid()])) end function free!(p::Ptr{C_Dense{Tv}}) where {Tv<:VTypes} @isok ccall((@cholmod_name("free_dense"), :libcholmod), Cint, - (Ref{Ptr{C_Dense{Tv}}}, Ptr{Cvoid}), - p, common_struct[Threads.threadid()]) + (Ref{Ptr{C_Dense{Tv}}}, Ptr{Common}), + p, common[Threads.threadid()]) end function zeros(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("zeros"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end zeros(m::Integer, n::Integer) = zeros(m, n, Float64) function ones(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("ones"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end ones(m::Integer, n::Integer) = ones(m, n, Float64) function eye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("eye"), :libcholmod), Ptr{C_Dense{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end eye(m::Integer, n::Integer) = eye(m, n, Float64) eye(n::Integer) = eye(n, n, Float64) function copy(A::Dense{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("copy_dense"), :libcholmod), Ptr{C_Dense{Tv}}, - (Ptr{C_Dense{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()])) + (Ptr{C_Dense{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end function sort!(S::Sparse{Tv}) where Tv<:VTypes @isok ccall((@cholmod_name("sort"), :libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - S, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + S, common[Threads.threadid()]) return S end @@ -467,15 +568,15 @@ function norm_dense(D::Dense{Tv}, p::Integer) where Tv<:VTypes throw(ArgumentError("second argument must be either 0 (Inf norm), 1, or 2")) end ccall((@cholmod_name("norm_dense"), :libcholmod), Cdouble, - (Ptr{C_Dense{Tv}}, Cint, Ptr{UInt8}), - D, p, common_struct[Threads.threadid()]) + (Ptr{C_Dense{Tv}}, Cint, Ptr{Common}), + D, p, common[Threads.threadid()]) end ### cholmod_check.h ### function check_dense(A::Dense{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_dense"), :libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Ptr{UInt8}), - pointer(A), common_struct[Threads.threadid()]) != 0 + (Ptr{C_Dense{Tv}}, Ptr{Common}), + pointer(A), common[Threads.threadid()]) != 0 end # Non-Dense wrappers @@ -485,42 +586,42 @@ function allocate_sparse(nrow::Integer, ncol::Integer, nzmax::Integer, Sparse(ccall((@cholmod_name("allocate_sparse"), :libcholmod), Ptr{C_Sparse{Tv}}, (Csize_t, Csize_t, Csize_t, Cint, - Cint, Cint, Cint, Ptr{Cvoid}), + Cint, Cint, Cint, Ptr{Common}), nrow, ncol, nzmax, sorted, - packed, stype, xtyp(Tv), common_struct[Threads.threadid()])) + packed, stype, xtyp(Tv), common[Threads.threadid()])) end function free!(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes @isok ccall((@cholmod_name("free_sparse"), :libcholmod), Cint, - (Ref{Ptr{C_Sparse{Tv}}}, Ptr{UInt8}), - ptr, common_struct[Threads.threadid()]) + (Ref{Ptr{C_Sparse{Tv}}}, Ptr{Common}), + ptr, common[Threads.threadid()]) end function free!(ptr::Ptr{C_Factor{Tv}}) where Tv<:VTypes # Warning! Important that finalizer doesn't modify the global Common struct. @isok ccall((@cholmod_name("free_factor"), :libcholmod), Cint, - (Ref{Ptr{C_Factor{Tv}}}, Ptr{Cvoid}), - ptr, common_struct[Threads.threadid()]) + (Ref{Ptr{C_Factor{Tv}}}, Ptr{Common}), + ptr, common[Threads.threadid()]) end function aat(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("aat"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Csize_t, Cint, Ptr{UInt8}), - A, fset, length(fset), mode, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Csize_t, Cint, Ptr{Common}), + A, fset, length(fset), mode, common[Threads.threadid()])) end function sparse_to_dense(A::Sparse{Tv}) where Tv<:VTypes Dense(ccall((@cholmod_name("sparse_to_dense"),:libcholmod), Ptr{C_Dense{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end function dense_to_sparse(D::Dense{Tv}, ::Type{SuiteSparse_long}) where Tv<:VTypes Sparse(ccall((@cholmod_name("dense_to_sparse"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Dense{Tv}}, Cint, Ptr{UInt8}), - D, true, common_struct[Threads.threadid()])) + (Ptr{C_Dense{Tv}}, Cint, Ptr{Common}), + D, true, common[Threads.threadid()])) end function factor_to_sparse!(F::Factor{Tv}) where Tv<:VTypes @@ -528,89 +629,89 @@ function factor_to_sparse!(F::Factor{Tv}) where Tv<:VTypes ss.xtype == PATTERN && throw(CHOLMODException("only numeric factors are supported")) Sparse(ccall((@cholmod_name("factor_to_sparse"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}), - F, common_struct[Threads.threadid()])) + (Ptr{C_Factor{Tv}}, Ptr{Common}), + F, common[Threads.threadid()])) end function change_factor!(F::Factor{Tv}, to_ll::Bool, to_super::Bool, to_packed::Bool, to_monotonic::Bool) where Tv<:VTypes @isok ccall((@cholmod_name("change_factor"),:libcholmod), Cint, - (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{UInt8}), - xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common_struct[Threads.threadid()]) + (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{Common}), + xtyp(Tv), to_ll, to_super, to_packed, to_monotonic, F, common[Threads.threadid()]) end function check_sparse(A::Sparse{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()]) != 0 + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()]) != 0 end function check_factor(F::Factor{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}), - F, common_struct[Threads.threadid()]) != 0 + (Ptr{C_Factor{Tv}}, Ptr{Common}), + F, common[Threads.threadid()]) != 0 end function nnz(A::Sparse{Tv}) where Tv<:VTypes ccall((@cholmod_name("nnz"),:libcholmod), Int, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()]) end function speye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes Sparse(ccall((@cholmod_name("speye"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, xtyp(Tv), common[Threads.threadid()])) end function spzeros(m::Integer, n::Integer, nzmax::Integer, ::Type{Tv}) where Tv<:VTypes Sparse(ccall((@cholmod_name("spzeros"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Csize_t, Csize_t, Csize_t, Cint, Ptr{UInt8}), - m, n, nzmax, xtyp(Tv), common_struct[Threads.threadid()])) + (Csize_t, Csize_t, Csize_t, Cint, Ptr{Common}), + m, n, nzmax, xtyp(Tv), common[Threads.threadid()])) end function transpose_(A::Sparse{Tv}, values::Integer) where Tv<:VTypes Sparse(ccall((@cholmod_name("transpose"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, values, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, values, common[Threads.threadid()])) end function copy(F::Factor{Tv}) where Tv<:VTypes Factor(ccall((@cholmod_name("copy_factor"),:libcholmod), Ptr{C_Factor{Tv}}, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}), - F, common_struct[Threads.threadid()])) + (Ptr{C_Factor{Tv}}, Ptr{Common}), + F, common[Threads.threadid()])) end function copy(A::Sparse{Tv}) where Tv<:VTypes Sparse(ccall((@cholmod_name("copy_sparse"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end function copy(A::Sparse{Tv}, stype::Integer, mode::Integer) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("copy"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Cint, Cint, Ptr{UInt8}), - A, stype, mode, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Cint, Cint, Ptr{Common}), + A, stype, mode, common[Threads.threadid()])) end ### cholmod_check.h ### function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes isascii(name) || error("non-ASCII name: $name") - set_print_level(common_struct[Threads.threadid()], 3) + common[Threads.threadid()] = 3 @isok ccall((@cholmod_name("print_sparse"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{UInt8}), - A, name, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Ptr{UInt8}, Ptr{Common}), + A, name, common[Threads.threadid()]) nothing end function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes - set_print_level(common_struct[Threads.threadid()], 3) + common[Threads.threadid()] = 3 @isok ccall((@cholmod_name("print_factor"),:libcholmod), Cint, - (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{UInt8}), - F, name, common_struct[Threads.threadid()]) + (Ptr{C_Factor{Tv}}, Ptr{UInt8}, Ptr{Common}), + F, name, common[Threads.threadid()]) nothing end @@ -625,9 +726,9 @@ function ssmult(A::Sparse{Tv}, B::Sparse{Tv}, stype::Integer, Sparse(ccall((@cholmod_name("ssmult"),:libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Cint, - Cint, Ptr{UInt8}), + Cint, Ptr{Common}), A, B, stype, values, - sorted, common_struct[Threads.threadid()])) + sorted, common[Threads.threadid()])) end function norm_sparse(A::Sparse{Tv}, norm::Integer) where Tv<:VTypes @@ -635,15 +736,15 @@ function norm_sparse(A::Sparse{Tv}, norm::Integer) where Tv<:VTypes throw(ArgumentError("norm argument must be either 0 or 1")) end ccall((@cholmod_name("norm_sparse"), :libcholmod), Cdouble, - (Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, norm, common_struct[Threads.threadid()]) + (Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, norm, common[Threads.threadid()]) end function horzcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("horzcat"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, B, values, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, B, values, common[Threads.threadid()])) end function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealTypes @@ -671,8 +772,8 @@ function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealType sA = unsafe_load(pointer(A)) @isok ccall((@cholmod_name("scale"),:libcholmod), Cint, - (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - S, scale, A, common_struct[Threads.threadid()]) + (Ptr{C_Dense{Tv}}, Cint, Ptr{C_Sparse{Tv}}, Ptr{Common}), + S, scale, A, common[Threads.threadid()]) A end @@ -687,16 +788,16 @@ function sdmult!(A::Sparse{Tv}, transpose::Bool, @isok ccall((@cholmod_name("sdmult"),:libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Cint, Ref{ComplexF64}, Ref{ComplexF64}, - Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{UInt8}), - A, transpose, α, β, X, Y, common_struct[Threads.threadid()]) + Ptr{C_Dense{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), + A, transpose, α, β, X, Y, common[Threads.threadid()]) Y end function vertcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes Sparse(ccall((@cholmod_name("vertcat"), :libcholmod), Ptr{C_Sparse{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), - A, B, values, common_struct[Threads.threadid()])) + (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{Common}), + A, B, values, common[Threads.threadid()])) end function symmetry(A::Sparse{Tv}, option::Integer) where Tv<:VTypes @@ -706,43 +807,42 @@ function symmetry(A::Sparse{Tv}, option::Integer) where Tv<:VTypes nzdiag = Ref{SuiteSparse_long}() rv = ccall((@cholmod_name("symmetry"), :libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Cint, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, - Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{UInt8}), + Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{Common}), A, option, xmatched, pmatched, - nzoffdiag, nzdiag, common_struct[Threads.threadid()]) + nzoffdiag, nzdiag, common[Threads.threadid()]) rv, xmatched[], pmatched[], nzoffdiag[], nzdiag[] end # cholmod_cholesky.h # For analyze, analyze_p, and factorize_p!, the Common argument must be # supplied in order to control if the factorization is LLt or LDLt -function analyze(A::Sparse{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes +function analyze(A::Sparse{Tv}) where Tv<:VTypes Factor(ccall((@cholmod_name("analyze"),:libcholmod), Ptr{C_Factor{Tv}}, - (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - A, cmmn)) + (Ptr{C_Sparse{Tv}}, Ptr{Common}), + A, common[Threads.threadid()])) end -function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}, - cmmn::Vector{UInt8}) where Tv<:VTypes +function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}) where Tv<:VTypes length(perm) != size(A,1) && throw(BoundsError()) Factor(ccall((@cholmod_name("analyze_p"),:libcholmod), Ptr{C_Factor{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, - Csize_t, Ptr{UInt8}), - A, perm, C_NULL, 0, cmmn)) + Csize_t, Ptr{Common}), + A, perm, C_NULL, 0, common[Threads.threadid()])) end -function factorize!(A::Sparse{Tv}, F::Factor{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes +function factorize!(A::Sparse{Tv}, F::Factor{Tv}) where Tv<:VTypes @isok ccall((@cholmod_name("factorize"),:libcholmod), Cint, - (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{UInt8}), - A, F, cmmn) + (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), + A, F, common[Threads.threadid()]) F end -function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes +function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}) where Tv<:VTypes # note that β is passed as a complex number (double beta[2]), # but the CHOLMOD manual says that only beta[0] (real part) is used @isok ccall((@cholmod_name("factorize_p"),:libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Ref{ComplexF64}, Ptr{SuiteSparse_long}, Csize_t, - Ptr{C_Factor{Tv}}, Ptr{UInt8}), - A, β, C_NULL, 0, F, cmmn) + Ptr{C_Factor{Tv}}, Ptr{Common}), + A, β, C_NULL, 0, F, common[Threads.threadid()]) F end @@ -760,8 +860,8 @@ function solve(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) where Tv<:VTypes end end Dense(ccall((@cholmod_name("solve"),:libcholmod), Ptr{C_Dense{Tv}}, - (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Dense{Tv}}, Ptr{UInt8}), - sys, F, B, common_struct[Threads.threadid()])) + (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Dense{Tv}}, Ptr{Common}), + sys, F, B, common[Threads.threadid()])) end function spsolve(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) where Tv<:VTypes @@ -771,16 +871,16 @@ function spsolve(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) where Tv<:VTypes end Sparse(ccall((@cholmod_name("spsolve"),:libcholmod), Ptr{C_Sparse{Tv}}, - (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Sparse{Tv}}, Ptr{UInt8}), - sys, F, B, common_struct[Threads.threadid()])) + (Cint, Ptr{C_Factor{Tv}}, Ptr{C_Sparse{Tv}}, Ptr{Common}), + sys, F, B, common[Threads.threadid()])) end # Autodetects the types function read_sparse(file::Libc.FILE, ::Type{SuiteSparse_long}) ptr = ccall((@cholmod_name("read_sparse"), :libcholmod), Ptr{C_Sparse{Cvoid}}, - (Ptr{Cvoid}, Ptr{UInt8}), - file.ptr, common_struct[Threads.threadid()]) + (Ptr{Cvoid}, Ptr{Common}), + file.ptr, common[Threads.threadid()]) if ptr == C_NULL throw(ArgumentError("sparse matrix construction failed. Check that input file is valid.")) end @@ -1274,24 +1374,22 @@ end ## Factorization methods ## Compute that symbolic factorization only -function fact_(A::Sparse{<:VTypes}, cm::Array{UInt8}; +function fact_(A::Sparse{<:VTypes}; perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing, postorder::Bool=true, userperm_only::Bool=true) sA = unsafe_load(pointer(A)) sA.stype == 0 && throw(ArgumentError("sparse matrix is not symmetric/Hermitian")) - if !postorder - unsafe_store!(common_postorder[Threads.threadid()], 0) - end + common[Threads.threadid()].postorder = postorder if perm === nothing || isempty(perm) # TODO: deprecate empty perm - F = analyze(A, cm) + F = analyze(A) else # user permutation provided if userperm_only # use perm even if it is worse than AMD - unsafe_store!(common_nmethods[Threads.threadid()], 1) + common[Threads.threadid()].nmethods = 1 end - F = analyze_p(A, SuiteSparse_long[p-1 for p in perm], cm) + F = analyze_p(A, SuiteSparse_long[p-1 for p in perm]) end return F @@ -1300,10 +1398,10 @@ end function cholesky!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0, check::Bool = true) where Tv # Makes it an LLt - unsafe_store!(common_final_ll[Threads.threadid()], 1) + common[Threads.threadid()].final_ll = true # Compute the numerical factorization - factorize_p!(A, shift, F, common_struct[Threads.threadid()]) + factorize_p!(A, shift, F) check && (issuccess(F) || throw(LinearAlgebra.PosDefException(1))) return F @@ -1336,11 +1434,11 @@ cholesky!(F::Factor, A::Union{SparseMatrixCSC{T}, function cholesky(A::Sparse; shift::Real=0.0, check::Bool = true, perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - cm = defaults(common_struct[Threads.threadid()]) - set_print_level(cm, 0) + cm = defaults!(common[Threads.threadid()]) + cm.print = 0 # Compute the symbolic factorization - F = fact_(A, cm; perm = perm) + F = fact_(A; perm = perm) # Compute the numerical factorization cholesky!(F, A; shift = shift, check = check) @@ -1460,14 +1558,14 @@ cholesky(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, function ldlt!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0, check::Bool = true) where Tv - cm = defaults(common_struct[Threads.threadid()]) - set_print_level(cm, 0) + cm = defaults!(common[Threads.threadid()]) + cm.print = 0 # Makes it an LDLt change_factor!(F, false, false, true, false) # Compute the numerical factorization - factorize_p!(A, shift, F, cm) + factorize_p!(A, shift, F) check && (issuccess(F) || throw(LinearAlgebra.ZeroPivotException(1))) return F @@ -1500,16 +1598,16 @@ ldlt!(F::Factor, A::Union{SparseMatrixCSC{T}, function ldlt(A::Sparse; shift::Real=0.0, check::Bool = true, perm::Union{Nothing,AbstractVector{SuiteSparse_long}}=nothing) - cm = defaults(common_struct[Threads.threadid()]) - set_print_level(cm, 0) + cm = defaults!(common[Threads.threadid()]) + cm.print = 0 # Makes it an LDLt - unsafe_store!(common_final_ll[Threads.threadid()], 0) + cm.final_ll = false # Really make sure it's an LDLt by avoiding supernodal factorization - unsafe_store!(common_supernodal[Threads.threadid()], 0) + cm.supernodal = 0 # Compute the symbolic factorization - F = fact_(A, cm; perm = perm) + F = fact_(A; perm = perm) # Compute the numerical factorization ldlt!(F, A; shift = shift, check = check) @@ -1580,8 +1678,8 @@ function lowrankupdowndate!(F::Factor{Tv}, C::Sparse{Tv}, update::Cint) where Tv throw(DimensionMismatch("matrix dimensions do not fit")) end @isok ccall((@cholmod_name("updown"), :libcholmod), Cint, - (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Cvoid}), - update, C, F, common_struct[Threads.threadid()]) + (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Common}), + update, C, F, common[Threads.threadid()]) F end diff --git a/stdlib/SuiteSparse/src/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl index e94fa73994d03..0cb0d470fc897 100644 --- a/stdlib/SuiteSparse/src/spqr.jl +++ b/stdlib/SuiteSparse/src/spqr.jl @@ -52,7 +52,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, Ptr{CHOLMOD.C_Sparse{Tv}}, Ptr{CHOLMOD.C_Sparse{Tv}}, Ptr{CHOLMOD.C_Dense{Tv}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.SuiteSparse_long}}, Ptr{Ptr{CHOLMOD.C_Sparse{Tv}}}, Ptr{Ptr{CHOLMOD.SuiteSparse_long}}, - Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{Cvoid}), + Ptr{Ptr{CHOLMOD.C_Dense{Tv}}}, Ptr{CHOLMOD.Common}), ordering, # all, except 3:given treated as 0:fixed tol, # columns with 2-norm <= tol treated as 0 econ, # e = max(min(m,econ),rank(A)) @@ -68,7 +68,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, H, # m-by-nh Householder vectors HPinv, # size m row permutation HTau, # 1-by-nh Householder coefficients - CHOLMOD.common_struct[Threads.threadid()]) # /* workspace and parameters */ + CHOLMOD.common[Threads.threadid()]) # /* workspace and parameters */ if rnk < 0 error("Sparse QR factorization failed") @@ -86,8 +86,8 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, # correct deallocator function is called and that the memory count in # the common struct is updated ccall((:cholmod_l_free, :libcholmod), Cvoid, - (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{Cvoid}), - n, sizeof(CHOLMOD.SuiteSparse_long), e, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{CHOLMOD.Common}), + n, sizeof(CHOLMOD.SuiteSparse_long), e, CHOLMOD.common[Threads.threadid()]) end hpinv = HPinv[] if hpinv == C_NULL @@ -101,8 +101,8 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, # correct deallocator function is called and that the memory count in # the common struct is updated ccall((:cholmod_l_free, :libcholmod), Cvoid, - (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{Cvoid}), - m, sizeof(CHOLMOD.SuiteSparse_long), hpinv, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Cint, Ptr{CHOLMOD.SuiteSparse_long}, Ptr{CHOLMOD.Common}), + m, sizeof(CHOLMOD.SuiteSparse_long), hpinv, CHOLMOD.common[Threads.threadid()]) end return rnk, _E, _HPinv diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index 020c7129cc56f..b0230f97eae2e 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -16,6 +16,21 @@ using SparseArrays: getcolptr # CHOLMOD tests Random.seed!(123) +@testset "Check that the Common and Method Julia structs are consistent with their C counterparts" begin + common_size = ccall((:jl_cholmod_common_size, :libsuitesparse_wrapper), Csize_t, ()) + @test common_size == sizeof(CHOLMOD.Common) + + method_offsets = Vector{Csize_t}(undef,15) + ccall((:jl_cholmod_method_offsets, :libsuitesparse_wrapper), + Nothing, (Ptr{Csize_t},), method_offsets) + @test method_offsets == fieldoffset.(CHOLMOD.Method,1:length(method_offsets)) + + common_offsets = Vector{Csize_t}(undef,107) + ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), + Nothing, (Ptr{Csize_t},), common_offsets) + @test common_offsets == fieldoffset.(CHOLMOD.Common,1:length(common_offsets)) +end + @testset "based on deps/SuiteSparse-4.0.2/CHOLMOD/Demo/" begin # chm_rdsp(joinpath(Sys.BINDIR, "../../deps/SuiteSparse-4.0.2/CHOLMOD/Demo/Matrix/bcsstk01.tri")) @@ -237,8 +252,8 @@ end ## The struct pointer must be constructed by the library constructor and then modified afterwards to checks that the method throws @testset "illegal dtype (for now but should be supported at some point)" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, CHOLMOD.SINGLE, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 4) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -246,8 +261,8 @@ end @testset "illegal dtype" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, 5, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 4) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -255,8 +270,8 @@ end @testset "illegal xtype" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, 3, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 3) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -264,8 +279,8 @@ end @testset "illegal itype I" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, CHOLMOD.INTLONG, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 2) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -273,8 +288,8 @@ end @testset "illegal itype II" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Cvoid}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) puint = convert(Ptr{UInt32}, p) unsafe_store!(puint, 5, 3*div(sizeof(Csize_t), 4) + 5*div(sizeof(Ptr{Cvoid}), 4) + 2) @test_throws CHOLMOD.CHOLMODException CHOLMOD.Sparse(p) @@ -324,8 +339,8 @@ end # Test Sparse and Factor @testset "test free!" begin p = ccall((:cholmod_l_allocate_sparse, :libcholmod), Ptr{CHOLMOD.C_Sparse{Float64}}, - (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{Cvoid}), - 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common_struct[Threads.threadid()]) + (Csize_t, Csize_t, Csize_t, Cint, Cint, Cint, Cint, Ptr{CHOLMOD.Common}), + 1, 1, 1, true, true, 0, CHOLMOD.REAL, CHOLMOD.common[Threads.threadid()]) @test CHOLMOD.free!(p) end diff --git a/stdlib/SuiteSparse_jll/Project.toml b/stdlib/SuiteSparse_jll/Project.toml index 6b704c4bf1112..436f919a60976 100644 --- a/stdlib/SuiteSparse_jll/Project.toml +++ b/stdlib/SuiteSparse_jll/Project.toml @@ -1,6 +1,6 @@ name = "SuiteSparse_jll" uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.8.1+0" +version = "5.8.1+2" [deps] libblastrampoline_jll = "8e850b90-86db-534c-a0d3-1478176c7d93"