Skip to content

Commit 9195b30

Browse files
committed
Integrate SparseVectors.jl with Base sparse module
Renamings: * Rename sparse module to SparseArrays, and improve its separation from base. This makes it very simple to dynamically reload the sparse module. Move docstrings to their proper place * _copy_convert → collect * Rename sparsevector to the existing spzeros and sparsevec. * Use call overloading instead of call Remove functionality from SparseVectors.jl: * Simplify and remove some functors * Remove SparseVectorView * Remove no-longer-needed ambiguity preventers Add functionality for SparseVectors: * Add similar for SparseVector * Allow sparsevec(::AbstractArray), not just vectors * Add spzeros(n); adapt some tests to SparseVector * Allow CHOLMOD linalg with vectors * Implement (c)transpose(::SparseVector). Returns a dense vector since a one-row CSC structure is effectively dense but with worse performance. * Add vector sprandbool and allow passing RNG to all vector sprand* functions. Harden tests against random failures. * Implement, test and doc spones(::SparseVector) Improve performance for SparseVector indexing: * Punt to SparseMatrix for some indexing behaviors. Since the datastructures are compatible and SparseMatrix's routines are more optimized, it is easiest to just construct a temporary SparseMatrix and index into that. This is faster in all but the smallest of cases (N<10) * Use searchsorted for indexing SparseVector by UnitRange. This is about 20% slower on very small vectors, but is faster in general. Change SparseMatrix behaviors to take advantage of vectors * Add indexing behaviors for SparseMatrix->SparseVector * `vec` and `sparsevec` for CSC return SparseVectors * Update documentation to incorporate vectors Minor bugfixes and changes to SparseVectors: * Compare to literal 0 in vector construction and setindex. This matches SparseMatrix semantics, and makes indexing semantics consistent with regard to stored zeros * Use checkbounds more thoroughly * Use error types that are consistent with SparseMatrixCSC * Minor sparse vector display tweaks. Turn on output limiting by default, remove unused variable `k`, implement and use Base.summary * Fix missing return, add test Add some tests: * Add a test and comment to ensure nobody else tries to share data between vectors and matrices * Ensure indexing is consistent between one-column sparse matrices and sparse vectors, with special attention to stored zeros.
1 parent 8313e52 commit 9195b30

22 files changed

+586
-629
lines changed

base/deprecated.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,4 +841,6 @@ for f in (:remotecall, :remotecall_fetch, :remotecall_wait)
841841
@deprecate ($f)(w::Worker, f::Function, args...) ($f)(f, w::Worker, args...)
842842
@deprecate ($f)(id::Integer, f::Function, args...) ($f)(f, id::Integer, args...)
843843
end
844-
end
844+
end
845+
846+
@deprecate_binding SparseMatrix SparseArrays

