diff --git a/src/Batches/batch.jl b/src/Batches/batch.jl index 10958516..4f0077d1 100644 --- a/src/Batches/batch.jl +++ b/src/Batches/batch.jl @@ -1,9 +1,11 @@ # Batches -struct Batch{T,S} <: BatchLike{T,S} +struct Batch{T,S} <: Batchable{T,S} data::Storage{T,S} end +storage(b::Batch) = b.data + Batch(xs) = Batch(Storage(xs)) convertel(T::Type, xs::Batch) = @@ -18,8 +20,10 @@ tobatch(xs) = tobatch(batchone(xs)) # Sequences -struct Seq{T,S} <: BatchLike{T,S} +struct Seq{T,S} <: Batchable{T,S} data::Storage{T,S} end +storage(s::Seq) = s.data + Seq(xs) = Seq(Storage(xs)) diff --git a/src/Batches/catmat.jl b/src/Batches/catmat.jl index 43651e84..e91e9b75 100644 --- a/src/Batches/catmat.jl +++ b/src/Batches/catmat.jl @@ -1,42 +1,10 @@ import Base: eltype, size, getindex, setindex!, convert, typename -rawbatch(xs) = xs - -# Generic methods - -abstract type BatchLike{T,S} <: AbstractVector{T} -end - -eltype{T}(::BatchLike{T}) = T - -rawbatch(xs::BatchLike) = rawbatch(xs.data) - -size(b::BatchLike) = (size(rawbatch(b), 1),) - -getindex(b::BatchLike, i)::eltype(b) = slicedim(rawbatch(b), 1, i) - -setindex!(b::BatchLike, v, i::Integer) = rawbatch(b)[i, :] = v - -function setindex!(b::BatchLike, xs, ::Colon) - for (i, x) in enumerate(xs) - b[i] = x - end -end - -typerender(B::Type) = B -typerender(B::Type{<:BatchLike}) = - Row(Juno.typ("$(typename(B).name)"), text"{", typerender(eltype(B)), text"}") - -@render Juno.Inline b::BatchLike begin - Tree(Row(typerender(typeof(b)), - Juno.fade("[$(length(b))]")), - Juno.trim(collect(b))) -end - # Concrete storage -struct Storage{T,S} <: BatchLike{T,S} +struct Storage{T,S} data::S + Storage{T,S}(data::S) where {T,S} = new{T,S}(data) end allequal(xs) = all(x -> x == first(xs), xs) @@ -50,28 +18,79 @@ function Storage{T,S}(xs, storage::S) where {T, S} return Storage{T,S}(storage) end -function Storage{T}(xs) where T +function Storage{T,S}(xs) where {T,S} xs′ = map(rawbatch, xs) - storage = similar(first(xs′), (length(xs′), size(first(xs′))...)) + storage = S(length(xs′), size(first(xs′))...) Storage{T,typeof(storage)}(xs′, storage) end +Storage{T}(xs) where T = Storage{T,diminc(typeof(rawbatch(first(xs))))}(xs) + Storage(xs) = Storage{eltype(xs)}(xs) -convert{T,S}(B::Type{<:BatchLike{T,S}}, data::S) = B(data) +convert{T,S}(::Type{Storage{T,S}}, data::S) = Storage{T,S}(data) + +convert{T}(::Type{Storage{T}}, data::AbstractArray) = convert(Storage{T,typeof(data)}, data) + +# Storage utility methods + +rawbatch(xs) = xs +rawbatch(xs::Storage) = xs.data + +eltype{T}(::Storage{T}) = T + +size(b::Storage) = (size(b.data, 1),) + +getindex(b::Storage, i)::eltype(b) = slicedim(b.data, 1, i) + +setindex!(b::Storage, v, i::Integer) = b.data[i, :] = v + +function setindex!(b::Storage, xs, ::Colon) + for (i, x) in enumerate(xs) + b[i] = x + end +end + +# Generic methods + +abstract type Batchable{T,S} <: AbstractVector{T} +end + +rawbatch(xs::Batchable) = rawbatch(storage(xs)) +size(xs::Batchable) = size(storage(xs)) +getindex(xs::Batchable, i) = getindex(storage(xs), i) + +typerender(B::Type) = B +typerender(B::Type{<:Batchable}) = + Row(Juno.typ("$(typename(B).name)"), text"{", typerender(eltype(B)), text"}") + +@render Juno.Inline b::Batchable begin + Tree(Row(typerender(typeof(b)), + Juno.fade("[$(length(b))]")), + Juno.trim(collect(b))) +end # Horrible type hacks follow this point deparam(T::Type) = typename(T).wrapper -dimless(T::Type{<:AbstractArray}) = ndims(T) == 1 ? eltype(T) : deparam(T){eltype(T),ndims(T)-1} +diminc(T::Type) = Vector{T} +diminc(T::Type{<:AbstractArray}) = deparam(T){eltype(T),ndims(T)+1} -btype(B::Type{<:BatchLike}, S::Type{<:AbstractArray}) = B{dimless(S),S} -btype(B::Type{<:BatchLike{T}} where T, S::Type{<:AbstractArray}) = B{S} -btype(B::Type{<:BatchLike{<:BatchLike}}, S::Type{<:AbstractArray}) = - deparam(B){btype(eltype(B), dimless(S)),S} +dimdec{T}(::Type{<:AbstractArray{T,1}}) = T +dimdec(T::Type{<:AbstractArray}) = deparam(T){eltype(T),ndims(T)-1} -convert{T<:BatchLike}(::Type{T}, xs::AbstractArray) = - convert(btype(T, typeof(xs)), xs) +btype(B::Type, S::Type{<:AbstractArray}) = B +btype(B::Type{<:Batchable}, S::Type{<:AbstractArray}) = B{dimdec(S),S} +btype(B::Type{<:Batchable{T}} where T, S::Type{<:AbstractArray}) = B{S} +btype(B::Type{<:Batchable{<:Batchable}}, S::Type{<:AbstractArray}) = + deparam(B){btype(eltype(B), dimdec(S)),S} -convert{T<:BatchLike}(::Type{T}, x::T) = x +convert{T<:Batchable}(::Type{Storage{T}}, data::AbstractArray) = + Storage{btype(T,dimdec(typeof(data))),typeof(data)}(data) + +convert{T,S<:AbstractArray}(B::Type{<:Batchable{T,S}}, data::S) = B(convert(Storage{T,S}, data)) + +convert{B<:Batchable}(::Type{B}, data::AbstractArray) = convert(btype(B,typeof(data)), data) + +convert{B<:Batchable}(::Type{B}, xs::B) = xs