Skip to content

Commit a4c599d

Browse files
committed
Be a bit more mindful with constructors
1 parent 268f119 commit a4c599d

File tree

4 files changed

+78
-50
lines changed

4 files changed

+78
-50
lines changed

examples/README.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ using SparseArraysBase:
5353
zero!
5454
using Test: @test, @test_throws
5555

56-
a = SparseArrayDOK{Float64}(2, 2)
56+
a = SparseArrayDOK{Float64}(undef, 2, 2)
5757

5858
# AbstractArray interface:
5959

@@ -118,32 +118,32 @@ b = a[1:2, 2]
118118
@test b == [12, 0]
119119
@test storedlength(b) == 1
120120

121-
a = SparseArrayDOK{Float64}(2, 2)
121+
a = SparseArrayDOK{Float64}(undef, 2, 2)
122122
a .= 2
123123
for I in eachindex(a)
124124
@test a[I] == 2
125125
end
126126
@test storedlength(a) == length(a)
127127

128-
a = SparseArrayDOK{Float64}(2, 2)
128+
a = SparseArrayDOK{Float64}(undef, 2, 2)
129129
fill!(a, 2)
130130
for I in eachindex(a)
131131
@test a[I] == 2
132132
end
133133
@test storedlength(a) == length(a)
134134

135-
a = SparseArrayDOK{Float64}(2, 2)
135+
a = SparseArrayDOK{Float64}(undef, 2, 2)
136136
fill!(a, 0)
137137
@test iszero(a)
138138
@test iszero(storedlength(a))
139139

140-
a = SparseArrayDOK{Float64}(2, 2)
140+
a = SparseArrayDOK{Float64}(undef, 2, 2)
141141
a[1, 2] = 12
142142
zero!(a)
143143
@test iszero(a)
144144
@test iszero(storedlength(a))
145145

146-
a = SparseArrayDOK{Float64}(2, 2)
146+
a = SparseArrayDOK{Float64}(undef, 2, 2)
147147
a[1, 2] = 12
148148
b = zero(a)
149149
@test iszero(b)

src/abstractsparsearrayinterface.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ end
243243
a::AbstractArray, T::Type, size::Tuple{Vararg{Int}}
244244
)
245245
# TODO: Define `default_similartype` or something like that?
246-
return SparseArrayDOK{T}(size...)
246+
return SparseArrayDOK{T}(undef, size)
247247
end
248248

249249
# map over a specified subset of indices of the inputs.

src/sparsearraydok.jl

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,56 @@
11
using Accessors: @set
2-
using Dictionaries: Dictionary, IndexError, set!
2+
using Dictionaries: AbstractDictionary, Dictionary, IndexError, set!
33

44
function default_getunstoredindex(a::AbstractArray, I::Int...)
55
return zero(eltype(a))
66
end
77

8+
const DOKStorage{T,N} = Dictionary{CartesianIndex{N},T}
9+
810
struct SparseArrayDOK{T,N,F} <: AbstractSparseArray{T,N}
9-
storage::Dictionary{CartesianIndex{N},T}
11+
storage::DOKStorage{T,N}
1012
size::NTuple{N,Int}
1113
getunstoredindex::F
14+
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
22+
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
30+
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)
37+
F = typeof(getunstoredindex)
38+
return SparseArrayDOK{T,N,F}(undef, dims, getunstoredindex)
39+
end
40+
function SparseArrayDOK{T}(::UndefInitializer, dims::Int...) where {T}
41+
return SparseArrayDOK{T}(undef, dims)
42+
end
43+
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
1254
end
1355

1456
function set_getunstoredindex(a::SparseArrayDOK, f)
@@ -20,20 +62,6 @@ using DerivableInterfaces: DerivableInterfaces
2062
# This defines the destination type of various operations in DerivableInterfaces.jl.
2163
DerivableInterfaces.arraytype(::AbstractSparseArrayInterface, T::Type) = SparseArrayDOK{T}
2264

23-
function SparseArrayDOK{T,N}(size::Vararg{Int,N}) where {T,N}
24-
getunstoredindex = default_getunstoredindex
25-
F = typeof(getunstoredindex)
26-
return SparseArrayDOK{T,N,F}(Dictionary{CartesianIndex{N},T}(), size, getunstoredindex)
27-
end
28-
29-
function SparseArrayDOK{T}(::UndefInitializer, size::Tuple{Vararg{Int}}) where {T}
30-
return SparseArrayDOK{T,length(size)}(size...)
31-
end
32-
33-
function SparseArrayDOK{T}(size::Int...) where {T}
34-
return SparseArrayDOK{T,length(size)}(size...)
35-
end
36-
3765
using DerivableInterfaces: @array_aliases
3866
# Define `SparseMatrixDOK`, `AnySparseArrayDOK`, etc.
3967
@array_aliases SparseArrayDOK

