Skip to content

Commit 4ee8aa3

Browse files
authored
[SparseArraysBase] Rename SparseArrayInterface to SparseArraysBase (#1591)
0 parents  commit 4ee8aa3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2058
-0
lines changed

.JuliaFormatter.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
style = "blue"
2+
indent = 2

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# SparseArraysBase
2+
3+
Defines a generic interface for sparse arrays in Julia.
4+
5+
The minimal interface is:
6+
```julia
7+
nonzeros(a::AbstractArray) = ...
8+
nonzero_index_to_index(a::AbstractArray, Inz) = ...
9+
index_to_nonzero_index(a::AbstractArray{<:Any,N}, I::CartesianIndex{N}) where {N} = ...
10+
Broadcast.BroadcastStyle(arraytype::Type{<:AbstractArray}) = SparseArraysBase.SparseArrayStyle{ndims(arraytype)}()
11+
```
12+
Once these are defined, along with Julia AbstractArray interface functions like
13+
`Base.size` and `Base.similar`, functions like the following will take advantage of sparsity:
14+
```julia
15+
SparseArraysBase.nonzero_length # SparseArrays.nnz
16+
SparseArraysBase.sparse_getindex
17+
SparseArraysBase.sparse_setindex!
18+
SparseArraysBase.sparse_map!
19+
SparseArraysBase.sparse_copy!
20+
SparseArraysBase.sparse_copyto!
21+
SparseArraysBase.sparse_permutedims!
22+
```
23+
which can be used to define the corresponding `Base` functions.
24+
25+
## TODO
26+
Still need to implement `Base` functions:
27+
```julia
28+
[x] sparse_zero(a::AbstractArray) = similar(a)
29+
[x] sparse_iszero(a::AbstractArray) = iszero(nonzero_length(a)) # Uses `all`, make `sparse_all`?
30+
[x] sparse_one(a::AbstractArray) = ...
31+
[x] sparse_isreal(a::AbstractArray) = ... # Uses `all`, make `sparse_all`?
32+
[x] sparse_isequal(a1::AbstractArray, a2::AbstractArray) = ...
33+
[x] sparse_conj!(a::AbstractArray) = conj!(nonzeros(a))
34+
[x] sparse_reshape(a::AbstractArray, dims) = ...
35+
[ ] sparse_all(f, a::AbstractArray) = ...
36+
[ ] sparse_getindex(a::AbstractArray, 1:2, 2:3) = ... # Slicing
37+
```
38+
`LinearAlgebra` functions:
39+
```julia
40+
[ ] sparse_mul!
41+
[ ] sparse_lmul!
42+
[ ] sparse_ldiv!
43+
[ ] sparse_rdiv!
44+
[ ] sparse_axpby!
45+
[ ] sparse_axpy!
46+
[ ] sparse_norm
47+
[ ] sparse_dot/sparse_inner
48+
[ ] sparse_adoint!
49+
[ ] sparse_transpose!
50+
51+
# Using conversion to `SparseMatrixCSC`:
52+
[ ] sparse_qr
53+
[ ] sparse_eigen
54+
[ ] sparse_svd
55+
```
56+
`TensorAlgebra` functions:
57+
```julia
58+
[ ] add!
59+
[ ] contract!
60+
```

src/SparseArraysBase.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module SparseArraysBase
2+
include("sparsearrayinterface/arraylayouts.jl")
3+
include("sparsearrayinterface/densearray.jl")
4+
include("sparsearrayinterface/vectorinterface.jl")
5+
include("sparsearrayinterface/interface.jl")
6+
include("sparsearrayinterface/interface_optional.jl")
7+
include("sparsearrayinterface/indexing.jl")
8+
include("sparsearrayinterface/base.jl")
9+
include("sparsearrayinterface/map.jl")
10+
include("sparsearrayinterface/copyto.jl")
11+
include("sparsearrayinterface/broadcast.jl")
12+
include("sparsearrayinterface/conversion.jl")
13+
include("sparsearrayinterface/wrappers.jl")
14+
include("sparsearrayinterface/zero.jl")
15+
include("sparsearrayinterface/cat.jl")
16+
include("sparsearrayinterface/SparseArraysBaseLinearAlgebraExt.jl")
17+
include("abstractsparsearray/abstractsparsearray.jl")
18+
include("abstractsparsearray/abstractsparsematrix.jl")
19+
include("abstractsparsearray/abstractsparsevector.jl")
20+
include("abstractsparsearray/wrappedabstractsparsearray.jl")
21+
include("abstractsparsearray/arraylayouts.jl")
22+
include("abstractsparsearray/sparsearrayinterface.jl")
23+
include("abstractsparsearray/base.jl")
24+
include("abstractsparsearray/broadcast.jl")
25+
include("abstractsparsearray/map.jl")
26+
include("abstractsparsearray/baseinterface.jl")
27+
include("abstractsparsearray/convert.jl")
28+
include("abstractsparsearray/cat.jl")
29+
include("abstractsparsearray/SparseArraysBaseSparseArraysExt.jl")
30+
include("abstractsparsearray/SparseArraysBaseLinearAlgebraExt.jl")
31+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using LinearAlgebra: LinearAlgebra
2+
3+
LinearAlgebra.norm(a::AbstractSparseArray, p::Real=2) = sparse_norm(a, p)
4+
5+
# a1 * a2 * α + a_dest * β
6+
function LinearAlgebra.mul!(
7+
a_dest::AbstractMatrix,
8+
a1::AbstractSparseMatrix,
9+
a2::AbstractSparseMatrix,
10+
α::Number=true,
11+
β::Number=false,
12+
)
13+
sparse_mul!(a_dest, a1, a2, α, β)
14+
return a_dest
15+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Base: Forward
2+
using SparseArrays: SparseArrays, SparseMatrixCSC, findnz, getcolptr, nonzeros, rowvals
3+
using ..SparseArraysBase: stored_length
4+
5+
# Julia Base `AbstractSparseArray` interface
6+
SparseArrays.nnz(a::AbstractSparseArray) = stored_length(a)
7+
8+
sparse_storage(a::SparseMatrixCSC) = nonzeros(a)
9+
function storage_index_to_index(a::SparseMatrixCSC, I)
10+
I1s, I2s = findnz(a)
11+
return CartesianIndex(I1s[I], I2s[I])
12+
end
13+
function index_to_storage_index(a::SparseMatrixCSC, I::CartesianIndex{2})
14+
i0, i1 = Tuple(I)
15+
r1 = getcolptr(a)[i1]
16+
r2 = getcolptr(a)[i1 + 1] - 1
17+
(r1 > r2) && return nothing
18+
r1 = searchsortedfirst(rowvals(a), i0, r1, r2, Forward)
19+
return ((r1 > r2) || (rowvals(a)[r1] != i0)) ? nothing : r1
20+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using ArrayLayouts: LayoutArray
2+
3+
abstract type AbstractSparseArray{T,N} <: LayoutArray{T,N} end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const AbstractSparseMatrix{T} = AbstractSparseArray{T,2}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const AbstractSparseVector{T} = AbstractSparseArray{T,1}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using ArrayLayouts: ArrayLayouts, Dot, DualLayout, MatMulMatAdd, MatMulVecAdd, MulAdd
2+
using LinearAlgebra: Adjoint, Transpose
3+
using ..TypeParameterAccessors: parenttype
4+
5+
function ArrayLayouts.MemoryLayout(arraytype::Type{<:AnyAbstractSparseArray})
6+
return SparseLayout()
7+
end
8+
9+
# TODO: Generalize to `SparseVectorLike`/`AnySparseVector`.
10+
function ArrayLayouts.MemoryLayout(arraytype::Type{<:Adjoint{<:Any,<:AbstractSparseVector}})
11+
return DualLayout{typeof(MemoryLayout(parenttype(arraytype)))}()
12+
end
13+
# TODO: Generalize to `SparseVectorLike`/`AnySparseVector`.
14+
function ArrayLayouts.MemoryLayout(
15+
arraytype::Type{<:Transpose{<:Any,<:AbstractSparseVector}}
16+
)
17+
return DualLayout{typeof(MemoryLayout(parenttype(arraytype)))}()
18+
end
19+
20+
function sparse_matmul!(m::MulAdd)
21+
α, a1, a2, β, a_dest = m.α, m.A, m.B, m.β, m.C
22+
sparse_mul!(a_dest, a1, a2, α, β)
23+
return a_dest
24+
end
25+
26+
function ArrayLayouts.materialize!(
27+
m::MatMulMatAdd{<:AbstractSparseLayout,<:AbstractSparseLayout,<:AbstractSparseLayout}
28+
)
29+
sparse_matmul!(m)
30+
return m.C
31+
end
32+
function ArrayLayouts.materialize!(
33+
m::MatMulVecAdd{<:AbstractSparseLayout,<:AbstractSparseLayout,<:AbstractSparseLayout}
34+
)
35+
sparse_matmul!(m)
36+
return m.C
37+
end
38+
39+
function Base.copy(d::Dot{<:SparseLayout,<:SparseLayout})
40+
return sparse_dot(d.A, d.B)
41+
end

src/abstractsparsearray/base.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using ..SparseArraysBase: SparseArraysBase
2+
3+
# Base
4+
function Base.:(==)(a1::AnyAbstractSparseArray, a2::AnyAbstractSparseArray)
5+
return SparseArraysBase.sparse_isequal(a1, a2)
6+
end
7+
8+
function Base.reshape(a::AnyAbstractSparseArray, dims::Tuple{Vararg{Int}})
9+
return SparseArraysBase.sparse_reshape(a, dims)
10+
end
11+
12+
function Base.zero(a::AnyAbstractSparseArray)
13+
return SparseArraysBase.sparse_zero(a)
14+
end
15+
16+
function Base.one(a::AnyAbstractSparseArray)
17+
return SparseArraysBase.sparse_one(a)
18+
end

0 commit comments

Comments
 (0)