From 04105c91ae2e2bbcc5924a03daab9d457f526513 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 15 Oct 2019 18:37:51 -0400 Subject: [PATCH 1/2] Implement three-argument `similar` methods Array wrappers such as `OffsetArray` assume that the three argument version exists for its interior arrays. --- src/structarray.jl | 10 +++++++++- test/runtests.jl | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/structarray.jl b/src/structarray.jl index f9b43c0a..a93e7bf0 100644 --- a/src/structarray.jl +++ b/src/structarray.jl @@ -102,10 +102,18 @@ end Base.similar(s::StructArray, sz::Base.DimOrInd...) = similar(s, Base.to_shape(sz)) Base.similar(s::StructArray) = similar(s, Base.to_shape(axes(s))) -function Base.similar(s::StructArray{T}, sz::Tuple) where {T} +function Base.similar(s::StructArray{T,N,C}, ::Type{T}, sz::NTuple{N,Int64}) where {T, N, C<:Union{Tuple, NamedTuple}} StructArray{T}(map(typ -> similar(typ, sz), fieldarrays(s))) end +function Base.similar(s::StructArray{T,N,C}, S::Type, sz::NTuple{N,Int64}) where {T, N, C<:Union{Tuple, NamedTuple}} + # If not specified, we don't really know what kind of array to use for each + # interior type, so we just pick the first one arbitrarily. If users need + # something else, they need to be more specific. + f1 = fieldarrays(s)[1] + buildfromschema(typ -> similar(f1, typ, sz), S) +end + """ `fieldarrays(s::StructArray)` diff --git a/test/runtests.jl b/test/runtests.jl index f699f8b1..5c74d9fa 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -646,3 +646,9 @@ end str = String(take!(io)) @test str == "StructArray(::Array{Int64,1}, ::Array{Int64,1})" end + +@testset "OffsetArray zero" begin + s = StructArray{ComplexF64}((rand(2), rand(2))) + soff = OffsetArray(s, 0:1) + @test isa(zero(soff).parent, StructArray) +end From a7576f689ee6d8fa37fd502831f21db82f7b5203 Mon Sep 17 00:00:00 2001 From: Pietro Vertechi Date: Fri, 18 Mar 2022 19:43:31 +0100 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Lucas C Wilcox --- src/structarray.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/structarray.jl b/src/structarray.jl index a93e7bf0..924937db 100644 --- a/src/structarray.jl +++ b/src/structarray.jl @@ -102,16 +102,20 @@ end Base.similar(s::StructArray, sz::Base.DimOrInd...) = similar(s, Base.to_shape(sz)) Base.similar(s::StructArray) = similar(s, Base.to_shape(axes(s))) -function Base.similar(s::StructArray{T,N,C}, ::Type{T}, sz::NTuple{N,Int64}) where {T, N, C<:Union{Tuple, NamedTuple}} +function Base.similar(s::StructArray{T,N,C}, ::Type{T}, sz::NTuple{M,Int64}) where {T, N, M, C<:Union{Tuple, NamedTuple}} StructArray{T}(map(typ -> similar(typ, sz), fieldarrays(s))) end -function Base.similar(s::StructArray{T,N,C}, S::Type, sz::NTuple{N,Int64}) where {T, N, C<:Union{Tuple, NamedTuple}} +function Base.similar(s::StructArray{T,N,C}, S::Type, sz::NTuple{M,Int64}) where {T, N, M, C<:Union{Tuple, NamedTuple}} # If not specified, we don't really know what kind of array to use for each # interior type, so we just pick the first one arbitrarily. If users need # something else, they need to be more specific. f1 = fieldarrays(s)[1] - buildfromschema(typ -> similar(f1, typ, sz), S) + if isstructtype(S) + return StructArrays.buildfromschema(typ -> similar(f1, typ, sz), S) + else + return similar(f1, S, sz) + end end """