How to create SMatrix from SVectors efficiently

Hi,
I have a function f(i) = SA[i,2i] that generates SVectors. I want to concatenate a small, but variable amount of them into a SMatrix. For a fixed amount I can do:

julia> [f(1) f(2) f(3)]'
3×2 SMatrix{3, 2, Int64, 6} with indices SOneTo(3)×SOneTo(2):
 1  2
 2  4
 3  6

which is fast:

julia> @benchmark [f(1) f(2) f(3)]'
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max):  0.023 ns … 0.082 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     0.027 ns             ┊ GC (median):    0.00%
 Time  (mean ± σ):   0.027 ns ± 0.003 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%
 Memory estimate: 0 bytes, allocs estimate: 0.

Is there a fast way to do this with a variable amount of calls to f, like [f(1) f(2) ... f(N)]?
I know I can do

julia> hcat( [f(i) for i in 1:3]...)'
3×2 SMatrix{3, 2, Int64, 6} with indices SOneTo(3)×SOneTo(2):
 1  2
 2  4
 3  6

but this approach is very slow:

julia> @benchmark hcat( [f(i) for i in 1:3]...)'
BenchmarkTools.Trial: 10000 samples with 705 evaluations.
 Range (min … max):  166.813 ns …   5.976 μs  ┊ GC (min … max):  0.00% … 95.94%
 Time  (median):     176.813 ns               ┊ GC (median):     0.00%
 Time  (mean ± σ):   206.796 ns ± 361.318 ns  ┊ GC (mean ± σ):  12.38% ±  6.82%
 Memory estimate: 336 bytes, allocs estimate: 6.

Thank you,
Nico

You could do

hcat( (f(i) for i in 1:4)...)
# or
hcat(ntuple(i->f(i), 4 )...)

They both appear to get constant folded. Remember that this only works well if the length (e.g. 4) is a compile-time constant. If it can change at runtime, you should probably not be using StaticMatrix for this.

2 Likes