Skip to content

Commit 701885b

Browse files
authored
fix #37199, indexing for 1-d views with offset ranges (#37204)
We had been assuming that IdentityUnitRange matched the indices of the parent (like Slices) but they define their own offset axes. Further, other `AbstractRanges` may be similarly offset. We do not need to consider other offset `AbstractArrays` as this code only applies to `IndexLinear` `SubArray`s.
1 parent 0ae8f95 commit 701885b

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

base/subarray.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -366,17 +366,20 @@ end
366366
# The running sum is `f`; the cumulative stride product is `s`.
367367
# If the parent is a vector, then we offset the parent's own indices with parameters of I
368368
compute_offset1(parent::AbstractVector, stride1::Integer, I::Tuple{AbstractRange}) =
369-
(@_inline_meta; first(I[1]) - first(axes1(I[1]))*stride1)
369+
(@_inline_meta; first(I[1]) - stride1*first(axes1(I[1])))
370370
# If the result is one-dimensional and it's a Colon, then linear
371-
# indexing uses the indices along the given dimension. Otherwise
372-
# linear indexing always starts with 1.
371+
# indexing uses the indices along the given dimension.
372+
# If the result is one-dimensional and it's a range, then linear
373+
# indexing might be offset if the index itself is offset
374+
# Otherwise linear indexing always starts with 1.
373375
compute_offset1(parent, stride1::Integer, I::Tuple) =
374376
(@_inline_meta; compute_offset1(parent, stride1, find_extended_dims(1, I...), find_extended_inds(I...), I))
375-
compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{Union{Slice, IdentityUnitRange}}, I::Tuple) =
377+
compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{Slice}, I::Tuple) =
376378
(@_inline_meta; compute_linindex(parent, I) - stride1*first(axes(parent, dims[1]))) # index-preserving case
379+
compute_offset1(parent, stride1::Integer, dims, inds::Tuple{AbstractRange}, I::Tuple) =
380+
(@_inline_meta; compute_linindex(parent, I) - stride1*first(axes1(inds[1]))) # potentially index-offsetting case
377381
compute_offset1(parent, stride1::Integer, dims, inds, I::Tuple) =
378382
(@_inline_meta; compute_linindex(parent, I) - stride1) # linear indexing starts with 1
379-
380383
function compute_linindex(parent, I::NTuple{N,Any}) where N
381384
@_inline_meta
382385
IP = fill_to_length(axes(parent), OneTo(1), Val(N))

test/subarray.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,33 @@ end
656656
@test _test_27632(view(ones(Int64, (1, 1, 1)), 1, 1, 1)) === nothing
657657
end
658658

659+
@testset "issue #37199: 1-d views with offset range indices" begin
660+
b = zeros(6, 3)
661+
b[Base.IdentityUnitRange(4:6), 2] .= 3
662+
@test b == [zeros(6, 1) [0,0,0,3,3,3] zeros(6,1)]
663+
b[4, Base.IdentityUnitRange(2:3)] .= 4
664+
@test b == [zeros(6,1) [0,0,0,4,3,3] [0,0,0,4,0,0]]
665+
b[Base.IdentityUnitRange(2:3), :] .= 5
666+
@test b == [zeros(1, 3); fill(5, 2, 3); [zeros(3) [4,3,3] [4,0,0]]]
667+
b[:, Base.IdentityUnitRange(3:3)] .= 6
668+
@test b == [[zeros(1, 2); fill(5, 2, 2); [zeros(3) [4,3,3]]] fill(6, 6)]
669+
670+
A = reshape(1:5*7*11, 11, 7, 5)
671+
inds = (1:4, 2:5, 2, :, fill(3))
672+
offset(x) = x
673+
offset(r::UnitRange) = Base.IdentityUnitRange(r)
674+
for i1 in inds
675+
for i2 in inds
676+
for i3 in inds
677+
vo = @view A[offset(i1), offset(i2), offset(i3)]
678+
v = @view A[i1, i2, i3]
679+
@test first(vo) == first(v) == first(A[i1, i2, i3])
680+
@test collect(A[i1, i2, i3]) == collect(vo) == collect(v)
681+
end
682+
end
683+
end
684+
end
685+
659686
@testset "issue #29608; contiguousness" begin
660687
@test Base.iscontiguous(view(ones(1), 1))
661688
@test Base.iscontiguous(view(ones(10), 1:10))

0 commit comments

Comments
 (0)