Skip to content

Commit

Permalink
Replace isfinite check in ranges with lo ≤ x ≤ hi (#45646)
Browse files Browse the repository at this point in the history
Co-authored-by: Viral B. Shah <ViralBShah@users.noreply.github.com>
  • Loading branch information
LilithHafner and ViralBShah authored Oct 3, 2022
1 parent 60bf5cd commit 5811825
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
15 changes: 7 additions & 8 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1396,14 +1396,13 @@ function sum(r::AbstractRange{<:Real})
end

function _in_range(x, r::AbstractRange)
if !isfinite(x)
return false
elseif iszero(step(r))
return !isempty(r) && first(r) == x
else
n = round(Integer, (x - first(r)) / step(r)) + 1
return n >= 1 && n <= length(r) && r[n] == x
end
isempty(r) && return false
f, l = first(r), last(r)
# check for NaN, Inf, and large x that may overflow in the next calculation
f <= x <= l || l <= x <= f || return false
iszero(step(r)) && return true
n = round(Integer, (x - f) / step(r)) + 1
n >= 1 && n <= length(r) && r[n] == x
end
in(x::Real, r::AbstractRange{<:Real}) = _in_range(x, r)
# This method needs to be defined separately since -(::T, ::T) can be implemented
Expand Down
33 changes: 30 additions & 3 deletions test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,10 @@ end
@test !(3.5 in 1:5)
@test (3 in 1:5)
@test (3 in 5:-1:1)
#@test (3 in 3+0*(1:5))
#@test !(4 in 3+0*(1:5))
@test (3 in 3 .+ 0*(1:5))
@test !(4 in 3 .+ 0*(1:5))
@test 0. in (0. .* (1:10))
@test !(0.1 in (0. .* (1:10)))

let r = 0.0:0.01:1.0
@test (r[30] in r)
Expand All @@ -536,8 +538,17 @@ end
x = (NaN16, Inf32, -Inf64, 1//0, -1//0)
@test !(x in r)
end

@test 1e40 0:1.0 # Issue #45747
@test 1e20 0:1e-20:1e-20
@test 1e20 0:1e-20
@test 1.0 0:1e-20:1e-20
@test 0.5 0:1e-20:1e-20
@test 1 0:1e-20:1e-20

@test_broken 17.0 0:1e40 # Don't support really long ranges
end
@testset "in() works across types, including non-numeric types (#21728)" begin
@testset "in() works across types, including non-numeric types (#21728 and #45646)" begin
@test 1//1 in 1:3
@test 1//1 in 1.0:3.0
@test !(5//1 in 1:3)
Expand All @@ -558,6 +569,22 @@ end
@test !(Complex(1, 0) in Date(2017, 01, 01):Dates.Day(1):Date(2017, 01, 05))
@test !in Date(2017, 01, 01):Dates.Day(1):Date(2017, 01, 05))
@test !("a" in Date(2017, 01, 01):Dates.Day(1):Date(2017, 01, 05))

# We use Ducks because of their propensity to stand in a row and because we know
# that no additional methods (e.g. isfinite) are defined specifically for Ducks.
struct Duck
location::Int
end
Base.:+(x::Duck, y::Int) = Duck(x.location + y)
Base.:-(x::Duck, y::Int) = Duck(x.location - y)
Base.:-(x::Duck, y::Duck) = x.location - y.location
Base.isless(x::Duck, y::Duck) = isless(x.location, y.location)

@test Duck(3) Duck(1):2:Duck(5)
@test Duck(3) Duck(5):-2:Duck(2)
@test Duck(4) Duck(5):-2:Duck(1)
@test Duck(4) Duck(1):Duck(5)
@test Duck(0) Duck(1):Duck(5)
end
end
@testset "indexing range with empty range (#4309)" begin
Expand Down

0 comments on commit 5811825

Please sign in to comment.