Skip to content

Commit

Permalink
Merge branch 'stevengj-floatrange_ops'
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed May 27, 2014
2 parents 08bb13a + 206881e commit b78eea9
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 11 deletions.
33 changes: 33 additions & 0 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,39 @@ to_index(I::(Any,Any,Any,Any)) = (to_index(I[1]), to_index(I[2]), to_index(I[3])
to_index(I::Tuple) = map(to_index, I)
to_index(i) = error("invalid index: $i")

# Addition/subtraction of ranges
for f in (:+, :-)
@eval begin
function $f(r1::OrdinalRange, r2::OrdinalRange)
r1l = length(r1)
r1l == length(r2) || error("argument dimensions must match")
range($f(r1.start,r2.start), $f(step(r1),step(r2)), r1l)
end

function $f{T<:FloatingPoint}(r1::FloatRange{T}, r2::FloatRange{T})
len = r1.len
len == r2.len || error("argument dimensions must match")
divisor1, divisor2 = r1.divisor, r2.divisor
if divisor1 == divisor2
FloatRange{T}($f(r1.start,r2.start), $f(r1.step,r2.step),
len, divisor1)
else
d1 = int(divisor1)
d2 = int(divisor2)
d = lcm(d1,d2)
s1 = div(d,d1)
s2 = div(d,d2)
FloatRange{T}($f(r1.start*s1, r2.start*s2),
$f(r1.step*s1, r2.step*s2), len, d)
end
end

$f(r1::FloatRange, r2::FloatRange) = $f(promote(r1,r2)...)
$f(r1::FloatRange, r2::OrdinalRange) = $f(promote(r1,r2)...)
$f(r1::OrdinalRange, r2::FloatRange) = $f(promote(r1,r2)...)
end
end

# vectorization

macro vectorize_1arg(S,f)
Expand Down
21 changes: 10 additions & 11 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -437,18 +437,17 @@ end
./(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")
range(r1.start+r2.start, step(r1)+step(r2), r1l)
end
promote_rule{T1,T2}(::Type{FloatRange{T1}},::Type{FloatRange{T2}}) =
FloatRange{promote_type(T1,T2)}
convert{T}(::Type{FloatRange{T}}, r::FloatRange) =
FloatRange{T}(r.start,r.step,r.len,r.divisor)

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)
end
promote_rule{F,OR<:OrdinalRange}(::Type{FloatRange{F}}, ::Type{OR}) =
FloatRange{promote_type(F,eltype(OR))}
convert{T}(::Type{FloatRange{T}}, r::OrdinalRange) =
FloatRange{T}(start(r), step(r), length(r), one(T))

# +/- of ranges is defined in operators.jl (to be able to use @eval etc.)

## non-linear operations on ranges ##

Expand Down
9 changes: 9 additions & 0 deletions test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,12 @@ end

# issue #6364
@test length((1:64)*(pi/5)) == 64

# issue #6973
let r1 = 1.0:0.1:2.0, r2 = 1.0f0:0.2f0:3.0f0, r3 = 1:2:21
@test r1 + r1 == 2*r1
@test r1 + r2 == 2.0:0.3:5.0
@test (r1 + r2) - r2 == r1
@test r1 + r3 == convert(FloatRange{Float64}, r3) + r1
@test r3 + r3 == 2 * r3
end

0 comments on commit b78eea9

Please sign in to comment.