Sparse Arrays

Julia has support for sparse vectors and sparse matrices in the SparseArrays stdlib module. Sparse arrays are arrays that contain enough zeros that storing them in a special data structure leads to savings in space and execution time, compared to dense arrays.

External packages which implement different sparse storage types, multidimensional sparse arrays, and more can be found in Noteworthy External Sparse Packages

Compressed Sparse Column (CSC) Sparse Matrix Storage

In Julia, sparse matrices are stored in the Compressed Sparse Column (CSC) format. Julia sparse matrices have the type SparseMatrixCSC{Tv,Ti}, where Tv is the type of the stored values, and Ti is the integer type for storing column pointers and row indices. The internal representation of SparseMatrixCSC is as follows:

struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}
    m::Int                  # Number of rows
    n::Int                  # Number of columns
    colptr::Vector{Ti}      # Column j is in colptr[j]:(colptr[j+1]-1)
    rowval::Vector{Ti}      # Row indices of stored values
    nzval::Vector{Tv}       # Stored values, typically nonzeros
end

The compressed sparse column storage makes it easy and quick to access the elements in the column of a sparse matrix, whereas accessing the sparse matrix by rows is considerably slower. Operations such as insertion of previously unstored entries one at a time in the CSC structure tend to be slow. This is because all elements of the sparse matrix that are beyond the point of insertion have to be moved one place over.

All operations on sparse matrices are carefully implemented to exploit the CSC data structure for performance, and to avoid expensive operations.

If you have data in CSC format from a different application or library, you can wrap the three arrays directly with SparseMatrixCSC(m, n, colptr, rowval, nzval). The arrays are not copied, so the matrix aliases them. Make copies if you want to avoid aliasing. They must satisfy the following invariants:

  • colptr has length n + 1, starts at 1, and is nondecreasing;

  • rowval and nzval both have length colptr[end] - 1, and rowval has the same element type as colptr;

  • within each column, the row indices are sorted, unique, and in 1:m.

The constructor throws an ArgumentError if the first two are violated, but it does not inspect the row indices. A matrix with unsorted, repeated or out-of-range row indices is constructed silently and then gives inconsistent results.

Arrays from C, Python (SciPy's indptr and indices) and other 0-based sources need 1 added to colptr and rowval.

One quick way to sort them is a double transpose. Since the transpose operation is lazy, make a copy to materialize each transpose. Alternatively, rebuild the matrix from its coordinates with findnz and sparse, which also adds up repeated entries:

julia> colptr = [1, 3, 4, 6]; rowval = [3, 1, 2, 3, 1]; nzval = [20.0, 10.0, 30.0, 50.0, 40.0];

julia> A = SparseMatrixCSC(3, 3, colptr, rowval, nzval);  # unsorted row indices

julia> B = copy(transpose(copy(transpose(A))))
3×3 SparseMatrixCSC{Float64, Int64} with 5 stored entries:
 10.0    ⋅   40.0
   ⋅   30.0    ⋅
 20.0    ⋅   50.0

julia> B == sparse(findnz(A)..., size(A)...)
true

The arrays of an m × n matrix in compressed sparse row (CSR) format are the CSC arrays of its transpose, so build the n × m matrix from them and transpose it:

julia> rowptr = [1, 3, 4]; colval = [1, 3, 2]; nzval = [1.0, 2.0, 3.0];  # 2 × 3 CSR

julia> copy(transpose(SparseMatrixCSC(3, 2, rowptr, colval, nzval)))
2×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
 1.0   ⋅   2.0
  ⋅   3.0   ⋅

In some applications, it is convenient to store explicit zero values in a SparseMatrixCSC. These are accepted by functions in Base (but there is no guarantee that they will be preserved in mutating operations). Such explicitly stored zeros are treated as structural nonzeros by many routines. The nnz function returns the number of elements explicitly stored in the sparse data structure, including non-structural zeros. In order to count the exact number of numerical nonzeros, use count(!iszero, x), which inspects every stored element of a sparse matrix. dropzeros, and the in-place dropzeros!, can be used to remove stored zeros from the sparse matrix.

julia> A = sparse([1, 1, 2, 3], [1, 3, 2, 3], [0, 1, 2, 0])
3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 0  ⋅  1
 ⋅  2  ⋅
 ⋅  ⋅  0

julia> dropzeros(A)
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 ⋅  ⋅  1
 ⋅  2  ⋅
 ⋅  ⋅  ⋅

Sparse Vector Storage

Sparse vectors are stored in a close analog to compressed sparse column format for sparse matrices. In Julia, sparse vectors have the type SparseVector{Tv,Ti} where Tv is the type of the stored values and Ti the integer type for the indices. The internal representation is as follows:

struct SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}
    n::Int              # Length of the sparse vector
    nzind::Vector{Ti}   # Indices of stored values
    nzval::Vector{Tv}   # Stored values, typically nonzeros
end

Like SparseMatrixCSC, the SparseVector type can also contain explicitly stored zeros. (See Sparse Matrix Storage.)

Sparse Vector and Matrix Constructors

The simplest way to create a sparse array is to use a function equivalent to the zeros function that Julia provides for working with dense arrays. To produce a sparse array instead, you can use the same name with an sp prefix:

julia> spzeros(3)
3-element SparseVector{Float64, Int64} with 0 stored entries

The sparse function is often a handy way to construct sparse arrays. For example, to construct a sparse matrix we can input a vector I of row indices, a vector J of column indices, and a vector V of stored values (this is also known as the COO (coordinate) format). sparse(I,J,V) then constructs a sparse matrix such that S[I[k], J[k]] = V[k]. The equivalent sparse vector constructor is sparsevec, which takes the (row) index vector I and the vector V with the stored values and constructs a sparse vector R such that R[I[k]] = V[k].

julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];

julia> S = sparse(I,J,V)
5×18 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅   ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅   ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  -5
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  2  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅   ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  3  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅   ⋅

julia> R = sparsevec(I,V)
5-element SparseVector{Int64, Int64} with 4 stored entries:
  [1]  =  1
  [3]  =  -5
  [4]  =  2
  [5]  =  3

The inverse of the sparse and sparsevec functions is findnz, which retrieves the inputs used to create the sparse array (including stored entries equal to zero). findall(!iszero, x) returns the Cartesian indices of non-zero entries in x (not including stored entries equal to zero).

julia> findnz(S)
([1, 4, 5, 3], [4, 7, 9, 18], [1, 2, 3, -5])

julia> findall(!iszero, S)
4-element Vector{CartesianIndex{2}}:
 CartesianIndex(1, 4)
 CartesianIndex(4, 7)
 CartesianIndex(5, 9)
 CartesianIndex(3, 18)

julia> findnz(R)
([1, 3, 4, 5], [1, -5, 2, 3])

julia> findall(!iszero, R)
4-element Vector{Int64}:
 1
 3
 4
 5

Another way to create a sparse array is to convert a dense array into a sparse array using the sparse function:

julia> sparse(Matrix(1.0I, 5, 5))
5×5 SparseMatrixCSC{Float64, Int64} with 5 stored entries:
 1.0   ⋅    ⋅    ⋅    ⋅
  ⋅   1.0   ⋅    ⋅    ⋅
  ⋅    ⋅   1.0   ⋅    ⋅
  ⋅    ⋅    ⋅   1.0   ⋅
  ⋅    ⋅    ⋅    ⋅   1.0

julia> sparse([1.0, 0.0, 1.0])
3-element SparseVector{Float64, Int64} with 2 stored entries:
  [1]  =  1.0
  [3]  =  1.0

You can go in the other direction using the Array constructor. The issparse function can be used to query if a matrix is sparse.

julia> issparse(spzeros(5))
true

Sparse matrix operations

Arithmetic operations on sparse matrices also work as they do on dense matrices. Indexing of, assignment into, and concatenation of sparse matrices work in the same way as dense matrices. Indexing operations, especially assignment, are expensive, when carried out one element at a time. In many cases it may be better to convert the sparse matrix into (I,J,V) format using findnz, manipulate the values or the structure in the dense vectors (I,J,V), and then reconstruct the sparse matrix.

