Custom indices range for arrays

The Julia manual talks about being able to define custom unit ranges Arrays with custom indices · The Julia Language.

There are at least 3 packages that deal with this. 1) GitHub - JuliaArrays/CustomUnitRanges.jl: Package-specific AbstractUnitRange types for julia 2) GitHub - JuliaArrays/OffsetArrays.jl: Fortran-like arrays with arbitrary, zero or negative starting indices. 3) GitHub - JuliaArrays/EndpointRanges.jl: Julia package for doing arithmetic on endpoints in array indexing

I am not having much luck figuring it out. I am trying to duplicate fortran code, this piece specifically

COMPLEX, DIMENSION(n,  0:nk) :: eikx
COMPLEX, DIMENSION(n,-nk:nk) :: eiky, eikz

In this particular case it is incredibly helpful to have negative indices (and 0 too).

One issue I have run into with OffsetArrays is that I can’t use setindex! or setindex. Unfortunately I must update the elements in the 2 dimension array constantly.

Is there a way to make a 2 dimensional complex array that can have negative indices and is mutable?

Following and slightly adapting the first example in the readme of OffsetArrays I get:

julia> nk = 1
1

julia> y = OffsetArray{Complex{Float64}}(undef, -nk:nk, -nk:nk)
OffsetArray(::Array{Complex{Float64},2}, -1:1, -1:1) with eltype Complex{Float64} with indices -1:1×-1:1:
 6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im
 6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im
 6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im

julia> y[-nk,-nk] = 1
1

julia> y
OffsetArray(::Array{Complex{Float64},2}, -1:1, -1:1) with eltype Complex{Float64} with indices -1:1×-1:1:
          1.0+0.0im           6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im
 6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im
 6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im  6.94641e-310+6.94641e-310im
1 Like

Yes this works! I was playing around with a simpler example from a forum and it would not allow me to mutate :S. This however does, so I am happy with that.

I was playing with test = OffsetArray(1:5,-2:2), and I could not update the values after… this is probably due to the use of a range.

1 Like

Yes, it uses the range as underlying storage:

julia> typeof(OffsetArray(1:5,-2:2))
OffsetArray{Int64,1,UnitRange{Int64}}

julia> typeof(OffsetArray([1:5...],-2:2)) # this you can mutate
OffsetArray{Int64,1,Array{Int64,1}}

The last parameter is the underlying storage.

1 Like