@@ -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)
226- end
227- return LinSpace (- start, - stop, - one (T), n)
228- 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
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 )
253223 end
224+ new (start,stop,len,max (len- 1 ,1 ))
254225 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,24 @@ 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+ @inline function lerpi {T} (j:: Integer , d:: Integer , a:: T , b:: T )
516+ t = j/ d
517+ # computes (1-t)*a + t*b
518+ T (fma (t, b, fma (- t, a, a)))
543519end
544520
545521getindex (r:: Range , :: Colon ) = copy (r)
@@ -581,11 +557,11 @@ end
581557function getindex {T} (r:: LinSpace{T} , s:: OrdinalRange )
582558 @_inline_meta
583559 @boundscheck checkbounds (r, s)
584- sl:: T = length (s)
560+ sl = length (s)
585561 ifirst = first (s)
586562 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
563+ vfirst = unsafe_getindex (r, ifirst)
564+ vlast = unsafe_getindex (r, ilast)
589565 return linspace (vfirst, vlast, sl)
590566end
591567
@@ -739,43 +715,58 @@ end
739715
740716- (r:: OrdinalRange ) = range (- first (r), - step (r), length (r))
741717- (r:: FloatRange ) = FloatRange (- r. start, - r. step, r. len, r. divisor)
742- - (r:: LinSpace ) = LinSpace (- r. start, - r. stop, r. len, r . divisor )
718+ - (r:: LinSpace ) = LinSpace (- r. start, - r. stop, r. len)
743719
744720.+ (x:: Real , r:: AbstractUnitRange ) = range (x + first (r), length (r))
745721.+ (x:: Real , r:: Range ) = (x+ first (r)): step (r): (x+ last (r))
746722# .+(x::Real, r::StepRange) = range(x + r.start, r.step, length(r))
747723.+ (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)
724+ function .+ (x:: Real , r:: LinSpace )
725+ LinSpace (x + r. start, x + r. stop, r. len)
726+ end
727+ function .+ (x:: Number , r:: LinSpace )
728+ LinSpace (x + r. start, x + r. stop, r. len)
729+ end
730+ function .+ {T}(x:: Ref{T} , r:: LinSpace{T} )
731+ LinSpace (x + r. start, x + r. stop, r. len)
751732end
752733.+ (r:: Range , x:: Real ) = x + r
753734# .+(r::FloatRange, x::Real) = x + r
754735
755736.- (x:: Real , r:: Range ) = (x- first (r)): - step (r): (x- last (r))
756737.- (x:: Real , r:: FloatRange ) = FloatRange (r. divisor* x - r. start, - r. step, r. len, r. divisor)
757738function .- (x:: Real , r:: LinSpace )
758- x2 = x * r. divisor / (r. len - 1 )
759- LinSpace (x2 - r. start, x2 - r. stop, r. len, r. divisor)
739+ LinSpace (x - r. start, x - r. stop, r. len)
740+ end
741+ function .- (x:: Number , r:: LinSpace )
742+ LinSpace (x - r. start, x - r. stop, r. len)
743+ end
744+ function .- {T}(x:: Ref{T} , r:: LinSpace{T} )
745+ LinSpace (x - r. start, x - r. stop, r. len)
760746end
761747.- (r:: AbstractUnitRange , x:: Real ) = range (first (r)- x, length (r))
762748.- (r:: StepRange , x:: Real ) = range (r. start- x, r. step, length (r))
763749.- (r:: FloatRange , x:: Real ) = FloatRange (r. start - r. divisor* x, r. step, r. len, r. divisor)
764750function .- (r:: LinSpace , x:: Real )
765- x2 = x * r. divisor / (r. len - 1 )
766- LinSpace (r. start - x2, r. stop - x2, r. len, r. divisor)
751+ LinSpace (r. start - x, r. stop - x, r. len)
752+ end
753+ function .- (r:: LinSpace , x:: Number )
754+ LinSpace (r. start - x, r. stop - x, r. len)
755+ end
756+ function .- {T}(r:: LinSpace{T} , x:: Ref{T} )
757+ LinSpace (r. start - x, r. stop - x, r. len)
767758end
768759
769760.* (x:: Real , r:: OrdinalRange ) = range (x* first (r), x* step (r), length (r))
770761.* (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 )
762+ .* (x:: Real , r:: LinSpace ) = LinSpace (x * r. start, x * r. stop, r. len)
772763.* (r:: Range , x:: Real ) = x .* r
773764.* (r:: FloatRange , x:: Real ) = x .* r
774765.* (r:: LinSpace , x:: Real ) = x .* r
775766
776767./ (r:: OrdinalRange , x:: Real ) = range (first (r)/ x, step (r)/ x, length (r))
777768./ (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 )
769+ ./ (r:: LinSpace , x:: Real ) = LinSpace (r. start / x, r. stop / x, r. len)
779770
780771promote_rule {T1,T2} (:: Type{UnitRange{T1}} ,:: Type{UnitRange{T2}} ) =
781772 UnitRange{promote_type (T1,T2)}
@@ -820,20 +811,20 @@ promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) =
820811 LinSpace{promote_type (T1,T2)}
821812convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: LinSpace{T} ) = r
822813convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: LinSpace ) =
823- LinSpace {T} (r. start, r. stop, r. len, r . divisor )
814+ LinSpace {T} (r. start, r. stop, r. len)
824815
825816promote_rule {F,OR<:OrdinalRange} (:: Type{LinSpace{F}} , :: Type{OR} ) =
826817 LinSpace{promote_type (F,eltype (OR))}
827818convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: OrdinalRange ) =
828- linspace (convert (T, first (r)), convert (T, last (r)), convert (T, length (r) ))
819+ linspace (convert (T, first (r)), convert (T, last (r)), length (r))
829820convert {T} (:: Type{LinSpace} , r:: OrdinalRange{T} ) =
830821 convert (LinSpace{typeof (float (first (r)))}, r)
831822
832823# Promote FloatRange to LinSpace
833824promote_rule {F,OR<:FloatRange} (:: Type{LinSpace{F}} , :: Type{OR} ) =
834825 LinSpace{promote_type (F,eltype (OR))}
835826convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: FloatRange ) =
836- linspace (convert (T, first (r)), convert (T, last (r)), convert (T, length (r) ))
827+ linspace (convert (T, first (r)), convert (T, last (r)), length (r))
837828convert {T<:AbstractFloat} (:: Type{LinSpace} , r:: FloatRange{T} ) =
838829 convert (LinSpace{T}, r)
839830
@@ -878,7 +869,7 @@ collect(r::Range) = vcat(r)
878869
879870reverse (r:: OrdinalRange ) = colon (last (r), - step (r), first (r))
880871reverse (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 )
872+ reverse (r:: LinSpace ) = LinSpace (r. stop, r. start, length (r) )
882873
883874# # sorting ##
884875
0 commit comments