Note: this package was made before I realized you could do e.g. A[mod1(4, end)]
without any external packages, which probably suffices for most cases.
A very simple package (26 lines of code before comments, docstring, and tests) with one export: Mod
. This is an object using for indexing, like Colon
from Base, and Not
from InvertedIndices.jl. Mod
provides an easy way to have wrap-around indexing of vectors and arrays (which can otherwise be annoying with 1-based indexing).
Usage:
julia> A = rand(3)
3-element Array{Float64,1}:
0.523471984061487
0.3975791533002422
0.3230510641200286
julia> A[Mod(4)]
0.523471984061487
julia> A[4]
ERROR: BoundsError: attempt to access 3-element Array{Float64,1} at index [4]
Stacktrace:
[1] getindex(::Array{Float64,1}, ::Int64) at ./array.jl:729
[2] top-level scope at none:0
Just like regular indexing, Mod
accepts
- scalars like
A[Mod(1)]
(i.e. typeInt
), - ranges like
A[Mod(1:2)]
(AbstractRange{Int}
) - and vectors like
A[Mod([1,2])]
(AbstractVector{Int}
). A non-allocating alternative is also provided here, namelyA[Mod(1,2)] == A[Mod([1,2])]
.
and is able to index into collections A
which are indexable and use Base.to_indices
to process the indices (which I think mostly are AbstractArray
's). For example, A
could be an Array
, OffsetArray
, SubArray
, StaticArray
, etc.
This package should possibly be called PeriodicIndices.jl
and Mod
renamed to Periodic
or similar.
This is similar to FFTViews.jl, but instead of constructing a periodic view type into an array, it provides an indexing object.
The code is heavily inspired by InvertedIndices.jl (but it's actually much simpler to do modular indexing than inverted indexing), and the idea for Mod
was discussed on JuliaLang/julia#32571.
julia> A = 1:3
1:3
julia> A[Mod(4)]
1
julia> A[Mod(2:4)]
3-element Array{Int64,1}:
2
3
1
julia> A = reshape(1:8, 2, 4)
2×4 reshape(::UnitRange{Int64}, 2, 4) with eltype Int64:
1 3 5 7
2 4 6 8
julia> A[Mod(4),2]
4
Works with OffsetArrays.jl too:
julia> using OffsetArrays
julia> A = OffsetArray([1,2,3], -1)
OffsetArray(::Array{Int64,1}, 0:2) with eltype Int64 with indices 0:2:
1
2
3
julia> A[3]
ERROR: BoundsError: attempt to access OffsetArray(::Array{Int64,1}, 0:2) with eltype Int64 with indices 0:2 at index [3]
Stacktrace:
[1] throw_boundserror(::OffsetArray{Int64,1,Array{Int64,1}}, ::Tuple{Int64}) at ./abstractarray.jl:484
[2] checkbounds at ./abstractarray.jl:449 [inlined]
[3] getindex(::OffsetArray{Int64,1,Array{Int64,1}}, ::Int64) at /Users/eh540/.julia/packages/OffsetArrays/vIbpP/src/OffsetArrays.jl:135
[4] top-level scope at none:0
julia> A[Mod(3)]
1