Reputation: 19142
I have some specially-defined arrays in Julia which you can think of being just a composition of many arrays. For example:
type CompositeArray{T}
x::Vector{T}
y::Vector{T}
end
with an indexing scheme
getindex(c::CompositeArray,i::Int) = i <= length(c) ? c.x[i] : c.y[i-length(c.x)]
I do have one caveat: the higher indexing scheme just goes to x
itself:
getindex(c::CompositeArray,i::Int...) = c.x[i...]
Now the iterator through these can easily be made as the chain of the iterator on x
and then on y
. This makes iterating through the values have almost no extra cost. However, can something similar be done for iteration to setindex!
?
I was thinking of having a separate dispatch on CartesianIndex{2}
just for indexing x
vs y
and the index, and building an eachindex
iterator for that, similar to what CatViews.jl does. However, I'm not certain how that will interact with the i...
dispatch, or whether it will be useful in this case.
In addition, will broadcasting automatically use this fast iteration scheme if it's built on eachindex
?
Edits:
length(c::CompositeArray) = length(c.x) + length(c.y)
In the real case, x
can be any AbstractArray
(and thus has a linear index), but since only the linear indexing is used (except for that one user-facing getindex
function), the problem really boils down to finding out how to do this with x
a Vector.
Upvotes: 3
Views: 88
Reputation: 31352
Making X[CartesianIndex(2,1)]
mean something different from X[2,1]
is certainly not going to end well. And I would expect similar troubles from the fact that X[100,1]
may mean something different from X[100]
or if length(X) != prod(size(X))
. You're free to break the rules, but you shouldn't be surprised when functions in Base and other packages expect you to follow them.
The safe way to do this would be to make eachindex(::CompositeArray)
return a custom iterator over objects that you control entirely. Maybe just throw a wrapper around and forward methods to CartesianRange
and CartesianIndex{2}
if that data structure is helpful. Then when you get one of these custom index types, you know that SplitIndex(CartesianIndex(1,2))
is indeed intending to refer to the first element in the second array.
Upvotes: 7