-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Add CheckIndexStyle trait for bounds-checking #42029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,6 +102,88 @@ IndexStyle(A::AbstractArray, B::AbstractArray...) = IndexStyle(IndexStyle(A), In | |
IndexStyle(::IndexLinear, ::IndexLinear) = IndexLinear() | ||
IndexStyle(::IndexStyle, ::IndexStyle) = IndexCartesian() | ||
|
||
|
||
abstract type CheckIndexStyle end | ||
""" | ||
Base.CheckIndexFirstLast() | ||
|
||
A [`Base.CheckIndexStyle`](@ref) trait-value indicating that bounds-checking | ||
only need test the first and last elements in an index vector. | ||
|
||
# Examples | ||
```jldoctest | ||
julia> r = 3:7; Base.CheckIndexStyle(r) | ||
Base.CheckIndexFirstLast() | ||
``` | ||
|
||
Ranges are declared `CheckIndexFirstLast` because `x[r]` can be tested | ||
for out-of-bounds indexing using just the first and last elements of `r`. | ||
|
||
See also [`Base.CheckIndexAll`](@ref) and [`Base.CheckIndexAxes`](@ref). | ||
""" | ||
struct CheckIndexFirstLast <: CheckIndexStyle end | ||
|
||
""" | ||
Base.CheckIndexAll() | ||
|
||
A [`Base.CheckIndexStyle`](@ref) trait-value indicating that bounds-checking | ||
must test all elements in an index vector. | ||
|
||
# Examples | ||
```jldoctest | ||
julia> idx = [3,4,5,6,7]; Base.CheckIndexStyle(idx) | ||
Base.CheckIndexAll() | ||
``` | ||
|
||
Since the entries in `idx` could be arbitrary, we have to check each | ||
entry for bounds violations. | ||
|
||
See also [`Base.CheckIndexFirstLast`](@ref) and [`Base.CheckIndexAxes`](@ref). | ||
""" | ||
struct CheckIndexAll <: CheckIndexStyle end | ||
|
||
""" | ||
Base.CheckIndexAxes() | ||
|
||
A [`CheckIndexStyle`](@ref) trait-value indicating that bounds-checking | ||
should consider the axes of the index rather than the values of the | ||
index. This is used in cases where the index acts as a filter to | ||
select elements. | ||
|
||
# Examples | ||
```jldoctest | ||
julia> idx = [true, false, true]; Base.CheckIndexStyle(idx) | ||
Base.CheckIndexAxes() | ||
``` | ||
|
||
When `idx` is used in `x[idx]`, it returns the entries in `x` | ||
corresponding to `true` entries in `idx`. Consequently, indexing | ||
should insist on `idx` and `x` having identical axes. | ||
|
||
See also [`Base.CheckIndexFirstLast`](@ref) and [`Base.CheckIndexAll`](@ref). | ||
""" | ||
struct CheckIndexAxes <: CheckIndexStyle end | ||
|
||
""" | ||
CheckIndexStyle(idx) | ||
CheckIndexStyle(typeof(idx)) | ||
|
||
`CheckIndexStyle` specifies how bounds-checking of `x[idx]` should be performed. | ||
Certain types of `idx`, such as ranges, may have particularly efficient ways | ||
to perform the bounds-checking. When you define a new [`AbstractArray`](@ref) type, | ||
you can choose to define a specific value for this trait: | ||
|
||
Base.CheckIndexStyle(::Type{<:MyRange}) = CheckIndexFirstLast() | ||
|
||
The default is [`CheckIndexAll()`](@ref), except for `AbstractVector`s with `Bool` | ||
`eltype` (which default to [`Base.CheckIndexAxes()`](@ref)) and subtypes of `AbstractRange` | ||
(which default to [`Base.CheckIndexFirstLast()`](@ref).) | ||
""" | ||
CheckIndexStyle(A::AbstractArray) = CheckIndexStyle(typeof(A)) | ||
CheckIndexStyle(::Type{Union{}}) = CheckIndexAll() | ||
CheckIndexStyle(::Type{<:AbstractArray{T}}) where T = T === Bool ? CheckIndexAxes() : CheckIndexAll() | ||
CheckIndexStyle(::Type{<:AbstractRange{T}}) where T = T === Bool ? CheckIndexAxes() : CheckIndexFirstLast() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we include things like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I follow. This checks the indexes, not the array you are indexing. So if we checked only the first and last elements of julia> a = [1, 2, 37, 4]
4-element Vector{Int64}:
1
2
37
4
julia> b = 1:4
1:4
julia> sa = view(a, :)
4-element view(::Vector{Int64}, :) with eltype Int64:
1
2
37
4
julia> isa(sa, Base.FastContiguousSubArray)
true
julia> b[sa]
ERROR: BoundsError: attempt to access 4-element UnitRange{Int64} at index [[1, 2, 37, 4]]
Stacktrace:
[1] throw_boundserror(A::UnitRange{Int64}, I::Tuple{SubArray{Int64, 1, Vector{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}}, true}})
@ Base ./abstractarray.jl:651
[2] checkbounds
@ ./abstractarray.jl:616 [inlined]
[3] _getindex
@ ./multidimensional.jl:831 [inlined]
[4] getindex(A::UnitRange{Int64}, I::SubArray{Int64, 1, Vector{Int64}, Tuple{Base.Slice{Base.OneTo{Int64}}}, true})
@ Base ./abstractarray.jl:1170
[5] top-level scope
@ REPL[6]:1 That said, special rules might apply to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The parent type would have to return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I think I get it, you mean if the index is a |
||
|
||
# array shape rules | ||
|
||
promote_shape(::Tuple{}, ::Tuple{}) = () | ||
|
Uh oh!
There was an error while loading. Please reload this page.