1
- @doc """
2
- An Interval represents all values between and including its two endpoints.
3
- Intervals are parameterized by the type of its endpoints; this type must be
4
- a concrete leaf type that supports a partial ordering. Promoting arithmetic
5
- is defined for Intervals of `Number` and `Dates.AbstractTime`.
6
-
7
- ### Type parameters
8
-
9
- ```julia
10
- immutable Interval{T}
11
- ```
12
- * `T` : the type of the interval's endpoints. Must be a concrete leaf type.
13
-
14
- ### Constructors
15
-
16
- ```julia
17
- Interval(a, b)
18
- a .. b
19
- ```
20
-
21
- ### Arguments
22
-
23
- * `a` : lower bound of the interval
24
- * `b` : upper bound of the interval
25
-
26
- ### Examples
27
-
28
- ```julia
29
- A = AxisArray(collect(1:20), Axis{:time}(.1:.1:2.0))
30
- A[Interval(0.2,0.5)]
31
- A[0.0 .. 0.5]
32
- ```
33
-
34
- """ ->
35
- immutable Interval{T}
36
- lo:: T
37
- hi:: T
38
- function Interval (lo, hi)
39
- lo <= hi ? new (lo, hi) : throw (ArgumentError (" lo must be less than or equal to hi" ))
40
- end
41
- end
42
- Interval {T} (a:: T ,b:: T ) = Interval {T} (a,b)
43
- # Allow promotion during construction, but only if it results in a leaf type
44
- function Interval {T,S} (a:: T , b:: S )
45
- R = promote_type (T,S)
46
- isleaftype (R) || throw (ArgumentError (" cannot promote $a and $b to a common leaf type" ))
47
- Interval {R} (promote (a,b)... )
48
- end
49
- const .. = Interval
50
-
51
- Base. convert {T} (:: Type{Interval} , x:: T ) = Interval {T} (x,x)
52
- Base. convert {T} (:: Type{Interval{T}} , x:: T ) = Interval {T} (x,x)
53
- Base. convert {T,S} (:: Type{Interval{T}} , x:: S ) = (y= convert (T, x); Interval {T} (y,y))
54
- Base. convert {T} (:: Type{Interval{T}} , w:: Interval ) = Interval {T} (convert (T, w. lo), convert (T, w. hi))
55
-
56
1
# Promotion rules for "promiscuous" types like Intervals and SIUnits, which both
57
2
# simply wrap any Number, are often ambiguous. That is, which type should "win"
58
- # -- is the promotion between an SIUnit and an Interval an SIQuantity{Interval }
59
- # or is it an Interval {SIQuantity}? For our uses in AxisArrays, though, we can
3
+ # -- is the promotion between an SIUnit and an ClosedInterval an SIQuantity{ClosedInterval }
4
+ # or is it an ClosedInterval {SIQuantity}? For our uses in AxisArrays, though, we can
60
5
# sidestep this problem by making Intervals *not* a subtype of Number. Then in
61
6
# order for them to plug into the promotion system, we *extend* the promoting
62
- # operator behaviors to Union{Number, Interval }. This way other types can
7
+ # operator behaviors to Union{Number, ClosedInterval }. This way other types can
63
8
# similarly define their own extensions to the promoting operators without fear
64
9
# of ambiguity -- there will simply be, e.g.,
65
10
#
66
11
# f(x::Number, y::Number) = f(promote(x,y)...) # in base
67
- # f(x::Union{Number, Interval }, y::Union{Number, Interval }) = f(promote(x,y)...)
12
+ # f(x::Union{Number, ClosedInterval }, y::Union{Number, ClosedInterval }) = f(promote(x,y)...)
68
13
# f(x::Union{Number, T}, y::Union{Number, T}) = f(promote(x,y)...)
69
14
#
70
15
# In this way, these "promiscuous" types will never interact unless explicitly
@@ -73,78 +18,71 @@ Base.convert{T}(::Type{Interval{T}}, w::Interval) = Interval{T}(convert(T, w.lo)
73
18
# could be considered as <: Number themselves. We do this in general for any
74
19
# supported Scalar:
75
20
typealias Scalar Union{Number, Dates. AbstractTime}
76
- Base. promote_rule {T<:Scalar} (:: Type{Interval {T}} , :: Type{T} ) = Interval {T}
77
- Base. promote_rule {T,S<:Scalar} (:: Type{Interval {T}} , :: Type{S} ) = Interval {promote_type (T,S)}
78
- Base. promote_rule {T,S} (:: Type{Interval {T}} , :: Type{Interval {S}} ) = Interval {promote_type (T,S)}
21
+ Base. promote_rule {T<:Scalar} (:: Type{ClosedInterval {T}} , :: Type{T} ) = ClosedInterval {T}
22
+ Base. promote_rule {T,S<:Scalar} (:: Type{ClosedInterval {T}} , :: Type{S} ) = ClosedInterval {promote_type (T,S)}
23
+ Base. promote_rule {T,S} (:: Type{ClosedInterval {T}} , :: Type{ClosedInterval {S}} ) = ClosedInterval {promote_type (T,S)}
79
24
80
25
import Base: isless, <= , >= , == , + , - , * , / , ^ , //
81
26
# TODO : Is this a total ordering? (antisymmetric, transitive, total)?
82
- isless (a:: Interval , b:: Interval ) = isless (a. hi , b. lo )
27
+ isless (a:: ClosedInterval , b:: ClosedInterval ) = isless (a. right , b. left )
83
28
# The default definition for <= assumes a strict total order (<=(x,y) = !(y < x))
84
- <= (a:: Interval , b:: Interval ) = a. lo <= b. lo && a. hi <= b. hi
85
- == (a:: Interval , b:: Interval ) = a. hi == b. hi && a. lo == b. lo
86
- const _interval_hash = UInt == UInt64 ? 0x1588c274e0a33ad4 : 0x1e3f7252
87
- Base. hash (a:: Interval , h:: UInt ) = hash (a. lo, hash (a. hi, hash (_interval_hash, h)))
88
- + (a:: Interval ) = a
89
- + (a:: Interval , b:: Interval ) = Interval (a. lo + b. lo, a. hi + b. hi)
90
- - (a:: Interval ) = Interval (- a. hi, - a. lo)
91
- - (a:: Interval , b:: Interval ) = a + (- b)
29
+ <= (a:: ClosedInterval , b:: ClosedInterval ) = a. left <= b. left && a. right <= b. right
30
+ + (a:: ClosedInterval ) = a
31
+ + (a:: ClosedInterval , b:: ClosedInterval ) = ClosedInterval (a. left + b. left, a. right + b. right)
32
+ - (a:: ClosedInterval ) = ClosedInterval (- a. right, - a. left)
33
+ - (a:: ClosedInterval , b:: ClosedInterval ) = a + (- b)
92
34
for f in (:(* ), :(/ ), :(// ))
93
35
# For a general monotonic operator, we compute the operation over all
94
36
# combinations of the endpoints and return the widest interval
95
- @eval function $ (f)(a:: Interval , b:: Interval )
96
- w = $ (f)(a. lo , b. lo )
97
- x = $ (f)(a. lo , b. hi )
98
- y = $ (f)(a. hi , b. lo )
99
- z = $ (f)(a. hi , b. hi )
100
- Interval (min (w,x,y,z), max (w,x,y,z))
37
+ @eval function $ (f)(a:: ClosedInterval , b:: ClosedInterval )
38
+ w = $ (f)(a. left , b. left )
39
+ x = $ (f)(a. left , b. right )
40
+ y = $ (f)(a. right , b. left )
41
+ z = $ (f)(a. right , b. right )
42
+ ClosedInterval (min (w,x,y,z), max (w,x,y,z))
101
43
end
102
44
end
103
45
104
- Base. in (a, b:: Interval ) = b. lo <= a <= b. hi
105
- Base. in (a:: Interval , b:: Interval ) = b. lo <= a. lo && a. hi <= b. hi
106
- Base. minimum (a:: Interval ) = a. lo
107
- Base. maximum (a:: Interval ) = a. hi
108
46
# Extend the promoting operators to include Intervals. The comparison operators
109
47
# (<, <=, and ==) are a pain since they are non-promoting fallbacks that call
110
48
# isless, !(y < x) (which is wrong), and ===. So implementing promotion with
111
- # Union{T, Interval } causes stack overflows for the base types. This is safer:
49
+ # Union{T, ClosedInterval } causes stack overflows for the base types. This is safer:
112
50
for f in (:isless , :(<= ), :(>= ), :(== ), :(+ ), :(- ), :(* ), :(/ ), :(// ))
113
51
# We don't use promote here, though, because promotions can be lossy... and
114
52
# that's particularly bad for comparisons. Just make an interval instead.
115
- @eval $ (f)(x:: Interval , y:: Scalar ) = $ (f)(x, y.. y)
116
- @eval $ (f)(x:: Scalar , y:: Interval ) = $ (f)(x.. x, y)
53
+ @eval $ (f)(x:: ClosedInterval , y:: Scalar ) = $ (f)(x, y.. y)
54
+ @eval $ (f)(x:: Scalar , y:: ClosedInterval ) = $ (f)(x.. x, y)
117
55
end
118
56
119
57
# And, finally, we have an Array-of-Structs to Struct-of-Arrays transform for
120
58
# the common case where the interval is constant over many offsets:
121
59
immutable RepeatedInterval{T,S,A} <: AbstractVector{T}
122
- window:: Interval {S}
60
+ window:: ClosedInterval {S}
123
61
offsets:: A # A <: AbstractVector
124
62
end
125
- RepeatedInterval {S,A<:AbstractVector} (window:: Interval {S} , offsets:: A ) = RepeatedInterval {promote_type(Interval {S}, eltype(A)), S, A} (window, offsets)
63
+ RepeatedInterval {S,A<:AbstractVector} (window:: ClosedInterval {S} , offsets:: A ) = RepeatedInterval {promote_type(ClosedInterval {S}, eltype(A)), S, A} (window, offsets)
126
64
Base. size (r:: RepeatedInterval ) = size (r. offsets)
127
65
Base. linearindexing {R<:RepeatedInterval} (:: Type{R} ) = Base. LinearFast ()
128
66
Base. getindex (r:: RepeatedInterval , i:: Int ) = r. window + r. offsets[i]
129
- + (window:: Interval , offsets:: AbstractVector ) = RepeatedInterval (window, offsets)
130
- + (offsets:: AbstractVector , window:: Interval ) = RepeatedInterval (window, offsets)
131
- - (window:: Interval , offsets:: AbstractVector ) = RepeatedInterval (window, - offsets)
132
- - (offsets:: AbstractVector , window:: Interval ) = RepeatedInterval (- window, offsets)
67
+ + (window:: ClosedInterval , offsets:: AbstractVector ) = RepeatedInterval (window, offsets)
68
+ + (offsets:: AbstractVector , window:: ClosedInterval ) = RepeatedInterval (window, offsets)
69
+ - (window:: ClosedInterval , offsets:: AbstractVector ) = RepeatedInterval (window, - offsets)
70
+ - (offsets:: AbstractVector , window:: ClosedInterval ) = RepeatedInterval (- window, offsets)
133
71
134
72
# As a special extension to intervals, we allow specifying Intervals about a
135
73
# particular index, which is resolved by an axis upon indexing.
136
74
immutable IntervalAtIndex{T}
137
- window:: Interval {T}
75
+ window:: ClosedInterval {T}
138
76
index:: Int
139
77
end
140
- atindex (window:: Interval , index:: Integer ) = IntervalAtIndex (window, index)
78
+ atindex (window:: ClosedInterval , index:: Integer ) = IntervalAtIndex (window, index)
141
79
142
80
# And similarly, an AoS -> SoA transform:
143
81
immutable RepeatedIntervalAtIndexes{T,A<: AbstractVector{Int} } <: AbstractVector{IntervalAtIndex{T}}
144
- window:: Interval {T}
82
+ window:: ClosedInterval {T}
145
83
indexes:: A # A <: AbstractVector{Int}
146
84
end
147
- atindex (window:: Interval , indexes:: AbstractVector ) = RepeatedIntervalAtIndexes (window, indexes)
85
+ atindex (window:: ClosedInterval , indexes:: AbstractVector ) = RepeatedIntervalAtIndexes (window, indexes)
148
86
Base. size (r:: RepeatedIntervalAtIndexes ) = size (r. indexes)
149
87
Base. linearindexing {R<:RepeatedIntervalAtIndexes} (:: Type{R} ) = Base. LinearFast ()
150
88
Base. getindex (r:: RepeatedIntervalAtIndexes , i:: Int ) = IntervalAtIndex (r. window, r. indexes[i])
0 commit comments