Skip to content

Commit db2cfb4

Browse files
authored
Merge pull request #118 from SciML/revert
Revert previous accidental push to master
2 parents 5cd6489 + 9c9365b commit db2cfb4

File tree

7 files changed

+107
-278
lines changed

7 files changed

+107
-278
lines changed

src/ArrayInterface.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ using IfElse
44
using Requires
55
using LinearAlgebra
66
using SparseArrays
7-
using Base.Cartesian
87

98
using Base: @pure, @propagate_inbounds, tail, OneTo, LogicalIndex, Slice, ReinterpretArray
109

src/dimensions.jl

Lines changed: 57 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ from_parent_dims(::Type{<:SubArray{T,N,A,I}}) where {T,N,A,I} = _from_sub_dims(A
3939
end
4040
out
4141
end
42-
from_parent_dims(::Type{<:PermutedDimsArray{T,N,<:Any,I}}) where {T,N,I} = static(Val(I))
42+
function from_parent_dims(::Type{<:PermutedDimsArray{T,N,<:Any,I}}) where {T,N,I}
43+
return _val_to_static(Val(I))
44+
end
4345

4446
"""
4547
to_parent_dims(::Type{T}) -> Bool
@@ -49,7 +51,7 @@ Returns the mapping from child dimensions to parent dimensions.
4951
to_parent_dims(x) = to_parent_dims(typeof(x))
5052
to_parent_dims(::Type{T}) where {T} = nstatic(Val(ndims(T)))
5153
to_parent_dims(::Type{T}) where {T<:Union{Transpose,Adjoint}} = (StaticInt(2), One())
52-
to_parent_dims(::Type{<:PermutedDimsArray{T,N,I}}) where {T,N,I} = static(Val(I))
54+
to_parent_dims(::Type{<:PermutedDimsArray{T,N,I}}) where {T,N,I} = _val_to_static(Val(I))
5355
to_parent_dims(::Type{<:SubArray{T,N,A,I}}) where {T,N,A,I} = _to_sub_dims(A, I)
5456
@generated function _to_sub_dims(::Type{A}, ::Type{I}) where {A,N,I<:Tuple{Vararg{Any,N}}}
5557
out = Expr(:tuple)
@@ -77,35 +79,18 @@ function has_dimnames(::Type{T}) where {T}
7779
end
7880
end
7981

80-
# this takes the place of dimension names that aren't defined
81-
const SUnderscore = StaticSymbol(:_)
82-
8382
"""
84-
dimnames(::Type{T}) -> Tuple{Vararg{StaticSymbol}}
85-
dimnames(::Type{T}, dim) -> StaticSymbol
83+
dimnames(::Type{T}) -> Tuple{Vararg{Symbol}}
84+
dimnames(::Type{T}, d) -> Symbol
8685
8786
Return the names of the dimensions for `x`.
8887
"""
8988
@inline dimnames(x) = dimnames(typeof(x))
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
95-
else
96-
return getfield(dimnames(T), dim)
97-
end
98-
end
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
105-
end
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))
10691
@inline function dimnames(::Type{T}) where {T}
10792
if parent_type(T) <: T
108-
return ntuple(_ -> SUnderscore, Val(ndims(T)))
93+
return ntuple(i -> :_, Val(ndims(T)))
10994
else
11095
return dimnames(parent_type(T))
11196
end
@@ -116,15 +101,15 @@ end
116101
# inserting the Val here seems to help inferability; I got a test failure without it.
117102
function _transpose_dimnames(::Val{S}) where {S}
118103
if length(S) == 1
119-
(SUnderscore, first(S))
104+
(:_, first(S))
120105
elseif length(S) == 2
121106
(last(S), first(S))
122107
else
123108
throw("Can't transpose $S of dim $(length(S)).")
124109
end
125110
end
126111
@inline _transpose_dimnames(x::Tuple{Symbol,Symbol}) = (last(x), first(x))
127-
@inline _transpose_dimnames(x::Tuple{Symbol}) = (SUnderscore, first(x))
112+
@inline _transpose_dimnames(x::Tuple{Symbol}) = (:_, first(x))
128113

129114
@inline function dimnames(::Type{T}) where {I,T<:PermutedDimsArray{<:Any,<:Any,I}}
130115
return map(i -> dimnames(parent_type(T), i), I)
@@ -138,7 +123,7 @@ end
138123
for i in 1:length(I)
139124
if I[i] > 0
140125
if nl < i
141-
push!(e.args, :(ArrayInterface.SUnderscore))
126+
push!(e.args, QuoteNode(:_))
142127
else
143128
push!(e.args, QuoteNode(L[i]))
144129
end
@@ -147,108 +132,58 @@ end
147132
return e
148133
end
149134

150-
_to_int(x::Integer) = Int(x)
151-
_to_int(x::StaticInt) = x
152-
153-
function no_dimname_error(@nospecialize(x), @nospecialize(dim))
154-
throw(ArgumentError("($(repr(dim))) does not correspond to any dimension of ($(x))"))
155-
end
156-
157135
"""
158-
to_dims(::Type{T}, dim) -> Integer
136+
to_dims(x[, d])
159137
160138
This returns the dimension(s) of `x` corresponding to `d`.
161139
"""
162-
to_dims(x, dim) = to_dims(typeof(x), dim)
163-
to_dims(::Type{T}, dim::Integer) where {T} = _to_int(dim)
164-
to_dims(::Type{T}, dim::Colon) where {T} = dim
165-
function to_dims(::Type{T}, dim::StaticSymbol) where {T}
166-
i = find_first_eq(dim, dimnames(T))
167-
i === nothing && no_dimname_error(T, dim)
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
168149
return i
169150
end
170-
@inline function to_dims(::Type{T}, dim::Symbol) where {T}
171-
i = find_first_eq(dim, Symbol.(dimnames(T)))
172-
i === nothing && no_dimname_error(T, dim)
173-
return i
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
174156
end
175-
#=
176-
return i
177-
i = 1
178-
out = 0
179-
for s in dimnames(T)
180-
if Symbol(s) === dim
181-
out = i
182-
break
183-
else
184-
i += i
157+
158+
"""
159+
tuple_issubset
160+
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.
164+
"""
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
185173
end
174+
found || return false
186175
end
187-
if out === 0
188-
no_dimname_error(T, dim)
189-
end
190-
return out
176+
return true
191177
end
192-
=#
193178

194-
to_dims(::Type{T}, dims::Tuple) where {T} = map(i -> to_dims(T, i), dims)
195-
#=
196-
order_named_inds(names, namedtuple)
197-
order_named_inds(names, subnames, inds)
179+
"""
180+
order_named_inds(Val(names); kwargs...)
181+
order_named_inds(Val(names), namedtuple)
198182
199183
Returns the tuple of index values for an array with `names`, when indexed by keywords.
200184
Any dimensions not fixed are given as `:`, to make a slice.
201185
An error is thrown if any keywords are used which do not occur in `nda`'s names.
202-
203-
204-
1. parse into static dimnension names and key words.
205-
2. find each dimnames in key words
206-
3. if nothing is found use Colon()
207-
4. if (ndims - ncolon) === nkwargs then all were found, else error
208-
=#
209-
order_named_inds(x::Tuple, ::NamedTuple{(),Tuple{}}) = ()
210-
function order_named_inds(x::Tuple, nd::NamedTuple{L}) where {L}
211-
return order_named_inds(x, static(Val(L)), Tuple(nd))
212-
end
213-
function order_named_inds(x::Tuple{Vararg{Any,N}}, nd::Tuple, inds::Tuple) where {N}
214-
out = eachop(((x, nd, inds), i) -> order_named_inds(x, nd, inds, i), (x, nd, inds), nstatic(Val(N)))
215-
_order_named_inds_check(out, length(nd))
216-
return out
217-
end
218-
function order_named_inds(x::Tuple, nd::Tuple, inds::Tuple, ::StaticInt{dim}) where {dim}
219-
index = find_first_eq(getfield(x, dim), nd)
220-
if index === nothing
221-
return Colon()
222-
else
223-
return @inbounds(inds[index])
224-
end
225-
end
226-
227-
ncolon(x::Tuple{Colon,Vararg}, n::Int) = ncolon(tail(x), n + 1)
228-
ncolon(x::Tuple{Any,Vararg}, n::Int) = ncolon(tail(x), n)
229-
ncolon(x::Tuple{Colon}, n::Int) = n + 1
230-
ncolon(x::Tuple{Any}, n::Int) = n
231-
function _order_named_inds_check(inds::Tuple{Vararg{Any,N}}, nkwargs::Int) where {N}
232-
if (N - ncolon(inds, 0)) !== nkwargs
233-
error("Not all keywords matched dimension names.")
234-
end
235-
return nothing
236-
end
237-
238-
239-
#=
240-
name_to_idx(name::StaticSymbol, kwargs::Tuple, inds::Tuple, )
241-
name_to_idx(name::StaticSymbol, kwargs::Tuple, inds::Tuple) = _name_to_index(find_first_eq(), inds)
242-
_name_to_index(::Zero, ::Tuple) = Colon()
243-
_name_to_index(::StaticInt{N}, inds::Tuple) where {N} = getfield(inds, N)
244-
245-
# return permute(inds, static_find_all_in(nd, x))
246-
_colon_or_inds(inds::Tuple, ::Zero) = :
247-
_colon_or_inds(inds::Tuple, ::StaticInt{I}) where {I} = getfield(inds, I)
248-
249-
n_i -> _colon_or_inds(inds, find_first_eq(n_i, x))
250-
# FIXME this needs to insert a colon on missing names
251-
186+
"""
252187
@inline function order_named_inds(val::Val{L}; kwargs...) where {L}
253188
if isempty(kwargs)
254189
return ()
@@ -268,8 +203,6 @@ end
268203
end
269204
return Expr(:tuple, exs...)
270205
end
271-
=#
272-
273206
@generated function _perm_tuple(::Type{T}, ::Val{P}) where {T,P}
274207
out = Expr(:curly, :Tuple)
275208
for p in P
@@ -378,6 +311,8 @@ end
378311
Expr(:block, Expr(:meta, :inline), out)
379312
end
380313

314+
315+
381316
"""
382317
size(A)
383318
@@ -395,7 +330,12 @@ julia> ArrayInterface.size(A)
395330
@inline size(A) = Base.size(A)
396331
@inline size(A, d::Integer) = size(A)[Int(d)]
397332
@inline size(A, d) = Base.size(A, to_dims(A, d))
398-
@inline size(x::VecAdjTrans) = (One(), static_length(x))
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
399339

400340
function size(B::S) where {N,NP,T,A<:AbstractArray{T,NP},I,S<:SubArray{T,N,A,I}}
401341
return _size(size(parent(B)), B.indices, map(static_length, B.indices))

src/indexing.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ Changing indexing based on a given argument from `args` should be done through
432432
@propagate_inbounds getindex(A, args...) = unsafe_getindex(A, to_indices(A, args))
433433
@propagate_inbounds function getindex(A; kwargs...)
434434
if has_dimnames(A)
435-
return A[order_named_inds(dimnames(A), kwargs.data)...]
435+
return A[order_named_inds(Val(dimnames(A)); kwargs...)...]
436436
else
437437
return unsafe_getindex(A, to_indices(A, ()); kwargs...)
438438
end
@@ -548,7 +548,7 @@ Store the given values at the given key or index within a collection.
548548
end
549549
@propagate_inbounds function setindex!(A, val; kwargs...)
550550
if has_dimnames(A)
551-
A[order_named_inds(dimnames(A), kwargs.data)...] = val
551+
A[order_named_inds(Val(dimnames(A)); kwargs...)...] = val
552552
else
553553
return unsafe_setindex!(A, val, to_indices(A, ()); kwargs...)
554554
end

0 commit comments

Comments
 (0)