Skip to content

Commit 7e82d1a

Browse files
committed
New design for handling unstored values
1 parent 1dd8127 commit 7e82d1a

File tree

9 files changed

+260
-226
lines changed

9 files changed

+260
-226
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SparseArraysBase"
22
uuid = "0d5efcca-f356-4864-8770-e1ed8d78f208"
33
authors = ["ITensor developers <[email protected]> and contributors"]
4-
version = "0.6.0"
4+
version = "0.7.0"
55

66
[deps]
77
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ SparseArraysBase = "0d5efcca-f356-4864-8770-e1ed8d78f208"
88
Dictionaries = "0.4.4"
99
Documenter = "1.8.1"
1010
Literate = "2.20.1"
11-
SparseArraysBase = "0.6.0"
11+
SparseArraysBase = "0.7.0"

examples/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
55

66
[compat]
77
Dictionaries = "0.4.4"
8-
SparseArraysBase = "0.6.0"
8+
SparseArraysBase = "0.7.0"
99
Test = "<0.0.1, 1"

src/abstractsparsearray.jl

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,33 @@ using DerivableInterfaces: @derive
2020
using ArrayLayouts: ArrayLayouts
2121
using LinearAlgebra: LinearAlgebra
2222

23-
# DerivableInterfaces `Base.getindex`, `Base.setindex!`, etc.
24-
# TODO: Define `AbstractMatrixOps` and overload for
25-
# `AnyAbstractSparseMatrix` and `AnyAbstractSparseVector`,
26-
# which is where matrix multiplication and factorizations
27-
# should go.
28-
@derive AnyAbstractSparseArray AbstractArrayOps
23+
@derive (T=AnyAbstractSparseArray,) begin
24+
Base.getindex(::T, ::Any...)
25+
Base.getindex(::T, ::Int...)
26+
Base.setindex!(::T, ::Any, ::Any...)
27+
Base.setindex!(::T, ::Any, ::Int...)
28+
Base.similar(::T, ::Type, ::Tuple{Vararg{Int}})
29+
Base.similar(::T, ::Type, ::Tuple{Base.OneTo,Vararg{Base.OneTo}})
30+
Base.copy(::T)
31+
Base.copy!(::AbstractArray, ::T)
32+
Base.copyto!(::AbstractArray, ::T)
33+
Base.map(::Any, ::T...)
34+
Base.map!(::Any, ::AbstractArray, ::T...)
35+
Base.mapreduce(::Any, ::Any, ::T...; kwargs...)
36+
Base.reduce(::Any, ::T...; kwargs...)
37+
Base.all(::Function, ::T)
38+
Base.all(::T)
39+
Base.iszero(::T)
40+
Base.real(::T)
41+
Base.fill!(::T, ::Any)
42+
DerivableInterfaces.zero!(::T)
43+
Base.zero(::T)
44+
Base.permutedims!(::Any, ::T, ::Any)
45+
Broadcast.BroadcastStyle(::Type{<:T})
46+
Base.copyto!(::T, ::Broadcast.Broadcasted{Broadcast.DefaultArrayStyle{0}})
47+
ArrayLayouts.MemoryLayout(::Type{<:T})
48+
LinearAlgebra.mul!(::AbstractMatrix, ::T, ::T, ::Number, ::Number)
49+
end
2950

3051
using DerivableInterfaces.Concatenate: concatenate
3152
# We overload `Base._cat` instead of `Base.cat` since it
@@ -75,27 +96,30 @@ from the input indices.
7596
This constructor does not take ownership of the supplied storage, and will result in an
7697
independent container.
7798
"""
78-
sparse(::Union{AbstractDict,AbstractDictionary}, dims...; kwargs...)
99+
sparse(::Union{AbstractDict,AbstractDictionary}, dims...)
79100

80101
const AbstractDictOrDictionary = Union{AbstractDict,AbstractDictionary}
81102
# checked constructor from data: use `setindex!` to validate/convert input
82-
function sparse(storage::AbstractDictOrDictionary, dims::Dims; kwargs...)
83-
A = SparseArrayDOK{valtype(storage)}(undef, dims; kwargs...)
103+
function sparse(storage::AbstractDictOrDictionary, unstored::AbstractArray)
104+
A = SparseArrayDOK(Unstored(unstored))
84105
for (i, v) in pairs(storage)
85106
A[i] = v
86107
end
87108
return A
88109
end
89-
function sparse(storage::AbstractDictOrDictionary, dims::Int...; kwargs...)
90-
return sparse(storage, dims; kwargs...)
110+
function sparse(storage::AbstractDictOrDictionary, ax::Tuple)
111+
return sparse(storage, Zeros{valtype(storage)}(ax))
112+
end
113+
function sparse(storage::AbstractDictOrDictionary, dims::Int...)
114+
return sparse(storage, dims)
91115
end
92116
# Determine the size automatically.
93-
function sparse(storage::AbstractDictOrDictionary; kwargs...)
117+
function sparse(storage::AbstractDictOrDictionary)
94118
dims = ntuple(Returns(0), length(keytype(storage)))
95119
for I in keys(storage)
96120
dims = map(max, dims, Tuple(I))
97121
end
98-
return sparse(storage, dims; kwargs...)
122+
return sparse(storage, dims)
99123
end
100124

101125
using Random: Random, AbstractRNG, default_rng
@@ -107,12 +131,18 @@ Create an empty size `dims` sparse array.
107131
The optional `T` argument specifies the element type, which defaults to `Float64`.
108132
""" sparsezeros
109133