Reductions along a dimension, such as sum(S; dims = 2), return a dense Matrix, as for dense input. To keep the result sparse, pass sparse = true: sum(S; dims = 2, sparse = true) stores an entry only for the rows of S that store one, at a cost proportional to the number of stored entries rather than to the number of rows. prod, maximum, minimum, count, any, all and mapreduce accept the keyword in the same way, as do adjoints and transposes of sparse matrices, views of a subset of their columns, and sparse vectors, for which the result is a SparseVector.

Broadcasting and map

broadcast (including dot syntax such as A .* B) and map over sparse vectors and matrices return a sparse result. To decide which entries to store, the function is first evaluated once on the zeros of the arguments' element types. If f(0, 0, ...) is zero, as for A .* B, abs.(A) or 2 .* A, only positions where some argument has a stored entry are visited. With a single sparse argument the result has exactly that argument's stored entries, so 2 .* A, abs.(A) and Float64.(A) keep the stored zeros of A, just as 2A, -A and float(A) do:

julia> A = sparse([1, 1, 2, 3], [1, 2, 2, 3], [1, 0, -2, 3])
3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 1   0  ⋅
 ⋅  -2  ⋅
 ⋅   ⋅  3

julia> Float64.(A)
3×3 SparseMatrixCSC{Float64, Int64} with 4 stored entries:
 1.0   0.0   ⋅
  ⋅   -2.0   ⋅
  ⋅     ⋅   3.0

With two or more sparse arguments, only the results that are nonzero are stored:

julia> B = sparse([1, 1, 3], [1, 3, 3], [1, 5, -3]);

julia> A .* B
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 1  ⋅   ⋅
 ⋅  ⋅   ⋅
 ⋅  ⋅  -9

julia> A .+ B
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2   ⋅  5
 ⋅  -2  ⋅
 ⋅   ⋅  ⋅

The entry A[3, 3] + B[3, 3] cancels to zero and is dropped rather than stored, and so is the stored zero A[1, 2], because A[1, 2] + B[1, 2] computes to zero.

If f(0, 0, ...) is not zero, as for A .+ 1, cos.(A) or A ./ B (where 0/0 is NaN), the result is still a sparse array, but every entry is stored, including any that happen to compute to zero. Such a result needs more memory than the equivalent Array, so convert to dense first when this is intended:

julia> A .+ 2
3×3 SparseMatrixCSC{Int64, Int64} with 9 stored entries:
 3  2  2
 2  0  2
 2  2  5

map follows the same rules, but requires all arguments to have the same shape and throws a DimensionMismatch otherwise, whereas broadcast expands singleton dimensions. A sparse vector behaves as a one-column matrix, and combining it with a sparse matrix or with the adjoint or transpose of a sparse vector gives a SparseMatrixCSC:

julia> v = sparsevec([1, 3], [1, 2], 3);

julia> A .+ v
3×3 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
 2   1  1
 ⋅  -2  ⋅
 2   2  5

julia> v .* v'
3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 1  ⋅  2
 ⋅  ⋅  ⋅
 2  ⋅  4

Scalars (and Refs) are folded into the function before the rules above are applied. Broadcasting a sparse array with a Vector, a Matrix, the adjoint or transpose of any of these, or a Diagonal, Bidiagonal, Tridiagonal or SymTridiagonal matrix first converts those arguments to sparse, so the result is sparse as well, even when it is full, as in A .+ ones(3, 3). A view of whole columns of a sparse matrix, such as @view A[:, 2:3] or @view A[:, j], or of a range of a sparse vector is copied to a sparse array in time proportional to its stored entries, so broadcasting over it is sparse too, even with no other sparse argument. Any other argument, such as a tuple, a range, a triangular or Symmetric wrapper, a view that selects some of the rows of a sparse matrix or an array with more than two dimensions, makes the broadcast fall back to the generic implementation, which visits every element and returns an Array. map accepts the same structured matrices alongside sparse matrices, and falls back to a dense result otherwise.

julia> A .* Diagonal([1, 2, 3])
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 1   ⋅  ⋅
 ⋅  -4  ⋅
 ⋅   ⋅  9

julia> typeof(A .* (1:3))
Matrix{Int64} (alias for Array{Int64, 2})

broadcast!, map! and .= with a sparse destination overwrite its stored pattern with that of the result, growing or shrinking its buffers as needed, so a preallocated destination saves allocations only when its buffers are already large enough. The destination may also be one of the arguments (they are copied first if they share memory with it), as in C .= C .+ C'. One exception: C .= 0 calls fill!, which keeps C's stored pattern and sets the stored values to zero.

julia> C = spzeros(Int, 3, 3);

julia> C .= A .* B;

julia> C
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 1  ⋅   ⋅
 ⋅  ⋅   ⋅
 ⋅  ⋅  -9

To apply a function to the stored values only, leaving the pattern untouched whatever the function returns for zero, broadcast over nonzeros instead:

julia> nonzeros(C) .= nonzeros(C) .+ 9;

julia> C
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 10  ⋅  ⋅
  ⋅  ⋅  ⋅
  ⋅  ⋅  0

Performance tips

Sparse code is fast when its cost is proportional to the number of stored entries, and the CSC layout determines which operations have that property.

Iterate over stored entries by column

The stored entries of column j are located at the positions nzrange(A, j) of rowvals(A) and nonzeros(A). Looping over the columns, and over that range within each column, visits every stored entry once and in memory order, without searching. For example, a matrix-vector product can be written as:

julia> A = sparse([1, 1, 2, 3], [1, 3, 2, 3], [1.0, 2.0, 3.0, 4.0]);

julia> function mymul(A::SparseMatrixCSC, x::Vector)
           y = zeros(promote_type(eltype(A), eltype(x)), size(A, 1))
           rows, vals = rowvals(A), nonzeros(A)
           for j in axes(A, 2), k in nzrange(A, j)
               y[rows[k]] += vals[k] * x[j]
           end
           return y
       end;

julia> mymul(A, [1.0, 10.0, 100.0]) == A * [1.0, 10.0, 100.0]
true

The same three accessors work on a SparseVector and on a column view @view A[:, j], which are treated as a single column: nzrange(x, 1) covers all the stored entries, and rowvals(x) holds their indices.

julia> x = sparsevec([2, 5], [1.5, 2.5], 6);

julia> [(rowvals(x)[k], nonzeros(x)[k]) for k in nzrange(x, 1)]
2-element Vector{Tuple{Int64, Float64}}:
 (2, 1.5)
 (5, 2.5)

In contrast, scalar indexing A[i, j] has to do a binary search of column j for row i. A loop over all (i, j) of an m-by-n matrix therefore performs m * n searches, however few entries are stored, instead of visiting the nnz(A) stored entries once.

Build a matrix from its entries in one call

Storing a value at a position that has no stored entry yet moves all the later entries of rowvals(A) and nonzeros(A) and updates the column pointers, so filling spzeros(m, n) one element at a time takes time proportional to nnz(A) for each insertion. sizehint!(A, n) reserves room for n stored entries, which avoids reallocating those vectors but not moving the entries. Instead, collect the row indices, column indices and values in three vectors and call sparse once. Entries with the same position are added together, or combined with the function passed as the last argument:

julia> I = [1, 1, 2]; J = [1, 1, 2]; V = [1.0, 2.0, 5.0];

julia> sparse(I, J, V)
2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
 3.0   ⋅
  ⋅   5.0

julia> sparse(I, J, V, 2, 2, max)
2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
 2.0   ⋅
  ⋅   5.0

Slice columns, not rows

A[:, j] copies one contiguous range of the stored entries. A[i, :] has to search every column for row i, so its cost grows with the number of columns even when the row is empty. When an algorithm works row by row, transpose the matrix once and work on the columns of the result. permutedims(A) and copy(transpose(A)) (equivalently sparse(transpose(A))) build the transposed matrix in time proportional to nnz(A).

julia> At = permutedims(A);

julia> At[:, 1] == A[1, :]
true

Choose a smaller index type

The index type Ti is used for the column pointers and for one row index per stored entry. With Float64 values, Int32 indices reduce the memory per stored entry from 16 to 12 bytes. Ti is taken from the index vectors given to sparse, can be given to spzeros, and an existing matrix is converted with the type constructor. Both dimensions have to be at most typemax(Ti), and the number of stored entries has to be less than typemax(Ti).

julia> A32 = SparseMatrixCSC{Float64,Int32}(A)
3×3 SparseMatrixCSC{Float64, Int32} with 4 stored entries:
 1.0   ⋅   2.0
  ⋅   3.0   ⋅
  ⋅    ⋅   4.0

julia> typeof(sparse(Int32[1, 2], Int32[1, 2], [1.0, 2.0])) == typeof(spzeros(Float64, Int32, 2, 2))
true

julia> spzeros(Float64, Int8, 200, 200)
ERROR: ArgumentError: number of rows (m = 200) does not fit in Ti = Int8
[...]

Operations between matrices with different index types promote to the wider one, so use one index type consistently.

Lazy transpose and adjoint

transpose(A) and A' do not copy; they return Transpose and Adjoint wrappers around A. The wrappers are handled without materializing the transpose in products with dense vectors and matrices (including mul!), in products with sparse vectors, in \, in ==, and in A'[i, :], which is a column slice of A. Products with another sparse matrix, broadcasting (which includes + and -), map, concatenation, kron and findnz first copy the wrapper into a new SparseMatrixCSC; this is proportional to nnz(A) but is repeated on every call. Other functions, such as sum, norm, and indexing other than by row, reach generic AbstractMatrix methods that visit the wrapper element by element. When a transposed matrix is used more than once, or is passed to code that is not one of the products or solves above, materialize it with copy, or with sparse when the argument may or may not be a wrapper.

julia> A' * [1.0, 10.0, 100.0]
3-element Vector{Float64}:
   1.0
  30.0
 402.0

julia> copy(A')
3×3 SparseMatrixCSC{Float64, Int64} with 4 stored entries:
 1.0   ⋅    ⋅
  ⋅   3.0   ⋅
 2.0   ⋅   4.0

Keep results sparse and free of stored zeros

A result stays sparse only if the operation maps zeros to zeros. A .+ 1 and exp.(A) return a SparseMatrixCSC in which every entry is stored, which is slower and larger than a Matrix; apply such functions to nonzeros(A) instead when only the stored entries are meant. Assigning zero to a stored entry, and cancellation in a matrix product, leave explicitly stored zeros behind. They are harmless for correctness but are visited by every kernel. dropzeros! removes them, droptol! removes entries of small magnitude, and fkeep! keeps the entries for which a predicate of (i, j, v) is true, all in place.

julia> B = copy(A); B[1, 1] = 0; nnz(B)
4

julia> nnz(dropzeros!(B))
3

julia> fkeep!((i, j, v) -> i == j, B)
3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
 ⋅   ⋅    ⋅
 ⋅  3.0   ⋅
 ⋅   ⋅   4.0

Correspondence of dense and sparse methods

The following table gives a correspondence between built-in methods on sparse matrices and their corresponding methods on dense matrix types. In general, methods that generate sparse matrices differ from their dense counterparts in that the resulting matrix follows the same sparsity pattern as a given sparse matrix S, or that the resulting sparse matrix has density d, i.e. each matrix element has a probability d of being non-zero.

Details can be found in the Sparse Vectors and Matrices section of the standard library reference.

SparseDenseDescription
spzeros(m,n)zeros(m,n)Creates a m-by-n matrix of zeros. (spzeros(m,n) is empty.)
sparse(I,n,n)Matrix(I,n,n)Creates a n-by-n identity matrix.
sparse(A)Array(S)Interconverts between dense and sparse formats.
sprand(m,n,d)rand(m,n)Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed uniformly on the half-open interval $[0, 1)$.
sprandn(m,n,d)randn(m,n)Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed according to the standard normal (Gaussian) distribution.
sprandn(rng,m,n,d)randn(rng,m,n)Creates a m-by-n random matrix (of density d) with iid non-zero elements generated with the rng random number generator.

SparseArrays API

SparseArrays — Module

Support for sparse arrays. Provides AbstractSparseArray and subtypes.

SparseArrays.AbstractSparseVector — Type
AbstractSparseVector{Tv,Ti}

Supertype for one-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. Alias for AbstractSparseArray{Tv,Ti,1}.

SparseArrays.AbstractSparseMatrix — Type
AbstractSparseMatrix{Tv,Ti}

Supertype for two-dimensional sparse arrays (or array-like types) with elements of type Tv and index type Ti. Alias for AbstractSparseArray{Tv,Ti,2}.

SparseArrays.SparseVector — Type
SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}

Vector type for storing sparse vectors. Can be created by passing the length of the vector, a sorted vector of non-zero indices, and a vector of non-zero values.

For instance, the vector [5, 6, 0, 7] can be represented as

SparseVector(4, [1, 2, 4], [5, 6, 7])

This indicates that the element at index 1 is 5, at index 2 is 6, at index 3 is zero(Int), and at index 4 is 7.

It may be more convenient to create sparse vectors directly from dense vectors using sparse as

sparse([5, 6, 0, 7])

yields the same sparse vector.

SparseArrays.SparseMatrixCSC — Type
SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}

Matrix type for storing sparse matrices in the Compressed Sparse Column format. The standard way of constructing SparseMatrixCSC is through the sparse function. See also spzeros, spdiagm and sprand.

SparseMatrixCSC(m::Integer, n::Integer, colptr::Vector, rowval::Vector, nzval::Vector)

Wrap existing CSC arrays as an m × n matrix without copying them. Column j holds the entries nzval[k] in rows rowval[k] for k in colptr[j]:(colptr[j+1] - 1).

Only colptr and the lengths of rowval and nzval are checked. The row indices are not inspected, and must be strictly increasing within each column and lie in 1:m. The kernels in this package rely on that. A matrix with unsorted, repeated or out-of-range row indices is constructed silently and then gives inconsistent results. To construct a matrix from repeated indices, use sparse, which adds up their values. See the manual for how to repair such arrays.

Examples

julia> SparseMatrixCSC(3, 2, [1, 3, 4], [1, 3, 2], [1.0, 2.0, 3.0])
3×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
 1.0   ⋅
  ⋅   3.0
 2.0   ⋅
SparseArrays.sparse — Function
sparse(A::Union{AbstractVector, AbstractMatrix})

Convert a vector or matrix A into a sparse array. Numerical zeros in A are turned into structural zeros.

Examples

julia> A = Matrix(1.0I, 3, 3)
3×3 Matrix{Float64}:
 1.0  0.0  0.0
 0.0  1.0  0.0
 0.0  0.0  1.0

julia> sparse(A)
3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
 1.0   ⋅    ⋅
  ⋅   1.0   ⋅
  ⋅    ⋅   1.0

julia> [1.0, 0.0, 1.0]
3-element Vector{Float64}:
 1.0
 0.0
 1.0

julia> sparse([1.0, 0.0, 1.0])
3-element SparseVector{Float64, Int64} with 2 stored entries:
  [1]  =  1.0
  [3]  =  1.0
sparse(I, J, V,[ m, n, combine])

Create a sparse matrix S of dimensions m x n such that S[I[k], J[k]] = V[k]. The combine function is used to combine duplicates. If m and n are not specified, they are set to maximum(I) and maximum(J) respectively. If the combine function is not supplied, combine defaults to + unless the elements of V are Booleans in which case combine defaults to |. All elements of I must satisfy 1 <= I[k] <= m, and all elements of J must satisfy 1 <= J[k] <= n. Numerical zeros in (I, J, V) are retained as structural nonzeros; to drop numerical zeros, use dropzeros!.

For additional documentation and an expert driver, see SparseArrays.sparse!.

Examples

julia> Is = [1; 2; 3];

julia> Js = [1; 2; 3];

julia> Vs = [1; 2; 3];

julia> sparse(Is, Js, Vs)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 1  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  3
SparseArrays.sparse! — Function
sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv},
        m::Integer, n::Integer, combine, klasttouch::Vector{Ti},
        csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv},
        [csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}] ) where {Tv,Ti<:Integer}

