Skip to content

Commit 53a7ec3

Browse files
committed
Adds Closed Interval
1 parent a3d451e commit 53a7ec3

File tree

6 files changed

+126
-6
lines changed

6 files changed

+126
-6
lines changed

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ os:
44
- linux
55
- osx
66
julia:
7-
- release
7+
- 0.5
88
- nightly
99
notifications:
1010
email: false
@@ -15,5 +15,3 @@ notifications:
1515
after_success:
1616
# push coverage results to Coveralls
1717
- julia -e 'cd(Pkg.dir("IntervalSets")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
18-
# push coverage results to Codecov
19-
- julia -e 'cd(Pkg.dir("IntervalSets")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
# IntervalSets.jl
22
Interval Sets for Julia
3+
4+
[![Build Status](https://travis-ci.org/JuliaMath/IntervalSets.jl.svg?branch=master)](https://travis-ci.org/JuliaMath/IntervalSets.jl)
5+
6+
[![Coverage Status](https://coveralls.io/repos/github/JuliaMath/IntervalSets.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaMath/IntervalSets.jl?branch=master)

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
julia 0.4
1+
julia 0.5-

src/IntervalSets.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,13 @@ module IntervalSets
22

33
# package code goes here
44

5+
import Base: show, in, length, isempty, isequal, issubset, ==, union, intersect
6+
7+
export ClosedInterval, , .., ±, ordered
8+
9+
include("closed.jl")
10+
11+
ordered{T}(a::T, b::T) = ifelse(a < b, (a, b), (b, a))
12+
ordered(a, b) = ordered(promote(a, b)...)
13+
514
end # module

src/closed.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
A `ClosedInterval(left, right)` is an interval set that includes both its upper and lower bounds. In
3+
mathematical notation, the constructed range is `[left, right]`.
4+
"""
5+
immutable ClosedInterval{T}
6+
left::T
7+
right::T
8+
end
9+
10+
ClosedInterval(left, right) = ClosedInterval(promote(left, right)...)
11+
12+
..(x, y) = ClosedInterval(x, y)
13+
14+
±(x, y) = ClosedInterval(x - y, x + y)
15+
±(x::CartesianIndex, y) = map(ClosedInterval, (x - y).I, (x + y).I)
16+
17+
show(io::IO, I::ClosedInterval) = print(io, I.left, "..", I.right)
18+
19+
in(v, I::ClosedInterval) = I.left <= v <= I.right
20+
21+
isempty(A::ClosedInterval) = A.left > A.right
22+
23+
isequal(A::ClosedInterval, B::ClosedInterval) = (isequal(A.left, B.left) & isequal(A.right, B.right)) | (isempty(A) & isempty(B))
24+
25+
==(A::ClosedInterval, B::ClosedInterval) = (A.left == B.left && A.right == B.right) || (isempty(A) && isempty(B))
26+
27+
function intersect(A::ClosedInterval, B::ClosedInterval)
28+
left = max(A.left, B.left)
29+
right = min(A.right, B.right)
30+
ClosedInterval(left, right)
31+
end
32+
33+
function union{T<:AbstractFloat}(A::ClosedInterval{T}, B::ClosedInterval{T})
34+
max(A.left, B.left) <= nextfloat(min(A.right, B.right)) || throw(ArgumentError("Cannot construct union of disjoint sets."))
35+
_union(A, B)
36+
end
37+
38+
function union(A::ClosedInterval, B::ClosedInterval)
39+
max(A.left, B.left) <= min(A.right, B.right) || throw(ArgumentError("Cannot construct union of disjoint sets."))
40+
_union(A, B)
41+
end
42+
43+
function _union(A::ClosedInterval, B::ClosedInterval)
44+
left = min(A.left, B.left)
45+
right = max(A.right, B.right)
46+
ClosedInterval(left, right)
47+
end
48+
49+
issubset(A::ClosedInterval, B::ClosedInterval) = ((A.left in B) && (A.right in B)) || isempty(A)
50+
51+
(A::ClosedInterval, B::ClosedInterval) = issubset(B, A)

test/runtests.jl

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,63 @@
11
using IntervalSets
22
using Base.Test
33

4-
# write your own tests here
5-
@test 1 == 2
4+
@testset "IntervalSets" begin
5+
io = IOBuffer()
6+
@test ordered(2, 1) == (1, 2)
7+
@test ordered(1, 2) == (1, 2)
8+
@test ordered(Float16(1), 2) == (1, 2)
9+
10+
@testset "Closed Sets" begin
11+
I = 0..3
12+
print(io, I)
13+
@test String(io) == "0..3"
14+
J = 3..2
15+
K = 5..4
16+
L = 3 ± 2
17+
M = ClosedInterval(2, 5.0)
18+
takebuf_array(io)
19+
print(io, M)
20+
@test String(io) == "2.0..5.0"
21+
N = ClosedInterval(UInt8(255), 300)
22+
O = CartesianIndex(1, 2, 3, 4) ± 2
23+
@test O == (-1..3, 0..4, 1..5, 2..6)
24+
25+
@test !isempty(I)
26+
@test isempty(J)
27+
@test J == K
28+
@test I != K
29+
@test I == I
30+
@test J == J
31+
@test L == L
32+
@test isequal(I, I)
33+
@test isequal(J, K)
34+
35+
@test typeof(M.left) == typeof(M.right) && typeof(M.left) == Float64
36+
@test typeof(N.left) == typeof(N.right) && typeof(N.left) == Int
37+
38+
@test 2 in I
39+
40+
@test I L == ClosedInterval(0, 5)
41+
@test I L == ClosedInterval(1, 3)
42+
@test isempty(J K)
43+
@test isempty((2..5) (7..10))
44+
@test isempty((1..10) (7..2))
45+
A = Float16(1.1)..Float16(1.234)
46+
B = Float16(1.235)..Float16(1.3)
47+
C = Float16(1.236)..Float16(1.3)
48+
D = Float16(1.1)..Float16(1.236)
49+
@test A B == Float16(1.1)..Float16(1.3)
50+
@test D B == Float16(1.1)..Float16(1.3)
51+
@test D C == Float16(1.1)..Float16(1.3)
52+
@test_throws(ArgumentError, A C)
53+
54+
@test J L
55+
@test (L J) == false
56+
@test K I
57+
@test ClosedInterval(1, 2) I
58+
@test I I
59+
@test (ClosedInterval(7, 9) I) == false
60+
@test I I
61+
@test I ClosedInterval(1, 2)
62+
end
63+
end

0 commit comments

Comments
 (0)