StaticArray using generator

I am trying to replace

# naive version that does works but fails to scale  
i1 = 1; i2 = 2; i3 = 3; 
I = SVector(i1, i1, i1, i2, i2, i2, i3, i3, i3)

by something better. The following code

I1 = SVector(i1, i2, i3) 
I2 = SVector{9}( I1[i] for i in 1:3 for j in 1:3 )

yields

DimensionMismatch: No precise constructor for SVector{9} found. Length of input was 1.

This looks like a job for the @SArray (or @SVector) macro. Unfortunately, it doesn’t quite work:

julia> @SArray [I1[i] for i in 1:3]
3-element SVector{3, Int64} with indices SOneTo(3):
 1
 2
 3

julia> @SArray [I1[i] for i in 1:3, j in 1:3]
3×3 SMatrix{3, 3, Int64, 9} with indices SOneTo(3)×SOneTo(3):
 1  1  1
 2  2  2
 3  3  3

julia> @SArray [I1[i] for i in 1:3 for j in 1:3]
ERROR: LoadError: Expected generator in comprehension, e.g. [f(i,j) for i = 1:3, j = 1:3]

It seems like this particular syntax just isn’t supported. An alternative is to create a vector and convert to SVector:

julia> SVector{9}( [I1[i] for i in 1:3 for j in 1:3] )
9-element SVector{9, Int64} with indices SOneTo(9):
 1
 1
 1
 2
 2
 2
 3
 3
 3

but this allocates an intermediate vector. A more efficient, but less elegant, workaround is:

julia> vec(@SArray [I1[i] for j in 1:3, i in 1:3])  # notice switched indexing order
9-element SVector{9, Int64} with indices SOneTo(9):
 1
 1
 1
 2
 2
 2
 3
 3
 3

This should be close to maximally efficient, I think.

1 Like

Thx again. I am looking into it.

If you splat the generator it works:

SVector{9}((I1[i] for i in 1:3 for j in 1:3)...)
2 Likes

The master at work, he he.

Why does splatting make it work? Thx.

I think you should use sacollect() to collect a StaticArray from a generator - see doc here:

using StaticArrays: sacollect
...
sacollect(SVector{9, Int}, I1[i] for i in 1:3 for j in 1:3)
1 Like

Will give it a look. Thx!