|
1 | 1 | using Accessors: @set
|
2 |
| -using Dictionaries: Dictionary, IndexError, set! |
| 2 | +using Dictionaries: AbstractDictionary, Dictionary, IndexError, set! |
3 | 3 |
|
4 | 4 | function default_getunstoredindex(a::AbstractArray, I::Int...)
|
5 | 5 | return zero(eltype(a))
|
6 | 6 | end
|
7 | 7 |
|
| 8 | +const DOKStorage{T,N} = Dictionary{CartesianIndex{N},T} |
| 9 | + |
8 | 10 | struct SparseArrayDOK{T,N,F} <: AbstractSparseArray{T,N}
|
9 |
| - storage::Dictionary{CartesianIndex{N},T} |
| 11 | + storage::DOKStorage{T,N} |
10 | 12 | size::NTuple{N,Int}
|
11 | 13 | getunstoredindex::F
|
12 |
| -end |
13 | 14 |
|
14 |
| -function set_getunstoredindex(a::SparseArrayDOK, f) |
15 |
| - @set a.getunstoredindex = f |
16 |
| - return a |
17 |
| -end |
18 |
| - |
19 |
| -using DerivableInterfaces: DerivableInterfaces |
20 |
| -# This defines the destination type of various operations in DerivableInterfaces.jl. |
| 15 | + # bare constructor |
| 16 | + function SparseArrayDOK{T,N,F}( |
| 17 | + ::UndefInitializer, size::Dims{N}, getunstoredindex::F |
| 18 | + ) where {T,N,F} |
| 19 | + storage = DOKStorage{T,N}() |
| 20 | + return new{T,N,F}(storage, size, getunstoredindex) |
| 21 | + end |
21 | 22 |
|
22 |
| -Base.similar(::AbstractSparseArrayInterface, T::Type, ax) = SparseArrayDOK{T}(undef, ax) |
| 23 | + # unchecked constructor from data |
| 24 | + function SparseArrayDOK{T,N,F}( |
| 25 | + storage::DOKStorage{T,N}, size::Dims{N}, getunstoredindex::F |
| 26 | + ) where {T,N,F} |
| 27 | + return new{T,N,F}(storage, size, getunstoredindex) |
| 28 | + end |
| 29 | +end |
23 | 30 |
|
24 |
| -function SparseArrayDOK{T,N}(size::Vararg{Int,N}) where {T,N} |
25 |
| - getunstoredindex = default_getunstoredindex |
| 31 | +# undef constructors |
| 32 | +function SparseArrayDOK{T}( |
| 33 | + ::UndefInitializer, dims::Dims, getunstoredindex=default_getunstoredindex |
| 34 | +) where {T} |
| 35 | + all(≥(0), dims) || throw(ArgumentError("Invalid dimensions: $dims")) |
| 36 | + N = length(dims) |
26 | 37 | F = typeof(getunstoredindex)
|
27 |
| - return SparseArrayDOK{T,N,F}(Dictionary{CartesianIndex{N},T}(), size, getunstoredindex) |
| 38 | + return SparseArrayDOK{T,N,F}(undef, dims, getunstoredindex) |
28 | 39 | end
|
29 |
| - |
30 |
| -function SparseArrayDOK{T}(::UndefInitializer, size::Tuple{Vararg{Int}}) where {T} |
31 |
| - return SparseArrayDOK{T,length(size)}(size...) |
| 40 | +function SparseArrayDOK{T}(::UndefInitializer, dims::Int...) where {T} |
| 41 | + return SparseArrayDOK{T}(undef, dims) |
32 | 42 | end
|
33 | 43 |
|
34 |
| -function SparseArrayDOK{T}(size::Int...) where {T} |
35 |
| - return SparseArrayDOK{T,length(size)}(size...) |
| 44 | +# checked constructor from data: use `setindex!` to validate input |
| 45 | +# does not take ownership of `storage`! |
| 46 | +function SparseArrayDOK( |
| 47 | + storage::Union{AbstractDictionary{I,T},AbstractDict{I,T}}, dims::Dims{N}, unstored... |
| 48 | +) where {N,I<:Union{Int,CartesianIndex{N}},T} |
| 49 | + A = SparseArrayDOK{T}(undef, dims, unstored...) |
| 50 | + for (i, v) in pairs(storage) |
| 51 | + A[i] = v |
| 52 | + end |
| 53 | + return A |
36 | 54 | end
|
37 | 55 |
|
38 | 56 | function SparseArrayDOK{T}(::UndefInitializer, axes::Tuple) where {T}
|
39 | 57 | return SparseArrayDOK{T}(undef, Base.to_shape(axes))
|
40 | 58 | end
|
41 | 59 |
|
| 60 | +function set_getunstoredindex(a::SparseArrayDOK, f) |
| 61 | + @set a.getunstoredindex = f |
| 62 | + return a |
| 63 | +end |
| 64 | + |
| 65 | +Base.similar(::AbstractSparseArrayInterface, T::Type, ax) = SparseArrayDOK{T}(undef, ax) |
| 66 | + |
42 | 67 | using DerivableInterfaces: @array_aliases
|
43 | 68 | # Define `SparseMatrixDOK`, `AnySparseArrayDOK`, etc.
|
44 | 69 | @array_aliases SparseArrayDOK
|
|
0 commit comments