Parent of and expert driver for sparse; see sparse for basic usage. This method allows the user to provide preallocated storage for sparse's intermediate objects and result as described below. This capability enables more efficient successive construction of SparseMatrixCSCs from coordinate representations, and also enables extraction of an unsorted-column representation of the result's transpose at no additional cost.

This method consists of three major steps: (1) Counting-sort the provided coordinate representation into an unsorted-row CSR form including repeated entries. (2) Sweep through the CSR form, simultaneously calculating the desired CSC form's column-pointer array, detecting repeated entries, and repacking the CSR form with repeated entries combined; this stage yields an unsorted-row CSR form with no repeated entries. (3) Counting-sort the preceding CSR form into a fully-sorted CSC form with no repeated entries.

Input arrays csrrowptr, csrcolval, and csrnzval constitute storage for the intermediate CSR forms and require length(csrrowptr) >= m + 1, length(csrcolval) >= length(I), and length(csrnzval >= length(I)). Input array klasttouch, workspace for the second stage, requires length(klasttouch) >= n. Optional input arrays csccolptr, cscrowval, and cscnzval constitute storage for the returned CSC form S. If necessary, these are resized automatically to satisfy length(csccolptr) = n + 1, length(cscrowval) = nnz(S) and length(cscnzval) = nnz(S); hence, if nnz(S) is unknown at the outset, passing in empty vectors of the appropriate type (Vector{Ti}() and Vector{Tv}() respectively) suffices, or calling the sparse! method neglecting cscrowval and cscnzval.

On return, csrrowptr, csrcolval, and csrnzval contain an unsorted-column representation of the result's transpose.

You may reuse the input arrays' storage (I, J, V) for the output arrays (csccolptr, cscrowval, cscnzval). For example, you may call sparse!(I, J, V, csrrowptr, csrcolval, csrnzval, I, J, V). Note that they will be resized to satisfy the conditions above.

For the sake of efficiency, this method performs no argument checking beyond 1 <= I[k] <= m and 1 <= J[k] <= n. Use with care. Testing with --check-bounds=yes is wise.

This method runs in O(m, n, length(I)) time. The HALFPERM algorithm described in F. Gustavson, "Two fast algorithms for sparse matrices: multiplication and permuted transposition," ACM TOMS 4(3), 250-269 (1978) inspired this method's use of a pair of counting sorts.

SparseArrays.sparse!(I, J, V, [m, n, combine]) -> SparseMatrixCSC

Variant of sparse! that re-uses the input vectors (I, J, V) for the final matrix storage. After construction the input vectors will alias the matrix buffers; S.colptr === I, S.rowval === J, and S.nzval === V holds, and they will be resize!d as necessary.

Note that some work buffers will still be allocated. Specifically, this method is a convenience wrapper around sparse!(I, J, V, m, n, combine, klasttouch, csrrowptr, csrcolval, csrnzval, csccolptr, cscrowval, cscnzval) where this method allocates klasttouch, csrrowptr, csrcolval, and csrnzval of appropriate size, but reuses I, J, and V for csccolptr, cscrowval, and cscnzval.

Arguments m, n, and combine defaults to maximum(I), maximum(J), and +, respectively.

Julia 1.10

This method requires Julia version 1.10 or later.

SparseArrays.sparsevec — Function
sparsevec(I, V, [m, combine])

Create a sparse vector S of length m such that S[I[k]] = V[k]. Duplicates are combined using the combine function, which defaults to + if no combine argument is provided, unless the elements of V are Booleans in which case combine defaults to |.

Examples

julia> II = [1, 3, 3, 5]; V = [0.1, 0.2, 0.3, 0.2];

julia> sparsevec(II, V)
5-element SparseVector{Float64, Int64} with 3 stored entries:
  [1]  =  0.1
  [3]  =  0.5
  [5]  =  0.2

julia> sparsevec(II, V, 8, -)
8-element SparseVector{Float64, Int64} with 3 stored entries:
  [1]  =  0.1
  [3]  =  -0.1
  [5]  =  0.2

julia> sparsevec([1, 3, 1, 2, 2], [true, true, false, false, false])
3-element SparseVector{Bool, Int64} with 3 stored entries:
  [1]  =  1
  [2]  =  0
  [3]  =  1
sparsevec(d::Dict, [m])

Create a sparse vector of length m where the nonzero indices are keys from the dictionary, and the nonzero values are the values from the dictionary.

Examples

julia> sparsevec(Dict(1 => 3, 2 => 2))
2-element SparseVector{Int64, Int64} with 2 stored entries:
  [1]  =  3
  [2]  =  2
sparsevec(A)

Convert a vector A into a sparse vector of length m. Numerical zeros in A are turned into structural zeros.

Examples

julia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0])
6-element SparseVector{Float64, Int64} with 3 stored entries:
  [1]  =  1.0
  [2]  =  2.0
  [5]  =  3.0
Base.similar — Method
similar(A::AbstractSparseMatrixCSC{Tv,Ti}, [::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer]) where {Tv,Ti}

Create an uninitialized mutable array with the given element type, index type, and size, based upon the given source SparseMatrixCSC. The new sparse matrix maintains the structure of the original sparse matrix, except in the case where dimensions of the output matrix are different from the output.

The output matrix has zeros in the same locations as the input, but uninitialized values for the nonzero locations. A FixedSparseCSC input keeps its fixed pattern only in the structure-preserving form; the forms taking a shape return a SparseMatrixCSC.

SparseArrays.issparse — Function
issparse(S)

Returns true if S is sparse or wraps a sparse array, and false otherwise.

issparse is a classification predicate. A true result does not guarantee support for a particular SparseArrays operation (such as nnz, nonzeros, or findnz), a particular sparse storage format, or that sparse(S) is an identity or efficient operation. Likewise, false means that S is not recognized as sparse by SparseArrays, not that it is dense: an array type that does not subtype AbstractSparseArray or wrap one yields false regardless of its storage. Code requiring a particular sparse interface should dispatch on the relevant abstract type or operation instead of branching on issparse.

Examples

julia> sv = sparsevec([1, 4], [2.3, 2.2], 10)
10-element SparseVector{Float64, Int64} with 2 stored entries:
  [1]  =  2.3
  [4]  =  2.2

julia> issparse(sv)
true

julia> issparse(Array(sv))
false
SparseArrays.nnz — Function
nnz(A)

Returns the number of stored (filled) elements in a sparse array.

Examples

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> nnz(A)
3
SparseArrays.findnz — Function
findnz(A::SparseMatrixCSC)

Return a tuple (I, J, V) where I and J are the row and column indices of the stored ("structurally non-zero") values in sparse matrix A, and V is a vector of the values. A may also be the adjoint or transpose of a sparse matrix or vector, in which case the values in V are correspondingly adjointed or transposed.

Examples

julia> A = sparse([1 2 0; 0 0 3; 0 4 0])
3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 1  2  ⋅
 ⋅  ⋅  3
 ⋅  4  ⋅

julia> findnz(A)
([1, 1, 3, 2], [1, 2, 2, 3], [1, 2, 4, 3])
SparseArrays.spzeros — Function
spzeros([type,]m[,n])

Create a sparse vector of length m or sparse matrix of size m x n. This sparse array will not contain any nonzero values, and no storage is allocated for them. The type defaults to Float64 if not specified.

This does not make the call allocation-free: the empty index and value buffers are still allocated, and a matrix additionally allocates a column pointer of n + 1 entries, so an m x n matrix uses memory proportional to n.

Examples

julia> spzeros(3, 3)
3×3 SparseMatrixCSC{Float64, Int64} with 0 stored entries:
 ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅

julia> spzeros(Float32, 4)
4-element SparseVector{Float32, Int64} with 0 stored entries
spzeros([type], I::AbstractVector, J::AbstractVector, [m, n])

Create a sparse matrix S of dimensions m x n with structural zeros at S[I[k], J[k]].

This method can be used to construct the sparsity pattern of the matrix, and is more efficient than using e.g. sparse(I, J, zeros(length(I))).

