Skip to content

Commit ef1eb7b

Browse files
mbaumanandreasnoack
authored andcommitted
Add a lazy ProductIndices type instead of creating the outer product
Both these lazy arrays are effectively generalizations of Tim's MappedArrays.jl package. Doing this generally adds a bit more difficulty in terms of element types, but that is true of the MappedArray type, too. It might be worth breaking this out into a package at some point.
1 parent 287f56d commit ef1eb7b

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/DistributedArrays.jl

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,11 @@ end
659659
# We also want to optimize setindex! with a SubDArray source, but this is hard
660660
# and only works on 0.5.
661661
if VERSION > v"0.5.0-dev+5230"
662-
# Similar to Base.indexin, but just create a logical mask
662+
# Similar to Base.indexin, but just create a logical mask. Note that this
663+
# must return a logical mask in order to support merging multiple masks
664+
# together into one linear index since we need to know how many elements to
665+
# skip at the end. In many cases range intersection would be much faster
666+
# than generating a logical mask, but that loses the endpoint information.
663667
indexin_mask(a, b::Number) = a .== b
664668
indexin_mask(a, r::Range{Int}) = [i in r for i in a]
665669
indexin_mask(a, b::AbstractArray{Int}) = indexin_mask(a, IntSet(b))
@@ -684,11 +688,12 @@ if VERSION > v"0.5.0-dev+5230"
684688
end
685689
end
686690
# The final indices are funky - they're allowed to accumulate together.
687-
# Too many masks is an easy fix -- just use the outer product to merge them:
691+
# An easy (albeit very inefficient) fix for too many masks is to use the
692+
# outer product to merge them. But we can do that lazily with a custom type:
688693
function restrict_indices(a::Tuple{Any}, b::Tuple{Any, Any, Vararg{Any}})
689-
restrict_indices(a, (map(Bool, vec(vec(b[1])*vec(b[2])')), tail(tail(b))...))
694+
(vec(a[1])[vec(ProductIndices(b, map(length, b)))],)
690695
end
691-
# But too many indices is much harder; this will require merging the indices
696+
# But too many indices is much harder; this requires merging the indices
692697
# in `a` before applying the final mask in `b`.
693698
function restrict_indices(a::Tuple{Any, Any, Vararg{Any}}, b::Tuple{Any})
694699
if length(a[1]) == 1
@@ -701,8 +706,15 @@ if VERSION > v"0.5.0-dev+5230"
701706
end
702707
end
703708

704-
immutable MergedIndices{T,N} <: AbstractArray{CartesianIndex{N}, N}
705-
indices::T
709+
immutable ProductIndices{I,N} <: AbstractArray{Bool, N}
710+
indices::I
711+
sz::NTuple{N,Int}
712+
end
713+
Base.size(P::ProductIndices) = P.sz
714+
Base.getindex{_,N}(P::ProductIndices{_,N}, I::Vararg{Int, N}) = Bool((&)(map(getindex, P.indices, I)...))
715+
716+
immutable MergedIndices{I,N} <: AbstractArray{CartesianIndex{N}, N}
717+
indices::I
706718
sz::NTuple{N,Int}
707719
end
708720
Base.size(M::MergedIndices) = M.sz

0 commit comments

Comments
 (0)