Type instability with StaticArrays

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)

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.

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).

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?

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}

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))

Thank you for your fast help!