# Struggling with type stability - is SMatrix type stable?

**URL:** https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951
**Category:** Performance
**Tags:** type-stability, staticarrays
**Created:** [August 6, 2018, 5:35pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951 "2018-08-06T17:35:49Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)
#### Post date: [August 6, 2018, 5:35pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/1 "2018-08-06T17:35:49Z")

</div>

I have a problem where I want to collect an Array of vectors as I perform an iteration. Something like this:

```
function foo(x::Vector{Float64}, size::Int8)
  tmat = SMatrix{4,4}{Float64}(eye(4))
  tmatrices = Array{SMatrix{4,4}{Float64}}(size)
  for j=1:size
	tmatrices[j] = bar(x[j])
	tmat *= tmatrices[j]
  end
  return tmat, tmatrices;
end

function bar(x)
    return eye(4)
end

```

where SMatrix is a Static Arrays type. When I run this using @code\_warntype, Julia complains that tmat is of an abstract type:

```
tmat::Any = SSAValue(4) # line 5:
  tmatrices::Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1} = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1}, svec(Any, Int64), Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1}, 0, 5, 0)) # line 6:
  SSAValue(6) = (Base.select_value)((Base.sle_int)(1, size::Int64)::Bool, size::Int64, (Base.sub_int)(1, 1)::Int64)::Int64
  #temp#@_5::Int64 = 1
  35: 
  unless (Base.not_int)((#temp#@_5::Int64 === (Base.add_int)(SSAValue(6), 1)::Int64)::Bool)::Bool goto 48
  SSAValue(7) = #temp#@_5::Int64
  SSAValue(8) = (Base.add_int)(#temp#@_5::Int64, 1)::Int64
  j::Int64 = SSAValue(7)
  #temp#@_5::Int64 = SSAValue(8) # line 7:
  SSAValue(2) = $(Expr(:invoke, MethodInstance for eye(::Type{Float64}, ::Int64, ::Int64), :(Base.eye), Float64, 4, 4))
  $(Expr(:invoke, MethodInstance for setindex!(::Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1}, ::Array{Float64,2}, ::Int64), :(Main.setindex!), :(tmatrices), SSAValue(2), :(j))) # line 8:
  tmat::Any = (tmat::Any * (Base.arrayref)(tmatrices::Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1}, j::Int64)::StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L)::Any
  46: 
  goto 35
  48: # line 10:
  return (Core.tuple)(tmat::Any, tmatrices::Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1})::Tuple{Any,Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1}}
end::Tuple{Any,Array{StaticArrays.SArray{Tuple{4,4},Float64,2,L} where L,1}}

```

Why?

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [August 6, 2018, 6:05pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/2 "2018-08-06T18:05:30Z")

</div>

`tmat` starts out as an `SArray`, but multiplying by an `Array` changes its type to the latter, hence the warning.

Not sure what your code does, but consider `I` instead of `eye`.

---

<div class="post-metadata">

### Author: ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)
#### Post date: [August 6, 2018, 6:06pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/3 "2018-08-06T18:06:48Z")

</div>

I’ve modified the code thus:

```
using StaticArrays

function foo(x::Vector{Float64}, size)
  tmat::SMatrix{4,4}{Float64} = SMatrix{4,4}{Float64}(@SMatrix eye(4))
  tmatrices = Array{SMatrix{4,4}{Float64}}(size)
  for j=1:size
 	tmatrices[j] = bar(x[j])
tmat *= tmatrices[j]
  end
  return tmat, tmatrices;
end

function bar(x)
    return @SMatrix eye(4)
end

```

but there is no change.

---

<div class="post-metadata">

### Author: ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)
#### Post date: [August 6, 2018, 6:11pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/4 "2018-08-06T18:11:14Z")

</div>

Changing it to:

```
function bar(x)
    return I
end

```

…also makes no difference:

```
tmat::Any = SSAValue(7) # line 5:

```

---

<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: [August 6, 2018, 6:14pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/5 "2018-08-06T18:14:29Z")

</div>

Yes, `SMatrix{4,4,Float64}` is an abstract type (alias).

```julia
julia> x = @SMatrix randn(4,4)
4×4 SArray{Tuple{4,4},Float64,2,16}:
 -1.55576 0.571037 0.927532 1.27703 
  0.162367 -1.78089 -0.832958 0.760511
  0.417475 -0.622358 -1.68881 -1.12098 
 -0.973613 0.941918 0.337696 1.63527 

julia> typeof(x)
SArray{Tuple{4,4},Float64,2,16}

```

For your array, use `SArray{Tuple{4,4},Float64,2,16}`, `SMatrix{4,4,Float64,16}`, or `typeof(tmat)`.  
That is use, `Array{SArray{Tuple{4,4},Float64,2,16}}(undef, size)` or `Array{typeof(tmat)}(undef, size)`.

EDIT:  
Your array as written would accept any of the following subtypes of `SMatrix{4,4,Float64}`:

```julia
julia> SMatrix{4,4,Float64,10} <: SMatrix{4,4,Float64}
true

julia> SMatrix{4,4,Float64,100} <: SMatrix{4,4,Float64}
true

julia> SMatrix{4,4,Float64,16} <: SMatrix{4,4,Float64}
true

```

However, all but the last are impossible, so you’d only want the last anyway.

---

<div class="post-metadata">

### Author: ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)
#### Post date: [August 6, 2018, 6:25pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/6 "2018-08-06T18:25:21Z")

</div>

OK, attempting to convert to I from eye(). There are places in my code where I really need to store an “initial” matrix that is the identity matrix. Like so:

```
struct M
    transform::Array{Float64}
end

function foo()
    return M(I)
end

```

which gives the error:

```
ERROR: MethodError: Cannot `convert` an object of type UniformScaling{Int64} to an object of type Array{Float64,N} where N

```

I seems to work fine “inline” when doing matrix algebra but it can’t be stored in a place where you want an array.

---

<div class="post-metadata">

### Author: ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)
#### Post date: [August 6, 2018, 6:30pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/7 "2018-08-06T18:30:25Z")

</div>

> Your array as written would accept any of the following subtypes of `SMatrix{4,4,Float64}` :

```julia
julia> SMatrix{4,4,Float64,10} <: SMatrix{4,4,Float64}
true

julia> SMatrix{4,4,Float64,100} <: SMatrix{4,4,Float64}
true

julia> SMatrix{4,4,Float64,16} <: SMatrix{4,4,Float64}
true

```

…huh. Why aren’t the “{4,4}” and the “16” parts of that declaration redundant?

---

<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: [August 6, 2018, 6:51pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/8 "2018-08-06T18:51:35Z")

</div>

Yeah, that is unfortunate, because we can derive the “16” deterministic ally from the “4”.  
We do need a 16, because the static arrays wrap NTuples.

I think there is an issue meant to allow that feature by allowing some calculations in struct declarations, so we could have something like:

```julia
struct SArray{S,T,N} <: AbstractArray{T,N}
    data::NTuple{prod(S),T}
end

```

but I couldn’t find it. Still, I think this will get resolved someday! Anyone have a link to that issue?

As an alternative, maybe because `SMatrices` are so heavily used, we could define something like:

```julia
struct SMatrix{M,N,T} <: AbstractMatrix{T}
    data::NTuple{N,NTuple{M,T}}
end

```

to be slightly more convenient on the user’s side of things.

EDIT:  
To get an array from `I`,

```julia
using LinearAlgebra
Matrix{Float64}(I,m,n)

```

---

<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: [August 6, 2018, 7:11pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/9 "2018-08-06T19:11:27Z")

</div>

Not sure what you’re trying to do, but I have some remarks.

This line is messy:

```julia
tmat::SMatrix{4,4}{Float64} = SMatrix{4,4}{Float64}(@SMatrix eye(4))

```

Remove the type assertion, it only causes problems. Also, you are putting an `SMatrix` in an `SMatrix` constructor, which is redundant, and may cause more trouble.

Finally, the `size` input argument in your function is not a good idea, `size` is the name of a _very_ important function, and also I suspect that it is unneeded. This code is type-stable, I think:

```julia
function foo(x::AbstractVector)
    tmat = @SMatrix eye(4)
    tmatrices = Vector{typeof(tmat)}(length(x))
    for j in eachindex(x)
        tmatrices[j] = bar(x[j])
        tmat *= tmatrices[j]
    end
    return tmat, tmatrices
end

function bar(x)
    return @SMatrix eye(4)
end

```

In general, try to remove type annotations, and see if that helps – some times they just get in your way.

---

<div class="post-metadata">

### Author: ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)
#### Post date: [August 6, 2018, 7:33pm UTC](https://discourse.julialang.org/t/struggling-with-type-stability-is-smatrix-type-stable/12951/10 "2018-08-06T19:33:55Z")

</div>

OK, in my real code I have created a type alias:

```
    const TransformationMatrix = SMatrix{4,4,Float64,16}

```

and I have replaced all instances of eye(4) with either I or

```
one(TransformationMatrix)

```

and with a bit of other fiddling I do not have any @code\_warntype issues, and my code is now 2x faster. Thanks!

> This line is messy:

Yeah, I have some cleanup to do now.
