# Convert Vector{SVector} to Matrix

**URL:** <https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939>\
**Category:** Performance\
**Tags:** staticarrays\
**Created:** [August 24, 2019, 4:04pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939 "2019-08-24T16:04:36Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![benzwick](https://avatars.discourse-cdn.com/v4/letter/b/a4c791/32.png) [@benzwick](https://discourse.julialang.org/u/benzwick)\
**Post date:** [August 24, 2019, 4:04pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/1 "2019-08-24T16:04:36Z")

</div>

I have some code where I need to store coordinates `x` of a mesh. I’m using a vector of points (static vectors), i.e.

```julia
using StaticArrays
Point{dim} = SVector{dim, Float64}
x = rand(Point{3}, 10)

```

but some parts of the code (e.g. using WriteVTK) require the coordinates to be in a matrix instead of a vector. Is there anything wrong with adding the following constructor method to convert the above vector to a matrix

```julia
Base.Matrix(v::Vector{SVector{S, T}}) where {S, T} = reduce(hcat, v)

```

and using

```julia
m = Matrix(x)
mT = transpose(Matrix(x))

```

to get the vector as a matrix and matrix transpose? (EDIT: Yes, because it creates a copy it is not efficient)

Is there a more efficient way to do this? (EDIT: Yes, use `reinterpret` and `reshape` as explained below)

Is there any way to do this without making a copy so that modifying elements of matrix `m` will change the corresponding elements of `x`? (EDIT: Yes, as above)

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 24, 2019, 4:37pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/2 "2019-08-24T16:37:15Z")

</div>

Checkout the amazing `reinterpret`:

```julia
julia> reinterpret(Float64, x)
30-element reinterpret(Float64, ::Array{SArray{Tuple{3},Float64,1,3},1}):
 0.8552062516276724 
 0.6691039952034261 
...

```

which you can then `reshape`. That could maybe be somewhere in the staticarrays doc.

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 24, 2019, 4:38pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/3 "2019-08-24T16:38:50Z")

</div>

Possibly even a `convert` method? So an array of svectors would be automatically converted to a matrix. But possibly that’d be a bit confusing…

---

<div class="post-metadata">

