Skip to content

Commit

Permalink
Support views on empty UnsafeArrays
Browse files Browse the repository at this point in the history
  • Loading branch information
oschulz committed Jul 24, 2024
1 parent 2dd8dbc commit b558c57
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/unsafe_array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,22 @@ Base.@propagate_inbounds _unsafe_view_impl(IFwd::NTuple{M,Base.ViewIndex}, A::Un
_unsafe_view_impl((IFwd..., i), A, I...)

@inline function _unsafe_view_impl(IFwd::NTuple{M,Base.Slice}, A::UnsafeArray{T,N}, i::DenseIdx, I::Integer...) where {T,M,N}
#@info "DEBUG" _unsafe_view_impl IFwd i I T M N
#global g_state = (;IFwd, i, I, T, M, N)
ax_A = axes(A)
@assert IFwd == ntuple(i -> axes(A)[i], Val{M}())
I_all = (IFwd..., i, I...)
@boundscheck checkbounds(A, I_all...)
startidxs = map(first, (IFwd..., i, I...))
firstidxs = map(first, ax_A)
sub_s = _sub_size(I_all...)
p = pointer(A, LinearIndices(size(A))[startidxs...])
A_isempty = length(A) == 0
view_isempty = prod(sub_s) == 0
# getindex on LinearIndices fails with startidxs if A is empty, so use pseudo-size in that case:
sz = size(A)
pseudo_sz = ntuple(_ -> 1, Val(N))
mod_size, mod_startidxs = ifelse(A_isempty && view_isempty, (pseudo_sz, firstidxs), (sz, startidxs))
p = pointer(A, LinearIndices(mod_size)[mod_startidxs...])
UnsafeArray(p, sub_s)
end

Expand Down
12 changes: 12 additions & 0 deletions test/unsafe_array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ using Random
end


function test_empty_A_UA(test_code::Function, ::Type{T}, Val_N::Val{N}) where {T, N}
A = rand(T, 0, fill(4, N-1)...)
UA = UnsafeArray(pointer(A), size(A))
UnsafeArrays.@gc_preserve A test_code(A, UA)
end


@testset "ctors" begin
test_A(Float64, Val(0)) do A
ptr = pointer(A)
Expand Down Expand Up @@ -146,6 +153,11 @@ using Random
@test isbits(view(UA, :, :, :)) == true
@test isbits(view(UA, :, 3, :)) == true
end

test_empty_A_UA(Float32, Val(2)) do A, UA
@test @inferred(view(UA, :, 2:3)) isa UnsafeArray
@test size(@inferred(view(UA, :, 2:3))) == (0, 2)
end
end


Expand Down

0 comments on commit b558c57

Please sign in to comment.