From ef3c6411055f4a42a02cd8dc346bf02c6d99ccd2 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 12 Mar 2014 17:20:31 -0400 Subject: [PATCH 01/11] alternate implementation of Range1 storing start,stop instead of start,len this Range1 could be the UnitRange of #5585, with Range1 deprecated also intended to address #5469 (performance) --- base/abstractarray.jl | 2 +- base/linalg/tridiag.jl | 4 +- base/range.jl | 103 ++++++++++++++++++++++------------------- test/core.jl | 4 -- test/ranges.jl | 29 +++--------- 5 files changed, 65 insertions(+), 77 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 24343feec8bef..1488ec497d4bb 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -322,7 +322,7 @@ full(x::AbstractArray) = x for fn in _numeric_conversion_func_names @eval begin $fn(r::Range ) = Range($fn(r.start), $fn(r.step), r.len) - $fn(r::Range1) = Range1($fn(r.start), r.len) + $fn(r::Range1) = Range1($fn(r.start), $fn(last(r))) $fn(r::FloatRange) = FloatRange($fn(r.start), $fn(r.step), r.len, $fn(r.divisor)) end end diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 46c58a81bac7f..ea768479393a5 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -309,7 +309,7 @@ function solve!(X::StridedMatrix, M::Tridiagonal, B::StridedMatrix) size(X) == size(B) || throw(DimensionMismatch("")) m, n = size(B) for j = 1:n - r = Range1((j-1)*m+1,m) + r = ((j-1)*m+1):((j-1)*m+m) solve!(X, r, M, B, r) end X @@ -346,7 +346,7 @@ function mult(X::StridedMatrix, M::Tridiagonal, B::StridedMatrix) size(X) == size(B) || throw(DimensionMismatch("")) m, n = size(B) for j = 1:n - r = Range1((j-1)*m+1,m) + r = ((j-1)*m+1):((j-1)*m+m) mult(X, r, M, B, r) end X diff --git a/base/range.jl b/base/range.jl index c81f43d2aa901..d36843223c80a 100644 --- a/base/range.jl +++ b/base/range.jl @@ -19,21 +19,13 @@ immutable Range{T<:Real} <: Ranges{T} end Range{T}(start::T, step, len::Integer) = Range{T}(start, step, len) -immutable Range1{T<:Real} <: Ranges{T} +immutable Range1{T} <: Ranges{T} start::T - len::Int - - function Range1(start::T, len::Int) - if len < 0; error("length must be non-negative"); end - new(start, len) - end - Range1(start::T, len::Integer) = Range1(start, int(len)) + stop::T - # TODO: this is a hack to elide the len<0 check for colon. - # should store start and stop for integer ranges instead - Range1(start::T, len::Integer, _) = new(start, int(len)) + Range1(start, stop) = new(start, ifelse(stop>=start, stop, oftype(T, start-1))) end -Range1{T}(start::T, len::Integer) = Range1{T}(start, len) +Range1{T}(start::T, stop::T) = Range1{T}(start, stop) immutable FloatRange{T<:FloatingPoint} <: Ranges{T} start::T @@ -88,23 +80,22 @@ function colon{T<:Real}(start::T, step::T, stop::T) end Range(start, step, len) end + function colon{T<:Real}(start::T, stop::T) - if stop < start - len = 0 - else + if T <: FloatingPoint nf = stop - start + 1 - if T <: FloatingPoint - n = round(nf) - len = abs(n-nf) < eps(n)*3 ? itrunc(n) : itrunc(nf) - else - n = nf - len = itrunc(n) + n = round(nf) + len = abs(n-nf) < eps(n)*3 ? itrunc(n) : itrunc(nf) + stop = oftype(start, start+(len-1)) + if stop == stop+1 + # Range1 doesn't work beyond maxintfloat + error("end point ", stop, " is too large for Range1") end if n >= typemax(Int) error("length ",n," is too large") end end - Range1(start, len) + Range1(start, stop) end colon(start::Real, step::Real, stop::Real) = colon(promote(start, step, stop)...) @@ -164,13 +155,25 @@ similar(r::Ranges, T::Type, dims::Dims) = Array(T, dims) length(r::Ranges) = integer(r.len) size(r::Ranges) = (length(r),) -isempty(r::Ranges) = r.len==0 first(r::Ranges) = r.start first(r::FloatRange) = r.start/r.divisor -last{T}(r::Range1{T}) = oftype(T, r.start + r.len-1) +last{T}(r::Range1{T}) = r.stop last{T}(r::Range{T}) = oftype(T, r.start + (r.len-1)*r.step) last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) +length{T<:Integer}(r::Range1{T}) = int(r.stop - r.start + 1) +length(r::Range1) = int(itrunc(r.stop - r.start)+1) + +if Int === Int32 + function length{T<:Union(Int8,Int16,Int32,Uint8,Uint16)}(r::Range1{T}) + checked_add(checked_sub(convert(Int,r.stop), convert(Int,r.start)), 1) + end +else + function length{T<:Union(Int8,Int16,Int32,Int64,Uint8,Uint16,Uint32)}(r::Range1{T}) + checked_add(checked_sub(convert(Int,r.stop), convert(Int,r.start)), 1) + end +end + step(r::Range) = r.step step(r::Range1) = one(r.start) step(r::FloatRange) = r.step/r.divisor @@ -183,39 +186,42 @@ maximum(r::Ranges) = isempty(r) ? error("range must be non-empty") : step(r) > 0 ctranspose(r::Ranges) = [x for _=1, x=r] transpose(r::Ranges) = r' -# Ranges are intended to be immutable +# Ranges are immutable copy(r::Ranges) = r getindex(r::Ranges, i::Real) = getindex(r, to_index(i)) function getindex{T}(r::Ranges{T}, i::Integer) - 1 <= i <= r.len || error(BoundsError) + 1 <= i <= length(r) || error(BoundsError) oftype(T, r.start + (i-1)*step(r)) end function getindex{T}(r::FloatRange{T}, i::Integer) - 1 <= i <= r.len || error(BoundsError) + 1 <= i <= length(r) || error(BoundsError) oftype(T, (r.start + (i-1)*r.step)/r.divisor) end function getindex(r::Range1, s::Range1{Int}) - if s.len > 0 - if !(1 <= last(s) <= r.len) + sl = length(s) + if sl > 0 + if !(1 <= last(s) <= length(r)) throw(BoundsError()) end - Range1(r[s.start], s.len) + st = r[s.start] else - Range1(r.start + s.start-1, s.len) + st = oftype(r.start, r.start + s.start-1) end + Range1(st, oftype(st,st+sl-1)) end function getindex(r::Ranges, s::Ranges{Int}) - if s.len > 0 - if !(1 <= last(s) <= r.len) + sl = length(s) + if sl > 0 + if !(1 <= last(s) <= length(r)) throw(BoundsError()) end - Range(r[s.start], step(r)*step(s), s.len) + Range(r[s.start], step(r)*step(s), sl) else - Range(r.start + (s.start-1)*step(r), step(r)*step(s), s.len) + Range(r.start + (s.start-1)*step(r), step(r)*step(s), sl) end end @@ -229,7 +235,6 @@ show{T<:FloatingPoint}(io::IO, r::Range{T}) = invoke(show, (IO,Any), io, r) start(r::Ranges) = 0 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) @@ -284,7 +289,7 @@ intersect{T<:Integer}(r::Range1{T}, i::Integer) = intersect(i, r) function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::Range{T2}) if length(s) == 0 - Range1(first(r), 0) + Range1(first(r), oftype(T1, first(r)-1)) elseif step(s) == 0 intersect(first(s), r) elseif step(s) < 0 @@ -398,38 +403,40 @@ end ## linear operations on ranges ## --(r::Ranges) = Range(-r.start, -step(r), r.len) +-(r::Ranges) = Range(-r.start, -step(r), length(r)) -(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) -+(x::Real, r::Range1) = Range1(x + r.start, r.len) ++(x::Real, r::Range1) = Range1(x + r.start, x + last(r)) +(x::Real, r::Range) = Range(x + r.start, r.step, r.len) +(x::Real, r::FloatRange) = FloatRange(r.divisor*x + r.start, r.step, r.len, r.divisor) +(r::Ranges, x::Real) = x + r +(r::FloatRange, x::Real) = x + r --(x::Real, r::Ranges) = Range(x - r.start, -step(r), r.len) +-(x::Real, r::Ranges) = Range(x - r.start, -step(r), length(r)) -(x::Real, r::FloatRange) = FloatRange(r.divisor*x - r.start, -r.step, r.len, r.divisor) --(r::Range1, x::Real) = Range1(r.start-x, r.len) +-(r::Range1, x::Real) = Range1(r.start-x, last(r)-x) -(r::Range , x::Real) = Range(r.start-x, r.step, r.len) -(r::FloatRange, x::Real) = FloatRange(r.start - r.divisor*x, r.step, r.len, r.divisor) -.*(x::Real, r::Ranges) = Range(x*r.start, x*step(r), r.len) +.*(x::Real, r::Ranges) = Range(x*r.start, x*step(r), length(r)) .*(x::Real, r::FloatRange) = FloatRange(x*r.start, x*r.step, r.len, r.divisor) .*(r::Ranges, x::Real) = x .* r .*(r::FloatRange, x::Real) = x .* r -./(r::Ranges, x::Real) = Range(r.start/x, step(r)/x, r.len) +./(r::Ranges, 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) # TODO: better implementations for FloatRanges? function +(r1::Ranges, r2::Ranges) - r1.len == r2.len || error("argument dimensions must match") - Range(r1.start+r2.start, step(r1)+step(r2), r1.len) + r1l = length(r1) + r1l == length(r2) || error("argument dimensions must match") + Range(r1.start+r2.start, step(r1)+step(r2), r1l) end function -(r1::Ranges, r2::Ranges) - r1.len == r2.len || error("argument dimensions must match") - Range(r1.start-r2.start, step(r1)-step(r2), r1.len) + r1l = length(r1) + r1l == length(r2) || error("argument dimensions must match") + Range(r1.start-r2.start, step(r1)-step(r2), r1l) end ## non-linear operations on ranges ## @@ -468,7 +475,7 @@ function vcat{T}(rs::Ranges{T}...) return a end -reverse(r::Ranges) = Range(last(r), -step(r), r.len) +reverse(r::Ranges) = Range(last(r), -step(r), length(r)) reverse(r::FloatRange) = FloatRange(last(r), -r.step, r.len, r.divisor) ## sorting ## diff --git a/test/core.jl b/test/core.jl index 9a5503d031908..4d8eb76ea5d9a 100644 --- a/test/core.jl +++ b/test/core.jl @@ -866,10 +866,6 @@ typealias Foo2919 Int type Baz2919; Foo2919::Foo2919; end @test Baz2919(3).Foo2919 === 3 -# issue #2959 -@test 1.0:1.5 == 1.0:1.0:1.5 == 1.0:1.0 -@test 1.0:(.3-.1)/.1 == 1.0:2.0 - # issue #2982 module M2982 abstract U diff --git a/test/ranges.jl b/test/ranges.jl index 9008ab0627474..21daef044a880 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -105,28 +105,9 @@ r = (-4*int64(maxintfloat(is(Int,Int32) ? Float32 : Float64))):5 @test length(1:4:typemax(Int)) == div(typemax(Int),4) + 1 # overflow in length -@test_throws 0:typemax(Int) -@test_throws typemin(Int):typemax(Int) -@test_throws -1:typemax(Int)-1 - -# parity between ranges and for loops (see issue #5355) - -@test length(2.0^53:(2.0^53+2)) == 3 -let s = 0 - r = 2.0^53:(2.0^53+2) - for i in r - s += 1 - @test s <= 3 - end - @test s == 3 - - s = 0 - for i in 2.0^53:(2.0^53+2) - s += 1 - @test s <= 3 - end - @test s == 3 -end +@test_throws length(0:typemax(Int)) +@test_throws length(typemin(Int):typemax(Int)) +@test_throws length(-1:typemax(Int)-1) let s = 0 # loops ending at typemax(Int) @@ -262,3 +243,7 @@ let end end end + +# issue #2959 +@test 1.0:1.5 == 1.0:1.0:1.5 == 1.0:1.0 +@test 1.0:(.3-.1)/.1 == 1.0:2.0 From 5ba25eaebc0a1d2db744fe7c28ca2b24768e4e79 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 18 Mar 2014 16:09:20 -0400 Subject: [PATCH 02/11] save checkin. at attempt to start on ordinal ranges (#5585) --- base/range.jl | 167 +++++++++++++++++++++----------------------------- 1 file changed, 69 insertions(+), 98 deletions(-) diff --git a/base/range.jl b/base/range.jl index d36843223c80a..111010ff77130 100644 --- a/base/range.jl +++ b/base/range.jl @@ -4,6 +4,10 @@ typealias Dims (Int...) abstract Ranges{T} <: AbstractArray{T,1} +## ordinal ranges + +abstract OrdinalRange{T,S} <: Ranges{T} + immutable Range{T<:Real} <: Ranges{T} start::T step::T @@ -19,14 +23,42 @@ immutable Range{T<:Real} <: Ranges{T} end Range{T}(start::T, step, len::Integer) = Range{T}(start, step, len) -immutable Range1{T} <: Ranges{T} - start::T - stop::T +# A StepRange has a start point, and moves by some step up through a last point. +# The element type is T, but we allow T+S to give a value from a lifted +# domain D instead of from T. We store a sentinel value stop+step from domain D, +# since T might not have any available sentinel value. +immutable StepRange{T,S,D} <: OrdinalRange{T,S} + start::D + sentinel::D + step::S + + StepRange(start, step, stop) = new(start, ifelse(stop>=start, stop+step, start), + step) +end + +StepRange{T,S}(start::T, step::S, stop::T) = + StepRange{T, S, typeof(stop+step)}(start, step, stop) + +immutable Range1{T<:Integer,D} <: OrdinalRange{T,Int} + start::D + sentinel::D - Range1(start, stop) = new(start, ifelse(stop>=start, stop, oftype(T, start-1))) + Range1(start, stop) = new(start, ifelse(stop>=start, stop+1, start)) end Range1{T}(start::T, stop::T) = Range1{T}(start, stop) +colon(a, b) = colon(promote(a,b)...) +colon(a::Real, b::Real, c::Real) = colon(promote(a,b,c)...) +colon(a, b, c) = colon(convert(promote_type(a,c),a), b, convert(promote_type(a,c),c)) + +colon{T<:Integer}(start::T, stop::T) = Range1{T}(start, stop) + +colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop) + +colon{T}(start::T, step, stop::T) = StepRange(start, step, stop) + +## floating point ranges + immutable FloatRange{T<:FloatingPoint} <: Ranges{T} start::T step::T @@ -36,71 +68,6 @@ end FloatRange(a::FloatingPoint, s::FloatingPoint, l::Real, d::FloatingPoint) = FloatRange{promote_type(typeof(a),typeof(s),typeof(d))}(a,s,l,d) -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))) -end - -colon{T<:Integer}(start::T, stop::T) = - Range1{T}(start, ifelse(stop 1 && abs(n-nf) < eps(n)*3 - # adjust step to try to hit stop exactly - step = (stop-start)/(n-1) - len = itrunc(n) - else - len = itrunc(nf) - end - else - n = nf - len = itrunc(n) - end - if n >= typemax(Int) - error("length ",n," is too large") - end - end - Range(start, step, len) -end - -function colon{T<:Real}(start::T, stop::T) - if T <: FloatingPoint - nf = stop - start + 1 - n = round(nf) - len = abs(n-nf) < eps(n)*3 ? itrunc(n) : itrunc(nf) - stop = oftype(start, start+(len-1)) - if stop == stop+1 - # Range1 doesn't work beyond maxintfloat - error("end point ", stop, " is too large for Range1") - end - if n >= typemax(Int) - error("length ",n," is too large") - end - end - Range1(start, stop) -end - -colon(start::Real, step::Real, stop::Real) = colon(promote(start, step, stop)...) -colon(start::Real, stop::Real) = colon(promote(start, stop)...) - # float rationalization helper function rat(x) y = x @@ -151,31 +118,31 @@ colon{T<:FloatingPoint}(start::T, step::T, stop::T) = (0 < step) != (start < stop) ? FloatRange{T}(start,step,0,1) : FloatRange{T}(frange(start,step,stop)...) +## interface implementations + similar(r::Ranges, T::Type, dims::Dims) = Array(T, dims) -length(r::Ranges) = integer(r.len) size(r::Ranges) = (length(r),) -first(r::Ranges) = r.start + +length(r::FloatRange) = r.len +length(r::StepRange) = itrunc((r.sentinal - r.start)/r.step) +length(r::Range1) = int(r.sentinel - r.start) +length(r::Range) = r.len + +first{T}(r::Ranges{T}) = oftype(T, r.start) first(r::FloatRange) = r.start/r.divisor -last{T}(r::Range1{T}) = r.stop + last{T}(r::Range{T}) = oftype(T, r.start + (r.len-1)*r.step) last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) +last{T}(r::OrdinalRange{T}) = oftype(T, r.sentinel-step(r)) -length{T<:Integer}(r::Range1{T}) = int(r.stop - r.start + 1) -length(r::Range1) = int(itrunc(r.stop - r.start)+1) - -if Int === Int32 - function length{T<:Union(Int8,Int16,Int32,Uint8,Uint16)}(r::Range1{T}) - checked_add(checked_sub(convert(Int,r.stop), convert(Int,r.start)), 1) - end -else - function length{T<:Union(Int8,Int16,Int32,Int64,Uint8,Uint16,Uint32)}(r::Range1{T}) - checked_add(checked_sub(convert(Int,r.stop), convert(Int,r.start)), 1) - end +function length(r::Range1{Int}) + checked_add(checked_sub(r.sentinel-1, r.start), 1) end step(r::Range) = r.step -step(r::Range1) = one(r.start) +step(r::StepRange) = r.step +step(r::Range1) = one(r.sentinel - r.start) step(r::FloatRange) = r.step/r.divisor minimum(r::Range1) = isempty(r) ? error("range must be non-empty") : first(r) @@ -189,6 +156,24 @@ transpose(r::Ranges) = r' # Ranges are immutable copy(r::Ranges) = r + +## iteration + +start(r::Ranges) = 0 +next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1) +done(r::Ranges, i) = (length(r) <= i) + +next{T}(r::FloatRange{T}, i) = (oftype(T, (r.start + i*r.step)/r.divisor), i+1) + +start(r::OrdinalRange) = r.start +next{T}(r::OrdinalRange{T}, i) = (oftype(T,i), i+step(r)) +done(r::OrdinalRange, i) = i==r.sentinel + +next{T,D}(r::Range1{T,D}, i) = (oftype(T,i), oftype(D, i+1)) + + +## indexing + getindex(r::Ranges, i::Real) = getindex(r, to_index(i)) function getindex{T}(r::Ranges{T}, i::Integer) @@ -233,20 +218,6 @@ show(io::IO, r::Range1) = print(io, repr(first(r)), ':', repr(last(r))) show{T<:FloatingPoint}(io::IO, r::Range{T}) = invoke(show, (IO,Any), io, r) -start(r::Ranges) = 0 -next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), 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 -# much better code for these. -start{T<:SmallInteger}(r::Range1{T}) = int(r.start) -next{T<:SmallInteger}(r::Range1{T}, i) = (oftype(T, i), i+1) -done{T<:SmallInteger}(r::Range1{T}, i) = i==r.start+r.len -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) - isequal{T<:Ranges}(r::T, s::T) = (first(r)==first(s)) & (step(r)==step(s)) & (length(r)==length(s)) From e733cf157aa0cc9a735b01d9a51971a5f7742c8b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 19 Mar 2014 03:08:40 -0400 Subject: [PATCH 03/11] nearly finish OrdinalRange still not clear what to do with floating point in StepRange --- base/abstractarray.jl | 16 +-- base/array.jl | 12 +- base/constants.jl | 2 +- base/exports.jl | 3 +- base/linalg/dense.jl | 4 +- base/linalg/tridiag.jl | 4 +- base/linalg/woodbury.jl | 2 +- base/multidimensional.jl | 4 +- base/random.jl | 8 +- base/range.jl | 240 +++++++++++++++++++-------------------- base/replutil.jl | 2 +- base/sort.jl | 10 +- base/statistics.jl | 14 +-- test/euler.jl | 2 +- test/ranges.jl | 37 +++--- 15 files changed, 179 insertions(+), 181 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 1488ec497d4bb..8af6bc4d45635 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -62,8 +62,8 @@ end checkbounds(sz::Int, i::Int) = 1 <= i <= sz || throw(BoundsError()) checkbounds(sz::Int, i::Real) = checkbounds(sz, to_index(i)) checkbounds(sz::Int, I::AbstractVector{Bool}) = length(I) == sz || throw(BoundsError()) -checkbounds(sz::Int, r::Ranges{Int}) = isempty(r) || (minimum(r) >= 1 && maximum(r) <= sz) || throw(BoundsError()) -checkbounds{T<:Real}(sz::Int, r::Ranges{T}) = checkbounds(sz, to_index(r)) +checkbounds(sz::Int, r::Range{Int}) = isempty(r) || (minimum(r) >= 1 && maximum(r) <= sz) || throw(BoundsError()) +checkbounds{T<:Real}(sz::Int, r::Range{T}) = checkbounds(sz, to_index(r)) function checkbounds{T <: Real}(sz::Int, I::AbstractArray{T}) for i in I @@ -321,7 +321,7 @@ full(x::AbstractArray) = x for fn in _numeric_conversion_func_names @eval begin - $fn(r::Range ) = Range($fn(r.start), $fn(r.step), r.len) + $fn(r::StepRange) = StepRange($fn(r.start), $fn(r.step), $fn(last(r))) $fn(r::Range1) = Range1($fn(r.start), $fn(last(r))) $fn(r::FloatRange) = FloatRange($fn(r.start), $fn(r.step), r.len, $fn(r.divisor)) end @@ -451,13 +451,13 @@ end ## get (getindex with a default value) ## -typealias RangeVecIntList{A<:AbstractVector{Int}} Union((Union(Ranges, AbstractVector{Int})...), AbstractVector{Range1{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}) +typealias RangeVecIntList{A<:AbstractVector{Int}} Union((Union(Range, AbstractVector{Int})...), AbstractVector{Range1{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}) get(A::AbstractArray, i::Integer, default) = in_bounds(length(A), i) ? A[i] : default get(A::AbstractArray, I::(), default) = similar(A, typeof(default), 0) get(A::AbstractArray, I::Dims, default) = in_bounds(size(A), I...) ? A[I...] : default -function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::Union(Ranges, AbstractVector{Int}), default::T) +function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::Union(Range, AbstractVector{Int}), default::T) ind = findin(I, 1:length(A)) X[ind] = A[I[ind]] X[1:first(ind)-1] = default @@ -465,7 +465,7 @@ function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::Union(Ranges, Abstrac X end -get(A::AbstractArray, I::Ranges, default) = get!(similar(A, typeof(default), length(I)), A, I, default) +get(A::AbstractArray, I::Range, default) = get!(similar(A, typeof(default), length(I)), A, I, default) function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::RangeVecIntList, default::T) fill!(X, default) @@ -823,7 +823,7 @@ function isequal(A::AbstractArray, B::AbstractArray) if size(A) != size(B) return false end - if isa(A,Ranges) != isa(B,Ranges) + if isa(A,Range) != isa(B,Range) return false end for i = 1:length(A) @@ -847,7 +847,7 @@ function (==)(A::AbstractArray, B::AbstractArray) if size(A) != size(B) return false end - if isa(A,Ranges) != isa(B,Ranges) + if isa(A,Range) != isa(B,Range) return false end for i = 1:length(A) diff --git a/base/array.jl b/base/array.jl index 988f5697cc9d0..b5493091e34b2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -118,11 +118,11 @@ end getindex(T::(Type...)) = Array(T,0) # T[a:b] and T[a:s:b] also contruct typed ranges -function getindex{T<:Number}(::Type{T}, r::Ranges) +function getindex{T<:Number}(::Type{T}, r::Range) copy!(Array(T,length(r)), r) end -function getindex{T<:Number}(::Type{T}, r1::Ranges, rs::Ranges...) +function getindex{T<:Number}(::Type{T}, r1::Range, rs::Range...) a = Array(T,length(r1)+sum(length,rs)) o = 1 copy!(a, o, r1) @@ -261,10 +261,10 @@ end function getindex{T<:Real}(A::Array, I::AbstractVector{T}) return [ A[i] for i in to_index(I) ] end -function getindex{T<:Real}(A::Ranges, I::AbstractVector{T}) +function getindex{T<:Real}(A::Range, I::AbstractVector{T}) return [ A[i] for i in to_index(I) ] end -function getindex(A::Ranges, I::AbstractVector{Bool}) +function getindex(A::Range, I::AbstractVector{Bool}) checkbounds(A, I) return [ A[i] for i in to_index(I) ] end @@ -716,7 +716,7 @@ for f in (:+, :-, :div, :mod, :&, :|, :$) return F end # interaction with Ranges - function ($f){S,T<:Real}(A::StridedArray{S}, B::Ranges{T}) + function ($f){S,T<:Real}(A::StridedArray{S}, B::Range{T}) F = similar(A, promote_type(S,T), promote_shape(size(A),size(B))) i = 1 for b in B @@ -725,7 +725,7 @@ for f in (:+, :-, :div, :mod, :&, :|, :$) end return F end - function ($f){S<:Real,T}(A::Ranges{S}, B::StridedArray{T}) + function ($f){S<:Real,T}(A::Range{S}, B::StridedArray{T}) F = similar(B, promote_type(S,T), promote_shape(size(A),size(B))) i = 1 for a in A diff --git a/base/constants.jl b/base/constants.jl index 29e4d57a715f3..a0f1f522267d8 100644 --- a/base/constants.jl +++ b/base/constants.jl @@ -68,7 +68,7 @@ const golden = φ for T in (MathConst, Rational, Integer, Number) ^(::MathConst{:e}, x::T) = exp(x) end -for T in (Ranges, BitArray, SparseMatrixCSC, StridedArray, AbstractArray) +for T in (Range, BitArray, SparseMatrixCSC, StridedArray, AbstractArray) .^(::MathConst{:e}, x::T) = exp(x) end ^(::MathConst{:e}, x::AbstractMatrix) = expm(x) diff --git a/base/exports.jl b/base/exports.jl index 901cd5b42ab7c..ecc08f29c12ad 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -70,6 +70,7 @@ export Matrix, MergeSort, ObjectIdDict, + OrdinalRange, PollingFileWatcher, ProcessGroup, QR, @@ -78,7 +79,6 @@ export Range, Range1, RangeIndex, - Ranges, Rational, Regex, RegexMatch, @@ -97,6 +97,7 @@ export SharedArray, SparseMatrixCSC, StatStruct, + StepRange, StridedArray, StridedMatrix, StridedVecOrMat, diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index fdb7bec2b0840..f0baa2752784d 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -70,9 +70,9 @@ end function diagind(m::Integer, n::Integer, k::Integer=0) if 0 < k < n - return Range(k*m+1,m+1,min(m,n-k)) + return (k*m+1):(m+1):(k*m + min(m,n-k)) elseif 0 <= -k <= m - return Range(1-k,m+1,min(m+k,n)) + return (1-l):(m+1):(-k + min(m+k,n)) end throw(BoundsError()) end diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index ea768479393a5..04f8e466c3770 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -254,7 +254,7 @@ end # Allocation-free variants # Note that solve is non-aliasing, so you can use the same array for # input and output -function solve!{T<:BlasFloat}(x::AbstractArray{T}, xrng::Ranges{Int}, M::Tridiagonal{T}, rhs::AbstractArray{T}, rhsrng::Ranges{Int}) +function solve!{T<:BlasFloat}(x::AbstractArray{T}, xrng::Range{Int}, M::Tridiagonal{T}, rhs::AbstractArray{T}, rhsrng::Range{Int}) d = M.d N = length(d) if length(xrng) != N || length(rhsrng) != N @@ -319,7 +319,7 @@ end \(M::Tridiagonal, rhs::StridedVecOrMat) = solve(M, rhs) # Tridiagonal multiplication -function mult(x::AbstractArray, xrng::Ranges{Int}, M::Tridiagonal, v::AbstractArray, vrng::Ranges{Int}) +function mult(x::AbstractArray, xrng::Range{Int}, M::Tridiagonal, v::AbstractArray, vrng::Range{Int}) dl = M.dl d = M.d du = M.du diff --git a/base/linalg/woodbury.jl b/base/linalg/woodbury.jl index 47bbbec51f039..0a9b29c4a747b 100644 --- a/base/linalg/woodbury.jl +++ b/base/linalg/woodbury.jl @@ -78,7 +78,7 @@ det(W::Woodbury)=det(W.A)*det(W.C)/det(W.Cp) # Allocation-free solver for arbitrary strides (requires that W.A has a # non-aliasing "solve" routine, e.g., is Tridiagonal) -function solve!(x::AbstractArray, xrng::Ranges{Int}, W::Woodbury, rhs::AbstractArray, rhsrng::Ranges{Int}) +function solve!(x::AbstractArray, xrng::Range{Int}, W::Woodbury, rhs::AbstractArray, rhsrng::Range{Int}) solve!(W.tmpN1, 1:length(W.tmpN1), W.A, rhs, rhsrng) A_mul_B!(W.tmpk1, W.V, W.tmpN1) A_mul_B!(W.tmpk2, W.Cp, W.tmpk1) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 95a24cfca25fe..e2ab1e966e451 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -5,9 +5,8 @@ nothing end - unsafe_getindex(v::Real, ind::Int) = v -unsafe_getindex(v::Ranges, ind::Int) = first(v) + (ind-1)*step(v) +unsafe_getindex(v::Range, ind::Int) = first(v) + (ind-1)*step(v) unsafe_getindex(v::BitArray, ind::Int) = Base.unsafe_bitgetindex(v.chunks, ind) unsafe_getindex(v::AbstractArray, ind::Int) = v[ind] unsafe_getindex(v, ind::Real) = unsafe_getindex(v, to_index(ind)) @@ -16,7 +15,6 @@ unsafe_setindex!{T}(v::AbstractArray{T}, x::T, ind::Int) = (v[ind] = x; v) unsafe_setindex!(v::BitArray, x::Bool, ind::Int) = (Base.unsafe_bitsetindex!(v.chunks, x, ind); v) unsafe_setindex!{T}(v::AbstractArray{T}, x::T, ind::Real) = unsafe_setindex!(v, x, to_index(ind)) - # Version that uses cartesian indexing for src @ngenerate N typeof(dest) function _getindex!(dest::Array, src::AbstractArray, I::NTuple{N,Union(Int,AbstractVector)}...) checksize(dest, I...) diff --git a/base/random.jl b/base/random.jl index 64701151014bc..11cf23637ad1a 100644 --- a/base/random.jl +++ b/base/random.jl @@ -168,7 +168,7 @@ function rand{T<:Integer,U<:Unsigned}(g::RandIntGen{T,U}) end rand{T<:Union(Signed,Unsigned,Bool,Char)}(r::Range1{T}) = rand(RandIntGen(r)) -rand{T<:Real}(r::Ranges{T}) = convert(T, first(r) + rand(0:(length(r)-1)) * step(r)) +rand{T<:Real}(r::Range{T}) = convert(T, first(r) + rand(0:(length(r)-1)) * step(r)) function rand!(g::RandIntGen, A::AbstractArray) for i = 1 : length(A) @@ -179,7 +179,7 @@ end rand!{T<:Union(Signed,Unsigned,Bool,Char)}(r::Range1{T}, A::AbstractArray) = rand!(RandIntGen(r), A) -function rand!{T<:Real}(r::Ranges{T}, A::AbstractArray) +function rand!{T<:Real}(r::Range{T}, A::AbstractArray) g = RandIntGen(0:(length(r)-1)) f = first(r) s = step(r) @@ -195,8 +195,8 @@ function rand!{T<:Real}(r::Ranges{T}, A::AbstractArray) return A end -rand{T<:Real}(r::Ranges{T}, dims::Dims) = rand!(r, Array(T, dims)) -rand(r::Ranges, dims::Int...) = rand(r, dims) +rand{T<:Real}(r::Range{T}, dims::Dims) = rand!(r, Array(T, dims)) +rand(r::Range, dims::Int...) = rand(r, dims) ## random Bools diff --git a/base/range.jl b/base/range.jl index 111010ff77130..adcc0a1589939 100644 --- a/base/range.jl +++ b/base/range.jl @@ -2,26 +2,11 @@ typealias Dims (Int...) -abstract Ranges{T} <: AbstractArray{T,1} +abstract Range{T} <: AbstractArray{T,1} ## ordinal ranges -abstract OrdinalRange{T,S} <: Ranges{T} - -immutable Range{T<:Real} <: Ranges{T} - start::T - step::T - len::Int - - function Range(start::T, step::T, len::Int) - if step != step; error("step cannot be NaN"); end - if !(len >= 0); error("length must be non-negative"); end - new(start, step, len) - end - Range(start::T, step::T, len::Integer) = Range(start, step, int(len)) - Range(start::T, step, len::Integer) = Range(start, convert(T,step), int(len)) -end -Range{T}(start::T, step, len::Integer) = Range{T}(start, step, len) +abstract OrdinalRange{T,S} <: Range{T} # A StepRange has a start point, and moves by some step up through a last point. # The element type is T, but we allow T+S to give a value from a lifted @@ -29,11 +14,23 @@ Range{T}(start::T, step, len::Integer) = Range{T}(start, step, len) # since T might not have any available sentinel value. immutable StepRange{T,S,D} <: OrdinalRange{T,S} start::D - sentinel::D step::S + sentinel::D - StepRange(start, step, stop) = new(start, ifelse(stop>=start, stop+step, start), - step) + function StepRange(start, step, stop) + if D<:FloatingPoint || S<:FloatingPoint + error("StepRange should not be used with floating point") + end + step == 0 && error("step cannot be zero") + step != step && error("step cannot be NaN") + nm1 = fld(stop-start, step) + if nm1 >= 0 + last = start + nm1 * step + new(start, step, last+step) + else + new(start, step, start) + end + end end StepRange{T,S}(start::T, step::S, stop::T) = @@ -45,21 +42,24 @@ immutable Range1{T<:Integer,D} <: OrdinalRange{T,Int} Range1(start, stop) = new(start, ifelse(stop>=start, stop+1, start)) end -Range1{T}(start::T, stop::T) = Range1{T}(start, stop) +Range1{T<:Integer}(start::T, stop::T) = Range1{T, typeof(stop+1)}(start, stop) colon(a, b) = colon(promote(a,b)...) -colon(a::Real, b::Real, c::Real) = colon(promote(a,b,c)...) -colon(a, b, c) = colon(convert(promote_type(a,c),a), b, convert(promote_type(a,c),c)) -colon{T<:Integer}(start::T, stop::T) = Range1{T}(start, stop) +colon{T<:Integer}(start::T, stop::T) = Range1(start, stop) colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop) +# first promote start and stop, leaving step alone +# this is for non-numeric ranges where step can be quite different +colon{A,C}(a::A, b, c::C) = colon(convert(promote_type(A,C),a), b, convert(promote_type(A,C),c)) + colon{T}(start::T, step, stop::T) = StepRange(start, step, stop) + ## floating point ranges -immutable FloatRange{T<:FloatingPoint} <: Ranges{T} +immutable FloatRange{T<:FloatingPoint} <: Range{T} start::T step::T len::T @@ -112,6 +112,12 @@ function frange{T<:FloatingPoint}(start::T, step::T, stop::T) start, step, floor(r)+1, one(step) end +colon{T<:FloatingPoint}(a::T, b::T) = colon(a, one(a), b) + +colon{T<:Real}(a::T, b::FloatingPoint, c::T) = colon(promote(a,b,c)...) +colon{T<:FloatingPoint}(a::T, b::FloatingPoint, c::T) = colon(promote(a,b,c)...) +colon{T<:FloatingPoint}(a::T, b::Real, c::T) = colon(promote(a,b,c)...) + colon{T<:FloatingPoint}(start::T, step::T, stop::T) = step == 0 ? error("step cannot be zero in colon syntax") : start == stop ? FloatRange{T}(start,step,1,1) : @@ -120,48 +126,43 @@ colon{T<:FloatingPoint}(start::T, step::T, stop::T) = ## interface implementations -similar(r::Ranges, T::Type, dims::Dims) = Array(T, dims) +similar(r::Range, T::Type, dims::Dims) = Array(T, dims) -size(r::Ranges) = (length(r),) +size(r::Range) = (length(r),) -length(r::FloatRange) = r.len -length(r::StepRange) = itrunc((r.sentinal - r.start)/r.step) -length(r::Range1) = int(r.sentinel - r.start) -length(r::Range) = r.len +step(r::StepRange) = r.step +step(r::Range1) = one(r.sentinel - r.start) +step(r::FloatRange) = r.step/r.divisor -first{T}(r::Ranges{T}) = oftype(T, r.start) -first(r::FloatRange) = r.start/r.divisor +length(r::StepRange) = integer(abs(div(r.sentinel - r.start, r.step))) +length(r::Range1) = integer(r.sentinel - r.start) +length(r::FloatRange) = integer(r.len) -last{T}(r::Range{T}) = oftype(T, r.start + (r.len-1)*r.step) -last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) -last{T}(r::OrdinalRange{T}) = oftype(T, r.sentinel-step(r)) +length(r::Range1{Int}) = checked_add(checked_sub(r.sentinel-1, r.start), 1) -function length(r::Range1{Int}) - checked_add(checked_sub(r.sentinel-1, r.start), 1) -end +first{T}(r::OrdinalRange{T}) = oftype(T, r.start) +first(r::FloatRange) = r.start/r.divisor -step(r::Range) = r.step -step(r::StepRange) = r.step -step(r::Range1) = one(r.sentinel - r.start) -step(r::FloatRange) = r.step/r.divisor +last{T}(r::OrdinalRange{T}) = oftype(T, r.sentinel-step(r)) +last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) minimum(r::Range1) = isempty(r) ? error("range must be non-empty") : first(r) maximum(r::Range1) = isempty(r) ? error("range must be non-empty") : last(r) -minimum(r::Ranges) = isempty(r) ? error("range must be non-empty") : step(r) > 0 ? first(r) : last(r) -maximum(r::Ranges) = isempty(r) ? error("range must be non-empty") : step(r) > 0 ? last(r) : first(r) +minimum(r::Range) = isempty(r) ? error("range must be non-empty") : min(first(r), last(r)) +maximum(r::Range) = isempty(r) ? error("range must be non-empty") : max(first(r), last(r)) -ctranspose(r::Ranges) = [x for _=1, x=r] -transpose(r::Ranges) = r' +ctranspose(r::Range) = [x for _=1, x=r] +transpose(r::Range) = r' # Ranges are immutable -copy(r::Ranges) = r +copy(r::Range) = r ## iteration -start(r::Ranges) = 0 +start(r::Range) = 0 next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1) -done(r::Ranges, i) = (length(r) <= i) +done(r::Range, i) = (length(r) <= i) next{T}(r::FloatRange{T}, i) = (oftype(T, (r.start + i*r.step)/r.divisor), i+1) @@ -174,11 +175,11 @@ next{T,D}(r::Range1{T,D}, i) = (oftype(T,i), oftype(D, i+1)) ## indexing -getindex(r::Ranges, i::Real) = getindex(r, to_index(i)) +getindex(r::Range, i::Real) = getindex(r, to_index(i)) -function getindex{T}(r::Ranges{T}, i::Integer) +function getindex{T}(r::Range{T}, i::Integer) 1 <= i <= length(r) || error(BoundsError) - oftype(T, r.start + (i-1)*step(r)) + oftype(T, start(r) + (i-1)*step(r)) end function getindex{T}(r::FloatRange{T}, i::Integer) 1 <= i <= length(r) || error(BoundsError) @@ -198,37 +199,38 @@ function getindex(r::Range1, s::Range1{Int}) Range1(st, oftype(st,st+sl-1)) end -function getindex(r::Ranges, s::Ranges{Int}) +function getindex(r::StepRange, s::Range{Int}) sl = length(s) if sl > 0 if !(1 <= last(s) <= length(r)) throw(BoundsError()) end - Range(r[s.start], step(r)*step(s), sl) + st = r[start(s)] else - Range(r.start + (s.start-1)*step(r), step(r)*step(s), sl) + st = oftype(r.start, r.start + (start(s)-1)*step(r)) end + StepRange(st, step(r)*step(s), oftype(st, st + sl - 1)) end -function show(io::IO, r::Ranges) +# TODO: getindex of FloatRange + +function show(io::IO, r::Range) step(r) == 0 ? invoke(show,(IO,Any),io,r) : print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) end show(io::IO, r::Range1) = print(io, repr(first(r)), ':', repr(last(r))) -show{T<:FloatingPoint}(io::IO, r::Range{T}) = invoke(show, (IO,Any), io, r) - -isequal{T<:Ranges}(r::T, s::T) = - (first(r)==first(s)) & (step(r)==step(s)) & (length(r)==length(s)) +isequal{T<:Range}(r::T, s::T) = + (first(r)==first(s)) & (step(r)==step(s)) & (last(r)==last(s)) -isequal(r::Ranges, s::Ranges) = false +isequal(r::Range, s::Range) = false -=={T<:Ranges}(r::T, s::T) = isequal(r, s) +=={T<:Range}(r::T, s::T) = isequal(r, s) -=={T<:Integer, S<:Integer}(r::Ranges{T}, s::Ranges{S}) = - (first(r)==first(s)) & (step(r)==step(s)) & (length(r)==length(s)) +=={T<:Integer, S<:Integer}(r::Range{T}, s::Range{S}) = + (first(r)==first(s)) & (step(r)==step(s)) & (last(r)==last(s)) -function ==(r::Ranges, s::Ranges) +function ==(r::Range, s::Range) lr = length(r) if lr != length(s) return false @@ -245,8 +247,8 @@ function ==(r::Ranges, s::Ranges) end # hashing ranges by component at worst leads to collisions for very similar ranges -hash(r::Ranges) = - bitmix(hash(first(r)), bitmix(hash(step(r)), bitmix(hash(length(r)), uint(0xaaeeaaee)))) +hash(r::Range) = + bitmix(hash(first(r)), bitmix(hash(step(r)), bitmix(hash(last(r)), uint(0xaaeeaaee)))) # TODO: isless? @@ -258,7 +260,7 @@ intersect{T<:Integer}(i::Integer, r::Range1{T}) = intersect{T<:Integer}(r::Range1{T}, i::Integer) = intersect(i, r) -function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::Range{T2}) +function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::StepRange{T2}) if length(s) == 0 Range1(first(r), oftype(T1, first(r)-1)) elseif step(s) == 0 @@ -277,19 +279,17 @@ function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::Range{T2}) end end -function intersect{T1<:Integer, T2<:Integer}(r::Range{T1}, s::Range1{T2}) - if step(r) == 0 - first(s) <= first(r) <= last(s) ? r : Range(first(r), 0, 0) - elseif step(r) < 0 +function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::Range1{T2}) + if step(r) < 0 reverse(intersect(s, reverse(r))) else intersect(s, r) end end -function intersect{T1<:Integer, T2<:Integer}(r::Range{T1}, s::Range{T2}) +function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::StepRange{T2}) if length(r) == 0 || length(s) == 0 - return Range(first(r), step(r), 0) + return StepRange(first(r), step(r), first(r)-step(r)) elseif step(s) < 0 return intersect(r, reverse(s)) elseif step(r) < 0 @@ -304,22 +304,22 @@ function intersect{T1<:Integer, T2<:Integer}(r::Range{T1}, s::Range{T2}) stop2 = last(s) a = lcm(step1, step2) - if a == 0 - # One or both ranges have step 0. - if step1 == 0 && step2 == 0 - return start1 == start2 ? r : Range(start1, 0, 0) - elseif step1 == 0 - return start2 <= start1 <= stop2 && rem(start1 - start2, step2) == 0 ? r : Range(start1, 0, 0) - else - return start1 <= start2 <= stop1 && rem(start2 - start1, step1) == 0 ? (start2:step1:start2) : Range(start1, step1, 0) - end - end + # if a == 0 + # # One or both ranges have step 0. + # if step1 == 0 && step2 == 0 + # return start1 == start2 ? r : Range(start1, 0, 0) + # elseif step1 == 0 + # return start2 <= start1 <= stop2 && rem(start1 - start2, step2) == 0 ? r : Range(start1, 0, 0) + # else + # return start1 <= start2 <= stop1 && rem(start2 - start1, step1) == 0 ? (start2:step1:start2) : Range(start1, step1, 0) + # end + # end g, x, y = gcdx(step1, step2) if rem(start1 - start2, g) != 0 # Unaligned, no overlap possible. - return Range(start1, a, 0) + return StepRange(start1, a, start1-a) end z = div(start1 - start2, g) @@ -332,7 +332,7 @@ function intersect{T1<:Integer, T2<:Integer}(r::Range{T1}, s::Range{T2}) m:a:n end -function intersect(r::Ranges, s::Ranges...) +function intersect(r::Range, s::Range...) i = r for t in s i = intersect(i, t) @@ -341,7 +341,7 @@ function intersect(r::Ranges, s::Ranges...) end # findin (the index of intersection) -function _findin{T1<:Integer, T2<:Integer}(r::Ranges{T1}, span::Range1{T2}) +function _findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::Range1{T2}) local ifirst local ilast fspan = first(span) @@ -374,53 +374,53 @@ end ## linear operations on ranges ## --(r::Ranges) = Range(-r.start, -step(r), length(r)) --(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) +-(r::OrdinalRange) = StepRange(-r.start, -step(r), -last(r)) +-(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) +(x::Real, r::Range1) = Range1(x + r.start, x + last(r)) -+(x::Real, r::Range) = Range(x + r.start, r.step, r.len) ++(x::Real, r::StepRange) = StepRange(x + r.start, r.step, x + last(r)) +(x::Real, r::FloatRange) = FloatRange(r.divisor*x + r.start, r.step, r.len, r.divisor) -+(r::Ranges, x::Real) = x + r ++(r::Range, x::Real) = x + r +(r::FloatRange, x::Real) = x + r --(x::Real, r::Ranges) = Range(x - r.start, -step(r), length(r)) +-(x::Real, r::OrdinalRange) = StepRange(x - start(r), -step(r), x - last(r)) -(x::Real, r::FloatRange) = FloatRange(r.divisor*x - r.start, -r.step, r.len, r.divisor) -(r::Range1, x::Real) = Range1(r.start-x, last(r)-x) --(r::Range , x::Real) = Range(r.start-x, r.step, r.len) +-(r::StepRange , x::Real) = StepRange(r.start-x, r.step, last(r)-x) -(r::FloatRange, x::Real) = FloatRange(r.start - r.divisor*x, r.step, r.len, r.divisor) -.*(x::Real, r::Ranges) = Range(x*r.start, x*step(r), length(r)) -.*(x::Real, r::FloatRange) = FloatRange(x*r.start, x*r.step, r.len, r.divisor) -.*(r::Ranges, x::Real) = x .* r -.*(r::FloatRange, x::Real) = x .* r +.*(x::Real, r::OrdinalRange) = StepRange(x*r.start, x*step(r), x*last(r)) +.*(x::Real, r::FloatRange) = FloatRange(x*r.start, x*r.step, r.len, r.divisor) +.*(r::Range, x::Real) = x .* r +.*(r::FloatRange, x::Real) = x .* r -./(r::Ranges, 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::OrdinalRange, x::Real) = StepRange(r.start/x, step(r)/x, last(r)/x) +./(r::FloatRange, x::Real) = FloatRange(r.start/x, r.step/x, r.len, r.divisor) # TODO: better implementations for FloatRanges? -function +(r1::Ranges, r2::Ranges) +function +(r1::OrdinalRange, r2::OrdinalRange) r1l = length(r1) r1l == length(r2) || error("argument dimensions must match") - Range(r1.start+r2.start, step(r1)+step(r2), r1l) + StepRange(r1.start+r2.start, step(r1)+step(r2), r1l) end -function -(r1::Ranges, r2::Ranges) +function -(r1::OrdinalRange, r2::OrdinalRange) r1l = length(r1) r1l == length(r2) || error("argument dimensions must match") - Range(r1.start-r2.start, step(r1)-step(r2), r1l) + StepRange(r1.start-r2.start, step(r1)-step(r2), r1l) end ## non-linear operations on ranges ## -./(x::Number, r::Ranges) = [ x/y for y=r ] -./(r::Ranges, y::Number) = [ x/y for x=r ] +./(x::Number, r::Range) = [ x/y for y=r ] +./(r::Range, y::Number) = [ x/y for x=r ] -.^(x::Number, r::Ranges) = [ x^y for y=r ] -.^(r::Ranges, y::Number) = [ x^y for x=r ] +.^(x::Number, r::Range) = [ x^y for y=r ] +.^(r::Range, y::Number) = [ x^y for x=r ] ## concatenation ## -function vcat{T}(r::Ranges{T}) +function vcat{T}(r::Range{T}) n = length(r) a = Array(T,n) i = 1 @@ -431,9 +431,9 @@ function vcat{T}(r::Ranges{T}) return a end -convert{T}(::Type{Array{T,1}}, r::Ranges{T}) = vcat(r) +convert{T}(::Type{Array{T,1}}, r::Range{T}) = vcat(r) -function vcat{T}(rs::Ranges{T}...) +function vcat{T}(rs::Range{T}...) n = sum(length,rs)::Int a = Array(T,n) i = 1 @@ -446,13 +446,13 @@ function vcat{T}(rs::Ranges{T}...) return a end -reverse(r::Ranges) = Range(last(r), -step(r), length(r)) -reverse(r::FloatRange) = FloatRange(last(r), -r.step, r.len, r.divisor) +reverse(r::OrdinalRange) = StepRange(last(r), -step(r), start(r)) +reverse(r::FloatRange) = FloatRange(last(r), -r.step, r.len, r.divisor) ## sorting ## issorted(r::Range1) = true -issorted(r::Ranges) = step(r) >= 0 +issorted(r::Range) = step(r) >= 0 sort(r::Range1) = r sort!(r::Range1) = r @@ -462,20 +462,20 @@ sort{T<:Real}(r::Range{T}) = issorted(r) ? r : reverse(r) sortperm(r::Range1) = 1:length(r) sortperm{T<:Real}(r::Range{T}) = issorted(r) ? (1:1:length(r)) : (length(r):-1:1) -function sum{T<:Real}(r::Ranges{T}) +function sum{T<:Real}(r::Range{T}) l = length(r) # note that a little care is required to avoid overflow in l*(l-1)/2 return l * first(r) + (iseven(l) ? (step(r) * (l-1)) * (l>>1) : (step(r) * l) * ((l-1)>>1)) end -function map!(f::Callable, dest, r::Ranges) +function map!(f::Callable, dest, r::Range) i = 1 for ri in r dest[i] = f(ri); i+=1; end dest end -function map_range_to!(f::Callable, first, dest, r::Ranges, state) +function map_range_to!(f::Callable, first, dest, r::Range, state) dest[1] = first i = 2 while !done(r, state) @@ -486,7 +486,7 @@ function map_range_to!(f::Callable, first, dest, r::Ranges, state) dest end -function map(f::Callable, r::Ranges) +function map(f::Callable, r::Range) if isempty(r); return {}; end state = start(r) (ri, state) = next(r, state) @@ -494,9 +494,9 @@ function map(f::Callable, r::Ranges) map_range_to!(f, first, Array(typeof(first), length(r)), r, state) end -function in(x, r::Ranges) +function in(x, r::Range) n = step(r) == 0 ? 1 : iround((x-first(r))/step(r))+1 n >= 1 && n <= length(r) && r[n] == x end -in{T<:Integer}(x, r::Ranges{T}) = isinteger(x) && x>=minimum(r) && x<=maximum(r) && (step(r)==0 || mod(int(x)-first(r),step(r))==0) +in{T<:Integer}(x, r::Range{T}) = isinteger(x) && x>=minimum(r) && x<=maximum(r) && (step(r)==0 || mod(int(x)-first(r),step(r))==0) diff --git a/base/replutil.jl b/base/replutil.jl index 7d1aa22f00842..8009cc06f13bd 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -12,7 +12,7 @@ function writemime(io::IO, ::MIME"text/plain", f::Function) end function writemime(io::IO, ::MIME"text/plain", v::AbstractVector) - if isa(v, Ranges) + if isa(v, Range) show(io, v) else print(io, summary(v)) diff --git a/base/sort.jl b/base/sort.jl index 31d0ff05afda3..cbc85920dcabe 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -174,7 +174,7 @@ function searchsorted(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering) return lo+1:hi-1 end -function searchsortedlast{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward) +function searchsortedlast{T<:Real}(a::Range{T}, x::Real, o::Ordering=Forward) if step(a) == 0 lt(o, x, first(a)) ? 0 : length(a) else @@ -183,7 +183,7 @@ function searchsortedlast{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward) end end -function searchsortedfirst{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward) +function searchsortedfirst{T<:Real}(a::Range{T}, x::Real, o::Ordering=Forward) if step(a) == 0 lt(o, first(a), x) ? length(a)+1 : 1 else @@ -192,7 +192,7 @@ function searchsortedfirst{T<:Real}(a::Ranges{T}, x::Real, o::Ordering=Forward) end end -function searchsortedlast{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward) +function searchsortedlast{T<:Integer}(a::Range{T}, x::Real, o::Ordering=Forward) if step(a) == 0 lt(o, x, first(a)) ? 0 : length(a) else @@ -200,7 +200,7 @@ function searchsortedlast{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward end end -function searchsortedfirst{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forward) +function searchsortedfirst{T<:Integer}(a::Range{T}, x::Real, o::Ordering=Forward) if step(a) == 0 lt(o, first(a), x) ? length(a)+1 : 1 else @@ -208,7 +208,7 @@ function searchsortedfirst{T<:Integer}(a::Ranges{T}, x::Real, o::Ordering=Forwar end end -searchsorted{T<:Real}(a::Ranges{T}, x::Real; kws...) = +searchsorted{T<:Real}(a::Range{T}, x::Real; kws...) = searchsortedfirst(a,x; kws...):searchsortedlast(a,x; kws...) for s in {:searchsortedfirst, :searchsortedlast, :searchsorted} diff --git a/base/statistics.jl b/base/statistics.jl index 7f693248e5772..2f87cb564b558 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -115,9 +115,9 @@ end ## variances over ranges -varm(v::Ranges, m::Number) = var(v) +varm(v::Range, m::Number) = var(v) -function var(v::Ranges) +function var(v::Range) s = step(v) l = length(v) if l == 0 || l == 1 @@ -378,7 +378,7 @@ end function histrange{T<:FloatingPoint,N}(v::AbstractArray{T,N}, n::Integer) if length(v) == 0 - return Range(0.0,1.0,1) + return 0.0:1.0:0.0 end lo, hi = minimum(v), maximum(v) if hi == lo @@ -396,12 +396,12 @@ function histrange{T<:FloatingPoint,N}(v::AbstractArray{T,N}, n::Integer) end end start = step*(ceil(lo/step)-1) - Range(start,step,1+iceil((hi - start)/step)) + start:step:(start + iceil((hi - start)/step)) end function histrange{T<:Integer,N}(v::AbstractArray{T,N}, n::Integer) if length(v) == 0 - return Range(0,1,1) + return 0:1:0 end lo, hi = minimum(v), maximum(v) if hi == lo @@ -421,11 +421,11 @@ function histrange{T<:Integer,N}(v::AbstractArray{T,N}, n::Integer) end end start = step*(iceil(lo/step)-1) - Range(start,step,1+iceil((hi - start)/step)) + start:step:(start + iceil((hi - start)/step)) end ## midpoints of intervals -midpoints(r::Ranges) = r[1:length(r)-1] + 0.5*step(r) +midpoints(r::Range) = r[1:length(r)-1] + 0.5*step(r) midpoints(v::AbstractVector) = [0.5*(v[i] + v[i+1]) for i in 1:length(v)-1] ## hist ## diff --git a/test/euler.jl b/test/euler.jl index 536d34a3456c3..889218e813e82 100644 --- a/test/euler.jl +++ b/test/euler.jl @@ -76,7 +76,7 @@ function euler11(grid,n) j = n:size(grid,2)-n+1, di = -1:1, dj = -1:1 di == dj == 0 && continue - idx = sub2ind(size(grid),Range(i,di,n),Range(j,dj,n)) + idx = sub2ind(size(grid),i:di:(i+n-1),j:dj:(j+n-1)) m = max(m,prod(grid[idx])) end return m diff --git a/test/ranges.jl b/test/ranges.jl index 21daef044a880..d88506fa1c2a4 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -36,12 +36,12 @@ let r = 15:-2:-38 @test findin(r, span) == 1:6 end -@test isempty(findin(5+0*(1:6), 2:4)) -@test findin(5+0*(1:6), 2:5) == 1:6 -@test findin(5+0*(1:6), 2:7) == 1:6 -@test findin(5+0*(1:6), 5:7) == 1:6 -@test isempty(findin(5+0*(1:6), 6:7)) -@test findin(5+0*(1:6), 5:5) == 1:6 +#@test isempty(findin(5+0*(1:6), 2:4)) +#@test findin(5+0*(1:6), 2:5) == 1:6 +#@test findin(5+0*(1:6), 2:7) == 1:6 +#@test findin(5+0*(1:6), 5:7) == 1:6 +#@test isempty(findin(5+0*(1:6), 6:7)) +#@test findin(5+0*(1:6), 5:5) == 1:6 @test intersect(1:5, 2:3) == 2:3 @test intersect(-3:5, 2:8) == 2:5 @@ -58,14 +58,14 @@ end @test isempty(intersect(-5:5, -6:13:20)) @test isempty(intersect(1:11, 15:4:-2)) @test isempty(intersect(11:1, 15:-4:-2)) -@test intersect(-5:5, 1+0*(1:3)) == 1:1 -@test isempty(intersect(-5:5, 6+0*(1:3))) +#@test intersect(-5:5, 1+0*(1:3)) == 1:1 +#@test isempty(intersect(-5:5, 6+0*(1:3))) @test intersect(-15:4:7, -10:-2) == -7:4:-3 @test intersect(13:-2:1, -2:8) == 7:-2:1 @test isempty(intersect(13:2:1, -2:8)) @test isempty(intersect(13:-2:1, 8:-2)) -@test intersect(5+0*(1:4), 2:8) == 5+0*(1:4) -@test isempty(intersect(5+0*(1:4), -7:3)) +#@test intersect(5+0*(1:4), 2:8) == 5+0*(1:4) +#@test isempty(intersect(5+0*(1:4), -7:3)) @test intersect(0:3:24, 0:4:24) == 0:12:24 @test intersect(0:4:24, 0:3:24) == 0:12:24 @test intersect(0:3:24, 24:-4:0) == 0:12:24 @@ -76,17 +76,17 @@ end @test isempty(intersect(1:6:2400, 0:4:2400)) @test intersect(-51:5:100, -33:7:125) == -26:35:79 @test intersect(-51:5:100, -32:7:125) == -11:35:94 -@test intersect(0:6:24, 6+0*(0:4:24)) == 6:6:6 -@test intersect(12+0*(0:6:24), 0:4:24) == Range(12, 0, 5) -@test isempty(intersect(6+0*(0:6:24), 0:4:24)) +#@test intersect(0:6:24, 6+0*(0:4:24)) == 6:6:6 +#@test intersect(12+0*(0:6:24), 0:4:24) == Range(12, 0, 5) +#@test isempty(intersect(6+0*(0:6:24), 0:4:24)) @test intersect(-10:3:24, -10:3:24) == -10:3:23 @test isempty(intersect(-11:3:24, -10:3:24)) @test !(3.5 in 1:5) @test (3 in 1:5) @test (3 in 5:-1:1) -@test (3 in 3+0*(1:5)) -@test !(4 in 3+0*(1:5)) +#@test (3 in 3+0*(1:5)) +#@test !(4 in 3+0*(1:5)) r = 0.0:0.01:1.0 @test (r[30] in r) @@ -223,13 +223,12 @@ for T = (Float32, Float64,),# BigFloat), end # near-equal ranges -@test 0.0:0.1:1.0 != Range(0.0,0.1,11) +@test 0.0:0.1:1.0 != 0.0f0:0.1f0:1.0f0 # comparing and hashing ranges let Rs = {1:2, int32(1:3:17), int64(1:3:17), 1:0, 17:-3:0, - 0.0:0.1:1.0, Range(0.0,0.1,11), - float32(0.0:0.1:1.0), float32(Range(0.0,0.1,11))} + 0.0:0.1:1.0, float32(0.0:0.1:1.0)} for r in Rs ar = collect(r) @test r != ar @@ -246,4 +245,4 @@ end # issue #2959 @test 1.0:1.5 == 1.0:1.0:1.5 == 1.0:1.0 -@test 1.0:(.3-.1)/.1 == 1.0:2.0 +#@test 1.0:(.3-.1)/.1 == 1.0:2.0 From e455737ce6aa97186c0de9b333c6ded72d4fc0e8 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 20 Mar 2014 16:05:26 -0400 Subject: [PATCH 04/11] fix typo in update to linalg code for new ranges --- base/linalg/dense.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index f0baa2752784d..53eee5afc4d92 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -72,7 +72,7 @@ function diagind(m::Integer, n::Integer, k::Integer=0) if 0 < k < n return (k*m+1):(m+1):(k*m + min(m,n-k)) elseif 0 <= -k <= m - return (1-l):(m+1):(-k + min(m+k,n)) + return (1-k):(m+1):(-k + min(m+k,n)) end throw(BoundsError()) end From b5ae2d1913b12bd72b2a7bd7d55bfed1ed0b9b1c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 20 Mar 2014 18:22:30 -0400 Subject: [PATCH 05/11] allow constructing StepRange by length It turns out there are many cases that are drastically easier this way. Tests not passing yet, but getting there. --- base/abstractarray.jl | 9 ++++-- base/linalg/dense.jl | 4 +-- base/operators.jl | 10 +++---- base/range.jl | 64 ++++++++++++++++++++----------------------- base/statistics.jl | 8 ++++-- test/euler.jl | 2 +- test/sorting.jl | 2 +- 7 files changed, 50 insertions(+), 49 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 8af6bc4d45635..c92e7014561b4 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -321,8 +321,13 @@ full(x::AbstractArray) = x for fn in _numeric_conversion_func_names @eval begin - $fn(r::StepRange) = StepRange($fn(r.start), $fn(r.step), $fn(last(r))) - $fn(r::Range1) = Range1($fn(r.start), $fn(last(r))) + $fn(r::StepRange) = $fn(r.start):$fn(r.step):$fn(last(r)) + $fn(r::Range1) = $fn(r.start):$fn(last(r)) + end +end + +for fn in (:float,:float16,:float32,:float64) + @eval begin $fn(r::FloatRange) = FloatRange($fn(r.start), $fn(r.step), r.len, $fn(r.divisor)) end end diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 53eee5afc4d92..e6b58f83e9497 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -70,9 +70,9 @@ end function diagind(m::Integer, n::Integer, k::Integer=0) if 0 < k < n - return (k*m+1):(m+1):(k*m + min(m,n-k)) + return StepRange(k*m+1, m+1, min(m, n-k)) elseif 0 <= -k <= m - return (1-k):(m+1):(-k + min(m+k,n)) + return StepRange(1-k, m+1, min(m+k,n)) end throw(BoundsError()) end diff --git a/base/operators.jl b/base/operators.jl index 766eb101950aa..df42a6f6c26ac 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -282,12 +282,10 @@ end # convert to integer index to_index(i::Int) = i to_index(i::Real) = convert(Int, i) -to_index(r::Range1{Int}) = r -to_index(r::Ranges{Int}) = r -to_index(I::Range1{Bool}) = find(I) -to_index(I::Ranges{Bool}) = find(I) -to_index{T<:Real}(r::Range1{T}) = to_index(first(r)):to_index(last(r)) -to_index{T<:Real}(r::Ranges{T}) = to_index(first(r)):to_index(step(r)):to_index(last(r)) +to_index(r::Range{Int}) = r +to_index(I::Range{Bool}) = find(I) +to_index{T<:Real}(r::UnitRange{T}) = to_index(first(r)):to_index(last(r)) +to_index{T<:Real}(r::StepRange{T}) = to_index(first(r)):to_index(step(r)):to_index(last(r)) to_index(I::AbstractArray{Bool}) = find(I) to_index(A::AbstractArray{Int}) = A to_index{T<:Real}(A::AbstractArray{T}) = [to_index(x) for x in A] diff --git a/base/range.jl b/base/range.jl index adcc0a1589939..b62a741d25c27 100644 --- a/base/range.jl +++ b/base/range.jl @@ -17,44 +17,39 @@ immutable StepRange{T,S,D} <: OrdinalRange{T,S} step::S sentinel::D - function StepRange(start, step, stop) + function StepRange(start, step, len) if D<:FloatingPoint || S<:FloatingPoint error("StepRange should not be used with floating point") end step == 0 && error("step cannot be zero") step != step && error("step cannot be NaN") - nm1 = fld(stop-start, step) - if nm1 >= 0 - last = start + nm1 * step - new(start, step, last+step) - else - new(start, step, start) - end + new(start, step, ifelse(len>=1, start + len*step, start)) end end -StepRange{T,S}(start::T, step::S, stop::T) = - StepRange{T, S, typeof(stop+step)}(start, step, stop) +StepRange{T,S}(start::T, step::S, len::Integer) = + StepRange{T, S, typeof(start+step)}(start, step, len) immutable Range1{T<:Integer,D} <: OrdinalRange{T,Int} start::D sentinel::D - Range1(start, stop) = new(start, ifelse(stop>=start, stop+1, start)) + Range1(start, len) = new(start, ifelse(len>=1, start+len, start)) + Range1(start, stop, _) = new(start, ifelse(stop>=start, stop+1, start)) end -Range1{T<:Integer}(start::T, stop::T) = Range1{T, typeof(stop+1)}(start, stop) +Range1{T<:Integer}(start::T, len::Integer) = Range1{T, typeof(start+1)}(start, len) colon(a, b) = colon(promote(a,b)...) -colon{T<:Integer}(start::T, stop::T) = Range1(start, stop) +colon{T<:Integer}(start::T, stop::T) = Range1{T,typeof(start+1)}(start, stop, 0) -colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop) +colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop-start+1) # first promote start and stop, leaving step alone # this is for non-numeric ranges where step can be quite different colon{A,C}(a::A, b, c::C) = colon(convert(promote_type(A,C),a), b, convert(promote_type(A,C),c)) -colon{T}(start::T, step, stop::T) = StepRange(start, step, stop) +colon{T}(start::T, step, stop::T) = StepRange(start, step, fld(stop-start, step)+1) ## floating point ranges @@ -179,7 +174,7 @@ getindex(r::Range, i::Real) = getindex(r, to_index(i)) function getindex{T}(r::Range{T}, i::Integer) 1 <= i <= length(r) || error(BoundsError) - oftype(T, start(r) + (i-1)*step(r)) + oftype(T, first(r) + (i-1)*step(r)) end function getindex{T}(r::FloatRange{T}, i::Integer) 1 <= i <= length(r) || error(BoundsError) @@ -196,7 +191,7 @@ function getindex(r::Range1, s::Range1{Int}) else st = oftype(r.start, r.start + s.start-1) end - Range1(st, oftype(st,st+sl-1)) + Range1(st, sl) end function getindex(r::StepRange, s::Range{Int}) @@ -205,14 +200,14 @@ function getindex(r::StepRange, s::Range{Int}) if !(1 <= last(s) <= length(r)) throw(BoundsError()) end - st = r[start(s)] + st = r[first(s)] else - st = oftype(r.start, r.start + (start(s)-1)*step(r)) + st = oftype(r.start, r.start + (first(s)-1)*step(r)) end - StepRange(st, step(r)*step(s), oftype(st, st + sl - 1)) + StepRange(st, step(r)*step(s), sl) end -# TODO: getindex of FloatRange +getindex(r::FloatRange, s::Range1) = r[first(s)]:step(r):r[last(s)] function show(io::IO, r::Range) step(r) == 0 ? invoke(show,(IO,Any),io,r) : @@ -262,7 +257,7 @@ intersect{T<:Integer}(r::Range1{T}, i::Integer) = intersect(i, r) function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::StepRange{T2}) if length(s) == 0 - Range1(first(r), oftype(T1, first(r)-1)) + Range1(first(r), 0) elseif step(s) == 0 intersect(first(s), r) elseif step(s) < 0 @@ -289,7 +284,7 @@ end function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::StepRange{T2}) if length(r) == 0 || length(s) == 0 - return StepRange(first(r), step(r), first(r)-step(r)) + return StepRange(first(r), step(r), 0) elseif step(s) < 0 return intersect(r, reverse(s)) elseif step(r) < 0 @@ -319,7 +314,7 @@ function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::StepRange{T2}) if rem(start1 - start2, g) != 0 # Unaligned, no overlap possible. - return StepRange(start1, a, start1-a) + return StepRange(start1, a, 0) end z = div(start1 - start2, g) @@ -374,27 +369,28 @@ end ## linear operations on ranges ## --(r::OrdinalRange) = StepRange(-r.start, -step(r), -last(r)) +-(r::OrdinalRange) = StepRange(-r.start, -step(r), length(r)) -(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) -+(x::Real, r::Range1) = Range1(x + r.start, x + last(r)) -+(x::Real, r::StepRange) = StepRange(x + r.start, r.step, x + last(r)) ++(x::Integer, r::Range1) = Range1(x + r.start, length(r)) ++(x::Real, r::Range) = (x+first(r)):step(r):(x+last(r)) +#+(x::Real, r::StepRange) = StepRange(x + r.start, r.step, length(r)) +(x::Real, r::FloatRange) = FloatRange(r.divisor*x + r.start, r.step, r.len, r.divisor) +(r::Range, x::Real) = x + r -+(r::FloatRange, x::Real) = x + r +#+(r::FloatRange, x::Real) = x + r --(x::Real, r::OrdinalRange) = StepRange(x - start(r), -step(r), x - last(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) --(r::Range1, x::Real) = Range1(r.start-x, last(r)-x) --(r::StepRange , x::Real) = StepRange(r.start-x, r.step, last(r)-x) +-(r::Range1, x::Integer) = Range1(r.start-x, length(r)) +-(r::StepRange , x::Real) = StepRange(r.start-x, r.step, length(r)) -(r::FloatRange, x::Real) = FloatRange(r.start - r.divisor*x, r.step, r.len, r.divisor) -.*(x::Real, r::OrdinalRange) = StepRange(x*r.start, x*step(r), x*last(r)) +.*(x::Real, r::OrdinalRange) = StepRange(x*r.start, x*step(r), length(r)) .*(x::Real, r::FloatRange) = FloatRange(x*r.start, x*r.step, r.len, r.divisor) .*(r::Range, x::Real) = x .* r .*(r::FloatRange, x::Real) = x .* r -./(r::OrdinalRange, x::Real) = StepRange(r.start/x, step(r)/x, last(r)/x) +./(r::OrdinalRange, x::Real) = StepRange(r.start/x, step(r)/x, length(r)) ./(r::FloatRange, x::Real) = FloatRange(r.start/x, r.step/x, r.len, r.divisor) # TODO: better implementations for FloatRanges? @@ -446,7 +442,7 @@ function vcat{T}(rs::Range{T}...) return a end -reverse(r::OrdinalRange) = StepRange(last(r), -step(r), start(r)) +reverse(r::OrdinalRange) = StepRange(last(r), -step(r), length(r)) reverse(r::FloatRange) = FloatRange(last(r), -r.step, r.len, r.divisor) ## sorting ## diff --git a/base/statistics.jl b/base/statistics.jl index 2f87cb564b558..2086fd71b94d9 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -396,7 +396,8 @@ function histrange{T<:FloatingPoint,N}(v::AbstractArray{T,N}, n::Integer) end end start = step*(ceil(lo/step)-1) - start:step:(start + iceil((hi - start)/step)) + nm1 = iceil((hi - start)/step) + start:step:(start + nm1*step) end function histrange{T<:Integer,N}(v::AbstractArray{T,N}, n::Integer) @@ -420,8 +421,9 @@ function histrange{T<:Integer,N}(v::AbstractArray{T,N}, n::Integer) step = 10*e end end - start = step*(iceil(lo/step)-1) - start:step:(start + iceil((hi - start)/step)) + start = step*(ceil(lo/step)-1) + nm1 = iceil((hi - start)/step) + start:step:(start + nm1*step) end ## midpoints of intervals diff --git a/test/euler.jl b/test/euler.jl index 889218e813e82..c7081bfdf47e8 100644 --- a/test/euler.jl +++ b/test/euler.jl @@ -76,7 +76,7 @@ function euler11(grid,n) j = n:size(grid,2)-n+1, di = -1:1, dj = -1:1 di == dj == 0 && continue - idx = sub2ind(size(grid),i:di:(i+n-1),j:dj:(j+n-1)) + idx = sub2ind(size(grid), StepRange(i,di,n), StepRange(j,dj,n)) m = max(m,prod(grid[idx])) end return m diff --git a/test/sorting.jl b/test/sorting.jl index c494e3848605e..7a197b5f66095 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -15,7 +15,7 @@ @test searchsorted([1, 1, 2, 2, 3, 3], 4) == 7:6 @test searchsorted([1.0, 1, 2, 2, 3, 3], 2.5) == 5:4 -for (rg,I) in {(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4), (3+0*(1:5),-5:.5:4)} +for (rg,I) in {(49:57,47:59), (1:2:17,-1:19), (-3:0.5:2,-5:.5:4)} rg_r = reverse(rg) rgv, rgv_r = [rg], [rg_r] for i = I From 458d27216f02d61e3e1249b8cd0f0b446c31e719 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 30 Mar 2014 17:21:10 -0400 Subject: [PATCH 06/11] introduce range() function for making ranges by length rename Range1 to UnitRange allow constructing a larger class of ranges, leaving overflow to length() --- base/exports.jl | 2 +- base/linalg/dense.jl | 4 +- base/range.jl | 134 ++++++++++++++++++++++++++----------------- doc/stdlib/base.rst | 4 ++ test/euler.jl | 4 +- 5 files changed, 91 insertions(+), 57 deletions(-) diff --git a/base/exports.jl b/base/exports.jl index ecc08f29c12ad..634a7e7e723f3 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -77,7 +77,6 @@ export QRPivoted, QuickSort, Range, - Range1, RangeIndex, Rational, Regex, @@ -556,6 +555,7 @@ export promote_shape, randcycle, randperm, + range, reducedim, repmat, reshape, diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index e6b58f83e9497..2128c24cdac59 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -70,9 +70,9 @@ end function diagind(m::Integer, n::Integer, k::Integer=0) if 0 < k < n - return StepRange(k*m+1, m+1, min(m, n-k)) + return range(k*m+1, m+1, min(m, n-k)) elseif 0 <= -k <= m - return StepRange(1-k, m+1, min(m+k,n)) + return range(1-k, m+1, min(m+k,n)) end throw(BoundsError()) end diff --git a/base/range.jl b/base/range.jl index b62a741d25c27..0a2a8c3ec4f5b 100644 --- a/base/range.jl +++ b/base/range.jl @@ -17,40 +17,59 @@ immutable StepRange{T,S,D} <: OrdinalRange{T,S} step::S sentinel::D - function StepRange(start, step, len) + function StepRange(start, step::S, stop) if D<:FloatingPoint || S<:FloatingPoint error("StepRange should not be used with floating point") end step == 0 && error("step cannot be zero") step != step && error("step cannot be NaN") - new(start, step, ifelse(len>=1, start + len*step, start)) + + start = convert(D, start) + stop = convert(D, stop) + + if (step>0 && stopstart) + sentinel = start + else + remain = (stop - start) % step # should be robust to overflow + sentinel = stop + (step - remain) + end + + new(start, step, sentinel) end end -StepRange{T,S}(start::T, step::S, len::Integer) = - StepRange{T, S, typeof(start+step)}(start, step, len) +StepRange{T,S}(start::T, step::S, stop::T) = + StepRange{T, S, typeof(start+step)}(start, step, stop) -immutable Range1{T<:Integer,D} <: OrdinalRange{T,Int} +immutable UnitRange{T<:Real,D} <: OrdinalRange{T,Int} start::D sentinel::D - Range1(start, len) = new(start, ifelse(len>=1, start+len, start)) - Range1(start, stop, _) = new(start, ifelse(stop>=start, stop+1, start)) + UnitRange(start, stop) = new(start, ifelse(stop >= start, stop+1, convert(D,start))) end -Range1{T<:Integer}(start::T, len::Integer) = Range1{T, typeof(start+1)}(start, len) +UnitRange{T<:Real}(start::T, stop::T) = UnitRange{T, typeof(start+1)}(start, stop) + +# deprecated +export Range1 +const Range1 = UnitRange colon(a, b) = colon(promote(a,b)...) -colon{T<:Integer}(start::T, stop::T) = Range1{T,typeof(start+1)}(start, stop, 0) +colon{T<:Real}(start::T, stop::T) = UnitRange(start, stop) +range(a::Real, len::Integer) = UnitRange{typeof(a), typeof(a+len-1)}(a, a+len-1) -colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop-start+1) +colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop) +range{T}(a::T, len::Integer) = + StepRange{T, typeof(a-a), typeof(a+one(a-a))}(a, one(a-a), a+oftype(a-a,(len-1))) # first promote start and stop, leaving step alone # this is for non-numeric ranges where step can be quite different colon{A,C}(a::A, b, c::C) = colon(convert(promote_type(A,C),a), b, convert(promote_type(A,C),c)) -colon{T}(start::T, step, stop::T) = StepRange(start, step, fld(stop-start, step)+1) +colon{T}(start::T, step, stop::T) = StepRange(start, step, stop) +range{T,S}(a::T, step::S, len::Integer) = + StepRange{T, S, typeof(a+one(S))}(a, step, a+step*(len-1)) ## floating point ranges @@ -114,26 +133,37 @@ colon{T<:FloatingPoint}(a::T, b::FloatingPoint, c::T) = colon(promote(a,b,c)...) colon{T<:FloatingPoint}(a::T, b::Real, c::T) = colon(promote(a,b,c)...) colon{T<:FloatingPoint}(start::T, step::T, stop::T) = - step == 0 ? error("step cannot be zero in colon syntax") : + step == 0 ? error("range step cannot be zero") : start == stop ? FloatRange{T}(start,step,1,1) : (0 < step) != (start < stop) ? FloatRange{T}(start,step,0,1) : FloatRange{T}(frange(start,step,stop)...) +range(a::FloatingPoint, len::Integer) = colon(a, oftype(a,a+len-1)) +range(a::FloatingPoint, st::FloatingPoint, len::Integer) = colon(a, st, a+oftype(st,(len-1)*st)) +range(a::Real, st::FloatingPoint, len::Integer) = colon(a, st, a+oftype(st,(len-1)*st)) +range(a::FloatingPoint, st::Real, len::Integer) = colon(a, st, oftype(a,a+(len-1)*st)) + ## interface implementations similar(r::Range, T::Type, dims::Dims) = Array(T, dims) size(r::Range) = (length(r),) +isempty(r::FloatRange) = length(r)==0 +isempty(r::OrdinalRange) = r.start == r.sentinel + step(r::StepRange) = r.step -step(r::Range1) = one(r.sentinel - r.start) +step(r::UnitRange) = one(r.sentinel - r.start) step(r::FloatRange) = r.step/r.divisor -length(r::StepRange) = integer(abs(div(r.sentinel - r.start, r.step))) -length(r::Range1) = integer(r.sentinel - r.start) +length(r::StepRange) = integer(div(r.sentinel - r.start, r.step)) +length(r::UnitRange) = integer(r.sentinel - r.start) length(r::FloatRange) = integer(r.len) -length(r::Range1{Int}) = checked_add(checked_sub(r.sentinel-1, r.start), 1) +length{T<:Union(Int,Uint)}(r::StepRange{T}) = + checked_add(div(checked_sub(r.sentinel-r.step, r.start), r.step), one(T)) +length{T<:Union(Int,Uint)}(r::UnitRange{T}) = + checked_add(checked_sub(r.sentinel-one(T), r.start), one(T)) first{T}(r::OrdinalRange{T}) = oftype(T, r.start) first(r::FloatRange) = r.start/r.divisor @@ -141,8 +171,8 @@ first(r::FloatRange) = r.start/r.divisor last{T}(r::OrdinalRange{T}) = oftype(T, r.sentinel-step(r)) last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) -minimum(r::Range1) = isempty(r) ? error("range must be non-empty") : first(r) -maximum(r::Range1) = isempty(r) ? error("range must be non-empty") : last(r) +minimum(r::UnitRange) = isempty(r) ? error("range must be non-empty") : first(r) +maximum(r::UnitRange) = isempty(r) ? error("range must be non-empty") : last(r) minimum(r::Range) = isempty(r) ? error("range must be non-empty") : min(first(r), last(r)) maximum(r::Range) = isempty(r) ? error("range must be non-empty") : max(first(r), last(r)) @@ -155,17 +185,15 @@ copy(r::Range) = r ## iteration -start(r::Range) = 0 -next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1) -done(r::Range, i) = (length(r) <= i) - +start(r::FloatRange) = 0 next{T}(r::FloatRange{T}, i) = (oftype(T, (r.start + i*r.step)/r.divisor), i+1) +done(r::FloatRange, i) = (length(r) <= i) start(r::OrdinalRange) = r.start next{T}(r::OrdinalRange{T}, i) = (oftype(T,i), i+step(r)) done(r::OrdinalRange, i) = i==r.sentinel -next{T,D}(r::Range1{T,D}, i) = (oftype(T,i), oftype(D, i+1)) +next{T,D}(r::UnitRange{T,D}, i) = (oftype(T,i), oftype(D, i+1)) ## indexing @@ -181,7 +209,7 @@ function getindex{T}(r::FloatRange{T}, i::Integer) oftype(T, (r.start + (i-1)*r.step)/r.divisor) end -function getindex(r::Range1, s::Range1{Int}) +function getindex(r::UnitRange, s::UnitRange{Int}) sl = length(s) if sl > 0 if !(1 <= last(s) <= length(r)) @@ -191,7 +219,7 @@ function getindex(r::Range1, s::Range1{Int}) else st = oftype(r.start, r.start + s.start-1) end - Range1(st, sl) + range(st, sl) end function getindex(r::StepRange, s::Range{Int}) @@ -204,16 +232,16 @@ function getindex(r::StepRange, s::Range{Int}) else st = oftype(r.start, r.start + (first(s)-1)*step(r)) end - StepRange(st, step(r)*step(s), sl) + range(st, step(r)*step(s), sl) end -getindex(r::FloatRange, s::Range1) = r[first(s)]:step(r):r[last(s)] +getindex(r::FloatRange, s::UnitRange) = r[first(s)]:step(r):r[last(s)] function show(io::IO, r::Range) step(r) == 0 ? invoke(show,(IO,Any),io,r) : print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) end -show(io::IO, r::Range1) = print(io, repr(first(r)), ':', repr(last(r))) +show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) isequal{T<:Range}(r::T, s::T) = (first(r)==first(s)) & (step(r)==step(s)) & (last(r)==last(s)) @@ -247,17 +275,17 @@ hash(r::Range) = # TODO: isless? -intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::Range1{T2}) = max(r.start,s.start):min(last(r),last(s)) +intersect{T1<:Integer, T2<:Integer}(r::UnitRange{T1}, s::UnitRange{T2}) = max(r.start,s.start):min(last(r),last(s)) -intersect{T<:Integer}(i::Integer, r::Range1{T}) = +intersect{T<:Integer}(i::Integer, r::UnitRange{T}) = i < first(r) ? (first(r):i) : i > last(r) ? (i:last(r)) : (i:i) -intersect{T<:Integer}(r::Range1{T}, i::Integer) = intersect(i, r) +intersect{T<:Integer}(r::UnitRange{T}, i::Integer) = intersect(i, r) -function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::StepRange{T2}) +function intersect{T1<:Integer, T2<:Integer}(r::UnitRange{T1}, s::StepRange{T2}) if length(s) == 0 - Range1(first(r), 0) + range(first(r), 0) elseif step(s) == 0 intersect(first(s), r) elseif step(s) < 0 @@ -274,7 +302,7 @@ function intersect{T1<:Integer, T2<:Integer}(r::Range1{T1}, s::StepRange{T2}) end end -function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::Range1{T2}) +function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::UnitRange{T2}) if step(r) < 0 reverse(intersect(s, reverse(r))) else @@ -284,7 +312,7 @@ end function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::StepRange{T2}) if length(r) == 0 || length(s) == 0 - return StepRange(first(r), step(r), 0) + return range(first(r), step(r), 0) elseif step(s) < 0 return intersect(r, reverse(s)) elseif step(r) < 0 @@ -314,7 +342,7 @@ function intersect{T1<:Integer, T2<:Integer}(r::StepRange{T1}, s::StepRange{T2}) if rem(start1 - start2, g) != 0 # Unaligned, no overlap possible. - return StepRange(start1, a, 0) + return range(start1, a, 0) end z = div(start1 - start2, g) @@ -336,7 +364,7 @@ function intersect(r::Range, s::Range...) end # findin (the index of intersection) -function _findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::Range1{T2}) +function _findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::UnitRange{T2}) local ifirst local ilast fspan = first(span) @@ -357,53 +385,53 @@ function _findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::Range1{T2}) ifirst, ilast end -function findin{T1<:Integer, T2<:Integer}(r::Range1{T1}, span::Range1{T2}) +function findin{T1<:Integer, T2<:Integer}(r::UnitRange{T1}, span::UnitRange{T2}) ifirst, ilast = _findin(r, span) ifirst:ilast end -function findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::Range1{T2}) +function findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::UnitRange{T2}) ifirst, ilast = _findin(r, span) ifirst:1:ilast end ## linear operations on ranges ## --(r::OrdinalRange) = StepRange(-r.start, -step(r), length(r)) +-(r::OrdinalRange) = range(-r.start, -step(r), length(r)) -(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) -+(x::Integer, r::Range1) = Range1(x + r.start, length(r)) ++(x::Integer, r::UnitRange) = range(x + r.start, length(r)) +(x::Real, r::Range) = (x+first(r)):step(r):(x+last(r)) -#+(x::Real, r::StepRange) = StepRange(x + r.start, r.step, length(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) +(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) --(r::Range1, x::Integer) = Range1(r.start-x, length(r)) --(r::StepRange , x::Real) = StepRange(r.start-x, r.step, length(r)) +-(r::UnitRange, x::Integer) = 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) -.*(x::Real, r::OrdinalRange) = StepRange(x*r.start, x*step(r), length(r)) +.*(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) .*(r::Range, x::Real) = x .* r .*(r::FloatRange, x::Real) = x .* r -./(r::OrdinalRange, x::Real) = StepRange(r.start/x, step(r)/x, length(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) # TODO: better implementations for FloatRanges? function +(r1::OrdinalRange, r2::OrdinalRange) r1l = length(r1) r1l == length(r2) || error("argument dimensions must match") - StepRange(r1.start+r2.start, step(r1)+step(r2), r1l) + range(r1.start+r2.start, step(r1)+step(r2), r1l) end function -(r1::OrdinalRange, r2::OrdinalRange) r1l = length(r1) r1l == length(r2) || error("argument dimensions must match") - StepRange(r1.start-r2.start, step(r1)-step(r2), r1l) + range(r1.start-r2.start, step(r1)-step(r2), r1l) end ## non-linear operations on ranges ## @@ -442,20 +470,20 @@ function vcat{T}(rs::Range{T}...) return a end -reverse(r::OrdinalRange) = StepRange(last(r), -step(r), length(r)) +reverse(r::OrdinalRange) = range(last(r), -step(r), length(r)) reverse(r::FloatRange) = FloatRange(last(r), -r.step, r.len, r.divisor) ## sorting ## -issorted(r::Range1) = true +issorted(r::UnitRange) = true issorted(r::Range) = step(r) >= 0 -sort(r::Range1) = r -sort!(r::Range1) = r +sort(r::UnitRange) = r +sort!(r::UnitRange) = r sort{T<:Real}(r::Range{T}) = issorted(r) ? r : reverse(r) -sortperm(r::Range1) = 1:length(r) +sortperm(r::UnitRange) = 1:length(r) sortperm{T<:Real}(r::Range{T}) = issorted(r) ? (1:1:length(r)) : (length(r):-1:1) function sum{T<:Real}(r::Range{T}) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 22f6d7bb4320c..d4c269f325da7 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -2262,6 +2262,10 @@ Mathematical Operators Called by ``:`` syntax for constructing ranges. +.. function:: range(start, [step], length) + + Construct a range by length, given a starting value and optional step (defaults to 1). + .. _==: .. function:: ==(x, y) diff --git a/test/euler.jl b/test/euler.jl index c7081bfdf47e8..04fd4f3b29c9b 100644 --- a/test/euler.jl +++ b/test/euler.jl @@ -76,7 +76,9 @@ function euler11(grid,n) j = n:size(grid,2)-n+1, di = -1:1, dj = -1:1 di == dj == 0 && continue - idx = sub2ind(size(grid), StepRange(i,di,n), StepRange(j,dj,n)) + idx = sub2ind(size(grid), + di==0 ? fill(i,n) : range(i,di,n), + dj==0 ? fill(j,n) : range(j,dj,n)) m = max(m,prod(grid[idx])) end return m From d9d3a6c503abfa971ab60080d46828dbb00337a6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 31 Mar 2014 00:09:07 -0400 Subject: [PATCH 07/11] remove * and div for Char export UnitRange NEWS for range changes remove random test for BigInt ranges, since they now have BigInt lengths, for which we can't yet generate random numbers. --- NEWS.md | 22 ++++++++++++++++++++++ base/char.jl | 2 -- base/deprecated.jl | 3 +++ base/exports.jl | 1 + base/random.jl | 6 +++--- contrib/julia-mode.el | 2 +- test/random.jl | 4 ++-- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index da8bf3f4f040b..b537c3d5e9f32 100644 --- a/NEWS.md +++ b/NEWS.md @@ -230,6 +230,22 @@ Library improvements * Faster performance on `fill!` and `copy!` for array types not supporting efficient linear indexing ([#5671], [#5387]) + * Changes to range types ([#5585]) + + * `Range` is now the abstract range type, instead of `Ranges` + + * New function `range` for constructing ranges by length + + * `Range` is now `StepRange`, and `Range1` is now `UnitRange`. Their + constructors accept end points instead of lengths. Both are subtypes of a + new abstract type `OrdinalRange`. + + * Ranges now support `BigInt` and general ordinal types. + + * Very large ranges (e.g. `0:typemax(Int)`) can now be constructed, but some + operations (e.g. `length`) will raise an `OverflowError`. + + Deprecated or removed --------------------- @@ -268,6 +284,8 @@ Deprecated or removed * `infs` and `nans` are deprecated in favor of the more general `fill`. + * `*` and `div` are no longer supported for `Char`. + [#4042]: https://github.com/JuliaLang/julia/issues/4042 [#5164]: https://github.com/JuliaLang/julia/issues/5164 [#4026]: https://github.com/JuliaLang/julia/issues/4026 @@ -342,9 +360,13 @@ Deprecated or removed [#6169]: https://github.com/JuliaLang/julia/issues/6169 [#5970]: https://github.com/JuliaLang/julia/issues/5970 [#6197]: https://github.com/JuliaLang/julia/pull/6197 +<<<<<<< HEAD [#5387]: https://github.com/JuliaLang/julia/pull/5387 [#5671]: https://github.com/JuliaLang/julia/pull/5671 [#5380]: https://github.com/JuliaLang/julia/pull/5380 +======= +[#5585]: https://github.com/JuliaLang/julia/issues/5585 +>>>>>>> remove * and div for Char Julia v0.2.0 Release Notes ========================== diff --git a/base/char.jl b/base/char.jl index ab4454cf1a0f9..f1aa284cc154f 100644 --- a/base/char.jl +++ b/base/char.jl @@ -20,8 +20,6 @@ promote_rule(::Type{Char}, ::Type{Uint128}) = Uint128 # numeric operations +(x::Char , y::Char ) = int(x)+int(y) -*(x::Char , y::Char ) = int(x)*int(y) -div(x::Char , y::Char ) = div(int(x),int(y)) # ordinal operations +(x::Char , y::Integer) = char(int(x)+int(y)) diff --git a/base/deprecated.jl b/base/deprecated.jl index 22c0a71fa0aa5..755a16f6eac09 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -388,6 +388,9 @@ const Stat = StatStruct export CharString const CharString = UTF32String +export Ranges +const Ranges = Range + @deprecate set_rounding(r::RoundingMode) set_rounding(Float64,r) @deprecate get_rounding() get_rounding(Float64) @deprecate with_rounding(f::Function, r::RoundingMode) with_rounding(f::Function, Float64, r) diff --git a/base/exports.jl b/base/exports.jl index 634a7e7e723f3..63c13b709b530 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -112,6 +112,7 @@ export TmStruct, Triangular, Tridiagonal, + UnitRange, UTF16String, UTF32String, VecOrMat, diff --git a/base/random.jl b/base/random.jl index 11cf23637ad1a..78afa27649e65 100644 --- a/base/random.jl +++ b/base/random.jl @@ -149,14 +149,14 @@ immutable RandIntGen{T<:Integer, U<:Unsigned} RandIntGen(a::T, k::U) = new(a, k, div(typemax(U),k)*k) end -RandIntGen{T<:Unsigned}(r::Range1{T}) = RandIntGen{T,T}(first(r), convert(T, length(r))) +RandIntGen{T<:Unsigned}(r::UnitRange{T}) = RandIntGen{T,T}(first(r), convert(T, length(r))) # specialized versions for (T, U) in [(Uint8, Uint32), (Uint16, Uint32), (Int8, Uint32), (Int16, Uint32), (Int32, Uint32), (Int64, Uint64), (Int128, Uint128), (Bool, Uint32), (Char, Uint32)] - @eval RandIntGen(r::Range1{$T}) = RandIntGen{$T, $U}(first(r), convert($U, length(r))) + @eval RandIntGen(r::UnitRange{$T}) = RandIntGen{$T, $U}(first(r), convert($U, length(r))) end function rand{T<:Integer,U<:Unsigned}(g::RandIntGen{T,U}) @@ -167,7 +167,7 @@ function rand{T<:Integer,U<:Unsigned}(g::RandIntGen{T,U}) convert(T, g.a + rem(x, g.k)) end -rand{T<:Union(Signed,Unsigned,Bool,Char)}(r::Range1{T}) = rand(RandIntGen(r)) +rand{T<:Union(Signed,Unsigned,Bool,Char)}(r::UnitRange{T}) = rand(RandIntGen(r)) rand{T<:Real}(r::Range{T}) = convert(T, first(r) + rand(0:(length(r)-1)) * step(r)) function rand!(g::RandIntGen, A::AbstractArray) diff --git a/contrib/julia-mode.el b/contrib/julia-mode.el index 63419282fd555..119530bef9014 100644 --- a/contrib/julia-mode.el +++ b/contrib/julia-mode.el @@ -77,7 +77,7 @@ ].* \\(in\\)\\(\\s-\\|$\\)+") (defconst julia-font-lock-keywords - (list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|DenseArray\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Ranges\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" . + (list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|DenseArray\\|Range\\|OrdinalRange\\|StepRange\\|UnitRange\\|FloatRange\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" . font-lock-type-face) (cons (concat "\\<\\(" diff --git a/test/random.jl b/test/random.jl index a144c67cf2786..a7ddc619ad367 100644 --- a/test/random.jl +++ b/test/random.jl @@ -21,8 +21,8 @@ A = zeros(2, 2) randn!(MersenneTwister(42), A) @test A == [-0.5560268761438383 0.027155338009146598; -0.44438335710729554 -0.2994840903585204] -for T in (Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Int128, Uint128, Char, BigInt, - Float16, Float32, Float64, Rational{Int}) +for T in (Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64, Int128, Uint128, + Char, Float16, Float32, Float64, Rational{Int}) r = rand(convert(T, 97):convert(T, 122)) @test typeof(r) == T @test 97 <= r <= 122 From cd15b6486a13b16aef796fa9a24cdf60ee7241ca Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 31 Mar 2014 11:47:13 -0400 Subject: [PATCH 08/11] add back a couple to_index methods --- base/operators.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/operators.jl b/base/operators.jl index df42a6f6c26ac..a5a47a294e33a 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -282,7 +282,9 @@ end # convert to integer index to_index(i::Int) = i to_index(i::Real) = convert(Int, i) +to_index(r::UnitRange{Int}) = r to_index(r::Range{Int}) = r +to_index(I::UnitRange{Bool}) = find(I) to_index(I::Range{Bool}) = find(I) to_index{T<:Real}(r::UnitRange{T}) = to_index(first(r)):to_index(last(r)) to_index{T<:Real}(r::StepRange{T}) = to_index(first(r)):to_index(step(r)):to_index(last(r)) From 221018c94acbe2129f42dafc80ce5c889fab883b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 31 Mar 2014 12:02:35 -0400 Subject: [PATCH 09/11] rename Range1 to UnitRange everywhere --- NEWS.md | 3 +++ base/abstractarray.jl | 8 ++++---- base/array.jl | 12 ++++++------ base/ascii.jl | 2 +- base/bitarray.jl | 6 +++--- base/combinatorics.jl | 4 ++-- base/darray.jl | 14 +++++++------- base/deprecated.jl | 15 +++++++++------ base/linalg/blas.jl | 8 ++++---- base/linalg/dense.jl | 2 +- base/linalg/matmul.jl | 8 ++++---- base/multi.jl | 4 ++-- base/multidimensional.jl | 16 ++++++++-------- base/precompile.jl | 16 ++++++++-------- base/random.jl | 2 +- base/range.jl | 9 ++------- base/sharedarray.jl | 8 ++++---- base/sort.jl | 8 ++++---- base/sparse/sparsematrix.jl | 2 +- base/string.jl | 4 ++-- base/subarray.jl | 14 +++++++------- base/utf8.jl | 2 +- 22 files changed, 84 insertions(+), 83 deletions(-) diff --git a/NEWS.md b/NEWS.md index b537c3d5e9f32..28f6ff0faeee3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -286,6 +286,9 @@ Deprecated or removed * `*` and `div` are no longer supported for `Char`. + * `Range` is renamed `StepRange` and `Range1` is renamed `UnitRange`. + `Ranges` is renamed `Range`. + [#4042]: https://github.com/JuliaLang/julia/issues/4042 [#5164]: https://github.com/JuliaLang/julia/issues/5164 [#4026]: https://github.com/JuliaLang/julia/issues/4026 diff --git a/base/abstractarray.jl b/base/abstractarray.jl index c92e7014561b4..5df578af69f22 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -202,7 +202,7 @@ end copy(a::AbstractArray) = copy!(similar(a), a) copy(a::AbstractArray{None}) = a # cannot be assigned into so is immutable -function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Ranges{Int}, jr_dest::Ranges{Int}, A::AbstractMatrix{S}, ir_src::Ranges{Int}, jr_src::Ranges{Int}) +function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Range{Int}, jr_dest::Range{Int}, A::AbstractMatrix{S}, ir_src::Range{Int}, jr_src::Range{Int}) if length(ir_dest) != length(ir_src) || length(jr_dest) != length(jr_src) error("source and destination must have same size") end @@ -220,7 +220,7 @@ function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Ranges{Int}, jr_dest::Ranges{ return B end -function copy_transpose!{R,S}(B::AbstractMatrix{R}, ir_dest::Ranges{Int}, jr_dest::Ranges{Int}, A::AbstractVecOrMat{S}, ir_src::Ranges{Int}, jr_src::Ranges{Int}) +function copy_transpose!{R,S}(B::AbstractMatrix{R}, ir_dest::Range{Int}, jr_dest::Range{Int}, A::AbstractVecOrMat{S}, ir_src::Range{Int}, jr_src::Range{Int}) if length(ir_dest) != length(jr_src) || length(jr_dest) != length(ir_src) error("source and destination must have same size") end @@ -322,7 +322,7 @@ full(x::AbstractArray) = x for fn in _numeric_conversion_func_names @eval begin $fn(r::StepRange) = $fn(r.start):$fn(r.step):$fn(last(r)) - $fn(r::Range1) = $fn(r.start):$fn(last(r)) + $fn(r::UnitRange) = $fn(r.start):$fn(last(r)) end end @@ -456,7 +456,7 @@ end ## get (getindex with a default value) ## -typealias RangeVecIntList{A<:AbstractVector{Int}} Union((Union(Range, AbstractVector{Int})...), AbstractVector{Range1{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}) +typealias RangeVecIntList{A<:AbstractVector{Int}} Union((Union(Range, AbstractVector{Int})...), AbstractVector{UnitRange{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}) get(A::AbstractArray, i::Integer, default) = in_bounds(length(A), i) ? A[i] : default get(A::AbstractArray, I::(), default) = similar(A, typeof(default), 0) diff --git a/base/array.jl b/base/array.jl index b5493091e34b2..471158774d4b2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -248,8 +248,8 @@ getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Real...) = arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5),to_index(I)...) -# Fast copy using copy! for Range1 -function getindex(A::Array, I::Range1{Int}) +# Fast copy using copy! for UnitRange +function getindex(A::Array, I::UnitRange{Int}) lI = length(I) X = similar(A, lI) if lI > 0 @@ -316,7 +316,7 @@ function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}) return A end -function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}) +function setindex!{T}(A::Array{T}, X::Array{T}, I::UnitRange{Int}) if length(X) != length(I) throw_setindex_mismatch(X, (I,)) end @@ -545,7 +545,7 @@ function deleteat!(a::Vector, i::Integer) return _deleteat!(a, i, 1) end -function deleteat!{T<:Integer}(a::Vector, r::Range1{T}) +function deleteat!{T<:Integer}(a::Vector, r::UnitRange{T}) n = length(a) f = first(r) l = last(r) @@ -599,7 +599,7 @@ function splice!(a::Vector, i::Integer, ins::AbstractArray=_default_splice) return v end -function splice!{T<:Integer}(a::Vector, r::Range1{T}, ins::AbstractArray=_default_splice) +function splice!{T<:Integer}(a::Vector, r::UnitRange{T}, ins::AbstractArray=_default_splice) v = a[r] m = length(ins) if m == 0 @@ -1157,7 +1157,7 @@ function indexin{T}(a::AbstractArray{T}, b::AbstractArray{T}) end # findin (the index of intersection) -function findin(a, b::Range1) +function findin(a, b::UnitRange) ind = Array(Int, 0) f = first(b) l = last(b) diff --git a/base/ascii.jl b/base/ascii.jl index 2d07abf71f570..4d819f3dd56f8 100644 --- a/base/ascii.jl +++ b/base/ascii.jl @@ -15,7 +15,7 @@ getindex(s::ASCIIString, i::Int) = (x=s.data[i]; x < 0x80 ? char(x) : '\ufffd') sizeof(s::ASCIIString) = sizeof(s.data) getindex(s::ASCIIString, r::Vector) = ASCIIString(getindex(s.data,r)) -getindex(s::ASCIIString, r::Range1{Int}) = ASCIIString(getindex(s.data,r)) +getindex(s::ASCIIString, r::UnitRange{Int}) = ASCIIString(getindex(s.data,r)) getindex(s::ASCIIString, indx::AbstractVector{Int}) = ASCIIString(s.data[indx]) search(s::ASCIIString, c::Char, i::Integer) = c < 0x80 ? search(s.data,uint8(c),i) : 0 rsearch(s::ASCIIString, c::Char, i::Integer) = c < 0x80 ? rsearch(s.data,uint8(c),i) : 0 diff --git a/base/bitarray.jl b/base/bitarray.jl index b1648a38ba282..23fa71472a857 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -707,7 +707,7 @@ function deleteat!(B::BitVector, i::Integer) return _deleteat!(B, i) end -function deleteat!(B::BitVector, r::Range1{Int}) +function deleteat!(B::BitVector, r::UnitRange{Int}) n = length(B) i_f = first(r) i_l = last(r) @@ -787,7 +787,7 @@ splice!(B::BitVector, i::Integer, ins::AbstractVector{Bool}) = splice!(B, i, bit const _default_bit_splice = BitVector(0) -function splice!(B::BitVector, r::Range1{Int}, ins::BitVector = _default_bit_splice) +function splice!(B::BitVector, r::UnitRange{Int}, ins::BitVector = _default_bit_splice) n = length(B) i_f = first(r) i_l = last(r) @@ -829,7 +829,7 @@ function splice!(B::BitVector, r::Range1{Int}, ins::BitVector = _default_bit_spl return v end -splice!(B::BitVector, r::Range1{Int}, ins::AbstractVector{Bool}) = splice!(B, r, bitpack(ins)) +splice!(B::BitVector, r::UnitRange{Int}, ins::AbstractVector{Bool}) = splice!(B, r, bitpack(ins)) function empty!(B::BitVector) ccall(:jl_array_del_end, Void, (Any, Uint), B.chunks, length(B.chunks)) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 383236831a1f3..45f6372ac5ce3 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -191,7 +191,7 @@ immutable Combinations{T} end eltype(c::Combinations) = typeof(c.a) -eltype{T}(c::Combinations{Range1{T}}) = Array{T,1} +eltype{T}(c::Combinations{UnitRange{T}}) = Array{T,1} eltype{T}(c::Combinations{Range{T}}) = Array{T,1} length(c::Combinations) = binomial(length(c.a),c.t) @@ -231,7 +231,7 @@ immutable Permutations{T} end eltype(c::Permutations) = typeof(c.a) -eltype{T}(c::Permutations{Range1{T}}) = Array{T,1} +eltype{T}(c::Permutations{UnitRange{T}}) = Array{T,1} eltype{T}(c::Permutations{Range{T}}) = Array{T,1} length(c::Permutations) = factorial(length(c.a)) diff --git a/base/darray.jl b/base/darray.jl index f4a77fb524160..ae26dd97954c5 100644 --- a/base/darray.jl +++ b/base/darray.jl @@ -7,7 +7,7 @@ type DArray{T,N,A} <: AbstractArray{T,N} pmap::Vector{Int} # indexes held by piece i - indexes::Array{NTuple{N,Range1{Int}},N} + indexes::Array{NTuple{N,UnitRange{Int}},N} # cuts[d][i] = first index of chunk i in dimension d cuts::Vector{Vector{Int}} @@ -104,7 +104,7 @@ end function chunk_idxs(dims, chunks) cuts = map(defaultdist, dims, chunks) n = length(dims) - idxs = Array(NTuple{n,Range1{Int}},chunks...) + idxs = Array(NTuple{n,UnitRange{Int}},chunks...) cartesianmap(tuple(chunks...)) do cidx... idxs[cidx...] = ntuple(n, i->(cuts[i][cidx[i]]:cuts[i][cidx[i]+1]-1)) end @@ -184,7 +184,7 @@ end function convert{S,T,N}(::Type{Array{S,N}}, s::SubDArray{T,N}) I = s.indexes d = s.parent - if isa(I,(Range1{Int}...)) && S<:T && T<:S + if isa(I,(UnitRange{Int}...)) && S<:T && T<:S l = locate(d, map(first, I)...) if isequal(d.indexes[l...], I) # SubDArray corresponds to a chunk @@ -243,14 +243,14 @@ function getindex{T}(d::DArray{T}, I::(Int...)) end getindex(d::DArray) = d[1] -getindex(d::DArray, I::Union(Int,Range1{Int})...) = sub(d,I) +getindex(d::DArray, I::Union(Int,UnitRange{Int})...) = sub(d,I) copy(d::SubOrDArray) = d # local copies are obtained by convert(Array, ) or assigning from # a SubDArray to a local Array. -function setindex!(a::Array, d::DArray, I::Range1{Int}...) +function setindex!(a::Array, d::DArray, I::UnitRange{Int}...) n = length(I) @sync begin for i = 1:length(d.chunks) @@ -261,7 +261,7 @@ function setindex!(a::Array, d::DArray, I::Range1{Int}...) a end -function setindex!(a::Array, s::SubDArray, I::Range1{Int}...) +function setindex!(a::Array, s::SubDArray, I::UnitRange{Int}...) n = length(I) d = s.parent J = s.indexes @@ -293,7 +293,7 @@ end # to disambiguate setindex!(a::Array{Any}, d::SubOrDArray, i::Int) = arrayset(a, d, i) -setindex!(a::Array, d::SubOrDArray, I::Union(Int,Range1{Int})...) = +setindex!(a::Array, d::SubOrDArray, I::Union(Int,UnitRange{Int})...) = setindex!(a, d, [isa(i,Int) ? (i:i) : i for i in I ]...) ## higher-order functions ## diff --git a/base/deprecated.jl b/base/deprecated.jl index 755a16f6eac09..a2642aec53f4b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -246,13 +246,13 @@ export ComplexPair # superseded sorting API -@deprecate select(v::AbstractVector,k::Union(Int,Range1),o::Ordering) select(v,k,order=o) -@deprecate select(v::AbstractVector,k::Union(Int,Range1),f::Function) select(v,k,lt=f) -@deprecate select(f::Function,v::AbstractVector,k::Union(Int,Range1)) select(v,k,lt=f) +@deprecate select(v::AbstractVector,k::Union(Int,UnitRange),o::Ordering) select(v,k,order=o) +@deprecate select(v::AbstractVector,k::Union(Int,UnitRange),f::Function) select(v,k,lt=f) +@deprecate select(f::Function,v::AbstractVector,k::Union(Int,UnitRange)) select(v,k,lt=f) -# @deprecate select!(v::AbstractVector,k::Union(Int,Range1),o::Ordering) select!(v,k,order=o) -@deprecate select!(v::AbstractVector,k::Union(Int,Range1),f::Function) select!(v,k,lt=f) -@deprecate select!(f::Function,v::AbstractVector,k::Union(Int,Range1)) select!(v,k,lt=f) +# @deprecate select!(v::AbstractVector,k::Union(Int,UnitRange),o::Ordering) select!(v,k,order=o) +@deprecate select!(v::AbstractVector,k::Union(Int,UnitRange),f::Function) select!(v,k,lt=f) +@deprecate select!(f::Function,v::AbstractVector,k::Union(Int,UnitRange)) select!(v,k,lt=f) @deprecate sort(v::AbstractVector,o::Ordering) sort(v,order=o) @deprecate sort(v::AbstractVector,a::Algorithm) sort(v,alg=a) @@ -391,6 +391,9 @@ const CharString = UTF32String export Ranges const Ranges = Range +export Range1 +const Range1 = UnitRange + @deprecate set_rounding(r::RoundingMode) set_rounding(Float64,r) @deprecate get_rounding() get_rounding(Float64) @deprecate with_rounding(f::Function, r::RoundingMode) with_rounding(f::Function, Float64, r) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 832710f4e3b5f..099bf41709de1 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -214,8 +214,8 @@ function axpy!{T<:BlasFloat,Ta<:Number}(alpha::Ta, x::Array{T}, y::Array{T}) axpy!(length(x), convert(T,alpha), x, 1, y, 1) end -function axpy!{T<:BlasFloat,Ta<:Number,Ti<:Integer}(alpha::Ta, x::Array{T}, rx::Union(Range1{Ti},Range{Ti}), - y::Array{T}, ry::Union(Range1{Ti},Range{Ti})) +function axpy!{T<:BlasFloat,Ta<:Number,Ti<:Integer}(alpha::Ta, x::Array{T}, rx::Union(UnitRange{Ti},Range{Ti}), + y::Array{T}, ry::Union(UnitRange{Ti},Range{Ti})) length(rx)==length(ry) || throw(DimensionMismatch("")) @@ -845,8 +845,8 @@ end end # module -function copy!{T<:BlasFloat,Ti<:Integer}(dest::Array{T}, rdest::Union(Range1{Ti},Range{Ti}), - src::Array{T}, rsrc::Union(Range1{Ti},Range{Ti})) +function copy!{T<:BlasFloat,Ti<:Integer}(dest::Array{T}, rdest::Union(UnitRange{Ti},Range{Ti}), + src::Array{T}, rsrc::Union(UnitRange{Ti},Range{Ti})) if minimum(rdest) < 1 || maximum(rdest) > length(dest) || minimum(rsrc) < 1 || maximum(rsrc) > length(src) throw(BoundsError()) end diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 2128c24cdac59..33a60f101164a 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -13,7 +13,7 @@ isposdef{T<:Number}(A::Matrix{T}, UL::Char) = isposdef!(float64(A), UL) isposdef{T<:Number}(A::Matrix{T}) = isposdef!(float64(A)) isposdef(x::Number) = imag(x)==0 && real(x) > 0 -function norm{T<:BlasFloat, TI<:Integer}(x::StridedVector{T}, rx::Union(Range1{TI},Range{TI})) +function norm{T<:BlasFloat, TI<:Integer}(x::StridedVector{T}, rx::Union(UnitRange{TI},Range{TI})) (minimum(rx) < 1 || maximum(rx) > length(x)) && throw(BoundsError()) BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) end diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 0bb46ff09002a..f7c5b2c953e21 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -28,14 +28,14 @@ scale(b::Vector, A::Matrix) = scale!(similar(b, promote_type(eltype(A),eltype(b) dot{T<:BlasReal}(x::Vector{T}, y::Vector{T}) = BLAS.dot(x, y) dot{T<:BlasComplex}(x::Vector{T}, y::Vector{T}) = BLAS.dotc(x, y) -function dot{T<:BlasReal, TI<:Integer}(x::Vector{T}, rx::Union(Range1{TI},Range{TI}), y::Vector{T}, ry::Union(Range1{TI},Range{TI})) +function dot{T<:BlasReal, TI<:Integer}(x::Vector{T}, rx::Union(UnitRange{TI},Range{TI}), y::Vector{T}, ry::Union(UnitRange{TI},Range{TI})) length(rx)==length(ry) || throw(DimensionMismatch("")) if minimum(rx) < 1 || maximum(rx) > length(x) || minimum(ry) < 1 || maximum(ry) > length(y) throw(BoundsError()) end BLAS.dot(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end -function dot{T<:BlasComplex, TI<:Integer}(x::Vector{T}, rx::Union(Range1{TI},Range{TI}), y::Vector{T}, ry::Union(Range1{TI},Range{TI})) +function dot{T<:BlasComplex, TI<:Integer}(x::Vector{T}, rx::Union(UnitRange{TI},Range{TI}), y::Vector{T}, ry::Union(UnitRange{TI},Range{TI})) length(rx)==length(ry) || throw(DimensionMismatch("")) if minimum(rx) < 1 || maximum(rx) > length(x) || minimum(ry) < 1 || maximum(ry) > length(y) throw(BoundsError()) @@ -241,7 +241,7 @@ end lapack_size(t::Char, M::AbstractVecOrMat) = (size(M, t=='N' ? 1:2), size(M, t=='N' ? 2:1)) -function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, tM::Char, M::AbstractMatrix{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) +function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::UnitRange{Int}, jr_dest::UnitRange{Int}, tM::Char, M::AbstractMatrix{S}, ir_src::UnitRange{Int}, jr_src::UnitRange{Int}) if tM == 'N' copy!(B, ir_dest, jr_dest, M, ir_src, jr_src) else @@ -250,7 +250,7 @@ function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{ end end -function copy_transpose!{R,S}(B::AbstractMatrix{R}, ir_dest::Range1{Int}, jr_dest::Range1{Int}, tM::Char, M::AbstractVecOrMat{S}, ir_src::Range1{Int}, jr_src::Range1{Int}) +function copy_transpose!{R,S}(B::AbstractMatrix{R}, ir_dest::UnitRange{Int}, jr_dest::UnitRange{Int}, tM::Char, M::AbstractVecOrMat{S}, ir_src::UnitRange{Int}, jr_src::UnitRange{Int}) if tM == 'N' Base.copy_transpose!(B, ir_dest, jr_dest, M, ir_src, jr_src) else diff --git a/base/multi.jl b/base/multi.jl index 234bb60752548..5eafe68476f85 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -1342,7 +1342,7 @@ function splitrange(N::Int, np::Int) each = div(N,np) extras = rem(N,np) nchunks = each > 0 ? np : extras - chunks = Array(Range1{Int}, nchunks) + chunks = Array(UnitRange{Int}, nchunks) lo = 1 for i in 1:nchunks hi = lo + each - 1 @@ -1415,7 +1415,7 @@ macro parallel(args...) var = loop.args[1+i].args[1] loop.args[1+i] = :( $(esc(var)) = ($(ranges[i]))[I[$i]] ) end - return :( DArray((I::(Range1{Int}...))->($loop), + return :( DArray((I::(UnitRange{Int}...))->($loop), tuple($(map(r->:(length($r)),ranges)...))) ) end elseif na==2 diff --git a/base/multidimensional.jl b/base/multidimensional.jl index e2ab1e966e451..07e7df2470d77 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -189,20 +189,20 @@ end # contiguous multidimensional indexing: if the first dimension is a range, # we can get some performance from using copy_chunks! -function unsafe_getindex(B::BitArray, I0::Range1{Int}) +function unsafe_getindex(B::BitArray, I0::UnitRange{Int}) X = BitArray(length(I0)) copy_chunks!(X.chunks, 1, B.chunks, first(I0), length(I0)) return X end -function getindex(B::BitArray, I0::Range1{Int}) +function getindex(B::BitArray, I0::UnitRange{Int}) checkbounds(B, I0) return unsafe_getindex(B, I0) end -getindex{T<:Real}(B::BitArray, I0::Range1{T}) = getindex(B, to_index(I0)) +getindex{T<:Real}(B::BitArray, I0::UnitRange{T}) = getindex(B, to_index(I0)) -@ngenerate N BitArray{length(index_shape(I0, I...))} function unsafe_getindex(B::BitArray, I0::Range1{Int}, I::NTuple{N,Union(Int,Range1{Int})}...) +@ngenerate N BitArray{length(index_shape(I0, I...))} function unsafe_getindex(B::BitArray, I0::UnitRange{Int}, I::NTuple{N,Union(Int,UnitRange{Int})}...) X = BitArray(index_shape(I0, I...)) f0 = first(I0) @@ -285,7 +285,7 @@ end # contiguous multidimensional indexing: if the first dimension is a range, # we can get some performance from using copy_chunks! -function unsafe_setindex!(B::BitArray, X::BitArray, I0::Range1{Int}) +function unsafe_setindex!(B::BitArray, X::BitArray, I0::UnitRange{Int}) l0 = length(I0) l0 == 0 && return B f0 = first(I0) @@ -293,7 +293,7 @@ function unsafe_setindex!(B::BitArray, X::BitArray, I0::Range1{Int}) return B end -function unsafe_setindex!(B::BitArray, x::Bool, I0::Range1{Int}) +function unsafe_setindex!(B::BitArray, x::Bool, I0::UnitRange{Int}) l0 = length(I0) l0 == 0 && return B f0 = first(I0) @@ -301,7 +301,7 @@ function unsafe_setindex!(B::BitArray, x::Bool, I0::Range1{Int}) return B end -@ngenerate N typeof(B) function unsafe_setindex!(B::BitArray, X::BitArray, I0::Range1{Int}, I::NTuple{N,Union(Int,Range1{Int})}...) +@ngenerate N typeof(B) function unsafe_setindex!(B::BitArray, X::BitArray, I0::UnitRange{Int}, I::NTuple{N,Union(Int,UnitRange{Int})}...) length(X) == 0 && return B f0 = first(I0) l0 = length(I0) @@ -329,7 +329,7 @@ end return B end -@ngenerate N typeof(B) function unsafe_setindex!(B::BitArray, x::Bool, I0::Range1{Int}, I::NTuple{N,Union(Int,Range1{Int})}...) +@ngenerate N typeof(B) function unsafe_setindex!(B::BitArray, x::Bool, I0::UnitRange{Int}, I::NTuple{N,Union(Int,UnitRange{Int})}...) f0 = first(I0) l0 = length(I0) l0 == 0 && return B diff --git a/base/precompile.jl b/base/precompile.jl index a98794caf36a6..44bf5ce1d1c9e 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -81,10 +81,10 @@ precompile(read, (IOStream, Array{Uint32,1})) precompile(hex, (Char, Int)) precompile(abs, (Char,)) precompile(abstract_eval, (LambdaStaticData, ObjectIdDict, StaticVarInfo)) -precompile(length, (Range1{Int},)) -precompile(start, (Range1{Int},)) -precompile(done, (Range1{Int},Int)) -precompile(next, (Range1{Int},Int)) +precompile(length, (UnitRange{Int},)) +precompile(start, (UnitRange{Int},)) +precompile(done, (UnitRange{Int},Int)) +precompile(next, (UnitRange{Int},Int)) precompile(IOStream, (ASCIIString, Array{Uint8,1})) precompile(mk_tupleref, (SymbolNode, Int)) precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) @@ -118,8 +118,8 @@ precompile(occurs_outside_tupleref, (Function, Symbol, StaticVarInfo, Int)) precompile(search, (ASCIIString, Regex, Int)) precompile(setindex!, (Vector{Any}, Uint8, Int)) precompile(setindex!, (Vector{Any}, Vector{Any}, Int)) -precompile(first, (Range1{Int},)) -precompile(last, (Range1{Int},)) +precompile(first, (UnitRange{Int},)) +precompile(last, (UnitRange{Int},)) precompile(isempty, (ASCIIString,)) precompile(normpath, (ASCIIString,)) precompile(print, (ASCIIString,)) @@ -226,8 +226,8 @@ precompile(LineEdit.fix_conflicts!, (Nothing, Int)) precompile(convert, (Type{Function}, Function)) precompile(convert, (Type{Any}, Function)) precompile(similar, (Array{LineEdit.Prompt, 1}, Type{LineEdit.TextInterface}, (Int,))) -precompile(setindex!, (Array{LineEdit.TextInterface, 1}, LineEdit.Prompt, Range1{Int})) -precompile(setindex!, (Array{LineEdit.TextInterface, 1}, LineEdit.HistoryPrompt, Range1{Int})) +precompile(setindex!, (Array{LineEdit.TextInterface, 1}, LineEdit.Prompt, UnitRange{Int})) +precompile(setindex!, (Array{LineEdit.TextInterface, 1}, LineEdit.HistoryPrompt, UnitRange{Int})) precompile(getindex, (Array{LineEdit.TextInterface, 1}, Int)) precompile(start, (Array{LineEdit.TextInterface, 1},)) precompile(done, (Array{LineEdit.TextInterface, 1}, Int)) diff --git a/base/random.jl b/base/random.jl index 78afa27649e65..6fe4bf385a40f 100644 --- a/base/random.jl +++ b/base/random.jl @@ -177,7 +177,7 @@ function rand!(g::RandIntGen, A::AbstractArray) return A end -rand!{T<:Union(Signed,Unsigned,Bool,Char)}(r::Range1{T}, A::AbstractArray) = rand!(RandIntGen(r), A) +rand!{T<:Union(Signed,Unsigned,Bool,Char)}(r::UnitRange{T}, A::AbstractArray) = rand!(RandIntGen(r), A) function rand!{T<:Real}(r::Range{T}, A::AbstractArray) g = RandIntGen(0:(length(r)-1)) diff --git a/base/range.jl b/base/range.jl index 0a2a8c3ec4f5b..0d4a5f8810b39 100644 --- a/base/range.jl +++ b/base/range.jl @@ -21,13 +21,13 @@ immutable StepRange{T,S,D} <: OrdinalRange{T,S} if D<:FloatingPoint || S<:FloatingPoint error("StepRange should not be used with floating point") end - step == 0 && error("step cannot be zero") + step == zero(S) && error("step cannot be zero") step != step && error("step cannot be NaN") start = convert(D, start) stop = convert(D, stop) - if (step>0 && stopstart) + if (step>zero(S) && stopstart) sentinel = start else remain = (stop - start) % step # should be robust to overflow @@ -49,10 +49,6 @@ immutable UnitRange{T<:Real,D} <: OrdinalRange{T,Int} end UnitRange{T<:Real}(start::T, stop::T) = UnitRange{T, typeof(start+1)}(start, stop) -# deprecated -export Range1 -const Range1 = UnitRange - colon(a, b) = colon(promote(a,b)...) colon{T<:Real}(start::T, stop::T) = UnitRange(start, stop) @@ -238,7 +234,6 @@ end getindex(r::FloatRange, s::UnitRange) = r[first(s)]:step(r):r[last(s)] function show(io::IO, r::Range) - step(r) == 0 ? invoke(show,(IO,Any),io,r) : print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) end show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 93e3dff667365..e0a4c596f2891 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -194,15 +194,15 @@ end shmem_fill(v, I::Int...; kwargs...) = shmem_fill(v, I; kwargs...) # rand variant with range -function shmem_rand(TR::Union(DataType, Range1), dims; kwargs...) - if isa(TR, Range1) +function shmem_rand(TR::Union(DataType, UnitRange), dims; kwargs...) + if isa(TR, UnitRange) SharedArray(Int, dims; init = S -> map!((x)->rand(TR), S.loc_subarr_1d), kwargs...) else SharedArray(TR, dims; init = S -> map!((x)->rand(TR), S.loc_subarr_1d), kwargs...) end end -shmem_rand(TR::Union(DataType, Range1), i::Int; kwargs...) = shmem_rand(TR, (i,); kwargs...) -shmem_rand(TR::Union(DataType, Range1), I::Int...; kwargs...) = shmem_rand(TR, I; kwargs...) +shmem_rand(TR::Union(DataType, UnitRange), i::Int; kwargs...) = shmem_rand(TR, (i,); kwargs...) +shmem_rand(TR::Union(DataType, UnitRange), I::Int...; kwargs...) = shmem_rand(TR, I; kwargs...) shmem_rand(dims; kwargs...) = shmem_rand(Float64, dims; kwargs...) shmem_rand(I::Int...; kwargs...) = shmem_rand(I; kwargs...) diff --git a/base/sort.jl b/base/sort.jl index cbc85920dcabe..1e67f72b4d6bf 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -81,7 +81,7 @@ function select!(v::AbstractVector, k::Int, lo::Int, hi::Int, o::Ordering) return v[lo] end -function select!(v::AbstractVector, r::Range1, lo::Int, hi::Int, o::Ordering) +function select!(v::AbstractVector, r::UnitRange, lo::Int, hi::Int, o::Ordering) a, b = first(r), last(r) lo <= a <= b <= hi || error("select index $k is out of range $lo:$hi") @inbounds while true @@ -111,12 +111,12 @@ function select!(v::AbstractVector, r::Range1, lo::Int, hi::Int, o::Ordering) end end -select!(v::AbstractVector, k::Union(Int,Range1), o::Ordering) = select!(v,k,1,length(v),o) -select!(v::AbstractVector, k::Union(Int,Range1); +select!(v::AbstractVector, k::Union(Int,UnitRange), o::Ordering) = select!(v,k,1,length(v),o) +select!(v::AbstractVector, k::Union(Int,UnitRange); lt::Function=isless, by::Function=identity, rev::Bool=false, order::Ordering=Forward) = select!(v, k, ord(lt,by,rev,order)) -select(v::AbstractVector, k::Union(Int,Range1); kws...) = select!(copy(v), k; kws...) +select(v::AbstractVector, k::Union(Int,UnitRange); kws...) = select!(copy(v), k; kws...) # reference on sorted binary search: # http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index b6c163bf8b743..f13c507787315 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -929,7 +929,7 @@ end # S = A[I, J] function getindex{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) m = size(A, 1) - if isa(I, Ranges) + if isa(I, Range) if I == 1:m # whole columns return getindex_cols(A, J) else # ranges are always sorted, but maybe in reverse diff --git a/base/string.jl b/base/string.jl index 3239bd202fdee..3ee7f3fa337ee 100644 --- a/base/string.jl +++ b/base/string.jl @@ -57,7 +57,7 @@ done(s::String,i) = (i > endof(s)) getindex(s::String, i::Int) = next(s,i)[1] getindex(s::String, i::Integer) = s[int(i)] getindex(s::String, x::Real) = s[to_index(x)] -getindex{T<:Integer}(s::String, r::Range1{T}) = s[int(first(r)):int(last(r))] +getindex{T<:Integer}(s::String, r::UnitRange{T}) = s[int(first(r)):int(last(r))] # TODO: handle other ranges with stride ±1 specially? getindex(s::String, v::AbstractVector) = sprint(length(v), io->(for i in v write(io,s[i]) end)) @@ -657,7 +657,7 @@ function serialize{T}(s, ss::SubString{T}) invoke(serialize, (Any,Any), s, convert(SubString{T}, convert(T,ss))) end -function getindex(s::String, r::Range1{Int}) +function getindex(s::String, r::UnitRange{Int}) if first(r) < 1 || endof(s) < last(r) error(BoundsError) end diff --git a/base/subarray.jl b/base/subarray.jl index 8e05b30907189..0e75321242ce0 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -1,6 +1,6 @@ ## subarrays ## -typealias RangeIndex Union(Int, Range{Int}, Range1{Int}) +typealias RangeIndex Union(Int, Range{Int}, UnitRange{Int}) type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N} parent::A @@ -17,7 +17,7 @@ type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N} end #linear indexing constructor (ranges) elseif N == 1 && length(I) == 1 && A <: Array - function SubArray(p::A, i::(Range1{Int},)) + function SubArray(p::A, i::(UnitRange{Int},)) new(p, i, (length(i[1]),), [1], first(i[1])) end function SubArray(p::A, i::(Range{Int},)) @@ -35,7 +35,7 @@ type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N} else push!(newdims, length(i[j])) #may want to return error if step(i[j]) <= 0 - push!(newstrides, isa(i[j],Range1) ? pstride : + push!(newstrides, isa(i[j],UnitRange) ? pstride : pstride * step(i[j])) newfirst += (first(i[j])-1)*pstride end @@ -47,7 +47,7 @@ type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N} end #linear indexing sub (may want to rename as slice) -function sub{T,N}(A::Array{T,N}, i::(Union(Range{Int}, Range1{Int}),)) +function sub{T,N}(A::Array{T,N}, i::(Union(Range{Int}, UnitRange{Int}),)) SubArray{T,1,typeof(A),typeof(i)}(A, i) end @@ -100,7 +100,7 @@ end # Drops all Ints from a tuple of RangeIndexes ranges_only(I::Int...) = () ranges_only(i::Int, I...) = ranges_only(I...) -ranges_only(i::Union(Range{Int}, Range1{Int}), I...) = tuple(i, ranges_only(I...)...) +ranges_only(i::Union(Range{Int}, UnitRange{Int}), I...) = tuple(i, ranges_only(I...)...) function slice_internal{T,N,L}(A::AbstractArray{T,N}, i::NTuple{N,RangeIndex}, ::NTuple{L,RangeIndex}) SubArray{T,L,typeof(A),typeof(i)}(A, i) @@ -249,7 +249,7 @@ getindex{T}(S::SubArray{T,3}, I::AbstractArray{Bool,3}) = getindex_bool_1d(S, I) getindex{T}(S::SubArray{T,4}, I::AbstractArray{Bool,4}) = getindex_bool_1d(S, I) getindex{T}(S::SubArray{T,5}, I::AbstractArray{Bool,5}) = getindex_bool_1d(S, I) -getindex{T}(s::SubArray{T,1}, I::Range1{Int}) = +getindex{T}(s::SubArray{T,1}, I::UnitRange{Int}) = getindex(s.parent, (s.first_index+(first(I)-1)*s.strides[1]):s.strides[1]:(s.first_index+(last(I)-1)*s.strides[1])) getindex{T}(s::SubArray{T,1}, I::Range{Int}) = @@ -371,7 +371,7 @@ setindex!{T}(s::SubArray{T,4}, v, i::Integer, j::Integer, k::Integer, l::Integer setindex!{T}(s::SubArray{T,5}, v, i::Integer, j::Integer, k::Integer, l::Integer, m::Integer) = setindex!(s.parent, v, s.first_index +(i-1)*s.strides[1]+(j-1)*s.strides[2]+(k-1)*s.strides[3]+(l-1)*s.strides[4]+(m-1)*s.strides[5]) -setindex!{T}(s::SubArray{T,1}, v, I::Range1{Int}) = +setindex!{T}(s::SubArray{T,1}, v, I::UnitRange{Int}) = setindex!(s.parent, v, (s.first_index+(first(I)-1)*s.strides[1]):s.strides[1]:(s.first_index+(last(I)-1)*s.strides[1])) setindex!{T}(s::SubArray{T,1}, v, I::Range{Int}) = diff --git a/base/utf8.jl b/base/utf8.jl index 6938d6edc910d..1a76c8a406134 100644 --- a/base/utf8.jl +++ b/base/utf8.jl @@ -97,7 +97,7 @@ isvalid(s::UTF8String, i::Integer) = const empty_utf8 = UTF8String(Uint8[]) -function getindex(s::UTF8String, r::Range1{Int}) +function getindex(s::UTF8String, r::UnitRange{Int}) isempty(r) && return empty_utf8 i, j = first(r), last(r) d = s.data From 4b1c9d67bbfce767582f7765d2fd47c39c548eeb Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 31 Mar 2014 13:30:28 -0400 Subject: [PATCH 10/11] eliminate 2nd type parameter from UnitRange this is likely to cause too much breakage; e.g. arrays of UnitRange{Int} are common. --- base/range.jl | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/base/range.jl b/base/range.jl index 0d4a5f8810b39..b5d043bffeeb3 100644 --- a/base/range.jl +++ b/base/range.jl @@ -41,18 +41,18 @@ end StepRange{T,S}(start::T, step::S, stop::T) = StepRange{T, S, typeof(start+step)}(start, step, stop) -immutable UnitRange{T<:Real,D} <: OrdinalRange{T,Int} - start::D - sentinel::D +immutable UnitRange{T<:Real} <: OrdinalRange{T,Int} + start::T + stop::T - UnitRange(start, stop) = new(start, ifelse(stop >= start, stop+1, convert(D,start))) + UnitRange(start, stop) = new(start, ifelse(stop >= start, stop, start-1)) end -UnitRange{T<:Real}(start::T, stop::T) = UnitRange{T, typeof(start+1)}(start, stop) +UnitRange{T<:Real}(start::T, stop::T) = UnitRange{T}(start, stop) colon(a, b) = colon(promote(a,b)...) colon{T<:Real}(start::T, stop::T) = UnitRange(start, stop) -range(a::Real, len::Integer) = UnitRange{typeof(a), typeof(a+len-1)}(a, a+len-1) +range(a::Real, len::Integer) = UnitRange{typeof(a)}(a, a+len-1) colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop) range{T}(a::T, len::Integer) = @@ -145,26 +145,28 @@ similar(r::Range, T::Type, dims::Dims) = Array(T, dims) size(r::Range) = (length(r),) +isempty(r::StepRange) = r.start == r.sentinel +isempty(r::UnitRange) = r.start > r.stop isempty(r::FloatRange) = length(r)==0 -isempty(r::OrdinalRange) = r.start == r.sentinel step(r::StepRange) = r.step -step(r::UnitRange) = one(r.sentinel - r.start) +step(r::UnitRange) = 1 step(r::FloatRange) = r.step/r.divisor length(r::StepRange) = integer(div(r.sentinel - r.start, r.step)) -length(r::UnitRange) = integer(r.sentinel - r.start) +length(r::UnitRange) = integer(r.stop - r.start + 1) length(r::FloatRange) = integer(r.len) length{T<:Union(Int,Uint)}(r::StepRange{T}) = checked_add(div(checked_sub(r.sentinel-r.step, r.start), r.step), one(T)) length{T<:Union(Int,Uint)}(r::UnitRange{T}) = - checked_add(checked_sub(r.sentinel-one(T), r.start), one(T)) + checked_add(checked_sub(r.stop, r.start), one(T)) first{T}(r::OrdinalRange{T}) = oftype(T, r.start) first(r::FloatRange) = r.start/r.divisor -last{T}(r::OrdinalRange{T}) = oftype(T, r.sentinel-step(r)) +last{T}(r::StepRange{T}) = oftype(T, r.sentinel-step(r)) +last(r::UnitRange) = r.stop last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) minimum(r::UnitRange) = isempty(r) ? error("range must be non-empty") : first(r) @@ -185,11 +187,13 @@ start(r::FloatRange) = 0 next{T}(r::FloatRange{T}, i) = (oftype(T, (r.start + i*r.step)/r.divisor), i+1) done(r::FloatRange, i) = (length(r) <= i) -start(r::OrdinalRange) = r.start -next{T}(r::OrdinalRange{T}, i) = (oftype(T,i), i+step(r)) -done(r::OrdinalRange, i) = i==r.sentinel +start(r::StepRange) = r.start +next{T}(r::StepRange{T}, i) = (oftype(T,i), i+step(r)) +done(r::StepRange, i) = i==r.sentinel -next{T,D}(r::UnitRange{T,D}, i) = (oftype(T,i), oftype(D, i+1)) +start(r::UnitRange) = oftype(r.start+1, r.start) +next{T}(r::UnitRange{T}, i) = (oftype(T,i), i+1) +done(r::OrdinalRange, i) = i==oftype(i,r.stop)+1 ## indexing From ff28fbb934c1c07d5740cdf756692d8cb1fc5dcf Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 31 Mar 2014 23:41:25 -0400 Subject: [PATCH 11/11] remove third type parameter from StepRange it expressed a degree of freedom that was not really there, since it really depended on the first two parameters. --- base/range.jl | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/base/range.jl b/base/range.jl index b5d043bffeeb3..37a8cd44658c4 100644 --- a/base/range.jl +++ b/base/range.jl @@ -8,38 +8,31 @@ abstract Range{T} <: AbstractArray{T,1} abstract OrdinalRange{T,S} <: Range{T} -# A StepRange has a start point, and moves by some step up through a last point. -# The element type is T, but we allow T+S to give a value from a lifted -# domain D instead of from T. We store a sentinel value stop+step from domain D, -# since T might not have any available sentinel value. -immutable StepRange{T,S,D} <: OrdinalRange{T,S} - start::D +immutable StepRange{T,S} <: OrdinalRange{T,S} + start::T step::S - sentinel::D + stop::T - function StepRange(start, step::S, stop) - if D<:FloatingPoint || S<:FloatingPoint + function StepRange(start::T, step::S, stop::T) + if T<:FloatingPoint || S<:FloatingPoint error("StepRange should not be used with floating point") end step == zero(S) && error("step cannot be zero") step != step && error("step cannot be NaN") - start = convert(D, start) - stop = convert(D, stop) - - if (step>zero(S) && stopstart) - sentinel = start + if (step>zero(S) && stopstart) + last = start-step else remain = (stop - start) % step # should be robust to overflow - sentinel = stop + (step - remain) + last = stop - remain end - new(start, step, sentinel) + new(start, step, last) end end StepRange{T,S}(start::T, step::S, stop::T) = - StepRange{T, S, typeof(start+step)}(start, step, stop) + StepRange{T, S}(start, step, stop) immutable UnitRange{T<:Real} <: OrdinalRange{T,Int} start::T @@ -56,7 +49,7 @@ range(a::Real, len::Integer) = UnitRange{typeof(a)}(a, a+len-1) colon{T}(start::T, stop::T) = StepRange(start, one(stop-start), stop) range{T}(a::T, len::Integer) = - StepRange{T, typeof(a-a), typeof(a+one(a-a))}(a, one(a-a), a+oftype(a-a,(len-1))) + StepRange{T, typeof(a-a)}(a, one(a-a), a+oftype(a-a,(len-1))) # first promote start and stop, leaving step alone # this is for non-numeric ranges where step can be quite different @@ -65,7 +58,7 @@ colon{A,C}(a::A, b, c::C) = colon(convert(promote_type(A,C),a), b, convert(promo colon{T}(start::T, step, stop::T) = StepRange(start, step, stop) range{T,S}(a::T, step::S, len::Integer) = - StepRange{T, S, typeof(a+one(S))}(a, step, a+step*(len-1)) + StepRange{T, S}(a, step, a+step*(len-1)) ## floating point ranges @@ -145,7 +138,7 @@ similar(r::Range, T::Type, dims::Dims) = Array(T, dims) size(r::Range) = (length(r),) -isempty(r::StepRange) = r.start == r.sentinel +isempty(r::StepRange) = r.start == r.stop+r.step isempty(r::UnitRange) = r.start > r.stop isempty(r::FloatRange) = length(r)==0 @@ -153,19 +146,19 @@ step(r::StepRange) = r.step step(r::UnitRange) = 1 step(r::FloatRange) = r.step/r.divisor -length(r::StepRange) = integer(div(r.sentinel - r.start, r.step)) +length(r::StepRange) = integer(div(r.stop+r.step - r.start, r.step)) length(r::UnitRange) = integer(r.stop - r.start + 1) length(r::FloatRange) = integer(r.len) length{T<:Union(Int,Uint)}(r::StepRange{T}) = - checked_add(div(checked_sub(r.sentinel-r.step, r.start), r.step), one(T)) + checked_add(div(checked_sub(r.stop, r.start), r.step), one(T)) length{T<:Union(Int,Uint)}(r::UnitRange{T}) = checked_add(checked_sub(r.stop, r.start), one(T)) first{T}(r::OrdinalRange{T}) = oftype(T, r.start) first(r::FloatRange) = r.start/r.divisor -last{T}(r::StepRange{T}) = oftype(T, r.sentinel-step(r)) +last{T}(r::StepRange{T}) = r.stop last(r::UnitRange) = r.stop last{T}(r::FloatRange{T}) = oftype(T, (r.start + (r.len-1)*r.step)/r.divisor) @@ -187,9 +180,11 @@ start(r::FloatRange) = 0 next{T}(r::FloatRange{T}, i) = (oftype(T, (r.start + i*r.step)/r.divisor), i+1) done(r::FloatRange, i) = (length(r) <= i) -start(r::StepRange) = r.start -next{T}(r::StepRange{T}, i) = (oftype(T,i), i+step(r)) -done(r::StepRange, i) = i==r.sentinel +# NOTE: For ordinal ranges, we assume start+step might be from a +# lifted domain (e.g. Int8+Int8 => Int); use that for iterating. +start(r::StepRange) = oftype(r.start+r.step, r.start) +next{T}(r::StepRange{T}, i) = (oftype(T,i), i+r.step) +done(r::StepRange, i) = i==oftype(i,r.stop)+r.step start(r::UnitRange) = oftype(r.start+1, r.start) next{T}(r::UnitRange{T}, i) = (oftype(T,i), i+1)