For additional documentation and an expert driver, see SparseArrays.spzeros!.

Julia 1.10

This methods requires Julia version 1.10 or later.

SparseArrays.spzeros! — Function
spzeros!(::Type{Tv}, I::AbstractVector{Ti}, J::AbstractVector{Ti}, m::Integer, n::Integer,
         klasttouch::Vector{Ti}, csrrowptr::Vector{Ti}, csrcolval::Vector{Ti},
         [csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}]) where {Tv,Ti<:Integer}

Parent of and expert driver for spzeros(I, J) allowing user to provide preallocated storage for intermediate objects. This method is to spzeros what SparseArrays.sparse! is to sparse. See documentation for SparseArrays.sparse! for details and required buffer lengths.

Julia 1.10

This methods requires Julia version 1.10 or later.

SparseArrays.spzeros!(::Type{Tv}, I, J, [m, n]) -> SparseMatrixCSC{Tv}

Variant of spzeros! that re-uses the input vectors I and J for the final matrix storage. After construction the input vectors will alias the matrix buffers; S.colptr === I and S.rowval === J holds, and they will be resize!d as necessary.

Note that some work buffers will still be allocated. Specifically, this method is a convenience wrapper around spzeros!(Tv, I, J, m, n, klasttouch, csrrowptr, csrcolval, csccolptr, cscrowval) where this method allocates klasttouch, csrrowptr, and csrcolval of appropriate size, but reuses I and J for csccolptr and cscrowval.

Arguments m and n defaults to maximum(I) and maximum(J).

Julia 1.10

This method requires Julia version 1.10 or later.

SparseArrays.spdiagm — Function
spdiagm(kv::Pair{<:Integer,<:AbstractVector}...)
spdiagm(m::Integer, n::Integer, kv::Pair{<:Integer,<:AbstractVector}...)

Construct a sparse diagonal matrix from Pairs of vectors and diagonals. Each vector kv.second will be placed on the kv.first diagonal. By default, the matrix is square and its size is inferred from kv, but a non-square size m×n (padded with zeros as needed) can be specified by passing m,n as the first arguments.

Examples

julia> spdiagm(-1 => [1,2,3,4], 1 => [4,3,2,1])
5×5 SparseMatrixCSC{Int64, Int64} with 8 stored entries:
 ⋅  4  ⋅  ⋅  ⋅
 1  ⋅  3  ⋅  ⋅
 ⋅  2  ⋅  2  ⋅
 ⋅  ⋅  3  ⋅  1
 ⋅  ⋅  ⋅  4  ⋅
spdiagm(v::AbstractVector)
spdiagm(m::Integer, n::Integer, v::AbstractVector)

Construct a sparse matrix with elements of the vector as diagonal elements. By default (no given m and n), the matrix is square and its size is given by length(v), but a non-square size m×n can be specified by passing m and n as the first arguments.

Julia 1.6

These functions require at least Julia 1.6.

Examples

julia> spdiagm([1,2,3])
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 1  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  3

julia> spdiagm(sparse([1,0,3]))
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 1  ⋅  ⋅
 ⋅  ⋅  ⋅
 ⋅  ⋅  3
SparseArrays.sparse_hcat — Function
sparse_hcat(A...)

Concatenate along dimension 2. Return a SparseMatrixCSC object.

Julia 1.8

This method was added in Julia 1.8. It mimics previous concatenation behavior, where the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl automatically yielded sparse output even in the absence of any SparseArray argument.

SparseArrays.sparse_vcat — Function
sparse_vcat(A...)

Concatenate along dimension 1. Return a SparseMatrixCSC object.

Julia 1.8

This method was added in Julia 1.8. It mimics previous concatenation behavior, where the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl automatically yielded sparse output even in the absence of any SparseArray argument.

SparseArrays.sparse_hvcat — Function
sparse_hvcat(rows::Tuple{Vararg{Int}}, values...)

Sparse horizontal and vertical concatenation in one call. This function is called for block matrix syntax. The first argument specifies the number of arguments to concatenate in each block row.

Julia 1.8

This method was added in Julia 1.8. It mimics previous concatenation behavior, where the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl automatically yielded sparse output even in the absence of any SparseArray argument.

SparseArrays.blockdiag — Function
blockdiag(A...)

Concatenate matrices block-diagonally. Currently only implemented for sparse matrices.

Examples

julia> blockdiag(sparse(2I, 3, 3), sparse(4I, 2, 2))
5×5 SparseMatrixCSC{Int64, Int64} with 5 stored entries:
 2  ⋅  ⋅  ⋅  ⋅
 ⋅  2  ⋅  ⋅  ⋅
 ⋅  ⋅  2  ⋅  ⋅
 ⋅  ⋅  ⋅  4  ⋅
 ⋅  ⋅  ⋅  ⋅  4
SparseArrays.sprand — Function
sprand([rng],[T::Type],m,[n],p::AbstractFloat)
sprand([rng],m,[n],p::AbstractFloat,[rfn=rand])

Create a random length m sparse vector or m by n sparse matrix, in which the probability of any element being nonzero is independently given by p (and hence the mean density of nonzeros is also exactly p). The optional rng argument specifies a random number generator, see Random Numbers. The optional T argument specifies the element type, which defaults to Float64.

By default, nonzero values are sampled from a uniform distribution using the rand function, i.e. by rand(T), or rand(rng, T) if rng is supplied; for the default T=Float64, this corresponds to nonzero values sampled uniformly in [0,1).

You can sample nonzero values from a different distribution by passing a custom rfn function instead of rand. This should be a function rfn(k) that returns an array of k random numbers sampled from the desired distribution; alternatively, if rng is supplied, it should instead be a function rfn(rng, k).

Examples

julia> sprand(Bool, 2, 2, 0.5)
2×2 SparseMatrixCSC{Bool, Int64} with 2 stored entries:
 1  1
 ⋅  ⋅

julia> sprand(Float64, 3, 0.75)
3-element SparseVector{Float64, Int64} with 2 stored entries:
  [1]  =  0.795547
  [2]  =  0.49425
SparseArrays.sprandn — Function
sprandn([rng][,Type],m[,n],p::AbstractFloat)

Create a random sparse vector of length m or sparse matrix of size m by n with the specified (independent) probability p of any entry being nonzero, where nonzero values are sampled from the normal distribution. The optional rng argument specifies a random number generator, see Random Numbers.

Julia 1.1

Specifying the output element type Type requires at least Julia 1.1.

Examples

julia> sprandn(2, 2, 0.75)
2×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
 -1.20577       ⋅
  0.311817  -0.234641
SparseArrays.getcolptr — Function
getcolptr(S)

Return the vector of column start indices of an AbstractSparseMatrixCSC pointing into rowvals and nonzeros: column j is stored at positions getcolptr(S)[j]:(getcolptr(S)[j+1] - 1). The returned vector aliases S, but implementations with fixed sparsity may make it read-only. When it is writable, modifications to it mutate S. See also getrowval, getnzval and nzrange.

Examples

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> getcolptr(A)
4-element Vector{Int64}:
 1
 2
 3
 4
SparseArrays.getrowval — Function
getrowval(A)

Return the vector of row indices of the structural nonzeros of sparse array A. For a SparseMatrixCSC this is the rowval field; for a SparseVector it is the nzind field. Any modifications to the returned vector will mutate A as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also getnzval and nzrange.

getrowval is equivalent to rowvals.

Examples

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> getrowval(A)
3-element Vector{Int64}:
 1
 2
 3

julia> getrowval(sparsevec([2, 5], [3.0, 4.0]))
2-element Vector{Int64}:
 2
 5
SparseArrays.getnzval — Function
getnzval(A)

Return the vector of structural nonzero values of sparse array A, i.e. the nzval field of a SparseMatrixCSC or SparseVector. This includes zeros that are explicitly stored in the sparse array. The returned vector points directly to the internal nonzero storage of A, and any modifications to the returned vector will mutate A as well. See also getrowval and nzrange.

getnzval is equivalent to nonzeros.

Examples

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> getnzval(A)
3-element Vector{Int64}:
 2
 2
 2

julia> getnzval(sparsevec([2, 5], [3.0, 4.0]))
2-element Vector{Float64}:
 3.0
 4.0
SparseArrays.indtype — Function
indtype(S)

Return the type used to index sparse array entries.

Examples

julia> indtype(sparse(Int32[1, 2], Int32[1, 2], [1.0, 2.0]))
Int32
SparseArrays.nonzeros — Function
nonzeros(A)

Return a vector of the structural nonzero values in sparse array A. This includes zeros that are explicitly stored in the sparse array. The returned vector points directly to the internal nonzero storage of A, and any modifications to the returned vector will mutate A as well. See rowvals and nzrange.

Examples

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> nonzeros(A)
3-element Vector{Int64}:
 2
 2
 2
SparseArrays.rowvals — Function
rowvals(A)

Return a vector of the row indices of sparse array A. Any modifications to the returned vector will mutate A as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also nonzeros and nzrange.

Examples

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> rowvals(A)
3-element Vector{Int64}:
 1
 2
 3

For a sparse vector or a column view of a sparse matrix, rowvals returns the indices of the stored entries:

julia> rowvals(sparsevec([2, 5], [1.5, 2.5], 6))
2-element Vector{Int64}:
 2
 5
SparseArrays.nzrange — Function
nzrange(A, col::Integer)

Return the range of indices to the structural nonzero values of column col of sparse array A. In conjunction with nonzeros and rowvals, this allows for convenient iterating over a sparse matrix :

A = sparse(I,J,V)
rows = rowvals(A)
vals = nonzeros(A)
m, n = size(A)
for j = 1:n
   for i in nzrange(A, j)
      row = rows[i]
      val = vals[i]
      # perform sparse wizardry...
   end
end
Warning

Adding or removing nonzero elements to the matrix may invalidate the nzrange, one should not mutate the matrix while iterating.

nzrange(x::SparseVectorOrView, col)

Give the range of indices to the structural nonzero values of a sparse vector. The column index col is ignored (assumed to be 1).

SparseArrays.droptol! — Function
droptol!(A::AbstractSparseMatrixCSC, tol)

Removes stored values from A whose absolute value is less than or equal to tol.

droptol!(x::AbstractCompressedVector, tol)

Removes stored values from x whose absolute value is less than or equal to tol.

SparseArrays.dropzeros! — Function
dropzeros!(x::AbstractCompressedVector)

Removes stored numerical zeros from x.

For an out-of-place version, see dropzeros. For algorithmic information, see fkeep!.

SparseArrays.dropzeros — Function
dropzeros(A::AbstractSparseMatrixCSC;)

Generates a copy of A and removes stored numerical zeros from that copy.

For an in-place version and algorithmic information, see dropzeros!.

Examples

julia> A = sparse([1, 2, 3], [1, 2, 3], [1.0, 0.0, 1.0])
3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
 1.0   ⋅    ⋅
  ⋅   0.0   ⋅
  ⋅    ⋅   1.0

julia> dropzeros(A)
3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
 1.0  ⋅   ⋅
  ⋅   ⋅   ⋅
  ⋅   ⋅  1.0
dropzeros(x::AbstractCompressedVector)

Generates a copy of x and removes numerical zeros from that copy.

For an in-place version and algorithmic information, see dropzeros!.

Examples

julia> A = sparsevec([1, 2, 3], [1.0, 0.0, 1.0])
3-element SparseVector{Float64, Int64} with 3 stored entries:
  [1]  =  1.0
  [2]  =  0.0
  [3]  =  1.0

julia> dropzeros(A)
3-element SparseVector{Float64, Int64} with 2 stored entries:
  [1]  =  1.0
  [3]  =  1.0
SparseArrays.dropstored! — Function
dropstored!(A::AbstractSparseMatrixCSC, i::Integer, j::Integer)

Drop entry A[i,j] from A if A[i,j] is stored, and otherwise do nothing.

julia> A = sparse([1 2; 0 0])
2×2 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 1  2
 ⋅  ⋅

julia> SparseArrays.dropstored!(A, 1, 2); A
2×2 SparseMatrixCSC{Int64, Int64} with 1 stored entry:
 1  ⋅
 ⋅  ⋅
dropstored!(A::AbstractSparseMatrixCSC, I::AbstractVector{<:Integer}, J::AbstractVector{<:Integer})

For each (i,j) where i in I and j in J, drop entry A[i,j] from A if A[i,j] is stored and otherwise do nothing. Derivative forms:

dropstored!(A::AbstractSparseMatrixCSC, i::Integer, J::AbstractVector{<:Integer})
dropstored!(A::AbstractSparseMatrixCSC, I::AbstractVector{<:Integer}, j::Integer)

Examples

julia> A = sparse(Diagonal([1, 2, 3, 4]))
4×4 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 1  ⋅  ⋅  ⋅
 ⋅  2  ⋅  ⋅
 ⋅  ⋅  3  ⋅
 ⋅  ⋅  ⋅  4

julia> SparseArrays.dropstored!(A, [1, 2], [1, 1])
4×4 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 ⋅  ⋅  ⋅  ⋅
 ⋅  2  ⋅  ⋅
 ⋅  ⋅  3  ⋅
 ⋅  ⋅  ⋅  4
dropstored!(x::SparseVector, i::Integer)

Drop entry x[i] from x if x[i] is stored and otherwise do nothing.

Examples

julia> x = sparsevec([1, 3], [1.0, 2.0])
3-element SparseVector{Float64, Int64} with 2 stored entries:
  [1]  =  1.0
  [3]  =  2.0

julia> SparseArrays.dropstored!(x, 3)
3-element SparseVector{Float64, Int64} with 1 stored entry:
  [1]  =  1.0

julia> SparseArrays.dropstored!(x, 2)
3-element SparseVector{Float64, Int64} with 1 stored entry:
  [1]  =  1.0
SparseArrays.fkeep! — Function
fkeep!(f, A::AbstractSparseArray)

Keep elements of A for which test f returns true. f's signature should be

f(i::Integer, [j::Integer,] x) -> Bool

where i and j are an element's row and column indices and x is the element's value. This method makes a single sweep through A, requiring O(size(A, 2), nnz(A))-time for matrices and O(nnz(A))-time for vectors and no space beyond that passed in.

Examples

julia> A = sparse(Diagonal([1, 2, 3, 4]))
4×4 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
 1  ⋅  ⋅  ⋅
 ⋅  2  ⋅  ⋅
 ⋅  ⋅  3  ⋅
 ⋅  ⋅  ⋅  4

julia> SparseArrays.fkeep!((i, j, v) -> isodd(v), A)
4×4 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
 1  ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  3  ⋅
 ⋅  ⋅  ⋅  ⋅
SparseArrays.permute — Function
permute(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},
        q::AbstractVector{<:Integer}) where {Tv,Ti}

Bilaterally permute A, returning PAQ (A[p,q]). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).

For expert drivers and additional information, see permute!.

Examples

julia> A = spdiagm(0 => [1, 2, 3, 4], 1 => [5, 6, 7])
4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
 1  5  ⋅  ⋅
 ⋅  2  6  ⋅
 ⋅  ⋅  3  7
 ⋅  ⋅  ⋅  4

julia> permute(A, [4, 3, 2, 1], [1, 2, 3, 4])
4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
 ⋅  ⋅  ⋅  4
 ⋅  ⋅  3  7
 ⋅  2  6  ⋅
 1  5  ⋅  ⋅

julia> permute(A, [1, 2, 3, 4], [4, 3, 2, 1])
4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
 ⋅  ⋅  5  1
 ⋅  6  2  ⋅
 7  3  ⋅  ⋅
 4  ⋅  ⋅  ⋅
Base.permute! — Method
permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti},
         p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer},
         [C::AbstractSparseMatrixCSC{Tv,Ti}]) where {Tv,Ti}

Bilaterally permute A, storing result PAQ (A[p,q]) in X. Stores intermediate result (AQ)^T (transpose(A[:,q])) in optional argument C if present. Requires that none of X, A, and, if present, C alias each other; to store result PAQ back into A, use the following method lacking X:

