# Undef array with customized index

**URL:** <https://discourse.julialang.org/t/undef-array-with-customized-index/60377>\
**Category:** General Usage\
**Created:** [May 1, 2021, 12:33pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377 "2021-05-01T12:33:27Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 1, 2021, 12:33pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/1 "2021-05-01T12:33:28Z")

</div>

I’m curious if there is a convenient way to define an array with customized index.  
In fortran, we have `real, dimension(2:6) :: array`.  
I know in julia we can use `Array{Float64}(undef, 10)` to declare a 10-element array with undef.  
We can then use `OffsetArray` to get an index starting from any integer.  
Is there an easy way like `array(Int, -3:3, -5:5)` or `Int[-3:3, -5:5]` to get an array with a customized index?

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [May 1, 2021, 1:42pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/2 "2021-05-01T13:42:34Z")

</div>

I am not sure if a helper function exists, but it is not hard to to write one, for example, the one-liner below work if you always use ranges to specify the axes:

```julia
oarray(::Type{T}, dims...) where {T} = OffsetArray(Array{T}(undef, length.(dims)...), dims...)

```

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 1, 2021, 2:08pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/3 "2021-05-01T14:08:32Z")

</div>

@Henrique_Becker Thanks, this is pretty close to what I want.  
I hope this kind of syntax can get support on the language level in the future.

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 1, 2021, 2:23pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/4 "2021-05-01T14:23:11Z")

</div>

Also, it seems `OffsetArray` is slower than the standard array when accessing the array elements.  
A language-level support should allow the compiler optimizes this away.

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [May 1, 2021, 3:33pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/5 "2021-05-01T15:33:55Z")

</div>

OffsetArrays already defines an `undef` constructor:

```julia
julia> OffsetArray{Int}(undef, -3:3, -5:3)
7×9 OffsetArray(::Matrix{Int64}, -3:3, -5:3) with eltype Int64 with indices -3:3×-5:3:
...

```

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 1, 2021, 6:19pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/6 "2021-05-01T18:19:07Z")

</div>

I don’t know this. Thanks!

Both answers are great.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 1, 2021, 7:28pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/7 "2021-05-01T19:28:34Z")

</div>

> [@linwaytin](#):
>
> `OffsetArray` is slower than the standard array when accessing the array elements

Is it? Sounds strange to me. I would like to know more about that.

In parallel, note that in Julia there are many ways to iterate over the elements of an array which are independent of the way indices are set. With those the interfaces with arrays of other languages is less prone to error.

```julia
for i in eachindex(v)

for (i,el) in pairs(v)

for el in v

for i in axes(v)[1]

```

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 1, 2021, 8:02pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/8 "2021-05-01T20:02:51Z")

</div>

What I meant is a simple element access like the following.

```julia
X = rand(10,10)
XO = OffsetArray(X, -5:4, -5:4)
@btime X[3, 3] # 14.729 ns (1 allocation: 16 bytes)
@btime XO[3, 3] # 17.698 ns (1 allocation: 16 bytes)

```

I’m still using `julia 1.5.4`. Maybe this is the reason.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 2, 2021, 5:31am UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/9 "2021-05-02T05:31:09Z")

</div>

