114 views (last 30 days)

Show older comments

Hi all,

Imagine I have a vector:

inpt = (1:6)';

Now I'd like to put elements of inpt in the upper triangular part of a 3 by 3 matrix otpt, so I have:

otpt =

1 2 4

0 3 5

0 0 6

What's the best way to do it? Thanks!

Jan
on 26 Jul 2017

Jan
on 26 Jul 2017

Edited: Jan
on 26 Jul 2017

Start with nested loops:

v = 1:6;

n = round((sqrt(8 * numel(v) + 1) - 1) / 2);

M = zeros(n, n);

c = 0;

for i2 = 1:n

for i1 = 1:i2

c = c + 1;

M(i1, i2) = v(c);

end

end

In the next step you can vectorize the inner loop: Move the loop index inside the assignment:

n = round((sqrt(8 * numel(v) + 1) - 1) / 2);

M = zeros(n, n);

a = 1;

for k = 1:n

b = a + k - 1;

M(1:k, k) = v(a:b);

a = b + 1;

end

Is this nicer? Questionable, but maybe faster.

Now use a built-in function:

n = round((sqrt(8 * numel(v) + 1) - 1) / 2);

M(triu(ones(n)) == 1) = v;

or better:

M(triu(true(n))) = v;

[EDITED] Some timings - what did you expect?

v = 1:5050;

tic; for k = 1:10000; y = SerialTriU(v); end, toc

Elapsed time is 0.772492 seconds. % Two loops

Elapsed time is 2.448738 seconds. % Inner loop vectorized

Elapsed time is 1.029641 seconds. % TRIU(ONES)

Elapsed time is 0.659360 seconds. % TRIU(TRUE)

Roger Stafford
on 26 Jul 2017

Let vector ‘inpt’ have size = n*(n+1)/2,1.

otpt = zeros(n);

otpt(triu(ones(n),0)==1) = inpt;

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!