# Indexing StaticArrays

**URL:** <https://discourse.julialang.org/t/indexing-staticarrays/83574>\
**Category:** General Usage\
**Tags:** indexing, staticarrays\
**Created:** [June 30, 2022, 6:07pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574 "2022-06-30T18:07:11Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![bmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bmit/32/12443_2.png) [@bmit](https://discourse.julialang.org/u/bmit)\
**Post date:** [June 30, 2022, 6:07pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/1 "2022-06-30T18:07:11Z")

</div>

This is such a basic question that I almost feel bad asking it, but it would be nice to get some clarification and examples of how others are using StaticArrays.jl. I’ve found [this thread](https://discourse.julialang.org/t/efficiently-selecting-parts-of-a-staticarray/4173), but I think my question is slightly more general.

```julia
using StaticArrays
x = SVector{5}([1.1, 1.2, 1.3, 1.4, 1.5])

```

> julia\> x[[2,5]]  
> 2-element Vector{Float64}:  
> 1.2  
> 1.5

> julia\> x[2:3]  
> 2-element Vector{Float64}:  
> 1.2  
> 1.3

First, it seems very strange to me that the return type is not `SVector`. I’m wondering what the intended baseline use case is where you’d want the type to change when indexing. Or maybe there’s not a way to make it work with multiple dispatch with StaticArrays.

After a bit of digging, I’ve found that I can do either of the following:

> julia\> x[SVector{2}([2,5])]  
> 2-element SVector{2, Float64} with indices SOneTo(2):  
> 1.2  
> 1.5

> julia\> x[StaticArrays.SUnitRange(2,3)]  
> 2-element SVector{2, Float64} with indices SOneTo(2):  
> 1.2  
> 1.3

Given that `SUnitRange` isn’t even exported, I’m guessing that I’m looking in the wrong place. This also seems to involve writing a lot of custom code when you want to use StaticArrays.

Ultimately, I think my questions are:

What is the “right” way to index StaticArrays?

How should we write general code that is dispatched to return a specified subset of an AbstractArray with the correct return type?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [June 30, 2022, 6:41pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/2 "2022-06-30T18:41:17Z")

</div>

Some of my heavily optimized code (non-allocating):

```julia
function residual!(res, yd, y::MVector{S, SimFloat}, s::KPS4, time) where S
    T = S-2 # T: three times the number of particles excluding the origin
    segments = div(T,6) - KITE_PARTICLES
    
    # Reset the force vector to zero.
    for i in 1:segments+KITE_PARTICLES+1
        s.forces[i] .= SVector(0.0, 0, 0)
    end
    # extract the data for the winch simulation
    length, v_reel_out = y[end-1], y[end]
    lengthd, v_reel_outd = yd[end-1], yd[end]
    # extract the data of the particles
    y_ = @view y[begin:end-2]
    yd_ = @view yd[begin:end-2]
    # unpack the vectors y and yd
    part = reshape(SVector{T}(y_), Size(3, div(T,6), 2))
    partd = reshape(SVector{T}(yd_), Size(3, div(T,6), 2))
    pos1, vel1 = part[:,:,1], part[:,:,2]
    pos = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(pos1[:,i-1]) end for i in 1:div(T,6)+1)
    vel = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(vel1[:,i-1]) end for i in 1:div(T,6)+1)
    posd1, veld1 = partd[:,:,1], partd[:,:,2]
    posd = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(posd1[:,i-1]) end for i in 1:div(T,6)+1)
    veld = SVector{div(T,6)+1}(if i==1 SVector(0.0,0,0) else SVector(veld1[:,i-1]) end for i in 1:div(T,6)+1)

```

Perhaps it gives you an idea…

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [June 30, 2022, 6:48pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/3 "2022-06-30T18:48:57Z")

</div>

The docs [recommend](https://juliaarrays.github.io/StaticArrays.jl/dev/pages/api/#Indexing) indexing with a `StaticVector`, since the compiler is otherwise ignorant of output shape without the type-domain size information carried by `StaticArrays`. That could look like this:

```julia
julia> x[SA[2, 5]]
2-element SVector{2, Float64} with indices SOneTo(2):
 1.2
 1.5

julia> x[SA[2:3...]]
2-element SVector{2, Float64} with indices SOneTo(2):
 1.2
 1.3

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [June 30, 2022, 6:51pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/4 "2022-06-30T18:51:38Z")

</div>

> [@stillyslalom](#):
>
> `[2:3...]`

What does this mean?

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [June 30, 2022, 6:57pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/5 "2022-06-30T18:57:05Z")

</div>

Without splatting (`...`), you’d have a one-element vector of eltype `UnitRange`:

```julia
julia> SA[2:3]
1-element SVector{1, UnitRange{Int64}} with indices SOneTo(1):
 2:3

julia> SA[2:3...]
2-element SVector{2, Int64} with indices SOneTo(2):
 2
 3

```

It might be nice to add a convenience indexing syntax to the `@SArray` interface, although I think it’d be a breaking change?

```julia
julia> @SArray x[2:3]
ERROR: ArgumentError: Static Array parameter T must be a type, got [1.1, 1.2, 1.3, 1.4, 1.5]
Stacktrace:

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 30, 2022, 7:09pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/6 "2022-06-30T19:09:11Z")

</div>

> [@bmit](#):
>
> `SVector{5}([1.1, 1.2, 1.3, 1.4, 1.5])`

One thing you should avoid is doing the above. Here you create an ordinary vector, and then convert it to an `SVector`.

Remove the brackets, then you don’t need to include the length either:

```julia
SVector(1.1, 1.2, 1.3, 1.4, 1.5)

```

because the number and the type of inputs is known to the compiler:

```julia
julia> @btime SVector{5}([1.1, 1.2, 1.3, 1.4, 1.5]);
  38.889 ns (1 allocation: 96 bytes)

julia> @btime SVector(1.1, 1.2, 1.3, 1.4, 1.5);
  2.000 ns (0 allocations: 0 bytes)

```

As for indexing, how can the compiler know the size (and hence the type) of the output array from an the input argument? Can you answer this:

What should the output type of `getindex(::SVector{5, Float64}, ::Vector{Int})` be? If you cannot answer it, how can the compiler?

On the other hand: What is the output type of `getindex(::SVector{5, Float64}, ::Svector{3, Int})`? _That_ you can answer.

---

<div class="post-metadata">

**Author:** ![bmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bmit/32/12443_2.png) [@bmit](https://discourse.julialang.org/u/bmit)\
**Post date:** [June 30, 2022, 7:44pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/7 "2022-06-30T19:44:16Z")

</div>

Great tips! I understand your point about `Vector` vs `SVector` for `getindex`, but what about `UnitRange`? Could you direct `getindex(::SVector{5, Float64}, ::UnitRange)` to return an `SVector`?

Perhaps not, since `UnitRange` is just a Tuple and the size isn’t in the type.

My motivation was the desire to avoid needing to write an additional method for anything in a codebase that did indexing.

Is there any syntax that works for StaticArrays that also happens to work for a normal array?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 30, 2022, 8:19pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/8 "2022-06-30T20:19:13Z")

</div>

> [@bmit](#):
>
> Perhaps not, since `UnitRange` is just a Tuple and the size isn’t in the type.

Exactly, you ask yourself what the type of `getindex(::SVector{5, Float64}, ::UnitRange)` is. There’s no answer that includes the size.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 30, 2022, 10:50pm UTC](https://discourse.julialang.org/t/indexing-staticarrays/83574/9 "2022-06-30T22:50:59Z")

</div>

> [@stillyslalom](#):
>
> The docs [recommend](https://juliaarrays.github.io/StaticArrays.jl/dev/pages/api/#Indexing) indexing with a `StaticVector`

I suppose the design is intended to better maintain type stability? Because a getindex-like method `function myget(x::SVector, i) x[SA[i...]] end` is type-unstable (same input types can result in multiple different return types). Using a dynamically sized index `i` to make a `SVector` must require type instability _somewhere_, but you have better control over type instabilities in your own code (function barriers) than in StaticArrays.jl’s code.