test/test_sparsearraydok.jl

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ arrayts = (Array,)
2323

2424
dev(x) = adapt(arrayt, x)
2525

26-
a = SparseArrayDOK{elt}(2, 2)
26+
a = SparseArrayDOK{elt}(undef, 2, 2)
2727
a[1, 2] = 12
2828
@test a isa SparseArrayDOK{elt,2}
2929
@test size(a) == (2, 2)
@@ -33,15 +33,15 @@ arrayts = (Array,)
3333
@test a[1, 2, 1] == 12
3434
@test storedlength(a) == 1
3535

36-
a = SparseArrayDOK{elt}(2, 2)
36+
a = SparseArrayDOK{elt}(undef, 2, 2)
3737
a[1, 2] = 12
3838
for b in (similar(a, Float32, (3, 3)), similar(a, Float32, Base.OneTo.((3, 3))))
3939
@test b isa SparseArrayDOK{Float32,2}
4040
@test b == zeros(Float32, 3, 3)
4141
@test size(b) == (3, 3)
4242
end
4343

44-
a = SparseArrayDOK{elt}(2, 2)
44+
a = SparseArrayDOK{elt}(undef, 2, 2)
4545
a[1, 2] = 12
4646
b = similar(a)
4747
bc = Broadcast.Broadcasted(x -> 2x, (a,))
@@ -50,49 +50,49 @@ arrayts = (Array,)
5050
@test b == [0 24; 0 0]
5151
@test storedlength(b) == 1
5252

53-
a = SparseArrayDOK{elt}(3, 3, 3)
53+
a = SparseArrayDOK{elt}(undef, 3, 3, 3)
5454
a[1, 2, 3] = 123
5555
b = permutedims(a, (2, 3, 1))
5656
@test b isa SparseArrayDOK{elt,3}
5757
@test b[2, 3, 1] == 123
5858
@test storedlength(b) == 1
5959

