Skip to content

Commit

Permalink
Merge pull request #3 from JuliaMath/teh/axisarrays
Browse files Browse the repository at this point in the history
Add features for supporting AxisArrays
  • Loading branch information
timholy authored Sep 11, 2016
2 parents 5da8cf9 + 024f3f5 commit 9a4d3ea
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 9 deletions.
20 changes: 18 additions & 2 deletions src/IntervalSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,29 @@ module IntervalSets

# package code goes here

import Base: show, in, length, isempty, isequal, issubset, ==, union, intersect
using Base: @pure
import Base: eltype, convert, show, in, length, isempty, isequal, issubset, ==, hash, union, intersect, minimum, maximum

export ClosedInterval, , .., ±, ordered
export AbstractInterval, ClosedInterval, , .., ±, ordered

abstract AbstractInterval{T}

include("closed.jl")

eltype{T}(::Type{AbstractInterval{T}}) = T
@pure eltype{I<:AbstractInterval}(::Type{I}) = eltype(supertype(I))

convert{I<:AbstractInterval}(::Type{I}, i::I) = i
function convert{I<:AbstractInterval}(::Type{I}, i::AbstractInterval)
T = eltype(I)
I(convert(T, i.left), convert(T, i.right))
end

ordered{T}(a::T, b::T) = ifelse(a < b, (a, b), (b, a))
ordered(a, b) = ordered(promote(a, b)...)

checked_conversion{T}(::Type{T}, a, b) = _checked_conversion(T, convert(T, a), convert(T, b))
_checked_conversion{T}(::Type{T}, a::T, b::T) = a, b
_checked_conversion{T}(::Type{T}, a, b) = throw(ArgumentError("$a and $b are not both of type $T"))

end # module
28 changes: 25 additions & 3 deletions src/closed.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
"""
A `ClosedInterval(left, right)` is an interval set that includes both its upper and lower bounds. In
A `ClosedInterval(left, right)` is an interval set that includes both its upper and lower bounds. In
mathematical notation, the constructed range is `[left, right]`.
"""
immutable ClosedInterval{T}
immutable ClosedInterval{T} <: AbstractInterval{T}
left::T
right::T

ClosedInterval(l::T, r::T) = new(l, r)
end

ClosedInterval{T}(left::T, right::T) = ClosedInterval{T}(left, right)
(::Type{ClosedInterval{T}}){T}(left, right) =
ClosedInterval{T}(checked_conversion(T, left, right)...)

function ClosedInterval(left, right)
# Defining this as ClosedInterval(promote(left, right)...) has one problem:
# if left and right do not promote to a common type, it triggers a StackOverflow.
T = promote_type(typeof(left), typeof(right))
ClosedInterval{T}(checked_conversion(T, left, right)...)
end

ClosedInterval(left, right) = ClosedInterval(promote(left, right)...)
ClosedInterval(i::AbstractInterval) = convert(ClosedInterval{eltype(i)}, i)
(::Type{ClosedInterval{T}}){T}(i::AbstractInterval) = convert(ClosedInterval{T}, i)

..(x, y) = ClosedInterval(x, y)

Expand All @@ -17,13 +31,21 @@ ClosedInterval(left, right) = ClosedInterval(promote(left, right)...)
show(io::IO, I::ClosedInterval) = print(io, I.left, "..", I.right)

in(v, I::ClosedInterval) = I.left <= v <= I.right
in(a::ClosedInterval, b::ClosedInterval) = (b.left <= a.left) & (a.right <= b.right)

isempty(A::ClosedInterval) = A.left > A.right

isequal(A::ClosedInterval, B::ClosedInterval) = (isequal(A.left, B.left) & isequal(A.right, B.right)) | (isempty(A) & isempty(B))

==(A::ClosedInterval, B::ClosedInterval) = (A.left == B.left && A.right == B.right) || (isempty(A) && isempty(B))

const _closed_interval_hash = UInt == UInt64 ? 0x1588c274e0a33ad4 : 0x1e3f7252

hash(I::ClosedInterval, h::UInt) = hash(I.left, hash(I.right, hash(_closed_interval_hash, h)))

minimum(I::ClosedInterval) = I.left
maximum(I::ClosedInterval) = I.right

function intersect(A::ClosedInterval, B::ClosedInterval)
left = max(A.left, B.left)
right = min(A.right, B.right)
Expand Down
22 changes: 18 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,28 @@ using Base.Test
@test ordered(Float16(1), 2) == (1, 2)

@testset "Closed Sets" begin
@test_throws ArgumentError :a .. "b"
I = 0..3
print(io, I)
@test String(io) == "0..3"
@test takebuf_string(io) == "0..3"
J = 3..2
K = 5..4
L = 3 ± 2
M = ClosedInterval(2, 5.0)
takebuf_array(io)
print(io, M)
@test String(io) == "2.0..5.0"
@test takebuf_string(io) == "2.0..5.0"
N = ClosedInterval(UInt8(255), 300)
O = CartesianIndex(1, 2, 3, 4) ± 2
@test O == (-1..3, 0..4, 1..5, 2..6)

@test eltype(I) == Int
@test eltype(M) == Float64
@test convert(ClosedInterval{Float64}, I) === 0.0..3.0
@test !(convert(ClosedInterval{Float64}, I) === 0..3)
@test ClosedInterval{Float64}(1,3) === 1.0..3.0
@test ClosedInterval(0.5..2.5) === 0.5..2.5
@test ClosedInterval{Int}(1.0..3.0) === 1..3

@test !isempty(I)
@test isempty(J)
@test J == K
Expand All @@ -33,9 +41,13 @@ using Base.Test
@test isequal(J, K)

@test typeof(M.left) == typeof(M.right) && typeof(M.left) == Float64
@test typeof(N.left) == typeof(N.right) && typeof(N.left) == Int
@test typeof(N.left) == typeof(N.right) && typeof(N.left) == Int

@test maximum(I) === 3
@test minimum(I) === 0

@test 2 in I
@test 1..2 in 0.5..2.5

@test I L == ClosedInterval(0, 5)
@test I L == ClosedInterval(1, 3)
Expand All @@ -59,5 +71,7 @@ using Base.Test
@test (ClosedInterval(7, 9) I) == false
@test I I
@test I ClosedInterval(1, 2)

@test hash(1..3) == hash(1.0..3.0)
end
end

0 comments on commit 9a4d3ea

Please sign in to comment.