Skip to content

Commit 05e15c6

Browse files
authored
Fix type stability with union (#119)
* fix type stability with union * fix typo * fix typo again * git add comments to visualize intervals * add `@infered` macro for union and intersection
1 parent 46bbdaa commit 05e15c6

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

src/interval.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,10 @@ end
120120
intersect(d1::AbstractInterval, d2::AbstractInterval) = intersect(Interval(d1), Interval(d2))
121121

122122

123-
function union(d1::TypedEndpointsInterval, d2::TypedEndpointsInterval)
124-
isempty(d1) && return d2
125-
isempty(d2) && return d1
123+
function union(d1::TypedEndpointsInterval{L1,R1,T1}, d2::TypedEndpointsInterval{L2,R2,T2}) where {L1,R1,T1,L2,R2,T2}
124+
T = promote_type(T1,T2)
125+
isempty(d1) && return Interval{L2,R2,T}(d2)
126+
isempty(d2) && return Interval{L1,R1,T}(d1)
126127
any((d1), endpoints(d2)) || any((d2), endpoints(d1)) ||
127128
throw(ArgumentError("Cannot construct union of disjoint sets."))
128129
_union(d1, d2)

test/runtests.jl

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,12 @@ struct IncompleteInterval <: AbstractInterval{Int} end
383383

384384
@testset "Union and intersection" begin
385385
for T in (Float32,Float64)
386+
# i1 0 ------>------ 1
387+
# i2 1/3 ->- 1/2
388+
# i3 1/2 ------>------ 2
389+
# i4 2 -->-- 3
390+
# i5 1.0+ -->-- 2
391+
# i_empty 0 ------<------ 1
386392
i1 = zero(T) .. one(T)
387393
i2 = one(T)/3 .. one(T)/2
388394
i3 = one(T)/2 .. 2*one(T)
@@ -391,7 +397,9 @@ struct IncompleteInterval <: AbstractInterval{Int} end
391397
i_empty = one(T) ..zero(T)
392398

393399
# - union of completely overlapping intervals
394-
@test i1 i2 i2 i1 i1
400+
# i1 0 ------>------ 1
401+
# i2 1/3 ->- 1/2
402+
@test (@inferred i1 i2) (@inferred i2 i1) i1
395403
@test Interval{:open,:closed}(i1) Interval{:open,:closed}(i2)
396404
Interval{:open,:closed}(i2) Interval{:open,:closed}(i1) Interval{:open,:closed}(i1)
397405
@test Interval{:closed,:open}(i1) Interval{:closed,:open}(i2)
@@ -408,7 +416,9 @@ struct IncompleteInterval <: AbstractInterval{Int} end
408416
@test Interval{:open,:closed}(i1) Interval{:closed,:open}(i2) Interval{:closed,:open}(i2) Interval{:open,:closed}(i1) Interval{:open,:closed}(i1)
409417

410418
# - intersection of completely overlapping intervals
411-
@test i1 i2 i2 i1 i2
419+
# i1 0 ------>------ 1
420+
# i2 1/3 ->- 1/2
421+
@test (@inferred i1 i2) (@inferred i2 i1) i2
412422
@test Interval{:open,:closed}(i1) Interval{:open,:closed}(i2)
413423
Interval{:open,:closed}(i2) Interval{:open,:closed}(i1) Interval{:open,:closed}(i2)
414424
@test Interval{:closed,:open}(i1) Interval{:closed,:open}(i2)
@@ -427,8 +437,10 @@ struct IncompleteInterval <: AbstractInterval{Int} end
427437

428438

429439
# - union of partially overlapping intervals
440+
# i1 0 ------>------ 1
441+
# i3 1/2 ------>------ 2
430442
d = zero(T) .. 2*one(T)
431-
@test i1 i3 i3 i1 d
443+
@test (@inferred i1 i3) (@inferred i3 i1) d
432444
@test Interval{:open,:closed}(i1) Interval{:open,:closed}(i3)
433445
Interval{:open,:closed}(i3) Interval{:open,:closed}(i1) Interval{:open,:closed}(d)
434446
@test Interval{:closed,:open}(i1) Interval{:closed,:open}(i3)
@@ -444,11 +456,11 @@ struct IncompleteInterval <: AbstractInterval{Int} end
444456
@test Interval{:open,:closed}(i1) OpenInterval(i3) OpenInterval(i3) Interval{:open,:closed}(i1) OpenInterval(d)
445457
@test Interval{:open,:closed}(i1) Interval{:closed,:open}(i3) Interval{:closed,:open}(i3) Interval{:open,:closed}(i1) OpenInterval(d)
446458

447-
448-
449459
# - intersection of partially overlapping intervals
460+
# i1 0 ------>------ 1
461+
# i3 1/2 ------>------ 2
450462
d = one(T)/2 .. one(T)
451-
@test i1 i3 i3 i1 d
463+
@test (@inferred i1 i3) (@inferred i3 i1) d
452464
@test Interval{:open,:closed}(i1) Interval{:open,:closed}(i3)
453465
Interval{:open,:closed}(i3) Interval{:open,:closed}(i1) Interval{:open,:closed}(d)
454466
@test Interval{:closed,:open}(i1) Interval{:closed,:open}(i3)
@@ -467,8 +479,10 @@ struct IncompleteInterval <: AbstractInterval{Int} end
467479

468480

469481
# - union of barely overlapping intervals
482+
# i2 1/3 ->- 1/2
483+
# i3 1/2 ------>------ 2
470484
d = one(T)/3 .. 2*one(T)
471-
@test i2 i3 i3 i2 d
485+
@test (@inferred i2 i3) (@inferred i3 i2) d
472486
@test Interval{:open,:closed}(i2) Interval{:open,:closed}(i3)
473487
Interval{:open,:closed}(i3) Interval{:open,:closed}(i2) Interval{:open,:closed}(d)
474488
@test Interval{:closed,:open}(i2) Interval{:closed,:open}(i3)
@@ -483,8 +497,10 @@ struct IncompleteInterval <: AbstractInterval{Int} end
483497
@test Interval{:open,:closed}(i2) Interval{:closed,:open}(i3) Interval{:closed,:open}(i3) Interval{:open,:closed}(i2) OpenInterval(d)
484498

485499
# - intersection of barely overlapping intervals
500+
# i2 1/3 ->- 1/2
501+
# i3 1/2 ------>------ 2
486502
d = one(T)/2 .. one(T)/2
487-
@test i2 i3 i3 i2 d
503+
@test (@inferred i2 i3) (@inferred i3 i2) d
488504
@test Interval{:open,:closed}(i2) Interval{:open,:closed}(i3)
489505
Interval{:open,:closed}(i3) Interval{:open,:closed}(i2) Interval{:open,:closed}(d)
490506
@test Interval{:closed,:open}(i2) Interval{:closed,:open}(i3)
@@ -505,6 +521,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
505521
@test intersect(MyUnitInterval(true,true), OpenInterval(0,1)) == OpenInterval(0,1)
506522

507523
# - union of non-overlapping intervals
524+
# i1 0 ------>------ 1
525+
# i4 2 -->-- 3
508526
@test_throws ArgumentError i1 i4
509527
@test_throws ArgumentError i4 i1
510528
@test_throws ArgumentError OpenInterval(i1) i4
@@ -513,6 +531,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
513531
@test_throws ArgumentError Interval{:closed,:open}(i1) OpenInterval(i4)
514532

515533
# - union of almost-overlapping intervals
534+
# i1 0 ------>------ 1
535+
# i5 1.0+ -->-- 2
516536
@test_throws ArgumentError i1 i5
517537
@test_throws ArgumentError i5 i1
518538
@test_throws ArgumentError OpenInterval(i1) i5
@@ -521,6 +541,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
521541
@test_throws ArgumentError Interval{:closed,:open}(i1) OpenInterval(i5)
522542

523543
# - intersection of non-overlapping intervals
544+
# i1 0 ------>------ 1
545+
# i4 2 -->-- 3
524546
@test isempty(i1 i4)
525547
@test isempty(i4 i1)
526548
@test isempty(OpenInterval(i1) i4)
@@ -534,6 +556,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
534556

535557

536558
# - intersection of almost-overlapping intervals
559+
# i1 0 ------>------ 1
560+
# i5 1.0+ -->-- 2
537561
@test isempty(i1 i5)
538562
@test isempty(i5 i1)
539563
@test isempty(OpenInterval(i1) i5)
@@ -546,6 +570,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
546570
@test isdisjoint(Interval{:closed,:open}(i1), i5)
547571

548572
# - union of interval with empty
573+
# i1 0 ------>------ 1
574+
# i_empty 0 ------<------ 1
549575
@test i1 i_empty i_empty i1 i1
550576
@test Interval{:open,:closed}(i1) Interval{:open,:closed}(i_empty)
551577
Interval{:open,:closed}(i_empty) Interval{:open,:closed}(i1) Interval{:open,:closed}(i1)
@@ -563,6 +589,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
563589
@test Interval{:open,:closed}(i1) Interval{:closed,:open}(i_empty) Interval{:closed,:open}(i_empty) Interval{:open,:closed}(i1) Interval{:open,:closed}(i1)
564590

565591
# - intersection of interval with empty
592+
# i1 0 ------>------ 1
593+
# i_empty 0 ------<------ 1
566594
@test isempty(i1 i_empty)
567595
@test isempty(i_empty i1)
568596
@test isempty(OpenInterval(i1) i_empty)

0 commit comments

Comments
 (0)