When assignment is allowed?

The question concerns the requirement of the sizes of the assignment between two arrays.
To my great surprise this is allowed
lhs = zeros(3,4,5);
rhs = ones(4,5);
lhs(1,:,:) = rhs;
I would thought the last statement would throw an error
"Unable to perform assignment because the size of the left side is 1-by-4-by-5 and the size of the right side is 4-by-5."
but obviously it's not.
Can someone points me to the official document that explains such assigment is allowed and how?

2 Comments

The documentation on how assignment works is nonexistent as far as I can tell.
Will be interested to see if there is a doc-based answer, or if this is a case of "Matlab knows what you want"
Also works for other dimensions, so the leading unity dimension is not some sort of special case
lhs = zeros(3,4,5);
rhs = ones(3,5);
try
lhs(:,2,:) = rhs;
disp('success');
catch
disp('error');
end
success
This would have taken me by surprise as well. I did not find this behavior in the documentation, but I did find it in this blog post from @Loren Shure. It is in the section "Retaining Array Shape During Assignment".

Sign in to comment.

 Accepted Answer

Matt J
Matt J on 6 Aug 2023
Edited: Matt J on 6 Aug 2023
The relevant documentation is at,
Singleton dimensions are ignored when determining if the right and left hand sides have matching dimensions.
x=1:8
x = 1×8
1 2 3 4 5 6 7 8
x(1:3)=[10;20;30] %assign 3x1 into a 1x3 data region
x = 1×8
10 20 30 4 5 6 7 8

8 Comments

Hi Matt J,
If that doc section answers Bruno's question, it's too bad that such a basic rule on assignment, which is used all day and every day in Matlab, is buried deep in some function related to programming with classes.
Also, I don't see how your example is related. The right hand side of the expression doesn't use indexing, but indexing seems to be the entire point of the linked doc section. I thought your example was more of an historical vagary from first implementation of Matlab.
Interestingly enough, the examples portion of that doc page doesn't include any examples with an indexed variable on the right hand side.
Matt J
Matt J on 6 Aug 2023
Edited: Matt J on 6 Aug 2023
Hi Paul,
The indexing used to generate the right hand side is superfluous, though I agree that may add confusion to the documentation. The indexing of B shown on the right hand side in the documentation is just a way of telling the reader what the dimensions of the assigned data block will be. Bruno's example also doesn't have any indexing on the right hand side.
"Bruno's example ...."
Which was one reason why I wasn't sure that that doc section was on point. But Bruno accepted the Answer so I guess he thinks it is.
As far as assigning 3x1 into a 1x3, I'm still thinking that's some sort of historical special case. In the following code, the 12-element rhs could be strung out into a column vector and assigned into the 12 elements of the lhs in column order, which looks like what happens in the 1-dimensional case. But it doesn't work in two dimensions. I'm not suggesting that it should, but it does look like an inconsistency.
rhs = zeros(3,4);
lhs = ones(4,3);
try
lhs(:,:) = rhs(:,:); % try to assign 12 elements into 12 elements
disp('success');
catch
disp('error');
end
error
I also don't understand how the subsassgn works in this case, because that page doesn't explain how it handles nonscalar subscripts that are paired up with scalar subscripts.
x = rand(1,3);
y = rand(3,1);
x(1,1:3) = y(1:3,1)
x = 1×3
0.3716 0.1901 0.8945
I'm really quite disappointed (and have been for a while) that the doc doesn't have a page dedicated to how assignment works, which needs to cover more than just indexing, e.g., assignment involving different data types.
I also don't understand how the subsassgn works in this case, because that page doesn't explain how it handles nonscalar subscripts
Doesn't it? From the doc: "The order and length of all nonscalar subscripts specified for A matches the order and length of nonscalar subscripts specified for B".
the 12-element rhs could be strung out into a column vector and assigned into the 12 elements of the lhs in column order, which looks like what happens in the 1-dimensional case
No, subsasgn is not stringing anything out. It's just ignoring singleton dimensions.
lhs=nan(4,3);
rhs=rand(1,1,1,1,1,1,1,4,1,3);
lhs(:,:)=rhs
lhs = 4×3
0.2026 0.8664 0.9167 0.0755 0.9524 0.6298 0.7000 0.3866 0.4551 0.9229 0.1938 0.4146
Bruno Luong
Bruno Luong on 7 Aug 2023
Edited: Bruno Luong on 7 Aug 2023
@Paul "I also don't understand how the subsassgn works in this case, because that page doesn't explain how it handles nonscalar subscripts that are paired up with scalar subscripts."
It doesn't have to, because this page is about subsasgn and it must explain the size relationship, and it does.
The subscripts part specification is more on the subsref doc page I think (see More About -> Understanding Indexing Expression).
"But Bruno accepted the Answer so I guess he thinks it is."
Yes I did because in this subasgn doc page correctly describe how to match the sizes lhs and rhs on the section Algorithms, and it also says this is this specification applied to MATLAB default behavior:
MATLAB uses the built-in subsasgn function to interpret indexed assignment statements.
But I'm with you 100% that such specification should not be burried in subasgn which is oriented toward class overload the "=" behavior.
Bruno Luong
Bruno Luong on 7 Aug 2023
Edited: Bruno Luong on 7 Aug 2023
Thanks Matt.
Now I know the specification, I wonder what is the usecase for such singleton contracting in assigment. It looks to me mainly for assigning lhs and rhs that has relative permutation of dimensions to each other, and somehow the order of the index and the user singleton indexes allow to do such shortcut syntax.
Personally I think I would never use such feature, even now I know how it works.
It really does help for 3D images. The mri.mat example dataset is [row,col,color,page] (even though it is grayscale), but most other places will use [row,col,page,color]. This sytax allow subindexing and swapping conventions with relative easy, without having to use permute or squeeze every second line
Bruno Luong
Bruno Luong on 7 Aug 2023
Edited: Bruno Luong on 7 Aug 2023
@Rik understood why you have 2 different orders of dimensions. In one case you want to process by color, in other you want to process by chromatic images.

Sign in to comment.

More Answers (0)

Products

Asked:

on 6 Aug 2023

Edited:

on 7 Aug 2023

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!