reshape may accept AbstractUnitRanges that begin at 1 as arguments#41003
reshape may accept AbstractUnitRanges that begin at 1 as arguments#41003jishnub wants to merge 4 commits intoJuliaLang:masterfrom
Conversation
| reshape(parent::AbstractArray, dims::IntOrInd...) = reshape(parent, dims) | ||
| reshape(parent::AbstractArray, dims::Union{Integer, AbstractUnitRange{<:Integer}, Colon}...) = reshape(parent, dims) | ||
| 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.
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 OffsetArrays
|
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
2The 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
5544374880Maybe 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 4StaticArrays chooses to leave all |
|
julia> permutedims(Diagonal(1:4))
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
1 ⋅ ⋅ ⋅
⋅ 2 ⋅ ⋅
⋅ ⋅ 3 ⋅
⋅ ⋅ ⋅ 4The
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.0imUnless 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
reshapealso ensure thatpermutedimsworks correctly forOffsetVectors: