Skip to content

Commit b16a91c

Browse files
committed
Unify reshape methods accepting Colon and OneTo
1 parent 64d37f5 commit b16a91c

File tree

5 files changed

+34
-20
lines changed

5 files changed

+34
-20
lines changed

base/abstractarray.jl

+2
Original file line numberDiff line numberDiff line change
@@ -834,11 +834,13 @@ similar(a::AbstractArray, ::Type{T}, dims::Dims{N}) where {T,N} = Array{T,N}(
834834
to_shape(::Tuple{}) = ()
835835
to_shape(dims::Dims) = dims
836836
to_shape(dims::DimsOrInds) = map(to_shape, dims)::DimsOrInds
837+
to_shape(dims::Tuple{Vararg{Union{Integer, AbstractUnitRange, Colon}}}) = map(to_shape, dims)
837838
# each dimension
838839
to_shape(i::Int) = i
839840
to_shape(i::Integer) = Int(i)
840841
to_shape(r::OneTo) = Int(last(r))
841842
to_shape(r::AbstractUnitRange) = r
843+
to_shape(r::Colon) = r
842844

843845
"""
844846
similar(storagetype, axes)

base/reshapedarray.jl

+19-17
Original file line numberDiff line numberDiff line change
@@ -119,31 +119,31 @@ julia> reshape(1:6, 2, 3)
119119
"""
120120
reshape
121121

122-
reshape(parent::AbstractArray, dims::IntOrInd...) = reshape(parent, dims)
123-
reshape(parent::AbstractArray, shp::Tuple{Union{Integer,OneTo}, Vararg{Union{Integer,OneTo}}}) = reshape(parent, to_shape(shp))
124-
reshape(parent::AbstractArray, dims::Tuple{Integer, Vararg{Integer}}) = reshape(parent, map(Int, dims))
122+
# we collect the vararg indices and only define methods for tuples of indices
123+
reshape(parent::AbstractArray, dims::Union{Integer,Colon,AbstractUnitRange}...) = reshape(parent, dims)
124+
reshape(parent::AbstractArray, dims::Tuple{Vararg{Integer}}) = reshape(parent, map(Int, dims))
125125
reshape(parent::AbstractArray, dims::Dims) = _reshape(parent, dims)
126126

127127
# Allow missing dimensions with Colon():
128-
reshape(parent::AbstractVector, ::Colon) = parent
129-
reshape(parent::AbstractVector, ::Tuple{Colon}) = parent
130-
reshape(parent::AbstractArray, dims::Int...) = reshape(parent, dims)
131-
reshape(parent::AbstractArray, dims::Integer...) = reshape(parent, dims)
132-
reshape(parent::AbstractArray, dims::Union{Integer,Colon}...) = reshape(parent, dims)
133-
reshape(parent::AbstractArray, dims::Tuple{Vararg{Union{Integer,Colon}}}) = reshape(parent, _reshape_uncolon(parent, dims))
134-
135-
@noinline throw1(dims) = throw(DimensionMismatch(LazyString("new dimensions ", dims,
128+
# convert axes to sizes using to_shape, and convert colons to sizes using _reshape_uncolon
129+
# We add a level of indirection to avoid method ambiguities in reshape
130+
reshape(parent::AbstractArray, dims::Tuple{Vararg{Union{Integer,Colon,OneTo}}}) = _reshape_maybecolon(parent, dims)
131+
_reshape_maybecolon(parent::AbstractVector, ::Tuple{Colon}) = parent
132+
_reshape_maybecolon(parent::AbstractArray, dims::Tuple{Vararg{Union{Integer,Colon,OneTo}}}) = reshape(parent, _reshape_uncolon(length(parent), to_shape(dims)))
133+
134+
@noinline _reshape_throwcolon(dims) = throw(DimensionMismatch(LazyString("new dimensions ", dims,
136135
" may have at most one omitted dimension specified by `Colon()`")))
137-
@noinline throw2(lenA, dims) = throw(DimensionMismatch(string("array size ", lenA,
136+
@noinline _reshape_throwsize(lenA, dims) = throw(DimensionMismatch(LazyString("array size ", lenA,
138137
" must be divisible by the product of the new dimensions ", dims)))
139138

140-
@inline function _reshape_uncolon(A, _dims::Tuple{Vararg{Union{Integer, Colon}}})
139+
_reshape_uncolon(len, ::Tuple{Colon}) = len
140+
@inline function _reshape_uncolon(len, _dims::Tuple{Vararg{Union{Integer, Colon}}})
141141
# promote the dims to `Int` at least
142142
dims = map(x -> x isa Colon ? x : promote_type(typeof(x), Int)(x), _dims)
143+
dims isa Tuple{Vararg{Integer}} && return dims
143144
pre = _before_colon(dims...)
144145
post = _after_colon(dims...)
145-
_any_colon(post...) && throw1(dims)
146-
len = length(A)
146+
_any_colon(post...) && _reshape_throwcolon(dims)
147147
_reshape_uncolon_computesize(len, dims, pre, post)
148148
end
149149
@inline function _reshape_uncolon_computesize(len::Int, dims, pre::Tuple{Vararg{Int}}, post::Tuple{Vararg{Int}})
@@ -167,18 +167,20 @@ end
167167
(pre..., sz, post...)
168168
end
169169
@inline function _reshape_uncolon_computesize_nonempty(len, dims, pr)
170-
iszero(pr) && throw2(len, dims)
170+
iszero(pr) && _reshape_throwsize(len, dims)
171171
(quo, rem) = divrem(len, pr)
172-
iszero(rem) || throw2(len, dims)
172+
iszero(rem) || _reshape_throwsize(len, dims)
173173
quo
174174
end
175175
@inline _any_colon() = false
176176
@inline _any_colon(dim::Colon, tail...) = true
177177
@inline _any_colon(dim::Any, tail...) = _any_colon(tail...)
178178
@inline _before_colon(dim::Any, tail...) = (dim, _before_colon(tail...)...)
179179
@inline _before_colon(dim::Colon, tail...) = ()
180+
@inline _before_colon() = ()
180181
@inline _after_colon(dim::Any, tail...) = _after_colon(tail...)
181182
@inline _after_colon(dim::Colon, tail...) = tail
183+
@inline _after_colon() = ()
182184

183185
reshape(parent::AbstractArray{T,N}, ndims::Val{N}) where {T,N} = parent
184186
function reshape(parent::AbstractArray, ndims::Val{N}) where N

test/abstractarray.jl

+3
Original file line numberDiff line numberDiff line change
@@ -2205,6 +2205,9 @@ end
22052205
@test b isa Matrix{Int}
22062206
@test b.ref === a.ref
22072207
end
2208+
C = reshape(CartesianIndices((2,2)), big(4))
2209+
@test axes(C, 1) == 1:4
2210+
@test C == CartesianIndex.([(1,1), (2,1), (1,2), (2,2)])
22082211
end
22092212
@testset "AbstractArrayMath" begin
22102213
@testset "IsReal" begin

test/offsetarray.jl

+10
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,16 @@ end
846846
a = OffsetArray(4:5, 5:6)
847847
@test reshape(a, :) === a
848848
@test reshape(a, (:,)) === a
849+
R = reshape(zeros(6), 2, :)
850+
@test R isa Matrix
851+
@test axes(R) == (1:2, 1:3)
852+
R = reshape(zeros(6,1), 2, :)
853+
@test R isa Matrix
854+
@test axes(R) == (1:2, 1:3)
855+
R = reshape(zeros(6), 2:3, :)
856+
@test axes(R) == (2:3, 1:3)
857+
R = reshape(zeros(6,1), 2:3, :)
858+
@test axes(R) == (2:3, 1:3)
849859
end
850860

851861
@testset "stack" begin

test/testhelpers/OffsetArrays.jl

-3
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,6 @@ _similar_axes_or_length(A, T, ax::I, ::I) where {I} = similar(A, T, map(_indexle
546546
_similar_axes_or_length(AT, ax::I, ::I) where {I} = similar(AT, map(_indexlength, ax))
547547

548548
# reshape accepts a single colon
549-
# this method is limited to AbstractUnitRange{<:Integer} to avoid method overwritten errors if Base defines the same,
550-
# see https://github.com/JuliaLang/julia/pull/56850
551-
Base.reshape(A::AbstractArray, inds::Union{Integer, Colon, AbstractUnitRange{<:Integer}}...) = reshape(A, inds)
552549
function Base.reshape(A::AbstractArray, inds::Tuple{Vararg{OffsetAxis}})
553550
AR = reshape(no_offset_view(A), map(_indexlength, inds))
554551
O = OffsetArray(AR, map(_offset, axes(AR), inds))

0 commit comments

Comments
 (0)