Skip to content

Commit

Permalink
Make LinSpace generic and endpoint-preserving. Fixes #14420.
Browse files Browse the repository at this point in the history
Implement StepRangeHiLo

Split out TwicePrecision utilities from basic Range functionality

Define AbstractTime numeric traits

Needed for tests with new ranges on 32-bit CPUs

New range performance optimizations

Add StepRangeLen to stdlib docs [ci skip]

Misc cleanups for range code

Fix printing bug with range of non-scalars

Simpler implementation of unsafe_getindex for LinSpace

Conflicts:
	base/dates/types.jl
	base/deprecated.jl
	base/exports.jl
	base/float.jl
	base/operators.jl
	base/range.jl
	doc/src/stdlib/math.md
	test/ranges.jl
  • Loading branch information
timholy committed Jan 11, 2017
1 parent 6a1e339 commit 737dd7c
Show file tree
Hide file tree
Showing 16 changed files with 1,128 additions and 289 deletions.
6 changes: 2 additions & 4 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -729,11 +729,9 @@ full(x::AbstractArray) = x

map{T<:Real}(::Type{T}, r::StepRange) = T(r.start):T(r.step):T(last(r))
map{T<:Real}(::Type{T}, r::UnitRange) = T(r.start):T(last(r))
map{T<:AbstractFloat}(::Type{T}, r::FloatRange) = FloatRange(T(r.start), T(r.step), r.len, T(r.divisor))
map{T<:AbstractFloat}(::Type{T}, r::StepRangeLen) = convert(StepRangeLen{T}, r)
function map{T<:AbstractFloat}(::Type{T}, r::LinSpace)
new_len = T(r.len)
new_len == r.len || error("$r: too long for $T")
LinSpace(T(r.start), T(r.stop), new_len, T(r.divisor))
LinSpace(T(r.start), T(r.stop), length(r))
end

## unsafe/pointer conversions ##
Expand Down
1 change: 1 addition & 0 deletions base/coreimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ typealias Cint Int32
typealias Csize_t UInt
include("promotion.jl")
include("tuple.jl")
include("traits.jl")
include("range.jl")
include("expr.jl")
include("error.jl")
Expand Down
3 changes: 3 additions & 0 deletions base/dates/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,6 @@ Base.isless(x::Date,y::Date) = isless(value(x),value(y))
Base.isless(x::DateTime,y::DateTime) = isless(value(x),value(y))
Base.isless(x::TimeType,y::TimeType) = isless(promote(x,y)...)
==(x::TimeType,y::TimeType) = ===(promote(x,y)...)

(::Type{Base.TypeOrder}){T<:AbstractTime}(::Type{T}) = Base.HasOrder()
(::Type{Base.TypeArithmetic}){T<:AbstractTime}(::Type{T}) = Base.ArithmeticOverflows()
3 changes: 2 additions & 1 deletion base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -785,4 +785,5 @@ const _oldstyle_array_vcat_ = false

Filesystem.stop_watching(stream::Filesystem._FDWatcher) = depwarn("stop_watching(::_FDWatcher) should not be used.", :stop_watching)

# End deprecations scheduled for 0.6
# FloatRange replaced by StepRangeLen
@deprecate FloatRange{T}(start::T, step, len, den) Base.floatrange(T, start, step, len, den)
2 changes: 1 addition & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export
Factorization,
FileMonitor,
Filter,
FloatRange,
StepRangeLen,
Future,
Hermitian,
UniformScaling,
Expand Down
29 changes: 25 additions & 4 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,29 @@ significand_mask(::Type{Float32}) = 0x007f_ffff
@pure exponent_bits{T<:AbstractFloat}(::Type{T}) = sizeof(T)*8 - significand_bits(T) - 1
@pure exponent_bias{T<:AbstractFloat}(::Type{T}) = Int(exponent_one(T) >> significand_bits(T))

