diff --git a/base/range.jl b/base/range.jl index 864eafa550480..4dd2467b9452f 100644 --- a/base/range.jl +++ b/base/range.jl @@ -382,6 +382,15 @@ function unsafe_getindex(r::FloatRange, s::OrdinalRange) FloatRange(r.start + (first(s)-1)*r.step, step(s)*r.step, length(s), r.divisor) end +function getindex{T}(r::LinSpace{T}, s::OrdinalRange) + sl::T = check_indexingrange(s, r) + ifirst = first(s) + ilast = last(s) + vfirst::T = ((r.len - ifirst) * r.start + (ifirst - 1) * r.stop) / r.divisor + vlast::T = ((r.len - ilast) * r.start + (ilast - 1) * r.stop) / r.divisor + return linspace(vfirst, vlast, sl) +end + function show(io::IO, r::Range) print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) end @@ -530,27 +539,34 @@ end -(r::OrdinalRange) = range(-r.start, -step(r), length(r)) -(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) +-(r::LinSpace) = LinSpace(-r.start, -r.stop, r.len, r.divisor) .+(x::Real, r::UnitRange) = range(x + r.start, length(r)) .+(x::Real, r::Range) = (x+first(r)):step(r):(x+last(r)) #.+(x::Real, r::StepRange) = range(x + r.start, r.step, length(r)) .+(x::Real, r::FloatRange) = FloatRange(r.divisor*x + r.start, r.step, r.len, r.divisor) +.+(x::Real, r::LinSpace) = LinSpace(x + r.start, x + r.stop, r.len, r.divisor) .+(r::Range, x::Real) = x + r #.+(r::FloatRange, x::Real) = x + r .-(x::Real, r::Range) = (x-first(r)):-step(r):(x-last(r)) .-(x::Real, r::FloatRange) = FloatRange(r.divisor*x - r.start, -r.step, r.len, r.divisor) +.-(x::Real, r::LinSpace) = LinSpace(x - r.start, x - r.stop, r.len, r.divisor) .-(r::UnitRange, x::Real) = range(r.start-x, length(r)) .-(r::StepRange , x::Real) = range(r.start-x, r.step, length(r)) .-(r::FloatRange, x::Real) = FloatRange(r.start - r.divisor*x, r.step, r.len, r.divisor) +.-(r::LinSpace, x::Real) = LinSpace(r.start - x, r.stop - x, r.len, r.divisor) .*(x::Real, r::OrdinalRange) = range(x*r.start, x*step(r), length(r)) .*(x::Real, r::FloatRange) = FloatRange(x*r.start, x*r.step, r.len, r.divisor) +.*(x::Real, r::LinSpace) = LinSpace(x * r.start, x * r.stop, r.len, r.divisor) .*(r::Range, x::Real) = x .* r .*(r::FloatRange, x::Real) = x .* r +.*(r::LinSpace, x::Real) = x .* r ./(r::OrdinalRange, x::Real) = range(r.start/x, step(r)/x, length(r)) ./(r::FloatRange, x::Real) = FloatRange(r.start/x, r.step/x, r.len, r.divisor) +./(r::LinSpace, x::Real) = LinSpace(r.start / x, r.stop / x, r.len, r.divisor) promote_rule{T1,T2}(::Type{UnitRange{T1}},::Type{UnitRange{T2}}) = UnitRange{promote_type(T1,T2)} @@ -581,6 +597,19 @@ convert{T}(::Type{FloatRange{T}}, r::OrdinalRange) = convert{T}(::Type{FloatRange}, r::OrdinalRange{T}) = FloatRange{typeof(float(first(r)))}(first(r), step(r), length(r), one(T)) +promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) = + LinSpace{promote_type(T1,T2)} +convert{T}(::Type{LinSpace{T}}, r::LinSpace{T}) = r +convert{T}(::Type{LinSpace{T}}, r::LinSpace) = + LinSpace{T}(r.start, r.stop, r.len, r.divisor) + +promote_rule{F,OR<:OrdinalRange}(::Type{LinSpace{F}}, ::Type{OR}) = + LinSpace{promote_type(F,eltype(OR))} +convert{T}(::Type{LinSpace{T}}, r::OrdinalRange) = + linspace(convert(T, first(r)), convert(T, last(r)), convert(T, length(r))) +convert{T}(::Type{LinSpace}, r::OrdinalRange{T}) = + convert(LinSpace{typeof(float(first(r)))}, r) + # +/- of ranges is defined in operators.jl (to be able to use @eval etc.) @@ -622,6 +651,7 @@ collect(r::Range) = vcat(r) reverse(r::OrdinalRange) = colon(last(r), -step(r), first(r)) reverse(r::FloatRange) = FloatRange(r.start + (r.len-1)*r.step, -r.step, r.len, r.divisor) +reverse(r::LinSpace) = LinSpace(r.stop, r.start, r.len, r.divisor) ## sorting ## diff --git a/test/ranges.jl b/test/ranges.jl index e4dcb20ddbd40..215b738f16eff 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -541,3 +541,47 @@ for x in r i += 2 end @test i == 7 + +# Issue 11049 and related +@test promote(linspace(0f0, 1f0, 3), linspace(0., 5., 2)) === + (linspace(0., 1., 3), linspace(0., 5., 2)) +@test convert(LinSpace{Float64}, linspace(0., 1., 3)) === linspace(0., 1., 3) +@test convert(LinSpace{Float64}, linspace(0f0, 1f0, 3)) === linspace(0., 1., 3) + +@test promote(linspace(0., 1., 3), 0:5) === (linspace(0., 1., 3), + linspace(0., 5., 6)) +@test convert(LinSpace{Float64}, 0:5) === linspace(0., 5., 6) +@test convert(LinSpace{Float64}, 0:1:5) === linspace(0., 5., 6) +@test convert(LinSpace, 0:5) === linspace(0., 5., 6) +@test convert(LinSpace, 0:1:5) === linspace(0., 5., 6) + +function test_range_index(r, s) + @test typeof(r[s]) == typeof(r) + @test [r;][s] == [r[s];] +end +test_range_index(linspace(0.1, 0.3, 3), 1:2) +test_range_index(linspace(0.1, 0.3, 3), 1:0) +test_range_index(linspace(1.0, 1.0, 1), 1:1) +test_range_index(linspace(1.0, 1.0, 1), 1:0) +test_range_index(linspace(1.0, 2.0, 0), 1:0) + +function test_linspace_identity(r, mr) + @test -r == mr + @test isa(-r, LinSpace) + + @test 1 + r + (-1) == r + @test isa(1 + r + (-1), LinSpace) + @test 1 - r - 1 == mr + @test isa(1 - r - 1, LinSpace) + + @test 1 * r * 1 == r + @test isa(1 * r * 1, LinSpace) + @test r / 1 == r + @test isa(r / 1, LinSpace) +end + +test_linspace_identity(linspace(1.0, 27.0, 1275), linspace(-1.0, -27.0, 1275)) + +@test reverse(linspace(1.0, 27.0, 1275)) == linspace(27.0, 1.0, 1275) +@test [reverse(linspace(1.0, 27.0, 1275));] == + reverse([linspace(1.0, 27.0, 1275);])