Skip to content

Support for general index types #27

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

Merged
merged 11 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
*.jl.mem
deps/deps.jl
.DS_Store
Manifest.toml
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
name = "QuasiArrays"
uuid = "c4ea9172-b204-11e9-377d-29865faadc5c"
authors = ["Sheehan Olver <[email protected]>"]
version = "0.1.1"
version = "0.2"

[deps]
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[compat]
ArrayLayouts = "0.1.4"
LazyArrays = "0.14.7, 0.15"
ArrayLayouts = "0.1.5"
LazyArrays = "0.15"
julia = "1.3"

[extras]
Expand Down
4 changes: 2 additions & 2 deletions src/QuasiArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Base: @_inline_meta, DimOrInd, OneTo, @_propagate_inbounds_meta, @_noinli
import Base: ViewIndex, Slice, IdentityUnitRange, ScalarIndex, RangeIndex, view, viewindexing, ensure_indexable, index_dimsum,
check_parent_index_match, reindex, _isdisjoint, unsafe_indices, _unsafe_ind2sub,
_ind2sub, _sub2ind, _ind2sub_recurse, _lookup, SubArray,
parentindices, reverse, ndims, checkbounds,
parentindices, reverse, ndims, checkbounds, uncolon,
promote_shape, maybeview, checkindex, checkbounds_indices,
throw_boundserror, rdims, replace_in_print_matrix, show,
hcat, vcat, hvcat
Expand Down Expand Up @@ -47,7 +47,7 @@ import Base.IteratorsMD
export AbstractQuasiArray, AbstractQuasiMatrix, AbstractQuasiVector, materialize,
QuasiArray, QuasiMatrix, QuasiVector, QuasiDiagonal, Inclusion,
QuasiAdjoint, QuasiTranspose, ApplyQuasiArray, ApplyQuasiMatrix, ApplyQuasiVector,
BroadcastQuasiArray, BroadcastQuasiMatrix, BroadcastQuasiVector
BroadcastQuasiArray, BroadcastQuasiMatrix, BroadcastQuasiVector, indextype

if VERSION < v"1.3-"
"""
Expand Down
155 changes: 50 additions & 105 deletions src/abstractquasiarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ convert(::Type{AbstractArray{T,N}}, a::AbstractQuasiArray{<:Any,N}) where {T,N}
convert(::Type{AbstractMatrix}, a::AbstractQuasiMatrix) = convert(AbstractArray, a)
convert(::Type{AbstractVector}, a::AbstractQuasiVector) = convert(AbstractArray, a)


indextype(A::AbstractQuasiArray) = Tuple{map(eltype, axes(A))...}


"""
Expand Down Expand Up @@ -218,8 +218,8 @@ end
keys(s::IndexStyle, A::AbstractQuasiArray, B::AbstractQuasiArray...) = eachindex(s, A, B...)

"""
lastindex(collection) -> Number
lastindex(collection, d) -> Number
lastindex(collection) -> index
lastindex(collection, d) -> index

Return the last index of `collection`. If `d` is given, return the last index of `collection` along dimension `d`.

Expand All @@ -239,8 +239,8 @@ lastindex(a::AbstractQuasiArray) = (@_inline_meta; last(eachindex(IndexLinear(),
lastindex(a::AbstractQuasiArray, d) = (@_inline_meta; last(axes(a, d)))

"""
firstindex(collection) -> Number
firstindex(collection, d) -> Number
firstindex(collection) -> index
firstindex(collection, d) -> index

Return the first index of `collection`. If `d` is given, return the first index of `collection` along dimension `d`.

Expand All @@ -259,7 +259,7 @@ firstindex(a::AbstractQuasiArray, d) = (@_inline_meta; first(axes(a, d)))
first(a::AbstractQuasiArray) = a[first(eachindex(a))]
stride(A::AbstractQuasiArray, k::Integer) = strides(A)[k]

function isassigned(a::AbstractQuasiArray, i::Number...)
function isassigned(a::AbstractQuasiArray, i...)
try
a[i...]
true
Expand All @@ -277,11 +277,6 @@ function checkbounds(::Type{Bool}, A::AbstractQuasiArray, I...)
checkbounds_indices(Bool, axes(A), I)
end

