Skip to content

Commit d1c9ae7

Browse files
Merge branch 'master' into lastindex-ragged
2 parents 40fc321 + 5271d8b commit d1c9ae7

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

src/vector_of_array.jl

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -805,13 +805,19 @@ function Base.view(A::AbstractVectorOfArray{T, N, <:AbstractVector{T}},
805805
end
806806
function Base.view(A::AbstractVectorOfArray, I::Vararg{Any, M}) where {M}
807807
@inline
808-
# Special handling for heterogeneous arrays when viewing a single column
809-
# The issue is that to_indices uses axes, which is based on the first element's size
810-
# For heterogeneous arrays, we need to use the actual size of the specific column
811-
if length(I) == 2 && I[1] == Colon() && I[2] isa Int
812-
@boundscheck checkbounds(A.u, I[2])
813-
# Use the actual size of the specific column instead of relying on axes/to_indices
814-
J = (Base.OneTo(length(A.u[I[2]])), I[2])
808+
# Generalized handling for heterogeneous arrays when the last index selects a column (Int)
809+
# The issue is that `to_indices` uses `axes(A)` which is based on the first element's size.
810+
# For heterogeneous arrays, use the actual axes of the specific selected inner array.
811+
if length(I) >= 1 && I[end] isa Int
812+
i = I[end]
813+
@boundscheck checkbounds(A.u, i)
814+
frontI = Base.front(I)
815+
# Normalize indices against the selected inner array's axes
816+
frontJ = to_indices(A.u[i], frontI)
817+
# Unalias indices and construct the full index tuple
818+
J = (map(j -> Base.unalias(A, j), frontJ)..., i)
819+
# Bounds check against the selected inner array to avoid relying on A's axes
820+
@boundscheck checkbounds(Bool, A.u[i], frontJ...) || throw(BoundsError(A, I))
815821
return SubArray(A, J)
816822
end
817823
J = map(i -> Base.unalias(A, i), to_indices(A, I))
@@ -847,10 +853,14 @@ function Base.checkbounds(::Type{Bool}, VA::AbstractVectorOfArray, idx...)
847853
return _checkbounds_ragged(Bool, VA, idx...)
848854
end
849855
checkbounds(Bool, VA.u, last(idx)) || return false
850-
for i in last(idx)
851-
checkbounds(Bool, VA.u[i], Base.front(idx)...) || return false
856+
if last(idx) isa Int
857+
return checkbounds(Bool, VA.u[last(idx)], Base.front(idx)...)
858+
else
859+
for i in last(idx)
860+
checkbounds(Bool, VA.u[i], Base.front(idx)...) || return false
861+
end
862+
return true
852863
end
853-
return true
854864
end
855865
function Base.checkbounds(VA::AbstractVectorOfArray, idx...)
856866
checkbounds(Bool, VA, idx...) || throw(BoundsError(VA, idx))

test/basic_indexing.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,38 @@ ragged2 = VectorOfArray([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0], [7.0, 8.0, 9.0]])
192192
@test ragged2[1:(end - 1), 2] == [5.0]
193193
@test ragged2[1:(end - 1), 3] == [7.0, 8.0]
194194

195+
# Broadcasting of heterogeneous arrays (issue #454)
196+
u = VectorOfArray([[1.0], [2.0, 3.0]])
197+
@test length(view(u, :, 1)) == 1
198+
@test length(view(u, :, 2)) == 2
199+
# broadcast assignment into selected column (last index Int)
200+
u[:, 2] .= [10.0, 11.0]
201+
@test u.u[2] == [10.0, 11.0]
202+
203+
# 2D inner arrays (matrices) with ragged second dimension
204+
u = VectorOfArray([zeros(1, n) for n in (2, 3)])
205+
@test length(view(u, 1, :, 1)) == 2
206+
@test length(view(u, 1, :, 2)) == 3
207+
u[1, :, 2] .= [1.0, 2.0, 3.0]
208+
@test u.u[2] == [1.0 2.0 3.0]
209+
# partial column selection by indices
210+
u[1, [1, 3], 2] .= [7.0, 9.0]
211+
@test u.u[2] == [7.0 2.0 9.0]
212+
213+
# 3D inner arrays (tensors) with ragged third dimension
214+
u = VectorOfArray([zeros(2, 1, n) for n in (2, 3)])
215+
@test size(view(u, :, :, :, 1)) == (2, 1, 2)
216+
@test size(view(u, :, :, :, 2)) == (2, 1, 3)
217+
# assign into a slice of the second inner array using last index Int
218+
u[2, 1, :, 2] .= [7.0, 8.0, 9.0]
219+
@test vec(u.u[2][2, 1, :]) == [7.0, 8.0, 9.0]
220+
# check mixed slicing with range on front dims
221+
u[1:2, 1, [1, 3], 2] .= [1.0 3.0; 2.0 4.0]
222+
@test u.u[2][1, 1, 1] == 1.0
223+
@test u.u[2][2, 1, 1] == 2.0
224+
@test u.u[2][1, 1, 3] == 3.0
225+
@test u.u[2][2, 1, 3] == 4.0
226+
195227
# Test that views can be modified
196228
f3 = VectorOfArray([[1.0, 2.0], [3.0, 4.0, 5.0]])
197229
v = view(f3, :, 2)

0 commit comments

Comments
 (0)