Skip to content

Commit

Permalink
fix #36753: fix write(::SubArray) by restoring pointer support
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mbauman committed Jul 21, 2020
1 parent 1de8d16 commit 2b82538
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
2 changes: 2 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ macro get!(h, key0, default)
end
end

pointer(V::SubArray{<:Any,<:Any,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::Tuple) = pointer(V, CartesianIndex(is))

# END 1.5 deprecations

# BEGIN 1.6 deprecations
Expand Down
6 changes: 3 additions & 3 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -680,14 +680,14 @@ function write(s::IO, a::SubArray{T,N,<:Array}) where {T,N}
colsz = size(a,1) * elsz
GC.@preserve a if stride(a,1) != 1
for idxs in CartesianIndices(size(a))
unsafe_write(s, pointer(a, idxs.I), elsz)
unsafe_write(s, pointer(a, idxs), elsz)
end
return elsz * length(a)
elseif N <= 1
return unsafe_write(s, pointer(a, 1), colsz)
else
for idxs in CartesianIndices((1, size(a)[2:end]...))
unsafe_write(s, pointer(a, idxs.I), colsz)
for colstart in CartesianIndices((1, size(a)[2:end]...))
unsafe_write(s, pointer(a, colstart), colsz)
end
return colsz * trailingsize(a,2)
end
Expand Down
9 changes: 9 additions & 0 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,15 @@ end
pointer(V::FastSubArray, i::Int) = pointer(V.parent, V.offset1 + V.stride1*i)
pointer(V::FastContiguousSubArray, i::Int) = pointer(V.parent, V.offset1 + i)

function pointer(V::SubArray{<:Any,<:Any,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::AbstractCartesianIndex{N}) where {N}
index = first_index(V)
strds = strides(V)
for d = 1:N
index += (is[d]-1)*strds[d]
end
return pointer(V.parent, index)
end

# indices are taken from the range/vector
# Since bounds-checking is performance-critical and uses
# indices, it's worth optimizing these implementations thoroughly
Expand Down
21 changes: 21 additions & 0 deletions test/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,27 @@ end
v = Vector{UInt48}(undef, 5)
read!(io, v)
@test v == view(a, :, 2)

seekstart(io)
@test write(io, view(a, 2:5, 1:4)) == 4*4*8
seekstart(io)
v = Matrix{UInt48}(undef, 4, 4)
read!(io, v)
@test v == view(a, 2:5, 1:4)

seekstart(io)
@test write(io, view(a, 5:-1:1, 3)) == 5*8
seekstart(io)
v = Vector{UInt48}(undef, 5)
read!(io, v)
@test v == view(a, 5:-1:1, 3)

seekstart(io)
@test write(io, view(a, 1:2:5, :)) == 3*5*8
seekstart(io)
v = Matrix{UInt48}(undef, 3, 5)
read!(io, v)
@test v == view(a, 1:2:5, :)
end

@testset "unaliascopy trimming; Issue #26263" begin
Expand Down

0 comments on commit 2b82538

Please sign in to comment.