@@ -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