@@ -149,13 +149,13 @@ module IteratorsMD
149
149
function Base. nextind (a:: AbstractArray{<:Any,N} , i:: CartesianIndex{N} ) where {N}
150
150
iter = CartesianIndices (axes (a))
151
151
# might overflow
152
- I = inc (i. I, first (iter). I, last (iter). I)
152
+ I = inc (i. I, first (iter). I, step .(iter . indices), last (iter). I)
153
153
return I
154
154
end
155
155
function Base. prevind (a:: AbstractArray{<:Any,N} , i:: CartesianIndex{N} ) where {N}
156
156
iter = CartesianIndices (axes (a))
157
157
# might underflow
158
- I = dec (i. I, last (iter). I, first (iter). I)
158
+ I = dec (i. I, last (iter). I, step .(iter . indices), first (iter). I)
159
159
return I
160
160
end
161
161
@@ -169,15 +169,15 @@ module IteratorsMD
169
169
# Iteration
170
170
"""
171
171
CartesianIndices(sz::Dims) -> R
172
- CartesianIndices((istart:istop, jstart:jstop, ...)) -> R
172
+ CartesianIndices((istart:[istep:] istop, jstart:[jstep:] jstop, ...)) -> R
173
173
174
174
Define a region `R` spanning a multidimensional rectangular range
175
175
of integer indices. These are most commonly encountered in the
176
176
context of iteration, where `for I in R ... end` will return
177
177
[`CartesianIndex`](@ref) indices `I` equivalent to the nested loops
178
178
179
- for j = jstart:jstop
180
- for i = istart:istop
179
+ for j = jstart:jstep: jstop
180
+ for i = istart:istep: istop
181
181
...
182
182
end
183
183
end
@@ -190,6 +190,10 @@ module IteratorsMD
190
190
As a convenience, constructing a `CartesianIndices` from an array makes a
191
191
range of its indices.
192
192
193
+ !!! compat "Julia 1.6"
194
+ The step range method `CartesianIndices((istart:istep:istop, jstart:[jstep:]jstop, ...))`
195
+ requires at least Julia 1.6.
196
+
193
197
# Examples
194
198
```jldoctest
195
199
julia> foreach(println, CartesianIndices((2, 2, 2)))
@@ -222,6 +226,15 @@ module IteratorsMD
222
226
223
227
julia> cartesian[4]
224
228
CartesianIndex(1, 2)
229
+
230
+ julia> cartesian = CartesianIndices((1:2:5, 1:2))
231
+ 3×2 CartesianIndices{2, Tuple{StepRange{Int64, Int64}, UnitRange{Int64}}}:
232
+ CartesianIndex(1, 1) CartesianIndex(1, 2)
233
+ CartesianIndex(3, 1) CartesianIndex(3, 2)
234
+ CartesianIndex(5, 1) CartesianIndex(5, 2)
235
+
236
+ julia> cartesian[2, 2]
237
+ CartesianIndex(3, 2)
225
238
```
226
239
227
240
## Broadcasting
@@ -248,29 +261,36 @@ module IteratorsMD
248
261
249
262
For cartesian to linear index conversion, see [`LinearIndices`](@ref).
250
263
"""
251
- struct CartesianIndices{N,R<: NTuple{N,AbstractUnitRange{ Int}} } <: AbstractArray{CartesianIndex{N},N}
264
+ struct CartesianIndices{N,R<: NTuple{N,OrdinalRange{Int, Int}} } <: AbstractArray{CartesianIndex{N},N}
252
265
indices:: R
253
266
end
254
267
255
268
CartesianIndices (:: Tuple{} ) = CartesianIndices {0,typeof(())} (())
256
- CartesianIndices (inds:: NTuple{N,AbstractUnitRange{<:Integer}} ) where {N} =
257
- CartesianIndices (map (r-> convert (AbstractUnitRange{Int}, r), inds))
269
+ function CartesianIndices (inds:: NTuple{N,OrdinalRange{<:Integer, <:Integer}} ) where {N}
270
+ indices = map (r-> convert (OrdinalRange{Int, Int}, r), inds)
271
+ CartesianIndices {N, typeof(indices)} (indices)
272
+ end
258
273
259
274
CartesianIndices (index:: CartesianIndex ) = CartesianIndices (index. I)
260
- CartesianIndices (sz:: NTuple{N,<:Integer} ) where {N} = CartesianIndices (map (Base. OneTo, sz))
261
- CartesianIndices (inds:: NTuple{N,Union{<:Integer,AbstractUnitRange{<:Integer}}} ) where {N} =
262
- CartesianIndices (map (i-> first (i): last (i), inds))
275
+ CartesianIndices (inds:: NTuple{N,Union{<:Integer,OrdinalRange{<:Integer}}} ) where {N} =
276
+ CartesianIndices (map (_range2ind, inds))
263
277
264
278
CartesianIndices (A:: AbstractArray ) = CartesianIndices (axes (A))
265
279
280
+ _range2ind (sz:: Integer ) = Base. OneTo (sz)
281
+ _range2ind (ind:: OrdinalRange ) = ind
282
+
266
283
"""
267
- (:)(I ::CartesianIndex, J ::CartesianIndex)
284
+ (:)(start ::CartesianIndex, [step::CartesianIndex], stop ::CartesianIndex)
268
285
269
- Construct [`CartesianIndices`](@ref) from two `CartesianIndex`.
286
+ Construct [`CartesianIndices`](@ref) from two `CartesianIndex` and an optional step .
270
287
271
288
!!! compat "Julia 1.1"
272
289
This method requires at least Julia 1.1.
273
290
291
+ !!! compat "Julia 1.6"
292
+ The step range method start:step:stop requires at least Julia 1.6.
293
+
274
294
# Examples
275
295
```jldoctest
276
296
julia> I = CartesianIndex(2,1);
@@ -281,17 +301,26 @@ module IteratorsMD
281
301
2×3 CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}:
282
302
CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3)
283
303
CartesianIndex(3, 1) CartesianIndex(3, 2) CartesianIndex(3, 3)
304
+
305
+ julia> I:CartesianIndex(1, 2):J
306
+ 2×2 CartesianIndices{2, Tuple{StepRange{Int64, Int64}, StepRange{Int64, Int64}}}:
307
+ CartesianIndex(2, 1) CartesianIndex(2, 3)
308
+ CartesianIndex(3, 1) CartesianIndex(3, 3)
284
309
```
285
310
"""
286
311
(:)(I:: CartesianIndex{N} , J:: CartesianIndex{N} ) where N =
287
312
CartesianIndices (map ((i,j) -> i: j, Tuple (I), Tuple (J)))
313
+ (:)(I:: CartesianIndex{N} , S:: CartesianIndex{N} , J:: CartesianIndex{N} ) where N =
314
+ CartesianIndices (map ((i,s,j) -> i: s: j, Tuple (I), Tuple (S), Tuple (J)))
288
315
289
316
promote_rule (:: Type{CartesianIndices{N,R1}} , :: Type{CartesianIndices{N,R2}} ) where {N,R1,R2} =
290
317
CartesianIndices{N,Base. indices_promote_type (R1,R2)}
291
318
292
319
convert (:: Type{Tuple{}} , R:: CartesianIndices{0} ) = ()
293
- convert (:: Type{NTuple{N,AbstractUnitRange{Int}}} , R:: CartesianIndices{N} ) where {N} =
294
- R. indices
320
+ for RT in (OrdinalRange{Int, Int}, StepRange{Int, Int}, AbstractUnitRange{Int})
321
+ @eval convert (:: Type{NTuple{N,$RT}} , R:: CartesianIndices{N} ) where {N} =
322
+ R. indices
323
+ end
295
324
convert (:: Type{NTuple{N,AbstractUnitRange}} , R:: CartesianIndices{N} ) where {N} =
296
325
convert (NTuple{N,AbstractUnitRange{Int}}, R)
297
326
convert (:: Type{NTuple{N,UnitRange{Int}}} , R:: CartesianIndices{N} ) where {N} =
@@ -318,13 +347,9 @@ module IteratorsMD
318
347
# AbstractArray implementation
319
348
Base. axes (iter:: CartesianIndices{N,R} ) where {N,R} = map (Base. axes1, iter. indices)
320
349
Base. IndexStyle (:: Type{CartesianIndices{N,R}} ) where {N,R} = IndexCartesian ()
321
- @inline function Base. getindex (iter:: CartesianIndices{N,<:NTuple{N,Base.OneTo}} , I:: Vararg{Int, N} ) where {N}
322
- @boundscheck checkbounds (iter, I... )
323
- CartesianIndex (I)
324
- end
325
350
@inline function Base. getindex (iter:: CartesianIndices{N,R} , I:: Vararg{Int, N} ) where {N,R}
326
351
@boundscheck checkbounds (iter, I... )
327
- CartesianIndex (I .- first .(Base . axes1 .( iter. indices)) .+ first .(iter . indices ))
352
+ CartesianIndex (getindex .( iter. indices, I ))
328
353
end
329
354
330
355
ndims (R:: CartesianIndices ) = ndims (typeof (R))
@@ -351,37 +376,39 @@ module IteratorsMD
351
376
iterfirst, iterfirst
352
377
end
353
378
@inline function iterate (iter:: CartesianIndices , state)
354
- valid, I = __inc (state. I, first (iter). I, last (iter). I)
379
+ valid, I = __inc (state. I, first (iter). I, step .(iter . indices), last (iter). I)
355
380
valid || return nothing
356
381
return CartesianIndex (I... ), CartesianIndex (I... )
357
382
end
358
383
359
384
# increment & carry
360
- @inline function inc (state, start, stop)
361
- _, I = __inc (state, start, stop)
385
+ # TODO : optimize this; it adds up about 5ns overhead
386
+ @inline function inc (state, start, step, stop)
387
+ _, I = __inc (state, start, step, stop)
362
388
return CartesianIndex (I... )
363
389
end
364
390
365
391
# increment post check to avoid integer overflow
366
- @inline __inc (:: Tuple{} , :: Tuple{} , :: Tuple{} ) = false , ()
367
- @inline function __inc (state:: Tuple{Int} , start:: Tuple{Int} , stop:: Tuple{Int} )
368
- valid = state[1 ] < stop[1 ]
369
- return valid, (state[1 ]+ 1 ,)
392
+ @inline __inc (:: Tuple{} , :: Tuple{} , :: Tuple{} , :: Tuple{} ) = false , ()
393
+ @inline function __inc (state:: Tuple{Int} , start:: Tuple{Int} , step:: Tuple{Int} , stop:: Tuple{Int} )
394
+ I = state[1 ] + step[1 ]
395
+ valid = I <= stop[1 ]
396
+ return valid, (I, )
370
397
end
371
398
372
- @inline function __inc (state, start, stop)
373
- if state[1 ] < stop[1 ]
374
- return true , (state[1 ]+ 1 , tail (state)... )
399
+ @inline function __inc (state, start, step, stop)
400
+ I = state[1 ] + step[1 ]
401
+ if I <= stop[1 ]
402
+ return true , (I, tail (state)... )
375
403
end
376
- valid, I = __inc (tail (state), tail (start), tail (stop))
404
+ valid, I = __inc (tail (state), tail (start), tail (step), tail ( stop))
377
405
return valid, (start[1 ], I... )
378
406
end
379
407
380
408
# 0-d cartesian ranges are special-cased to iterate once and only once
381
409
iterate (iter:: CartesianIndices{0} , done= false ) = done ? nothing : (CartesianIndex (), true )
382
410
383
- size (iter:: CartesianIndices ) = map (dimlength, first (iter). I, last (iter). I)
384
- dimlength (start, stop) = stop- start+ 1
411
+ size (iter:: CartesianIndices ) = map (length, iter. indices)
385
412
386
413
length (iter:: CartesianIndices ) = prod (size (iter))
387
414
@@ -395,11 +422,8 @@ module IteratorsMD
395
422
@inline to_indices (A, inds, I:: Tuple{CartesianIndices{0},Vararg{Any}} ) =
396
423
(first (I), to_indices (A, inds, tail (I))... )
397
424
398
- @inline function in (i:: CartesianIndex{N} , r:: CartesianIndices{N} ) where {N}
399
- _in (true , i. I, first (r). I, last (r). I)
400
- end
401
- _in (b, :: Tuple{} , :: Tuple{} , :: Tuple{} ) = b
402
- @inline _in (b, i, start, stop) = _in (b & (start[1 ] <= i[1 ] <= stop[1 ]), tail (i), tail (start), tail (stop))
425
+ @inline in (i:: CartesianIndex , r:: CartesianIndices ) = false
426
+ @inline in (i:: CartesianIndex{N} , r:: CartesianIndices{N} ) where {N} = all (map (in, i. I, r. indices))
403
427
404
428
simd_outer_range (iter:: CartesianIndices{0} ) = iter
405
429
function simd_outer_range (iter:: CartesianIndices )
@@ -448,36 +472,38 @@ module IteratorsMD
448
472
iterfirst, iterfirst
449
473
end
450
474
@inline function iterate (r:: Reverse{<:CartesianIndices} , state)
451
- valid, I = __dec (state. I, last (r. itr). I, first (r. itr). I)
475
+ valid, I = __dec (state. I, last (r. itr). I, step .(r . itr . indices), first (r. itr). I)
452
476
valid || return nothing
453
477
return CartesianIndex (I... ), CartesianIndex (I... )
454
478
end
455
479
456
480
# decrement & carry
457
- @inline function dec (state, start, stop)
458
- _, I = __dec (state, start, stop)
481
+ @inline function dec (state, start, step, stop)
482
+ _, I = __dec (state, start, step, stop)
459
483
return CartesianIndex (I... )
460
484
end
461
485
462
486
# decrement post check to avoid integer overflow
463
- @inline __dec (:: Tuple{} , :: Tuple{} , :: Tuple{} ) = false , ()
464
- @inline function __dec (state:: Tuple{Int} , start:: Tuple{Int} , stop:: Tuple{Int} )
465
- valid = state[1 ] > stop[1 ]
466
- return valid, (state[1 ]- 1 ,)
487
+ @inline __dec (:: Tuple{} , :: Tuple{} , :: Tuple{} , :: Tuple{} ) = false , ()
488
+ @inline function __dec (state:: Tuple{Int} , start:: Tuple{Int} , step:: Tuple{Int} , stop:: Tuple{Int} )
489
+ I = state[1 ] - step[1 ]
490
+ valid = I >= stop[1 ]
491
+ return valid, (I,)
467
492
end
468
493
469
- @inline function __dec (state, start, stop)
470
- if state[1 ] > stop[1 ]
471
- return true , (state[1 ]- 1 , tail (state)... )
494
+ @inline function __dec (state, start, step, stop)
495
+ I = state[1 ] - step[1 ]
496
+ if I >= stop[1 ]
497
+ return true , (I, tail (state)... )
472
498
end
473
- valid, I = __dec (tail (state), tail (start), tail (stop))
499
+ valid, I = __dec (tail (state), tail (start), tail (step), tail ( stop))
474
500
return valid, (start[1 ], I... )
475
501
end
476
502
477
503
# 0-d cartesian ranges are special-cased to iterate once and only once
478
504
iterate (iter:: Reverse{<:CartesianIndices{0}} , state= false ) = state ? nothing : (CartesianIndex (), true )
479
505
480
- Base. LinearIndices (inds:: CartesianIndices{N,R} ) where {N,R} = LinearIndices {N,R} ( inds. indices )
506
+ Base. LinearIndices (inds:: CartesianIndices{N,R} ) where {N,R} = LinearIndices ( axes ( inds) )
481
507
482
508
# array operations
483
509
Base. intersect (a:: CartesianIndices{N} , b:: CartesianIndices{N} ) where N =
0 commit comments