-
Notifications
You must be signed in to change notification settings - Fork 18
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
[WIP] Interval bounds field #217
base: v2-DEV
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -10,6 +10,7 @@ using Dates: AbstractDateTime, value, coarserperiod | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import Base: ⊆, ⊇, ⊈, ⊉, union, union!, merge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# TODO: Drop these types in favour of symbols when we switch to extending IntervalSets.jl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
abstract type Bound end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
abstract type Bounded <: Bound end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
struct Closed <: Bounded end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -18,23 +19,52 @@ struct Unbounded <: Bound end | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bound_type(x::Bool) = x ? Closed : Open | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
abstract type AbstractInterval{T, L <: Bound, R <: Bound} end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Methods for convert between int and tuple representations for space efficiency | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# (Open, Closed) is 16 bytes while the integer represenation is only 1 byte. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# TODO: Convert types to symbols when we switch to extending IntervalSets.jl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Open}, r::Type{Open}) = 0x00 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Closed}, r::Type{Open}) = 0x01 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Open}, r::Type{Closed}) = 0x02 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Closed}, r::Type{Closed}) = 0x03 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(x::Integer) = bounds_types(Val(UInt8(x))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+25
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed opportunities to use bit masks:
Suggested change
Can make this logic even cleaner with something like: https://github.com/JuliaTime/TimeZones.jl/blob/master/src/class.jl There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually my initial pass did this, but I concluded that the value dispatch was more declarative / readable and I didn't notice a performance difference either way... though maybe there's a specific case you're thinking of? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just from a reasoning standpoint it seems sensible to denote each of the 8-bits for a specific purpose. Your values from I'm fine with using |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x00}) = (Open, Open) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x01}) = (Closed, Open) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x02}) = (Open, Closed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x03}) = (Closed, Closed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Extension for backwards support of Unbounded endpoints to avoid changing existing logic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# TODO: Drop these in favour of the approach in IntervalSets.jl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like an approach has yet to be worked out: JuliaMath/IntervalSets.jl#123 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the question is whether it should be the responsibility of either IntervalSets.jl or Intervals.jl to handle this with yet another custom type. AFAICT, bounded-ness is just a question of whether an endpoint value There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do agree that using
This is where it started to make more sense to have the intervals to support infinity themselves. For example An alternative strategy could be something like: struct Interval{T}
first::Union{T,NegInf}
last::Union{T,PosInf}
end but I doubt that would be an improvement over the v1 setup. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Open}, r::Type{Unbounded}) = 0x04 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Closed}, r::Type{Unbounded}) = 0x05 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Unbounded}, r::Type{Open}) = 0x06 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Unbounded}, r::Type{Closed}) = 0x07 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_int(l::Type{Unbounded}, r::Type{Unbounded}) = 0x08 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x04}) = (Open, Unbounded) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x05}) = (Closed, Unbounded) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x06}) = (Unbounded, Open) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x07}) = (Unbounded, Closed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(::Val{0x08}) = (Unbounded, Unbounded) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
abstract type AbstractInterval{T} end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Base.eltype(::AbstractInterval{T}) where {T} = T | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Base.broadcastable(x::AbstractInterval) = Ref(x) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bounds_types(x::AbstractInterval{T,L,R}) where {T,L,R} = (L, R) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Subtypes should implement: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# 1. first and last accessors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# 2. bounds_integer and bounds_types accessor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("isfinite.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("endpoint.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("interval.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("interval_sets.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# include("interval_sets.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("anchoredinterval.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("parse.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("description.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("plotting.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("docstrings.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("deprecated.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
include("compat.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include("plotting.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include("docstrings.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include("deprecated.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include("compat.jl") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export Bound, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Closed, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been catching up with the motivation behind these changes. Is there rational why using symbols is a better approach than using types? Should IntervalSets.jl be updated to use types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel like it matters either way. My preference is more focused on making things consistent between the two, so Intervals.jl can extend IntervalSets.jl. As it stands, there doesn't seem to be much advantage to having them be types. We don't leverage the type hierarchy much and we don't store any information in them, so it's just extra names/types to remember. The practical benefit of switching to symbols is that it means we may be able to have Intervals.jl extend IntervalSets.jl with only one breaking release in Intervals.jl. Going the other way around would require a breaking release to IntervalSets.jl and a lot more updates in the ecosystem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the counter argument to using symbols is that by using types you can use the standard type inspection functions to determine what the names are used by this package. Dispatch on these types isn't used commonly outside of this package but I do think it's extremely useful for the internal logic in
endpoint.jl
.