MATLAB: Unexpected singleton dimension removal

automatic reshapingsingleton dimension

When I create a three dimensional array and assign it to an undefined array, the assignment does not behave as I expect if the first two dimensions are singletons:
>> it = rand(1,1,3)
it(:,:,1) =
0.9157
it(:,:,2) =
0.7922
it(:,:,3) =
0.9595
>> vom(1,:,:) = it
vom =
0.9157 0.7922 0.9595
>> vom(:,1,:) = it
vom =
0.2769
0.0462
0.0971
I know there are a million ways around this, but this behavior seems unnatural to me. Is this singleton dimension removal documented anywhere?

Best Answer

Is this singleton dimension removal documented anywhere?
I think the best documentation you'll find will be this excerpt from the SUBSASGN documentation, note the portion in bold
"For multidimensional arrays, a(I,J,K,...) = b assigns b to the specified elements of a. b must be length(I)-by-length(J)-by-length(K)-... or be shiftable to that size by adding or removing singleton dimensions. "
So, in other words, it is applying shiftdim() to the right hand side "b", until it reaches a shape that will work. The question is, when vom is undefined, how does it choose the direction to shift? What accounts for differences in the 3 tests below? I believe the answer is, it will start with a right-shift of 1 and continue to right shift until it finds a shape that will work.
>> clear vom; vom(1,:,:) = it
vom =
0.9134 0.6324 0.0975
>> clear vom; vom(1,:,:) = it(:)
vom =
0.9134 0.6324 0.0975
>> clear vom; vom(1,:,:) = it(:)'
vom(:,:,1) =
0.9134
vom(:,:,2) =
0.6324
vom(:,:,3) =
0.0975
So, in the first test above, "it" is right shiftdimmed by 1 making it into a column vector, but a column vector is not a shape compatible with the indexing vom(1,:,:). The target shape has to be either a row vector or 1x1x3. So, "it" is right shifted again, making it a row vector, which works.
Similarly, in the second test, the right hand side starts as a column vector, gets right shifted by 1, making it a row vector which is a legal target shape, and so that's the shape that gets chosen
Finally, the 3rd test is the most interesting. The given right hand side it(:)' starts as a row vector, and the sensible thing would be to stop there, since this is a legal target shape. However, as I mentioned, the rule is that the code will always attempt at least one right shift and so it converts the right hand side to 1x1x3. But this is also a legal target shape and so that's the shape that gets selected.