Skip to content

Commit 98ce750

Browse files
jishnubtecosaur
authored andcommitted
Orthogonalize re-indexing for FastSubArrays (JuliaLang#53369)
By separating out the re-indexing step for `FastSubArray`s and specializing this for `FastContiguousSubArray`s, we don't need to define specialized `getindex`, `setindex!` and `isassigned` for `FastContiguousSubArray`s anymore. The fallback method for `FastSubArray`s will correctly handle the special case.
1 parent f1973c1 commit 98ce750

File tree

1 file changed

+28
-58
lines changed

1 file changed

+28
-58
lines changed

base/subarray.jl

+28-58
Original file line numberDiff line numberDiff line change
@@ -320,47 +320,46 @@ end
320320

321321
# But SubArrays with fast linear indexing pre-compute a stride and offset
322322
FastSubArray{T,N,P,I} = SubArray{T,N,P,I,true}
323+
# We define a convenience functions to compute the shifted parent index
324+
# This differs from reindex as this accepts the view directly, instead of its indices
325+
@inline _reindexlinear(V::FastSubArray, i::Int) = V.offset1 + V.stride1*i
326+
@inline _reindexlinear(V::FastSubArray, i::AbstractUnitRange{Int}) = V.offset1 .+ V.stride1 .* i
327+
323328
function getindex(V::FastSubArray, i::Int)
324329
@inline
325330
@boundscheck checkbounds(V, i)
326-
@inbounds r = V.parent[V.offset1 + V.stride1*i]
331+
@inbounds r = V.parent[_reindexlinear(V, i)]
327332
r
328333
end
329-
# We can avoid a multiplication if the first parent index is a Colon or AbstractUnitRange,
330-
# or if all the indices are scalars, i.e. the view is for a single value only
331-
FastContiguousSubArray{T,N,P,I<:Union{Tuple{Union{Slice, AbstractUnitRange}, Vararg{Any}},
332-
Tuple{Vararg{ScalarIndex}}}} = SubArray{T,N,P,I,true}
333-
function getindex(V::FastContiguousSubArray, i::Int)
334+
335+
# For vector views with linear indexing, we disambiguate to favor the stride/offset
336+
# computation as that'll generally be faster than (or just as fast as) re-indexing into a range.
337+
function getindex(V::FastSubArray{<:Any, 1}, i::Int)
334338
@inline
335339
@boundscheck checkbounds(V, i)
336-
@inbounds r = V.parent[V.offset1 + i]
340+
@inbounds r = V.parent[_reindexlinear(V, i)]
337341
r
338342
end
343+
344+
# We can avoid a multiplication if the first parent index is a Colon or AbstractUnitRange,
345+
# or if all the indices are scalars, i.e. the view is for a single value only
346+
FastContiguousSubArray{T,N,P,I<:Union{Tuple{Union{Slice, AbstractUnitRange}, Vararg{Any}},
347+
Tuple{Vararg{ScalarIndex}}}} = SubArray{T,N,P,I,true}
348+
349+
@inline _reindexlinear(V::FastContiguousSubArray, i::Int) = V.offset1 + i
350+
@inline _reindexlinear(V::FastContiguousSubArray, i::AbstractUnitRange{Int}) = V.offset1 .+ i
351+
339352
# parents of FastContiguousSubArrays may support fast indexing with AbstractUnitRanges,
340353
# so we may just forward the indexing to the parent
341354
# This may only be done for non-offset ranges, as the result would otherwise have offset axes
342355
const OneBasedRanges = Union{OneTo{Int}, UnitRange{Int}, Slice{OneTo{Int}}, IdentityUnitRange{OneTo{Int}}}
343356
function getindex(V::FastContiguousSubArray, i::OneBasedRanges)
344357
@inline
345358
@boundscheck checkbounds(V, i)
346-
@inbounds r = V.parent[V.offset1 .+ i]
359+
@inbounds r = V.parent[_reindexlinear(V, i)]
347360
r
348361
end
349362

350-
# For vector views with linear indexing, we disambiguate to favor the stride/offset
351-
# computation as that'll generally be faster than (or just as fast as) re-indexing into a range.
352-
function getindex(V::FastSubArray{<:Any, 1}, i::Int)
353-
@inline
354-
@boundscheck checkbounds(V, i)
355-
@inbounds r = V.parent[V.offset1 + V.stride1*i]
356-
r
357-
end
358-
function getindex(V::FastContiguousSubArray{<:Any, 1}, i::Int)
359-
@inline
360-
@boundscheck checkbounds(V, i)
361-
@inbounds r = V.parent[V.offset1 + i]
362-
r
363-
end
364363
@inline getindex(V::FastContiguousSubArray, i::Colon) = getindex(V, to_indices(V, (:,))...)
365364

366365
# Indexed assignment follows the same pattern as `getindex` above
@@ -373,40 +372,23 @@ end
373372
function setindex!(V::FastSubArray, x, i::Int)
374373
@inline
375374
@boundscheck checkbounds(V, i)
376-
@inbounds V.parent[V.offset1 + V.stride1*i] = x
375+
@inbounds V.parent[_reindexlinear(V, i)] = x
377376
V
378377
end
379-
function setindex!(V::FastContiguousSubArray, x, i::Int)
378+
function setindex!(V::FastSubArray{<:Any, 1}, x, i::Int)
380379
@inline
381380
@boundscheck checkbounds(V, i)
382-
@inbounds V.parent[V.offset1 + i] = x
381+
@inbounds V.parent[_reindexlinear(V, i)] = x
383382
V
384383
end
384+
385385
function setindex!(V::FastSubArray, x, i::AbstractUnitRange{Int})
386386
@inline
387387
@boundscheck checkbounds(V, i)
388-
@inbounds V.parent[V.offset1 .+ V.stride1 .* i] = x
389-
V
390-
end
391-
function setindex!(V::FastContiguousSubArray, x, i::AbstractUnitRange{Int})
392-
@inline
393-
@boundscheck checkbounds(V, i)
394-
@inbounds V.parent[V.offset1 .+ i] = x
388+
@inbounds V.parent[_reindexlinear(V, i)] = x
395389
V
396390
end
397391

398-
function setindex!(V::FastSubArray{<:Any, 1}, x, i::Int)
399-
@inline
400-
@boundscheck checkbounds(V, i)
401-
@inbounds V.parent[V.offset1 + V.stride1*i] = x
402-
V
403-
end
404-
function setindex!(V::FastContiguousSubArray{<:Any, 1}, x, i::Int)
405-
@inline
406-
@boundscheck checkbounds(V, i)
407-
@inbounds V.parent[V.offset1 + i] = x
408-
V
409-
end
410392
@inline setindex!(V::FastSubArray, x, i::Colon) = setindex!(V, x, to_indices(V, (i,))...)
411393

412394
function isassigned(V::SubArray{T,N}, I::Vararg{Int,N}) where {T,N}
@@ -418,25 +400,13 @@ end
418400
function isassigned(V::FastSubArray, i::Int)
419401
@inline
420402
@boundscheck checkbounds(Bool, V, i) || return false
421-
@inbounds r = isassigned(V.parent, V.offset1 + V.stride1*i)
422-
r
423-
end
424-
function isassigned(V::FastContiguousSubArray, i::Int)
425-
@inline
426-
@boundscheck checkbounds(Bool, V, i) || return false
427-
@inbounds r = isassigned(V.parent, V.offset1 + i)
403+
@inbounds r = isassigned(V.parent, _reindexlinear(V, i))
428404
r
429405
end
430406
function isassigned(V::FastSubArray{<:Any, 1}, i::Int)
431407
@inline
432408
@boundscheck checkbounds(Bool, V, i) || return false
433-
@inbounds r = isassigned(V.parent, V.offset1 + V.stride1*i)
434-
r
435-
end
436-
function isassigned(V::FastContiguousSubArray{<:Any, 1}, i::Int)
437-
@inline
438-
@boundscheck checkbounds(Bool, V, i) || return false
439-
@inbounds r = isassigned(V.parent, V.offset1 + i)
409+
@inbounds r = isassigned(V.parent, _reindexlinear(V, i))
440410
r
441411
end
442412

0 commit comments

Comments
 (0)