@@ -147,68 +147,76 @@ function to_parent_dims(::Type{T}, ::StaticInt{dim}) where {T,dim}
147147 end
148148end
149149
150+ _nunderscore (:: Val{N} ) where {N} = ntuple (Compat. Returns (:_ ), Val (N))
151+
150152"""
151- has_dimnames(::Type{T}) -> Bool
153+ has_dimnames(::Type{T}) -> StaticBool
152154
153155Returns `static(true)` if `x` has on or more named dimensions. If all dimensions correspond
154156to `static(:_)`, then `static(false)` is returned.
155157"""
156- has_dimnames (x) = has_dimnames (typeof (x))
157- @inline has_dimnames (:: Type{T} ) where {T} = _has_dimnames (dimnames (T))
158- _has_dimnames (:: Tuple{Vararg{StaticSymbol{:_}}} ) = static (false )
159- _has_dimnames (:: Tuple ) = static (true )
160-
161- # this takes the place of dimension names that aren't defined
162- const SUnderscore = StaticSymbol (:_ )
158+ Compat. @constprop :aggressive has_dimnames (x) = static (_is_named (known_dimnames (x)))
159+ _is_named (x:: NTuple{N,Symbol} ) where {N} = x != = _nunderscore (Val (N))
160+ _is_named (:: Any ) = true
163161
164162"""
165- dimnames (::Type{T}) -> Tuple{Vararg{StaticSymbol }}
166- dimnames (::Type{T}, dim) -> StaticSymbol
163+ known_dimnames (::Type{T}) -> Tuple{Vararg{Union{Symbol,Missing} }}
164+ known_dimnames (::Type{T}, dim::Union{Int,StaticInt} ) -> Union{Symbol,Missing}
167165
168- Return the names of the dimensions for `x`. `static(:_) ` is used to indicate a dimension
169- does not have a name.
166+ Return the names of the dimensions for `x`. `:_ ` is used to indicate a dimension does not
167+ have a name.
170168"""
171- @inline dimnames (x) = dimnames (typeof (x))
172- @inline dimnames (:: Type{T} ) where {T} = _dimnames (has_parent (T), T)
173- _dimnames (:: False , :: Type{T} ) where {T} = ntuple (_-> static (:_ ), Val (ndims (T)))
174- @inline function _dimnames (:: True , :: Type{T} ) where {T}
175- eachop (_perm_dimnames, to_parent_dims (T), dimnames (parent_type (T)))
169+ @inline known_dimnames (x, dim:: Integer ) = _known_dimname (known_dimnames (x), canonicalize (dim))
170+ known_dimnames (x) = known_dimnames (typeof (x))
171+ known_dimnames (:: Type{T} ) where {T} = _known_dimnames (T, parent_type (T))
172+ _known_dimnames (:: Type{T} , :: Type{T} ) where {T} = _unknown_dimnames (Base. IteratorSize (T))
173+ _unknown_dimnames (:: Base.HasShape{N} ) where {N} = _nunderscore (Val (N))
174+ _unknown_dimnames (:: Any ) = (:_ ,)
175+ function _known_dimnames (:: Type{C} , :: Type{P} ) where {C,P}
176+ eachop (_inbounds_known_dimname, to_parent_dims (C), known_dimnames (P))
177+ end
178+ @inline function _known_dimname (x:: Tuple{Vararg{Any,N}} , dim:: CanonicalInt ) where {N}
179+ @boundscheck (dim > N || dim < 1 ) && return :_
180+ return @inbounds (x[dim])
176181end
182+ @inline _inbounds_known_dimname (x, dim) = @inbounds (_known_dimname (x, dim))
177183
178- @inline dimnames (x, dim) = dimnames (typeof (x), dim)
179- @inline dimnames (:: Type{T} , dim:: Integer ) where {T} = _perm_dimnames (dimnames (T), dim)
180- function _perm_dimnames (dnames:: Tuple{Vararg{StaticSymbol,N}} , dim) where {N}
181- if dim > N
182- return static (:_ )
183- else
184- return @inbounds (dnames[dim])
185- end
184+ """
185+ dimnames(x) -> Tuple{Vararg{Union{Symbol,StaticSymbol}}}
186+ dimnames(x, dim::Union{Int,StaticInt}) -> Union{Symbol,StaticSymbol}
187+
188+ Return the names of the dimensions for `x`. `:_` is used to indicate a dimension does not
189+ have a name.
190+ """
191+ @inline dimnames (x, dim:: Integer ) = _dimname (dimnames (x), canonicalize (dim))
192+ @inline dimnames (x) = _dimnames (has_parent (x), x)
193+ @inline function _dimnames (:: True , x)
194+ eachop (_inbounds_dimname, to_parent_dims (x), dimnames (parent (x)))
195+ end
196+ _dimnames (:: False , x) = ntuple (_-> static (:_ ), Val (ndims (x)))
197+ @inline function _dimname (x:: Tuple{Vararg{Any,N}} , dim:: CanonicalInt ) where {N}
198+ @boundscheck (dim > N || dim < 1 ) && return static (:_ )
199+ return @inbounds (x[dim])
186200end
201+ @inline _inbounds_dimname (x, dim) = @inbounds (_dimname (x, dim))
187202
188203"""
189- to_dims(::Type{T} , dim) -> Union{Int,StaticInt}
204+ to_dims(x , dim) -> Union{Int,StaticInt}
190205
191- This returns the dimension(s) of `x` corresponding to `d `.
206+ This returns the dimension(s) of `x` corresponding to `dim `.
192207"""
193- to_dims (x, dim) = to_dims (typeof (x), dim)
194- to_dims (:: Type{T} , dim:: StaticInt ) where {T} = dim
195- to_dims (:: Type{T} , dim:: Integer ) where {T} = Int (dim)
196- to_dims (:: Type{T} , dim:: Colon ) where {T} = dim
197- function to_dims (:: Type{T} , dim:: StaticSymbol ) where {T}
198- i = find_first_eq (dim, dimnames (T))
199- if i === nothing
200- throw_dim_error (T, dim)
201- end
202- return i
208+ to_dims (x, dim:: Colon ) = dim
209+ to_dims (x, dim:: Integer ) = canonicalize (dim)
210+ to_dims (x, dim:: Union{StaticSymbol,Symbol} ) = _to_dim (dimnames (x), dim)
211+ function to_dims (x, dims:: Tuple{Vararg{Any,N}} ) where {N}
212+ eachop (_to_dims, nstatic (Val (N)), dimnames (x), dims)
203213end
204- Compat. @constprop :aggressive function to_dims (:: Type{T} , dim:: Symbol ) where {T}
205- i = find_first_eq (dim, map (Symbol, dimnames (T)))
206- if i === nothing
207- throw_dim_error (T, dim)
208- end
214+ @inline _to_dims (x:: Tuple , d:: Tuple , n:: StaticInt{N} ) where {N} = _to_dim (x, getfield (d, N))
215+ @inline function _to_dim (x:: Tuple , d:: Union{Symbol,StaticSymbol} )
216+ i = find_first_eq (d, x)
217+ i === nothing && throw (DimensionMismatch (" dimension name $(d) not found" ))
209218 return i
210219end
211- to_dims (:: Type{T} , dims:: Tuple ) where {T} = map (i -> to_dims (T, i), dims)
212220
213221#=
214222 order_named_inds(names, namedtuple)
@@ -224,37 +232,31 @@ An error is thrown if any keywords are used which do not occur in `nda`'s names.
2242323. if missing is found use Colon()
2252334. if (ndims - ncolon) === nkwargs then all were found, else error
226234=#
227- order_named_inds (x:: Tuple , :: NamedTuple{(),Tuple{}} ) = ()
228- function order_named_inds (x:: Tuple , nd:: NamedTuple{L} ) where {L}
229- return order_named_inds (x, static (Val (L)), Tuple (nd))
230- end
231- Compat. @constprop :aggressive function order_named_inds (
232- x:: Tuple{Vararg{Any,N}} ,
233- nd:: Tuple ,
234- inds:: Tuple
235- ) where {N}
236-
237- out = eachop (order_named_inds, nstatic (Val (N)), x, nd, inds)
238- _order_named_inds_check (out, length (nd))
239- return out
240- end
241- function order_named_inds (x:: Tuple , nd:: Tuple , inds:: Tuple , :: StaticInt{dim} ) where {dim}
242- index = find_first_eq (getfield (x, dim), nd)
243- if index === nothing
244- return Colon ()
235+ @generated function find_all_dimnames (x:: Tuple{Vararg{Any,ND}} , nd:: Tuple{Vararg{Any,NI}} , inds:: Tuple , default) where {ND,NI}
236+ if NI === 0
237+ return :(())
245238 else
246- return @inbounds (inds[index])
247- end
248- end
249-
250- ncolon (x:: Tuple{Colon,Vararg} , n:: Int ) = ncolon (tail (x), n + 1 )
251- ncolon (x:: Tuple{Any,Vararg} , n:: Int ) = ncolon (tail (x), n)
252- ncolon (x:: Tuple{Colon} , n:: Int ) = n + 1
253- ncolon (x:: Tuple{Any} , n:: Int ) = n
254- function _order_named_inds_check (inds:: Tuple{Vararg{Any,N}} , nkwargs:: Int ) where {N}
255- if (N - ncolon (inds, 0 )) != = nkwargs
256- error (" Not all keywords matched dimension names." )
239+ out = Expr (:block , Expr (:(= ), :names_found , 0 ))
240+ t = Expr (:tuple )
241+ for i in 1 : ND
242+ index_i = Symbol (:index_ , i)
243+ val_i = Symbol (:val_ , i)
244+ push! (t. args, val_i)
245+ push! (out. args, quote
246+ $ index_i = find_first_eq (getfield (x, $ i), nd)
247+ if $ index_i === nothing
248+ $ val_i = default
249+ else
250+ $ val_i = @inbounds (inds[$ index_i])
251+ names_found += 1
252+ end
253+ end )
254+ end
255+ return quote
256+ $ out
257+ @boundscheck names_found === $ NI || error (" Not all keywords matched dimension names." )
258+ return $ t
259+ end
257260 end
258- return missing
259261end
260262
0 commit comments