@@ -209,68 +209,29 @@ range(a::AbstractFloat, st::Real, len::Integer) = FloatRange(a, float(st), len,
209
209
210
210
# # linspace and logspace
211
211
212
- immutable LinSpace{T<: AbstractFloat } <: Range{T}
212
+ immutable LinSpace{T} <: Range{T}
213
213
start:: T
214
214
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 )
226
223
end
227
- return LinSpace ( - start, - stop, - one (T), n )
224
+ new ( start,stop,len, max (len - 1 , 1 ) )
228
225
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)
265
226
end
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 )
270
231
end
271
232
272
233
"""
273
- linspace(start::Real , stop::Real , n::Real =50)
234
+ linspace(start, stop, n=50)
274
235
275
236
Construct a range of `n` linearly spaced elements from `start` to `stop`.
276
237
@@ -280,8 +241,7 @@ julia> linspace(1.3,2.9,9)
280
241
1.3,1.5,1.7,1.9,2.1,2.3,2.5,2.7,2.9
281
242
```
282
243
"""
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))
285
245
286
246
function show (io:: IO , r:: LinSpace )
287
247
print (io, " linspace(" )
@@ -398,7 +358,7 @@ julia> step(linspace(2.5,10.9,85))
398
358
step (r:: StepRange ) = r. step
399
359
step (r:: AbstractUnitRange ) = 1
400
360
step (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
402
362
403
363
unsafe_length (r:: Range ) = length (r) # generic fallback
404
364
@@ -412,7 +372,7 @@ unsafe_length(r::OneTo) = r.stop
412
372
length (r:: AbstractUnitRange ) = unsafe_length (r)
413
373
length (r:: OneTo ) = unsafe_length (r)
414
374
length (r:: FloatRange ) = Integer (r. len)
415
- length (r:: LinSpace ) = Integer ( r. len + signbit (r . len - 1 ))
375
+ length (r:: LinSpace ) = r. len
416
376
417
377
function length {T<:Union{Int,UInt,Int64,UInt64}} (r:: StepRange{T} )
418
378
isempty (r) && return zero (T)
@@ -452,11 +412,11 @@ end
452
412
first {T} (r:: OrdinalRange{T} ) = convert (T, r. start)
453
413
first {T} (r:: OneTo{T} ) = one (T)
454
414
first {T} (r:: FloatRange{T} ) = convert (T, r. start/ r. divisor)
455
- first {T} (r:: LinSpace{T} ) = convert (T, (r . len - 1 ) * r . start/ r . divisor)
415
+ first (r:: LinSpace ) = r . start
456
416
457
417
last {T} (r:: OrdinalRange{T} ) = convert (T, r. stop)
458
418
last {T} (r:: FloatRange{T} ) = convert (T, (r. start + (r. len- 1 )* r. step)/ r. divisor)
459
- last {T} (r:: LinSpace{T} ) = convert (T, (r . len - 1 ) * r . stop/ r . divisor)
419
+ last (r:: LinSpace ) = r . stop
460
420
461
421
minimum (r:: AbstractUnitRange ) = isempty (r) ? throw (ArgumentError (" range must be non-empty" )) : first (r)
462
422
maximum (r:: AbstractUnitRange ) = isempty (r) ? throw (ArgumentError (" range must be non-empty" )) : last (r)
@@ -479,8 +439,10 @@ next{T}(r::FloatRange{T}, i::Int) =
479
439
480
440
start (r:: LinSpace ) = 1
481
441
done (r:: LinSpace , i:: Int ) = length (r) < i
482
- next {T} (r:: LinSpace{T} , i:: Int ) =
483
- (convert (T, ((r. len- i)* r. start + (i- 1 )* r. stop)/ r. divisor), i+ 1 )
442
+ function next (r:: LinSpace , i:: Int )
443
+ @_inline_meta
444
+ unsafe_getindex (r, i), i+ 1
445
+ end
484
446
485
447
start (r:: StepRange ) = oftype (r. start + r. step, r. start)
486
448
next {T} (r:: StepRange{T} , i) = (convert (T,i), i+ r. step)
@@ -538,10 +500,25 @@ function getindex{T}(r::FloatRange{T}, i::Integer)
538
500
convert (T, (r. start + (i- 1 )* r. step)/ r. divisor)
539
501
end
540
502
541
- function getindex {T} (r:: LinSpace{T} , i:: Integer )
503
+ function getindex (r:: LinSpace , i:: Integer )
542
504
@_inline_meta
543
505
@boundscheck checkbounds (r, i)
544
- convert (T, ((r. len- i)* r. start + (i- 1 )* r. stop)/ r. divisor)
506
+ unsafe_getindex (r, i)
507
+ end
508
+
509
+ # This is separate to make it useful even when running with --check-bounds=yes
510
+ function unsafe_getindex (r:: LinSpace , i:: Integer )
511
+ d = r. lendiv
512
+ j, a, b = ifelse (2 i >= length (r), (i- 1 , r. start, r. stop), (length (r)- i, r. stop, r. start))
513
+ lerpi (j, d, a, b)
514
+ end
515
+
516
+ # High-precision interpolation. Accurate for t ∈ [0.5,1], so that 1-t is exact.
517
+ function lerpi {T} (j:: Integer , d:: Integer , a:: T , b:: T )
518
+ @_inline_meta
519
+ t = j/ d
520
+ # computes (1-t)*a + t*b
521
+ T (fma (t, b, fma (- t, a, a)))
545
522
end
546
523
547
524
getindex (r:: Range , :: Colon ) = copy (r)
@@ -583,11 +560,11 @@ end
583
560
function getindex {T} (r:: LinSpace{T} , s:: OrdinalRange )
584
561
@_inline_meta
585
562
@boundscheck checkbounds (r, s)
586
- sl:: T = length (s)
563
+ sl = length (s)
587
564
ifirst = first (s)
588
565
ilast = last (s)
589
- vfirst:: T = ((r . len - ifirst) * r . start + (ifirst - 1 ) * r . stop) / r . divisor
590
- vlast:: T = ((r . len - ilast) * r . start + (ilast - 1 ) * r . stop) / r . divisor
566
+ vfirst = unsafe_getindex (r, ifirst)
567
+ vlast = unsafe_getindex (r, ilast)
591
568
return linspace (vfirst, vlast, sl)
592
569
end
593
570
@@ -741,18 +718,18 @@ end
741
718
742
719
- (r:: OrdinalRange ) = range (- first (r), - step (r), length (r))
743
720
- (r:: FloatRange ) = FloatRange (- r. start, - r. step, r. len, r. divisor)
744
- - (r:: LinSpace ) = LinSpace (- r. start, - r. stop, r. len, r . divisor )
721
+ - (r:: LinSpace ) = LinSpace (- r. start, - r. stop, r. len)
745
722
746
723
+ (x:: Real , r:: AbstractUnitRange ) = range (x + first (r), length (r))
747
724
+ (x:: Real , r:: Range ) = (x+ first (r)): step (r): (x+ last (r))
748
725
# +(x::Real, r::StepRange) = range(x + r.start, r.step, length(r))
749
726
+ (x:: Real , r:: FloatRange ) = FloatRange (r. divisor* x + r. start, r. step, r. len, r. divisor)
750
- function + {T}(x:: Real , r:: LinSpace{T} )
751
- x2 = x * r. divisor / (r. len - 1 )
752
- LinSpace (x2 + r. start, x2 + r. stop, r. len, r. divisor)
727
+ function + (x:: Real , r:: LinSpace )
728
+ LinSpace (x + r. start, x + r. stop, r. len)
729
+ end
730
+ function + (x:: Number , r:: LinSpace )
731
+ LinSpace (x + r. start, x + r. stop, r. len)
753
732
end
754
- + (r:: Range , x:: Real ) = x + r
755
- # +(r::FloatRange, x::Real) = x + r
756
733
757
734
- (x:: Real , r:: Range ) = (x- first (r)): - step (r): (x- last (r))
758
735
- (x:: Real , r:: FloatRange ) = FloatRange (r. divisor* x - r. start, - r. step, r. len, r. divisor)
778
755
/ (r:: OrdinalRange , x:: Real ) = range (first (r)/ x, step (r)/ x, length (r))
779
756
/ (r:: FloatRange , x:: Real ) = FloatRange (r. start/ x, r. step/ x, r. len, r. divisor)
780
757
/ (r:: LinSpace , x:: Real ) = LinSpace (r. start / x, r. stop / x, r. len, r. divisor)
758
+ ====== =
759
+ .- (x:: Real , r:: Range ) = (x- first (r)): - step (r): (x- last (r))
760
+ .- (x:: Real , r:: FloatRange ) = FloatRange (r. divisor* x - r. start, - r. step, r. len, r. divisor)
761
+ function .- (x:: Real , r:: LinSpace )
762
+ LinSpace (x - r. start, x - r. stop, r. len)
763
+ end
764
+ function .- (x:: Number , r:: LinSpace )
765
+ LinSpace (x - r. start, x - r. stop, r. len)
766
+ end
767
+ function .- {T}(x:: Ref{T} , r:: LinSpace{T} )
768
+ LinSpace (x - r. start, x - r. stop, r. len)
769
+ end
770
+ .- (r:: AbstractUnitRange , x:: Real ) = range (first (r)- x, length (r))
771
+ .- (r:: StepRange , x:: Real ) = range (r. start- x, r. step, length (r))
772
+ .- (r:: FloatRange , x:: Real ) = FloatRange (r. start - r. divisor* x, r. step, r. len, r. divisor)
773
+ function .- (r:: LinSpace , x:: Real )
774
+ LinSpace (r. start - x, r. stop - x, r. len)
775
+ end
776
+ function .- (r:: LinSpace , x:: Number )
777
+ LinSpace (r. start - x, r. stop - x, r. len)
778
+ end
779
+ function .- {T}(r:: LinSpace{T} , x:: Ref{T} )
780
+ LinSpace (r. start - x, r. stop - x, r. len)
781
+ end
782
+
783
+ .* (x:: Real , r:: OrdinalRange ) = range (x* first (r), x* step (r), length (r))
784
+ .* (x:: Real , r:: FloatRange ) = FloatRange (x* r. start, x* r. step, r. len, r. divisor)
785
+ .* (x:: Real , r:: LinSpace ) = LinSpace (x * r. start, x * r. stop, r. len)
786
+ .* (r:: Range , x:: Real ) = x .* r
787
+ .* (r:: FloatRange , x:: Real ) = x .* r
788
+ .* (r:: LinSpace , x:: Real ) = x .* r
789
+
790
+ ./ (r:: OrdinalRange , x:: Real ) = range (first (r)/ x, step (r)/ x, length (r))
791
+ ./ (r:: FloatRange , x:: Real ) = FloatRange (r. start/ x, r. step/ x, r. len, r. divisor)
792
+ ./ (r:: LinSpace , x:: Real ) = LinSpace (r. start / x, r. stop / x, r. len)
793
+ >>>>>> > 6f27 d2b... Make LinSpace generic and endpoint- preserving. Fixes # 14420.
781
794
782
795
promote_rule {T1,T2} (:: Type{UnitRange{T1}} ,:: Type{UnitRange{T2}} ) =
783
796
UnitRange{promote_type (T1,T2)}
@@ -822,20 +835,20 @@ promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) =
822
835
LinSpace{promote_type (T1,T2)}
823
836
convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: LinSpace{T} ) = r
824
837
convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: LinSpace ) =
825
- LinSpace {T} (r. start, r. stop, r. len, r . divisor )
838
+ LinSpace {T} (r. start, r. stop, r. len)
826
839
827
840
promote_rule {F,OR<:OrdinalRange} (:: Type{LinSpace{F}} , :: Type{OR} ) =
828
841
LinSpace{promote_type (F,eltype (OR))}
829
842
convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: OrdinalRange ) =
830
- linspace (convert (T, first (r)), convert (T, last (r)), convert (T, length (r) ))
843
+ linspace (convert (T, first (r)), convert (T, last (r)), length (r))
831
844
convert {T} (:: Type{LinSpace} , r:: OrdinalRange{T} ) =
832
845
convert (LinSpace{typeof (float (first (r)))}, r)
833
846
834
847
# Promote FloatRange to LinSpace
835
848
promote_rule {F,OR<:FloatRange} (:: Type{LinSpace{F}} , :: Type{OR} ) =
836
849
LinSpace{promote_type (F,eltype (OR))}
837
850
convert {T<:AbstractFloat} (:: Type{LinSpace{T}} , r:: FloatRange ) =
838
- linspace (convert (T, first (r)), convert (T, last (r)), convert (T, length (r) ))
851
+ linspace (convert (T, first (r)), convert (T, last (r)), length (r))
839
852
convert {T<:AbstractFloat} (:: Type{LinSpace} , r:: FloatRange{T} ) =
840
853
convert (LinSpace{T}, r)
841
854
@@ -877,7 +890,7 @@ collect(r::Range) = vcat(r)
877
890
878
891
reverse (r:: OrdinalRange ) = colon (last (r), - step (r), first (r))
879
892
reverse (r:: FloatRange ) = FloatRange (r. start + (r. len- 1 )* r. step, - r. step, r. len, r. divisor)
880
- reverse (r:: LinSpace ) = LinSpace (r. stop, r. start, r . len, r . divisor )
893
+ reverse (r:: LinSpace ) = LinSpace (r. stop, r. start, length (r) )
881
894
882
895
# # sorting ##
883
896
0 commit comments