Skip to content

Commit

Permalink
Fix computation of range length in certain cases (fix #20373) (#20377)
Browse files Browse the repository at this point in the history
Linspace construction fails on 32-bit systems, a failure mode uncovered by the new tests added in this change, but not caused by the change. Thus the failing tests are disabled and/or commented out to be fixed in another PR.
  • Loading branch information
StefanKarpinski authored Feb 8, 2017
1 parent e2cceb6 commit e849169
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
5 changes: 3 additions & 2 deletions base/twiceprecision.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ end

function colon{T<:Union{Float16,Float32,Float64}}(start::T, step::T, stop::T)
step == 0 && throw(ArgumentError("range step cannot be zero"))
len = max(0, floor(Int, (stop-start)/step) + 1)
# Because len might be too small by 1 due to roundoff error, let's
# see if the inputs have exact rational approximations (and if so,
# perform all computations in terms of the rationals)
step_n, step_d = rat(step)
Expand All @@ -149,6 +147,9 @@ function colon{T<:Union{Float16,Float32,Float64}}(start::T, step::T, stop::T)
end
end
# Fallback, taking start and step literally
len = max(0, floor(Int, (stop-start)/step) + 1)
stop′ = start + len*step
len += (start < stop′ <= stop) + (start > stop′ >= stop)
StepRangeLen(TwicePrecision(start, zero(T)), twiceprecision(step, nbitslen(T, len, 1)), len)
end

Expand Down
23 changes: 23 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,29 @@ for T = (Float32, Float64,),# BigFloat),
@test [r[n:-2:1];] == [r;][n:-2:1]
end

# issue #20373 (unliftable ranges with exact end points)
@test [3*0.05:0.05:0.2;] == [linspace(3*0.05,0.2,2);] == [3*0.05,0.2]
@test [0.2:-0.05:3*0.05;] == [linspace(0.2,3*0.05,2);] == [0.2,3*0.05]
@test [-3*0.05:-0.05:-0.2;] == [linspace(-3*0.05,-0.2,2);] == [-3*0.05,-0.2]
@test [-0.2:0.05:-3*0.05;] == [linspace(-0.2,-3*0.05,2);] == [-0.2,-3*0.05]

for T = (Float32, Float64,), i = 1:2^15, n = 1:5
start, step = randn(T), randn(T)
stop = start + (n-1)*step
r = start:step:stop
@test n == length(r)
# FIXME: these fail some small portion of the time
@test_skip start == first(r)
@test_skip stop == last(r)
# FIXME: linspace construction fails on 32-bit
Sys.WORD_SIZE == 64 || continue
l = linspace(start,stop,n)
@test n == length(l)
# FIXME: these fail some small portion of the time
@test_skip start == first(l)
@test_skip stop == last(l)
end

# linspace & ranges with very small endpoints
for T = (Float32, Float64)
z = zero(T)
Expand Down

0 comments on commit e849169

Please sign in to comment.