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.

+3


source to share


4 answers


One approach vectorized

-



nrows = 4;
ncols = 12;

row_idx = repmat(1:nrows,ncols/nrows,1)
out = bsxfun(@le,[1:nrows]',row_idx(:).')

      

+2


source


Create an upper triangular matrix from these, move the second and third dimensions, repeat on the second dimension and reshape to the desired shape:



m = 4;
n = 12;
result = reshape(repmat(permute(triu(ones(m,m)), [1 3 2]), [1 n/m 1]), [m n]);

      

+2


source


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

      

enter image description here

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.

enter image description here

+2


source


depending on your matlab version

m = 4;
n = 12;

dec2bin(bitshift(num,-1*[0:n/m:n-1])) %this prints out a string

      

it should be boolean arrays (I don't have any of them, so I can't test it)

decimalToBinaryVector(bitshift(num,-1*[0:n/m:n-1]))

de2bi(bitshift(num,-1*[0:n/m:n-1]))

      

0


source







All Articles