Skip to content
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

range() fails for some UInt64 lengths #57113

Open
ajalexei opened this issue Jan 21, 2025 · 1 comment
Open

range() fails for some UInt64 lengths #57113

ajalexei opened this issue Jan 21, 2025 · 1 comment
Labels
ranges Everything AbstractRange

Comments

@ajalexei
Copy link

range command seems to misbehave when UInt64 length argument is used:

julia> range(0.1, 5.0, UInt64(101))
ERROR: InexactError: UInt64(-1.0)
Stacktrace:
  [1] UInt64
    @ ./float.jl:973 [inlined]
  [2] convert
    @ ./number.jl:7 [inlined]
  [3] _round_convert
    @ ./rounding.jl:480 [inlined]
  [4] round
    @ ./rounding.jl:479 [inlined]
  [5] round
    @ ./rounding.jl:477 [inlined]
  [6] _linspace(::Type{Float64}, start_n::Int64, stop_n::Int64, len::UInt64, den::Int64)
    @ Base ./twiceprecision.jl:721
  [7] range_start_stop_length(start::Float64, stop::Float64, len::UInt64)
    @ Base ./twiceprecision.jl:660
  [8] _range
    @ ./range.jl:167 [inlined]
  [9] range(start::Float64, stop::Float64, length::UInt64)
    @ Base ./range.jl:151
 [10] top-level scope
    @ REPL[53]:1

The problem seem to disappear if:

  1. range(0, 5.0, UInt64(71)) works but range(0, 5.0, UInt64(81)) fails with the similar message as above
  2. 0.1 is replaced with 0: range(0, 5.0, UInt64(101)) -- works fine
  3. UInt64 is replaced with UInt32 (maybe larger lengths are needed)

Julia version:

julia> versioninfo()
Julia Version 1.11.2
Commit 5e9a32e7af2 (2024-12-01 20:02 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin24.0.0)
  CPU: 8 × Apple M1
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)

The problem also replicates on an x86_64 machine.

@inkydragon inkydragon added the ranges Everything AbstractRange label Jan 21, 2025
@christiangnrd
Copy link
Contributor

I looked into this and it works for UInt32 because lengths of types < 64 bit get promoted to Int64 from line 646 of base/twiceprecision:

function range_start_stop_length(start::T, stop::T, len::Integer) where {T<:IEEEFloat}
len = len + 0 # promote with Int
len < 2 && return _linspace1(T, start, stop, len)
if start == stop
return steprangelen_hp(T, start, zero(T), 0, len, 1)
end
# Attempt to find exact rational approximations
start_n, start_d = rat(start)
stop_n, stop_d = rat(stop)
if start_d != 0 && stop_d != 0
den = lcm_unchecked(start_d, stop_d)
m = maxintfloat(T, Int)
if den != 0 && abs(den*start) <= m && abs(den*stop) <= m
start_n = round(Int, den*start)
stop_n = round(Int, den*stop)
if T(start_n/den) == start && T(stop_n/den) == stop
return _linspace(T, start_n, stop_n, len, den)
end
end
end
_linspace(start, stop, len)
end

I tried to haveimin converted to L after clamping, but that still leaves different but related bugs with things like negative starting values with unsigned lengths so I don't think that's the correct solution and will let people more familiar with the code figure out the best way to solve this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ranges Everything AbstractRange
Projects
None yet
Development

No branches or pull requests

3 participants