From f00d217f230f8bd4a77cee0437ad175a8eb67712 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sat, 18 Nov 2017 20:45:36 -0500 Subject: [PATCH] Move SuiteSparse to stdlib Remove CHOLMOD stuff from precompile.jl Move unexported SparseArrays increment and decrement APIs to SuiteSparse Update SuiteSparse tests Add license text to new files. --- base/precompile.jl | 3 -- base/sparse/linalg.jl | 16 ---------- base/sparse/sparse.jl | 6 ---- base/sysimg.jl | 1 + doc/src/manual/linear-algebra.md | 1 - stdlib/SuiteSparse/src/SuiteSparse.jl | 30 +++++++++++++++++++ .../SuiteSparse/src}/cholmod.jl | 5 ++-- .../SuiteSparse/src}/cholmod_h.jl | 0 .../sparse => stdlib/SuiteSparse/src}/spqr.jl | 4 +-- .../SuiteSparse/src}/umfpack.jl | 4 ++- .../SuiteSparse/src}/umfpack_h.jl | 0 .../SuiteSparse/test}/cholmod.jl | 18 +++++------ stdlib/SuiteSparse/test/runtests.jl | 10 +++++++ .../SuiteSparse/test}/spqr.jl | 4 +-- .../SuiteSparse/test}/umfpack.jl | 20 ++++++------- test/choosetests.jl | 3 -- 16 files changed, 70 insertions(+), 55 deletions(-) create mode 100644 stdlib/SuiteSparse/src/SuiteSparse.jl rename {base/sparse => stdlib/SuiteSparse/src}/cholmod.jl (99%) rename {base/sparse => stdlib/SuiteSparse/src}/cholmod_h.jl (100%) rename {base/sparse => stdlib/SuiteSparse/src}/spqr.jl (99%) rename {base/sparse => stdlib/SuiteSparse/src}/umfpack.jl (99%) rename {base/sparse => stdlib/SuiteSparse/src}/umfpack_h.jl (100%) rename {test/sparse => stdlib/SuiteSparse/test}/cholmod.jl (98%) create mode 100644 stdlib/SuiteSparse/test/runtests.jl rename {test/sparse => stdlib/SuiteSparse/test}/spqr.jl (97%) rename {test/sparse => stdlib/SuiteSparse/test}/umfpack.jl (86%) diff --git a/base/precompile.jl b/base/precompile.jl index b047275fbd82f0..08b1b636f60c2e 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -10,9 +10,6 @@ precompile(Tuple{typeof(Base.pointer), Array{UInt8, 1}, UInt64}) precompile(Tuple{typeof(Base.convert), Type{Ptr{Int32}}, Ptr{UInt8}}) -if USE_GPL_LIBS -precompile(Tuple{typeof(Base.SparseArrays.CHOLMOD.set_print_level), Array{UInt8, 1}, Int64}) -end precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.TTY}) precompile(Tuple{typeof(Base._start)}) precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Int64, Array{Any, 1}, Int64, Int64}) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index cbdee2c69b99be..eb3d3f2e36d3a5 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -2,22 +2,6 @@ import Base.LinAlg: checksquare -## Functions to switch to 0-based indexing to call external sparse solvers - -# Convert from 1-based to 0-based indices -function decrement!(A::AbstractArray{T}) where T<:Integer - for i in 1:length(A); A[i] -= oneunit(T) end - A -end -decrement(A::AbstractArray{<:Integer}) = decrement!(copy(A)) - -# Convert from 0-based to 1-based indices -function increment!(A::AbstractArray{T}) where T<:Integer - for i in 1:length(A); A[i] += oneunit(T) end - A -end -increment(A::AbstractArray{<:Integer}) = increment!(copy(A)) - ## sparse matrix multiplication function (*)(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 097e9b90296901..0b41b9e0731136 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -38,12 +38,6 @@ include("abstractsparse.jl") include("sparsematrix.jl") include("sparsevector.jl") include("higherorderfns.jl") - include("linalg.jl") -if Base.USE_GPL_LIBS - include("umfpack.jl") - include("cholmod.jl") - include("spqr.jl") -end end diff --git a/base/sysimg.jl b/base/sysimg.jl index 96edb6d019daed..b872ad4ea5663c 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -490,6 +490,7 @@ unshift!(Base._included_files, (@__MODULE__, joinpath(@__DIR__, "sysimg.jl"))) Base.require(:DelimitedFiles) Base.require(:Test) Base.require(:Dates) +Base.require(:SuiteSparse) empty!(LOAD_PATH) diff --git a/doc/src/manual/linear-algebra.md b/doc/src/manual/linear-algebra.md index 3a5cefc6263b43..8d8d4c24203abe 100644 --- a/doc/src/manual/linear-algebra.md +++ b/doc/src/manual/linear-algebra.md @@ -275,7 +275,6 @@ of the standard library documentation. | `CholeskyPivoted` | [Pivoted](https://en.wikipedia.org/wiki/Pivot_element) Cholesky factorization | | `LU` | [LU factorization](https://en.wikipedia.org/wiki/LU_decomposition) | | `LUTridiagonal` | LU factorization for [`Tridiagonal`](@ref) matrices | -| `UmfpackLU` | LU factorization for sparse matrices (computed by UMFPack) | | `QR` | [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | | `QRCompactWY` | Compact WY form of the QR factorization | | `QRPivoted` | Pivoted [QR factorization](https://en.wikipedia.org/wiki/QR_decomposition) | diff --git a/stdlib/SuiteSparse/src/SuiteSparse.jl b/stdlib/SuiteSparse/src/SuiteSparse.jl new file mode 100644 index 00000000000000..e233ef24f84824 --- /dev/null +++ b/stdlib/SuiteSparse/src/SuiteSparse.jl @@ -0,0 +1,30 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +module SuiteSparse + +import Base: At_ldiv_B, Ac_ldiv_B, A_ldiv_B! +import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc! + +## Functions to switch to 0-based indexing to call external sparse solvers + +# Convert from 1-based to 0-based indices +function decrement!(A::AbstractArray{T}) where T<:Integer + for i in 1:length(A); A[i] -= oneunit(T) end + A +end +decrement(A::AbstractArray{<:Integer}) = decrement!(copy(A)) + +# Convert from 0-based to 1-based indices +function increment!(A::AbstractArray{T}) where T<:Integer + for i in 1:length(A); A[i] += oneunit(T) end + A +end +increment(A::AbstractArray{<:Integer}) = increment!(copy(A)) + +if Base.USE_GPL_LIBS + include("umfpack.jl") + include("cholmod.jl") + include("spqr.jl") +end + +end # module SuiteSparse diff --git a/base/sparse/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl similarity index 99% rename from base/sparse/cholmod.jl rename to stdlib/SuiteSparse/src/cholmod.jl index e4ea0ded032995..a90822c8aa4911 100644 --- a/base/sparse/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -16,8 +16,9 @@ export Factor, Sparse -import ..SparseArrays: AbstractSparseMatrix, SparseMatrixCSC, increment, indtype, sparse, - spzeros, nnz +import ..SparseArrays: AbstractSparseMatrix, SparseMatrixCSC, indtype, sparse, spzeros, nnz + +import ..increment, ..increment!, ..decrement, ..decrement! ######### # Setup # diff --git a/base/sparse/cholmod_h.jl b/stdlib/SuiteSparse/src/cholmod_h.jl similarity index 100% rename from base/sparse/cholmod_h.jl rename to stdlib/SuiteSparse/src/cholmod_h.jl diff --git a/base/sparse/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl similarity index 99% rename from base/sparse/spqr.jl rename to stdlib/SuiteSparse/src/spqr.jl index e1bf8119ec1333..7189a6a157116b 100644 --- a/base/sparse/spqr.jl +++ b/stdlib/SuiteSparse/src/spqr.jl @@ -22,8 +22,8 @@ const ORDERING_BESTAMD = Int32(9) # try COLAMD and AMD; pick best# # the best of AMD and METIS. METIS is not tried if it isn't installed. using ..SparseArrays: SparseMatrixCSC -using ..SparseArrays.CHOLMOD -using ..SparseArrays.CHOLMOD: change_stype!, free! +using ..SuiteSparse.CHOLMOD +using ..SuiteSparse.CHOLMOD: change_stype!, free! function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, A::Sparse{Tv}, diff --git a/base/sparse/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl similarity index 99% rename from base/sparse/umfpack.jl rename to stdlib/SuiteSparse/src/umfpack.jl index 8355312cbbb66a..13f2a4cd17185b 100644 --- a/base/sparse/umfpack.jl +++ b/stdlib/SuiteSparse/src/umfpack.jl @@ -8,7 +8,9 @@ import Base: (\), Ac_ldiv_B, At_ldiv_B, findnz, getindex, show, size import Base.LinAlg: A_ldiv_B!, Ac_ldiv_B!, At_ldiv_B!, Factorization, det, lufact using ..SparseArrays -import ..SparseArrays: increment, increment!, decrement, decrement!, nnz +import ..SparseArrays: nnz + +import ..increment, ..increment!, ..decrement, ..decrement! include("umfpack_h.jl") struct MatrixIllConditionedException <: Exception diff --git a/base/sparse/umfpack_h.jl b/stdlib/SuiteSparse/src/umfpack_h.jl similarity index 100% rename from base/sparse/umfpack_h.jl rename to stdlib/SuiteSparse/src/umfpack_h.jl diff --git a/test/sparse/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl similarity index 98% rename from test/sparse/cholmod.jl rename to stdlib/SuiteSparse/test/cholmod.jl index 11bbbd4d0392bd..a86483dd1e010a 100644 --- a/test/sparse/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Base.SparseArrays.CHOLMOD +using SuiteSparse.CHOLMOD using DelimitedFiles using Test @@ -328,8 +328,8 @@ end A1pdSparse = CHOLMOD.Sparse( A1pd.m, A1pd.n, - Base.SparseArrays.decrement(A1pd.colptr), - Base.SparseArrays.decrement(A1pd.rowval), + SuiteSparse.decrement(A1pd.colptr), + SuiteSparse.decrement(A1pd.rowval), A1pd.nzval) ## High level interface @@ -584,7 +584,7 @@ end Asp = As[p,p] LDp = sparse(ldltfact(Asp, perm=[1,2,3])[:LD]) # LDp = sparse(Fs[:LD]) - Lp, dp = Base.SparseArrays.CHOLMOD.getLd!(copy(LDp)) + Lp, dp = SuiteSparse.CHOLMOD.getLd!(copy(LDp)) Dp = sparse(Diagonal(dp)) @test Fs\b ≈ Af\b @test Fs[:UP]\(Fs[:PtLD]\b) ≈ Af\b @@ -634,7 +634,7 @@ end end @testset "Issue 14134" begin - A = SparseArrays.CHOLMOD.Sparse(sprandn(10,5,0.1) + I |> t -> t't) + A = CHOLMOD.Sparse(sprandn(10,5,0.1) + I |> t -> t't) b = IOBuffer() serialize(b, A) seekstart(b) @@ -655,9 +655,9 @@ end end @testset "Issue with promotion during conversion to CHOLMOD.Dense" begin - @test SparseArrays.CHOLMOD.Dense(ones(Float32, 5)) == ones(5, 1) - @test SparseArrays.CHOLMOD.Dense(ones(Int, 5)) == ones(5, 1) - @test SparseArrays.CHOLMOD.Dense(ones(Complex{Float32}, 5, 2)) == ones(5, 2) + @test CHOLMOD.Dense(ones(Float32, 5)) == ones(5, 1) + @test CHOLMOD.Dense(ones(Int, 5)) == ones(5, 1) + @test CHOLMOD.Dense(ones(Complex{Float32}, 5, 2)) == ones(5, 2) end @testset "Further issue with promotion #14894" begin @@ -719,7 +719,7 @@ end @testset "Check that Symmetric{SparseMatrixCSC} can be constructed from CHOLMOD.Sparse" begin A = sprandn(10, 10, 0.1) - B = SparseArrays.CHOLMOD.Sparse(A) + B = CHOLMOD.Sparse(A) C = B'B # Change internal representation to symmetric (upper/lower) o = fieldoffset(CHOLMOD.C_Sparse{eltype(C)}, find(fieldnames(CHOLMOD.C_Sparse{eltype(C)}) .== :stype)[1]) diff --git a/stdlib/SuiteSparse/test/runtests.jl b/stdlib/SuiteSparse/test/runtests.jl new file mode 100644 index 00000000000000..f27f76068991a7 --- /dev/null +++ b/stdlib/SuiteSparse/test/runtests.jl @@ -0,0 +1,10 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Test +using SuiteSparse + +if Base.USE_GPL_LIBS + include("umfpack.jl") + include("cholmod.jl") + include("spqr.jl") +end diff --git a/test/sparse/spqr.jl b/stdlib/SuiteSparse/test/spqr.jl similarity index 97% rename from test/sparse/spqr.jl rename to stdlib/SuiteSparse/test/spqr.jl index beb984288f8092..e851ab05a4ee45 100644 --- a/test/sparse/spqr.jl +++ b/stdlib/SuiteSparse/test/spqr.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Base.SparseArrays.SPQR -using Base.SparseArrays.CHOLMOD +using SuiteSparse.SPQR +using SuiteSparse.CHOLMOD @testset "Sparse QR" begin m, n = 100, 10 diff --git a/test/sparse/umfpack.jl b/stdlib/SuiteSparse/test/umfpack.jl similarity index 86% rename from test/sparse/umfpack.jl rename to stdlib/SuiteSparse/test/umfpack.jl index af9cb3f247d161..ebb48dffd6ea99 100644 --- a/test/sparse/umfpack.jl +++ b/stdlib/SuiteSparse/test/umfpack.jl @@ -7,7 +7,7 @@ # based on deps/Suitesparse-4.0.2/UMFPACK/Demo/umfpack_di_demo.c - using Base.SparseArrays.UMFPACK.increment! + using SuiteSparse.increment! A0 = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), increment!([0,4,0,2,1,2,1,4,3,2,1,2]), @@ -15,7 +15,7 @@ @testset "Core functionality for $Tv elements" for Tv in (Float64, Complex128) # We might be able to support two index sizes one day - for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) + for Ti in Base.uniontypes(SuiteSparse.UMFPACK.UMFITypes) A = convert(SparseMatrixCSC{Tv,Ti}, A0) lua = lufact(A) @test nnz(lua) == 18 @@ -31,7 +31,7 @@ @test A*x ≈ b z = complex.(b) - x = Base.SparseArrays.A_ldiv_B!(lua, z) + x = SuiteSparse.A_ldiv_B!(lua, z) @test x ≈ float([1:5;]) @test z === x y = similar(z) @@ -46,11 +46,11 @@ @test A'*x ≈ b z = complex.(b) - x = Base.SparseArrays.Ac_ldiv_B!(lua, z) + x = SuiteSparse.Ac_ldiv_B!(lua, z) @test x ≈ float([1:5;]) @test x === z y = similar(x) - Base.SparseArrays.Ac_ldiv_B!(y, lua, complex.(b)) + SuiteSparse.Ac_ldiv_B!(y, lua, complex.(b)) @test y ≈ x @test A'*x ≈ b @@ -58,10 +58,10 @@ @test x ≈ float([1:5;]) @test A.'*x ≈ b - x = Base.SparseArrays.At_ldiv_B!(lua,complex.(b)) + x = SuiteSparse.At_ldiv_B!(lua,complex.(b)) @test x ≈ float([1:5;]) y = similar(x) - Base.SparseArrays.At_ldiv_B!(y, lua,complex.(b)) + SuiteSparse.At_ldiv_B!(y, lua,complex.(b)) @test y ≈ x @test A.'*x ≈ b @@ -73,7 +73,7 @@ @testset "More tests for complex cases" begin Ac0 = complex.(A0,A0) - for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) + for Ti in Base.uniontypes(SuiteSparse.UMFPACK.UMFITypes) Ac = convert(SparseMatrixCSC{Complex128,Ti}, Ac0) x = complex.(ones(size(Ac, 1)), ones(size(Ac,1))) lua = lufact(Ac) @@ -142,9 +142,9 @@ @testset "Test aliasing" begin a = rand(5) - @test_throws ArgumentError Base.SparseArrays.UMFPACK.solve!(a, lufact(sparse(1.0I, 5, 5)), a, Base.SparseArrays.UMFPACK.UMFPACK_A) + @test_throws ArgumentError SuiteSparse.UMFPACK.solve!(a, lufact(sparse(1.0I, 5, 5)), a, SuiteSparse.UMFPACK.UMFPACK_A) aa = complex(a) - @test_throws ArgumentError Base.SparseArrays.UMFPACK.solve!(aa, lufact(sparse((1.0im)I, 5, 5)), aa, Base.SparseArrays.UMFPACK.UMFPACK_A) + @test_throws ArgumentError SuiteSparse.UMFPACK.solve!(aa, lufact(sparse((1.0im)I, 5, 5)), aa, SuiteSparse.UMFPACK.UMFPACK_A) end @testset "Issues #18246,18244 - lufact sparse pivot" begin diff --git a/test/choosetests.jl b/test/choosetests.jl index e2196d2b3fbe5c..a24043dee47494 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -99,9 +99,6 @@ function choosetests(choices = []) end sparsetests = ["sparse/sparse", "sparse/sparsevector", "sparse/higherorderfns"] - if Base.USE_GPL_LIBS - append!(sparsetests, ["sparse/umfpack", "sparse/cholmod", "sparse/spqr"]) - end if "sparse" in skip_tests filter!(x -> (x != "sparse" && !(x in sparsetests)), tests) elseif "sparse" in tests