You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I expect firstindex(v::AbstractVector) to be the same as as first(axes(v, 1)) and to have the same type as lastindex(v), but this example (adapted from sorting tests) violates that expectation:
struct T
n::Int8end
Base.zero(::T) =T(0)
Base.convert(::Type{T}, n::Integer) =T(Int8(n))
Base.isless(a::T, b::T) =isless(a.n, b.n)
Base.:(-)(a::T, b::T) =T(a.n - b.n)
Base.:(+)(a::T, b::T) =T(a.n + b.n)
Base.:(*)(n::Integer, a::T) =T(n * a.n)
Base.rem(a::T, b::T) =T(rem(a.n, b.n))
# The important part of this test is that the return type of length might be different from Int
Base.length(r::StepRange{T,T}) =Int8((last(r).n -first(r).n +1) ÷step(r).n)
x =T(1):T(3)
println(typeof(first(axes(x, 1)))) # Int8println(typeof(last(axes(x, 1)))) # Int8println(typeof(firstindex(x))) # Int64println(typeof(lastindex(x))) # Int8
If this is indeed a bug, we can probably fix it by changing this
IIUC, these methods was introduced for performance. Keeping the result is a better choice.
However, performance remains a problem: one(eltype(axes1(r))) is almost equivalent with the the general firstindex for AbstractArray. UnitRange and LinRange have simple length, thus no problem. length(::StepRange) is somehow too complex. we might need
functionfirstindex(::StepRange{T1,T2}) where {T1<:HWReal,T2<:HWReal}
sizeof(T1) <sizeof(Int) &&return1returnend
to make sure there's no regression.
Edit: div(one(T1), one(T2)) might not be the correct way. as length(::StepRange) is not stable sometime.
For example, @code_warntype length(StepRange(1,Int128(1),1)). We need to fix that first.
Ah, I was surprised and disappointed to find that one(eltype(axes1(x))) does not compile to a constant.
Ideally, length, axes1, firstindex, and lastindex are all stable.
If length (and therefore axes1 and lastindex) are unstable, however, then firstindex should also be unstable (e.g. use the general firstindex for AbstractArray).
I think generic methods and the compiler already efficiently handle the type stable case, so these optimizations are no longer necessary in that case, and only make a difference when lastindex is unstable, a difference that is buggy in my opinion.
I expect
firstindex(v::AbstractVector)
to be the same as asfirst(axes(v, 1))
and to have the same type aslastindex(v)
, but this example (adapted from sorting tests) violates that expectation:If this is indeed a bug, we can probably fix it by changing this
julia/base/range.jl
Line 691 in 6e06132
to
or similar (and doing the same for the subsequent two lines).
The text was updated successfully, but these errors were encountered: