diff --git a/base/range.jl b/base/range.jl index 65190707928e5..a02eed68034a4 100644 --- a/base/range.jl +++ b/base/range.jl @@ -35,6 +35,15 @@ immutable Range1{T<:Real} <: Ranges{T} end Range1{T}(start::T, len::Integer) = Range1{T}(start, len) +immutable FloatRange{T<:FloatingPoint} <: Ranges{T} + start::T + step::T + divisor::T + len::T +end +FloatRange(a::FloatingPoint, s::FloatingPoint, d::FloatingPoint, l::Real) = + FloatRange{promote_type(typeof(a),typeof(s),typeof(d))}(a,s,d,l) + function colon{T<:Integer}(start::T, step::T, stop::T) step != 0 || error("step cannot be zero in colon syntax") Range{T}(start, step, max(0, 1 + fld(stop-start, step))) @@ -59,7 +68,7 @@ end function colon{T<:Real}(start::T, step::T, stop::T) step != 0 || error("step cannot be zero in colon syntax") - if (step<0) != (stop 0 @@ -156,18 +198,16 @@ function getindex(r::Ranges, s::Ranges{Int}) end end -function show(io::IO, r::Range) - if step(r) == 0 - print(io, "Range(",r.start,",",step(r),",",r.len,")") - else - print(io, repr(r.start),':',repr(step(r)),':',repr(last(r))) - end +function show(io::IO, r::Union(Range,FloatRange)) + step(r) == 0 ? invoke(show,(IO,Any),r) : + print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) end -show(io::IO, r::Range1) = print(io, repr(r.start),':',repr(last(r))) +show(io::IO, r::Range1) = print(io, repr(first(r)), ':', repr(last(r))) start(r::Ranges) = 0 -next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1) +next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1) next{T}(r::Range1{T}, i) = (oftype(T, r.start + i), i+1) +next{T}(r::FloatRange{T}, i) = (oftype(T, (r.start + i*r.step)/r.divisor), i+1) done(r::Ranges, i) = (length(r) <= i) # though these look very similar to the above, for some reason LLVM generates @@ -176,7 +216,7 @@ start{T<:Integer}(r::Range1{T}) = r.start next{T<:Integer}(r::Range1{T}, i) = (i, oftype(T, i+1)) done{T<:Integer}(r::Range1{T}, i) = i==oftype(T, r.start+r.len) -==(r::Ranges, s::Ranges) = (r.start==s.start) & (step(r)==step(s)) & (r.len==s.len) +==(r::Ranges, s::Ranges) = (first(r)==first(s)) & (step(r)==step(s)) & (length(r)==length(s)) ==(r::Range1, s::Range1) = (r.start==s.start) & (r.len==s.len) # TODO: isless? @@ -389,7 +429,8 @@ function vcat{T}(rs::Ranges{T}...) return a end -reverse{T<:Real}(r::Ranges{T}) = Range(last(r), -step(r), r.len) +reverse(r::Ranges) = Range(last(r), -step(r), r.len) +reverse(r::FloatRange) = FloatRange(last(r), -r.step, r.divisor, r.len) ## sorting ## diff --git a/test/random.jl b/test/random.jl index 3d2745df1edb0..a73222dbf8a06 100644 --- a/test/random.jl +++ b/test/random.jl @@ -6,12 +6,12 @@ @test minimum([rand(int32(1):int32(7^7)) for i = 1:100000]) > 0 @test(typeof(rand(false:true)) == Bool) -for T in (Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Int128, Uint128, Char, BigInt, - Float16, Float32, Float64, Rational{Int}) - r = rand(convert(T, 97):convert(T, 122)) +for T in (Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Int128, Uint128, + Char, BigInt, Float32, Float64, Rational{Int}) + r = rand(convert(T,97):convert(T,122)) @test typeof(r) == T @test 97 <= r <= 122 - r = rand(convert(T, 97):convert(T,2):convert(T, 122),2)[1] + r = rand(convert(T,97):convert(T,2):convert(T,122),2)[1] @test typeof(r) == T @test 97 <= r <= 122 @test mod(r,2)==1 diff --git a/test/ranges.jl b/test/ranges.jl index 9dabf23bd7ec3..ed00a06e9d1ee 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -150,3 +150,39 @@ let s = 0 end @test s == 2 end + +# tricky floating-point ranges + +@test 0.1:0.1:0.3 == [1:3]./10 +@test 0.0:0.1:0.3 == [0:3]./10 +@test 0.3:-0.1:-0.1 == [3:-1:-1]./10 +@test 0.1:-0.1:-0.3 == [1:-1:-3]./10 +@test 0.0:0.1:1.0 == [0:10]./10 +@test 0.0:-0.1:1.0 == [] +@test 0.0:0.1:-1.0 == [] +@test 0.0:-0.1:-1.0 == [0:-1:-10]./10 +@test 1.0:1/49:27.0 == [49:1323]./49 +@test 0.0:0.7:2.1 == [0:7:21]./10 +@test 0.0:1.1:3.3 == [0:11:33]./10 +@test 0.1:1.1:3.4 == [1:11:34]./10 +@test 0.0:1.3:3.9 == [0:13:39]./10 +@test 0.1:1.3:4.0 == [1:13:40]./10 +@test 1.1:1.1:3.3 == [11:11:33]./10 +@test 0.3:0.1:1.1 == [3:1:11]./10 + +@test 0.0:1.0:5.5 == [0:10:55]./10 +@test 0.0:-1.0:0.5 == [] +@test 0.0:1.0:0.5 == [0.0] + +@test prevfloat(0.1):0.1:0.3 == [prevfloat(0.1), 0.2, 0.3] +@test nextfloat(0.1):0.1:0.3 == [nextfloat(0.1), 0.2] +@test prevfloat(0.0):0.1:0.3 == [prevfloat(0.0), 0.1, 0.2, 0.3] +@test nextfloat(0.0):0.1:0.3 == [nextfloat(0.0), 0.1, 0.2, 0.3] +@test 0.1:0.1:prevfloat(0.3) == [0.1, 0.2] +@test 0.1:0.1:nextfloat(0.3) == [0.1, 0.2, nextfloat(0.3)] +@test 0.0:0.1:prevfloat(0.3) == [0.0, 0.1, 0.2] +@test 0.0:0.1:nextfloat(0.3) == [0.0, 0.1, 0.2, nextfloat(0.3)] +@test 0.1:prevfloat(0.1):0.3 == [0.1, 0.2, 0.3] +@test 0.1:nextfloat(0.1):0.3 == [0.1, 0.2] +@test 0.0:prevfloat(0.1):0.3 == [0.0, prevfloat(0.1), prevfloat(0.2), 0.3] +@test 0.0:nextfloat(0.1):0.3 == [0.0, nextfloat(0.1), nextfloat(0.2)]