Skip to content

Commit

Permalink
Merge pull request #20396 from JuliaLang/sk/frfix0.5
Browse files Browse the repository at this point in the history
[release-0.5] Fix computation of range length in certain cases (fix 0.5/#20373)
  • Loading branch information
tkelman authored Mar 1, 2017
2 parents b08227b + 03f5df7 commit 7f1e1a0
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
14 changes: 12 additions & 2 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,23 @@ function colon{T<:AbstractFloat}(start::T, step::T, stop::T)
a *= div(e,b)
c *= div(e,d)
eT = convert(T,e)
if (a+n*c)/eT == stop
if a/eT == start && (a+n*c)/eT == stop
return FloatRange{T}(a, c, n+1, eT)
end
end
end
end
FloatRange{T}(start, step, floor(r)+1, one(step))
if r < 0
len = 0
elseif r == 0
len = 1
else
len = round(Int, r) + 1
stop′ = start + (len-1)*step
# if we've overshot the end, subtract one:
len -= (start < stop < stop′) + (start > stop > stop′)
end
FloatRange{T}(start, step, len, one(step))
end

colon{T<:AbstractFloat}(a::T, b::T) = colon(a, one(a), b)
Expand Down
27 changes: 27 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,33 @@ 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)
step == 0 && continue
stop = start + (n-1)*step
# `n` is not necessarily unique s.t. `start + (n-1)*step == stop`
# so test that `length(start:step:stop)` satisfies this identity
# and is the closest value to `(stop-start)/step` to do so
lo = hi = n
while start + (lo-1)*step == stop; lo -= 1; end
while start + (hi-1)*step == stop; hi += 1; end
m = clamp(round(Int, (stop-start)/step) + 1, lo+1, hi-1)
r = start:step:stop
@test m == length(r)
@test start == first(r)
@test stop == last(r)
l = linspace(start,stop,n)
@test n == length(l)
@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

2 comments on commit 7f1e1a0

@tkelman
Copy link
Contributor Author

@tkelman tkelman commented on 7f1e1a0 Mar 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at commit 7f1e1a0: @nanosoldier runbenchmarks(ALL, vs = "@3c9d75391c72d7c32eea75ff187ce77b2d5effc8")

the previous commit was mostly okay, aside from conversion a lot of the slowdowns were just above the noise threshold (though they're like that persistently, which is worrying)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

Please sign in to comment.