@@ -271,10 +271,34 @@ end
271271
272272Base. similar (A:: OffsetArray , :: Type{T} , dims:: Dims ) where T =
273273 similar (parent (A), T, dims)
274- function Base. similar (A:: AbstractArray , :: Type{T} , inds:: Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}} ) where T
275- B = similar (A, T, map (_indexlength, inds))
276- return OffsetArray (B, map (_offset, axes (B), inds))
274+ function Base. similar (A:: AbstractArray , :: Type{T} , shape:: Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}} ) where T
275+ # strip IdOffsetRanges to extract the parent range and use it to generate the array
276+ new_shape = map (_strip_IdOffsetRange, shape)
277+ # route through _similar_axes_or_length to avoid a stack overflow if map(_strip_IdOffsetRange, shape) === shape
278+ # This tries to use new_shape directly in similar if similar(A, T, ::typeof(new_shape)) is defined
279+ # If this fails, it calls similar(A, T, map(_indexlength, new_shape)) to use the size along each axis
280+ # to generate the new array
281+ P = _similar_axes_or_length (A, T, new_shape, shape)
282+ return OffsetArray (P, map (_offset, axes (P), shape))
277283end
284+ function Base. similar (:: Type{T} , shape:: Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}} ) where {T<: AbstractArray }
285+ new_shape = map (_strip_IdOffsetRange, shape)
286+ P = _similar_axes_or_length (T, new_shape, shape)
287+ OffsetArray (P, map (_offset, axes (P), shape))
288+ end
289+ # Try to use the axes to generate the parent array type
290+ # This is useful if the axes have special meanings, such as with static arrays
291+ # This method is hit if at least one axis provided to similar(A, T, axes) is an IdOffsetRange
292+ # For example this is hit when similar(A::OffsetArray) is called,
293+ # which expands to similar(A, eltype(A), axes(A))
294+ _similar_axes_or_length (A, T, ax, :: Any ) = similar (A, T, ax)
295+ _similar_axes_or_length (AT, ax, :: Any ) = similar (AT, ax)
296+ # Handle the general case by resorting to lengths along each axis
297+ # This is hit if none of the axes provided to similar(A, T, axes) are IdOffsetRanges,
298+ # and if similar(A, T, axes::AX) is not defined for the type AX.
299+ # In this case the best that we can do is to create a mutable array of the correct size
300+ _similar_axes_or_length (A, T, ax:: I , :: I ) where {I} = similar (A, T, map (_indexlength, ax))
301+ _similar_axes_or_length (AT, ax:: I , :: I ) where {I} = similar (AT, map (_indexlength, ax))
278302
279303# reshape accepts a single colon
280304Base. reshape (A:: AbstractArray , inds:: OffsetAxis... ) = reshape (A, inds)
@@ -295,11 +319,6 @@ Base.reshape(A::OffsetVector, ::Colon) = A
295319Base. reshape (A:: OffsetArray , inds:: Union{Int,Colon} ...) = reshape (parent (A), inds)
296320Base. reshape (A:: OffsetArray , inds:: Tuple{Vararg{Union{Int,Colon}}} ) = reshape (parent (A), inds)
297321
298- function Base. similar (:: Type{T} , shape:: Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}} ) where {T<: AbstractArray }
299- P = T (undef, map (_indexlength, shape))
300- OffsetArray (P, map (_offset, axes (P), shape))
301- end
302-
303322Base. fill (v, inds:: NTuple{N, Union{Integer, AbstractUnitRange}} ) where {N} =
304323 fill! (similar (Array{typeof (v)}, inds), v)
305324Base. zeros (:: Type{T} , inds:: NTuple{N, Union{Integer, AbstractUnitRange}} ) where {T, N} =
0 commit comments