Type instability with StaticArrays

question

#1

Hi all,
I was unable to create a type stable static matrix from an Array{T,2}
How make it type stable?
Tanks!

using StaticArrays
function Tmaker(kdim::IT) where IT<:Integer
    T=reshape([isodd(x÷(2^y)) for y in 0:(kdim-1) for x in 0:(2^kdim-1)],:,kdim)
    TT=SMatrix{size(T)...}(T)
end
@code_warntype Tmaker(3)

#2

Yes, you are unable to do that. Array{T,2} has insufficient type information to be able to specify a fully typed static array at compile time.


#3

This is inherently type unstable in that the type of the output depends on the value of the input.

You can give the input as a type and do something like

 function Tmaker(::Val{kdim}) where {kdim}
    T=reshape([isodd(x÷(2^y)) for y in 0:(kdim-1) for x in 0:(2^kdim-1)],:,kdim)
    TT=SMatrix{2^kdim, kdim}(T)
end
julia> @code_warntype Tmaker(Val(2))
Body::SArray{Tuple{4,2},Bool,2,8}

or you just work around the type instability using a function barrier (see performance tips in the julia manual).


#4

That’s interesting, I tried exactly the same value type trick, but tested with kdim=3 and saw that it wasn’t type-stable, because SMatrix{2^kdim, kdim} has a calculation:

@code_warntype Tmaker(Val(3))

Somehow 2^2 is caught as a special case that can be inferred?


#5

Ah, the ^2 is special cased. Can hack around it with:

julia> Base.@pure mypow(x, y) = x^y
mypow (generic function with 1 method)

julia> function Tmaker(::Val{kdim}) where {kdim}
           T=reshape([isodd(x÷(2^y)) for y in 0:(kdim-1) for x in 0:(2^kdim-1)],:,kdim)
           TT=SMatrix{mypow(kdim, 2), kdim}(T)
       end
Tmaker (generic function with 2 methods)

julia> @code_warntype Tmaker(Val(3))
Body::SArray{Tuple{9,3},Bool,2,27}

#6

Nice. I’m terrified of @pure but was cobbling this together:

@generated twopow(::Val{n}) where n = 2^n

function Tmaker(valk::Val{kdim}) where {kdim}
    M=reshape([isodd(x÷(2^y)) for y in 0:(kdim-1) for x in 0:(2^kdim-1)],:,kdim)
    SMatrix{twopow(valk), kdim}(M)
end

@code_warntype Tmaker(Val(3))

#7

Thank you for your fast help!