From 15cf02f577841aa331d78dd29f8d58612633fa88 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Wed, 20 Mar 2024 06:04:27 +0000 Subject: [PATCH 1/3] Fix behavior of `copy` and `similar` --- src/ReadOnlyArrays.jl | 4 ++-- test/runtests.jl | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ReadOnlyArrays.jl b/src/ReadOnlyArrays.jl index a6b3eb7..b973dd0 100644 --- a/src/ReadOnlyArrays.jl +++ b/src/ReadOnlyArrays.jl @@ -31,7 +31,7 @@ CanonicalIndexError: setindex! not defined for ReadOnlyArray{Int64,2,Array{Int64 """ struct ReadOnlyArray{T,N,A} <: AbstractArray{T,N} parent::A - function ReadOnlyArray(parent::AbstractArray{T,N}) where {T,N} + function ReadOnlyArray(parent::AbstractArray{T,N}) where {T,N} new{T,N,typeof(parent)}(parent) end end @@ -69,7 +69,7 @@ Base.iterate(x::ReadOnlyArray, args...) = iterate(x.parent, args...) Base.length(x::ReadOnlyArray) = length(x.parent) -Base.similar(x::ReadOnlyArray) = similar(x.parent) |> ReadOnlyArray +Base.similar(x::ReadOnlyArray) = similar(x.parent) Base.axes(x::ReadOnlyArray) = axes(x.parent) diff --git a/test/runtests.jl b/test/runtests.jl index 77a4bd5..d86f881 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -51,6 +51,12 @@ end fa = f() @test fa isa ReadOnlyArray{Float64,2} @test fa == x + + a = ReadOnly([1, 2]) + @test typeof(similar(a)) === Vector{Int64} + + @test copy(a) == [1, 2] + @test typeof(copy(a)) === Vector{Int64} end end From 0b06463433999bf848e6a0a790352acba26597df Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Wed, 20 Mar 2024 15:05:48 +0900 Subject: [PATCH 2/3] Formatting --- src/ReadOnlyArrays.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ReadOnlyArrays.jl b/src/ReadOnlyArrays.jl index b973dd0..a850b22 100644 --- a/src/ReadOnlyArrays.jl +++ b/src/ReadOnlyArrays.jl @@ -31,7 +31,7 @@ CanonicalIndexError: setindex! not defined for ReadOnlyArray{Int64,2,Array{Int64 """ struct ReadOnlyArray{T,N,A} <: AbstractArray{T,N} parent::A - function ReadOnlyArray(parent::AbstractArray{T,N}) where {T,N} + function ReadOnlyArray(parent::AbstractArray{T,N}) where {T,N} new{T,N,typeof(parent)}(parent) end end From b2155b9710fff775371be881e82d23768a2ab8c3 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Wed, 20 Mar 2024 06:23:55 +0000 Subject: [PATCH 3/3] Cache shape parameters of `ReadOnlyArray` --- src/ReadOnlyArrays.jl | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/ReadOnlyArrays.jl b/src/ReadOnlyArrays.jl index a850b22..f10d85f 100644 --- a/src/ReadOnlyArrays.jl +++ b/src/ReadOnlyArrays.jl @@ -29,10 +29,22 @@ CanonicalIndexError: setindex! not defined for ReadOnlyArray{Int64,2,Array{Int64 [...] ``` """ -struct ReadOnlyArray{T,N,A} <: AbstractArray{T,N} +struct ReadOnlyArray{T,N,A,LE,SI,AX,I} <: AbstractArray{T,N} parent::A + _length::LE + _size::SI + _axes::AX + _firstindex::I + _lastindex::I + function ReadOnlyArray(parent::AbstractArray{T,N}) where {T,N} - new{T,N,typeof(parent)}(parent) + _l = length(parent) + _s = size(parent) + _a = axes(parent) + _f = firstindex(parent) + _l = lastindex(parent) + _I = typejoin(typeof(_f), typeof(_l)) + new{T,N,typeof.((parent,_l,_s,_a))...,_I}(parent, _l, _s, _a, _f, _l) end end @@ -57,7 +69,16 @@ ReadOnlyMatrix(parent::AbstractMatrix) = ReadOnlyArray(parent) # interface, excluding setindex!() and similar() # https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-parentay -Base.size(x::ReadOnlyArray, args...) = size(x.parent, args...) +Base.size(x::ReadOnlyArray) = x._size +Base.length(x::ReadOnlyArray) = x._length +Base.axes(x::ReadOnlyArray) = x._axes +Base.firstindex(x::ReadOnlyArray) = x._firstindex +Base.lastindex(x::ReadOnlyArray) = x._lastindex + +# Special caching for `Array` +Base.size(a::ReadOnlyArray{<:Any,<:Any,<:Array}, d::Integer) = x._size[d] + +Base.size(x::ReadOnlyArray, arg, args...) = size(x.parent, arg, args...) @propagate_inbounds function Base.getindex(x::ReadOnlyArray, args...) getindex(x.parent, args...) @@ -67,12 +88,8 @@ Base.IndexStyle(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} = IndexStyle(P) Base.iterate(x::ReadOnlyArray, args...) = iterate(x.parent, args...) -Base.length(x::ReadOnlyArray) = length(x.parent) - Base.similar(x::ReadOnlyArray) = similar(x.parent) -Base.axes(x::ReadOnlyArray) = axes(x.parent) - function Base.IteratorSize(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} Base.IteratorSize(P) end @@ -85,10 +102,6 @@ function Base.eltype(::Type{<:ReadOnlyArray{T,N,P}}) where {T,N,P} eltype(P) end -Base.firstindex(x::ReadOnlyArray) = firstindex(x.parent) - -Base.lastindex(x::ReadOnlyArray) = lastindex(x.parent) - Base.strides(x::ReadOnlyArray) = strides(x.parent) function Base.unsafe_convert(p::Type{Ptr{T}}, x::ReadOnlyArray) where {T}