@@ -58,53 +58,78 @@ Base.eachindex(A::KeyedArray) = eachindex(parent(A))
5858
5959Base. keys (A:: KeyedArray ) = error (" Base.keys(::KeyedArray) not defined, please open an issue if this happens unexpectedly." )
6060
61- for (bget, rget, cpy) in [(:getindex , :keys_getindex , :copy ), (:view , :keys_view , :identity )]
61+ for (get_or_view, key_get, maybe_copy) in [
62+ (:getindex , :keys_getindex , :copy ),
63+ (:view , :keys_view , :identity )
64+ ]
6265 @eval begin
6366
64- @inline function Base. $bget (A:: KeyedArray , I:: Integer... )
65- @boundscheck checkbounds (parent (A), I... )
66- @inbounds Base.$ bget (parent (A), I... )
67- end
67+ @inline function Base. $get_or_view (A:: KeyedArray , raw_inds... )
68+ inds = to_indices (A, raw_inds)
69+ @boundscheck checkbounds (parent (A), inds... )
70+ data = @inbounds $ get_or_view (parent (A), inds... )
71+ data isa AbstractArray || return data # scalar output
72+
73+ raw_keys = $ key_get (axiskeys (A), inds)
74+ raw_keys === () && return data # things like A[A .> 0]
6875
69- @inline function Base. $bget (A:: KeyedArray , I:: Union{Colon, CartesianIndex, BitArray} )
70- @boundscheck checkbounds (parent (A), I)
71- @inbounds Base.$ bget (parent (A), I)
76+ new_keys = ntuple (ndims (data)) do d
77+ isnothing (raw_keys) && return axes (data, d)
78+ raw_keys[d]
79+ end
80+ KeyedArray (data, new_keys)
7281 end
7382
74- @inline @propagate_inbounds function Base. $bget (A:: KeyedArray , Iraw... )
75- I = Base. to_indices (A, Iraw) # allows InvertedIndices.jl
83+ # drop all, for A[:] and A[A .> 0] with ndims>=2
84+ @inline $ key_get (keys:: Tuple{Any, Any, Vararg{Any}} , inds:: Tuple{Base.LogicalIndex} ) = ()
85+ @inline $ key_get (keys:: Tuple{Any, Any, Vararg{Any}} , inds:: Tuple{Base.Slice} ) = ()
7686
77- @boundscheck checkbounds (parent (A), I... )
78- data = @inbounds Base.$ bget (parent (A), I... )
87+ # drop one, for integer index
88+ @inline $ key_get (keys:: Tuple , inds:: Tuple{Integer, Vararg{Any}} ) =
89+ $ key_get (tail (keys), tail (inds))
7990
80- @boundscheck map (checkbounds, axiskeys (A), I)
81- new_keys = $ rget (axiskeys (A), I)
91+ # from a Colon, k[:] would copy too, but this avoids view([1,2,3], :)
92+ @inline $ key_get (keys:: Tuple , inds:: Tuple{Base.Slice, Vararg{Any}} ) =
93+ ($ maybe_copy (first (keys)), $ key_get (tail (keys), tail (inds))... )
8294
83- new_keys isa Tuple{} ? data : KeyedArray (data, new_keys)
95+ # this avoids making views of 1:10 etc, they are immutable anyway
96+ @inline function $key_get (keys:: Tuple , inds:: Tuple{AbstractVector, Vararg{Any}} )
97+ got = if first (keys) isa AbstractRange
98+ @inbounds getindex (first (keys), first (inds))
99+ else
100+ @inbounds $ get_or_view (first (keys), first (inds))
101+ end
102+ (got, $ key_get (tail (keys), tail (inds))... )
84103 end
85104
86- @inline function $rget (keys, inds)
87- got = map (keys, inds) do r,i
88- i isa Integer && return nothing
89- i isa Colon && return $ cpy (r) # avoids view([1,2,3], :)
90- r isa AbstractRange && return getindex (r,i) # don't make views of 1:10
91- return @inbounds $ bget (r,i)
92- end
93- filter (r -> r isa AbstractArray, got)
105+ # newindex=[CartesianIndex{0}()], uses up one ind, sets N keys to default i.e. axes
106+ @inline function $key_get (keys:: Tuple , inds:: Tuple{AbstractVector{CartesianIndex{0}}, Vararg{Any}} )
107+ (OneTo (1 ), $ key_get (keys, tail (inds))... )
94108 end
109+ @inline function $key_get (keys:: Tuple , inds:: Tuple{AbstractVector{CartesianIndex{N}}, Vararg{Any}} ) where {N}
110+ _, keys_left = Base. IteratorsMD. split (keys, Val (N))
111+ (ntuple (_-> nothing , N)... , $ key_get (keys_left, tail (inds))... )
112+ end
113+
114+ # terminating case, trailing 1s (already checked) could be left over
115+ @inline $ key_get (keys:: Tuple{} , inds:: Tuple{} ) = ()
116+ @inline $ key_get (keys:: Tuple{} , inds:: Tuple{Integer, Vararg{Any}} ) = ()
95117
96118 end
97119end
98120
99- @inline function Base. setindex! (A:: KeyedArray , val, I... )
121+ @inline function Base. setindex! (A:: KeyedArray , val, raw_inds... )
122+ I = Base. to_indices (A, raw_inds)
100123 @boundscheck checkbounds (A, I... )
101124 @inbounds setindex! (parent (A), val, I... )
102125 val
103126end
104127
105- @inline function Base. Broadcast. dotview (A:: KeyedArray , I... )
128+ @inline function Base. dotview (A:: KeyedArray , raw_inds... )
129+ I = Base. to_indices (A, raw_inds)
106130 @boundscheck checkbounds (A, I... )
107- @inbounds Base. dotview (parent (A), I... )
131+ @inbounds setindex! (parent (A), val, I... )
132+ val
108133end
109134
110135"""
0 commit comments