Implemented findall(in(interval), x::AbstractRange), fixes #52#63
Implemented findall(in(interval), x::AbstractRange), fixes #52#63
Conversation
jagot
commented
May 9, 2020
|
I realized I wanted to add the following function as well: Base.findall(interval_d::Base.Fix2{typeof(in),Interval{L,R,T}}, x::AbstractArray) where {L,R,T} =
findall(v -> v ∈ interval_d.x, x)but this breaks an ambiguity test: The function seems to work as intended, so I'm not sure if the test should be amended, or what else. EDIT: It's basically this ambiguity: julia> x = sprand(5,3,0.5)
5×3 SparseMatrixCSC{Float64,Int64} with 12 stored entries:
[1, 1] = 0.00663687
[2, 1] = 0.0354308
[4, 1] = 0.205993
[5, 1] = 0.537299
[1, 2] = 0.882739
[2, 2] = 0.990146
[4, 2] = 0.331874
[1, 3] = 0.377636
[2, 3] = 0.203865
[3, 3] = 0.287234
[4, 3] = 0.839448
[5, 3] = 0.731989
julia> findall(in(0.3..0.9), x)
ERROR: MethodError: findall(::Base.Fix2{typeof(in),Interval{:closed,:closed,Float64}}, ::SparseMatrixCSC{Float64,Int64}) is ambiguous. Candidates:
findall(p::Base.Fix2{typeof(in),T} where T, x::SparseArrays.AbstractSparseMatrixCSC) in SparseArrays at /Applications/Julia-1.4.app/Contents/Resources/julia/share/julia/stdlib/v1.4/SparseArrays/src/sparsematrix.jl:1419
findall(interval_d::Base.Fix2{typeof(in),Interval{L,R,T}}, x::AbstractArray) where {L, R, T} in IntervalSets at /Users/jagot/.julia/dev/IntervalSets/src/findall.jl:81
findall(p::Function, S::SparseArrays.AbstractSparseMatrixCSC) in SparseArrays at /Applications/Julia-1.4.app/Contents/Resources/julia/share/julia/stdlib/v1.4/SparseArrays/src/sparsematrix.jl:1400
findall(pred::Base.Fix2{typeof(in),T} where T, x::Union{Tuple, AbstractArray}) in Base at array.jl:2322
Possible fix, define
findall(::Base.Fix2{typeof(in),Interval{L,R,T}}, ::SparseArrays.AbstractSparseMatrixCSC) where {L, R, T} |
|
Just fix the ambiguity? |
|
That would be nice to have work, I was a bit surprised the default didn't just work. Here's where it goes, BTW: It's a little tempting to write |
|
Does this look good now? |
|
Scratch that, I think I found an edge case which is not working yet: x = 0.0:0.02040816326530612:1.0
findall(in(Interval{:closed,:open}(1.0..1.0)), x)gives a |
dlfivefifty
left a comment
There was a problem hiding this comment.
Looks good, made one comment about Random.seed! and perhaps add some BigFloat tests, but I'm happy for it to be merged when you are, if no one else pipes up
|
I found I had already covered the corner case above in my B-spline code (🤦). Will probably cook up some BigFloat tests, de-duplicate the tests I have now and re-add @mcabbott's OffsetArrays examples. |
|
Good catch with the BigFloats, there were indeed some corner cases for reverse ranges, that I think I've fixed now. |
|
Many thanks for getting this done. I just found another edge case, which I'm not really sure this ought to try to support, but anyway here it is: julia> using IntervalSets
julia> using Dates
julia> findall(in(Interval(Date(2020, 1, 8), Date(2020, 1, 22))), Date(2020):Week(1):Date(2021))
ERROR: MethodError: no method matching isless(::Week, ::Int64)
Closest candidates are:
isless(::Missing, ::Any) at missing.jl:87
isless(::DoubleFloats.DoubleFloat{T}, ::Integer) where T<:Union{Float16, Float32, Float64} at /Users/me/.julia/packages/DoubleFloats/8fO4c/src/type/compare.jl:135
isless(::AbstractFloat, ::Real) at operators.jl:158
...
Stacktrace:
[1] <(::Week, ::Int64) at ./operators.jl:268
[2] findall(::Base.Fix2{typeof(in),Interval{:closed,:closed,Date}}, ::StepRange{Date,Week}) at /Users/me/.julia/packages/IntervalSets/D282g/src/findall.jl:43 |
|
I don't think we should not support it, but I find myself unwilling to get into date semantics :) julia> w = Week(1)
1 week
julia> cld(3w,2w)
2 |
|
@mcabbott I think this is fairly easy to fix, once JuliaLang/julia#36099 is taken care of: a,b = if δx < zero(δx)
rev = findall(in(interval), reverse(x))
isempty(rev) && return rev
a = (il+ir)-last(rev)
b = (il+ir)-first(rev)
a,b
else
lx, rx = first(x), last(x)
l = max(leftendpoint(interval), lx-one(δx))
r = min(rightendpoint(interval), rx+one(δx))
(l > rx || r < lx) && return 1:0
a = il + max(0, round(Int, cld(l-lx, δx)))
a += (a ≤ ir && (x[a] == l && L == :open || x[a] < l))
b = min(ir, round(Int, cld(r-lx, δx)) + il)
b -= (b ≥ il && (x[b] == r && R == :open || x[b] > r))
a,b
end |
|
Thanks for digging, I haven't got back to this... although I think I was guilty of introducing the |