permute!(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},
         q::AbstractVector{<:Integer}[, C::AbstractSparseMatrixCSC{Tv,Ti},
         [workcolptr::Vector{Ti}]]) where {Tv,Ti}

X's dimensions must match those of A (size(X, 1) == size(A, 1) and size(X, 2) == size(A, 2)), and X must have enough storage to accommodate all allocated entries in A (length(rowvals(X)) >= nnz(A) and length(nonzeros(X)) >= nnz(A)). Column-permutation q's length must match A's column count (length(q) == size(A, 2)). Row-permutation p's length must match A's row count (length(p) == size(A, 1)).

C's dimensions must match those of transpose(A) (size(C, 1) == size(A, 2) and size(C, 2) == size(A, 1)), and C must have enough storage to accommodate all allocated entries in A (length(rowvals(C)) >= nnz(A) and length(nonzeros(C)) >= nnz(A)).

For additional (algorithmic) information, and for versions of these methods that forgo argument checking, see (unexported) parent methods unchecked_noalias_permute! and unchecked_aliasing_permute!.

See also permute.

SparseArrays.halfperm! — Function
halfperm!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{TvA,Ti},
          q::AbstractVector{<:Integer}, f::Function = identity) where {Tv,TvA,Ti}

Column-permute and transpose A, simultaneously applying f to each entry of A, storing the result (f(A)Q)^T (map(f, transpose(A[:,q]))) in X.

Element type Tv of X must match f(::TvA), where TvA is the element type of A. X's dimensions must match those of transpose(A) (size(X, 1) == size(A, 2) and size(X, 2) == size(A, 1)), and X must have enough storage to accommodate all allocated entries in A (length(rowvals(X)) >= nnz(A) and length(nonzeros(X)) >= nnz(A)). Column-permutation q's length must match A's column count (length(q) == size(A, 2)).

This method is the parent of several methods performing transposition and permutation operations on SparseMatrixCSCs. As this method performs no argument checking, prefer the safer child methods ([c]transpose[!], permute[!]) to direct use.

This method implements the HALFPERM algorithm described in F. Gustavson, "Two fast algorithms for sparse matrices: multiplication and permuted transposition," ACM TOMS 4(3), 250-269 (1978). The algorithm runs in O(size(A, 1), size(A, 2), nnz(A)) time and requires no space beyond that passed in.

SparseArrays.ftranspose! — Function
ftranspose!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}, f::Function) where {Tv,Ti}

Transpose A and store it in X while applying the function f to the non-zero elements. Does not remove the zeros created by f. size(X) must be equal to size(transpose(A)). No additional memory is allocated other than resizing the rowval and nzval of X, if needed.

See halfperm!

LinearAlgebra.transpose! — Method
transpose!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}) where {Tv,Ti}

Transpose the matrix A and stores it in the matrix X. size(X) must be equal to size(transpose(A)). No additional memory is allocated other than resizing the rowval and nzval of X, if needed.

See halfperm!

LinearAlgebra.adjoint! — Method
adjoint!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}) where {Tv,Ti}

Transpose the matrix A and stores the adjoint of the elements in the matrix X. size(X) must be equal to size(transpose(A)). No additional memory is allocated other than resizing the rowval and nzval of X, if needed.

See halfperm!

Base.sort! — Method
sort!(A::AbstractSparseMatrixCSC; dims::Integer, kws...)

Sort A in place along dimension dims, moving its stored entries to their sorted positions without adding new stored entries, so that nnz(A) is unchanged. Within each column (or row), stored values that compare equal to zero under the ordering are grouped after the structural zeros, so the result may differ from the dense sort! for orderings that do not distinguish stored values from zero (such as by = iszero).

A may not be a FixedSparseCSC, since its row indices are read-only; use sort instead.

The remaining keyword arguments are those of sort! for a Vector.

Base.sort — Method
sort(A::AbstractSparseMatrixCSC; dims::Integer, kws...)

Return a sorted copy of A along dimension dims as a SparseMatrixCSC, keeping only the stored entries of A. See sort! for the treatment of stored values that compare equal to zero.

Base.sort! — Method
sort!(x::AbstractCompressedVector; kws...)
sort!(x::SparseColumnView; kws...)

Sort the stored entries of x in place and rewrite the stored indices so that the values sorting before zero(eltype(x)) end up at the start of x and the remaining values at the end, with the structural zeros in between. Stored values that compare equal to zero under the ordering are placed after the structural zeros. nnz(x) is left untouched.

A column view view(A, :, j) of a sparse matrix is sorted through the same method, which is how sort! of a sparse matrix sorts each column.

x may not be a fixed sparse vector, nor a column view of a fixed sparse matrix, since its stored indices are read-only.

LinearAlgebra.opnorm — Method
opnorm(A::AbstractMatrix, p::Real=2)

Compute the operator norm (or matrix norm) induced by the vector p-norm, where valid values of p are 1, 2, or Inf. (Note that for sparse matrices, p=2 is currently not implemented.) Use norm to compute the Frobenius norm.

When p=1, the operator norm is the maximum absolute column sum of A:

\[\|A\|_1 = \max_{1 ≤ j ≤ n} \sum_{i=1}^m | a_{ij} |\]

with $a_{ij}$ the entries of $A$, and $m$ and $n$ its dimensions.

When p=2, the operator norm is the spectral norm, equal to the largest singular value of A.

When p=Inf, the operator norm is the maximum absolute row sum of A:

\[\|A\|_\infty = \max_{1 ≤ i ≤ m} \sum _{j=1}^n | a_{ij} |\]

Examples

julia> A = [1 -2 -3; 2 3 -1]
2×3 Matrix{Int64}:
 1  -2  -3
 2   3  -1

julia> opnorm(A, Inf)
6.0

julia> opnorm(A, 1)
5.0
opnorm(A::AbstractSparseMatrixCSC, p::Real=2)

Operator p-norm of the sparse matrix A, for p equal to 1, 2 or Inf.

For p = 2 the norm is an iterative estimate from Lanczos bidiagonalization rather than a full singular value decomposition. It approaches the norm from below, to a relative accuracy of about 1e-10, and is computed in Float64 arithmetic even when the element type is wider. Each iteration costs a product with A and one with A'. Matrices whose largest singular values are tightly clustered may need a number of iterations comparable to their size; use opnorm(Array(A)) when such a matrix is small enough.

SparseArrays.fixed — Function
fixed(x...)

Experimental. Like sparse but returns a sparse array whose sparsity pattern is read-only: stored entries can change value, but none can be added or removed.

SparseArrays.FixedSparseCSC — Type
FixedSparseCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}

Experimental AbstractSparseMatrixCSC whose non-zero index are fixed.

SparseArrays.FixedSparseVector — Type
FixedSparseVector{Tv,Ti<:Integer} <: AbstractCompressedVector{Tv,Ti}

Experimental AbstractCompressedVector whose non-zero index are fixed.

SparseArrays.allowscalar — Function
allowscalar(::Bool)

An experimental function that allows one to disable and re-enable scalar indexing for sparse matrices and vectors.

allowscalar(false) will disable scalar indexing for sparse matrices and vectors. allowscalar(true) will restore the original scalar indexing functionality.

Since this function overwrites existing definitions, it will lead to recompilation. It is useful mainly when testing code for devices such as GPUs, where the presence of scalar indexing can lead to substantial slowdowns. Disabling scalar indexing during such tests can help identify performance bottlenecks quickly.

Internals

The helpers below are not part of the API: they are unexported, may change or disappear in any release. This internal documentation is also not complete, but it is meant to be treated as a companion to the documentation of the public facing APIs adding more details and colour.

SparseArrays.ReadOnly — Type

ReadOnly{T,N,<:AbstractArray{T,N,V<:AbstractArray{T,N}}} <: AbstractArray{T,N}

Internal. Wrapper around an AbstractArray that blocks change. Practically no-op operations are not blocked. For instance, setindex!(x, getindex(x, i...), i...) or resize!(x, length(x)) for x isa ReadOnly.

SparseArrays.ColumnIndices — Type
ColumnIndices(S::AbstractSparseMatrixCSC)

