Skip to content

Commit 1539061

Browse files
authored
Merge pull request #19589 from Sacha0/mapbciszero
Fix #19561 (sparse map/broadcast where the output eltype is not a concrete subtype of Number)
2 parents d9318d5 + 72b38af commit 1539061

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

base/sparse/higherorderfns.jl

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,13 @@ map!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMa
6565
(_checksameshape(C, A, Bs...); _noshapecheck_map!(f, C, A, Bs...))
6666
function _noshapecheck_map!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N})
6767
fofzeros = f(_zeros_eltypes(A, Bs...)...)
68-
fpreszeros = fofzeros == zero(fofzeros)
68+
fpreszeros = _iszero(fofzeros)
6969
return fpreszeros ? _map_zeropres!(f, C, A, Bs...) :
7070
_map_notzeropres!(f, fofzeros, C, A, Bs...)
7171
end
7272
function _noshapecheck_map{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N})
7373
fofzeros = f(_zeros_eltypes(A, Bs...)...)
74-
fpreszeros = fofzeros == zero(fofzeros)
74+
fpreszeros = _iszero(fofzeros)
7575
maxnnzC = fpreszeros ? min(length(A), _sumnnzs(A, Bs...)) : length(A)
7676
entrytypeC = Base.Broadcast._broadcast_type(Any, f, A, Bs...)
7777
indextypeC = _promote_indtype(A, Bs...)
@@ -86,7 +86,7 @@ function broadcast!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Varar
8686
_aresameshape(C, A, Bs...) && return _noshapecheck_map!(f, C, A, Bs...)
8787
Base.Broadcast.check_broadcast_indices(indices(C), A, Bs...)
8888
fofzeros = f(_zeros_eltypes(A, Bs...)...)
89-
fpreszeros = fofzeros == zero(fofzeros)
89+
fpreszeros = _iszero(fofzeros)
9090
return fpreszeros ? _broadcast_zeropres!(f, C, A, Bs...) :
9191
_broadcast_notzeropres!(f, fofzeros, C, A, Bs...)
9292
end
@@ -99,7 +99,7 @@ broadcast{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) =
9999
_diffshape_broadcast(f, A, Bs...)
100100
function _diffshape_broadcast{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N})
101101
fofzeros = f(_zeros_eltypes(A, Bs...)...)
102-
fpreszeros = fofzeros == zero(fofzeros)
102+
fpreszeros = _iszero(fofzeros)
103103
indextypeC = _promote_indtype(A, Bs...)
104104
entrytypeC = Base.Broadcast._broadcast_type(Any, f, A, Bs...)
105105
shapeC = to_shape(Base.Broadcast.broadcast_indices(A, Bs...))
@@ -111,6 +111,9 @@ end
111111
# helper functions for map[!]/broadcast[!] entry points (and related methods below)
112112
@inline _sumnnzs(A) = nnz(A)
113113
@inline _sumnnzs(A, Bs...) = nnz(A) + _sumnnzs(Bs...)
114+
@inline _iszero(x) = x == 0
115+
@inline _iszero(x::Number) = Base.iszero(x)
116+
@inline _iszero(x::AbstractArray) = Base.iszero(x)
114117
@inline _zeros_eltypes(A) = (zero(eltype(A)),)
115118
@inline _zeros_eltypes(A, Bs...) = (zero(eltype(A)), _zeros_eltypes(Bs...)...)
116119
@inline _promote_indtype(A) = indtype(A)
@@ -159,7 +162,7 @@ function _map_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat)
159162
setcolptr!(C, j, Ck)
160163
for Ak in colrange(A, j)
161164
Cx = f(storedvals(A)[Ak])
162-
if Cx != zero(eltype(C))
165+
if !_iszero(Cx)
163166
Ck > spaceC && (spaceC = expandstorage!(C, Ck + nnz(A) - (Ak - 1)))
164167
storedinds(C)[Ck] = storedinds(A)[Ak]
165168
storedvals(C)[Ck] = Cx
@@ -240,7 +243,7 @@ function _map_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::Spar
240243
# cases are equally or more likely than the Ai < Bi and Bi < Ai cases. Hence
241244
# the ordering of the conditional chain above differs from that in the
242245
# corresponding broadcast code (below).
243-
if Cx != zero(eltype(C))
246+
if !_iszero(Cx)
244247
Ck > spaceC && (spaceC = expandstorage!(C, Ck + (nnz(A) - (Ak - 1)) + (nnz(B) - (Bk - 1))))
245248
storedinds(C)[Ck] = Ci
246249
storedvals(C)[Ck] = Cx
@@ -305,7 +308,7 @@ function _map_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMa
305308
# rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As)
306309
vals, ks, rows = _fusedupdate_all(rowsentinel, activerow, rows, ks, stopks, As)
307310
Cx = f(vals...)
308-
if Cx != zero(eltype(C))
311+
if !_iszero(Cx)
309312
Ck > spaceC && (spaceC = expandstorage!(C, Ck + min(length(C), _sumnnzs(As...)) - (sum(ks) - N)))
310313
storedinds(C)[Ck] = activerow
311314
storedvals(C)[Ck] = Cx
@@ -461,7 +464,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B
461464
# pattern) the Ai < Bi and Bi < Ai cases are equally or more likely than the
462465
# Ai == Bi and termination cases. Hence the ordering of the conditional
463466
# chain above differs from that in the corresponding map code.
464-
if Cx != zero(eltype(C))
467+
if !_iszero(Cx)
465468
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), A, B)))
466469
storedinds(C)[Ck] = Ci
467470
storedvals(C)[Ck] = Cx
@@ -483,7 +486,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B
483486
# B's jth column without storing every entry in C's jth column
484487
while Bk < stopBk
485488
Cx = f(Ax, storedvals(B)[Bk])
486-
if Cx != zero(eltype(C))
489+
if !_iszero(Cx)
487490
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), A, B)))
488491
storedinds(C)[Ck] = storedinds(B)[Bk]
489492
storedvals(C)[Ck] = Cx
@@ -502,7 +505,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B
502505
else
503506
Cx = fvAzB
504507
end
505-
if Cx != zero(eltype(C))
508+
if !_iszero(Cx)
506509
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), A, B)))
507510
storedinds(C)[Ck] = Ci
508511
storedvals(C)[Ck] = Cx
@@ -524,7 +527,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B
524527
# A's jth column without storing every entry in C's jth column
525528
while Ak < stopAk
526529
Cx = f(storedvals(A)[Ak], Bx)
527-
if Cx != zero(eltype(C))
530+
if !_iszero(Cx)
528531
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), A, B)))
529532
storedinds(C)[Ck] = storedinds(A)[Ak]
530533
storedvals(C)[Ck] = Cx
@@ -543,7 +546,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B
543546
else
544547
Cx = fzAvB
545548
end
546-
if Cx != zero(eltype(C))
549+
if !_iszero(Cx)
547550
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), A, B)))
548551
storedinds(C)[Ck] = Ci
549552
storedvals(C)[Ck] = Cx
@@ -674,7 +677,7 @@ function _broadcast_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseV
674677
# rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As)
675678
args, ks, rows = _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As)
676679
Cx = f(args...)
677-
if Cx != zero(eltype(C))
680+
if !_iszero(Cx)
678681
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), As)))
679682
storedinds(C)[Ck] = activerow
680683
storedvals(C)[Ck] = Cx
@@ -695,7 +698,7 @@ function _broadcast_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseV
695698
else
696699
Cx = defaultCx
697700
end
698-
if Cx != zero(eltype(C))
701+
if !_iszero(Cx)
699702
Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), As)))
700703
storedinds(C)[Ck] = Ci
701704
storedvals(C)[Ck] = Cx

test/sparse/higherorderfns.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ end
193193
end
194194
end
195195

196+
@testset "sparse map/broadcast with result eltype not a concrete subtype of Number (#19561/#19589)" begin
197+
intoneorfloatzero(x) = x != 0.0 ? Int(1) : Float64(x)
198+
stringorfloatzero(x) = x != 0.0 ? "Hello" : Float64(x)
199+
@test map(intoneorfloatzero, speye(4)) == sparse(map(intoneorfloatzero, eye(4)))
200+
@test map(stringorfloatzero, speye(4)) == sparse(map(stringorfloatzero, eye(4)))
201+
@test broadcast(intoneorfloatzero, speye(4)) == sparse(broadcast(intoneorfloatzero, eye(4)))
202+
@test broadcast(stringorfloatzero, speye(4)) == sparse(broadcast(stringorfloatzero, eye(4)))
203+
end
204+
196205
# Older tests of sparse broadcast, now largely covered by the tests above
197206
@testset "assorted tests of sparse broadcast over two input arguments" begin
198207
N, p = 10, 0.3

0 commit comments

Comments
 (0)