base/docs/helpdb.jl

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,17 +2389,6 @@ Right division operator: multiplication of `x` by the inverse of `y` on the righ
23892389
"""
23902390
Base.(:(/))
23912391

2392-
doc"""
2393-
ldltfact(::Union{SparseMatrixCSC,Symmetric{Float64,SparseMatrixCSC{Flaot64,SuiteSparse_long}},Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}}; shift=0, perm=Int[]) -> CHOLMOD.Factor
2394-
2395-
Compute the `LDLt` factorization of a sparse symmetric or Hermitian matrix. A fill-reducing permutation is used. `F = ldltfact(A)` is most frequently used to solve systems of equations `A*x = b` with `F\b`, but also the methods `diag`, `det`, `logdet` are defined for `F`. You can also extract individual factors from `F`, using `F[:L]`. However, since pivoting is on by default, the factorization is internally represented as `A == P'*L*D*L'*P` with a permutation matrix `P`; using just `L` without accounting for `P` will give incorrect answers. To include the effects of permutation, it's typically preferable to extact "combined" factors like `PtL = F[:PtL]` (the equivalent of `P'*L`) and `LtP = F[:UP]` (the equivalent of `L'*P`). The complete list of supported factors is `:L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP`.
2396-
2397-
Setting optional `shift` keyword argument computes the factorization of `A+shift*I` instead of `A`. If the `perm` argument is nonempty, it should be a permutation of `1:size(A,1)` giving the ordering to use (instead of CHOLMOD's default AMD ordering).
2398-
2399-
The function calls the C library CHOLMOD and many other functions from the library are wrapped but not exported.
2400-
"""
2401-
ldltfact(A::SparseMatrixCSC; shift=0, perm=Int[])
2402-
24032392
doc"""
24042393
connect([host],port) -> TcpSocket
24052394
@@ -7231,13 +7220,6 @@ Tests whether `A` or its elements are of type `T`.
72317220
"""
72327221
iseltype
72337222

7234-
doc"""
7235-
symperm(A, p)
7236-
7237-
Return the symmetric permutation of `A`, which is `A[p,p]`. `A` should be symmetric and sparse, where only the upper triangular part of the matrix is stored. This algorithm ignores the lower triangular part of the matrix. Only the upper triangular part of the result is returned as well.
7238-
"""
7239-
symperm
7240-
72417223
doc"""
72427224
min(x, y, ...)
72437225
@@ -9984,15 +9966,6 @@ Like permute!, but the inverse of the given permutation is applied.
99849966
"""
99859967
ipermute!
99869968

9987-
doc"""
9988-
```rst
9989-
.. full(S)
9990-
9991-
Convert a sparse matrix ``S`` into a dense matrix.
9992-
```
9993-
"""
9994-
full(::AbstractSparseMatrix)
9995-
99969969
doc"""
99979970
```rst
99989971
.. full(F)
@@ -10478,13 +10451,6 @@ k]``.)
1047810451
"""
1047910452
eigfact(A,B)
1048010453

10481-
doc"""
10482-
rowvals(A)
10483-
10484-
Return a vector of the row indices of `A`, and any modifications to the returned vector will mutate `A` as well. Given the internal storage format of sparse matrices, providing access to how the row indices are stored internally can be useful in conjuction with iterating over structural nonzero values. See `nonzeros(A)` and `nzrange(A, col)`.
10485-
"""
10486-
rowvals
10487-
1048810454
doc"""
1048910455
mkdir(path, [mode])
1049010456

base/exports.jl

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,12 @@ export
2020
BLAS,
2121
LAPACK,
2222
Serializer,
23-
SparseMatrix,
2423
Docs,
2524
Markdown,
2625

2726
# Types
2827
AbstractChannel,
2928
AbstractMatrix,
30-
AbstractSparseArray,
31-
AbstractSparseMatrix,
32-
AbstractSparseVector,
3329
AbstractVector,
3430
AbstractVecOrMat,
3531
Array,
@@ -107,7 +103,6 @@ export
107103
SharedArray,
108104
SharedMatrix,
109105
SharedVector,
110-
SparseMatrixCSC,
111106
StatStruct,
112107
StepRange,
113108
StridedArray,
@@ -562,7 +557,6 @@ export
562557
minimum,
563558
minmax,
564559
ndims,
565-
nnz,
566560
nonzeros,
567561
nthperm!,
568562
nthperm,
@@ -715,21 +709,7 @@ export
715709
×,
716710

717711
# sparse
718-
etree,
719712
full,
720-
issparse,
721-
sparse,
722-
sparsevec,
723-
spdiagm,
724-
speye,
725-
spones,
726-
sprand,
727-
sprandbool,
728-
sprandn,
729-
spzeros,
730-
symperm,
731-
rowvals,
732-
nzrange,
733713

734714
# bitarrays
735715
bitpack,

base/irrationals.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,9 @@ const golden = φ
122122
for T in (Irrational, Rational, Integer, Number)
123123
^(::Irrational{:e}, x::T) = exp(x)
124124
end
125-
for T in (Range, BitArray, SparseMatrixCSC, StridedArray, AbstractArray)
125+
for T in (Range, BitArray, StridedArray, AbstractArray)
126126
.^(::Irrational{:e}, x::T) = exp(x)
127127
end
128-
^(::Irrational{:e}, x::AbstractMatrix) = expm(x)
129128

130129
log(::Irrational{:e}) = 1 # use 1 to correctly promote expressions like log(x)/log(e)
131130
log(::Irrational{:e}, x) = log(x)

base/precompile.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ precompile(Base.next, (Dict{Symbol,Any},Int))
294294
precompile(Base.next, (IntSet, Int))
295295
precompile(Base.next, (UnitRange{Int},Int))
296296
precompile(Base.nextind, (ASCIIString, Int))
297-
precompile(Base.nnz, (BitArray{1},))
298297
precompile(Base.normpath, (ASCIIString, ASCIIString))
299298
precompile(Base.normpath, (ASCIIString,))
300299
precompile(Base.normpath, (UTF8String, UTF8String))

base/sparse.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
# This file is a part of Julia. License is MIT: http://julialang.org/license
22

3-
module SparseMatrix
3+
module SparseArrays
44

55
using Base: Func, AddFun, OrFun, ConjFun, IdFun
66
using Base.Sort: Forward
77
using Base.LinAlg: AbstractTriangular
88

99
importall Base
10-
importall ..Base.Operators
10+
importall Base.Operators
1111
importall Base.LinAlg
1212
import Base.promote_eltype
1313
import Base.@get!
1414
import Base.Broadcast.eltype_plus, Base.Broadcast.broadcast_shape
1515

1616
export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, SparseMatrixCSC,
17-
blkdiag, dense, droptol!, dropzeros!, etree, issparse, nnz, nonzeros, nzrange,
17+
SparseVector,
18+
blkdiag, dense, droptol!, dropzeros!, etree, issparse, nonzeros, nzrange,
1819
rowvals, sparse, sparsevec, spdiagm, speye, spones, sprand, sprandbool, sprandn,
19-
spzeros, symperm
20+
spzeros, symperm, nnz
2021

2122
include("sparse/abstractsparse.jl")
2223
include("sparse/sparsematrix.jl")
24+
include("sparse/sparsevector.jl")
2325
include("sparse/csparse.jl")
2426

2527
include("sparse/linalg.jl")
@@ -29,4 +31,4 @@ if Base.USE_GPL_LIBS
2931
include("sparse/spqr.jl")
3032
end
3133

32-
end # module SparseMatrix
34+
end

base/sparse/cholmod.jl

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import Base.LinAlg: (\), A_mul_Bc, A_mul_Bt, Ac_ldiv_B, Ac_mul_B, At_ldiv_B, At_
99
cholfact, det, diag, ishermitian, isposdef,
1010
issym, ldltfact, logdet
1111

12-
import Base.SparseMatrix: sparse, nnz
12+
importall ..SparseArrays
1313

1414
export
1515
Dense,
1616
Factor,
1717
Sparse
1818

19-
using Base.SparseMatrix: AbstractSparseMatrix, SparseMatrixCSC, increment, indtype
19+
import ..SparseArrays: AbstractSparseMatrix, SparseMatrixCSC, increment, indtype
2020

2121
#########
2222
# Setup #
@@ -853,6 +853,9 @@ function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_l
853853

854854
return o
855855
end
856+
857+
# convert SparseVectors into CHOLMOD Sparse types through a mx1 CSC matrix
858+
convert{Tv<:VTypes}(::Type{Sparse}, A::SparseVector{Tv,SuiteSparse_long}) = convert(Sparse, convert(SparseMatrixCSC, A))
856859
function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_long})
857860
o = Sparse(A, 0)
858861
# check if array is symmetric and change stype if it is
@@ -994,7 +997,7 @@ function sparse(F::Factor)
994997
L, d = getLd!(LD)
995998
A = scale(L, d)*L'
996999
end
997-
SparseMatrix.sortSparseMatrixCSC!(A)
1000+
SparseArrays.sortSparseMatrixCSC!(A)
9981001
p = get_perm(F)
9991002
if p != [1:s.n;]
10001003
pinv = Array(Int, length(p))
@@ -1216,6 +1219,32 @@ function cholfact(A::Sparse; kws...)
12161219
return F
12171220
end
12181221

1222+
doc"""
1223+
ldltfact(::Union{SparseMatrixCSC,Symmetric{Float64,SparseMatrixCSC{Flaot64,SuiteSparse_long}},Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}}; shift=0, perm=Int[]) -> CHOLMOD.Factor
1224+
1225+
Compute the `LDLt` factorization of a sparse symmetric or Hermitian matrix. A
1226+
fill-reducing permutation is used. `F = ldltfact(A)` is most frequently used to
1227+
solve systems of equations `A*x = b` with `F\b`. The returned factorization
1228+
object `F` also supports the methods `diag`, `det`, and `logdet`. You can
1229+
extract individual factors from `F` using `F[:L]`. However, since pivoting is
1230+
on by default, the factorization is internally represented as `A == P'*L*D*L'*P`
1231+
with a permutation matrix `P`; using just `L` without accounting for `P` will
1232+
give incorrect answers. To include the effects of permutation, it's typically
1233+
preferable to extact "combined" factors like `PtL = F[:PtL]` (the equivalent of
1234+
`P'*L`) and `LtP = F[:UP]` (the equivalent of `L'*P`). The complete list of
1235+
supported factors is `:L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP`.
1236+
1237+
Setting optional `shift` keyword argument computes the factorization of
1238+
`A+shift*I` instead of `A`. If the `perm` argument is nonempty, it should be a
1239+
permutation of `1:size(A,1)` giving the ordering to use (instead of CHOLMOD's
1240+
default AMD ordering).
1241+
1242+
The function calls the C library CHOLMOD and many other functions from the
1243+
library are wrapped but not exported.
1244+
1245+
"""
1246+
ldltfact(A::SparseMatrixCSC; shift=0, perm=Int[])
1247+
12191248
function ldltfact(A::Sparse; kws...)
12201249
cm = defaults(common()) # setting the common struct to default values. Should only be done when creating new factorization.
12211250
set_print_level(cm, 0) # no printing from CHOLMOD by default
@@ -1294,13 +1323,15 @@ for (T, f) in ((:Dense, :solve), (:Sparse, :spsolve))
12941323
end
12951324
end
12961325

1326+
typealias SparseVecOrMat{Tv,Ti} Union{SparseVector{Tv,Ti}, SparseMatrixCSC{Tv,Ti}}
1327+
12971328
function (\)(L::FactorComponent, b::Vector)
12981329
reshape(convert(Matrix, L\Dense(b)), length(b))
12991330
end
13001331
function (\)(L::FactorComponent, B::Matrix)
13011332
convert(Matrix, L\Dense(B))
13021333
end
1303-
function (\)(L::FactorComponent, B::SparseMatrixCSC)
1334+
function (\)(L::FactorComponent, B::SparseVecOrMat)
13041335
sparse(L\Sparse(B,0))
13051336
end
13061337

@@ -1311,12 +1342,12 @@ Ac_ldiv_B(L::FactorComponent, B) = ctranspose(L)\B
13111342
(\)(L::Factor, B::Matrix) = convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))
13121343
(\)(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B)
13131344
# When right hand side is sparse, we have to ensure that the rhs is not marked as symmetric.
1314-
(\)(L::Factor, B::SparseMatrixCSC) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0)))
1345+
(\)(L::Factor, B::SparseVecOrMat) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0)))
13151346

13161347
Ac_ldiv_B(L::Factor, B::Dense) = solve(CHOLMOD_A, L, B)
13171348
Ac_ldiv_B(L::Factor, B::VecOrMat) = convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))
13181349
Ac_ldiv_B(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B)
1319-
Ac_ldiv_B(L::Factor, B::SparseMatrixCSC) = Ac_ldiv_B(L, Sparse(B))
1350+
Ac_ldiv_B(L::Factor, B::SparseVecOrMat) = Ac_ldiv_B(L, Sparse(B))
13201351

13211352
## Other convenience methods
13221353
function diag{Tv}(F::Factor{Tv})
@@ -1398,7 +1429,7 @@ function ishermitian(A::Sparse{Complex{Float64}})
13981429
end
13991430
end
14001431

1401-
(*){Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, B::SparseMatrixCSC{Float64,Ti}) = sparse(Sparse(A)*Sparse(B))
1402-
(*){Ti}(A::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}, B::SparseMatrixCSC{Complex{Float64},Ti}) = sparse(Sparse(A)*Sparse(B))
1432+
(*){Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, B::SparseVecOrMat{Float64,Ti}) = sparse(Sparse(A)*Sparse(B))
1433+
(*){Ti}(A::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}, B::SparseVecOrMat{Complex{Float64},Ti}) = sparse(Sparse(A)*Sparse(B))
14031434

14041435
end #module

base/sparse/csparse.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,17 @@ function csc_permute{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, pinv::Vector{Ti}, q::Vect
313313
(C.').' # double transpose to order the columns
314314
end
315315

316+
316317
# based on cs_symperm p. 21, "Direct Methods for Sparse Linear Systems"
317318
# form A[p,p] for a symmetric A stored in the upper triangle
319+
doc"""
320+
symperm(A, p)
321+
322+
Return the symmetric permutation of `A`, which is `A[p,p]`. `A` should be
323+
symmetric, sparse, and only contain nonzeros in the upper triangular part of the
324+
matrix is stored. This algorithm ignores the lower triangular part of the
325+
matrix. Only the upper triangular part of the result is returned.
326+
"""
318327
function symperm{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, pinv::Vector{Ti})
319328
m, n = size(A)
320329
if m != n

base/sparse/linalg.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ function spmatmul{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti};
160160

161161
# The Gustavson algorithm does not guarantee the product to have sorted row indices.
162162
Cunsorted = SparseMatrixCSC(mA, nB, colptrC, rowvalC, nzvalC)
163-
C = Base.SparseMatrix.sortSparseMatrixCSC!(Cunsorted, sortindices=sortindices)
163+
C = SparseArrays.sortSparseMatrixCSC!(Cunsorted, sortindices=sortindices)
164164
return C
165165
end
166166

@@ -752,7 +752,7 @@ inv(A::SparseMatrixCSC) = error("The inverse of a sparse matrix can often be den
752752

753753
## scale methods
754754

755-
# Copy colptr and rowval from one SparseMatrix to another
755+
# Copy colptr and rowval from one sparse matrix to another
756756
function copyinds!(C::SparseMatrixCSC, A::SparseMatrixCSC)
757757
if C.colptr !== A.colptr
758758
resize!(C.colptr, length(A.colptr))

0 commit comments

Comments
 (0)