-
Notifications
You must be signed in to change notification settings - Fork 150
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
Fix #556, use IdentityUnitRange in place of Base.Slice #568
Conversation
Rebase to base fork
Okay, so I think the travis tests fail because the type of |
I just started looking into this myself from the PkgEval failures in JuliaLang/julia#30374 (comment) — this is the root cause of the AstroLib failure over there. This seems to be a good fix. My first attempt at a fix (before finding this PR) was to peel back things at a lower level. We could inform Base that Regarding the fact that Edit: Oh, my last paragraph is wrong. |
src/abstractarray.jl
Outdated
@@ -126,9 +126,10 @@ similar(::Type{A}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray | |||
similar(::A,::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray,T} = similar(A, T, Size(last.(shape))) | |||
similar(::Type{A},::Type{T}, shape::Tuple{SOneTo, Vararg{SOneTo}}) where {A<:AbstractArray,T} = similar(A, T, Size(last.(shape))) | |||
|
|||
const SOneToLike{n} = Union{SOneTo{n}, Base.Slice{SOneTo{n}}} | |||
const SOneToLike{n} = Union{Integer, SOneTo{n}, IdentityUnitRange{SOneTo{n}}} |
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 don't think I'd include Integer
here — if you want to get a static array from an indexing slice, then I think you should have to use a static array of indices to do so.
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.
If I don't include it, the method similar(::Type{A},::Type{T}, shape::Tuple{SOneToLike, Vararg{SOneToLike}})
in line 134 will not get dispatched to by the similar
call from base (which is the origin of the error here), and the whole thing stops working. This seems to be the approach suggested in Base, I think. Check https://github.com/JuliaLang/julia/blob/e83693749032d28e9f5f0f75695fad46729ea2b4/base/abstractarray.jl#L581 and surrounding code/comments.
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.
Ah, right, of course. We need dispatch on a Tuple with at least one SOneTo
to accomplish what we want here, which of course we cannot currently express (directly).
Here's what I think I'd do, in pseudocode:
const PossiblyStaticAxis = Union{Integer, OneTo, SOneTo, IdentityUnitRange{<:SOneTo}}
similar(…, ::Tuple{PossiblyStaticAxis, Vararg{PossiblyStaticAxis}}) = static_similar(…)
static_similar(…, ::Tuple{SOneTo, Vararg{SOneTo}}) = actually_static_similar(…)
static_similar(…, ::Tuple{Any, Vararg{Any}}) = similar(…, map(length, …))
I think that should do the trick — and hopefully make things work much better all around. The method tables of similar
are disastrously messy, so this is indeed quite hard.
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.
Yeah, I confess I struggle a bit getting my head around this :-). Thanks for your suggestion Matt. Feel free to take over this PR if you want. Otherwise I'll implement your suggestion tomorrow and report back.
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.
The problem with the modification you propose, as far as I can see, is that it only dispatches to actually_static_similar
those shapes that are all SOneTo
. The original PR first converts each PossiblyStaticAxis
element of shape
into an integer (the size along each direction), regardless of whether it is an SOneTo
, and IdentityUnitRange
or an actual Int
. It then transforms it into a Size
and proceeds.
Another little problem is that I think OneTo
needs not be a subtype of PossiblyStaticAxis
, as it gets converted to and Int
in base, before getting here. After playing with it for a while I've sort of convinced myself that the current PR is probably ok, without considerably reworking the design.
One of the problems of the current design, it seems to me, is the difficulty of making it yield and MArray
when shape
is an NTuple{Int}
, which is why s[1:2, 1:2] isa Array
instead of returning an MArray
as I think it should. If I try to add a specific dispatch for this, like
similar(::SA, ::Type{T}, shape::Tuple{Integer, Vararg{Integer}}) where {SA<:StaticArray,T} = similar(SA, T, Size(shape))
I run into an ambiguity with the default similar
method fallback in base similar(a::AbstractArray, ::Type{T}, dims::Dims{N})
.
EDIT: Scratch that, it's as easy as doing
similar(::SA, ::Type{T}, shape::Base.Dims) where {SA<:StaticArray,T} = similar(SA, T, Size(shape))
I added this to the current PR, which now has this nice added bonus
julia> s = @SArray[1 2; 3 4]
2×2 SArray{Tuple{2,2},Int64,2,4}:
1 2
3 4
julia> s[1:2, 1:1]
2×1 MArray{Tuple{2,1},Int64,2,2}:
1
3
This restructures the similar method table along the lines that I suggested in JuliaArrays#568 (comment). I also used a bit of internals magic to match how the Base `OneTo` operates -- this is a little fragile but I think it is a good way to replicate how `OneTo` works.
@mbauman : Oops, didn't realise you had began another PR on this and I pushed another commit. No problem, go ahead and close this when you are satisfied. Do have a look at my reply above, particularly to the possibility of returning an |
Closing in favor of #569 |
This restructures the similar method table along the lines that I suggested in JuliaArrays#568 (comment). I also used a bit of internals magic to match how the Base `OneTo` operates -- this is a little fragile but I think it is a good way to replicate how `OneTo` works.
This restructures the similar method table along the lines that I suggested in #568 (comment). I also used a bit of internals magic to match how the Base `OneTo` operates -- this is a little fragile but I think it is a good way to replicate how `OneTo` works.
This is my attempt to fix #556, using OffsetArrays/#62 and the
similar
code in base/abstractarrays.jl as inspiration. My understanding of the underlying Slice/IdentityUnitRange mechanisms is a bit sketchy, so please review with some care (@timholy)With this PR, the cases in #556 (
s[:, 1:1]
ands[:, [true, false]]
) both work and yieldMArray
s. In the 0.7 days, this resulted in anArray
so I'm assuming we've improved over 0.7?However
s[1:2, 1:1]
always yields anArray
, both in 0.7, 1.1 and with this PR. This suggests to me that work is perhaps not complete here.