Create a horizontally stretched upper triangular matrix
I would like to create a matrix 4x12
that is very similar to the top triangular matrix, looks like this:
1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1
So my question is. What is the most efficient way to create it? no loops, no cellfun. Thank.
source to share
Matlab R2015a and later approach using newly introduced repelem
n = 4;
m = 3;
out = repelem(triu(ones(n)),1,m);
out =
1 1 1 1 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1
It even seems to be faster than the approach bsxfun
, although I can't believe it;)
Benchmark
Unfortunately, I could not review the andrew solution as it is not complete and I did not get it completely.
function [t] = bench()
n = 4;
m = 12;
t = zeros(3,15);
for ii = 1:15
fcns = {
@() thewaywewalk(ii*n,ii*m);
@() Divakar(ii*n,ii*m);
@() LuisMendo(ii*n,ii*m);
};
% timeit
for jj = 1:100;
t(:,ii) = t(:,ii) + cellfun(@timeit, fcns);
end
end
plot(1:15,t(1,:)); hold on;
plot(1:15,t(2,:)); hold on;
plot(1:15,t(3,:)); hold on;
xlabel('Matrix size: n = x*4, m = x*12')
ylabel('timing')
legend({'thewaywewalk','Divakar','Luis Mendo'},'location','northwest')
end
function Z = thewaywewalk(n,m)
Z = repelem(triu(ones(n)),1,m/n);
end
function Z = Divakar(n,m)
row_idx = repmat(1:n,m/n,1);
Z = bsxfun(@le,[1:n]',row_idx(:).');
end
function Z = LuisMendo(n,m)
Z = reshape(repmat(permute(triu(ones(n,n)), [1 3 2]), [1 m/n 1]), [n m]);
end
The first bottom line is small matrices:
The new one does a very good job, but it also won't disappoint.An approach lags slightly behind some mid-size matrices before it becomes the leader for large matrices: repelem
reshape(repmat(permute...
bsxfun
The second bottom line is large matrices:
As predicted by Divakar, bsxfun
is the fastest for large matrices, in fact as expected, since it is bsxfun
always the fastest! Interestingly, the other two fit together perfectly, they might assume they almost work the same way.
source to share