Skip to content

Commit 06eeaa3

Browse files
committed
Deprecate findn(x) in favor of find(!iszero, x), which now returns cartesian indices
Also make find(::Function, ::SparseMatrixCSC) slightly more efficient by avoiding an intermediate allocation of index vectors.
1 parent 5ec147b commit 06eeaa3

File tree

13 files changed

+26
-129
lines changed

13 files changed

+26
-129
lines changed

NEWS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,8 @@ This section lists changes that do not have deprecation warnings.
364364
trait; see its documentation for details. Types which support subtraction (operator
365365
`-`) must now implement `widen` for hashing to work inside heterogeneous arrays.
366366

367-
* `findn(x::AbstractVector)` now returns a 1-tuple with the vector of indices, to be
368-
consistent with higher order arrays ([#25365]).
367+
* `findn(x::AbstractArray)` has been deprecated in favor of `find(!iszero, x)`, which
368+
now returns cartesian indices for multidimensional arrays (see below, [#25532]).
369369

370370
* `find` now returns the same type of indices as `keys`/`pairs` for `AbstractArray`,
371371
`AbstractDict`, `AbstractString`, `Tuple` and `NamedTuple` objects ([#24774]).
@@ -1191,3 +1191,4 @@ Command-line option changes
11911191
[#25231]: https://github.com/JuliaLang/julia/issues/25231
11921192
[#25365]: https://github.com/JuliaLang/julia/issues/25365
11931193
[#25424]: https://github.com/JuliaLang/julia/issues/25424
1194+
[#25532]: https://github.com/JuliaLang/julia/issues/25532

base/bitarray.jl

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,9 +1629,10 @@ function find(B::BitArray)
16291629
return I
16301630
end
16311631

1632-
findn(B::BitVector) = find(B)
1632+
# For performance
1633+
find(::typeof(!iszero), B::BitArray) = find(B)
16331634

1634-
function findn(B::BitMatrix)
1635+
function findnz(B::BitMatrix)
16351636
nnzB = count(B)
16361637
I = Vector{Int}(uninitialized, nnzB)
16371638
J = Vector{Int}(uninitialized, nnzB)
@@ -1643,11 +1644,6 @@ function findn(B::BitMatrix)
16431644
cnt += 1
16441645
end
16451646
end
1646-
return I, J
1647-
end
1648-
1649-
function findnz(B::BitMatrix)
1650-
I, J = findn(B)
16511647
return I, J, trues(length(I))
16521648
end
16531649

base/deprecated.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,6 +2772,9 @@ end
27722772

27732773
@deprecate findin(a, b) find(occursin(b), a)
27742774

2775+
@deprecate findn(a::AbstractVector) (find(!iszero, a),)
2776+
@deprecate findn(x::AbstractMatrix) (I = find(!iszero, x); (getindex.(I, 1), getindex.(I, 2)))
2777+
@deprecate findn(a::AbstractArray{T, N}) where {T, N} (I = find(!iszero, x); ntuple(i -> getindex.(I, i), N))
27752778

27762779
# END 0.7 deprecations
27772780

base/exports.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,6 @@ export
495495
findmin,
496496
findmin!,
497497
findmax!,
498-
findn,
499498
findnext,
500499
findprev,
501500
findnz,

base/multidimensional.jl

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -687,51 +687,6 @@ end
687687

688688
##
689689

690-
# small helper function since we cannot use a closure in a generated function
691-
_countnz(x) = x != 0
692-
693-
"""
694-
findn(A)
695-
696-
Return one vector for each dimension containing indices giving the
697-
locations of the non-zeros in `A` (determined by `A[i] != 0`).
698-
699-
# Examples
700-
```jldoctest
701-
julia> A = [1 2 0; 0 0 3; 0 4 0]
702-
3×3 Array{Int64,2}:
703-
1 2 0
704-
0 0 3
705-
0 4 0
706-
707-
julia> findn(A)
708-
([1, 1, 3, 2], [1, 2, 2, 3])
709-
710-
julia> A = [0 0; 0 0]
711-
2×2 Array{Int64,2}:
712-
0 0
713-
0 0
714-
715-
julia> findn(A)
716-
(Int64[], Int64[])
717-
```
718-
"""
719-
@generated function findn(A::AbstractArray{T,N}) where {T,N}
720-
quote
721-
nnzA = count(_countnz, A)
722-
@nexprs $N d->(I_d = Vector{Int}(uninitialized, nnzA))
723-
k = 1
724-
@nloops $N i A begin
725-
@inbounds if (@nref $N A i) != 0
726-
@nexprs $N d->(I_d[k] = i_d)
727-
k += 1
728-
end
729-
end
730-
@ntuple $N I
731-
end
732-
end
733-
734-
735690
# see discussion in #18364 ... we try not to widen type of the resulting array
736691
# from cumsum or cumprod, but in some cases (+, Bool) we may not have a choice.
737692
rcum_promote_type(op, ::Type{T}, ::Type{S}) where {T,S<:Number} = promote_op(op, T, S)
@@ -1597,25 +1552,6 @@ end
15971552
end
15981553
end
15991554

1600-
## findn
1601-
1602-
@generated function findn(B::BitArray{N}) where N
1603-
quote
1604-
nnzB = count(B)
1605-
I = ntuple(x->Vector{Int}(uninitialized, nnzB), Val($N))
1606-
if nnzB > 0
1607-
count = 1
1608-
@nloops $N i B begin
1609-
if (@nref $N B i) # TODO: should avoid bounds checking
1610-
@nexprs $N d->(I[d][count] = i_d)
1611-
count += 1
1612-
end
1613-
end
1614-
end
1615-
return I
1616-
end
1617-
end
1618-
16191555
## isassigned
16201556

16211557
@generated function isassigned(B::BitArray, I_0::Int, I::Int...)

doc/src/base/arrays.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ Base.circshift!
126126
Base.circcopy!
127127
Base.find(::Any)
128128
Base.find(::Function, ::Any)
129-
Base.findn
130129
Base.findnz
131130
Base.findfirst(::Any)
132131
Base.findfirst(::Function, ::Any)

stdlib/SparseArrays/docs/src/index.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,19 @@ julia> R = sparsevec(I,V)
115115

116116
The inverse of the [`sparse`](@ref) and [`sparsevec`](@ref) functions is
117117
[`findnz`](@ref), which retrieves the inputs used to create the sparse array.
118-
There is also a [`findn`](@ref) function which only returns the index vectors.
118+
[`find(!iszero, x)`](@ref) returns the cartesian indices of non-zero entries in `x`
119+
(including stored entries equal to zero).
119120

120121
```jldoctest sparse_function
121122
julia> findnz(S)
122123
([1, 4, 5, 3], [4, 7, 9, 18], [1, 2, 3, -5])
123124
124-
julia> findn(S)
125-
([1, 4, 5, 3], [4, 7, 9, 18])
125+
julia> find(!iszero, S)
126+
4-element Array{CartesianIndex{2},1}:
127+
CartesianIndex(1, 4)
128+
CartesianIndex(4, 7)
129+
CartesianIndex(5, 9)
130+
CartesianIndex(3, 18)
126131
127132
julia> findnz(R)
128133
([1, 3, 4, 5], [1, -5, 2, 3])

stdlib/SparseArrays/src/SparseArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Base.LinAlg: mul!, ldiv!, rdiv!
1717
import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh,
1818
atan, atand, atanh, broadcast!, chol, conj!, cos, cosc, cosd, cosh, cospi, cot,
1919
cotd, coth, count, csc, cscd, csch, adjoint!, diag, diff, done, dot, eig,
20-
exp10, exp2, findn, findprev, findnext, floor, hash, indmin, inv,
20+
exp10, exp2, findprev, findnext, floor, hash, indmin, inv,
2121
issymmetric, istril, istriu, log10, log2, lu, next, sec, secd, sech, show,
2222
sin, sinc, sind, sinh, sinpi, squeeze, start, sum, summary, tan,
2323
tand, tanh, trace, transpose!, tril!, triu!, trunc, vecnorm, abs, abs2,

stdlib/SparseArrays/src/sparsematrix.jl

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,31 +1274,22 @@ function find(p::Function, S::SparseMatrixCSC)
12741274
if p(zero(eltype(S)))
12751275
return invoke(find, Tuple{Function, Any}, p, S)
12761276
end
1277-
sz = size(S)
1278-
I, J = _findn(p, S)
1279-
return CartesianIndex.(I, J)
1280-
end
1281-
find(p::Base.OccursIn, x::SparseMatrixCSC) =
1282-
invoke(find, Tuple{Base.OccursIn, AbstractArray}, p, x)
1283-
1284-
findn(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = _findn(x->true, S)
12851277

1286-
function _findn(p::Function, S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti}
12871278
numnz = nnz(S)
1288-
I = Vector{Ti}(uninitialized, numnz)
1289-
J = Vector{Ti}(uninitialized, numnz)
1279+
inds = Vector{CartesianIndex{2}}(uninitialized, numnz)
12901280

12911281
count = 1
12921282
@inbounds for col = 1 : S.n, k = S.colptr[col] : (S.colptr[col+1]-1)
12931283
if p(S.nzval[k])
1294-
I[count] = S.rowval[k]
1295-
J[count] = col
1284+
inds[count] = CartesianIndex(S.rowval[k], col)
12961285
count += 1
12971286
end
12981287
end
12991288

1300-
return (I, J)
1289+
return inds
13011290
end
1291+
find(p::Base.OccursIn, x::SparseMatrixCSC) =
1292+
invoke(find, Tuple{Base.OccursIn, AbstractArray}, p, x)
13021293

13031294
function findnz(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti}
13041295
numnz = nnz(S)

stdlib/SparseArrays/test/sparse.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,12 +1156,6 @@ Base.isless(x::CustomType, y::CustomType) = isless(x.x, y.x)
11561156
end
11571157
end
11581158

1159-
@testset "findn" begin
1160-
b = findn( sparse(1.0I, 4, 4) )
1161-
@test (length(b[1]) == 4)
1162-
@test (length(b[2]) == 4)
1163-
end
1164-
11651159
@testset "rotations" begin
11661160
a = sparse( [1,1,2,3], [1,3,4,1], [1,2,3,4] )
11671161

0 commit comments

Comments
 (0)