@@ -390,16 +390,29 @@ Changing indexing based on a given argument from `args` should be done through
390
390
[`flatten_args`](@ref), [`to_index`](@ref), or [`to_axis`](@ref).
391
391
"""
392
392
@propagate_inbounds getindex (A, args... ) = unsafe_getindex (A, to_indices (A, args))
393
+ @propagate_inbounds function getindex (A; kwargs... )
394
+ if has_dimnames (A)
395
+ return A[order_named_inds (Val (dimnames (A)); kwargs... )... ]
396
+ else
397
+ return unsafe_getindex (A, to_indices (A, ()); kwargs... )
398
+ end
399
+ end
393
400
394
401
"""
395
402
unsafe_getindex(A, inds)
396
403
397
404
Indexes into `A` given `inds`. This method assumes that `inds` have already been
398
405
bounds-checked.
399
406
"""
400
- unsafe_getindex (A, inds) = unsafe_getindex (UnsafeIndex (A, inds), A, inds)
401
- unsafe_getindex (:: UnsafeGetElement , A, inds) = unsafe_get_element (A, inds)
402
- unsafe_getindex (:: UnsafeGetCollection , A, inds) = unsafe_get_collection (A, inds)
407
+ function unsafe_getindex (A, inds; kwargs... )
408
+ return unsafe_getindex (UnsafeIndex (A, inds), A, inds; kwargs... )
409
+ end
410
+ function unsafe_getindex (:: UnsafeGetElement , A, inds; kwargs... )
411
+ return unsafe_get_element (A, inds; kwargs... )
412
+ end
413
+ function unsafe_getindex (:: UnsafeGetCollection , A, inds; kwargs... )
414
+ return unsafe_get_collection (A, inds; kwargs... )
415
+ end
403
416
404
417
"""
405
418
unsafe_get_element(A::AbstractArray{T}, inds::Tuple) -> T
@@ -408,9 +421,7 @@ Returns an element of `A` at the indices `inds`. This method assumes all `inds`
408
421
have been checked for being in bounds. Any new array type using `ArrayInterface.getindex`
409
422
must define `unsafe_get_element(::NewArrayType, inds)`.
410
423
"""
411
- function unsafe_get_element (A, inds)
412
- throw (MethodError (unsafe_getindex, (A, inds)))
413
- end
424
+ unsafe_get_element (A, inds; kwargs... ) = throw (MethodError (unsafe_getindex, (A, inds)))
414
425
function unsafe_get_element (A:: Array , inds)
415
426
if length (inds) === 0
416
427
return Base. arrayref (false , A, 1 )
@@ -433,11 +444,11 @@ end
433
444
434
445
Returns a collection of `A` given `inds`. `inds` is assumed to have been bounds-checked.
435
446
"""
436
- function unsafe_get_collection (A, inds)
447
+ function unsafe_get_collection (A, inds; kwargs ... )
437
448
axs = to_axes (A, inds)
438
449
dest = similar (A, axs)
439
450
if map (Base. unsafe_length, axes (dest)) == map (Base. unsafe_length, axs)
440
- Base . _unsafe_getindex! (dest, A, inds... ) # usually a generated function, don't allow it to impact inference result
451
+ _unsafe_getindex! (dest, A, inds... ; kwargs ... ) # usually a generated function, don't allow it to impact inference result
441
452
else
442
453
Base. throw_checksize_error (dest, axs)
443
454
end
@@ -490,16 +501,29 @@ Store the given values at the given key or index within a collection.
490
501
" elements after construction." )
491
502
end
492
503
end
504
+ @propagate_inbounds function setindex! (A, val; kwargs... )
505
+ if has_dimnames (A)
506
+ A[order_named_inds (Val (dimnames (A)); kwargs... )... ] = val
507
+ else
508
+ return unsafe_setindex! (A, val, to_indices (A, ()); kwargs... )
509
+ end
510
+ end
493
511
494
512
"""
495
- unsafe_setindex!(A, val, inds::Tuple)
513
+ unsafe_setindex!(A, val, inds::Tuple; kwargs... )
496
514
497
515
Sets indices (`inds`) of `A` to `val`. This method assumes that `inds` have already been
498
516
bounds-checked. This step of the processing pipeline can be customized by:
499
517
"""
500
- unsafe_setindex! (A, val, inds:: Tuple ) = unsafe_setindex! (UnsafeIndex (A, inds), A, val, inds)
501
- unsafe_setindex! (:: UnsafeGetElement , A, val, inds:: Tuple ) = unsafe_set_element! (A, val, inds)
502
- unsafe_setindex! (:: UnsafeGetCollection , A, val, inds:: Tuple ) = unsafe_set_collection! (A, val, inds)
518
+ function unsafe_setindex! (A, val, inds:: Tuple ; kwargs... )
519
+ return unsafe_setindex! (UnsafeIndex (A, inds), A, val, inds; kwargs... )
520
+ end
521
+ function unsafe_setindex! (:: UnsafeGetElement , A, val, inds:: Tuple ; kwargs... )
522
+ return unsafe_set_element! (A, val, inds; kwargs... )
523
+ end
524
+ function unsafe_setindex! (:: UnsafeGetCollection , A, val, inds:: Tuple ; kwargs... )
525
+ return unsafe_set_collection! (A, val, inds; kwargs... )
526
+ end
503
527
504
528
"""
505
529
unsafe_set_element!(A, val, inds::Tuple)
@@ -508,7 +532,7 @@ Sets an element of `A` to `val` at indices `inds`. This method assumes all `inds
508
532
have been checked for being in bounds. Any new array type using `ArrayInterface.setindex!`
509
533
must define `unsafe_set_element!(::NewArrayType, val, inds)`.
510
534
"""
511
- function unsafe_set_element! (A, val, inds)
535
+ function unsafe_set_element! (A, val, inds; kwargs ... )
512
536
throw (MethodError (unsafe_set_element!, (A, val, inds)))
513
537
end
514
538
function unsafe_set_element! (A:: Array{T} , val, inds:: Tuple ) where {T}
527
551
528
552
Sets `inds` of `A` to `val`. `inds` is assumed to have been bounds-checked.
529
553
"""
530
- @inline function unsafe_set_collection! (A, val, inds)
531
- return Base. _unsafe_setindex! (IndexStyle (A), A, val, inds... )
554
+ @inline function unsafe_set_collection! (A, val, inds; kwargs... )
555
+ return _unsafe_setindex! (IndexStyle (A), A, val, inds... ; kwargs... )
556
+ end
557
+
558
+
559
+ # these let us use `@ncall` on getindex/setindex! that have kwargs
560
+ function _setindex_kwargs! (x, val, kwargs, args... )
561
+ @inbounds setindex! (x, val, args... ; kwargs... )
562
+ end
563
+ function _getindex_kwargs (x, kwargs, args... )
564
+ @inbounds getindex (x, args... ; kwargs... )
565
+ end
566
+
567
+ function _generate_unsafe_getindex!_body (N:: Int )
568
+ quote
569
+ Base. @_inline_meta
570
+ D = eachindex (dest)
571
+ Dy = iterate (D)
572
+ @inbounds Base. Cartesian. @nloops $ N j d-> I[d] begin
573
+ # This condition is never hit, but at the moment
574
+ # the optimizer is not clever enough to split the union without it
575
+ Dy === nothing && return dest
576
+ (idx, state) = Dy
577
+ dest[idx] = Base. Cartesian. @ncall $ N _getindex_kwargs src kwargs j
578
+ Dy = iterate (D, state)
579
+ end
580
+ return dest
581
+ end
532
582
end
583
+
584
+ function _generate_unsafe_setindex!_body (N:: Int )
585
+ quote
586
+ x′ = Base. unalias (A, x)
587
+ Base. Cartesian. @nexprs $ N d-> (I_d = Base. unalias (A, I[d]))
588
+ idxlens = Base. Cartesian. @ncall $ N Base. index_lengths I
589
+ Base. Cartesian. @ncall $ N Base. setindex_shape_check x′ (d-> idxlens[d])
590
+ Xy = iterate (x′)
591
+ @inbounds Base. Cartesian. @nloops $ N i d-> I_d begin
592
+ # This is never reached, but serves as an assumption for
593
+ # the optimizer that it does not need to emit error paths
594
+ Xy === nothing && break
595
+ (val, state) = Xy
596
+ Base. Cartesian. @ncall $ N _setindex_kwargs! A val kwargs i
597
+ Xy = iterate (x′, state)
598
+ end
599
+ A
600
+ end
601
+ end
602
+
603
+ @generated function _unsafe_getindex! (dest:: AbstractArray , src:: AbstractArray , I:: Vararg{Union{Real, AbstractArray}, N} ; kwargs... ) where N
604
+ _generate_unsafe_getindex!_body (N)
605
+ end
606
+
607
+ @generated function _unsafe_setindex! (:: IndexStyle , A:: AbstractArray , x, I:: Vararg{Union{Real,AbstractArray}, N} ; kwargs... ) where N
608
+ _generate_unsafe_setindex!_body (N)
609
+ end
610
+
0 commit comments