@@ -39,9 +39,7 @@ from_parent_dims(::Type{<:SubArray{T,N,A,I}}) where {T,N,A,I} = _from_sub_dims(A
3939 end
4040 out
4141end
42- function from_parent_dims (:: Type{<:PermutedDimsArray{T,N,<:Any,I}} ) where {T,N,I}
43- return _val_to_static (Val (I))
44- end
42+ from_parent_dims (:: Type{<:PermutedDimsArray{T,N,<:Any,I}} ) where {T,N,I} = static (Val (I))
4543
4644"""
4745 to_parent_dims(::Type{T}) -> Bool
@@ -51,7 +49,7 @@ Returns the mapping from child dimensions to parent dimensions.
5149to_parent_dims (x) = to_parent_dims (typeof (x))
5250to_parent_dims (:: Type{T} ) where {T} = nstatic (Val (ndims (T)))
5351to_parent_dims (:: Type{T} ) where {T<: Union{Transpose,Adjoint} } = (StaticInt (2 ), One ())
54- to_parent_dims (:: Type{<:PermutedDimsArray{T,N,I}} ) where {T,N,I} = _val_to_static (Val (I))
52+ to_parent_dims (:: Type{<:PermutedDimsArray{T,N,I}} ) where {T,N,I} = static (Val (I))
5553to_parent_dims (:: Type{<:SubArray{T,N,A,I}} ) where {T,N,A,I} = _to_sub_dims (A, I)
5654@generated function _to_sub_dims (:: Type{A} , :: Type{I} ) where {A,N,I<: Tuple{Vararg{Any,N}} }
5755 out = Expr (:tuple )
@@ -79,37 +77,44 @@ function has_dimnames(::Type{T}) where {T}
7977 end
8078end
8179
80+ # this takes the place of dimension names that aren't defined
81+ const SUnderscore = StaticSymbol (:_ )
82+
8283"""
83- dimnames(::Type{T}) -> Tuple{Vararg{Symbol }}
84- dimnames(::Type{T}, d ) -> Symbol
84+ dimnames(::Type{T}) -> Tuple{Vararg{StaticSymbol }}
85+ dimnames(::Type{T}, dim ) -> StaticSymbol
8586
8687Return the names of the dimensions for `x`.
8788"""
8889@inline dimnames (x) = dimnames (typeof (x))
89- @inline dimnames (x, i :: Integer ) = dimnames (typeof (x), i )
90- @inline dimnames (:: Type{T} , d :: Integer ) where {T} = getfield ( dimnames (T ), to_dims (T, d) )
91- @inline function dimnames (:: Type{T} ) where {T}
92- if parent_type (T) <: T
93- return ntuple (i -> :_ , Val ( ndims (T)))
90+ @inline dimnames (x, dim :: Int ) = dimnames (typeof (x), dim )
91+ @inline dimnames (x, dim :: StaticInt ) = dimnames (typeof (x ), dim )
92+ @inline function dimnames (:: Type{T} , :: StaticInt{dim} ) where {T,dim }
93+ if ndims (T) < dim
94+ return SUnderscore
9495 else
95- return dimnames (parent_type (T) )
96+ return getfield ( dimnames (T), dim )
9697 end
9798end
98- @inline function dimnames (:: Type{T} ) where {T<: Union{Transpose,Adjoint} }
99- return _transpose_dimnames (Val (dimnames (parent_type (T))))
99+ @inline function dimnames (:: Type{T} , dim:: Int ) where {T}
100+ if ndims (T) < dim
101+ return SUnderscore
102+ else
103+ return getfield (dimnames (T), dim)
104+ end
100105end
101- # inserting the Val here seems to help inferability; I got a test failure without it.
102- function _transpose_dimnames (:: Val{S} ) where {S}
103- if length (S) == 1
104- (:_ , first (S))
105- elseif length (S) == 2
106- (last (S), first (S))
106+ @inline function dimnames (:: Type{T} ) where {T}
107+ if parent_type (T) <: T
108+ return ntuple (_ -> SUnderscore, Val (ndims (T)))
107109 else
108- throw ( " Can't transpose $S of dim $( length (S)) . " )
110+ return dimnames ( parent_type (T) )
109111 end
110112end
111- @inline _transpose_dimnames (x:: Tuple{Symbol,Symbol} ) = (last (x), first (x))
112- @inline _transpose_dimnames (x:: Tuple{Symbol} ) = (:_ , first (x))
113+ @inline function dimnames (:: Type{T} ) where {T<: Union{Adjoint,Transpose} }
114+ _transpose_dimnames (dimnames (parent_type (T)))
115+ end
116+ @inline _transpose_dimnames (x:: Tuple{Any,Any} ) = (last (x), first (x))
117+ @inline _transpose_dimnames (x:: Tuple{Any} ) = (SUnderscore, first (x))
113118
114119@inline function dimnames (:: Type{T} ) where {I,T<: PermutedDimsArray{<:Any,<:Any,I} }
115120 return map (i -> dimnames (parent_type (T), i), I)
123128 for i in 1 : length (I)
124129 if I[i] > 0
125130 if nl < i
126- push! (e. args, QuoteNode ( :_ ))
131+ push! (e. args, :(ArrayInterface . SUnderscore ))
127132 else
128133 push! (e. args, QuoteNode (L[i]))
129134 end
@@ -132,83 +137,79 @@ end
132137 return e
133138end
134139
135- """
136- to_dims(x[, d])
140+ _to_int (x :: Integer ) = Int (x)
141+ _to_int (x :: StaticInt ) = x
137142
138- This returns the dimension(s) of `x` corresponding to `d`.
139- """
140- to_dims (x, d) = to_dims (dimnames (x), d)
141- to_dims (x:: Tuple{Vararg{Symbol}} , d:: Integer ) = Int (d)
142- to_dims (x:: Tuple{Vararg{Symbol}} , d:: Colon ) = d # `:` is the default for most methods that take `dims`
143- @inline to_dims (x:: Tuple{Vararg{Symbol}} , d:: Tuple ) = map (i -> to_dims (x, i), d)
144- @inline function to_dims (x:: Tuple{Vararg{Symbol}} , d:: Symbol ):: Int
145- i = _sym_to_dim (x, d)
146- if i === 0
147- throw (ArgumentError (" Specified name ($(repr (d)) ) does not match any dimension name ($(x) )" ))
148- end
149- return i
150- end
151- Base. @pure function _sym_to_dim (x:: Tuple{Vararg{Symbol,N}} , sym:: Symbol ) where {N}
152- for i in 1 : N
153- getfield (x, i) === sym && return i
154- end
155- return 0
143+ function no_dimname_error (@nospecialize (x), @nospecialize (dim))
144+ throw (ArgumentError (" ($(repr (dim)) ) does not correspond to any dimension of ($(x) )" ))
156145end
157146
158147"""
159- tuple_issubset
148+ to_dims(::Type{T}, dim) -> Integer
160149
161- A version of `issubset` sepecifically for `Tuple`s of `Symbol`s, that is `@pure`.
162- This helps it get optimised out of existance. It is less of an abuse of `@pure` than
163- most of the stuff for making `NamedTuples` work.
150+ This returns the dimension(s) of `x` corresponding to `d`.
164151"""
165- Base . @pure function tuple_issubset (
166- lhs :: Tuple{Vararg{Symbol,N}} , rhs :: Tuple{Vararg{Symbol,M}}
167- ) where {N,M}
168- N <= M || return false
169- for a in lhs
170- found = false
171- for b in rhs
172- found |= a === b
173- end
174- found || return false
175- end
176- return true
152+ to_dims (x, dim) = to_dims ( typeof (x), dim)
153+ to_dims ( :: Type{T} , dim :: Integer ) where {T} = _to_int (dim)
154+ to_dims ( :: Type{T} , dim :: Colon ) where {T} = dim
155+ function to_dims ( :: Type{T} , dim :: StaticSymbol ) where {T}
156+ i = find_first_eq (dim, dimnames (T))
157+ i === nothing && no_dimname_error (T, dim)
158+ return i
159+ end
160+ @inline function to_dims ( :: Type{T} , dim :: Symbol ) where {T}
161+ i = find_first_eq (dim, Symbol .( dimnames (T)))
162+ i === nothing && no_dimname_error (T, dim)
163+ return i
177164end
165+ to_dims (:: Type{T} , dims:: Tuple ) where {T} = map (i -> to_dims (T, i), dims)
178166
179- """
180- order_named_inds(Val( names); kwargs... )
181- order_named_inds(Val( names), namedtuple )
167+ #=
168+ order_named_inds(names, namedtuple )
169+ order_named_inds(names, subnames, inds )
182170
183171Returns the tuple of index values for an array with `names`, when indexed by keywords.
184172Any dimensions not fixed are given as `:`, to make a slice.
185173An error is thrown if any keywords are used which do not occur in `nda`'s names.
186- """
187- @inline function order_named_inds (val:: Val{L} ; kwargs... ) where {L}
188- if isempty (kwargs)
189- return ()
174+
175+
176+ 1. parse into static dimnension names and key words.
177+ 2. find each dimnames in key words
178+ 3. if nothing is found use Colon()
179+ 4. if (ndims - ncolon) === nkwargs then all were found, else error
180+ =#
181+ order_named_inds (x:: Tuple , :: NamedTuple{(),Tuple{}} ) = ()
182+ function order_named_inds (x:: Tuple , nd:: NamedTuple{L} ) where {L}
183+ return order_named_inds (x, static (Val (L)), Tuple (nd))
184+ end
185+ @aggressive_constprop function order_named_inds (
186+ x:: Tuple{Vararg{Any,N}} ,
187+ nd:: Tuple ,
188+ inds:: Tuple
189+ ) where {N}
190+
191+ out = eachop (((x, nd, inds), i) -> order_named_inds (x, nd, inds, i), (x, nd, inds), nstatic (Val (N)))
192+ _order_named_inds_check (out, length (nd))
193+ return out
194+ end
195+ function order_named_inds (x:: Tuple , nd:: Tuple , inds:: Tuple , :: StaticInt{dim} ) where {dim}
196+ index = find_first_eq (getfield (x, dim), nd)
197+ if index === nothing
198+ return Colon ()
190199 else
191- return order_named_inds (val, kwargs. data)
192- end
193- end
194- @generated function order_named_inds (val:: Val{L} , ni:: NamedTuple{K} ) where {L,K}
195- tuple_issubset (K, L) || throw (DimensionMismatch (" Expected subset of $L , got $K " ))
196- exs = map (L) do n
197- if Base. sym_in (n, K)
198- qn = QuoteNode (n)
199- :(getfield (ni, $ qn))
200- else
201- :(Colon ())
202- end
200+ return @inbounds (inds[index])
203201 end
204- return Expr (:tuple , exs... )
205202end
206- @generated function _perm_tuple (:: Type{T} , :: Val{P} ) where {T,P}
207- out = Expr (:curly , :Tuple )
208- for p in P
209- push! (out. args, T. parameters[p])
203+
204+ ncolon (x:: Tuple{Colon,Vararg} , n:: Int ) = ncolon (tail (x), n + 1 )
205+ ncolon (x:: Tuple{Any,Vararg} , n:: Int ) = ncolon (tail (x), n)
206+ ncolon (x:: Tuple{Colon} , n:: Int ) = n + 1
207+ ncolon (x:: Tuple{Any} , n:: Int ) = n
208+ function _order_named_inds_check (inds:: Tuple{Vararg{Any,N}} , nkwargs:: Int ) where {N}
209+ if (N - ncolon (inds, 0 )) != = nkwargs
210+ error (" Not all keywords matched dimension names." )
210211 end
211- Expr ( :block , Expr ( :meta , :inline ), out)
212+ return nothing
212213end
213214
214215"""
@@ -226,14 +227,11 @@ function axes_types(::Type{T}) where {T}
226227 return axes_types (parent_type (T))
227228 end
228229end
229- function axes_types (:: Type{T} ) where {T<: Adjoint }
230- return _perm_tuple ( axes_types (parent_type (T)), Val (( 2 , 1 ) ))
230+ function axes_types (:: Type{T} ) where {T<: MatAdjTrans }
231+ return eachop_tuple (_get_tuple, axes_types (parent_type (T)), to_parent_dims (T ))
231232end
232- function axes_types (:: Type{T} ) where {T<: Transpose }
233- return _perm_tuple (axes_types (parent_type (T)), Val ((2 , 1 )))
234- end
235- function axes_types (:: Type{T} ) where {I1,T<: PermutedDimsArray{<:Any,<:Any,I1} }
236- return _perm_tuple (axes_types (parent_type (T)), Val (I1))
233+ function axes_types (:: Type{T} ) where {T<: PermutedDimsArray }
234+ return eachop_tuple (_get_tuple, axes_types (parent_type (T)), to_parent_dims (T))
237235end
238236function axes_types (:: Type{T} ) where {T<: AbstractRange }
239237 if known_length (T) === nothing
311309 Expr (:block , Expr (:meta , :inline ), out)
312310end
313311
314-
315-
316312"""
317313 size(A)
318314
@@ -330,12 +326,7 @@ julia> ArrayInterface.size(A)
330326@inline size (A) = Base. size (A)
331327@inline size (A, d:: Integer ) = size (A)[Int (d)]
332328@inline size (A, d) = Base. size (A, to_dims (A, d))
333- @inline function size (x:: LinearAlgebra.Adjoint{T,V} ) where {T,V<: AbstractVector{T} }
334- return (One (), static_length (x))
335- end
336- @inline function size (x:: LinearAlgebra.Transpose{T,V} ) where {T,V<: AbstractVector{T} }
337- return (One (), static_length (x))
338- end
329+ @inline size (x:: VecAdjTrans ) = (One (), static_length (x))
339330
340331function size (B:: S ) where {N,NP,T,A<: AbstractArray{T,NP} ,I,S<: SubArray{T,N,A,I} }
341332 return _size (size (parent (B)), B. indices, map (static_length, B. indices))
357348 Expr (:block , Expr (:meta , :inline ), t)
358349end
359350@inline size (v:: AbstractVector ) = (static_length (v),)
360- @inline size (B:: MatAdjTrans ) = permute (size (parent (B)), Val {(2, 1)} ( ))
351+ @inline size (B:: MatAdjTrans ) = permute (size (parent (B)), to_parent_dims (B ))
361352@inline function size (B:: PermutedDimsArray{T,N,I1,I2,A} ) where {T,N,I1,I2,A}
362- return permute (size (parent (B)), Val {I1} ( ))
353+ return permute (size (parent (B)), to_parent_dims (B ))
363354end
364355@inline size (A:: AbstractArray , :: StaticInt{N} ) where {N} = size (A)[N]
365356@inline size (A:: AbstractArray , :: Val{N} ) where {N} = size (A)[N]
0 commit comments