Search code examples
arraysmatlabmatrixmultidimensional-arraymatrix-indexing

Matlab concatenation possible bug


I would like to concatenate two 3d arrays in a way that supports concatenation when the left hand side is empty. I'd expect the following code to work, but Matlab (2012b, and 2013a) seems to insert an extra zero matrix at the beginning.

a=[]
a =
 []
K>> a(:,:,(end+1):(end+2))=ones(2,2,2)
a(:,:,1) =
     0     0
     0     0
a(:,:,2) =
     1     1
     1     1
a(:,:,3) =
     1     1
     1     1

Is this a bug? What's the proper way of achieving this?


Solution

  • The problem is with the way you initialize a. Consider the following:

    >> a = [];    % equivalent to zeros(0,0)
    >> [m,n,p] = size(a)
    m =
         0
    n =
         0
    p =
         1
    

    This is explained in the documentation of the size function:

    [d1,d2,d3,...,dn] = size(X), for n > 1, returns the sizes of the dimensions of the array X in the variables d1,d2,d3,...,dn, provided the number of output arguments n equals ndims(X). If n does not equal ndims(X), the following exceptions hold:

    • n > ndims(X): size returns ones in the "extra" variables, that is, those corresponding to ndims(X)+1 through n.

    The size is used by end to compute the index returned. To see this in action, we could overload the end function with our custom version:

    @double\end.m

    function ind = end(a, k, n)
        ind = builtin('end',a,k,n);
        keyboard
    end
    

    with the above function saved somewhere on the path, call:

    >> a = [];
    >> a(:,:,end+1) = ones(2);
    

    You will see that the computed index ind returned by end is 1, which is then incremented by one end+1 resulting in a(:,:,2)=ones(2) hence the extra space at the beginning is filled with zeros.

    To fix this, initialize the matrix correctly:

    >> a = zeros(0,0,0);
    >> a(:,:,end+1) = ones(2);