Specifying StaticArray Types

If a struct’s field is a StaticArray, then how do I (generically) specify its type? As seen below, not specifying the type has an effect on performance, but my attempt is obviously no good either, as it’s far to specific.

using BenchmarkTools, StaticArrays

mutable struct TypedModel
    A::SArray{Tuple{6,6},Float64,2,36}
    Atranspose::SArray{Tuple{6,6},Float64,2,36}
    u::SArray{Tuple{6},Float64,1,6}
    R::SArray{Tuple{6,6},Float64,2,36}
end

mutable struct Model
    A
    Atranspose
    u
    R
end

function multiplythings!(μ, Σ, A, Atranspose, u, R, n)
    for i = 1:n
        μ[i] = A * μ[i] + u
        Σ[i] = A * Σ[i] * Atranspose + R
    end
end

function multiplythings!(μ, Σ, model, n)
    for i = 1:n
        μ[i] = model.A * μ[i] + model.u
        Σ[i] = model.A * Σ[i] * model.Atranspose + model.R
    end
end

# Model
xdim = 6
n = 1000
A = @SMatrix rand(xdim, xdim)
Atranspose = A'
u = @SVector rand(xdim)
R = @SMatrix rand(xdim, xdim)
# State estimate parameters
μ = [@SVector rand(xdim) for _ = 1:n]
Σ = [@SMatrix rand(xdim, xdim) for _ = 1:n]
# Create models
model = Model(A, Atranspose, u, R)
typedmodel = TypedModel(A, Atranspose, u, R)
@btime multiplythings!($μ, $Σ, $A, $Atranspose, $u, $R, $n)
@btime multiplythings!($μ, $Σ, $typedmodel, $n)
@btime multiplythings!($μ, $Σ, $model, $n)

A StaticVector is characterized by its length (VecN) and the element type (VecT). A StaticMatrix is characterized by its size (nrows MatR, ncolumns MatC) and the element type (MatT). These characterizing features can be given as parameters. That is likely the most general way to get most specific.

struct S{VecN, VecT, MatR, MatC, MatT}
  staticvec::SArray{Tuple{VecN}, VecT}
  staticmat::SArray{Tuple{MatR,MatC}, MatT}
end

function S(vec::Vector{VecT}, mat::Matrix{MatT}) where {VecT, MatT}
  VecN = length(vec)
  MatR, MatC = size(mat)
  return S{VecN, VecT, MatR, MatC, MatT}(vec, mat)
end
julia> test = S([1, 2, 3], [1 2; 3 4])
S{3,Int64,2,2,Int64}([1, 2, 3], [1 2; 3 4])

julia> test.staticvec
3-element SArray{Tuple{3},Int64,1,3} with indices SOneTo(3):
 1
 2
 3

julia> test.staticmat
2×2 SArray{Tuple{2,2},Int64,2,4} with indices SOneTo(2)×SOneTo(2):
 1  2
 3  4

To pass your vector as a tuple, define another constructor. To pass your matrix as a tuple with a two-tuple size (nrows, ncolumns) define another constructor.

I tried this and it works, but my performance suffers. I tried:

mutable struct TypedModel{X, T}
    A::SArray{Tuple{X, X}, T}
    Atranspose::SArray{Tuple{X, X}, T}
    u::SArray{Tuple{X}, T}
    R::SArray{Tuple{X, X}, T}
end

typedmodel = TypedModel{xdim, Float64}(A, Atranspose, u, R)
@btime multiplythings!($μ, $Σ, $typedmodel, $n)
287.900 μs (7978 allocations: 1.48 MiB)

What is going wrong here?

I don’t know what you are doing (see points 3 & 4 here).
Show me that the performance suffers using my minimal example (perhaps with a larger vector and a larger matrix). Include the vector and matrix explicitly, so we have something specific to compare.

OK, I tracked it down. To get the performance you need to provide all the parameters. My oversight. N is the vector length, N2 is N*N, the matrix length, T is the shared element type.

mutable struct TypedModel3{N, N2, T}
   A::SArray{Tuple{N, N}, T, 2, N2}
   Atranspose::SArray{Tuple{N, N}, T, 2, N2}
   u::SArray{Tuple{N}, T, 1, N}
   R::SArray{Tuple{N, N}, T, 2, N2}
end

x2dim = xdim * xdim
typedmodel3 = TypedModel3{xdim, x2dim, Float64}(A, Atranspose, u, R)

julia> @btime multiplythings!($μ, $Σ, $typedmodel3, $n)
  46.600 μs (0 allocations: 0 bytes)

As far as I understand it is not enough to specify the length of the two dimensions of an SMatrix, you also have to give the number of elements. Even though it’s in principle trivial to calculate the latter from the former, the compiler isn’t able to.

Edit: oops, to late.