Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Infinity.jl #95

Closed
wants to merge 12 commits into from
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ name = "Intervals"
uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
license = "MIT"
authors = ["Invenia Technical Computing"]
version = "1.1.0"
version = "1.2.0"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Infinity = "a303e19e-6eb4-11e9-3b09-cd9505f79100"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53"

[compat]
Infinity = "0.1"
RecipesBase = "0.8, 1"
TimeZones = "0.7, 0.8, 0.9, 0.10, 0.11, 1"
julia = "1"
Expand Down
1 change: 1 addition & 0 deletions src/Intervals.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Intervals

using Dates
using Infinity: Infinite, InfExtended, isposinf, isneginf
using Printf
using RecipesBase
using TimeZones
Expand Down
25 changes: 24 additions & 1 deletion src/interval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@ struct Interval{T} <: AbstractInterval{T}
end
end

"""
Check if a value is ∞ or not. Specifically check if the type is `Infinite`,
or `InfExtended`, and then check if the value is pos or neg infinity.
"""
function isbounded(a)
T = typeof(a)
if T <: Infinite || T <: InfExtended
return !isposinf(a) && !isneginf(a)
else
return true
end
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if a user has explicitly set T we shouldn't be messing with it.

Copy link
Member Author

@fchorney fchorney May 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm yeah I suppose this change is actually just a byproduct of trying to throw in unbounded values into the tests.

This test is specifically the issue (https://github.com/invenia/Intervals.jl/blob/fc/using-infinity/test/interval.jl#L46-L47):

@test Interval(b, a, Inclusivity(true, false)) == Interval{typeof(a)}(a, b, Inclusivity(false, true))

When you create the interval on the left side of == it will promote(b, a) so if one value is and the other is a value, let's say 10, then it converts both values to InfExtended. Now on the right side of ==, if a is of type Infinite (due to being a or -∞) then it will try to convert(Infinite, 10) for b, which is an error. On the other side of the spectrum, if a is 10 which would make it Int64 type, then trying to do convert(Int64, ∞) for b will also fail. I guess we can just let it be an error if somebody puts in the wrong type in the Interval constructor.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the test should be updated to be using:

julia> promote_type(Infinite, Int)
InfExtended{Int64}

Then in the tests you can use Interval{promote_type(typeof(a), typeof(b))}(...)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isfinite works with Infinity and InfExtended types as well as the Inf from Float64. Additionally this works with TimeTypes:

Suggested change
function isbounded(a)
T = typeof(a)
if T <: Infinite || T <: InfExtended
return !isposinf(a) && !isneginf(a)
else
return true
end
end
isbounded(x) = isfinite(x)

isunbounded(a) = !isbounded(a)

Interval{T}(f, l, inc::Inclusivity) where T = Interval{T}(convert(T, f), convert(T, l), inc)
Interval{T}(f, l, x::Bool, y::Bool) where T = Interval{T}(f, l, Inclusivity(x, y))
Interval{T}(f, l) where T = Interval{T}(f, l, true, true)
Expand All @@ -89,6 +103,14 @@ function Interval{T}(left::LeftEndpoint{T}, right::RightEndpoint{T}) where T
Interval{T}(left.endpoint, right.endpoint, left.included, right.included)
end

"""
When the endpoints are different types, try to find a common type to combined them into
"""
function Interval(left::LeftEndpoint{S}, right::RightEndpoint{D}) where {S, D}
T = promote_type(S, D)
return Interval{T}(left.endpoint, right.endpoint, left.included, right.included)
end

Interval(left::LeftEndpoint{T}, right::RightEndpoint{T}) where T = Interval{T}(left, right)

# Empty Intervals
Expand Down Expand Up @@ -161,7 +183,8 @@ end

##### ARITHMETIC #####

Base.:+(a::T, b) where {T <: Interval} = T(first(a) + b, last(a) + b, inclusivity(a))
Base.:+(a::Interval, b) = Interval(first(a) + b, last(a) + b, inclusivity(a))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous version always kept the Interval unit type the same. This could cause the Interval type to change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This becomes the same issue as most of the other issues that cropped up by adding Infinity. If a is -∞ .. ∞ and b is of type Int then ∞ - b where b is 1 becomes an InfExtended{Int64} type which will error out since T would have been Interval{Infinite}(...). So we end up trying to run convert(Infinite, InfExtended{Int64}) which is undefined. That being said, maybe that shouldn't be undefined. Converting an InfExtended{Int64}) to Infinite could potentially work if we check the value to make sure it's not an actual extended value

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That conversion makes sense if the InfExtended{Int64} is infinite

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by adding the conversion: cjdoris/Infinity.jl#7



Base.:+(a, b::Interval) = b + a
Base.:-(a::Interval, b) = a + -b
Expand Down
Loading