**Author:** ![benzwick](https://avatars.discourse-cdn.com/v4/letter/b/a4c791/32.png) [@benzwick](https://discourse.julialang.org/u/benzwick)\
**Post date:** [August 24, 2019, 5:24pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/4 "2019-08-24T17:24:02Z")

</div>

Thanks @antoine-levitt, I wasn’t aware of the `reinterpret` function. This does appear to be much faster for large arrays:

```julia
using StaticArrays

Base.Matrix(v::Vector{SVector{S, T}}) where {S, T} = reduce(hcat, v)

eltocols(v::Vector{SVector{dim, T}}) where {dim, T} =
    reshape(reinterpret(Float64, v), dim, :)

eltorows(v::Vector{SVector{dim, T}}) where {dim, T} =
    transpose(reshape(reinterpret(Float64, v), dim, :))

Point{dim} = SVector{dim, Float64}

x = rand(Point{3}, 1000000)

using BenchmarkTools

@benchmark m = Matrix($x)
@benchmark mT = transpose(Matrix($x))
@benchmark m = eltocols($x)
@benchmark mT = eltorows($x)

```

Results:

```julia
julia> @benchmark m = Matrix($x)
BenchmarkTools.Trial: 
  memory estimate: 22.89 MiB
  allocs estimate: 2
  --------------
  minimum time: 10.874 ms (0.00% GC)
  median time: 17.070 ms (0.00% GC)
  mean time: 15.128 ms (4.16% GC)
  maximum time: 53.498 ms (78.78% GC)
  --------------
  samples: 331
  evals/sample: 1

julia> @benchmark mT = transpose(Matrix($x))
BenchmarkTools.Trial: 
  memory estimate: 22.89 MiB
  allocs estimate: 3
  --------------
  minimum time: 10.695 ms (0.00% GC)
  median time: 11.154 ms (0.00% GC)
  mean time: 11.346 ms (2.48% GC)
  maximum time: 52.555 ms (78.71% GC)
  --------------
  samples: 441
  evals/sample: 1

julia> @benchmark m = eltocols($x)
BenchmarkTools.Trial: 
  memory estimate: 64 bytes
  allocs estimate: 2
  --------------
  minimum time: 13.549 ns (0.00% GC)
  median time: 15.117 ns (0.00% GC)
  mean time: 17.357 ns (6.48% GC)
  maximum time: 1.122 μs (97.98% GC)
  --------------
  samples: 10000
  evals/sample: 998

julia> @benchmark mT = eltorows($x)
BenchmarkTools.Trial: 
  memory estimate: 80 bytes
  allocs estimate: 3
  --------------
  minimum time: 16.939 ns (0.00% GC)
  median time: 17.799 ns (0.00% GC)
  mean time: 20.796 ns (8.00% GC)
  maximum time: 1.255 μs (98.28% GC)
  --------------
  samples: 10000
  evals/sample: 998

```

Moreover, it doesn’t create a copy so the original `x` vector can be modified by changing the entries of the matrix `m`.

```julia
julia> x = rand(Point{3}, 1000000)
1000000-element Array{SArray{Tuple{3},Float64,1,3},1}:
 [0.4185398323656475, 0.501898669373563, 0.41183968543604865]

julia> m = eltocols(x)
3×1000000 reshape(reinterpret(Float64, ::Array{SArray{Tuple{3},Float64,1,3},1}), 3, 1000000) with eltype Float64:
 0.41854 0.86096 0.762052 0.801235 … 0.293778 0.1493 0.462913
 0.501899 0.964937 0.796707 0.379564 0.932526 0.0662906 0.149578
 0.41184 0.790648 0.52458 0.837944 0.921923 0.477261 0.267126

julia> m[1,1] = 0

julia> x
1000000-element Array{SArray{Tuple{3},Float64,1,3},1}:
 [0.0, 0.501898669373563, 0.41183968543604865]           

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [August 25, 2019, 12:43am UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/5 "2019-08-25T00:43:34Z")

</div>

> [@antoine-levitt](#):
>
> That could maybe be somewhere in the staticarrays doc.

It is  
[https://juliaarrays.github.io/StaticArrays.jl/stable/pages/api.html#Arrays-of-static-arrays-1](https://juliaarrays.github.io/StaticArrays.jl/stable/pages/api.html#Arrays-of-static-arrays-1)

---

<div class="post-metadata">

**Author:** ![benzwick](https://avatars.discourse-cdn.com/v4/letter/b/a4c791/32.png) [@benzwick](https://discourse.julialang.org/u/benzwick)\
**Post date:** [August 25, 2019, 3:41am UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/6 "2019-08-25T03:41:27Z")

</div>

The doc explains how to convert from a dynamically sized `AbstractArray` to one of the statically sized array types, and how to `reinterpret` a `dim` x `N` `Matrix{T}` as a `Vector{SVector{dim,T}}` but not how to `reinterpret` a `Vector{SVector{dim,T}}` as a `Matrix{T}`.

However, it is still very helpful.

Thank you so much!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [August 25, 2019, 4:27am UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/7 "2019-08-25T04:27:59Z")

</div>

> [@benzwick](#):
>
> but not how to `reinterpret` a `Vector{SVector{dim,T}}` as a `Matrix{T}` .

`reinterpret` does not give you a `Matrix` though.

---

<div class="post-metadata">

**Author:** ![benzwick](https://avatars.discourse-cdn.com/v4/letter/b/a4c791/32.png) [@benzwick](https://discourse.julialang.org/u/benzwick)\
**Post date:** [August 25, 2019, 6:26am UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/8 "2019-08-25T06:26:12Z")

</div>

Thanks @kristoffer.carlsson, I didn’t think of that. In practice they appear to behave the same (see below) which is what I need. What should I call this “matrix-like” type: `3×1000000 reshape(reinterpret(Float64, ::Array{SArray{Tuple{3},Float64,1,3},1}), 3, 1000000) with eltype Float64`? Could it be a an `AbstractMatrix`? And is there any difference in practice apart from the different type (for dispatch etc.)?

Comparing `Matrix(x)` with `eltocols(x)`:

```julia
julia> m = Matrix(x)
3×1000000 Array{Float64,2}:
 0.468326 0.568942 0.599504 0.569535 … 0.917145 0.440911 0.739385
 0.470099 0.442289 0.811437 0.809661 0.559429 0.42691 0.382616
 0.200765 0.235891 0.985741 0.960975 0.0103481 0.41207 0.507787

julia> r = eltocols(x)
3×1000000 reshape(reinterpret(Float64, ::Array{SArray{Tuple{3},Float64,1,3},1}), 3, 1000000) with eltype Float64:
 0.468326 0.568942 0.599504 0.569535 … 0.917145 0.440911 0.739385
 0.470099 0.442289 0.811437 0.809661 0.559429 0.42691 0.382616
 0.200765 0.235891 0.985741 0.960975 0.0103481 0.41207 0.507787

julia> using LinearAlgebra

julia> norm(m - r)
0.0

julia> norm(m[1,1:10] - r[1,1:10])
0.0
```

---

<div class="post-metadata">

**Author:** ![benzwick](https://avatars.discourse-cdn.com/v4/letter/b/a4c791/32.png) [@benzwick](https://discourse.julialang.org/u/benzwick)\
**Post date:** [August 25, 2019, 6:31am UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/9 "2019-08-25T06:31:57Z")

</div>

I guess I just answered my own question:

```julia
julia> typeof(m)
Array{Float64,2}

julia> supertype(typeof(m))
DenseArray{Float64,2}

julia> typeof(r)
Base.ReshapedArray{Float64,2,Base.ReinterpretArray{Float64,1,SArray{Tuple{3},Float64,1,3},Array{SArray{Tuple{3},Float64,1,3},1}},Tuple{}}

julia> supertype(typeof(r))
AbstractArray{Float64,2}

julia> typeof(r) <: AbstractMatrix
true

```

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [January 14, 2023, 3:16pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/10 "2023-01-14T15:16:46Z")

</div>

> [@benzwick](#):
>
> ```julia
> eltocols(v::Vector{SVector{dim, T}}) where {dim, T} =
> reshape(reinterpret(Float64, v), dim, :)
> 
> ```

Thanks! I was looking for a method to convert a `Vector` of `SVector`s into a matrix without allocation, and your technique is the solution.

But as you mentioned, I notice that modifying the resulting `ReshapedArray` entries modifies the entries of the original `SVector`s. How is this possible? I thought the entries of `SVector`s are unmutable. Does this mean that we can always bypass the unmutability of an unmutable type (like `SVector` in the present example) by `reinterpret`ing it as a mutable type (like `ReshapedArray` in the present example)?

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [March 2, 2023, 4:50pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/11 "2023-03-02T16:50:52Z")

</div>

Note you can now also `reinterpret(reshape, ...`:

```julia
julia> x = [@SVector(rand(3)) for _ in 1:5];

julia> reinterpret(reshape, eltype(eltype(x)), x)
3×5 reinterpret(reshape, Float64, ::Vector{SVector{3, Float64}}) with eltype Float64:
 0.12019 0.0829133 0.580475 0.873409 0.710157
 0.97712 0.556687 0.696489 0.419789 0.0425647
 0.506971 0.106399 0.887721 0.116239 0.486331

```

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [March 2, 2023, 4:52pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/12 "2023-03-02T16:52:01Z")

</div>

> [@wsshin](#):
>
> But as you mentioned, I notice that modifying the resulting `ReshapedArray` entries modifies the entries of the original `SVector`s. How is this possible? I thought the entries of `SVector`s are unmutable. Does this mean that we can always bypass the unmutability of an unmutable type (like `SVector` in the present example) by `reinterpret`ing it as a mutable type (like `ReshapedArray` in the present example)?

They’re elements of a mutable array.  
You can always edit the mutable array `x` in my above example, by replacing one immutable `SVector` with another immutable `SVector`.  
The `reinterpret(reshape` array does alias `x`, so mutating it will also change the contents of the mutable `x`.

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [March 3, 2023, 2:24am UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/13 "2023-03-03T02:24:14Z")

</div>

> [@Elrod](#):
>
> They’re elements of a mutable array.  
> You can always edit the mutable array `x` in my above example, by replacing one immutable `SVector` with another immutable `SVector`.

For example, consider

```julia-repl
julia> a = [SVector(1,2,3), SVector(4,5,6)]
2-element Vector{SVector{3, Int64}}:
 [1, 2, 3]
 [4, 5, 6]

julia> A = reinterpret(reshape, Int64, a)
3×2 reinterpret(reshape, Int64, ::Vector{SVector{3, Int64}}) with eltype Int64:
 1 4
 2 5
 3 6

```

Here, if I set `A[1,1] = 0`, then `a` also changes:

```julia-repl
julia> A[1,1] = 0
0

julia> a
2-element Vector{SVector{3, Int64}}:
 [0, 2, 3]
 [4, 5, 6]

```

To me, replacing `A[1,1]` seems equivalent to replacing the first entry to `a[1]`. Because `a[1]` is `SVector`, being able to replace its first entry seems strange to me.

But you say that replacing `A[1,1]` is actually equivalent to replacing the entire vector `a[1]`. I am not sure how replacing one element `A[1,1]` could be interpreted as replacing the entire `a[1]` with three entries. Still, I think you are correct, because if we make `a` an `SVector` of `SVector`s, we cannot replace `A[1,1]`:

```julia-repl
julia> a = SVector(SVector(1,2,3), SVector(4,5,6))
2-element SVector{2, SVector{3, Int64}} with indices SOneTo(2):
 [1, 2, 3]
 [4, 5, 6]

julia> A = reinterpret(reshape, Int64, a)
3×2 reinterpret(reshape, Int64, ::SVector{2, SVector{3, Int64}}) with eltype Int64 with indices Base.OneTo(3)×SOneTo(2):
 1 4
 2 5
 3 6

julia> A[1,1] = 0
ERROR: setindex!(::SVector{2, SVector{3, Int64}}, value, ::Int) is not defined.
 Hint: Use `MArray` or `SizedArray` to create a mutable static array
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] setindex!(a::SVector{2, SVector{3, Int64}}, value::SVector{3, Int64}, i::Int64)
   @ StaticArrays ~/Programming/StaticArrays/src/indexing.jl:3
 [3] _setindex_ra!
   @ ./reinterpretarray.jl:648 [inlined]
 [4] setindex!(::Base.ReinterpretArray{Int64, 2, SVector{3, Int64}, SVector{2, SVector{3, Int64}}, true}, ::Int64, ::Int64, ::Int64)
   @ Base ./reinterpretarray.jl:507
 [5] top-level scope
   @ REPL[33]:1

```

---

<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:** [March 3, 2023, 6:27pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/14 "2023-03-03T18:27:22Z")

</div>

I think the `SVector` here is distracting you. We can do this even just with `Int`s:

```julia
julia> b = [1, 3];

julia> B = reinterpret(Bool, b)
16-element reinterpret(Bool, ::Vector{Int64}):
 1
 0
 0
 0
 0
 0
 0
 0
 1
 0
 0
 0
 0
 0
 0
 0

```

```julia
julia> B[1] = false; B[2] = true;

julia> b
2-element Vector{Int64}:
 256
   3

```

Just like an `Int`, an `SVector{Int}` is just a collection of bits. Once we put those bits in an array, the memory of the array is mutable so we can change their values.

---

<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:** [March 3, 2023, 7:55pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/15 "2023-03-03T19:55:34Z")

</div>

You are not mutating an immutable data structure, if that’s what you are worrying about:

```julia
as = SVector(1,2,3)
a = [as, SVector(4,5,6)]
A = reinterpret(reshape, Int64, a)
A[1,1] = 0

```

Now,

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

```

as you know, but `as` is unchanged.

```julia
julia> as
3-element SVector{3, Int64} with indices SOneTo(3):
 1
 2
 3

```

You have only mutated the _mutable_ variable `a`.

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [March 6, 2023, 3:57pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/16 "2023-03-06T15:57:55Z")

</div>

> [@Mason](#):
>
> Just like an `Int`, an `SVector{Int}` is just a collection of bits. Once we put those bits in an array, the memory of the array is mutable so we can change their values.

@Mason, this doesn’t explain why we _cannot_ mutate `A[1,1]` reinterpreted from `a` that is `SVector` of `SVector`s as shown in the last example in [my earlier posting above](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/13).

---

<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:** [March 6, 2023, 4:25pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/17 "2023-03-06T16:25:19Z")

</div>

In your final example, you have an `SVector` of `SVector`s as the base memory. That’s all immutable so of course you can’t mutate it, unlike the case where you have an mutable array of `SVector`s

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [March 6, 2023, 6:27pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/18 "2023-03-06T18:27:30Z")

</div>

Sure, I’m just just pointing out that my final example contradicts your following claim:

> [@Mason](#):
>
> Just like an `Int`, an `SVector{Int}` is just a collection of bits. Once we put those bits in an array, the memory of the array is mutable so we can change their values.

Actually I had the same thought as your above claim, but I was puzzled because my final example didn’t allow me to change the bit array.

---

<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:** [March 6, 2023, 6:38pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/19 "2023-03-06T18:38:41Z")

</div>

> [@wsshin](#):
>
> Sure, I’m just just pointing out that my final example contradicts your following claim:
> 
> > [@Mason](#):
> >
> > Just like an `Int`, an `SVector{Int}` is just a collection of bits. Once we put those bits in an array, the memory of the array is mutable so we can change their values.

No it doesnt. Note that I wrote **Once we put those bits in an array, the memory of the array is mutable so we can change their values.**

SArrays are not mutable. Your example would work if you used an MArray.

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [March 6, 2023, 7:26pm UTC](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939/20 "2023-03-06T19:26:37Z")

</div>

I feel that the discussion is going a bit tangential, but what did you mean by this?

> [@Mason](#):
>
> Once we put those bits in an array

I thought it meant performing `A = reinterpret(reshape, Int64, a)`. Then it sounded like we could change the contents of `A` regardless of the type of `a`, because this operation put `a` into an array `A` of bits.

[Next page](https://discourse.julialang.org/t/convert-vector-svector-to-matrix/27939.md?page=2)