Return the column indices of the stored values in S. This is an internal type that is used in displaying sparse matrices, and is not a part of the public interface.

SparseArrays.iswrsparse — Function
iswrsparse(::S)
iswrsparse(::Type{S})

Returns true if type S is backed by a sparse array, and false otherwise.

SparseArrays.depth — Function
depth(::Type{S})

Returns 0 for unwrapped S, and nesting depth for wrapped (nested) abstract arrays.

SparseArrays.sparse_with_lmul — Function
sparse_with_lmul(Tv, Ti, Q) -> SparseMatrixCSC

Helper function that creates a SparseMatrixCSC{Tv,Ti} representation of Q, where Q is supposed to not have fast getindex or not admit an iteration protocol at all, but instead a fast lmul!(Q, v) for dense vectors v. The prime example for such Qs is the Q factor of a (sparse) QR decomposition.

SparseArrays.rowcheck_index — Function
rowcheck_index(A::AbstractSparseMatrixCSC, row::Integer, col::Integer)

Check if A[row, col] is a stored value, and return the index of the row in rowvals(A). Returns (row_exists, row_ind), where row_exists::Bool signifies whether the corresponding index is populated, and row_ind is the index. If row_exists is false, the row_ind is the index where the value should be inserted into rowvals(A) such that the subarray @view rowvals(A)[nzrange(A, col)] remains sorted.

SparseArrays.mergeinds! — Function
mergeinds!(C::AbstractSparseMatrixCSC, A::AbstractSparseMatrixCSC)

Update C to contain stored values corresponding to the stored indices of A. Stored indices common to C and A are not touched. Indices of A at which C did not have a stored value are populated with zeros after the call.

Examples

julia> A = spzeros(3,3);

julia> A[4:4:8] .= 1;

julia> A
3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
 ⋅  1.0   ⋅
 ⋅   ⋅   1.0
 ⋅   ⋅    ⋅

julia> C = spzeros(3,3);

julia> C[2:4:6] .= 2;

julia> C
3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
  ⋅    ⋅   ⋅
 2.0   ⋅   ⋅
  ⋅   2.0  ⋅

julia> SparseArrays.mergeinds!(C, A)
3×3 SparseMatrixCSC{Float64, Int64} with 4 stored entries:
  ⋅   0.0   ⋅
 2.0   ⋅   0.0
  ⋅   2.0   ⋅
SparseArrays.move_fixed — Function
move_fixed(x::AbstractSparseMatrixCSC)

Experimental, unsafe. Make a FixedSparseCSC by reusing the colptr, rowvals and nonzeros of x.

SparseArrays._unsafe_unfix — Function
_unsafe_unfix(x)

Experimental, unsafe. Returns a modifiable version of x for compatibility with this codebase.

inverse of fixed, should not allocate

SparseArrays.@RCI — Macro
@RCI f

records the function f to be overwritten (and restored) with allowscalar(::Bool). This is an experimental feature.

Note that it will evaluate the function in the top level of the package. The original code for f is stored in _restore_scalar_indexing and a function that has the same definition as f but returns an error is stored in _destroy_scalar_indexing.

SparseArrays._densify! — Function
_densify!(x::AbstractCompressedVector, active::AbstractUnitRange{Int})

Make every index of active a stored entry of x, filling the new ones with zero, and return the range of storage positions that then holds x[active]. A fixed pattern cannot grow, so it must already cover active, which is checked before anything is written.

SparseArrays.HigherOrderFns._map_zeropres! — Function

Gives C the pattern of A and stores f(A[i])/f(A[i,j]) at each stored entry, whether or not that value is zero, so that f.(A) keeps its stored zeros like 2A and float(A) do.

SparseArrays._spsetz_setindex! — Function

Helper method for immediately preceding fill! method. For all (i,j) such that i in I and j in J, assigns zero to A[i,j] if A[i,j] is a presently-stored entry, and otherwise does nothing.

SparseArrays._spsetnz_setindex! — Function

Helper method for immediately preceding fill! method. For all (i,j) such that i in I and j in J, assigns x to A[i,j] if A[i,j] is a presently-stored entry, and allocates and assigns x to A[i,j] if A[i,j] is not presently stored.

SparseArrays.unchecked_noalias_permute! — Function
unchecked_noalias_permute!(X::AbstractSparseMatrixCSC{Tv,Ti},
    A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},
    q::AbstractVector{<:Integer}, C::AbstractSparseMatrixCSC{Tv,Ti}) where {Tv,Ti}

See permute! for basic usage. Parent of permute[!] methods operating on SparseMatrixCSCs that assume none of X, A, and C alias each other. As this method performs no argument checking, prefer the safer child methods (permute[!]) to direct use.

This method consists of two major steps: (1) Column-permute (Q,I[:,q]) and transpose A to generate intermediate result (AQ)^T (transpose(A[:,q])) in C. (2) Column-permute (P^T, I[:,p]) and transpose intermediate result (AQ)^T to generate result ((AQ)^T P^T)^T = PAQ (A[p,q]) in X.

The first step is a call to halfperm!, and the second is a variant on halfperm! that avoids an unnecessary length-nnz(A) array-sweep and associated recomputation of column pointers. See halfperm! for additional algorithmic information.

See also unchecked_aliasing_permute!.

SparseArrays.unchecked_aliasing_permute! — Function
unchecked_aliasing_permute!(A::AbstractSparseMatrixCSC{Tv,Ti},
    p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer},
    C::AbstractSparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) where {Tv,Ti}

See permute! for basic usage. Parent of permute! methods operating on SparseMatrixCSCs where the source and destination matrices are the same. See unchecked_noalias_permute! for additional information; these methods are identical but for this method's requirement of the additional workcolptr, length(workcolptr) >= size(A, 2) + 1, which enables efficient handling of the source-destination aliasing.

SparseArrays._computecolptrs_permute! — Function

Helper method for unchecked_noalias_permute! and unchecked_aliasing_permute!. Computes PAQ's column pointers, storing them shifted one position forward in getcolptr(X); _distributevals_halfperm! fixes this shift. Saves some work relative to _computecolptrs_halfperm! as described in uncheckednoalias_permute!'s documentation.

SparseArrays._computecolptrs_halfperm! — Function

Helper method for halfperm!. Computes transpose(A[:,q])'s column pointers, storing them shifted one position forward in getcolptr(X); _distributevals_halfperm! fixes this shift.

SparseArrays._distributevals_halfperm! — Function

Helper method for halfperm!. With transpose(A[:,q])'s column pointers shifted one position forward in getcolptr(X), computes map(f, transpose(A[:,q])) by appropriately distributing rowvals(A) and f-transformed nonzeros(A) into rowvals(X) and nonzeros(X) respectively. Simultaneously fixes the one-position-forward shift in getcolptr(X).

Noteworthy External Sparse Packages

Several other Julia packages provide sparse matrix implementations that should be mentioned:

  1. SuiteSparseGraphBLAS.jl is a wrapper over the fast, multithreaded SuiteSparse:GraphBLAS C library.

  2. CUDA.jl exposes the CUSPARSE library for GPU sparse matrix operations.

  3. SparseMatricesCSR.jl provides a Julia native implementation of the Compressed Sparse Rows (CSR) format.

  4. MKLSparse.jl accelerates SparseArrays sparse-dense matrix operations using Intel's MKL library.

  5. SparseArrayKit.jl available for multidimensional sparse arrays.

  6. LuxurySparse.jl provides static sparse array formats, as well as a coordinate format.

  7. ExtendableSparse.jl enables fast insertion into sparse matrices using a lazy approach to new stored indices.

  8. Finch.jl supports extensive multidimensional sparse array formats and operations through a mini tensor language and compiler, all in native Julia. Support for COO, CSF, CSR, CSC and more, as well as operations like broadcast, reduce, etc. and custom operations.

External packages providing sparse direct solvers:

  1. KLU.jl

  2. Pardiso.jl

External packages providing solvers for iterative solution of eigensystems and singular value decompositions:

  1. ArnoldiMethod.jl

  2. KrylovKit

  3. Arpack.jl

External packages for working with graphs:

  1. Graphs.jl