Skip to content

mcabbott/StarSlice.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

StarSlice.jl

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.

See also

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

About

🥒

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages