struct MyOffsetVector{T,S} <: AbstractVector{T}
data::Vector{T}
offset::Int
end
@generated function offset_index(v::MyOffsetVector{T,S}, i) where {T,S}
S == 1 && return :(i - v.offset + 1)
log2S = log2(S)
if round(log2S) == log2S
return :( ((i - v.offset) >> $log2S) + 1)
else
return :( ((i - v.offset) Ă· $S) + 1)
end
end
@inbounds Base.getindex(v::MyOffsetVector, i) = v.data[offset_index(v,i)]
@inbounds Base.setindex!(v::MyOffsetVector, i, x) = v.data[offset_index(v,i)] = x
Base.size(v::MyOffsetVector) = size(v.data)
You might want to replace offset_index with something that throws an error if there is a remainder (ie, use divrem, and throw an error for non-zero remainders).
I haven’t tested this, but I imagine you’ll see a lot of errors from here.
For example IndexStyle() is neither IndexLinear() or IndexCartesian(), meaning things like “print” will try generic Cartesian indices incrementing by a step at a time for printing and other array operations.
So if I wanted to do something like this, I’d probably look into defining a new IndexStyle. AbstractArray Interface.