|
| 1 | +using OffsetArrays |
| 2 | + |
| 3 | +# Helper function to test that findall(in(interval), x) works. By |
| 4 | +# default, a reference is generated using the general algorithm, |
| 5 | +# linear in complexity, by generating a vector with the same contents |
| 6 | +# as x. |
| 7 | +function assert_in_interval(x, interval, |
| 8 | + expected=findall(v -> v ∈ interval, x)) |
| 9 | + |
| 10 | + result = :(findall(in($interval), $x)) |
| 11 | + expr = :($result == $expected || isempty($result) && isempty($expected)) |
| 12 | + if !(@eval $expr) |
| 13 | + println("Looking for elements of $x ∈ $interval, got $(@eval $result), expected $expected") |
| 14 | + length(x) < 30 && println(" x = ", collect(pairs(x)), "\n") |
| 15 | + end |
| 16 | + @eval @test $expr |
| 17 | +end |
| 18 | + |
| 19 | +@testset "Interval coverage" begin |
| 20 | + @testset "Basic tests" begin |
| 21 | + let x = range(0, stop=1, length=21) |
| 22 | + Random.seed!(321) |
| 23 | + @testset "$kind" for (kind,end_points) in [ |
| 24 | + ("Two intervals", [(0.0, 0.5), (0.25,0.5)]), |
| 25 | + ("Three intervals", [(0, 1/3), (1/3, 2/3), (2/3, 1)]), |
| 26 | + ("Random intervals", [minmax(rand(),rand()) for i = 1:2]), |
| 27 | + ("Interval containing one point", [(0.4619303378979984,0.5450937144417902)]), |
| 28 | + ("Interval containing no points", [(0.9072957410215778,0.9082803807133988)]) |
| 29 | + ] |
| 30 | + @testset "L=$L" for L=[:closed,:open] |
| 31 | + @testset "R=$R" for R=[:closed,:open] |
| 32 | + for (a,b) in end_points |
| 33 | + interval = Interval{L,R}(a, b) |
| 34 | + @testset "Reversed: $reversed" for reversed in [false, true] |
| 35 | + assert_in_interval(reversed ? reverse(x) : x, interval) |
| 36 | + end |
| 37 | + end |
| 38 | + end |
| 39 | + end |
| 40 | + end |
| 41 | + |
| 42 | + @testset "Open interval" begin |
| 43 | + assert_in_interval(x, OpenInterval(0.2,0.4), 6:8) |
| 44 | + end |
| 45 | + end |
| 46 | + end |
| 47 | + |
| 48 | + @testset "Partially covered intervals" begin |
| 49 | + @testset "$T" for T in (Float32,Float64,BigFloat) |
| 50 | + @testset "$name, x = $x" for (name,x) in [ |
| 51 | + ("Outside left",range(T(-1),stop=T(-0.5),length=10)), |
| 52 | + ("Touching left",range(T(-1),stop=T(0),length=10)), |
| 53 | + ("Touching left-ϵ",range(T(-1),stop=T(0)-eps(T),length=10)), |
| 54 | + ("Touching left+ϵ",range(T(-1),stop=T(0)+eps(T),length=10)), |
| 55 | + |
| 56 | + ("Outside right",range(T(1.5),stop=T(2),length=10)), |
| 57 | + ("Touching right",range(T(1),stop=T(2),length=10)), |
| 58 | + ("Touching right-ϵ",range(T(1)-eps(T),stop=T(2),length=10)), |
| 59 | + ("Touching right+ϵ",range(T(1)+eps(T),stop=T(2),length=10)), |
| 60 | + |
| 61 | + ("Other right",range(T(0.5),stop=T(1),length=10)), |
| 62 | + ("Other right-ϵ",range(T(0.5)-eps(T(0.5)),stop=T(1),length=10)), |
| 63 | + ("Other right+ϵ",range(T(0.5)+eps(T(0.5)),stop=T(1),length=10)), |
| 64 | + |
| 65 | + ("Complete", range(T(0),stop=T(1),length=10)), |
| 66 | + ("Complete-ϵ", range(eps(T),stop=T(1)-eps(T),length=10)), |
| 67 | + ("Complete+ϵ", range(-eps(T),stop=T(1)+eps(T),length=10)), |
| 68 | + |
| 69 | + ("Left partial", range(T(-0.5),stop=T(0.6),length=10)), |
| 70 | + ("Left", range(T(-0.5),stop=T(1.0),length=10)), |
| 71 | + ("Right partial", range(T(0.5),stop=T(1.6),length=10)), |
| 72 | + ("Right", range(T(0),stop=T(1.6),length=10))] |
| 73 | + @testset "L=$L" for L=[:closed,:open] |
| 74 | + @testset "R=$R" for R=[:closed,:open] |
| 75 | + @testset "Reversed: $reversed" for reversed in [false, true] |
| 76 | + for (a,b) in [(T(0.0),T(0.5)),(T(0.5),T(1.0))] |
| 77 | + interval = Interval{L,R}(a, b) |
| 78 | + assert_in_interval(reversed ? reverse(x) : x, interval) |
| 79 | + end |
| 80 | + end |
| 81 | + end |
| 82 | + end |
| 83 | + end |
| 84 | + end |
| 85 | + end |
| 86 | + |
| 87 | + @testset "Large intervals" begin |
| 88 | + @test findall(in(4..Inf), 2:2:10) == 2:5 |
| 89 | + @test findall(in(4..1e20), 2:2:10) == 2:5 |
| 90 | + @test isempty(findall(in(-Inf..(-1e20)), 2:2:10)) |
| 91 | + end |
| 92 | + |
| 93 | + @testset "Reverse intervals" begin |
| 94 | + for x in [1:10, 1:3:10, 2:3:11, -1:9, -2:0.5:5] |
| 95 | + for lo in -3:4, hi in 5:13 |
| 96 | + for L in [:closed, :open], R in [:closed, :open] |
| 97 | + interval = Interval{L,R}(lo,hi) |
| 98 | + assert_in_interval(x, interval) |
| 99 | + assert_in_interval(reverse(x), interval) |
| 100 | + end |
| 101 | + end |
| 102 | + end |
| 103 | + end |
| 104 | + |
| 105 | + @testset "Arrays" begin |
| 106 | + @test findall(in(1..6), collect(0:7)) == 2:7 |
| 107 | + @test findall(in(1..6), reshape(1:16, 4, 4)) == |
| 108 | + vcat([CartesianIndex(i,1) for i = 1:4], CartesianIndex(1,2), CartesianIndex(2,2)) |
| 109 | + end |
| 110 | + |
| 111 | + @testset "Empty ranges and intervals" begin |
| 112 | + # Range empty |
| 113 | + @test isempty(findall(in(1..6), 1:0)) |
| 114 | + # Interval empty |
| 115 | + @test isempty(findall(in(Interval{:closed,:open}(1.0..1.0)), |
| 116 | + 0.0:0.02040816326530612:1.0)) |
| 117 | + end |
| 118 | + |
| 119 | + @testset "Offset arrays" begin |
| 120 | + for (x,interval) in [(OffsetArray(ones(10), -5), -1..1), |
| 121 | + (OffsetArray(1:5, -3), 2..4), |
| 122 | + (OffsetArray(5:-1:1, -5), 2..4)] |
| 123 | + assert_in_interval(x, interval) |
| 124 | + assert_in_interval(reverse(x), interval) |
| 125 | + end |
| 126 | + end |
| 127 | +end |
0 commit comments