Skip to content

Commit 1256ff4

Browse files
committed
drop support of view(ReshapedArrayLF)
revert changes in reshapedarray.jl use Iterators.rest Update broadcast.jl move `@inbounds` outside the loop body. see JuliaLang#38086
1 parent eb5e05e commit 1256ff4

File tree

3 files changed

+46
-32
lines changed

3 files changed

+46
-32
lines changed

base/broadcast.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -973,14 +973,14 @@ end
973973
destc = dest.chunks
974974
cind = 1
975975
bc′ = preprocess(dest, bc)
976-
for P in Iterators.partition(eachindex(bc′), bitcache_size)
976+
@inbounds for P in Iterators.partition(eachindex(bc′), bitcache_size)
977977
ind = 1
978978
@simd for I in P
979-
@inbounds tmp[ind] = bc′[I]
979+
tmp[ind] = bc′[I]
980980
ind += 1
981981
end
982982
@simd for i in ind:bitcache_size
983-
@inbounds tmp[i] = false
983+
tmp[i] = false
984984
end
985985
dumpbitcache(destc, cind, tmp)
986986
cind += bitcache_chunks

base/multidimensional.jl

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ module IteratorsMD
591591
CartesianIndices(intersect.(a.indices, b.indices))
592592

593593
# Views of reshaped CartesianIndices are used for partitions — ensure these are fast
594-
const CartesianPartition{T<:CartesianIndex, P<:CartesianIndices, R<:ReshapedArray{T,1,P}} = SubArray{T,1,R,Tuple{UnitRange{Int}},false}
594+
const CartesianPartition{T<:CartesianIndex, P<:CartesianIndices, R<:ReshapedArray{T,1,P}} = SubArray{T,1,R,<:Tuple{AbstractUnitRange{Int}},false}
595595
eltype(::Type{PartitionIterator{T}}) where {T<:ReshapedArrayLF} = SubArray{eltype(T), 1, T, Tuple{UnitRange{Int}}, true}
596596
eltype(::Type{PartitionIterator{T}}) where {T<:ReshapedArray} = SubArray{eltype(T), 1, T, Tuple{UnitRange{Int}}, false}
597597
Iterators.IteratorEltype(::Type{<:PartitionIterator{T}}) where {T<:ReshapedArray} = Iterators.IteratorEltype(T)
@@ -600,7 +600,6 @@ module IteratorsMD
600600
eltype(::Type{PartitionIterator{T}}) where {T<:Union{UnitRange, StepRange, StepRangeLen, LinRange}} = T
601601
Iterators.IteratorEltype(::Type{<:PartitionIterator{T}}) where {T<:Union{OneTo, UnitRange, StepRange, StepRangeLen, LinRange}} = Iterators.IteratorEltype(T)
602602

