|
4 | 4 | module IteratorsMD |
5 | 5 | import .Base: eltype, length, size, first, last, in, getindex, setindex!, IndexStyle, |
6 | 6 | min, max, zero, oneunit, isless, eachindex, ndims, IteratorSize, |
7 | | - convert, show, iterate, promote_rule, to_indices, to_index |
| 7 | + convert, show, iterate, promote_rule |
8 | 8 |
|
9 | 9 | import .Base: +, -, *, (:) |
10 | 10 | import .Base: simd_outer_range, simd_inner_length, simd_index, setindex |
| 11 | + import .Base: to_indices, to_index, _to_indices1, _cutdim |
11 | 12 | using .Base: IndexLinear, IndexCartesian, AbstractCartesianIndex, fill_to_length, tail, |
12 | | - ReshapedArray, ReshapedArrayLF, OneTo |
| 13 | + ReshapedArray, ReshapedArrayLF, OneTo, Fix1 |
13 | 14 | using .Base.Iterators: Reverse, PartitionIterator |
14 | 15 | using .Base: @propagate_inbounds |
15 | 16 |
|
@@ -75,13 +76,9 @@ module IteratorsMD |
75 | 76 | CartesianIndex{N}() where {N} = CartesianIndex{N}(()) |
76 | 77 | # Un-nest passed CartesianIndexes |
77 | 78 | CartesianIndex(index::Union{Integer, CartesianIndex}...) = CartesianIndex(flatten(index)) |
78 | | - flatten(I::Tuple{}) = I |
79 | | - flatten(I::Tuple{Any}) = I |
80 | | - flatten(I::Tuple{<:CartesianIndex}) = I[1].I |
81 | | - @inline flatten(I) = _flatten(I...) |
82 | | - @inline _flatten() = () |
83 | | - @inline _flatten(i, I...) = (i, _flatten(I...)...) |
84 | | - @inline _flatten(i::CartesianIndex, I...) = (i.I..., _flatten(I...)...) |
| 79 | + flatten(::Tuple{}) = () |
| 80 | + flatten(I::Tuple{Any}) = Tuple(I[1]) |
| 81 | + @inline flatten(I::Tuple) = (Tuple(I[1])..., flatten(tail(I))...) |
85 | 82 | CartesianIndex(index::Tuple{Vararg{Union{Integer, CartesianIndex}}}) = CartesianIndex(index...) |
86 | 83 | show(io::IO, i::CartesianIndex) = (print(io, "CartesianIndex"); show(io, i.I)) |
87 | 84 |
|
@@ -457,13 +454,11 @@ module IteratorsMD |
457 | 454 | last(iter::CartesianIndices) = CartesianIndex(map(last, iter.indices)) |
458 | 455 |
|
459 | 456 | # When used as indices themselves, CartesianIndices can simply become its tuple of ranges |
460 | | - @inline function to_indices(A, inds, I::Tuple{CartesianIndices{N}, Vararg{Any}}) where N |
461 | | - _, indstail = split(inds, Val(N)) |
462 | | - (map(i -> to_index(A, i), I[1].indices)..., to_indices(A, indstail, tail(I))...) |
463 | | - end |
| 457 | + _to_indices1(A, inds, I1::CartesianIndices) = map(Fix1(to_index, A), I1.indices) |
| 458 | + _cutdim(inds::Tuple, I1::CartesianIndices) = split(inds, Val(ndims(I1)))[2] |
| 459 | + |
464 | 460 | # but preserve CartesianIndices{0} as they consume a dimension. |
465 | | - @inline to_indices(A, inds, I::Tuple{CartesianIndices{0},Vararg{Any}}) = |
466 | | - (first(I), to_indices(A, inds, tail(I))...) |
| 461 | + _to_indices1(A, inds, I1::CartesianIndices{0}) = (I1,) |
467 | 462 |
|
468 | 463 | @inline in(i::CartesianIndex, r::CartesianIndices) = false |
469 | 464 | @inline in(i::CartesianIndex{N}, r::CartesianIndices{N}) where {N} = all(map(in, i.I, r.indices)) |
@@ -835,33 +830,23 @@ ensure_indexable(I::Tuple{}) = () |
835 | 830 | @inline to_indices(A, I::Tuple{Vararg{Union{Integer, CartesianIndex}}}) = to_indices(A, (), I) |
836 | 831 | # But some index types require more context spanning multiple indices |
837 | 832 | # CartesianIndex is unfolded outside the inner to_indices for better inference |
838 | | -@inline function to_indices(A, inds, I::Tuple{CartesianIndex{N}, Vararg{Any}}) where N |
839 | | - _, indstail = IteratorsMD.split(inds, Val(N)) |
840 | | - (map(i -> to_index(A, i), I[1].I)..., to_indices(A, indstail, tail(I))...) |
841 | | -end |
| 833 | +_to_indices1(A, inds, I1::CartesianIndex) = map(Fix1(to_index, A), I1.I) |
| 834 | +_cutdim(inds, I1::CartesianIndex) = IteratorsMD.split(inds, Val(length(I1)))[2] |
842 | 835 | # For arrays of CartesianIndex, we just skip the appropriate number of inds |
843 | | -@inline function to_indices(A, inds, I::Tuple{AbstractArray{CartesianIndex{N}}, Vararg{Any}}) where N |
844 | | - _, indstail = IteratorsMD.split(inds, Val(N)) |
845 | | - (to_index(A, I[1]), to_indices(A, indstail, tail(I))...) |
846 | | -end |
| 836 | +_cutdim(inds, I1::AbstractArray{CartesianIndex{N}}) where {N} = IteratorsMD.split(inds, Val(N))[2] |
847 | 837 | # And boolean arrays behave similarly; they also skip their number of dimensions |
848 | | -@inline function to_indices(A, inds, I::Tuple{AbstractArray{Bool, N}, Vararg{Any}}) where N |
849 | | - _, indstail = IteratorsMD.split(inds, Val(N)) |
850 | | - (to_index(A, I[1]), to_indices(A, indstail, tail(I))...) |
851 | | -end |
| 838 | +_cutdim(inds::Tuple, I1::AbstractArray{Bool}) = IteratorsMD.split(inds, Val(ndims(I1)))[2] |
852 | 839 | # As an optimization, we allow trailing Array{Bool} and BitArray to be linear over trailing dimensions |
853 | 840 | @inline to_indices(A, inds, I::Tuple{Union{Array{Bool,N}, BitArray{N}}}) where {N} = |
854 | 841 | (_maybe_linear_logical_index(IndexStyle(A), A, I[1]),) |
855 | 842 | _maybe_linear_logical_index(::IndexStyle, A, i) = to_index(A, i) |
856 | 843 | _maybe_linear_logical_index(::IndexLinear, A, i) = LogicalIndex{Int}(i) |
857 | 844 |
|
858 | 845 | # Colons get converted to slices by `uncolon` |
859 | | -@inline to_indices(A, inds, I::Tuple{Colon, Vararg{Any}}) = |
860 | | - (uncolon(inds, I), to_indices(A, _maybetail(inds), tail(I))...) |
| 846 | +_to_indices1(A, inds, I1::Colon) = (uncolon(inds),) |
861 | 847 |
|
862 | | -const CI0 = Union{CartesianIndex{0}, AbstractArray{CartesianIndex{0}}} |
863 | | -uncolon(inds::Tuple{}, I::Tuple{Colon, Vararg{Any}}) = Slice(OneTo(1)) |
864 | | -uncolon(inds::Tuple, I::Tuple{Colon, Vararg{Any}}) = Slice(inds[1]) |
| 848 | +uncolon(::Tuple{}) = Slice(OneTo(1)) |
| 849 | +uncolon(inds::Tuple) = Slice(inds[1]) |
865 | 850 |
|
866 | 851 | ### From abstractarray.jl: Internal multidimensional indexing definitions ### |
867 | 852 | getindex(x::Union{Number,AbstractChar}, ::CartesianIndex{0}) = x |
|
0 commit comments