110-
function sparsezeros(::Type{T}, dims::Dims; kwargs...) where {T}
111-
return SparseArrayDOK{T}(undef, dims; kwargs...)
134+
function sparsezeros(::Type{T}, unstored::AbstractArray{<:Any,N}) where {T,N}
135+
return SparseArrayDOK{T,N}(Unstored(unstored))
136+
end
137+
function sparsezeros(unstored::AbstractArray{T,N}) where {T,N}
138+
return SparseArrayDOK{T,N}(Unstored(unstored))
139+
end
140+
function sparsezeros(::Type{T}, dims::Dims) where {T}
141+
return sparsezeros(T, Zeros{T}(dims))
112142
end
113-
sparsezeros(::Type{T}, dims::Int...; kwargs...) where {T} = sparsezeros(T, dims; kwargs...)
114-
sparsezeros(dims::Dims; kwargs...) = sparsezeros(Float64, dims; kwargs...)
115-
sparsezeros(dims::Int...; kwargs...) = sparsezeros(Float64, dims; kwargs...)
143+
sparsezeros(::Type{T}, dims::Int...) where {T} = sparsezeros(T, dims)
144+
sparsezeros(dims::Dims) = sparsezeros(Float64, dims)
145+
sparsezeros(dims::Int...) = sparsezeros(Float64, dims)
116146

117147
@doc """
118148
sparserand([rng], [T::Type], dims; density::Real=0.5, randfun::Function=rand) -> A::SparseArrayDOK{T}

src/abstractsparsearrayinterface.jl

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using Base: @_propagate_inbounds_meta
22
using DerivableInterfaces:
33
DerivableInterfaces, @derive, @interface, AbstractArrayInterface, zero!
4+
using FillArrays: Zeros
45

6+
function unstored end
57
function eachstoredindex end
68
function getstoredindex end
79
function getunstoredindex end
@@ -12,9 +14,27 @@ function storedlength end
1214
function storedpairs end
1315
function storedvalues end
1416

15-
# Replace the function for accessing
16-
# unstored values.
17-
function set_getunstoredindex end
17+
# Indicates that the array should be interpreted
18+
# as the unstored values of a sparse array.
19+
struct Unstored{T,N,P<:AbstractArray{T,N}} <: AbstractArray{T,N}
20+
parent::P
21+
end
22+
Base.parent(a::Unstored) = a.parent
23+
24+
unstored(a::AbstractArray) = Zeros{eltype(a)}(axes(a))
25+
26+
function unstoredsimilar(a::AbstractArray, T::Type, ax::Tuple)
27+
return Zeros{T}(ax)
28+
end
29+
function unstoredsimilar(a::AbstractArray, T::Type)
30+
return unstoredsimilar(a, T, axes(a))
31+
end
32+
function unstoredsimilar(a::AbstractArray, ax::Tuple)
33+
return unstoredsimilar(a, eltype(a), ax)
34+
end
35+
function unstoredsimilar(a::AbstractArray)
36+
return unstoredsimilar(a, eltype(a), axes(a))
37+
end
1838

1939
# Generic functionality for converting to a
2040
# dense array, trying to preserve information
@@ -84,13 +104,22 @@ Base.size(a::StoredValues) = size(a.storedindices)
84104
return setindex!(a.array, value, a.storedindices[I])
85105
end
86106

87-
# TODO: This may need to be defined in `sparsearraydok.jl`, after `SparseArrayDOK`
88-
# is defined. And/or define `default_type(::SparseArrayStyle, T::Type) = SparseArrayDOK{T}`.
89107
@interface ::AbstractSparseArrayInterface function Base.similar(
90-
a::AbstractArray, T::Type, size::Tuple{Vararg{Int}}
108+
a::AbstractArray, T::Type, ax::Tuple
91109
)
92-
# TODO: Define `default_similartype` or something like that?
93-
return SparseArrayDOK{T}(undef, size)
110+
return SparseArrayDOK(Unstored(unstoredsimilar(unstored(a), T, ax)))
111+
end
112+
# Fix ambiguity error with DerivableInterfaces.jl.
113+
@interface ::AbstractSparseArrayInterface function Base.similar(
114+
a::AbstractArray, T::Type, ax::Tuple{Int,Vararg{Int}}
115+
)
116+
return SparseArrayDOK(Unstored(unstoredsimilar(unstored(a), T, ax)))
117+
end
118+
# Fix ambiguity error with DerivableInterfaces.jl.
119+
@interface ::AbstractSparseArrayInterface function Base.similar(
120+
a::AbstractArray, T::Type, ax::Tuple{Base.OneTo,Vararg{Base.OneTo}}
121+
)
122+
return SparseArrayDOK(Unstored(unstoredsimilar(unstored(a), T, ax)))
94123
end
95124
using DerivableInterfaces: DerivableInterfaces, zero!
96125

@@ -136,7 +165,10 @@ end
136165

137166
abstract type AbstractSparseArrayStyle{N} <: Broadcast.AbstractArrayStyle{N} end
138167

139-
@derive AbstractSparseArrayStyle AbstractArrayStyleOps
168+
@derive (T=AbstractSparseArrayStyle,) begin
169+
Base.similar(::Broadcast.Broadcasted{<:T}, ::Type, ::Tuple)
170+
Base.copyto!(::AbstractArray, ::Broadcast.Broadcasted{<:T})
171+
end
140172

141173
struct SparseArrayStyle{N} <: AbstractSparseArrayStyle{N} end
142174

0 commit comments

Comments
 (0)