@@ -163,10 +163,81 @@ range(a::FloatingPoint, st::FloatingPoint, len::Integer) = FloatRange(a,st,len,o
163
163
range (a:: Real , st:: FloatingPoint , len:: Integer ) = FloatRange (float (a), st, len, one (st))
164
164
range (a:: FloatingPoint , st:: Real , len:: Integer ) = FloatRange (a, float (st), len, one (a))
165
165
166
- linrange (a:: Real , b:: Real , len:: Integer ) =
167
- len >= 2 ? range (a, (b- a)/ (len- 1 ), len) :
168
- len == 1 && a == b ? range (a, zero ((b- a)/ (len- 1 )), 1 ) :
169
- throw (ArgumentError (" invalid range length" ))
166
+ # # linspace and logspace
167
+
168
+ immutable LinSpace{T<: FloatingPoint } <: Range{T}
169
+ start:: T
170
+ stop:: T
171
+ len:: T
172
+ divisor:: T
173
+ end
174
+
175
+ function linspace {T<:FloatingPoint} (start:: T , stop:: T , len:: T )
176
+ len == round (len) || throw (InexactError ())
177
+ 0 <= len || error (" linspace($start , $stop , $len ): negative length" )
178
+ if len == 0
179
+ n = convert (T, 2 )
180
+ if isinf (n* start) || isinf (n* stop)
181
+ start /= n; stop /= n; n = one (T)
182
+ end
183
+ return LinSpace (- start, - stop, - one (T), n)
184
+ end
185
+ if len == 1
186
+ start == stop || error (" linspace($start , $stop , $len ): endpoints differ" )
187
+ return LinSpace (- start, - start, zero (T), one (T))
188
+ end
189
+ n = convert (T, len - 1 )
190
+ len - n == 1 || error (" linspace($start , $stop , $len ): too long for $T " )
191
+ a0, b = rat (start)
192
+ a = convert (T,a0)
193
+ if a/ convert (T,b) == start
194
+ c0, d = rat (stop)
195
+ c = convert (T,c0)
196
+ if c/ convert (T,d) == stop
197
+ e = lcm (b,d)
198
+ a *= div (e,b)
199
+ c *= div (e,d)
200
+ s = convert (T,n* e)
201
+ if isinf (a* n) || isinf (c* n)
202
+ s, p = frexp (s)
203
+ p = oftype (s,2 )^ p
204
+ a /= p; c /= p
205
+ end
206
+ if a* n/ s == start && c* n/ s == stop
207
+ return LinSpace (a, c, len, s)
208
+ end
209
+ end
210
+ end
211
+ a, c, s = start, stop, n
212
+ if isinf (a* n) || isinf (c* n)
213
+ s, p = frexp (s)
214
+ p = oftype (s,2 )^ p
215
+ a /= p; c /= p
216
+ end
217
+ if a* n/ s == start && c* n/ s == stop
218
+ return LinSpace (a, c, len, s)
219
+ end
220
+ error (" linspace($start , $stop , $len ): cannot be constructed" )
221
+ end
222
+ function linspace {T<:FloatingPoint} (start:: T , stop:: T , len:: Real )
223
+ T_len = convert (T, len)
224
+ T_len == len || throw (InexactError ())
225
+ linspace (start, stop, T_len)
226
+ end
227
+ linspace (start:: Real , stop:: Real , len:: Real = 50 ) =
228
+ linspace (promote (FloatingPoint (start), FloatingPoint (stop))... , len)
229
+
230
+ function show (io:: IO , r:: LinSpace )
231
+ print (io, " linspace(" )
232
+ show (io, first (r))
233
+ print (io, ' ,' )
234
+ show (last (r))
235
+ print (io, ' ,' )
236
+ show (length (r))
237
+ print (io, ' )' )
238
+ end
239
+
240
+ logspace (start:: Real , stop:: Real , n:: Integer = 50 ) = 10. ^ linspace (start, stop, n)
170
241
171
242
# # interface implementations
172
243
@@ -178,18 +249,21 @@ size(r::Range) = (length(r),)
178
249
isempty (r:: StepRange ) =
179
250
(r. start != r. stop) & ((r. step > zero (r. step)) != (r. stop > r. start))
180
251
isempty (r:: UnitRange ) = r. start > r. stop
181
- isempty (r:: FloatRange ) = length (r)== 0
252
+ isempty (r:: FloatRange ) = length (r) == 0
253
+ isempty (r:: LinSpace ) = length (r) == 0
182
254
183
255
step (r:: StepRange ) = r. step
184
256
step (r:: UnitRange ) = 1
185
257
step (r:: FloatRange ) = r. step/ r. divisor
258
+ step {T} (r:: LinSpace{T} ) = ifelse (r. len <= 0 , convert (T,NaN ), (r. stop- r. start)/ r. divisor)
186
259
187
260
function length (r:: StepRange )
188
261
n = Integer (div (r. stop+ r. step - r. start, r. step))
189
262
isempty (r) ? zero (n) : n
190
263
end
191
264
length (r:: UnitRange ) = Integer (r. stop - r. start + 1 )
192
265
length (r:: FloatRange ) = Integer (r. len)
266
+ length (r:: LinSpace ) = Integer (r. len + signbit (r. len - 1 ))
193
267
194
268
function length {T<:Union(Int,UInt,Int64,UInt64)} (r:: StepRange{T} )
195
269
isempty (r) && return zero (T)
@@ -220,11 +294,13 @@ let smallint = (Int === Int64 ?
220
294
end
221
295
222
296
first {T} (r:: OrdinalRange{T} ) = convert (T, r. start)
223
- first (r:: FloatRange ) = r. start/ r. divisor
297
+ first {T} (r:: FloatRange{T} ) = convert (T, r. start/ r. divisor)
298
+ first {T} (r:: LinSpace{T} ) = convert (T, (r. len- 1 )* r. start/ r. divisor)
224
299
225
300
last {T} (r:: StepRange{T} ) = r. stop
226
301
last (r:: UnitRange ) = r. stop
227
302
last {T} (r:: FloatRange{T} ) = convert (T, (r. start + (r. len- 1 )* r. step)/ r. divisor)
303
+ last {T} (r:: LinSpace{T} ) = convert (T, (r. len- 1 )* r. stop/ r. divisor)
228
304
229
305
minimum (r:: UnitRange ) = isempty (r) ? throw (ArgumentError (" range must be non-empty" )) : first (r)
230
306
maximum (r:: UnitRange ) = isempty (r) ? throw (ArgumentError (" range must be non-empty" )) : last (r)
@@ -241,8 +317,14 @@ copy(r::Range) = r
241
317
# # iteration
242
318
243
319
start (r:: FloatRange ) = 0
244
- next {T} (r:: FloatRange{T} , i:: Int ) = (convert (T, (r. start + i* r. step)/ r. divisor), i+ 1 )
245
- done (r:: FloatRange , i:: Int ) = (length (r) <= i)
320
+ done (r:: FloatRange , i:: Int ) = length (r) <= i
321
+ next {T} (r:: FloatRange{T} , i:: Int ) =
322
+ (convert (T, (r. start + i* r. step)/ r. divisor), i+ 1 )
323
+
324
+ start (r:: LinSpace ) = 1
325
+ done (r:: LinSpace , i:: Int ) = length (r) < i
326
+ next {T} (r:: LinSpace{T} , i:: Int ) =
327
+ (convert (T, ((r. len- i)* r. start + (i- 1 )* r. stop)/ r. divisor), i+ 1 )
246
328
247
329
# NOTE: For ordinal ranges, we assume start+step might be from a
248
330
# lifted domain (e.g. Int8+Int8 => Int); use that for iterating.
@@ -268,6 +350,10 @@ function getindex{T}(r::FloatRange{T}, i::Integer)
268
350
1 <= i <= length (r) || throw (BoundsError ())
269
351
convert (T, (r. start + (i- 1 )* r. step)/ r. divisor)
270
352
end
353
+ function getindex {T} (r:: LinSpace{T} , i:: Integer )
354
+ 1 <= i <= length (r) || throw (BoundsError ())
355
+ convert (T, ((r. len- i)* r. start + (i- 1 )* r. stop)/ r. divisor)
356
+ end
271
357
272
358
function check_indexingrange (s, r)
273
359
sl = length (s)
0 commit comments