-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Allow multidimensional array indexing with any eltype #12273
Conversation
@@ -316,7 +316,7 @@ to_index(c::Colon) = c | |||
to_index(I::AbstractArray{Bool}) = find(I) | |||
to_index(A::AbstractArray{Int}) = A | |||
to_index{T<:Integer}(A::AbstractArray{T}) = [to_index(x) for x in A] | |||
to_index(i) = error("invalid index: $i") | |||
to_index(i) = i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose doing it this way makes for some less intelligible error messages. We could be a little less lenient and keep the error, and add to_index(i::AbstractArray) = i
.
Ref #10525 (comment) and cc @timholy, @tlycken |
Nice! I had some test breakage in Interpolations.jl only yesterday because I tried to do something like |
Nope, same error still:
I think the problem is that since we allow indexing with
What would be the best way to fix this? Do we need to add a method in Interpolations.jl, or should something rather be changed in base? |
Ah, shucks. Of course. This would require dispatch on complements of The other thing I realized is that you may run into trouble with element types since interpolating doesn't always return the |
This doesn't seem like a viable long-term solution, so I'll just hold off on it for now. But it would be awesome if base could learn to handle these things :)
We've gone quite some length to make sure that the |
In Interpolations, if we want to make use of the fallbacks in #10525 we should probably restrict the index type to I approve of this PR. |
I want to simplify things here a bit further before this gets merged. |
This enables the use of the multidimensional abstract array indexing fallbacks for all element types. In particular, this fixes #12271: `A[[]]`. It also allows indexing with `A[Any[1,2,3]]`. I think this is a good direction in general, since we simply index through the array and pass along the elements to a scalar indexing method. If the `AbstractArray` subtype doesn't support indexing with those elements, then it'll throw an error there. But I think this starts allowing fancier capabilities in packages, like indexing with an array of Dual numbers.
I think the behavior here is more flexible and gives better error messages at the same time: ```jl julia> A[[]] 0-element Array{Int64,1} julia> A[im] ERROR: indexing Array{Int64,3} with types Tuple{Complex{Bool}} is not supported in error at ./error.jl:21 in getindex at abstractarray.jl:463 julia> A[[im]] ERROR: ArgumentError: unable to check bounds for indices of type Complex{Bool} in getindex at abstractarray.jl:463 julia> A[Vector[[1,2],[3,4]]] ERROR: ArgumentError: invalid index: Array{T,1}[[1,2],[3,4]] in getindex at abstractarray.jl:463 ```
f74d4a9
to
47e24ec
Compare
Ok, this is much better now: julia> A[[]]
0-element Array{Int64,1}
julia> A[im]
ERROR: indexing Array{Int64,3} with types Tuple{Complex{Bool}} is not supported
in error at ./error.jl:21
in getindex at abstractarray.jl:463
julia> A[[im]]
ERROR: ArgumentError: unable to check bounds for indices of type Complex{Bool}
in getindex at abstractarray.jl:463
julia> A[Vector[[1,2],[3,4]]]
ERROR: ArgumentError: invalid index: Array{T,1}[[1,2],[3,4]]
in getindex at abstractarray.jl:463 We're still not quite at the point where we can support any element types for non-scalar indexing. The goals of scalar and non-scalar indexing fallbacks are slightly different. Scalar indexing:
Non-scalar indexing:
For non-scalar indexing, we don't really care what the element types of the index arrays are... except for that hoisted Anyhow, that's an aside and a project for another time... and really just notes for my future self. |
checkbounds(A, I...) | ||
unsafe_getindex(A, sub2ind(size(A), to_indexes(I...)...)) | ||
J = to_indexes(I...) | ||
checkbounds(A, J...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing the check before calling to_indexes
is better-optimized for logical indexing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, but this is scalar indexing so I<:Tuple{Vararg{Real}}
. It's something that I think we can get rid of once float indices are no longer supported, but that will take some thought about what to do with non-Int
integers. We'll still want to convert small unsigned integers to Int
before doing sub2ind arithmetic... and ideally also allow larger integers, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point---I was still remembering the original thinking behind this code and not noticing what it had become. Great work as always.
Ready to merge? |
Yup! |
Allow multidimensional array indexing with any eltype
This enables the use of the multidimensional abstract array indexing fallbacks for all element types. In particular, this fixes #12271:
A[[]]
. It also allows indexing withA[Any[1,2,3]]
. I think this is a good direction in general, since we simply index through the array and pass along the elements to a scalar indexing method. If theAbstractArray
subtype doesn't support indexing with those elements, then it'll throw an error there. But I think this starts allowing fancier capabilities in packages, like indexing with an array of Dual numbers.