Skip to content

Commit

Permalink
Detect negative via sign instead of zero
Browse files Browse the repository at this point in the history
  • Loading branch information
omus committed Jul 28, 2020
1 parent cbea139 commit 9b68184
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 31 deletions.
19 changes: 10 additions & 9 deletions src/anchoredinterval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ AnchoredInterval{P,L,R}(anchor::T) where {P,T,L,R} = AnchoredInterval{P,T,L,R}(a
# When an interval is anchored to the lesser endpoint, default to Inclusivity(false, true)
# When an interval is anchored to the greater endpoint, default to Inclusivity(true, false)
function AnchoredInterval{P,T}(anchor) where {P,T}
L = bound_type(P zero(P))
R = bound_type(P zero(P))
s = sign(P)
L = bound_type(s 0)
R = bound_type(s 0)
return AnchoredInterval{P,T,L,R}(anchor)
end

Expand Down Expand Up @@ -160,11 +161,11 @@ end
# that is no longer comparable (e.g., `NaN`).

function Base.first(interval::AnchoredInterval{P}) where P
P < zero(P) ? (interval.anchor + P) : (interval.anchor)
sign(P) < 0 ? (interval.anchor + P) : (interval.anchor)
end

function Base.last(interval::AnchoredInterval{P}) where P
P < zero(P) ? (interval.anchor) : (interval.anchor + P)
sign(P) < 0 ? (interval.anchor) : (interval.anchor + P)
end

anchor(interval::AnchoredInterval) = interval.anchor
Expand All @@ -175,7 +176,7 @@ span(interval::AnchoredInterval{P}) where P = abs(P)
# Allows an interval to be converted to a scalar when the set contained by the interval only
# contains a single element.
function Base.convert(::Type{T}, interval::AnchoredInterval{P,T}) where {P,T}
if isclosed(interval) && (iszero(P) || first(interval) == last(interval))
if isclosed(interval) && (sign(P) == 0 || first(interval) == last(interval))
return first(interval)
else
# Remove deprecation in version 2.0.0
Expand Down Expand Up @@ -206,13 +207,13 @@ end
#=
function Base.convert(::Type{AnchoredInterval{P,T}}, interval::Interval{T}) where {P,T}
@assert abs(P) == span(interval)
anchor = P < zero(P) ? last(interval) : first(interval)
anchor = sign(P) < 0 ? last(interval) : first(interval)
AnchoredInterval{P,T}(last(interval), inclusivity(interval))
end
function Base.convert(::Type{AnchoredInterval{P}}, interval::Interval{T}) where {P,T}
@assert abs(P) == span(interval)
anchor = P < zero(P) ? last(interval) : first(interval)
anchor = sign(P) < 0 ? last(interval) : first(interval)
AnchoredInterval{P,T}(anchor, inclusivity(interval))
end
=#
Expand Down Expand Up @@ -308,15 +309,15 @@ end
##### SET OPERATIONS #####

function Base.isempty(interval::AnchoredInterval{P,T}) where {P,T}
return P == zero(P) && !isclosed(interval)
return sign(P) == 0 && !isclosed(interval)
end

# When intersecting two `AnchoredInterval`s attempt to return an `AnchoredInterval`
function Base.intersect(a::AnchoredInterval{P,T}, b::AnchoredInterval{Q,T}) where {P,Q,T}
interval = invoke(intersect, Tuple{AbstractInterval{T}, AbstractInterval{T}}, a, b)

sp = isa(P, Period) ? canonicalize(typeof(P), span(interval)) : span(interval)
if P zero(P)
if sign(P) 0
anchor = last(interval)
new_P = -sp
else
Expand Down
51 changes: 30 additions & 21 deletions test/anchoredinterval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,30 @@ using Intervals: Bounded, Ending, Beginning, canonicalize, isunbounded
@testset "infinite" begin
x = 1 # Non-zero value representing any positive value

interval = 0 .. Inf
@test AnchoredInterval{Inf,Closed,Closed}(0.0) == interval
# Not-possible: AnchoredInterval{-?,Closed,Closed}(Inf)

interval = -Inf .. 0
# Not-possible: AnchoredInterval{+?,Closed,Closed}(-Inf)
@test AnchoredInterval{-Inf,Closed,Closed}(0.0) == interval

interval = -Inf .. Inf
@test_throws ArgumentError AnchoredInterval{Inf,Closed,Closed}(-Inf)
@test_throws ArgumentError AnchoredInterval{-Inf,Closed,Closed}(Inf)

interval = -Inf .. -Inf
@test AnchoredInterval{+x,Closed,Closed}(-Inf) == interval
@test AnchoredInterval{-x,Closed,Closed}(-Inf) == interval
@test AnchoredInterval{0}(-Inf) == interval

interval = Inf .. Inf
@test AnchoredInterval{+x,Closed,Closed}(Inf) == interval
@test AnchoredInterval{-x,Closed,Closed}(Inf) == interval
@test AnchoredInterval{0}(Inf) == interval
# Note: Ideally the exception raised would always be `ArgumentError`.
@testset "$inf" for (inf, Error) in zip((Inf, ∞), (ArgumentError, InfMinusInfError))
interval = 0 .. inf
@test AnchoredInterval{inf,Closed,Closed}(0.0) == interval
# Not-possible: AnchoredInterval{-?,Closed,Closed}(inf)

interval = -inf .. 0
# Not-possible: AnchoredInterval{+?,Closed,Closed}(-inf)
@test AnchoredInterval{-inf,Closed,Closed}(0.0) == interval

interval = -inf .. inf
@test_throws Error AnchoredInterval{inf,Closed,Closed}(-inf)
@test_throws Error AnchoredInterval{-inf,Closed,Closed}(inf)

interval = -inf .. -inf
@test AnchoredInterval{+x,Closed,Closed}(-inf) == interval
@test AnchoredInterval{-x,Closed,Closed}(-inf) == interval
@test AnchoredInterval{0}(-inf) == interval

interval = inf .. inf
@test AnchoredInterval{+x,Closed,Closed}(inf) == interval
@test AnchoredInterval{-x,Closed,Closed}(inf) == interval
@test AnchoredInterval{0}(inf) == interval
end
end

@testset "nan" begin
Expand Down Expand Up @@ -136,6 +139,12 @@ using Intervals: Bounded, Ending, Beginning, canonicalize, isunbounded
@test_throws ArgumentError convert(AnchoredInterval{Ending}, Interval(0, Inf))
@test convert(AnchoredInterval{Beginning}, Interval(0, Inf)) == AnchoredInterval{Inf,Float64,Closed,Closed}(0)

@test convert(AnchoredInterval{Ending}, Interval(-∞, 0)) == AnchoredInterval{-∞,Float64,Closed,Closed}(0)
@test_throws InfMinusInfError convert(AnchoredInterval{Beginning}, Interval(-∞, 0))

@test_throws InfMinusInfError convert(AnchoredInterval{Ending}, Interval(0, ∞))
@test convert(AnchoredInterval{Beginning}, Interval(0, ∞)) == AnchoredInterval{∞,Float64,Closed,Closed}(0)

@test_throws ArgumentError convert(AnchoredInterval{Ending}, Interval(nothing, 0))
@test_throws ArgumentError convert(AnchoredInterval{Beginning}, Interval(nothing, 0))

Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Base.Iterators: product
using Dates
using Documenter: doctest
using Infinity: Infinite, InfExtendedReal, InfExtendedTime, ∞
using Infinity: Infinite, InfExtendedReal, InfExtendedTime, InfMinusInfError,
using Intervals
using Serialization: deserialize
using Test
Expand Down

0 comments on commit 9b68184

Please sign in to comment.