diff --git a/src/arrayops.jl b/src/arrayops.jl index 176290d..4b9e99b 100644 --- a/src/arrayops.jl +++ b/src/arrayops.jl @@ -28,14 +28,18 @@ ContiguousSubArray{T,N,P, Array types with contiguous first dimension. """ -ContiguousArray{T,N} = Union{DenseArray{T,N}, ContiguousSubArray{T,N}} +ContiguousArray{T,N} = Union{DenseArray{T,N}, ContiguousSubArray{T,N}, + Base.ReinterpretArray{T,N,T2,A} where {A <: Union{DenseArray{T2,N}, + ContiguousSubArray{T2,N}}} where {T2}} """ FastContiguousArray{T,N} This is the type of arrays that `pointer(A, i)` works. """ -FastContiguousArray{T,N} = Union{DenseArray{T,N}, Base.FastContiguousSubArray{T,N}} +FastContiguousArray{T,N} = Union{DenseArray{T,N}, Base.FastContiguousSubArray{T,N}, + Base.ReinterpretArray{T,N,T2,A} where {A <: Union{DenseArray{T2,N}, + Base.FastContiguousSubArray{T2,N}}} where {T2}} # https://github.com/eschnett/SIMD.jl/pull/40#discussion_r254131184 # https://github.com/JuliaArrays/MappedArrays.jl/pull/24#issuecomment-460568978 @@ -270,12 +274,15 @@ end _pointer(arr, i, I) Pointer to the element `arr[i, I...]`. """ -Base.@propagate_inbounds _pointer(arr::Array, i, I) = +Base.@propagate_inbounds _pointer(arr::Union{Array, Base.ReinterpretArray}, i, I) = pointer(arr, LinearIndices(arr)[i, I...]) Base.@propagate_inbounds _pointer(arr::Base.FastContiguousSubArray, i, I) = pointer(arr, (i, I...)) Base.@propagate_inbounds _pointer(arr::Base.FastContiguousSubArray, i, I::Tuple{}) = pointer(arr, i) +# must be separate methods to resolve ambiguity +Base.@propagate_inbounds _pointer(arr::Base.ReinterpretArray, i, I::Tuple{}) = + pointer(arr, i) Base.@propagate_inbounds _pointer(arr::SubArray, i, I) = pointer(Base.unsafe_view(arr, 1, I...), i) diff --git a/test/runtests.jl b/test/runtests.jl index 53f090d..3274c03 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -809,4 +809,31 @@ llvm_ir(f, args) = sprint(code_llvm, f, Base.typesof(args...)) @test shufflevector(a, b, Val((2,3,4,5))) === Vec{4,Bool}((true,false,false,false)) end end + + @testset "Contiguous ReinterpretArrays load/store" begin + a = UInt8[1:32...] + b = reinterpret(UInt32, a)::Base.ReinterpretArray + c = vload(Vec{4,UInt32}, b, 2) + c_expected = Vec{4, UInt32}((0x08070605, 0x0c0b0a09, 0x100f0e0d, 0x14131211)) + @test c === c_expected + + c += 1 + a_expected = copy(a) + a_expected[[5,9,13,17]] .+= 1 + vstore(c, b, 2) + @test a == a_expected + + # indexing methods + @test b[VecRange{2}(1)] === Vec{2, UInt32}((0x04030201, 0x08070606)) + + b[VecRange{2}(1)] = Vec{2, UInt32}((0x01020304, 0x06060708)) + @test b[1:2] == [0x01020304, 0x06060708] + + # multidimensional indexing + d = reshape(a, (8,4)) + e = reinterpret(UInt32, d)::Base.ReinterpretArray + @test e[VecRange{2}(1), 2] === Vec{2, UInt32}((0x0c0b0a0a, 0x100f0e0e)) + e[VecRange{2}(1), 2] = Vec{2, UInt32}((0x0a0a0b0c, 0x0e0e0f10)) + @test e[1:2, 2] == [0x0a0a0b0c, 0x0e0e0f10] + end # end