# Linear indexing is explicitly allowed when there is only one (non-cartesian) index
function checkbounds(::Type{Bool}, A::AbstractQuasiArray, i)
@_inline_meta
checkindex(Bool, eachindex(IndexLinear(), A), i)
end
# As a special extension, allow using logical arrays that match the source array exactly
function checkbounds(::Type{Bool}, A::AbstractQuasiArray{<:Any,N}, I::AbstractQuasiArray{Bool,N}) where N
@_inline_meta
Expand All @@ -291,7 +286,7 @@ end

function checkbounds(A::AbstractQuasiArray, I...)
@_inline_meta
checkbounds(Bool, A, I...) || throw_boundserror(A, I)
checkbounds(Bool, A, to_indices(A,I)...) || throw_boundserror(A, I)
nothing
end

Expand All @@ -302,11 +297,11 @@ similar(a::AbstractQuasiArray, ::Type{T}) where {T} = simila
similar(a::AbstractQuasiArray{T}, dims::Tuple) where {T} = similar(a, T, dims)
similar(a::AbstractQuasiArray{T}, dims::QuasiDimOrInd...) where {T} = similar(a, T, dims)
similar(a::AbstractQuasiArray, ::Type{T}, dims::QuasiDimOrInd...) where {T} = similar(a, T, dims)
similar(::Type{<:AbstractQuasiArray{T}}, shape::NTuple{N,AbstractQuasiOrVector{<:Number}}) where {N,T} =
similar(::Type{<:AbstractQuasiArray{T}}, shape::NTuple{N,AbstractQuasiOrVector}) where {N,T} =
QuasiArray{T,N}(undef, convert.(AbstractVector, shape))
similar(a::AbstractQuasiArray, ::Type{T}, dims::NTuple{N,AbstractQuasiOrVector{<:Number}}) where {T,N} =
similar(a::AbstractQuasiArray, ::Type{T}, dims::NTuple{N,AbstractQuasiOrVector}) where {T,N} =
QuasiArray{T,N}(undef, convert.(AbstractVector, dims))
similar(a::AbstractQuasiArray, ::Type{T}, dims::Vararg{AbstractQuasiOrVector{<:Number},N}) where {T,N} =
similar(a::AbstractQuasiArray, ::Type{T}, dims::Vararg{AbstractQuasiOrVector,N}) where {T,N} =
QuasiArray{T,N}(undef, convert.(AbstractVector, dims))

similar(a::AbstractQuasiArray{T}, m::Int) where {T} = Vector{T}(undef, m)
Expand Down Expand Up @@ -376,56 +371,45 @@ end

isempty(a::AbstractQuasiArray) = (length(a) == 0)

function getindex(A::AbstractQuasiArray, I...)
getindex(A::AbstractQuasiArray, I...) = _getindex(indextype(A), A, I)

function _getindex(::Type{IND}, A::AbstractQuasiArray, I) where IND
@_propagate_inbounds_meta
error_if_canonical_getindex(IndexStyle(A), A, I...)
_getindex(IndexStyle(A), A, to_indices(A, I)...)
error_if_canonical_getindex(IndexStyle(A), A, I)
_getindex(IND, IndexStyle(A), A, to_indices(A, I))
end
function unsafe_getindex(A::AbstractQuasiArray, I...)
@_inline_meta
@inbounds r = getindex(A, I...)
r
end

error_if_canonical_getindex(::IndexLinear, A::AbstractQuasiArray, ::Number) =
error("getindex not defined for ", typeof(A))
error_if_canonical_getindex(::IndexCartesian, A::AbstractQuasiArray{T,N}, ::Vararg{Number,N}) where {T,N} =
error("getindex not defined for ", typeof(A))
error_if_canonical_getindex(::IndexStyle, ::AbstractQuasiArray, ::Any...) = nothing

## Internal definitions
_getindex(::IndexStyle, A::AbstractQuasiArray, I...) = lazy_getindex(A, I...)
_getindex(_, ::IndexStyle, A::AbstractQuasiArray, I) = lazy_getindex(A, I...)

