This package overloads getindex
and friends to make slices.
Inserting *
means that a given index will label the position in the outer container.
view
makes views, and eachslice
makes a generator:
julia> ones(Int, 2,3,4)[:, *, 4]
3-element Array{Array{Int64,1},1}:
[1, 1]
[1, 1]
[1, 1]
julia> @view ones(Int, 2,3)[*, :]
2-element Array{SubArray{Int64,1,Array{Int64,2},Tuple{Int64,Base.Slice{Base.OneTo{Int64}}},true},1}:
[1, 1, 1]
[1, 1, 1]
julia> eachslice(ones(Int, 2,3,4,5), *, :, 4, *) |> typeof
Base.Generator{Base.Iterators.ProductIterator{Tuple{Base.OneTo{Int64},Base.RefValue{Colon},
Base.RefValue{Int64},Base.OneTo{Int64}}},StarSlice.var"#75#76"{Array{Int64,4}}}
While dimensions marked *
belong only to the outer container,
and those marked :
belong only to the inner array,
those marked &
or !
belong to both,
surviving as trivial dimensions of either the slices, or the container.
julia> ones(Int, 2,3,4)[!, *, 4] # with `!` in place of `:`, outer array keeps 1st dimension
1×3 Array{Array{Int64,1},2}:
[1, 1] [1, 1] [1, 1]
julia> ones(Int, 2,3,4)[:, &, 4] # with `&` in place of `*`, inner arrays keep 2nd dimension
3-element Array{Array{Int64,2},1}:
[1; 1]
[1; 1]
[1; 1]
julia> size(first(ans))
(2, 1)
One use of this is for mapslices
-like operations. It goes well with LazyStack.jl:
julia> using StarSlice, LazyStack
julia> info(x) = [ndims(x), size(x)...]
info (generic function with 1 method)
julia> mapslices(info, rand(10,20,30), dims=(1,3))
3×20×1 Array{Int64,3}:
[:, :, 1] =
2 2 2 2 2 2 2 2 … 2 2 2 2 2 2 2
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
julia> stack(info, @view rand(10,20,30)[:,*,:])
3×20 Array{Int64,2}:
2 2 2 2 2 2 2 2 … 2 2 2 2 2 2 2
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
Another is to explore reductions...
mat = rand(1:99, 3, 4)
prod.(mat[!,*]) == prod(mat, dims=1)
prod.(mat[:,*]) == dropdims(prod(mat, dims=1), dims=1)
sum(mat[:,&]) == sum(mat, dims=2) # but this won't work for prod
sum(mat[:,*]) == dropdims(sum(mat, dims=2), dims=2)
Right now the eachslice
generator returns an Array
not a view, and re-uses the same one. But this appears to provide few benefits.
-
SliceMap.jl, differentiable mapslices.
-
JuliaLang/julia#32310 about
EachSlice
type -
tkf/ReduceDims.jl from JuliaLang/julia#16606. Compare:
using ReduceDims, StarSlice
mat = rand(1:99, 3, 4)
s1 = sum(along(mat, &, :)) # lazy mapreduce along "&" directions
sum(mat, dims=1) .== s1 # all equal
sum(mat[&, :]) == sum.(mat[:, &]) == copy(s1)
p1 = prod(along(mat, &, :)) |> copy
prod(mat, dims=1) == p1
prod.(mat[:, *]) == vec(p1) # and prod(mat[*, :]) is an error