Skip to content

Commit fe4b76e

Browse files
committedNov 3, 2017
Optimized findnext() for sparse: update now that predicate needs to be explicit
Since we now need explicit predicates [1], this optimization only works if we know that the predicate is a function that is false for zero values. As suggested in that pull request, we could find out by calling `f(zero(eltype(array)))` and hoping that `f` is pure, but I like being a bit more conservative and only applying this optimization only to the case where we *know* `f` is equal to `!iszero`. For clarity, this commit also renames the helper method _sparse_findnext() to _sparse_findnextnz(), because now that the predicate-less version doesn't exist anymore, the `nz` part isn't implicit anymore either. [1]: #23812
1 parent 1ac4141 commit fe4b76e

File tree

4 files changed

+20
-20
lines changed

4 files changed

+20
-20
lines changed
 

‎base/sparse/abstractsparse.jl

+10-10
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,30 @@ end
3131

3232
# The following two methods should be overloaded by concrete types to avoid
3333
# allocating the I = find(...)
34-
_sparse_findnext(v::AbstractSparseArray, i) = (I = find(v); n = searchsortedfirst(I, i); n<=length(I) ? I[n] : 0)
35-
_sparse_findprev(v::AbstractSparseArray, i) = (I = find(v); n = searchsortedlast(I, i); n>0 ? I[n] : 0)
34+
_sparse_findnextnz(v::AbstractSparseArray, i) = (I = find(!iszero, v); n = searchsortedfirst(I, i); n<=length(I) ? I[n] : 0)
35+
_sparse_findprevnz(v::AbstractSparseArray, i) = (I = find(!iszero, v); n = searchsortedlast(I, i); n>0 ? I[n] : 0)
3636

37-
function findnext(v::AbstractSparseArray, i::Int)
38-
j = _sparse_findnext(v, i)
37+
function findnext(f::typeof(!iszero), v::AbstractSparseArray, i::Int)
38+
j = _sparse_findnextnz(v, i)
3939
if j == 0
4040
return 0
4141
end
42-
while v[j] == 0
43-
j = _sparse_findnext(v, j+1)
42+
while !f(v[j])
43+
j = _sparse_findnextnz(v, j+1)
4444
if j == 0
4545
return 0
4646
end
4747
end
4848
return j
4949
end
5050

51-
function findprev(v::AbstractSparseArray, i::Int)
52-
j = _sparse_findprev(v, i)
51+
function findprev(f::typeof(!iszero), v::AbstractSparseArray, i::Int)
52+
j = _sparse_findprevnz(v, i)
5353
if j == 0
5454
return 0
5555
end
56-
while v[j] == 0
57-
j = _sparse_findprev(v, j-1)
56+
while !f(v[j])
57+
j = _sparse_findprevnz(v, j-1)
5858
if j == 0
5959
return 0
6060
end

‎base/sparse/sparsematrix.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ function findnz(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti}
13181318
return (I, J, V)
13191319
end
13201320

1321-
function _sparse_findnext(m::SparseMatrixCSC, i::Int)
1321+
function _sparse_findnextnz(m::SparseMatrixCSC, i::Int)
13221322
if i > length(m)
13231323
return 0
13241324
end
@@ -1336,7 +1336,7 @@ function _sparse_findnext(m::SparseMatrixCSC, i::Int)
13361336
return sub2ind(m, m.rowval[nextlo], nextcol-1)
13371337
end
13381338

1339-
function _sparse_findprev(m::SparseMatrixCSC, i::Int)
1339+
function _sparse_findprevnz(m::SparseMatrixCSC, i::Int)
13401340
if i < 1
13411341
return 0
13421342
end

‎base/sparse/sparsevector.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ function findnz(x::SparseVector{Tv,Ti}) where {Tv,Ti}
737737
return (I, V)
738738
end
739739

740-
function _sparse_findnext(v::SparseVector, i::Int)
740+
function _sparse_findnextnz(v::SparseVector, i::Int)
741741
n = searchsortedfirst(v.nzind, i)
742742
if n > length(v.nzind)
743743
return 0
@@ -746,7 +746,7 @@ function _sparse_findnext(v::SparseVector, i::Int)
746746
end
747747
end
748748

749-
function _sparse_findprev(v::SparseVector, i::Int)
749+
function _sparse_findprevnz(v::SparseVector, i::Int)
750750
n = searchsortedlast(v.nzind, i)
751751
if n < 1
752752
return 0

‎test/sparse/sparse.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -2155,8 +2155,8 @@ end
21552155
x_sp = sparse(x)
21562156

21572157
for i=1:length(x)
2158-
@test findnext(x,i) == findnext(x_sp,i)
2159-
@test findprev(x,i) == findprev(x_sp,i)
2158+
@test findnext(!iszero, x,i) == findnext(!iszero, x_sp,i)
2159+
@test findprev(!iszero, x,i) == findprev(!iszero, x_sp,i)
21602160
end
21612161

21622162
y = [0 0 0 0 0;
@@ -2167,15 +2167,15 @@ end
21672167
y_sp = sparse(y)
21682168

21692169
for i=1:length(y)
2170-
@test findnext(y,i) == findnext(y_sp,i)
2171-
@test findprev(y,i) == findprev(y_sp,i)
2170+
@test findnext(!iszero, y,i) == findnext(!iszero, y_sp,i)
2171+
@test findprev(!iszero, y,i) == findprev(!iszero, y_sp,i)
21722172
end
21732173

21742174
z_sp = sparsevec(Dict(1=>1, 5=>1, 8=>0, 10=>1))
21752175
z = collect(z_sp)
21762176

21772177
for i=1:length(z)
2178-
@test findnext(z,i) == findnext(z_sp,i)
2179-
@test findprev(z,i) == findprev(z_sp,i)
2178+
@test findnext(!iszero, z,i) == findnext(!iszero, z_sp,i)
2179+
@test findprev(!iszero, z,i) == findprev(!iszero, z_sp,i)
21802180
end
21812181
end

0 commit comments

Comments
 (0)