Search code examples
matlabmatrixvectorizationmatrix-indexingsubmatrix

Loopless submatrix assignment in Matlab


I have a matrix F of size D-by-N and a vector A of length N of random integers in the range [1,a]. I want to create a matrix M of size D * a such that each colum M(:,i) has the vector F(:,i) starting from the index (A(i)-1)*D+1 to (A(i)-1)*D+D.

Example:

F = [1 2 3 10
     4 5 6 22]

A = [3 2 1 2]

a = 4

M = [0 0 3 0
     0 0 6 0
     0 2 0 10
     0 5 0 22
     1 0 0 0
     4 0 0 0
     0 0 0 0
     0 0 0 0]

I can do it with a simple loop

        for i = 1 : N
            M((A(i)-1)*D+1:(A(i)-1)*D+D,i) = F(:,i);
        end

but for large N this might take a while. I am looking for a way to do it without loop.


Solution

  • You can use bsxfun for a linear-indexing based approach -

    [D,N] = size(F);    %// Get size of F
    
    start_idx = (A-1)*D+1 + [0:N-1]*D*a;          %// column start linear indices
    all_idx = bsxfun(@plus,start_idx,[0:D-1]');   %//'# all linear indices
    
    out = zeros(D*a,N); %// Initialize output array with zeros
    out(all_idx) = F;   %// Insert values from F into output array
    

    Sample run -

    F =
         1     2     3    10
         4     5     6    22
    A =
         3     2     1     2
    a =
         4
    out =
         0     0     3     0
         0     0     6     0
         0     2     0    10
         0     5     0    22
         1     0     0     0
         4     0     0     0
         0     0     0     0
         0     0     0     0