@@ -147,68 +147,76 @@ function to_parent_dims(::Type{T}, ::StaticInt{dim}) where {T,dim}
147
147
end
148
148
end
149
149
150
+ _nunderscore (:: Val{N} ) where {N} = ntuple (Compat. Returns (:_ ), Val (N))
151
+
150
152
"""
151
- has_dimnames(::Type{T}) -> Bool
153
+ has_dimnames(::Type{T}) -> StaticBool
152
154
153
155
Returns `static(true)` if `x` has on or more named dimensions. If all dimensions correspond
154
156
to `static(:_)`, then `static(false)` is returned.
155
157
"""
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
163
161
164
162
"""
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}
167
165
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.
170
168
"""
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])
176
181
end
182
+ @inline _inbounds_known_dimname (x, dim) = @inbounds (_known_dimname (x, dim))
177
183
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])
186
200
end
201
+ @inline _inbounds_dimname (x, dim) = @inbounds (_dimname (x, dim))
187
202
188
203
"""
189
- to_dims(::Type{T} , dim) -> Union{Int,StaticInt}
204
+ to_dims(x , dim) -> Union{Int,StaticInt}
190
205
191
- This returns the dimension(s) of `x` corresponding to `d `.
206
+ This returns the dimension(s) of `x` corresponding to `dim `.
192
207
"""
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)
203
213
end
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" ))
209
218
return i
210
219
end
211
- to_dims (:: Type{T} , dims:: Tuple ) where {T} = map (i -> to_dims (T, i), dims)
212
220
213
221
#=
214
222
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.
224
232
3. if missing is found use Colon()
225
233
4. if (ndims - ncolon) === nkwargs then all were found, else error
226
234
=#
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 :(())
245
238
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
257
260
end
258
- return missing
259
261
end
260
262
0 commit comments