Skip to content

Commit 1c68f8a

Browse files
authored
Merge pull request #25532 from JuliaLang/nl/findn
Deprecate findn(x) in favor of find(!iszero, x), which now returns cartesian indices
2 parents 60cd7cf + 06eeaa3 commit 1c68f8a

File tree

15 files changed

+57
-140
lines changed

15 files changed

+57
-140
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/array.jl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1778,11 +1778,29 @@ _pairs(iter) = zip(OneTo(typemax(Int)), iter) # safe for objects that don't imp
17781778
"""
17791779
find(A)
17801780
1781-
Return a vector of the linear indices of the `true` values in `A`.
1781+
Return a vector `I` of the `true` indices or keys of `A`.
1782+
If there are no such elements of `A`, return an empty array.
17821783
To search for other kinds of values, pass a predicate as the first argument.
17831784
1785+
Indices or keys are of the same type as those returned by [`keys(A)`](@ref)
1786+
and [`pairs(A)`](@ref) for `AbstractArray`, `AbstractDict`, `AbstractString`
1787+
`Tuple` and `NamedTuple` objects, and are linear indices starting at `1`
1788+
for other iterables.
1789+
17841790
# Examples
17851791
```jldoctest
1792+
julia> A = [true, false, false, true]
1793+
4-element Array{Bool,1}:
1794+
true
1795+
false
1796+
false
1797+
true
1798+
1799+
julia> find(A)
1800+
2-element Array{Int64,1}:
1801+
1
1802+
4
1803+
17861804
julia> A = [true false; false true]
17871805
2×2 Array{Bool,2}:
17881806
true false

base/bitarray.jl

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,39 +1601,40 @@ end
16011601
function find(B::BitArray)
16021602
l = length(B)
16031603
nnzB = count(B)
1604-
I = Vector{Int}(uninitialized, nnzB)
1604+
ind = first(keys(B))
1605+
I = Vector{typeof(ind)}(uninitialized, nnzB)
16051606
nnzB == 0 && return I
16061607
Bc = B.chunks
1607-
Bcount = 1
16081608
Icount = 1
16091609
for i = 1:length(Bc)-1
16101610
u = UInt64(1)
16111611
c = Bc[i]
16121612
for j = 1:64
16131613
if c & u != 0
1614-
I[Icount] = Bcount
1614+
I[Icount] = ind
16151615
Icount += 1
16161616
end
1617-
Bcount += 1
1617+
ind = nextind(B, ind)
16181618
u <<= 1
16191619
end
16201620
end
16211621
u = UInt64(1)
16221622
c = Bc[end]
16231623
for j = 0:_mod64(l-1)
16241624
if c & u != 0
1625-
I[Icount] = Bcount
1625+
I[Icount] = ind
16261626
Icount += 1
16271627
end
1628-
Bcount += 1
1628+
ind = nextind(B, ind)
16291629
u <<= 1
16301630
end
16311631
return I
16321632
end
16331633

1634-
findn(B::BitVector) = find(B)
1634+
# For performance
1635+
find(::typeof(!iszero), B::BitArray) = find(B)
16351636

1636-
function findn(B::BitMatrix)
1637+
function findnz(B::BitMatrix)
16371638
nnzB = count(B)
16381639
I = Vector{Int}(uninitialized, nnzB)
16391640
J = Vector{Int}(uninitialized, nnzB)
@@ -1645,11 +1646,6 @@ function findn(B::BitMatrix)
16451646
cnt += 1
16461647
end
16471648
end
1648-
return I, J
1649-
end
1650-
1651-
function findnz(B::BitMatrix)
1652-
I, J = findn(B)
16531649
return I, J, trues(length(I))
16541650
end
16551651

base/deprecated.jl

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

27792779
@deprecate findin(a, b) find(occursin(b), a)
27802780

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

27822785
# END 0.7 deprecations
27832786

base/exports.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,6 @@ export
489489
findmin,
490490
findmin!,
491491
findmax!,
492-
findn,
493492
findnext,
494493
findprev,
495494
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
@@ -124,7 +124,6 @@ Base.circshift!
124124
Base.circcopy!
125125
Base.find(::Any)
126126
Base.find(::Function, ::Any)
127-
Base.findn
128127
Base.findnz
129128
Base.findfirst(::Any)
130129
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)

0 commit comments

Comments
 (0)