@@ -179,16 +179,21 @@ for f in [:first, :last]
179
179
@eval @inline Base.$ f (r:: IdOffsetRange ) = eltype (r)($ f (r. parent) + r. offset)
180
180
end
181
181
182
- @inline function Base . iterate (r :: IdOffsetRange )
183
- ret = iterate (r . parent )
184
- ret === nothing && return nothing
185
- return ( eltype (r)(ret[ 1 ] + r . offset), ret[ 2 ])
186
- end
187
- @inline function Base . iterate (r:: IdOffsetRange , i)
188
- ret = iterate (r. parent, i)
182
+ # Iteration for an IdOffsetRange
183
+ @inline Base . iterate (r :: IdOffsetRange , i ... ) = _iterate (r, i ... )
184
+ # In general we iterate over the parent term by term and add the offset.
185
+ # This might have some performance degradation when coupled with bounds-checking
186
+ # See https://github.com/JuliaArrays/OffsetArrays.jl/issues/214
187
+ @inline function _iterate (r:: IdOffsetRange , i... )
188
+ ret = iterate (r. parent, i... )
189
189
ret === nothing && return nothing
190
190
return (eltype (r)(ret[1 ] + r. offset), ret[2 ])
191
191
end
192
+ # Base.OneTo(n) is known to be exactly equivalent to the range 1:n,
193
+ # and has no specialized iteration defined for it,
194
+ # so we may add the offset to the range directly and iterate over the result
195
+ # This gets around the performance issue described in issue #214
196
+ @inline _iterate (r:: IdOffsetRange{<:Integer, <:Base.OneTo} , i... ) = iterate (r. parent .+ r. offset, i... )
192
197
193
198
@inline function Base. getindex (r:: IdOffsetRange , i:: Integer )
194
199
i isa Bool && throw (ArgumentError (" invalid index: $i of type Bool" ))
0 commit comments