## TwicePrecision utilities
# The numeric constants are half the number of bits in the mantissa
for (F, T, n) in ((Float16, UInt16, 5), (Float32, UInt32, 12), (Float64, UInt64, 26))
@eval begin
function truncbits(x::$F, nb)
@_inline_meta
truncmask(x, typemax($T) << nb)
end
function truncmask(x::$F, mask)
@_inline_meta
box($F, unbox($T, mask & box($T, unbox($F, x))))
end
function splitprec(x::$F)
@_inline_meta
hi = truncmask(x, typemax($T) << $n)
hi, x-hi
end
end
end

truncbits(x, nb) = x
truncmask(x, mask) = x

## Array operations on floating point numbers ##

float{T<:AbstractFloat}(A::AbstractArray{T}) = A
Expand All @@ -540,11 +563,9 @@ for fn in (:float,:big)
@eval begin
$fn(r::StepRange) = $fn(r.start):$fn(r.step):$fn(last(r))
$fn(r::UnitRange) = $fn(r.start):$fn(last(r))
$fn(r::FloatRange) = FloatRange($fn(r.start), $fn(r.step), r.len, $fn(r.divisor))
$fn(r::StepRangeLen) = StepRangeLen($fn(r.ref), $fn(r.step), length(r), r.offset)
function $fn(r::LinSpace)
new_len = $fn(r.len)
new_len == r.len || error(string(r, ": too long for ", $fn))
LinSpace($fn(r.start), $fn(r.stop), new_len, $fn(r.divisor))
LinSpace($fn(r.start), $fn(r.stop), length(r))
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -894,4 +894,9 @@ function Base.deepcopy_internal(x::BigFloat, stackdict::ObjectIdDict)
return y
end

function lerpi(j::Integer, d::Integer, a::BigFloat, b::BigFloat)
t = BigFloat(j)/d
fma(t, b, fma(-t, a, a))
end

end #module
44 changes: 14 additions & 30 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -508,45 +508,29 @@ for f in (:+, :-)
range($f(first(r1),first(r2)), $f(step(r1),step(r2)), r1l)
end

function $f{T<:AbstractFloat}(r1::FloatRange{T}, r2::FloatRange{T})
function $f{T}(r1::LinSpace{T}, r2::LinSpace{T})
len = r1.len
(len == r2.len ||
throw(DimensionMismatch("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

function $f{T<:AbstractFloat}(r1::LinSpace{T}, r2::LinSpace{T})
len = r1.len
(len == r2.len ||
throw(DimensionMismatch("argument dimensions must match")))
divisor1, divisor2 = r1.divisor, r2.divisor
if divisor1 == divisor2
LinSpace{T}($f(r1.start, r2.start), $f(r1.stop, r2.stop),
len, divisor1)
else
linspace(convert(T, $f(first(r1), first(r2))),
convert(T, $f(last(r1), last(r2))), len)
end
linspace(convert(T, $f(first(r1), first(r2))),
convert(T, $f(last(r1), last(r2))), len)
end

$f(r1::Union{FloatRange, OrdinalRange, LinSpace},
r2::Union{FloatRange, OrdinalRange, LinSpace}) =
$f(r1::Union{StepRangeLen, OrdinalRange, LinSpace},
r2::Union{StepRangeLen, OrdinalRange, LinSpace}) =
$f(promote(r1, r2)...)
end
end

function +{T,S}(r1::StepRangeLen{T,S}, r2::StepRangeLen{T,S})
len = length(r1)
(len == length(r2) ||
throw(DimensionMismatch("argument dimensions must match")))
StepRangeLen(first(r1)+first(r2), step(r1)+step(r2), len)
end

-(r1::StepRangeLen, r2::StepRangeLen) = +(r1, -r2)

# vectorization

macro vectorize_1arg(S,f)
Expand Down
Loading

0 comments on commit 737dd7c

Please sign in to comment.