@@ -390,16 +390,29 @@ Changing indexing based on a given argument from `args` should be done through
390390[`flatten_args`](@ref), [`to_index`](@ref), or [`to_axis`](@ref).
391391"""
392392@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
393400
394401"""
395402 unsafe_getindex(A, inds)
396403
397404Indexes into `A` given `inds`. This method assumes that `inds` have already been
398405bounds-checked.
399406"""
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
403416
404417"""
405418 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`
408421have been checked for being in bounds. Any new array type using `ArrayInterface.getindex`
409422must define `unsafe_get_element(::NewArrayType, inds)`.
410423"""
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)))
414425function unsafe_get_element (A:: Array , inds)
415426 if length (inds) === 0
416427 return Base. arrayref (false , A, 1 )
@@ -433,11 +444,11 @@ end
433444
434445Returns a collection of `A` given `inds`. `inds` is assumed to have been bounds-checked.
435446"""
436- function unsafe_get_collection (A, inds)
447+ function unsafe_get_collection (A, inds; kwargs ... )
437448 axs = to_axes (A, inds)
438449 dest = similar (A, axs)
439450 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
441452 else
442453 Base. throw_checksize_error (dest, axs)
443454 end
@@ -490,16 +501,29 @@ Store the given values at the given key or index within a collection.
490501 " elements after construction." )
491502 end
492503end
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
493511
494512"""
495- unsafe_setindex!(A, val, inds::Tuple)
513+ unsafe_setindex!(A, val, inds::Tuple; kwargs... )
496514
497515Sets indices (`inds`) of `A` to `val`. This method assumes that `inds` have already been
498516bounds-checked. This step of the processing pipeline can be customized by:
499517"""
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
503527
504528"""
505529 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
508532have been checked for being in bounds. Any new array type using `ArrayInterface.setindex!`
509533must define `unsafe_set_element!(::NewArrayType, val, inds)`.
510534"""
511- function unsafe_set_element! (A, val, inds)
535+ function unsafe_set_element! (A, val, inds; kwargs ... )
512536 throw (MethodError (unsafe_set_element!, (A, val, inds)))
513537end
514538function unsafe_set_element! (A:: Array{T} , val, inds:: Tuple ) where {T}
527551
528552Sets `inds` of `A` to `val`. `inds` is assumed to have been bounds-checked.
529553"""
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
532582end
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