60-
a = SparseArrayDOK{elt}(2, 2)
60+
a = SparseArrayDOK{elt}(undef, 2, 2)
6161
a[1, 2] = 12
6262
b = copy(a')
6363
@test b isa SparseArrayDOK{elt,2}
6464
@test b == [0 0; 12 0]
6565
@test storedlength(b) == 1
6666

67-
a = SparseArrayDOK{elt}(2, 2)
67+
a = SparseArrayDOK{elt}(undef, 2, 2)
6868
a[1, 2] = 12
6969
b = map(x -> 2x, a)
7070
@test b isa SparseArrayDOK{elt,2}
7171
@test b == [0 24; 0 0]
7272
@test storedlength(b) == 1
7373

74-
a = SparseArrayDOK{elt}(2, 2)
74+
a = SparseArrayDOK{elt}(undef, 2, 2)
7575
a[1, 2] = 12
7676
b = a * a'
7777
@test b isa SparseArrayDOK{elt,2}
7878
@test b == [144 0; 0 0]
7979
@test storedlength(b) == 1
8080

81-
a = SparseArrayDOK{elt}(2, 2)
81+
a = SparseArrayDOK{elt}(undef, 2, 2)
8282
a[1, 2] = 12
8383
b = a .+ 2 .* a'
8484
@test b isa SparseArrayDOK{elt,2}
8585
@test b == [0 12; 24 0]
8686
@test storedlength(b) == 2
8787

88-
a = SparseArrayDOK{elt}(2, 2)
88+
a = SparseArrayDOK{elt}(undef, 2, 2)
8989
a[1, 2] = 12
9090
b = a[1:2, 2]
9191
@test b isa SparseArrayDOK{elt,1}
9292
@test b == [12, 0]
9393
@test storedlength(b) == 1
9494

95-
a = SparseArrayDOK{elt}(2, 2)
95+
a = SparseArrayDOK{elt}(undef, 2, 2)
9696
@test iszero(a)
9797
a[2, 1] = 21
9898
a[1, 2] = 12
@@ -101,7 +101,7 @@ arrayts = (Array,)
101101
@test sum(a) == 33
102102
@test mapreduce(x -> 2x, +, a) == 66
103103

104-
a = SparseArrayDOK{elt}(2, 2)
104+
a = SparseArrayDOK{elt}(undef, 2, 2)
105105
a[1, 2] = 12
106106
b = similar(a)
107107
copyto!(b, a)
@@ -110,58 +110,58 @@ arrayts = (Array,)
110110
@test b[1, 2] == 12
111111
@test storedlength(b) == 1
112112

113-
a = SparseArrayDOK{elt}(2, 2)
113+
a = SparseArrayDOK{elt}(undef, 2, 2)
114114
a .= 2
115115
@test storedlength(a) == length(a)
116116
for I in eachindex(a)
117117
@test a[I] == 2
118118
end
119119

120-
a = SparseArrayDOK{elt}(2, 2)
120+
a = SparseArrayDOK{elt}(undef, 2, 2)
121121
fill!(a, 2)
122122
@test storedlength(a) == length(a)
123123
for I in eachindex(a)
124124
@test a[I] == 2
125125
end
126126

127-
a = SparseArrayDOK{elt}(2, 2)
127+
a = SparseArrayDOK{elt}(undef, 2, 2)
128128
a[1, 2] = 12
129129
zero!(a)
130130
@test iszero(a)
131131
@test iszero(storedlength(a))
132132

133-
a = SparseArrayDOK{elt}(2, 2)
133+
a = SparseArrayDOK{elt}(undef, 2, 2)
134134
a[1, 2] = 12
135135
b = zero(a)
136136
@test b isa SparseArrayDOK{elt,2}
137137
@test iszero(b)
138138
@test iszero(storedlength(b))
139139

140-
a = SparseArrayDOK{elt}(2, 2)
140+
a = SparseArrayDOK{elt}(undef, 2, 2)
141141
a[1, 2] = 12
142-
b = SparseArrayDOK{elt}(4, 4)
142+
b = SparseArrayDOK{elt}(undef, 4, 4)
143143
b[2:3, 2:3] .= a
144144
@test isone(storedlength(b))
145145
@test b[2, 3] == 12
146146

147-
a = SparseArrayDOK{elt}(2, 2)
147+
a = SparseArrayDOK{elt}(undef, 2, 2)
148148
a[1, 2] = 12
149-
b = SparseArrayDOK{elt}(4, 4)
149+
b = SparseArrayDOK{elt}(undef, 4, 4)
150150
b[2:3, 2:3] = a
151151
@test isone(storedlength(b))
152152
@test b[2, 3] == 12
153153

154-
a = SparseArrayDOK{elt}(2, 2)
154+
a = SparseArrayDOK{elt}(undef, 2, 2)
155155
a[1, 2] = 12
156-
b = SparseArrayDOK{elt}(4, 4)
156+
b = SparseArrayDOK{elt}(undef, 4, 4)
157157
c = @view b[2:3, 2:3]
158158
c .= a
159159
@test isone(storedlength(b))
160160
@test b[2, 3] == 12
161161

162-
a1 = SparseArrayDOK{elt}(2, 2)
162+
a1 = SparseArrayDOK{elt}(undef, 2, 2)
163163
a1[1, 2] = 12
164-
a2 = SparseArrayDOK{elt}(2, 2)
164+
a2 = SparseArrayDOK{elt}(undef, 2, 2)
165165
a2[2, 1] = 21
166166
b = cat(a1, a2; dims=(1, 2))
167167
@test b isa SparseArrayDOK{elt,2}
@@ -173,21 +173,21 @@ arrayts = (Array,)
173173
# Printing
174174
# Not testing other element types since they change the
175175
# spacing so it isn't easy to make the test general.
176-
a = SparseArrayDOK{elt}(2, 2)
176+
a = SparseArrayDOK{elt}(undef, 2, 2)
177177
a[1, 2] = 12
178178
@test sprint(show, "text/plain", a) == "$(summary(a)):\n$(eltype(a)(12))\n ⋅ ⋅"
179179
end
180180

181181
# Regression test for:
182182
# https://github.com/ITensor/SparseArraysBase.jl/issues/19
183-
a = SparseArrayDOK{elt}(2, 2)
183+
a = SparseArrayDOK{elt}(undef, 2, 2)
184184
a[1, 1] = 1
185185
a .*= 2
186186
@test a == [2 0; 0 0]
187187
@test storedlength(a) == 1
188188

189189
# Test aliasing behavior.
190-
a = SparseArrayDOK{elt}(2, 2)
190+
a = SparseArrayDOK{elt}(undef, 2, 2)
191191
a[1, 1] = 11
192192
a[1, 2] = 12
193193
a[2, 2] = 22
@@ -202,7 +202,7 @@ arrayts = (Array,)
202202
@test storedlength(a) == 3
203203

204204
# Test aliasing behavior.
205-
a = SparseArrayDOK{elt}(2, 2)
205+
a = SparseArrayDOK{elt}(undef, 2, 2)
206206
a[1, 1] = 11
207207
a[1, 2] = 12
208208
a[2, 2] = 22

0 commit comments

Comments
 (0)