## IndexLinear Scalar indexing: canonical method is one Int
_getindex(::IndexLinear, A::AbstractQuasiArray, i::Number) = (@_propagate_inbounds_meta; getindex(A, i))
function _getindex(::IndexLinear, A::AbstractQuasiArray, I::Vararg{Number,M}) where M
@_inline_meta
@boundscheck checkbounds(A, I...) # generally _to_linear_index requires bounds checking
@inbounds r = getindex(A, _to_linear_index(A, I...))
r
end
_to_linear_index(A::AbstractQuasiArray, i::Number) = i
_to_linear_index(A::AbstractQuasiVector, i::Number, I::Number...) = i
_to_linear_index(A::AbstractQuasiArray) = 1
_to_linear_index(A::AbstractQuasiArray, I::Number...) = (@_inline_meta; _sub2ind(A, I...))

## IndexCartesian Scalar indexing: Canonical method is full dimensionality of Numbers
function _getindex(::IndexCartesian, A::AbstractQuasiArray, I::Vararg{Number,M}) where M
## IndexCartesian Scalar indexing: Canonical method is full dimensionality of indices
function _getindex(::Type{IND}, ::IndexCartesian, A::AbstractQuasiArray, I::IND) where {M,IND}
@_inline_meta
@boundscheck checkbounds(A, I...) # generally _to_subscript_indices requires bounds checking
@inbounds r = getindex(A, _to_subscript_indices(A, I...)...)
r
end
function _getindex(::IndexCartesian, A::AbstractQuasiArray{T,N}, I::Vararg{Number, N}) where {T,N}
@_propagate_inbounds_meta
getindex(A, I...)
end
_to_subscript_indices(A::AbstractQuasiArray, i::Number) = (@_inline_meta; _unsafe_ind2sub(A, i))

error_if_canonical_getindex(::IndexCartesian, A::AbstractQuasiArray{T,N}, I::Tuple) where {T,N} =
_error_if_canonical_getindex(indextype(A), A, I)

_error_if_canonical_getindex(::Type{IND}, A::AbstractQuasiArray{T,N}, I::IND) where {T,N,IND} =
error("getindex not defined for ", typeof(A))

_error_if_canonical_getindex(::Type, ::AbstractQuasiArray, ::Any...) = nothing

