Skip to content

Commit

Permalink
Fix computation of range length in certain cases (fix 0.5/#20373)
Browse files Browse the repository at this point in the history
This is the 0.5 edition: with this change a, b, n are always hit
exactly by a:s:a+n*s construction tests. There are two parts to
the fix: 1) check that the lifted rational endpoint is exact even
*after* we've reduced terms of the fractions; 2) apply the same
fix that I've proposed for the length in the non-lifted case.
  • Loading branch information
StefanKarpinski committed Feb 2, 2017
1 parent 6a1e339 commit 990ddf6
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
7 changes: 5 additions & 2 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,16 @@ 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))
len = max(0, floor(r) + 1)
stop′ = start + len*step
len += (start < stop′ <= stop) + (start > stop′ >= stop)
FloatRange{T}(start, step, len, one(step))
end

colon{T<:AbstractFloat}(a::T, b::T) = colon(a, one(a), b)
Expand Down
19 changes: 19 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,25 @@ 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)
@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

0 comments on commit 990ddf6

Please sign in to comment.