diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index fc1526b..6a79e34 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: version: - - "^1.6.0-0" + - "^1.7.0-0" - 'nightly' os: - ubuntu-latest diff --git a/Project.toml b/Project.toml index 722e0f6..c41fce8 100644 --- a/Project.toml +++ b/Project.toml @@ -8,7 +8,7 @@ Lazy = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0" [compat] Lazy = "0.15" -julia = "1.6" +julia = "1.7" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/PatternFolds.jl b/src/PatternFolds.jl index 1c8bbbb..c0af992 100644 --- a/src/PatternFolds.jl +++ b/src/PatternFolds.jl @@ -4,19 +4,31 @@ module PatternFolds using Lazy # exports -export PatternFold -export IVectorFold, VectorFold -export Interval, IntervalsFold -export pattern, gap, folds, check_pattern +export Interval +export IntervalsFold +export IVectorFold +export VectorFold + +export a_isless +export a_ismore +export b_isless +export b_ismore +export check_pattern +export closed +export fold +export folds +export gap export length -export fold, unfold -export value, closed, opened -export a_isless, b_isless, a_ismore, b_ismore +export make_vector_fold +export opened +export pattern +export unfold +export value # includes +include("intervals.jl") include("common.jl") include("immutable_vector.jl") include("vector.jl") -include("intervals.jl") end diff --git a/src/common.jl b/src/common.jl index e78d3fc..01c5b07 100644 --- a/src/common.jl +++ b/src/common.jl @@ -1,12 +1,26 @@ """ - PatternFold{T, P} -An abstract stype used as an interface for folded patterns such as `VectorFold`. + AbstractVectorFold{T, P} +An abstract type used as an interface for folded vectors such as `VectorFold`. To implement the interface and inherit from it, a new structure must define three fields: - `pattern::P`. Note that both `length(::P)` and `rand(::P)` methods must be available - `gap::T` - `folds::int` """ -abstract type PatternFold{T, P} end +abstract type AbstractVectorFold{T} <: AbstractVector{T} end + +""" + PatternFold{T, P} +A `Union` type used as an interface for folded patterns such as `VectorFold`. +To implement the interface and inherit from it, a new structure `MyFold{T[,P]}` must define three fields: +- `pattern::P`. Note that both `length(::P)` and `rand(::P)` methods must be available +- `gap::T`S +- `folds::int` +Finally one can redefine PatternFold{T} +```julia +PatternFold{T} = Union{AbstractVectorFold{T}, IntervalsFold{T}, MyFold{T[,P]}} +``` +""" +PatternFold{T} = Union{AbstractVectorFold{T}, IntervalsFold{T}} """ pattern(<:PatternFold) @@ -29,7 +43,6 @@ folds(pf) = pf.folds # Forwards isempty, ndims @forward PatternFold.pattern Base.isempty, Base.ndims -# TODO - look if another name is more appropriate """ pattern_length(pf<:PatternFold) Return the length of the basic pattern of `pf`. @@ -41,11 +54,12 @@ pattern_length(pf) = length(pattern(pf)) Return the length of `pf` if unfolded. """ Base.length(pf::PatternFold) = pattern_length(pf) * folds(pf) +Base.size(pf::PatternFold) = (length(pf),) """ eltype(pf<: PatternFolds) """ -Base.eltype(::Type{<:PatternFold{T,P}}) where {T,P} = T +Base.eltype(::Type{<:PatternFold{T}}) where {T} = T """ rand(pf<:PatternFold) @@ -83,6 +97,14 @@ function fold(v::V, depth = 0; kind = :mutable) where {T <: Real, V <: AbstractV end end +""" + make_vector_fold(pattern, gap, fold, kind = :mutable) +A dispatcher to construct a folded vector. The `kind` of vector can be set to either `:mutable` (default) or `:immutable`. The default is faster in most cases but it depends on the `pattern`, `gap`, and `fold` parameters. For critical code, it is recommended to benchmark both options. +""" function make_vector_fold(pattern, gap, fold, kind = :mutable) return make_vector_fold(pattern, gap, fold, Val(kind)) end + +function Base.print_array(io::IO, X::AbstractVectorFold) + print(io, "\tPattern: $(pattern(X))\n\tGap: $(gap(X))\n\tFolds: $(folds(X))") +end diff --git a/src/immutable_vector.jl b/src/immutable_vector.jl index c96ce49..2774519 100644 --- a/src/immutable_vector.jl +++ b/src/immutable_vector.jl @@ -2,7 +2,7 @@ VectorFold{T,V <: AbstractVector{T}} A folded vector structure that extends the methods of AbstractVector to a folded structure. """ -struct IVectorFold{T,V <: AbstractVector{T}} <: PatternFold{T,V} +struct IVectorFold{T,V <: AbstractVector{T}} <: AbstractVectorFold{T} pattern::V gap::T folds::Int diff --git a/src/intervals.jl b/src/intervals.jl index a857ae1..ad028cf 100644 --- a/src/intervals.jl +++ b/src/intervals.jl @@ -52,7 +52,7 @@ Base.isempty(i::Interval) = size(i) == 0 && (opened(i, :a) || opened(i, :b)) Base.ndims(::Interval) = 1 Base.rand(i::Interval) = rand() * size(i) + value(i, :a) -mutable struct IntervalsFold{T <: Real} <: PatternFold{T, Interval{T}} +mutable struct IntervalsFold{T <: Real} #<: PatternFold{T, Interval{T}} pattern::Interval{T} gap::T folds::Int diff --git a/src/vector.jl b/src/vector.jl index 9dd563d..291746f 100644 --- a/src/vector.jl +++ b/src/vector.jl @@ -1,9 +1,9 @@ """ - MVectorFold{T,V <: AbstractVector{T}} -A mutable structure for folded vector that extends the methods of AbstractVector. Compared to `VectorFold`, this tructure is about 20% faster using iterators. Unfolding is twice slower though. -Note that this structure keep an active pointer to the `current` *unfolded* pattern. However, its external behavior is similar to `VectorFold`. + VectorFold{T,V <: AbstractVector{T}} +A mutable structure for folded vector that extends the methods of AbstractVector. Compared to `IVectorFold`, this tructure is about 20% faster using iterators. +Note that this structure keep an active pointer to the `current` *unfolded* pattern. However, its external behavior is similar to `IVectorFold`. """ -mutable struct VectorFold{T,V <: AbstractVector{T}} <: PatternFold{T,V} +mutable struct VectorFold{T,V <: AbstractVector{T}} <: AbstractVectorFold{T} pattern::V gap::T folds::Int @@ -22,7 +22,7 @@ end pattern(mvf::VectorFold, index) = pattern(mvf)[index] """ - set_fold!(mvf::MVectorFold, new_fold = mvf.current + 1) + set_fold!(mvf::VectorFold, new_fold = mvf.current + 1) Set the *unfolded* pattern to `new_fold`. By default move the next *fold* after `current`. """ function set_fold!(mvf, new_fold = mvf.current + 1) diff --git a/test/vector.jl b/test/vector.jl index 6a3991a..461c96e 100644 --- a/test/vector.jl +++ b/test/vector.jl @@ -1,6 +1,6 @@ @testset "VectorFold" begin vf_dict = Dict([ - IVectorFold([1,2], 10, 5) => Dict( + make_vector_fold([1,2], 10, 5, :immutable) => Dict( :pattern => [1,2], :gap => 10, :folds => 5, @@ -8,7 +8,7 @@ :unfold => [1,2,11,12,21,22,31,32,41,42], :reverse => reverse([1,2,11,12,21,22,31,32,41,42]), ), - VectorFold([1,2], 10, 5) => Dict( + make_vector_fold([1,2], 10, 5, :mutable) => Dict( :pattern => [1,2], :gap => 10, :folds => 5, @@ -29,16 +29,16 @@ @test collect(vf) == [i for i in vf] == unfold(vf) @test collect(Iterators.reverse(vf)) == reverse(collect(vf)) == results[:reverse] end - @test isempty(IVectorFold(Vector(),1,1)) - @test isempty(VectorFold(Vector(),1,1)) + @test isempty(make_vector_fold(Vector(),1,1,:immutable)) + @test isempty(make_vector_fold(Vector(),1,1)) - v1 = VectorFold([42,3,45,6],13,4) + v1 = make_vector_fold([42,3,45,6],13,4) w1 = unfold(v1) v11 = fold(w1) @test unfold(v11) == w1 - v2 = VectorFold([34,34,43,43],10,3) + v2 = make_vector_fold([34,34,43,43],10,3) w2 = unfold(v2) v22 = fold(w2)