_to_subscript_indices(A::AbstractQuasiArray, i) = (@_inline_meta; _unsafe_ind2sub(A, i))
_to_subscript_indices(A::AbstractQuasiArray{T,N}) where {T,N} = (@_inline_meta; fill_to_length((), 1, Val(N)))
_to_subscript_indices(A::AbstractQuasiArray{T,0}) where {T} = ()
_to_subscript_indices(A::AbstractQuasiArray{T,0}, i::Number) where {T} = ()
_to_subscript_indices(A::AbstractQuasiArray{T,0}, I::Number...) where {T} = ()
function _to_subscript_indices(A::AbstractQuasiArray{T,N}, I::Number...) where {T,N}
_to_subscript_indices(A::AbstractQuasiArray{T,0}, i) where {T} = ()
_to_subscript_indices(A::AbstractQuasiArray{T,0}, I...) where {T} = ()
function _to_subscript_indices(A::AbstractQuasiArray{T,N}, I...) where {T,N}
@_inline_meta
J, Jrem = IteratorsMD.split(I, Val(N))
_to_subscript_indices(A, J, Jrem)
Expand All @@ -437,51 +421,43 @@ function __to_subscript_indices(A::AbstractQuasiArray,
@_inline_meta
(J..., map(first, tail(_remaining_size(J, axes(A))))...)
end
_to_subscript_indices(A::AbstractQuasiArray{T,N}, I::Vararg{Number,N}) where {T,N} = I
_to_subscript_indices(A::AbstractQuasiArray{T,N}, I::Vararg{Any,N}) where {T,N} = I

## Setindex! is defined similarly. We first dispatch to an internal _setindex!
# function that allows dispatch on array storage


function setindex!(A::AbstractQuasiArray, v, I...)
@_propagate_inbounds_meta
error_if_canonical_setindex(IndexStyle(A), A, I...)
_setindex!(IndexStyle(A), A, v, to_indices(A, I)...)
error_if_canonical_setindex(IndexStyle(A), A, I)
_setindex!(indextype(A), IndexStyle(A), A, v, to_indices(A, I))
end
function unsafe_setindex!(A::AbstractQuasiArray, v, I...)
@_inline_meta
@inbounds r = setindex!(A, v, I...)
r
end

error_if_canonical_setindex(::IndexLinear, A::AbstractQuasiArray, ::Number) =
error("setindex! not defined for ", typeof(A))
error_if_canonical_setindex(::IndexCartesian, A::AbstractQuasiArray{T,N}, ::Vararg{Number,N}) where {T,N} =
error_if_canonical_setindex(::IndexCartesian, A::AbstractQuasiArray{T,N}, I::Tuple) where {T,N} =
_error_if_canonical_setindex(indextype(A), A, I)

_error_if_canonical_setindex(::Type{IND}, A::AbstractQuasiArray{T,N}, I::IND) where {T,N,IND} =
error("setindex! not defined for ", typeof(A))
error_if_canonical_setindex(::IndexStyle, ::AbstractQuasiArray, ::Any...) = nothing

_error_if_canonical_setindex(::Type, ::AbstractQuasiArray, ::Any...) = nothing
## Internal definitions
_setindex!(::IndexStyle, A::AbstractQuasiArray, v, I...) =
_setindex!(::Type, ::IndexStyle, A::AbstractQuasiArray, v, I) =
error("setindex! for $(typeof(A)) with types $(typeof(I)) is not supported")

## IndexLinear Scalar indexing
_setindex!(::IndexLinear, A::AbstractQuasiArray, v, i::Number) = (@_propagate_inbounds_meta; setindex!(A, v, i))
function _setindex!(::IndexLinear, A::AbstractQuasiArray, v, I::Vararg{Number,M}) where M
@_inline_meta
@boundscheck checkbounds(A, I...)
@inbounds r = setindex!(A, v, _to_linear_index(A, I...))
r
end

# IndexCartesian Scalar indexing
function _setindex!(::IndexCartesian, A::AbstractQuasiArray{T,N}, v, I::Vararg{Number, N}) where {T,N}
function _setindex!(::Type{IND}, ::IndexCartesian, A::AbstractQuasiArray{T,N}, v, I::NTuple{N,Any}) where {T,N,IND}
@_propagate_inbounds_meta
setindex!(A, v, I...)
end
function _setindex!(::IndexCartesian, A::AbstractQuasiArray, v, I::Vararg{Number,M}) where M
function _setindex!(::Type{IND}, ::IndexCartesian, A::AbstractQuasiArray, v, I::NTuple{M,Any}) where {M,IND}
@_inline_meta
@boundscheck checkbounds(A, I...)
@inbounds r = setindex!(A, v, _to_subscript_indices(A, I...)...)
@inbounds r = setindex!(A, v, _to_subscript_indices(IND, A, I...)...)
r
end

Expand Down Expand Up @@ -516,8 +492,8 @@ dataids(A::AbstractQuasiArray) = (UInt(objectid(A)),)


## structured matrix methods ##
replace_in_print_matrix(A::AbstractQuasiMatrix,i::Number,j::Number,s::AbstractString) = s
replace_in_print_matrix(A::AbstractQuasiVector,i::Number,j::Number,s::AbstractString) = s
replace_in_print_matrix(A::AbstractQuasiMatrix,i,j,s::AbstractString) = s
replace_in_print_matrix(A::AbstractQuasiVector,i,j,s::AbstractString) = s

## Concatenation ##
eltypeof(x::AbstractQuasiArray) = eltype(x)
Expand Down Expand Up @@ -565,45 +541,14 @@ function (==)(A::AbstractQuasiArray, B::AbstractQuasiArray)
return anymissing ? missing : true
end

# _sub2ind and _ind2sub
# fallbacks
function _sub2ind(A::AbstractQuasiArray, I...)
@_inline_meta
_sub2ind(axes(A), I...)
end

function _ind2sub(A::AbstractQuasiArray, ind)
@_inline_meta
_ind2sub(axes(A), ind)
end

# Vectorized forms
function _sub2ind(inds::Indices{1}, I1::AbstractQuasiVector{T}, I::AbstractQuasiVector{T}...) where T<:Number
throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays"))
end
_sub2ind(inds::Tuple{OneTo}, I1::AbstractQuasiVector{T}, I::AbstractQuasiVector{T}...) where {T<:Number} =
_sub2ind_vecs(inds, I1, I...)
_sub2ind(inds::Union{DimsInteger,Indices}, I1::AbstractQuasiVector{T}, I::AbstractQuasiVector{T}...) where {T<:Number} =
_sub2ind_vecs(inds, I1, I...)
function _sub2ind_vecs(inds, I::AbstractQuasiVector...)
I1 = I[1]
Iinds = axes1(I1)
for j = 2:length(I)
axes1(I[j]) == Iinds || throw(DimensionMismatch("indices of I[1] ($(Iinds)) does not match indices of I[$j] ($(axes1(I[j])))"))
end
Iout = similar(I1)
_sub2ind!(Iout, inds, Iinds, I)
Iout
end

_lookup(ind, r::Inclusion) = ind

_ind2sub(dims::NTuple{N,Number}, ind::Number) where N = (@_inline_meta; _ind2sub_recurse(dims, ind-1))
_ind2sub(inds::QuasiIndices, ind::Number) = (@_inline_meta; _ind2sub_recurse(inds, ind-1))
_ind2sub(inds::Tuple{Inclusion{<:Number},AbstractUnitRange{<:Integer}}, ind::Number) = (@_inline_meta; _ind2sub_recurse(inds, ind-1))
_ind2sub(inds::Tuple{AbstractUnitRange{<:Integer},Inclusion{<:Number}}, ind::Number) = (@_inline_meta; _ind2sub_recurse(inds, ind-1))
_ind2sub(dims::NTuple{N,Any}, ind) where N = (@_inline_meta; _ind2sub_recurse(dims, ind-1))
_ind2sub(inds::QuasiIndices, ind) = (@_inline_meta; _ind2sub_recurse(inds, ind-1))
_ind2sub(inds::Tuple{Inclusion{<:Any},AbstractUnitRange{<:Integer}}, ind) = (@_inline_meta; _ind2sub_recurse(inds, ind-1))
_ind2sub(inds::Tuple{AbstractUnitRange{<:Integer},Inclusion{<:Any}}, ind) = (@_inline_meta; _ind2sub_recurse(inds, ind-1))

function _ind2sub(inds::Union{NTuple{N,Number},QuasiIndices{N}}, ind::AbstractQuasiVector{<:Number}) where N
function _ind2sub(inds::Union{NTuple{N,Any},QuasiIndices{N}}, ind::AbstractQuasiVector) where N
M = length(ind)
t = ntuple(n->similar(ind),Val(N))
for (i,idx) in pairs(IndexLinear(), ind)
Expand Down
39 changes: 30 additions & 9 deletions src/indices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,23 @@ to_index(I::AbstractQuasiArray) = I
to_index(I::AbstractQuasiArray{<:Union{AbstractArray, Colon}}) =
throw(ArgumentError("invalid index: $I of type $(typeof(I))"))

to_quasi_index(i::Number) = i
to_quasi_index(i) = Base.to_index(i)
to_index(A::AbstractQuasiArray, i) = to_quasi_index(i)
to_quasi_index(::Type{IND}, i) where IND = convert(IND, i)
to_quasi_index(::Type{IND}, I::AbstractArray) where IND<:AbstractArray = convert(IND, I)
to_quasi_index(::Type{IND}, I::AbstractQuasiArray) where IND<:AbstractQuasiArray = convert(IND, I)
to_quasi_index(::Type{IND}, I::AbstractArray) where IND = convert(AbstractArray{IND}, I)
to_quasi_index(::Type{IND}, I::AbstractQuasiArray) where IND = convert(AbstractQuasiArray{IND}, I)
to_quasi_index(::Type{IND}, I::AbstractArray{<:AbstractArray}) where IND<:AbstractArray = convert(AbstractArray{IND}, I)
to_quasi_index(::Type{IND}, I::AbstractQuasiArray{<:AbstractArray}) where IND<:AbstractArray = convert(AbstractQuasiArray{IND}, I)

to_quasi_index(A, IND, i) = to_quasi_index(IND,i)

to_indices(A::AbstractQuasiArray, inds, ::Tuple{}) = ()
to_indices(A::AbstractQuasiArray, inds, I::Tuple{Any,Vararg{Any}}) =
(@_inline_meta; (to_quasi_index(A, eltype(inds[1]), I[1]), to_indices(A, _maybetail(inds), tail(I))...))
@inline to_indices(A::AbstractQuasiArray, inds, I::Tuple{Colon, Vararg{Any}}) =
(uncolon(inds, I), to_indices(A, _maybetail(inds), tail(I))...)



LinearIndices(A::AbstractQuasiArray) = LinearIndices(axes(A))

Expand Down Expand Up @@ -164,9 +178,9 @@ size(S::Inclusion) = (cardinality(S.domain),)
length(S::Inclusion) = cardinality(S.domain)
unsafe_length(S::Inclusion) = cardinality(S.domain)
cardinality(S::Inclusion) = cardinality(S.domain)
getindex(S::Inclusion{T}, i::Number) where T =
getindex(S::Inclusion{T}, i::T) where T =
(@_inline_meta; @boundscheck checkbounds(S, i); convert(T,i))
getindex(S::Inclusion{T}, i::AbstractVector{<:Number}) where T =
getindex(S::Inclusion{T}, i::AbstractVector{T}) where T =
(@_inline_meta; @boundscheck checkbounds(S, i); convert(AbstractVector{T},i))
getindex(S::Inclusion, i::Inclusion) =
(@_inline_meta; @boundscheck checkbounds(S, i); copy(S))
Expand All @@ -176,10 +190,10 @@ iterate(S::Inclusion, s...) = iterate(S.domain, s...)

in(x, S::Inclusion) = x in S.domain

checkindex(::Type{Bool}, inds::Inclusion, i::Number) = i ∈ inds.domain
checkindex(::Type{Bool}, inds::Inclusion, i) = i ∈ inds.domain
checkindex(::Type{Bool}, inds::Inclusion, ::Colon) = true
checkindex(::Type{Bool}, inds::Inclusion, ::Inclusion) = true
function checkindex(::Type{Bool}, inds::Inclusion, I::AbstractArray)
function __checkindex(::Type{Bool}, inds::Inclusion, I::AbstractArray)
@_inline_meta
b = true
for i in I
Expand All @@ -188,9 +202,16 @@ function checkindex(::Type{Bool}, inds::Inclusion, I::AbstractArray)
b
end

function checkindex(::Type{Bool}, inds::Inclusion, r::AbstractRange)
checkindex(::Type{Bool}, inds::Inclusion{T}, I::AbstractArray{T}) where T =
__checkindex(Bool, inds, I)
checkindex(::Type{Bool}, inds::Inclusion{T}, I::AbstractArray{T}) where T<:AbstractArray =
__checkindex(Bool, inds, I)
checkindex(::Type{Bool}, inds::Inclusion{T}, I::AbstractArray{<:AbstractArray}) where T<:AbstractArray =
__checkindex(Bool, inds, convert(AbstractArray{T}, I))

function checkindex(::Type{Bool}, inds::Inclusion{T}, r::AbstractRange) where T
@_propagate_inbounds_meta
isempty(r) | (checkindex(Bool, inds, first(r)) & checkindex(Bool, inds, last(r)))
isempty(r) | (checkindex(Bool, inds, convert(T, first(r))) & checkindex(Bool, inds, last(r)))
end
checkindex(::Type{Bool}, indx::Inclusion, I::AbstractVector{Bool}) = indx == axes1(I)
checkindex(::Type{Bool}, indx::Inclusion, I::AbstractArray{Bool}) = false
Loading