@@ -317,15 +317,35 @@ end
317317
318318Base. similar (A:: OffsetArray , :: Type{T} , dims:: Dims ) where T =
319319 similar (parent (A), T, dims)
320+
321+ """
322+ isonebased(ax::AbstractUnitRange{<:Integer})
323+
324+ Return whether `firstindex(ax)` is statically known to be `1`. Custom axis types may extend this method
325+ to ensure that the axis offset is ignored, for example in `similar`.
326+ """
327+ isonebased (_) = false
328+ isonebased (:: Integer ) = true
329+ isonebased (:: Base.OneTo ) = true
330+ isonebased (:: IIUR{<:Base.OneTo} ) = true
331+
332+ to_length (i:: Integer ) = i
333+ to_length (i:: AbstractUnitRange ) = length (i)
334+
335+ # Since the following is committing type-piracy, we provide an opt-out mechanism to the users
320336function Base. similar (A:: AbstractArray , :: Type{T} , shape:: Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}} ) where T
321- # strip IdOffsetRanges to extract the parent range and use it to generate the array
322- new_shape = map (_strip_IdOffsetRange, shape)
323- # route through _similar_axes_or_length to avoid a stack overflow if map(_strip_IdOffsetRange, shape) === shape
324- # This tries to use new_shape directly in similar if similar(A, T, ::typeof(new_shape)) is defined
325- # If this fails, it calls similar(A, T, map(_indexlength, new_shape)) to use the size along each axis
326- # to generate the new array
327- P = _similar_axes_or_length (A, T, new_shape, shape)
328- return OffsetArray (P, map (_offset, axes (P), shape))
337+ if all (isonebased, shape)
338+ return similar (A, T, map (to_length, shape))
339+ else
340+ # strip IdOffsetRanges to extract the parent range and use it to generate the array
341+ new_shape = map (_strip_IdOffsetRange, shape)
342+ # route through _similar_axes_or_length to avoid a stack overflow if map(_strip_IdOffsetRange, shape) === shape
343+ # This tries to use new_shape directly in similar if similar(A, T, ::typeof(new_shape)) is defined
344+ # If this fails, it calls similar(A, T, map(_indexlength, new_shape)) to use the size along each axis
345+ # to generate the new array
346+ P = _similar_axes_or_length (A, T, new_shape, shape)
347+ return OffsetArray (P, map (_offset, axes (P), shape))
348+ end
329349end
330350Base. similar (:: Type{A} , sz:: Tuple{Vararg{Int}} ) where {A<: OffsetArray } = similar (Array{eltype (A)}, sz)
331351function Base. similar (:: Type{T} , shape:: Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}} ) where {T<: AbstractArray }
@@ -699,11 +719,11 @@ no_offset_view(a::Array) = a
699719no_offset_view (i:: Number ) = i
700720no_offset_view (A:: AbstractArray ) = _no_offset_view (axes (A), A)
701721_no_offset_view (:: Tuple{} , A:: AbstractArray{T,0} ) where T = A
702- _no_offset_view (:: Tuple{Base.OneTo, Vararg{Base.OneTo}} , A:: AbstractArray ) = A
703- # the following method is needed for ambiguity resolution
704- _no_offset_view ( :: Tuple{Base.OneTo, Vararg{Base.OneTo}} , A :: AbstractUnitRange ) = A
705- _no_offset_view ( :: Any , A:: AbstractArray ) = OffsetArray (A, Origin (1 ))
706- _no_offset_view ( :: Any , A:: AbstractUnitRange ) = UnitRange (A)
722+ function _no_offset_view (ax :: Tuple , A:: AbstractArray )
723+ all (isonebased, ax) ? A : __no_offset_view (A)
724+ end
725+ __no_offset_view ( A:: AbstractArray ) = OffsetArray (A, Origin (1 ))
726+ __no_offset_view ( A:: AbstractUnitRange ) = UnitRange (A)
707727
708728# ####
709729# center/centered
0 commit comments