# Creating SVector of a single SVector{1, Float64}

**URL:** <https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979>\
**Category:** New to Julia\
**Tags:** question, staticarrays\
**Created:** [April 2, 2023, 6:08pm UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979 "2023-04-02T18:08:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![aafsar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aafsar/32/47420_2.png) [@aafsar](https://discourse.julialang.org/u/aafsar)\
**Post date:** [April 2, 2023, 6:08pm UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/1 "2023-04-02T18:08:57Z")

</div>

**Short version:** Why can I create SVector of at least 2 SVectors of size 1, or a SVector of a single SVector of at least size 2, but cannot create SVector of a single SVector of size 1?:

```shell
julia> using StaticArrays

julia> my_vector_1d = SVector{1, Float64}(0.8)
1-element SVector{1, Float64} with indices SOneTo(1):
 0.8

julia> my_vector_2d = SVector{2, Float64}(0.8, 0.9)
2-element SVector{2, Float64} with indices SOneTo(2):
 0.8
 0.9

julia> my_container_2d = SVector{1, SVector{2, Float64}}(my_vector_2d)
1-element SVector{1, SVector{2, Float64}} with indices SOneTo(1):
 [0.8, 0.9]

julia> my_container_1d = SVector{2, SVector{1, Float64}}(my_vector_1d, my_vector_1d)
2-element SVector{2, SVector{1, Float64}} with indices SOneTo(2):
 [0.8]
 [0.8]

julia> my_other_container_1d = SVector{1, SVector{1, Float64}}(my_vector_1d)
ERROR: MethodError: Cannot `convert` an object of type Float64 to an object of type SVector{1, Float64}
Closest candidates are:
  convert(::Type{SVector{N, T}}, ::CartesianIndex{N}) where {N, T} at ~/.julia/packages/StaticArrays/a4r2v/src/SVector.jl:8
  convert(::Type{T}, ::Factorization) where T<:AbstractArray at /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/LinearAlgebra/src/factorization.jl:58
  convert(::Type{SA}, ::Tuple) where SA<:StaticArray at ~/.julia/packages/StaticArrays/a4r2v/src/convert.jl:179
  ...
Stacktrace:
 [1] macro expansion
   @ ~/.julia/packages/StaticArraysCore/U2Z1K/src/StaticArraysCore.jl:81 [inlined]
 [2] convert_ntuple
   @ ~/.julia/packages/StaticArraysCore/U2Z1K/src/StaticArraysCore.jl:77 [inlined]
 [3] SVector{1, SVector{1, Float64}}(x::Tuple{Float64})
   @ StaticArraysCore ~/.julia/packages/StaticArraysCore/U2Z1K/src/StaticArraysCore.jl:113
 [4] SVector{1, SVector{1, Float64}}(sa::SVector{1, Float64})
   @ StaticArrays ~/.julia/packages/StaticArrays/a4r2v/src/convert.jl:167
 [5] top-level scope
   @ REPL[54]:1

```

**Long version:**  
I have a model where I deal with points of a multidimensional space with a known and fixed dimension, and I use `SVector{Dim, Float64}` to represent a point. I also deal with elements of (Cartesian) product spaces of `N` of these spaces, again with known and fixed `N`, and I represent these elements as `SVector{N, SVector{Dim, Float64}}`. Of course I could have represented these elements as `SMatrix` but conceptually it is more suitable to represent them as vectors (of vectors).

Now, I can define SVectors of SVectors as long as the collection consists of at least two SVectors, i.e. N \>= 2. But I need to work on subspaces of the product space, which means that sometimes I need to create collections of lower sizes, which can be N=1. The problem is that if the original spaces are unidimensional, i.e. Dim=1, and the subset consists of a single space, i.e. N=1, I get the above error.

If indeed it is not allowed to create `SVector{1, SVector{1, Float64}` objects, I can check this condition in compile-time and treat these objects as of type `<: Real`, but then either:

1. I have to add methods everywhere to work with `Real`s,
2. or perhaps define a Union type and let compiler to generate specialized methods, since the operations are purely arithmetic/algebraic.

Thank you!

---

<div class="post-metadata">

**Author:** ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)\
**Post date:** [April 2, 2023, 7:21pm UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/2 "2023-04-02T19:21:44Z")

</div>

i normally build `SVectors` with the `SA` constructor:

```julia
julia> SA[SA[1.]]
1-element SVector{1, SVector{1, Float64}} with indices SOneTo(1):
 [1.0]

```

---

<div class="post-metadata">

