@@ -209,68 +209,29 @@ range(a::AbstractFloat, st::Real, len::Integer) = FloatRange(a, float(st), len,
209209
210210# # linspace and logspace
211211
212- immutable LinSpace{T<: AbstractFloat } <: Range{T}
212+ immutable LinSpace{T} <: Range{T}
213213 start:: T
214214 stop:: T
215- len:: T
216- divisor:: T
217- end
218-
219- function linspace {T<:AbstractFloat} (start:: T , stop:: T , len:: T )
220- len == round (len) || throw (InexactError ())
221- 0 <= len || error (" linspace($start , $stop , $len ): negative length" )
222- if len == 0
223- n = convert (T, 2 )
224- if isinf (n* start) || isinf (n* stop)
225- start /= n; stop /= n; n = one (T)
215+ len:: Int
216+ lendiv:: Int
217+
218+ function LinSpace (start,stop,len)
219+ len >= 0 || error (" linspace($start , $stop , $len ): negative length" )
220+ if len == 1
221+ start == stop || error (" linspace($start , $stop , $len ): endpoints differ" )
222+ return new (start, stop, 1 , 1 )
226223 end
227- return LinSpace ( - start, - stop, - one (T), n )
224+ new ( start,stop,len, max (len - 1 , 1 ) )
228225 end
229- if len == 1
230- start == stop || error (" linspace($start , $stop , $len ): endpoints differ" )
231- return LinSpace (- start, - start, zero (T), one (T))
232- end
233- n = convert (T, len - 1 )
234- len - n == 1 || error (" linspace($start , $stop , $len ): too long for $T " )
235- a0, b = rat (start)
236- a = convert (T,a0)
237- if a/ convert (T,b) == start
238- c0, d = rat (stop)
239- c = convert (T,c0)
240- if c/ convert (T,d) == stop
241- e = lcm (b,d)
242- a *= div (e,b)
243- c *= div (e,d)
244- s = convert (T,n* e)
245- if isinf (a* n) || isinf (c* n)
246- s, p = frexp (s)
247- p2 = oftype (s,2 )^ p
248- a /= p2; c /= p2
249- end
250- if a* n/ s == start && c* n/ s == stop
251- return LinSpace (a, c, len, s)
252- end
253- end
254- end
255- a, c, s = start, stop, n
256- if isinf (a* n) || isinf (c* n)
257- s, p = frexp (s)
258- p2 = oftype (s,2 )^ p
259- a /= p2; c /= p2
260- end
261- if a* n/ s == start && c* n/ s == stop
262- return LinSpace (a, c, len, s)
263- end
264- return LinSpace (start, stop, len, n)
265226end
266- function linspace {T<:AbstractFloat} (start :: T , stop :: T , len :: Real )
267- T_len = convert (T, len)
268- T_len == len || throw ( InexactError () )
269- linspace (start, stop, T_len )
227+
228+ function LinSpace (start, stop, len:: Integer )
229+ T = typeof ((stop - start) / len )
230+ LinSpace {T} (start, stop, len )
270231end
271232
272233"""
273- linspace(start::Real , stop::Real , n::Real =50)
234+ linspace(start, stop, n=50)
274235
275236Construct a range of `n` linearly spaced elements from `start` to `stop`.
276237
@@ -280,8 +241,7 @@ julia> linspace(1.3,2.9,9)
280241 1.3,1.5,1.7,1.9,2.1,2.3,2.5,2.7,2.9
281242```
282243"""
283- linspace (start:: Real , stop:: Real , len:: Real = 50 ) =
284- linspace (promote (AbstractFloat (start), AbstractFloat (stop))... , len)
244+ linspace (start, stop, len:: Real = 50 ) = LinSpace (start, stop, Int (len))
285245
286246function show (io:: IO , r:: LinSpace )
287247 print (io, " linspace(" )
@@ -398,7 +358,7 @@ julia> step(linspace(2.5,10.9,85))
398358step (r:: StepRange ) = r. step
399359step (r:: AbstractUnitRange ) = 1
400360step (r:: FloatRange ) = r. step/ r. divisor
401- step {T} (r:: LinSpace{T} ) = ifelse (r . len <= 0 , convert (T, NaN ), (r . stop - r . start) / r. divisor)
361+ step (r:: LinSpace ) = ( last (r) - first (r)) / r. lendiv
402362
403363unsafe_length (r:: Range ) = length (r) # generic fallback
404364
@@ -412,7 +372,7 @@ unsafe_length(r::OneTo) = r.stop
412372length (r:: AbstractUnitRange ) = unsafe_length (r)
413373length (r:: OneTo ) = unsafe_length (r)
414374length (r:: FloatRange ) = Integer (r. len)
415- length (r:: LinSpace ) = Integer ( r. len + signbit (r . len - 1 ))
375+ length (r:: LinSpace ) = r. len
416376
417377function length {T<:Union{Int,UInt,Int64,UInt64}} (r:: StepRange{T} )
418378 isempty (r) && return zero (T)
@@ -450,11 +410,11 @@ end
450410first {T} (r:: OrdinalRange{T} ) = convert (T, r. start)
451411first {T} (r:: OneTo{T} ) = one (T)
452412first {T} (r:: FloatRange{T} ) = convert (T, r. start/ r. divisor)
453- first {T} (r:: LinSpace{T} ) = convert (T, (r . len - 1 ) * r . start/ r . divisor)
413+ first (r:: LinSpace ) = r . start
454414
455415last {T} (r:: OrdinalRange{T} ) = convert (T, r. stop)
456416last {T} (r:: FloatRange{T} ) = convert (T, (r. start + (r. len- 1 )* r. step)/ r. divisor)
457- last {T} (r:: LinSpace{T} ) = convert (T, (r . len - 1 ) * r . stop/ r . divisor)
417+ last (r:: LinSpace ) = r . stop
458418
459419minimum (r:: AbstractUnitRange ) = isempty (r) ? throw (ArgumentError (" range must be non-empty" )) : first (r)
460420maximum (r:: AbstractUnitRange ) = isempty (r) ? throw (ArgumentError (" range must be non-empty" )) : last (r)
@@ -477,8 +437,10 @@ next{T}(r::FloatRange{T}, i::Int) =
477437
478438start (r:: LinSpace ) = 1
479439done (r:: LinSpace , i:: Int ) = length (r) < i
480- next {T} (r:: LinSpace{T} , i:: Int ) =
481- (convert (T, ((r. len- i)* r. start + (i- 1 )* r. stop)/ r. divisor), i+ 1 )
440+ function next (r:: LinSpace , i:: Int )
441+ @_inline_meta
442+ unsafe_getindex (r, i), i+ 1
443+ end
482444
483445start (r:: StepRange ) = oftype (r. start + r. step, r. start)
484446next {T} (r:: StepRange{T} , i) = (convert (T,i), i+ r. step)
@@ -536,10 +498,25 @@ function getindex{T}(r::FloatRange{T}, i::Integer)
536498 convert (T, (r. start + (i- 1 )* r. step)/ r. divisor)
537499end
538500
539- function getindex {T} (r:: LinSpace{T} , i:: Integer )
501+ function getindex (r:: LinSpace , i:: Integer )
540502 @_inline_meta
541503 @boundscheck checkbounds (r, i)
542- convert (T, ((r. len- i)* r. start + (i- 1 )* r. stop)/ r. divisor)
504+ unsafe_getindex (r, i)
505+ end
506+
507+ # This is separate to make it useful even when running with --check-bounds=yes
508+ function unsafe_getindex (r:: LinSpace , i:: Integer )
509+ d = r. lendiv
510+ j, a, b = ifelse (2 i >= length (r), (i- 1 , r. start, r. stop), (length (r)- i, r. stop, r. start))
511+ lerpi (j, d, a, b)
512+ end
513+
514+ # High-precision interpolation. Accurate for t ∈ [0.5,1], so that 1-t is exact.
515+ function lerpi {T} (j:: Integer , d:: Integer , a:: T , b:: T )
516+ @_inline_meta
517+ t = j/ d
518+ # computes (1-t)*a + t*b
519+ T (fma (t, b, fma (- t, a, a)))
543520end
544521
545522getindex (r:: Range , :: Colon ) = copy (r)
@@ -581,11 +558,11 @@ end
581558function getindex {T} (r:: LinSpace{T} , s:: OrdinalRange )
582559 @_inline_meta
583560 @boundscheck checkbounds (r, s)
584- sl:: T = length (s)
561+ sl = length (s)
585562 ifirst = first (s)
586563 ilast = last (s)
587- vfirst:: T = ((r . len - ifirst) * r . start + (ifirst - 1 ) * r . stop) / r . divisor
588- vlast:: T = ((r . len - ilast) * r . start + (ilast - 1 ) * r . stop) / r . divisor
564+ vfirst = unsafe_getindex (r, ifirst)
565+ vlast = unsafe_getindex (r, ilast)
589566 return linspace (vfirst, vlast, sl)
590567end
591568
@@ -739,43 +716,58 @@ end
739716
740717- (r:: OrdinalRange ) = range (- first (r), - step (r), length (r))
741718- (r:: FloatRange ) = FloatRange (- r. start, - r. step, r. len, r. divisor)
742- - (r:: LinSpace ) = LinSpace (- r. start, - r. stop, r. len, r . divisor )
719+ - (r:: LinSpace ) = LinSpace (- r. start, - r. stop, r. len)
743720
744721.+ (x:: Real , r:: AbstractUnitRange ) = range (x + first (r), length (r))
745722.+ (x:: Real , r:: Range ) = (x+ first (r)): step (r): (x+ last (r))
746723# .+(x::Real, r::StepRange) = range(x + r.start, r.step, length(r))
747724.+ (x:: Real , r:: FloatRange ) = FloatRange (r. divisor* x + r. start, r. step, r. len, r. divisor)
748- function .+ {T}(x:: Real , r:: LinSpace{T} )
749- x2 = x * r. divisor / (r. len - 1 )
750- LinSpace (x2 + r. start, x2 + r. stop, r. len, r. divisor)
725+ function .+ (x:: Real , r:: LinSpace )
726+ LinSpace (x + r. start, x + r. stop, r. len)
727+ end
728+ function .+ (x:: Number , r:: LinSpace )
729+ LinSpace (x + r. start, x + r. stop, r. len)
730+ end
731+ function .+ {T}(x:: Ref{T} , r:: LinSpace{T} )
732+ LinSpace (x + r. start, x + r. stop, r. len)
751733end
752734.+ (r:: Range , x:: Real ) = x + r
753735# .+(r::FloatRange, x::Real) = x + r
754736
755737.- (x:: Real , r:: Range ) = (x- first (r)): - step (r): (x- last (r))
756738.- (x:: Real , r:: FloatRange ) = FloatRange (r. divisor* x - r. start, - r. step, r. len, r. divisor)
757739function .- (x:: Real , r:: LinSpace )
758- x2 = x * r. divisor / (r. len - 1 )
759- LinSpace (x2 - r. start, x2 - r. stop, r. len, r. divisor)
740+ LinSpace (x - r. start, x - r. stop, r. len)
741+ end
742+ function .- (x:: Number , r:: LinSpace )
743+ LinSpace (x - r. start, x - r. stop, r. len)
744+ end
745+ function .- {T}(x:: Ref{T} , r:: LinSpace{T} )
746+ LinSpace (x - r. start, x - r. stop, r. len)
760747end
761748.- (r:: AbstractUnitRange , x:: Real ) = range (first (r)- x, length (r))
762749.- (r:: StepRange , x:: Real ) = range (r. start- x, r. step, length (r))
763750.- (r:: FloatRange , x:: Real ) = FloatRange (r. start - r. divisor* x, r. step, r. len, r. divisor)
764751function .- (r:: LinSpace , x:: Real )
765- x2 = x * r. divisor / (r. len - 1 )
766- LinSpace (r. start - x2, r. stop - x2, r. len, r. divisor)
752+ LinSpace (r. start - x, r. stop - x, r. len)
753+ end
754+ function .- (r:: LinSpace , x:: Number )
755+ LinSpace (r. start - x, r. stop - x, r. len)
756+ end
757+ function .- {T}(r:: LinSpace{T} , x:: Ref{T} )
758+ LinSpace (r. start - x, r. stop - x, r. len)
767759end
768760
769761.* (x:: Real , r:: OrdinalRange ) = range (x* first (r), x* step (r), length (r))
770762.* (x:: Real , r:: FloatRange ) = FloatRange (x* r. start, x* r. step, r. len, r. divisor)
771- .* (x:: Real , r:: LinSpace ) = LinSpace (x * r. start, x * r. stop, r. len, r . divisor )
763+ .* (x:: Real , r:: LinSpace ) = LinSpace (x * r. start, x * r. stop, r. len)
772764.* (r:: Range , x:: Real ) = x .* r
773765.* (r:: FloatRange , x:: Real ) = x .* r
774766.* (r:: LinSpace , x:: Real ) = x .* r
775767
776768./ (r:: OrdinalRange , x:: Real ) = range (first (r)/ x, step (r)/ x, length (r))
777769./ (r:: FloatRange , x:: Real ) = FloatRange (r. start/ x, r. step/ x, r. len, r. divisor)
778- ./ (r:: LinSpace , x:: Real ) = LinSpace (r. start / x, r. stop / x, r. len, r . divisor )
770+ ./ (r:: LinSpace , x:: Real ) = LinSpace (r. start / x, r. stop / x, r. len)
779771
780772promote_rule {T1,T2} (:: Type{UnitRange{T1}} ,:: Type{UnitRange{T2}} ) =
781773 UnitRange{promote_type (T1,T2)}
@@ -820,20 +812,20 @@ promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) =
820812 LinSpace{promote_type (T1,T2)}
821813convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: LinSpace{T} ) = r
822814convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: LinSpace ) =
823- LinSpace {T} (r. start, r. stop, r. len, r . divisor )
815+ LinSpace {T} (r. start, r. stop, r. len)
824816
825817promote_rule {F,OR<:OrdinalRange} (:: Type{LinSpace{F}} , :: Type{OR} ) =
826818 LinSpace{promote_type (F,eltype (OR))}
827819convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: OrdinalRange ) =
828- linspace (convert (T, first (r)), convert (T, last (r)), convert (T, length (r) ))
820+ linspace (convert (T, first (r)), convert (T, last (r)), length (r))
829821convert {T} (:: Type{LinSpace} , r:: OrdinalRange{T} ) =
830822 convert (LinSpace{typeof (float (first (r)))}, r)
831823
832824# Promote FloatRange to LinSpace
833825promote_rule {F,OR<:FloatRange} (:: Type{LinSpace{F}} , :: Type{OR} ) =
834826 LinSpace{promote_type (F,eltype (OR))}
835827convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: FloatRange ) =
836- linspace (convert (T, first (r)), convert (T, last (r)), convert (T, length (r) ))
828+ linspace (convert (T, first (r)), convert (T, last (r)), length (r))
837829convert {T<:AbstractFloat} (:: Type{LinSpace} , r:: FloatRange{T} ) =
838830 convert (LinSpace{T}, r)
839831
@@ -878,7 +870,7 @@ collect(r::Range) = vcat(r)
878870
879871reverse (r:: OrdinalRange ) = colon (last (r), - step (r), first (r))
880872reverse (r:: FloatRange ) = FloatRange (r. start + (r. len- 1 )* r. step, - r. step, r. len, r. divisor)
881- reverse (r:: LinSpace ) = LinSpace (r. stop, r. start, r . len, r . divisor )
873+ reverse (r:: LinSpace ) = LinSpace (r. stop, r. start, length (r) )
882874
883875# # sorting ##
884876
0 commit comments