-
Notifications
You must be signed in to change notification settings - Fork 152
overload Base.rest #844
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
overload Base.rest #844
Conversation
Thanks, that's interesting. Could you also add a method for |
Co-authored-by: Mateusz Baran <[email protected]>
I don't think that we can implement this for |
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, awesome, thanks. :)
Could you make this instead for generic
StaticVector
using similar_type
and decrementing the length appropriately?
I’m not sure about matrices, etc, any ideas?
I've changed your implementation to @inline Base.rest(a::SizedArray{S}, st=(nothing, 0)) where S = SizedVector{StaticArrays.tuple_prod(S)-st[2]}(Base.rest(Tuple(a), st[2] + 1))
@inline Base.rest(a::SArray, st=(nothing, 0)) = SVector(Base.rest(Tuple(a), st[2] + 1))
@inline Base.rest(a::MArray, st=(nothing, 0)) = MVector(Base.rest(Tuple(a), st[2] + 1)) and it constant-propagates fine? julia> using StaticArrays
julia> @inline Base.rest(a::SizedArray{S}, st=(nothing, 0)) where S = SizedVector{StaticArrays.tuple_prod(S)-st[2]}(Base.rest(Tuple(a), st[2] + 1))
julia> @inline Base.rest(a::SArray, st=(nothing, 0)) = SVector(Base.rest(Tuple(a), st[2] + 1))
julia> @inline Base.rest(a::MArray, st=(nothing, 0)) = MVector(Base.rest(Tuple(a), st[2] + 1))
julia> as = SizedMatrix{2,2}([1 2; 3 4])
2×2 SizedMatrix{2, 2, Int64, 2, Matrix{Int64}} with indices SOneTo(2)×SOneTo(2):
1 2
3 4
julia> function ff(sss); a, b... = sss; return sum(b); end
ff (generic function with 1 method)
julia> ff(as)
9
julia> @code_typed ff(as)
CodeInfo(
1 ─ %1 = Base.getfield(sss, :data)::Matrix{Int64}
│ Base.arrayref(true, %1, 1)::Int64
│ %3 = Base.getfield(sss, :data)::Matrix{Int64}
│ Base.arrayref(false, %3, 1)::Int64
│ %5 = Base.getfield(sss, :data)::Matrix{Int64}
│ %6 = Base.arrayref(false, %5, 2)::Int64
│ %7 = Base.getfield(sss, :data)::Matrix{Int64}
│ %8 = Base.arrayref(false, %7, 3)::Int64
│ %9 = Base.getfield(sss, :data)::Matrix{Int64}
│ %10 = Base.arrayref(false, %9, 4)::Int64
│ %11 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Vector{Int64}, svec(Any, Int64), 0, :(:ccall), Vector{Int64}, 3, 3))::Vector{Int64}
│ Base.arrayset(false, %11, %6, 1)::Vector{Int64}
│ Base.arrayset(false, %11, %8, 2)::Vector{Int64}
│ Base.arrayset(false, %11, %10, 3)::Vector{Int64}
│ %15 = Base.arrayref(false, %11, 1)::Int64
│ %16 = Base.arrayref(false, %11, 2)::Int64
│ %17 = Base.add_int(%15, %16)::Int64
│ %18 = Base.arrayref(false, %11, 3)::Int64
│ %19 = Base.add_int(%17, %18)::Int64
└── return %19
) => Int64 |
Ah, I didn't look into this closely enough. I thought
Is converting |
I am not sure, what assumtion
The way it's implemented in Base, |
Until recently it just wrapped a normal
As far as I know you get the same specializations unless you operate on the wrapped array. Converting to Currently, at least for me, the main reason to use EDIT: "should be surprising" -> "should not be surprising" |
And one more thing, you need to propagate the element type to the constructor to make it work for static arrays of length 1: @inline Base.rest(a::SizedArray{S}, st=(nothing, 0)) where {S,T} = SizedVector{StaticArrays.tuple_prod(S)-st[2],T}(Base.rest(Tuple(a), st[2] + 1))
@inline Base.rest(a::SArray{S,T}, st=(nothing, 0)) where {S,T} = SVector{StaticArrays.tuple_prod(S)-st[2],T}(Base.rest(Tuple(a), st[2] + 1))
@inline Base.rest(a::MArray{S,T}, st=(nothing, 0)) where {S,T} = MVector{StaticArrays.tuple_prod(S)-st[2],T}(Base.rest(Tuple(a), st[2] + 1)) julia> a, b... = SA[1]
1-element SVector{1, Int64} with indices SOneTo(1):
1
julia> b
0-element SVector{0, Int64} with indices SOneTo(0) I think you should add this as a test case. |
Hmm, the MacOS runner seems to be hanging during Pkg setup... |
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.
This is nice; it's also very close to the generic version I requested. Instead of worrying about loops over concrete types it should just be:
@inline function Base.rest(a::StaticArray, (_, i) = (nothing, 0))
newlen = StaticArrays.tuple_prod(Size(a)) - i
return similar_type(typeof(a), Size(newlen))(Base.rest(Tuple(a), i + 1))
end
The purpose of |
See my comment above. The problem with that is that it would make the specific implementation of |
It already is! :) By default If someone wanted to specialize a static array that is a bit different they surely could but I'd expect them to overide many of the provided methods, including To be clear - I am very thankful that you are considering such cases, but there is so much work to be done to properly support |
0a5f949
to
c2c47b5
Compare
Things like iteration currently fail for SizedArrays with offset axes, so I think it's better to error right array. See JuliaArrays#844 (comment)
Things like iteration currently fail for SizedArrays with offset axes, so I think it's better to error right array. See JuliaArrays#844 (comment)
Co-authored-by: Mateusz Baran <[email protected]>
Bump. Can this be merged? |
Things like iteration currently fail for SizedArrays with offset axes, so I think it's better to error right array. See #844 (comment)
This makes the new lhs slurping syntax return an
S/MVector
if the rhs is anS/MArray
. See JuliaLang/julia#37410