-
-
Notifications
You must be signed in to change notification settings - Fork 15
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 Base.OneTo(::StaticInt)
#41
base: master
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #41 +/- ##
==========================================
- Coverage 98.11% 97.91% -0.21%
==========================================
Files 8 8
Lines 478 479 +1
==========================================
Hits 469 469
- Misses 9 10 +1
Continue to review full report at Codecov.
|
The problem is function vcat(rs::AbstractRange{T}...) where T
n::Int = 0
for ra in rs
n += length(ra)
end
a = Vector{T}(undef, n)
i = 1
for ra in rs, x in ra
@inbounds a[i] = x
i += 1
end
return a
end |
Seems odd to overwrite and arrays |
I was hoping to get to a statically-sized interval. The benefit of |
Oh but this isn't good julia> myrange = Base.OneTo(static(3))
Base.OneTo(static(3))
julia> typeof(myrange)
OneTo{StaticInt{3}}
julia> supertype(ans)
AbstractUnitRange{StaticInt{3}} I think the right solution might be to create a new range type allowing start and end to have different types, and make things like |
Hmm, it looks like ArrayInterface also covers this, with lots of type piracy. Is there a reason this code should be there instead of here? |
I just haven't figured out how to cleanly disentangle those types from methods specific to ArrayInterface. |
From this Base.:(:)(L::Integer, ::StaticInt{U}) where {U} = OptionallyStaticUnitRange(L, StaticInt(U))
Base.:(:)(::StaticInt{L}, U::Integer) where {L} = OptionallyStaticUnitRange(StaticInt(L), U)
function Base.:(:)(::StaticInt{L}, ::StaticInt{U}) where {L,U}
return OptionallyStaticUnitRange(StaticInt(L), StaticInt(U))
end I'd think Maybe we do that, and then make Base.OneTo(s::StaticInt{N}) where {N} = static(1):s What do you think? |
I think it makes total sense to have those defined in the same place. But then we also need to move @propagate_inbounds function Base.getindex(
r::OptionallyStaticUnitRange,
s::AbstractUnitRange{<:Integer},
)
@boundscheck checkbounds(r, s)
f = ArrayInterface.static_first(r)
fnew = f - one(f)
return (fnew+ArrayInterface.static_first(s)):(fnew+ArrayInterface.static_last(s))
end |
Why not have
Does the refactoring ever hit a point like this? |
That's exactly what I ran into when I tried to hash this out one afternoon. I was actually trying to do a PR to Base and then realized that I didn't have the time to really sell StaticInt along with everything else. This JuliaArrays/ArrayInterface.jl#211 (comment) recent comment briefly tells why I've dragged my feet on figuring out where to put everything. |
I don't want to derail that discussion, but this is painful:
I believe it, but... ouch. We need a way to be sure some things are evaluated statically, and the type system (with generated functions) seems like the only way to go. I had assumed this would become idiomatic and gain support - the alternative is kind of scary. |
As I later comment in that issue, I think it's unclear what the implications of that comment are for developers. Even if we should be able to propagate size information, what if you want to specialize on 4x4 arrays? If that's not a trait then is it supposed to be an implementation as an additional pass in the compiler? That's gonna be rough for anyone that wants to write very exact matrix manipulations without spending some serious time learning how the compiler works. |
@cscherrer we have proper range construction here now. Does that solve the issue motivating this PR |
Fixes #40
This is not yet ready to go, because