# Sub-arrays of static arrays

**URL:** <https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406>\
**Category:** Performance\
**Created:** [April 25, 2025, 2:20pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406 "2025-04-25T14:20:59Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![TimHargreaves](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timhargreaves/32/207284_2.png) [@TimHargreaves](https://discourse.julialang.org/u/TimHargreaves)\
**Post date:** [April 25, 2025, 2:20pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/1 "2025-04-25T14:20:59Z")

</div>

From a previous step in my computations, I have a static array and I would now like to perform an operation, say a QR decomposition, on a sub-array. This is performance critical code so I would like to squeeze as much speed out of it as possible—ideally being roughly the same speed as performing the operation directly on a static array the same size as the sub-array.

I’ve played around with a few ideas:

```julia
julia> A = @SMatrix rand(4, 4);

# Baseline comparison
julia> A_sub = SMatrix{3, 3}(A[1:3, 1:3]);

julia> 1e9 * @belapsed qr($A_sub)
20.519558676028083

# Views are not efficient
julia> 1e9 * @belapsed qr(@view ($A)[1:3, 1:3])
880.5961538461538

# Constructing a new SMatrix is better but still a bit slower than the target
julia> 1e9 * @belapsed qr(SMatrix{3, 3}($A[1:3, 1:3]))
50.49797160243408

# We can manually construct a new matrix and we then get the speed we desired. Can we automate this?
julia> 1e9 * @belapsed qr(SMatrix{3, 3}(($A)[1,1], ($A)[2,1], ($A)[3,1], 
                              ($A)[1,2], ($A)[2,2], ($A)[3,2],
                              ($A)[1,3], ($A)[2,3], ($A)[3,3]))
22.024072216649948

```

The last results seems to suggest what I’m after is possible, but I’m not sure how to generalise this. Any thoughts would be appreciated.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [April 25, 2025, 2:40pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/2 "2025-04-25T14:40:40Z")

</div>

You could do

```julia
julia> A[SOneTo(3), SOneTo(3)]
3×3 SMatrix{3, 3, Float64, 9} with indices SOneTo(3)×SOneTo(3):
 0.679889 0.422904 0.851232
 0.248234 0.805128 0.460355
 0.584804 0.0535163 0.903487

```

i.e.

```julia
qr(A[SOneTo(3), SOneTo(3)])

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 25, 2025, 2:45pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/3 "2025-04-25T14:45:13Z")

</div>

And that’s also exactly what `@view A[SOneTo(3), SOneTo(3)]` returns, too. Since static arrays are immutable, there’s no meaningful distinction between views and `getindex`. You just need to give it static _indices_ so it can know exactly how big the sub-array needs to be.

---

<div class="post-metadata">

**Author:** ![TimHargreaves](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timhargreaves/32/207284_2.png) [@TimHargreaves](https://discourse.julialang.org/u/TimHargreaves)\
**Post date:** [April 25, 2025, 2:57pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/4 "2025-04-25T14:57:09Z")

</div>

Ah fantastic, thank you both! That gives the target speed

```julia
1e9 * @belapsed qr(($A)[SOneTo(3), SOneTo(3)])
21.837349397590362

```

Does this only work for unit ranges starting from one? I can’t seem to find any variants for say `i:j` where `i`, `j` are known at compile time.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [April 25, 2025, 3:00pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/5 "2025-04-25T15:00:48Z")

</div>

Yeah, there really should be a static range type. For now though you can just write

```julia
function srange(i,j;kwargs...) 
    r = range(i,j;kwargs...)
    SVector{length(r)}(r)
end

```

and then e.g.

```julia
qr(A[srange(2, 4), srange(1, 3)])

```

---

<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:** [April 25, 2025, 5:29pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/6 "2025-04-25T17:29:44Z")

</div>

This one seems a bit more robust with respect to performance:

```julia
 function srange_(start, step, len)
    t = ntuple(i->(i-1)*step + start, len)
    return SVector(t)
end

```

It seems fast in most cases, but if you really need it you can provide `len` as a `Val`. This also works for float ranges.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [April 25, 2025, 5:53pm UTC](https://discourse.julialang.org/t/sub-arrays-of-static-arrays/128406/7 "2025-04-25T17:53:47Z")

</div>

There is the internal `StaticArrays.SUnitRange(start, stop)`. It may have some pitfalls or missing features and (since it isn’t part of the interface) might someday break. But _for now_ it works. And I would hope that eventually something like this gets made public interface.
