Vector of upper triangle

question

#1

Is there an elegant way of extracting the upper triangle of a matrix as a vector using Base? Besides, of course, writing something like

function vec_triu(M::AbstractMatrix{T}) where T
    m, n = size(M)
    m == n || throw(error("not square"))
    l = n*(n+1) ÷ 2
    v = Vector{T}(l)
    k = 0
    for i in 1:n
        v[k + (1:i)] = M[1:i, i]
        k += i
    end
    v
end

so that

julia> vec_triu(reshape(1:9, 3, :))
6-element Array{Int64,1}:
 1
 4
 5
 7
 8
 9

#2

M[triu(trues(M))]

See also Half Vectorization


#3

Not that I know, but just FYI, you need to write out the loop; your function allocates (on 0.7 from this week). This does not even make your code longer or harder to read.

@inbounds for ell=1:i v[k + ell] = M[ell, i] end

#4

[A[i, j] for j in indices(A, 1) for i in 1:j]

It’s allocating a little more than expected, though.


#5

Thanks everyone for the replies. Results below, related code in gist.

function time (ns) allocation
vec_triu 232 528
vec_triu_collect 278 848
vec_triu_inbounds 201 528
vec_triu_loop 37 128