From b558c57ad8b865b7f9f51f4b1e757b664b45eb74 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Wed, 24 Jul 2024 12:38:24 +0200 Subject: [PATCH] Support views on empty UnsafeArrays --- src/unsafe_array.jl | 12 +++++++++++- test/unsafe_array.jl | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/unsafe_array.jl b/src/unsafe_array.jl index da3e51d..337a411 100644 --- a/src/unsafe_array.jl +++ b/src/unsafe_array.jl @@ -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 diff --git a/test/unsafe_array.jl b/test/unsafe_array.jl index 4c32b10..14f180a 100644 --- a/test/unsafe_array.jl +++ b/test/unsafe_array.jl @@ -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) @@ -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