1

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?

Amro
  • 123,847
  • 25
  • 243
  • 454
Leo
  • 1,213
  • 2
  • 13
  • 26

1 Answers1

1

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);
Amro
  • 123,847
  • 25
  • 243
  • 454
  • ok so maybe the builtin `end` function doesn't actually call `size` itself, but I think somewhere in its internal implementation it depends on the convention that an array size is considered 1's beyond its number of dimensions. This fact is ultimately used to compute the index to be returned (by multiplying the sizes along the dimensions which, when `end` is used beyond the array bounds to automatically grow it, will be `1*1*..*1 = 1`); see the sample implementation shown in that last link I gave. Of course since the function is builtin, we can't know how it's actually implemented.. – Amro Jan 11 '14 at 03:45