1
1
@eval module $ (gensym ())
2
2
using Compat: Returns
3
3
using Test: @test , @testset , @test_broken
4
- using BlockArrays: Block, BlockedOneTo, blockedrange, blocklengths, blocksize
4
+ using BlockArrays:
5
+ AbstractBlockArray, Block, BlockedOneTo, blockedrange, blocklengths, blocksize
5
6
using NDTensors. BlockSparseArrays: BlockSparseArray, block_nstored
6
7
using NDTensors. GradedAxes:
7
- GradedAxes, GradedOneTo, UnitRangeDual, blocklabels, dual, gradedrange
8
+ GradedAxes,
9
+ GradedOneTo,
10
+ GradedUnitRange,
11
+ GradedUnitRangeDual,
12
+ blocklabels,
13
+ dual,
14
+ gradedrange,
15
+ isdual
8
16
using NDTensors. LabelledNumbers: label
9
17
using NDTensors. SparseArrayInterface: nstored
10
18
using NDTensors. TensorAlgebra: fusedims, splitdims
19
+ using LinearAlgebra: adjoint
11
20
using Random: randn!
12
21
function blockdiagonal! (f, a:: AbstractArray )
13
22
for i in 1 : minimum (blocksize (a))
@@ -31,15 +40,15 @@ const elts = (Float32, Float64, Complex{Float32}, Complex{Float64})
31
40
d2 = gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ])
32
41
a = BlockSparseArray {elt} (d1, d2, d1, d2)
33
42
blockdiagonal! (randn!, a)
43
+ @test axes (a, 1 ) isa GradedOneTo
44
+ @test axes (view (a, 1 : 4 , 1 : 4 , 1 : 4 , 1 : 4 ), 1 ) isa GradedOneTo
34
45
35
46
for b in (a + a, 2 * a)
36
47
@test size (b) == (4 , 4 , 4 , 4 )
37
48
@test blocksize (b) == (2 , 2 , 2 , 2 )
38
49
@test blocklengths .(axes (b)) == ([2 , 2 ], [2 , 2 ], [2 , 2 ], [2 , 2 ])
39
50
@test nstored (b) == 32
40
51
@test block_nstored (b) == 2
41
- # TODO : Have to investigate why this fails
42
- # on Julia v1.6, or drop support for v1.6.
43
52
for i in 1 : ndims (a)
44
53
@test axes (b, i) isa GradedOneTo
45
54
end
@@ -103,16 +112,17 @@ const elts = (Float32, Float64, Complex{Float32}, Complex{Float64})
103
112
@test blocksize (m) == (3 , 3 )
104
113
@test a == splitdims (m, (d1, d2), (d1, d2))
105
114
end
115
+
106
116
@testset " dual axes" begin
107
117
r = gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ])
108
118
for ax in ((r, r), (dual (r), r), (r, dual (r)), (dual (r), dual (r)))
109
119
a = BlockSparseArray {elt} (ax... )
110
120
@views for b in [Block (1 , 1 ), Block (2 , 2 )]
111
121
a[b] = randn (elt, size (a[b]))
112
122
end
113
- # TODO : Define and use `isdual` here.
114
123
for dim in 1 : ndims (a)
115
124
@test typeof (ax[dim]) === typeof (axes (a, dim))
125
+ @test isdual (ax[dim]) == isdual (axes (a, dim))
116
126
end
117
127
@test @view (a[Block (1 , 1 )])[1 , 1 ] == a[1 , 1 ]
118
128
@test @view (a[Block (1 , 1 )])[2 , 1 ] == a[2 , 1 ]
@@ -130,41 +140,149 @@ const elts = (Float32, Float64, Complex{Float32}, Complex{Float64})
130
140
@test a[I] == a_dense[I]
131
141
end
132
142
@test axes (a' ) == dual .(reverse (axes (a)))
133
- # TODO : Define and use `isdual` here.
134
- @test typeof (axes (a' , 1 )) === typeof ( dual ( axes (a, 2 ) ))
135
- @test typeof (axes (a' , 2 )) === typeof ( dual ( axes (a, 1 ) ))
143
+
144
+ @test isdual (axes (a' , 1 )) ≠ isdual ( axes (a, 2 ))
145
+ @test isdual (axes (a' , 2 )) ≠ isdual ( axes (a, 1 ))
136
146
@test isnothing (show (devnull , MIME (" text/plain" ), a))
137
147
138
148
# Check preserving dual in tensor algebra.
139
149
for b in (a + a, 2 * a, 3 * a - a)
140
150
@test Array (b) ≈ 2 * Array (a)
141
- # TODO : Define and use `isdual` here.
142
151
for dim in 1 : ndims (a)
143
- @test typeof (axes (b, dim)) === typeof (axes (b , dim))
152
+ @test isdual (axes (b, dim)) == isdual (axes (a , dim))
144
153
end
145
154
end
146
155
147
156
@test isnothing (show (devnull , MIME (" text/plain" ), @view (a[Block (1 , 1 )])))
148
157
@test @view (a[Block (1 , 1 )]) == a[Block (1 , 1 )]
149
158
end
150
159
160
+ @testset " GradedOneTo" begin
161
+ r = gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ])
162
+ a = BlockSparseArray {elt} (r, r)
163
+ @views for i in [Block (1 , 1 ), Block (2 , 2 )]
164
+ a[i] = randn (elt, size (a[i]))
165
+ end
166
+ b = 2 * a
167
+ @test block_nstored (b) == 2
168
+ @test Array (b) == 2 * Array (a)
169
+ for i in 1 : 2
170
+ @test axes (b, i) isa GradedOneTo
171
+ @test axes (a[:, :], i) isa GradedOneTo
172
+ end
173
+
174
+ I = [Block (1 )[1 : 1 ]]
175
+ @test a[I, :] isa AbstractBlockArray
176
+ @test a[:, I] isa AbstractBlockArray
177
+ @test size (a[I, I]) == (1 , 1 )
178
+ @test ! isdual (axes (a[I, I], 1 ))
179
+ end
180
+
181
+ @testset " GradedUnitRange" begin
182
+ r = gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ])[1 : 3 ]
183
+ a = BlockSparseArray {elt} (r, r)
184
+ @views for i in [Block (1 , 1 ), Block (2 , 2 )]
185
+ a[i] = randn (elt, size (a[i]))
186
+ end
187
+ b = 2 * a
188
+ @test block_nstored (b) == 2
189
+ @test Array (b) == 2 * Array (a)
190
+ for i in 1 : 2
191
+ @test axes (b, i) isa GradedUnitRange
192
+ @test axes (a[:, :], i) isa GradedUnitRange
193
+ end
194
+
195
+ I = [Block (1 )[1 : 1 ]]
196
+ @test a[I, :] isa AbstractBlockArray
197
+ @test axes (a[I, :], 1 ) isa GradedOneTo
198
+ @test axes (a[I, :], 2 ) isa GradedUnitRange
199
+
200
+ @test a[:, I] isa AbstractBlockArray
201
+ @test axes (a[:, I], 2 ) isa GradedOneTo
202
+ @test axes (a[:, I], 1 ) isa GradedUnitRange
203
+ @test size (a[I, I]) == (1 , 1 )
204
+ @test ! isdual (axes (a[I, I], 1 ))
205
+ end
206
+
151
207
# Test case when all axes are dual.
152
- for r in (gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ]), blockedrange ([2 , 2 ]))
208
+ @testset " dual GradedOneTo" begin
209
+ r = gradedrange ([U1 (- 1 ) => 2 , U1 (1 ) => 2 ])
153
210
a = BlockSparseArray {elt} (dual (r), dual (r))
154
211
@views for i in [Block (1 , 1 ), Block (2 , 2 )]
155
212
a[i] = randn (elt, size (a[i]))
156
213
end
157
214
b = 2 * a
158
215
@test block_nstored (b) == 2
159
216
@test Array (b) == 2 * Array (a)
160
- for ax in axes (b)
161
- @test ax isa UnitRangeDual
217
+ for i in 1 : 2
218
+ @test axes (b, i) isa GradedUnitRangeDual
219
+ @test axes (a[:, :], i) isa GradedUnitRangeDual
162
220
end
221
+ I = [Block (1 )[1 : 1 ]]
222
+ @test a[I, :] isa AbstractBlockArray
223
+ @test a[:, I] isa AbstractBlockArray
224
+ @test size (a[I, I]) == (1 , 1 )
225
+ @test isdual (axes (a[I, :], 2 ))
226
+ @test isdual (axes (a[:, I], 1 ))
227
+ @test_broken isdual (axes (a[I, :], 1 ))
228
+ @test_broken isdual (axes (a[:, I], 2 ))
229
+ @test_broken isdual (axes (a[I, I], 1 ))
230
+ @test_broken isdual (axes (a[I, I], 2 ))
231
+ end
232
+
233
+ @testset " dual GradedUnitRange" begin
234
+ r = gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ])[1 : 3 ]
235
+ a = BlockSparseArray {elt} (dual (r), dual (r))
236
+ @views for i in [Block (1 , 1 ), Block (2 , 2 )]
237
+ a[i] = randn (elt, size (a[i]))
238
+ end
239
+ b = 2 * a
240
+ @test block_nstored (b) == 2
241
+ @test Array (b) == 2 * Array (a)
242
+ for i in 1 : 2
243
+ @test axes (b, i) isa GradedUnitRangeDual
244
+ @test axes (a[:, :], i) isa GradedUnitRangeDual
245
+ end
246
+
247
+ I = [Block (1 )[1 : 1 ]]
248
+ @test a[I, :] isa AbstractBlockArray
249
+ @test a[:, I] isa AbstractBlockArray
250
+ @test size (a[I, I]) == (1 , 1 )
251
+ @test isdual (axes (a[I, :], 2 ))
252
+ @test isdual (axes (a[:, I], 1 ))
253
+ @test_broken isdual (axes (a[I, :], 1 ))
254
+ @test_broken isdual (axes (a[:, I], 2 ))
255
+ @test_broken isdual (axes (a[I, I], 1 ))
256
+ @test_broken isdual (axes (a[I, I], 2 ))
163
257
end
164
258
165
- # Test case when all axes are dual
166
- # from taking the adjoint.
167
- for r in (gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ]), blockedrange ([2 , 2 ]))
259
+ @testset " dual BlockedUnitRange" begin # self dual
260
+ r = blockedrange ([2 , 2 ])
261
+ a = BlockSparseArray {elt} (dual (r), dual (r))
262
+ @views for i in [Block (1 , 1 ), Block (2 , 2 )]
263
+ a[i] = randn (elt, size (a[i]))
264
+ end
265
+ b = 2 * a
266
+ @test block_nstored (b) == 2
267
+ @test Array (b) == 2 * Array (a)
268
+ @test a[:, :] isa BlockSparseArray
269
+ for i in 1 : 2
270
+ @test axes (b, i) isa BlockedOneTo
271
+ @test axes (a[:, :], i) isa BlockedOneTo
272
+ end
273
+
274
+ I = [Block (1 )[1 : 1 ]]
275
+ @test a[I, :] isa BlockSparseArray
276
+ @test a[:, I] isa BlockSparseArray
277
+ @test size (a[I, I]) == (1 , 1 )
278
+ @test ! isdual (axes (a[I, I], 1 ))
279
+ end
280
+
281
+ # Test case when all axes are dual from taking the adjoint.
282
+ for r in (
283
+ gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ]),
284
+ gradedrange ([U1 (0 ) => 2 , U1 (1 ) => 2 ])[begin : end ],
285
+ )
168
286
a = BlockSparseArray {elt} (r, r)
169
287
@views for i in [Block (1 , 1 ), Block (2 , 2 )]
170
288
a[i] = randn (elt, size (a[i]))
@@ -173,8 +291,13 @@ const elts = (Float32, Float64, Complex{Float32}, Complex{Float64})
173
291
@test block_nstored (b) == 2
174
292
@test Array (b) == 2 * Array (a)'
175
293
for ax in axes (b)
176
- @test ax isa UnitRangeDual
294
+ @test ax isa typeof ( dual (r))
177
295
end
296
+
297
+ I = [Block (1 )[1 : 1 ]]
298
+ @test size (b[I, :]) == (1 , 4 )
299
+ @test size (b[:, I]) == (4 , 1 )
300
+ @test size (b[I, I]) == (1 , 1 )
178
301
end
179
302
end
180
303
@testset " Matrix multiplication" begin
0 commit comments