**Author:** ![aafsar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aafsar/32/47420_2.png) [@aafsar](https://discourse.julialang.org/u/aafsar)\
**Post date:** [April 3, 2023, 11:27am UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/3 "2023-04-03T11:27:15Z")

</div>

Thank you @longemen3000, `SA` constructor does create nested SVectors even when both have `Size` 1 (i.e. `N=1` and `Dim=1`). But I would still like to understand what prevents the constructor with explicit type parameters (I have also tried directly using `SArray` constructor, without using the `SVector` alias, and got the same error). I checked the source code of [StaticArraysCore.jl](https://github.com/JuliaArrays/StaticArraysCore.jl/blob/main/src/StaticArraysCore.jl) but couldn’t understand why:  
A) `SVector` of a `Size`-2 `Svector` (or `Size`-2 `SVector` of `Size`-1 `SVector`s) either (1) uses the first inner construct of `SArray`, or (2) passes the `convert_tuple`,  
B) while a `SVector` of a `Size`-1 `Svector` fails in the `convert_tuple`.

Moreover, `SA` constructor seems to be much slower when passed an existing `SVector` and makes an extra allocation, compared to passing directly the type parameters of the inner `SVector`. [See a similar discussion on creating SVector of SVectors](https://discourse.julialang.org/t/how-to-create-an-svector-of-svectors-part-ii/61109)

```julia
julia> my_vector_2d
2-element SVector{2, Float64} with indices SOneTo(2):
 0.8
 0.9

julia> @benchmark SA[my_vector_2d]
BenchmarkTools.Trial: 10000 samples with 590 evaluations.
 Range (min … max): 197.217 ns … 6.917 μs ┊ GC (min … max): 0.00% … 96.72%
 Time (median): 209.234 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 230.900 ns ± 153.116 ns ┊ GC (mean ± σ): 1.39% ± 2.16%

  ▅▇█▇▃ ▂▂▁ ▁▁▂ ▁
  █████▇████▇██████████▇▇▆█▇███▇▇▇▆▆▆▆▆▆▆▆▇▆▆▆▆▅▆▆▅▆▅▅▆▅▅▅▆▅▅▅▅ █
  197 ns Histogram: log(frequency) by time 486 ns <

 Memory estimate: 64 bytes, allocs estimate: 2.

julia> @benchmark SVector{1, SVector{2, Float64}}(my_vector_2d)
BenchmarkTools.Trial: 10000 samples with 942 evaluations.
 Range (min … max): 79.872 ns … 4.579 μs ┊ GC (min … max): 0.00% … 98.13%
 Time (median): 82.801 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 93.011 ns ± 85.076 ns ┊ GC (mean ± σ): 1.75% ± 1.95%

  ▇█▇▂ ▁▂▁▂▃ ▁▁ ▁ ▁
  ████▇▇▇▆█████▆▅▆▇████▇████▇▇▇██▆▆▆▅▆▆▇▇▇▆▆▅▅▅▅▆▅▆▆▅▆▅▅▄▄▄▅▅ █
  79.9 ns Histogram: log(frequency) by time 201 ns <

 Memory estimate: 32 bytes, allocs estimate: 1.

```

and here is an MWE without benchmarks:

```julia
using BenchmarkTools, StaticArrays

# Inner SVectors
my_vector_1d = SVector{1, Float64}(0.8)
my_vector_2d = SVector{2, Float64}(0.8, 0.9)

# Container SVectors
# Size-1 SVector of Size-1 SVector
# my_container_faulty = SVector{1, SVector{1, Float64}}(my_vector_1d) # gives error
my_container_a = SA[my_vector_1d]
# Size-2 SVector of Size-1 SVectors
my_container_b = SVector{2, SVector{1, Float64}}(my_vector_1d, my_other_vector_1d)
# Size-1 SVector of Size-2 Svector
my_container_c = SVector{1, SVector{2, Float64}}(my_vector_2d)
```

---

<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:** [April 3, 2023, 11:42am UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/4 "2023-04-03T11:42:55Z")

</div>

> [@aafsar](#):
>
> `SA` constructor seems to be much slower

This is a benchmarking artifact from not interpolating the variables:

```julia
julia> x = SVector{2,Float64}(1,1)
2-element SVector{2, Float64} with indices SOneTo(2):
 1.0
 1.0

julia> @benchmark SA[$x]
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 1.538 ns … 7.332 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 1.551 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 1.558 ns ± 0.098 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

     ▁▃▇█▆▄                                                  
  ▂▄▇██████▃▂▂▂▂▂▁▁▂▂▂▂▂▂▂▂▂▁▁▁▁▁▂▁▁▁▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▂▂▂▂▂▂ ▃
  1.54 ns Histogram: frequency by time 1.66 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark SVector{1,SVector{2,Float64}}($x)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 1.751 ns … 4.871 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 1.766 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 1.783 ns ± 0.128 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

      █▇▇▆                                                   
  ▂▂▃▅████▃▂▂▂▂▂▂▁▂▂▂▂▃▄▄▄▂▂▂▂▂▁▁▁▁▁▂▂▂▂▂▂▂▂▂▂▁▁▁▁▂▁▁▁▁▁▁▂▂ ▃
  1.75 ns Histogram: frequency by time 1.89 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

Concerning the original question, that is either a bug or some limitation introduced by internals of the representations. I would report it.

---

<div class="post-metadata">

**Author:** ![aafsar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aafsar/32/47420_2.png) [@aafsar](https://discourse.julialang.org/u/aafsar)\
**Post date:** [April 3, 2023, 11:45am UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/5 "2023-04-03T11:45:40Z")

</div>

Ah I see, thank you @lmiq!

---

<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:** [April 3, 2023, 12:14pm UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/6 "2023-04-03T12:14:50Z")

</div>

It seems that removing the type of a 1-element SArray in a nested constructor is a deliberate design choice (there are even tests for that). Whether do that or not is set in the `need_unwrap` function of the package, which unwraps the array if `length(array) == 1`.

For instance, this is specifically tested:

```julia
julia> x = SMatrix{1,1,Float64,1}(1.0)
1×1 SMatrix{1, 1, Float64, 1} with indices SOneTo(1)×SOneTo(1):
 1.0

julia> SMatrix(x)
1×1 SMatrix{1, 1, Float64, 1} with indices SOneTo(1)×SOneTo(1):
 1.0

```

(it does not return nested `SMatrix`ces). I don´t know the rationale behind that decision, but it seems to be deliberate.

---

<div class="post-metadata">

**Author:** ![aafsar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aafsar/32/47420_2.png) [@aafsar](https://discourse.julialang.org/u/aafsar)\
**Post date:** [April 3, 2023, 1:19pm UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/7 "2023-04-03T13:19:44Z")

</div>

Hmm, I somehow couldn’t be able to find `need_unwrap` function in both repos ([StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) and [StaticArraysCore](https://github.com/JuliaArrays/StaticArraysCore.jl)), but the thing that confuses me is that the nested constructor works (i.e. creates nested SArrays) when the inner SVectors are of length 1 if the outer SVector is of length greater than 1, or when the outer SVector is of length 1 when the inner SVectors are of length greater than 1.

I have also posted [the question in the package’s GitHub](https://github.com/JuliaArrays/StaticArrays.jl/issues/1151).

---

<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:** [April 3, 2023, 3:02pm UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/8 "2023-04-03T15:02:18Z")

</div>

Oh, sorry, is `need_rewrap`. This one: [StaticArrays.jl/convert.jl at afaead0595cdc8009fe54a16d2c165cb6f7cc513 · JuliaArrays/StaticArrays.jl · GitHub](https://github.com/JuliaArrays/StaticArrays.jl/blob/afaead0595cdc8009fe54a16d2c165cb6f7cc513/src/convert.jl#L146)

---

<div class="post-metadata">

**Author:** ![aafsar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aafsar/32/47420_2.png) [@aafsar](https://discourse.julialang.org/u/aafsar)\
**Post date:** [April 4, 2023, 5:48am UTC](https://discourse.julialang.org/t/creating-svector-of-a-single-svector-1-float64/96979/9 "2023-04-04T05:48:22Z")

</div>

Thank you again @lmiq! It seems that only the default constructor does not “rewrap” a `StaticArray` input of `length==1`. In the GitHub issue I was suggested to wrap the inner `StaticArray` input with a tuple, which works fine. Since wrapping any inner `StaticArray` either with a tuple or a vector, regardless of length, doesn’t seem to hurt, this solution works fine even with parametric sizes.

In my use case, I need to create two types of `SVector` containers of `SVector`s; one with a given `Size`, and one with one size less, `Size-1`, one element removed. When I need to create a lower sized `SVectors`, I first create a normal `Vector` either by concatenating the relevant sub-parts of the original container, or by comprehension, which then works as a `Vector` wrapper. Then I pass this to the constructor with the size given explicitly. I’m guessing this can be improved, but the following works as intended:

```julia
const VectorContainer{N, Dim} = SVector{N, SVector{Dim, Float64}}

function separate_vector(i::Integer, vector_container::VectorContainer{N, Dim}) where {N, Dim}
	vectorᵢ = vector_container[i]
	subspace_dim = Size(vector_container)[1] - 1
	container_subset = SVector{subspace_dim}(vcat(vector_container[1:(i - 1)], vector_container[(i + 1):N]))
	return vectorᵢ, container_subset
end

vector_a = SVector(0.8)
vector_b = SVector(0.9)
container_a = SVector(vector_a, vector_b)

my_vec, my_subset = separate_vector(1, container_a)
typeof(my_vec) # SVector{1, Float64}
typeof(my_subset) # SVector{1, SVector{1, Float64}}

```
