193
193
end
194
194
end
195
195
196
+
196
197
@testset " sparse map/broadcast with result eltype not a concrete subtype of Number (#19561/#19589)" begin
197
198
intoneorfloatzero (x) = x != 0.0 ? Int (1 ) : Float64 (x)
198
199
stringorfloatzero (x) = x != 0.0 ? " Hello" : Float64 (x)
@@ -202,10 +203,10 @@ end
202
203
@test broadcast (stringorfloatzero, speye (4 )) == sparse (broadcast (stringorfloatzero, eye (4 )))
203
204
end
204
205
205
- @testset " broadcast over combinations of scalars and sparse vectors/matrices" begin
206
- N, M, p = 10 , 12 , 0.3
206
+ @testset " broadcast[!] over combinations of scalars and sparse vectors/matrices" begin
207
+ N, M, p = 10 , 12 , 0.5
207
208
elT = Float64
208
- s = elT (2.0 )
209
+ s = Float32 (2.0 )
209
210
V = sprand (elT, N, p)
210
211
A = sprand (elT, N, M, p)
211
212
fV, fA = Array (V), Array (A)
235
236
((s, spargsl... , s, s, spargsr... ), (s, dargsl... , s, s, dargsr... )),
236
237
((spargsl... , s, s, spargsr... , s), (dargsl... , s, s, dargsr... , s)),
237
238
((spargsl... , s, s, s, spargsr... ), (dargsl... , s, s, s, dargsr... )), )
239
+ # test broadcast entry point
238
240
@test broadcast (* , sparseargs... ) == sparse (broadcast (* , denseargs... ))
239
241
@test isa (@inferred (broadcast (* , sparseargs... )), SparseMatrixCSC{elT})
242
+ # test broadcast! entry point
243
+ fX = broadcast (* , sparseargs... ); X = sparse (fX)
244
+ @test broadcast! (* , X, sparseargs... ) == sparse (broadcast! (* , fX, denseargs... ))
245
+ @test isa (@inferred (broadcast! (* , X, sparseargs... )), SparseMatrixCSC{elT})
246
+ X = sparse (fX) # reset / warmup for @allocated test
247
+ @test_broken (@allocated broadcast! (* , X, sparseargs... )) == 0
248
+ # This test (and the analog below) fails for three reasons:
249
+ # (1) In all cases, generating the closures that capture the scalar arguments
250
+ # results in allocation, not sure why.
251
+ # (2) In some cases, though _broadcast_eltype (which wraps _return_type)
252
+ # consistently provides the correct result eltype when passed the closure
253
+ # that incorporates the scalar arguments to broadcast (and, with #19667,
254
+ # is inferable, so the overall return type from broadcast is inferred),
255
+ # in some cases inference seems unable to determine the return type of
256
+ # direct calls to that closure. This issue causes variables in both the
257
+ # broadcast[!] entry points (fofzeros = f(_zeros_eltypes(args...)...)) and
258
+ # the driver routines (Cx in _map_zeropres! and _broadcast_zeropres!) to have
259
+ # inferred type Any, resulting in allocation and lackluster performance.
260
+ # (3) The sparseargs... splat in the call above allocates a bit, but of course
261
+ # that issue is negligible and perhaps could be accounted for in the test.
240
262
end
241
263
end
242
264
# test combinations at the limit of inference (eight arguments net)
248
270
((s, V, A, s, V, A, s, A), (s, fV, fA, s, fV, fA, s, fA)), # three scalars, five sparse vectors/matrices
249
271
((V, A, V, s, A, V, A, s), (fV, fA, fV, s, fA, fV, fA, s)), # two scalars, six sparse vectors/matrices
250
272
((V, A, V, A, s, V, A, V), (fV, fA, fV, fA, s, fV, fA, fV)) ) # one scalar, seven sparse vectors/matrices
273
+ # test broadcast entry point
251
274
@test broadcast (* , sparseargs... ) == sparse (broadcast (* , denseargs... ))
252
275
@test isa (@inferred (broadcast (* , sparseargs... )), SparseMatrixCSC{elT})
276
+ # test broadcast! entry point
277
+ fX = broadcast (* , sparseargs... ); X = sparse (fX)
278
+ @test broadcast! (* , X, sparseargs... ) == sparse (broadcast! (* , fX, denseargs... ))
279
+ @test isa (@inferred (broadcast! (* , X, sparseargs... )), SparseMatrixCSC{elT})
280
+ X = sparse (fX) # reset / warmup for @allocated test
281
+ @test_broken (@allocated broadcast! (* , X, sparseargs... )) == 0
282
+ # please see the note a few lines above re. this @test_broken
253
283
end
254
284
end
255
285
0 commit comments