-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
reshape may accept AbstractUnitRanges that begin at 1 as arguments #41003
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
reshape(parent::AbstractArray, shp::Tuple{Union{Integer,OneTo}, Vararg{Union{Integer,OneTo}}}) = reshape(parent, to_shape(shp)) | ||
reshape(parent::AbstractArray, shp::Tuple) = reshape(parent, map(_toshape, shp)::Tuple{Vararg{Union{Int,Colon}}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This uses a general Tuple
instead of one with a union of valid types to allow OffsetArrays to define methods for AbstractUnitRange arguments that return OffsetArray
s
This means that loading OffsetArrays will change some results. That's a stronger form of piracy than changing e.g. julia> reshape('a':'h', 1:2, 1:4) # with this PR
2×4 reshape(::StepRange{Char, Int64}, 2, 4) with eltype Char:
'a' 'c' 'e' 'g'
'b' 'd' 'f' 'h'
julia> using OffsetArrays
julia> reshape('a':'h', 1:2, 1:4)
2×4 OffsetArray(reshape(::StepRange{Char, Int64}, 2, 4), 1:2, 1:4) with eltype Char with indices 1:2×1:4:
'a' 'c' 'e' 'g'
'b' 'd' 'f' 'h' |
Yes loading The goal of this PR was mainly to allow custom 1-based range types such as the axes of julia> s = SVector{2}(1:2);
julia> reshape(s, axes(s,1), 1)
ERROR: MethodError: no method matching reshape(::SVector{2, Int64}, ::Tuple{SOneTo{2}, Int64}) With this PR this will work: julia> s = SVector{2}(1:2);
julia> reshape(s, axes(s,1), 1)
2×1 reshape(::SVector{2, Int64}, 2, 1) with eltype Int64:
1
2 The axes of |
I thought this was resolved precisely by not defining such methods: For StaticArrays, isn't deciding what to do with its own static range types something it ought to handle? In many cases it does so: julia> using StaticArrays
julia> s = SA[1,2];
julia> m = similar(1:0, axes(s,1), axes(s,1)) # correctly overloaded
2×2 MMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
25 4607885968
100 26
julia> vec(m) # correctly overloaded -- this is preferable to reshape(::MMatrix{...})
4-element MVector{4, Int64} with indices SOneTo(4):
25
100
4607885968
26
julia> axes(reshape(m, :)) # not overloaded, hence loses static information
(Base.OneTo(4),)
julia> reshape(s, axes(s,1), axes(s,2)) # also not overloaded, that's a bug perhaps?
ERROR: MethodError: no method matching reshape(::SVector{2, Int64}, ::Tuple{SOneTo{2}, Base.OneTo{Int64}})
julia> using OffsetArrays
julia> reshape(s, axes(s,1), axes(s,2)) # piracy! But at least it was an error before
2×1 OffsetArray(reshape(::SVector{2, Int64}, 2, 1), 1:2, 1:1) with eltype Int64 with indices 1:2×1:1:
1
2
julia> axes(ans) # static structure is not preserved
(OffsetArrays.IdOffsetRange(values=1:2, indices=1:2), OffsetArrays.IdOffsetRange(values=1:1, indices=1:1))
julia> similar(1:0, axes(s,1)) # this is not affected by piracy, good
2-element MVector{2, Int64} with indices SOneTo(2):
4631963440
5544374880 Maybe there are stranger examples than mine. You can still use dispatch to catch
This sounds like an argument for an |
So let me try to summarize the status:
|
Incidentally |
I would say that Fixing that will mean that it just works on a 1D OffsetArray, since OffsetArrays already overloads all relevant Fixing that will also turn julia> permutedims(SA[1 2; 3 4]) # not implemented, goes via similar, fails to preserve SMatrix
2×2 MMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
1 3
2 4
julia> adjoint(SA[1 2; 3 4]) # is implemented, preserves SMatrix
2×2 SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
1 3
2 4 StaticArrays chooses to leave all |
julia> permutedims(Diagonal(1:4))
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
1 ⋅ ⋅ ⋅
⋅ 2 ⋅ ⋅
⋅ ⋅ 3 ⋅
⋅ ⋅ ⋅ 4 The
This PR only changes the |
My unwrapping example requires 1.7, it seems. Fixing |
I agree wrt the julia> A = ones(2:3)
2-element OffsetArray(::Vector{Float64}, 2:3) with eltype Float64 with indices 2:3:
1.0
1.0
julia> S = StructArray{ComplexF64}((A, A))
2-element StructArray(OffsetArray(::Vector{Float64}, 2:3), OffsetArray(::Vector{Float64}, 2:3)) with eltype ComplexF64 with indices 2:3:
1.0 + 1.0im
1.0 + 1.0im
julia> T = ComplexF64[1+im for _ in axes(A,1)]
2-element OffsetArray(::Vector{ComplexF64}, 2:3) with eltype ComplexF64 with indices 2:3:
1.0 + 1.0im
1.0 + 1.0im
julia> S == T
true
julia> permutedims(S) == permutedims(T)
false
julia> permutedims(S)
1×2 StructArray(::Matrix{Float64}, ::Matrix{Float64}) with eltype ComplexF64:
1.0+1.0im 1.0+1.0im
julia> permutedims(T)
1×2 OffsetArray(::Matrix{ComplexF64}, 1:1, 2:3) with eltype ComplexF64 with indices 1:1×2:3:
1.0+1.0im 1.0+1.0im Unless the |
Currently this works:
but this doesn't
After this PR the latter will work:
Performance seems identical:
Aside from this, these now behave correctly:
These added methods to
reshape
also ensure thatpermutedims
works correctly forOffsetVector
s: