diff --git a/Project.toml b/Project.toml index 5c0d359..b0e15ac 100644 --- a/Project.toml +++ b/Project.toml @@ -17,10 +17,11 @@ Lazy = "0.15" Reexport = "1" TestItemRunner = "0.2" TestItems = "0.1" -julia = "1.8" +julia = "1.6" [extras] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Aqua", "Test"] diff --git a/src/PatternFolds.jl b/src/PatternFolds.jl index 9e7898d..6816c8a 100644 --- a/src/PatternFolds.jl +++ b/src/PatternFolds.jl @@ -6,8 +6,9 @@ using Reexport # Import @reexport using Intervals using Lazy -using Random +# using Random using TestItems +using TestItemRunner # exports export IntervalsFold diff --git a/src/intervals.jl b/src/intervals.jl index 083e9bc..ea6b54c 100644 --- a/src/intervals.jl +++ b/src/intervals.jl @@ -4,29 +4,29 @@ Base.ndims(::Interval) = 1 function Base.rand(i::Interval{T, L, R}) where {T, L, R} - # α = max(_minfloat(T), first(i)) - # β = min(_maxfloat(T), last(i)) - μ = maxintfloat(T, Int) - α = max(-μ, first(i)) - β = min(μ, last(i)) - δ = β - α - # if δ === Inf - if δ > μ - return rand(rand() < 0.5 ? α .. zero(T) : zero(T) .. β) - else - # r = α + exp10(log10(δ) * rand()) - r = α + δ * rand() - r ∉ i && return rand(i) - return r - end + # α = max(_minfloat(T), first(i)) + # β = min(_maxfloat(T), last(i)) + μ = maxintfloat(T, Int) + α = max(-μ, first(i)) + β = min(μ, last(i)) + δ = β - α + # if δ === Inf + if δ > μ + return rand(rand() < 0.5 ? α .. zero(T) : zero(T) .. β) + else + # r = α + exp10(log10(δ) * rand()) + r = α + δ * rand() + r ∉ i && return rand(i) + return r + end end # TODO - Optimise the type of Intervals.Bound (currently abstract super type) mutable struct IntervalsFold{T <: AbstractFloat, L <: Intervals.Bound, R <: Intervals.Bound} - pattern::Interval{T, L, R} - gap::T - folds::Int - current::Int + pattern::Interval{T, L, R} + gap::T + folds::Int + current::Int end IntervalsFold(p, g, f, c = 1) = IntervalsFold(p, g, f, c) @@ -38,58 +38,58 @@ Base.lastindex(isf::IntervalsFold) = folds(isf) Base.getindex(isf::IntervalsFold, key...) = map(k -> get_fold!(isf, k), key) function pattern(isf::IntervalsFold) - distortion = gap(isf) * (isf.current - 1) - return isf.pattern + (-distortion) + distortion = gap(isf) * (isf.current - 1) + return isf.pattern + (-distortion) end function unfold(isf::IntervalsFold{T, L, R}) where {T, L, R} - reset_pattern!(isf) - x = first(pattern(isf)) - y = last(pattern(isf)) - g = gap(isf) - f = folds(isf) - return [Interval{T, L, R}(x + g * i, y + g * i) for i in 0:(f - 1)] + reset_pattern!(isf) + x = first(pattern(isf)) + y = last(pattern(isf)) + g = gap(isf) + f = folds(isf) + return [Interval{T, L, R}(x + g * i, y + g * i) for i in 0:(f - 1)] end function set_fold!(isf::IntervalsFold, new_fold = isf.current + 1) - if new_fold != isf.current && 0 < new_fold ≤ isf.folds - distortion = gap(isf) * (new_fold - isf.current) - isf.pattern += distortion - isf.current = new_fold - end + if new_fold != isf.current && 0 < new_fold ≤ isf.folds + distortion = gap(isf) * (new_fold - isf.current) + isf.pattern += distortion + isf.current = new_fold + end end function get_fold!(isf::IntervalsFold, f) - set_fold!(isf, f) - return isf.pattern + set_fold!(isf, f) + return isf.pattern end function Base.iterate(iter::IntervalsFold) - reset_pattern!(iter) - return pattern(iter), 1 + reset_pattern!(iter) + return pattern(iter), 1 end # "Induction" iterate method function Base.iterate(iter::IntervalsFold, state::Int) - state ≥ folds(iter) && return nothing - set_fold!(iter) - return iter.pattern, state + 1 + state ≥ folds(iter) && return nothing + set_fold!(iter) + return iter.pattern, state + 1 end # Reverse iterate method function Base.iterate( - r_iter::Base.Iterators.Reverse{<:IntervalsFold}, state::Int = length(r_iter.itr) + r_iter::Base.Iterators.Reverse{<:IntervalsFold}, state::Int = length(r_iter.itr) ) - state < 1 && return nothing - iter = r_iter.itr - next_state = state - 1 - set_fold!(iter, state) - return iter.pattern, next_state + state < 1 && return nothing + iter = r_iter.itr + next_state = state - 1 + set_fold!(iter, state) + return iter.pattern, next_state end function Base.in(val, isf::IntervalsFold) - reset_pattern!(isf) - return any(i -> val ∈ i, isf) + reset_pattern!(isf) + return any(i -> val ∈ i, isf) end Base.size(isf::IntervalsFold) = span(isf.pattern) * folds(isf) @@ -103,56 +103,57 @@ is_points(isf) = is_point(pattern(isf)) pattern_length(isf::IntervalsFold) = span(pattern(isf)) function Base.rand(isf::IntervalsFold) - i = rand(1:folds(isf)) - 1 - p = pattern(isf) - return rand(p) + i * gap(isf) + i = rand(1:folds(isf)) - 1 + p = pattern(isf) + return rand(p) + i * gap(isf) end """ - Base.rand(::Vector{IntervalsFold}) + Base.rand(::Vector{IntervalsFold}) + Extend the `Base.rand` function to `Vector{IntervalsFold}`. """ function Base.rand(v::V) where {V <: Set{<:IntervalsFold}} - λ = map(size, collect(v)) - Λ = sum(λ) - σ = [sum(λ[1:i]) / Λ for i in 1:length(v)] - r = rand() - for z in zip(σ, v) - r < z[1] && return rand(z[2]) - end + λ = map(size, collect(v)) + Λ = sum(λ) + σ = [sum(λ[1:i]) / Λ for i in 1:length(v)] + r = rand() + for z in zip(σ, v) + r < z[1] && return rand(z[2]) + end end @testitem "IntervalsFold" tags=[:intervals] begin - i01 = Interval{Open, Closed}(0.0, 1.0) - i23 = Interval{Open, Closed}(2.0, 3.0) - i45 = Interval{Open, Closed}(4.0, 5.0) - i67 = Interval{Open, Closed}(6.0, 7.0) - i89 = Interval{Open, Closed}(8.0, 9.0) - isf_dict = Dict([ - IntervalsFold(i01, 2.0, 5) => Dict( - :pattern => i01, - :gap => 2.0, - :folds => 5, - :length => 5, - :size => 5.0, - :unfold => [i01, i23, i45, i67, i89], - :reverse => reverse([i01, i23, i45, i67, i89]) - ) - ]) - - for (isf, results) in isf_dict - @test pattern(isf) == results[:pattern] - @test gap(isf) == results[:gap] - @test folds(isf) == results[:folds] - @test length(isf) == results[:length] - @test size(isf) == results[:size] - @test unfold(isf) == results[:unfold] - @test ndims(isf) == 1 - for i in 1:1000 - @test rand(isf) ∈ isf - end - @test collect(isf) == [i for i in isf] == unfold(isf) - @test collect(Iterators.reverse(isf)) == reverse(collect(isf)) == results[:reverse] - end - @test isempty(IntervalsFold(Interval{Open, Closed}(1.0, 1.0), 1.0, 1)) + i01 = Interval{Open, Closed}(0.0, 1.0) + i23 = Interval{Open, Closed}(2.0, 3.0) + i45 = Interval{Open, Closed}(4.0, 5.0) + i67 = Interval{Open, Closed}(6.0, 7.0) + i89 = Interval{Open, Closed}(8.0, 9.0) + isf_dict = Dict([ + IntervalsFold(i01, 2.0, 5) => Dict( + :pattern => i01, + :gap => 2.0, + :folds => 5, + :length => 5, + :size => 5.0, + :unfold => [i01, i23, i45, i67, i89], + :reverse => reverse([i01, i23, i45, i67, i89]) + ) + ]) + + for (isf, results) in isf_dict + @test pattern(isf) == results[:pattern] + @test gap(isf) == results[:gap] + @test folds(isf) == results[:folds] + @test length(isf) == results[:length] + @test size(isf) == results[:size] + @test unfold(isf) == results[:unfold] + @test ndims(isf) == 1 + for i in 1:1000 + @test rand(isf) ∈ isf + end + @test collect(isf) == [i for i in isf] == unfold(isf) + @test collect(Iterators.reverse(isf)) == reverse(collect(isf)) == results[:reverse] + end + @test isempty(IntervalsFold(Interval{Open, Closed}(1.0, 1.0), 1.0, 1)) end diff --git a/test/Aqua.jl b/test/Aqua.jl index e1d6386..3d747b7 100644 --- a/test/Aqua.jl +++ b/test/Aqua.jl @@ -1,3 +1,30 @@ -using Aqua +@testset "Aqua.jl" begin + import Aqua + import Intervals + import PatternFolds -Aqua.test_all(PatternFolds) + # TODO: Fix the broken tests and remove the `broken = true` flag + Aqua.test_all( + PatternFolds; + ambiguities = (broken = true,), + deps_compat = false, + piracies = (broken = true,) + ) + + @testset "Ambiguities: PatternFolds" begin + Aqua.test_ambiguities(PatternFolds) + end + + @testset "Piracies: PatternFolds" begin + Aqua.test_piracies(PatternFolds; + treat_as_own = [Intervals.Interval] + ) + end + + @testset "Dependencies compatibility (no extras)" begin + Aqua.test_deps_compat(PatternFolds; + check_extras = false, + ignore = [:Random] + ) + end +end diff --git a/test/Project.toml b/test/Project.toml deleted file mode 100644 index ddae804..0000000 --- a/test/Project.toml +++ /dev/null @@ -1,7 +0,0 @@ -[deps] -Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a" - -[compat] -Aqua = "0.8" \ No newline at end of file diff --git a/test/TestItemRunner.jl b/test/TestItemRunner.jl new file mode 100644 index 0000000..8e6c195 --- /dev/null +++ b/test/TestItemRunner.jl @@ -0,0 +1,3 @@ +@testset "TestItemRunner" begin + @run_package_tests +end diff --git a/test/runtests.jl b/test/runtests.jl index a80a725..1b50982 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ +using Test using TestItemRunner -using PatternFolds -include("Aqua.jl") - -@run_package_tests +@testset "Package tests: PatternFolds" begin + include("Aqua.jl") + include("TestItemRunner.jl") +end