Your benchmark isn’t measuring what you think–it’s dominated by the fact that `X` and `XO` are non-constant global variables. See: [GitHub - JuliaCI/BenchmarkTools.jl: A benchmarking framework for the Julia language](https://github.com/JuliaCI/BenchmarkTools.jl#quick-start) for more info.

Fixing this gives quite different results (on Julia 1.5.3):

```julia

julia> @btime ($X)[3, 3]
  1.753 ns (0 allocations: 0 bytes)
0.34069137833211705

julia> @btime ($XO)[3, 3]
  2.841 ns (0 allocations: 0 bytes)
0.7901133830907208

```

Updating to Julia 1.6.1 makes `OffsetArrays` even faster:

```julia
julia> @btime ($X)[3, 3]
  1.593 ns (0 allocations: 0 bytes)
0.41741256881369937

julia> @btime ($XO)[3, 3]
  2.250 ns (0 allocations: 0 bytes)
0.4126414953734878

```

> [@linwaytin](#):
>
> A language-level support should allow the compiler optimizes this away.

What do you actually mean by this? Most of Julia is implemented in Julia already, so there is no difference between “language-level” code and user code in terms of performance.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [May 2, 2021, 6:29am UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/10 "2021-05-02T06:29:27Z")

</div>

Recommended way is `axes(v, 1)`

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [May 2, 2021, 8:04am UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/11 "2021-05-02T08:04:52Z")

</div>

While there is a small overhead in the “raw” indexing while accessing each individual element, this often does not matter much in practical applications when you access a large number of elements in a loop (see [this issue](https://github.com/JuliaArrays/OffsetArrays.jl/issues/166) in OffsetArrays.jl). Such differences, when the exist, are perhaps due to the bounds-checking being sub-optimal (there is [another issue](https://github.com/JuliaArrays/OffsetArrays.jl/issues/214) in OffsetArrays where we are trying to improve this).

Here is an example:

```julia
julia> using OffsetArrays

julia> f(x) = sum(xi for xi in x);

julia> g(x) = sum(x[i] for i in eachindex(x));

julia> g2(x) = sum((@inbounds x[i]) for i in eachindex(x));

julia> A = ones(2000,2000);

julia> AO = ones(1:2000, 1:2000);

julia> @btime f($A);
  6.686 ms (0 allocations: 0 bytes)

julia> @btime f($AO);
  6.754 ms (0 allocations: 0 bytes)

julia> @btime g($A);
  6.738 ms (0 allocations: 0 bytes)

julia> @btime g($AO);
  6.791 ms (0 allocations: 0 bytes)

julia> @btime g2($A);
  6.727 ms (0 allocations: 0 bytes)

julia> @btime g2($AO);
  6.724 ms (0 allocations: 0 bytes)

```

We see that with bounds-checking turned off, there is no performance gap anymore.

To answer the original question, you should be able to use the `OffsetArray` constructor to initialize an undefined array.

```julia
julia> OffsetArray{Float64}(undef, 2:3, 4:5)
2×2 OffsetArray(::Matrix{Float64}, 2:3, 4:5) with eltype Float64 with indices 2:3×4:5:
 0.0 0.0
 0.0 0.0

```

Another useful function is `similar`, which chooses an appropriate array type for you depending on the axes.

```julia
julia> similar(Array{Float64}, 2:3, 4:5)
2×2 OffsetArray(::Matrix{Float64}, 2:3, 4:5) with eltype Float64 with indices 2:3×4:5:
 6.94499e-310 6.94499e-310
 6.94499e-310 0.0

```

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 2, 2021, 3:29pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/12 "2021-05-02T15:29:22Z")

</div>

@rdeits Thanks, could you please explain why you use ($X) in the benchmark?  
I can see the difference (no allocation) but I don’t understand why.

I thought proper language support might make the OffsetArrays more efficient.  
I might be wrong, but what causes the different access time?  
The difference is more than 0.5ns in your benchmark.  
Is it from the bound checking?

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 2, 2021, 3:32pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/13 "2021-05-02T15:32:16Z")

</div>

@jishnub Thanks, I understand that in practice the overhead is not important.  
Thank you for pointing out there are other ways to achieve what I want.

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 2, 2021, 3:34pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/14 "2021-05-02T15:34:13Z")

</div>

@Skoffer Could you please elaborate on how to do this?

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [May 2, 2021, 4:18pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/15 "2021-05-02T16:18:30Z")

</div>

I only meant, that instead of `axes(v) [1]` one should use `axes(v, 1)`

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 2, 2021, 9:19pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/16 "2021-05-02T21:19:07Z")

</div>

@Skoffer Thanks.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 3, 2021, 4:31am UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/17 "2021-05-03T04:31:53Z")

</div>

> [@linwaytin](#):
>
> Thanks, could you please explain why you use ($X) in the benchmark?  
> I can see the difference (no allocation) but I don’t understand why.

Check the BenchmarkTools documentation here for an explanation of what’s going on: [GitHub - JuliaCI/BenchmarkTools.jl: A benchmarking framework for the Julia language](https://github.com/JuliaCI/BenchmarkTools.jl#quick-start)

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [May 3, 2021, 2:17pm UTC](https://discourse.julialang.org/t/undef-array-with-customized-index/60377/18 "2021-05-03T14:17:11Z")

</div>

@rdeits Thanks! I didn’t know that.
