# Reinterpret between SVector{N,ComplexF64} and SVector{2N,Float64} without accessing internal fields

**URL:** <https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183>\
**Category:** General Usage\
**Tags:** question, staticarrays\
**Created:** [March 13, 2026, 12:28pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183 "2026-03-13T12:28:39Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![pmc4](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pmc4/32/211593_2.png) [@pmc4](https://discourse.julialang.org/u/pmc4)\
**Post date:** [March 13, 2026, 12:28pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/1 "2026-03-13T12:28:39Z")

</div>

Hi, everyone. I want to ask you if you know a better way of doing the following that does not imply accessing internal fields.

Imagine I have a vector of complex numbers:

```julia-auto
julia> v1 = [1.0 + 0.5im, 4.8 - 9.0im]
2-element Vector{ComplexF64}:
 1.0 + 0.5im
 4.8 - 9.0im

```

I can convert it to a vector of floats with:

```julia-auto
julia> v2 = reinterpret(Float64, v1)
4-element reinterpret(Float64, ::Vector{ComplexF64}):
  1.0
  0.5
  4.8
 -9.0

```

And go back likewise:

```julia-auto
julia> v3 = reinterpret(ComplexF64, v2)
2-element Vector{ComplexF64}:
 1.0 + 0.5im
 4.8 - 9.0im

```

Everything works fine as I like it. Now I would like to do the same with SVectors:

```julia-auto
julia> s1 = SVector(1.0 + 0.5im, 4.8 - 9.0im)
2-element SVector{2, ComplexF64} with indices SOneTo(2):
 1.0 + 0.5im
 4.8 - 9.0im

```

The naïve implementation fails:

```julia-auto
julia> s2 = reinterpret(SVector{4,Float64}, s1)
Error showing value of type Base.ReinterpretArray{SVector{4, Float64}, 1, ComplexF64, SVector{2, ComplexF64}, false}:

SYSTEM (REPL): showing an error caused an error
ERROR: 1-element ExceptionStack:
DimensionMismatch: 1:1 is inconsistent with SOneTo{2}
Stacktrace:
...

```

However, if access the internal field `data` of `s1`, then it works.

```julia-auto
julia> s2 = reinterpret(SVector{4,Float64}, s1.data)
4-element SVector{4, Float64} with indices SOneTo(4):
  1.0
  0.5
  4.8
 -9.0

```

If I wanted to go back, I could do so accessing again `.data`:

```julia-auto
julia> s3 = reinterpret(SVector{2,ComplexF64}, s2.data)
2-element SVector{2, ComplexF64} with indices SOneTo(2):
 1.0 + 0.5im
 4.8 - 9.0im

```

Is there a way of doing this without accessing `.data`? What I show here is MWE of what I need. I cannot afford to allocate intermediate arrays in the process.

Likewise, in another part of the program, I need to convert SMatrix and SHermitianCompact arrays back to the vector that built them, and the only way to do so is accessing those internal fields. I know it is a bad practice in case the api changes in the future, but I haven’t found a better way for now.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [March 13, 2026, 12:52pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/2 "2026-03-13T12:52:56Z")

</div>

> [@pmc4](#):
>
> Now I would like to do the same with SVectors:

Just destructure and construct a new ‘SArray’.

> [@pmc4](#):
>
> I cannot afford to allocate intermediate arrays in the process.

If the array is an ‘SArray’, it is supposed not to be heap allocated.

> [@pmc4](#):
>
> only way to do so is accessing those internal fields

The problem here is that you consider interface violation as “a way”.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [March 13, 2026, 1:10pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/3 "2026-03-13T13:10:21Z")

</div>

IIRC `Tuple(::SArray)` is public interface, so `s2 = reinterpret(SVector{4,Float64}, Tuple(s1))` is legitimate.

For `SMatrix`, use `vec(matr)`.

For a Hermitian matrix, you can use `StaticArrays.sacollect`.

---

<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:** [March 13, 2026, 2:55pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/4 "2026-03-13T14:55:53Z")

</div>

I suspect the reason direct `reinterpret` does not work is that in your `s2 = reinterpret(SVector{4,Float64}, s1)`, `s1 <: AbstractArray`. So it goes through the `ReinterpretArray` machinery instead of the path for `isbits` values. One could try to fix this in `StaticArrays.jl`, though getting the dispatch right might be difficult.

I think the above suggestion to use `Tuple` is the right idea here.

---

<div class="post-metadata">

**Author:** ![pmc4](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pmc4/32/211593_2.png) [@pmc4](https://discourse.julialang.org/u/pmc4)\
**Post date:** [March 13, 2026, 2:59pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/5 "2026-03-13T14:59:27Z")

</div>

> [@Vasily\_Pisarev](#):
>
> IIRC `Tuple(::SArray)` is public interface, so `s2 = reinterpret(SVector{4,Float64}, Tuple(s1))` is legitimate.
> 
> For `SMatrix`, use `vec(matr)`.

You’re right, I forgot to call `Tuple` directly o the `SVector`. It works like a charm, thanks!

> [@Vasily\_Pisarev](#):
>
> For a Hermitian matrix, you can use `StaticArrays.sacollect`.

Oh, nice. Even though this method is not exported, it’s very useful. I’ve come up with something like this:

```julia-auto
import StaticArrays: sacollect

function f(::Val{N}, A) where N
    L = div(N*(N+1), 2)
    return sacollect(SVector{L, eltype(A)}, A[i,j] for j in 1:N for i in j:N)
end

```

It is fast, it doesn’t allocate and does not depend on internal fields.

---

<div class="post-metadata">

**Author:** ![pmc4](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pmc4/32/211593_2.png) [@pmc4](https://discourse.julialang.org/u/pmc4)\
**Post date:** [March 13, 2026, 3:02pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/6 "2026-03-13T15:02:57Z")

</div>

> [@nsajko](#):
>
> Just destructure and construct a new ‘SArray’.

> [@nsajko](#):
>
> The problem here is that you consider interface violation as “a way”.

Yes, that’s what I was thinking at the beginning, but I couldn’t figure out the way of doing it withoug calling to those internal fields. The solution proposed by @Vasily_Pisarev avoids this problem, too.

> [@nsajko](#):
>
> If the array is an ‘SArray’, it is supposed not to be heap allocated.

What I meant is that I could always transform the SArray to Array, do the reinterpret and go back to SArray, all without internal fields, but at the cost of allocating.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [March 14, 2026, 12:36pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/7 "2026-03-14T12:36:54Z")

</div>

I realized there’s an even simpler method by reinterpreting `Scalar{<:SArray}` which works with the same syntax for all of the cases:

```julia-auto
julia> using StaticArrays

julia> s_2cf64 = SVector(1.0 + 0.5im, 4.8 - 9.0im);

julia> reinterpret(SVector{4,Float64}, Scalar(s_2cf64))[]
4-element SVector{4, Float64} with indices SOneTo(4):
  1.0
  0.5
  4.8
 -9.0

julia> s_2x2fp64 = @SMatrix [1.0 2.0; 3.0 4.0];

julia> reinterpret(SVector{4,Float64}, Scalar(s_2x2fp64))[]
4-element SVector{4, Float64} with indices SOneTo(4):
 1.0
 3.0
 2.0
 4.0

julia> s_2x2hf64 = SHermitianCompact{2,Float64}([1, 2, 3]);

julia> reinterpret(SVector{3,Float64}, Scalar(s_2x2hf64))[]
3-element SVector{3, Float64} with indices SOneTo(3):
 1.0
 2.0
 3.0

```

---

<div class="post-metadata">

**Author:** ![pmc4](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pmc4/32/211593_2.png) [@pmc4](https://discourse.julialang.org/u/pmc4)\
**Post date:** [March 14, 2026, 3:51pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/8 "2026-03-14T15:51:02Z")

</div>

Wow, that’s cool! I guess in the case of the `SHermitianCompact` what is happening with `Scalar` is that it is treating everything as a block and then reinterpret can read the `.lowertriangle` data? I don’t completely understand it, though. It even allows me to directly reinterpret a complex hermitian matrix into a vector of floats:

```julia-auto
julia> sh = SHermitianCompact{2, ComplexF64, 3}([1.3 - 6.8im, 0.5 + 2im, -7.3 + 1.4im])
2×2 SHermitianCompact{2, ComplexF64, 3} with indices SOneTo(2)×SOneTo(2):
 1.3-6.8im 0.5-2.0im
 0.5+2.0im -7.3+1.4im

julia> reinterpret(SVector{6,Float64}, Scalar(sh))[]
6-element SVector{6, Float64} with indices SOneTo(6):
  1.3
 -6.8
  0.5
  2.0
 -7.3
  1.4

```

I’ve tested both approachs with `@btime` and for 3x3 matrices they seem equal.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [March 16, 2026, 1:11pm UTC](https://discourse.julialang.org/t/reinterpret-between-svector-n-complexf64-and-svector-2n-float64-without-accessing-internal-fields/136183/9 "2026-03-16T13:11:19Z")

</div>

> [@pmc4](#):
>
> I guess in the case of the `SHermitianCompact` what is happening with `Scalar` is that it is treating everything as a block and then reinterpret can read the `.lowertriangle` data?

Yes. `Scalar` is just an alias for 0-rank `SArray`. Basically, `reinterpret(S, ::SArray{N,T})` has issues whenever sizes of `S` and `T` don’t match, but we can add another layer of container on top so that the outer container does not change its size. The trick here is to use a static array as the outer container to avoid heap allocations.