603-
604603
@inline function iterate(iter::CartesianPartition)
605604
isempty(iter) && return nothing
606605
f = first(iter)
@@ -616,33 +615,45 @@ module IteratorsMD
616615
# In general, the Cartesian Partition might start and stop in the middle of the outer
617616
# dimensions — thus the outer range of a CartesianPartition is itself a
618617
# CartesianPartition.
619-
t = tail(iter.parent.parent.indices)
620-
ci = CartesianIndices(t)
621-
li = LinearIndices(t)
622-
return @inbounds view(ci, li[tail(iter[1].I)...]:li[tail(iter[end].I)...])
618+
mi = iter.parent.mi
619+
ci = iter.parent.parent
620+
ax, ax1 = axes(ci), Base.axes1(ci)
621+
subs = Base.ind2sub_rs(ax, mi, first(iter.indices[1]))
622+
vl, fl = Base._sub2ind(tail(ax), tail(subs)...), subs[1]
623+
vr, fr = divrem(last(iter.indices[1]) - 1, mi[end]) .+ (1, first(ax1))
624+
oci = CartesianIndices(tail(ci.indices))
625+
# A fake CartesianPartition to reuse the outer iterate fallback
626+
outer = @inbounds view(ReshapedArray(oci, (length(oci),), mi), vl:vr)
627+
init = @inbounds dec(oci[tail(subs)...].I, oci.indices) # real init state
628+
# Use Generator to make inner loop branchless
629+
@inline function skip_len_I(i::Int, I::CartesianIndex)
630+
l = i == 1 ? fl : first(ax1)
631+
r = i == length(outer) ? fr : last(ax1)
632+
l - first(ax1), r - l + 1, I
633+
end
634+
(skip_len_I(i, I) for (i, I) in Iterators.enumerate(Iterators.rest(outer, (init, 0))))
623635
end
624-
function simd_outer_range(iter::CartesianPartition{CartesianIndex{2}})
636+
@inline function simd_outer_range(iter::CartesianPartition{CartesianIndex{2}})
625637
# But for two-dimensional Partitions the above is just a simple one-dimensional range
626638
# over the second dimension; we don't need to worry about non-rectangular staggers in
627639
# higher dimensions.
628-
return @inbounds CartesianIndices((iter[1][2]:iter[end][2],))
629-
end
630-
@inline function simd_inner_length(iter::CartesianPartition, I::CartesianIndex)
631-
inner = iter.parent.parent.indices[1]
632-
@inbounds fi = iter[1].I
633-
@inbounds li = iter[end].I
634-
inner_start = I.I == tail(fi) ? fi[1] : first(inner)
635-
inner_end = I.I == tail(li) ? li[1] : last(inner)
636-
return inner_end - inner_start + 1
637-
end
638-
@inline function simd_index(iter::CartesianPartition, Ilast::CartesianIndex, I1::Int)
639-
# I1 is the 0-based distance from the first dimension's offest
640-
offset = first(iter.parent.parent.indices[1]) # (this is 1 for 1-based arrays)
641-
# In the first column we need to also add in the iter's starting point (branchlessly)
642-
f = @inbounds iter[1]
643-
startoffset = (Ilast.I == tail(f.I))*(f[1] - 1)
644-
CartesianIndex((I1 + offset + startoffset, Ilast.I...))
640+
mi = iter.parent.mi
641+
ci = iter.parent.parent
642+
ax, ax1 = axes(ci), Base.axes1(ci)
643+
fl, vl = Base.ind2sub_rs(ax, mi, first(iter.indices[1]))
644+
fr, vr = Base.ind2sub_rs(ax, mi, last(iter.indices[1]))
645+
outer = @inbounds CartesianIndices((ci.indices[2][vl:vr],))
646+
# Use Generator to make inner loop branchless
647+
@inline function skip_len_I(I::CartesianIndex{1})
648+
l = I == first(outer) ? fl : first(ax1)
649+
r = I == last(outer) ? fr : last(ax1)
650+
l - first(ax1), r - l + 1, I
651+
end
652+
(skip_len_I(I) for I in outer)
645653
end
654+
@inline simd_inner_length(iter::CartesianPartition, (_, len, _)::Tuple{Int,Int,CartesianIndex}) = len
655+
@propagate_inbounds simd_index(iter::CartesianPartition, (skip, _, I)::Tuple{Int,Int,CartesianIndex}, n::Int) =
656+
simd_index(iter.parent.parent, I, n + skip)
646657
end # IteratorsMD
647658

648659

test/iterators.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -550,12 +550,15 @@ end
550550
(1,1), (8,8), (11, 13),
551551
(1,1,1), (8, 4, 2), (11, 13, 17)),
552552
part in (1, 7, 8, 11, 63, 64, 65, 142, 143, 144)
553-
P = partition(CartesianIndices(dims), part)
554-
for I in P
555-
@test length(I) == iterate_length(I) == simd_iterate_length(I) == simd_trip_count(I)
556-
@test collect(I) == iterate_elements(I) == simd_iterate_elements(I) == index_elements(I)
553+
for fun in (i -> 1:i, i -> 1:2:2i, i -> Base.IdentityUnitRange(-i:i))
554+
iter = CartesianIndices(map(fun, dims))
555+
P = partition(iter, part)
556+
for I in P
557+
@test length(I) == iterate_length(I) == simd_iterate_length(I) == simd_trip_count(I)
558+
@test collect(I) == iterate_elements(I) == simd_iterate_elements(I) == index_elements(I)
559+
end
560+
@test all(Base.splat(==), zip(Iterators.flatten(map(collect, P)), iter))
557561
end
558-
@test all(Base.splat(==), zip(Iterators.flatten(map(collect, P)), CartesianIndices(dims)))
559562
end
560563
@testset "empty/invalid partitions" begin
561564
@test_throws ArgumentError partition(1:10, 0)

0 commit comments

Comments
 (0)