Skip to content

Commit d9b7d7e

Browse files
authored
fix #36753: fix write(::SubArray) by restoring pointer support (#36757)
Followup to #36739 (and currently built atop it), this restores the `pointer(::SubArray{<:Any,<:Any,<:Array,<:Tuple{Vararg{RangeIndex}}}, ::Tuple)` method that was removed in #36405. It does so, however, as a deprecated method, with the actual method being implemented on `(::SubArray{...}, ::CartesianIndex)`. The rationale here is because the `::Tuple` method was undocumented and only supported on that one _highly_ specific `SubArray` type. I am keeping this patch as minimal as possible for backporting; in the future I aim to support `Vararg{CartesianIndex, Integer}` locations to make this more `getindex`-y and move farther away from the conflation with memory offsets.
1 parent dac31d3 commit d9b7d7e

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

base/deprecated.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ macro get!(h, key0, default)
207207
end
208208
end
209209

210+
pointer(V::SubArray{<:Any,<:Any,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::Tuple) = pointer(V, CartesianIndex(is))
211+
210212
# END 1.5 deprecations
211213

212214
# BEGIN 1.6 deprecations

base/io.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,14 +680,14 @@ function write(s::IO, a::SubArray{T,N,<:Array}) where {T,N}
680680
colsz = size(a,1) * elsz
681681
GC.@preserve a if stride(a,1) != 1
682682
for idxs in CartesianIndices(size(a))
683-
unsafe_write(s, pointer(a, idxs.I), elsz)
683+
unsafe_write(s, pointer(a, idxs), elsz)
684684
end
685685
return elsz * length(a)
686686
elseif N <= 1
687687
return unsafe_write(s, pointer(a, 1), colsz)
688688
else
689-
for idxs in CartesianIndices((1, size(a)[2:end]...))
690-
unsafe_write(s, pointer(a, idxs.I), colsz)
689+
for colstart in CartesianIndices((1, size(a)[2:end]...))
690+
unsafe_write(s, pointer(a, colstart), colsz)
691691
end
692692
return colsz * trailingsize(a,2)
693693
end

base/subarray.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,15 @@ end
408408
pointer(V::FastSubArray, i::Int) = pointer(V.parent, V.offset1 + V.stride1*i)
409409
pointer(V::FastContiguousSubArray, i::Int) = pointer(V.parent, V.offset1 + i)
410410

411+
function pointer(V::SubArray{<:Any,<:Any,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::AbstractCartesianIndex{N}) where {N}
412+
index = first_index(V)
413+
strds = strides(V)
414+
for d = 1:N
415+
index += (is[d]-1)*strds[d]
416+
end
417+
return pointer(V.parent, index)
418+
end
419+
411420
# indices are taken from the range/vector
412421
# Since bounds-checking is performance-critical and uses
413422
# indices, it's worth optimizing these implementations thoroughly

test/subarray.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,27 @@ end
615615
v = Vector{UInt48}(undef, 5)
616616
read!(io, v)
617617
@test v == view(a, :, 2)
618+
619+
seekstart(io)
620+
@test write(io, view(a, 2:5, 1:4)) == 4*4*8
621+
seekstart(io)
622+
v = Matrix{UInt48}(undef, 4, 4)
623+
read!(io, v)
624+
@test v == view(a, 2:5, 1:4)
625+
626+
seekstart(io)
627+
@test write(io, view(a, 5:-1:1, 3)) == 5*8
628+
seekstart(io)
629+
v = Vector{UInt48}(undef, 5)
630+
read!(io, v)
631+
@test v == view(a, 5:-1:1, 3)
632+
633+
seekstart(io)
634+
@test write(io, view(a, 1:2:5, :)) == 3*5*8
635+
seekstart(io)
636+
v = Matrix{UInt48}(undef, 3, 5)
637+
read!(io, v)
638+
@test v == view(a, 1:2:5, :)
618639
end
619640

620641
@testset "unaliascopy trimming; Issue #26263" begin

0 commit comments

Comments
 (0)