Skip to content

iszero/isone aren't efficient on InfRanges #178

@DanielVandH

Description

@DanielVandH
julia> using InfiniteArrays

julia> findfirst(isone, 1:∞) # works because it checks each element one at a time
1

julia> findfirst(isone, 2:∞) # never finds it, so hangs
WARNING: Force throwing a SIGINT
ERROR: InterruptException:
Stacktrace:
 [1] getindex
   @ C:\Users\User\.julia\packages\InfiniteArrays\7v9AI\src\infrange.jl:0 [inlined]
 [2] findnext(testf::typeof(isone), A::InfiniteArrays.InfUnitRange{Int64}, start::Int64)
   @ Base .\array.jl:2155
 [3] findfirst(testf::Function, A::InfiniteArrays.InfUnitRange{Int64})
   @ Base .\array.jl:2206
 [4] top-level scope
   @ REPL[9]:1

julia> ^C

julia> findfirst(iszero, 0:∞)
1

julia> findfirst(iszero, 1:∞)
WARNING: Force throwing a SIGINT
ERROR: InterruptException:
Stacktrace:
 [1] getindex
   @ C:\Users\User\.julia\packages\InfiniteArrays\7v9AI\src\infrange.jl:0 [inlined]
 [2] findnext(testf::typeof(iszero), A::InfiniteArrays.InfUnitRange{Int64}, start::Int64)
   @ Base .\array.jl:2155
 [3] findfirst(testf::Function, A::InfiniteArrays.InfUnitRange{Int64})
   @ Base .\array.jl:2206
 [4] top-level scope
   @ REPL[11]:1

julia> findfirst(==(0), 1:∞) # efficient

julia> findfirst(==(1), 2:∞)

These calls are a bit specific so not much of a priority, but the methods in

for op in (:isequal, :(==))
@eval begin
findfirst(p::Fix2{typeof($op),T}, r::InfStepRange{T,S}) where {T,S} =
_step_findfirst(p, r)
findfirst(p::Fix2{typeof($op),T}, r::InfStepRange{T,<:Integer}) where {T<:Integer} =
_step_findfirst(p, r)
findfirst(p::Fix2{typeof($op),<:Integer}, r::InfStepRange{<:Integer,<:Integer}) =
_step_findfirst(p, r)
function findfirst(p::Fix2{typeof($op),<:Integer}, r::AbstractInfUnitRange{<:Integer})
first(r) <= p.x || return nothing
p.x - first(r) + 1
end
findfirst(p::Fix2{typeof($op),<:Number}, r::AbstractInfUnitRange{<:Integer}) =
isinteger(p.x) ? findfirst($op(convert(Integer, p.x)), r) : nothing
findfirst(p::Fix2{typeof($op),<:Number}, r::InfStepRange{<:Integer,<:Integer}) =
isinteger(p.x) ? findfirst($op(convert(V, p.x)), r) : nothing
end
end

could perhaps be used so that findfirst(iszero, <:InfRanges) uses findfirst(==(0), <:InfRanges) and similarly for isone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions