I stumbled across an unexpected behavior of the addition operator.
a=[1 2 3];
b=[5; 7; 11];
a+b
Produces
ans =
6 7 8 % a(1)+b(1) a(1)+b(2) a(1)+b(3)
8 9 10 % a(2)+b(1) a(2)+b(2) a(2)+b(3)
12 13 14 % a(3)+b(1) a(3)+b(2) a(3)+b(3)
This behavior probably falls under the Add a Vector to a Matrix example in the documentation.
Create an array, A, and add a column vector to it. The vector is
treated as though it is a matrix of the same size as A, so that each
element in the vector is added to a row in A.
Although, b in my example cannot be treated as the same size as a. Both vectors must be duplicated.
What can I call this behavior when I am describing it to others? None of the definitions of Matrix Addition fit. Vector addition also has a different definition. The best I could come up with was the "sum of the elements in the cartesian product".
That's called binary singleton expansion. Starting with R2016b, MATLAB does it automatically with standard operators. See bsxfun for more details.
Related
In something which made me spent several hours, I have found an inconsistency in how Matlab deals with dimensions. I somebody can explain to me OR indicate me how to report this to Matlab, please enlight me.
For size, ones,zeros,mean, std, and most every other old and common commands existing inside Matlab, the dimension arrangement is like the classical one and like the intended standard (as per the size of every dimension), the first dimension is along the column vector, the second dimension is along the row vector, and the following are the non graphical following indexes.
>x(:,:,1)=[1 2 3 4;5 6 7 8];
>x(:,:,2)=[9 10 11 12;13 14 15 16];
>m=mean(x,1)
m(:,:,1) = 3 4 5 6
m(:,:,2) = 11 12 13 14
m=mean(x,2)
m(:,:,1) =
2.5000
6.5000
m(:,:,2) =
10.5000
14.5000
m=mean(x,3)
m = 5 6 7 8
9 10 11 12
d=size(m)
d = 2 4 2
However, for graphical commands like stream3,streamline and others relying on the meshgrid output format, the dimensions 1 and 2 are swapped!: the first dimension is the row vector and the second dimension is the column vector, and the following (third) is the non graphical index.
> [x,y]=meshgrid(1:2,1:3)
x = 1 2
1 2
1 2
y = 1 1
2 2
3 3
Then, for stream3 to operate with classically arranged matrices, we should use permute(XXX,[2 1 3]) at every 3D argument:
xyz=stream3(permute(x,[2 1 3]),permute(y,[2 1 3]),permute(z,[2 1 3])...
,permute(u,[2 1 3]),permute(v,[2 1 3]),permute(w,[2 1 3])...
,xs,ys,zs);
If anybody can explain why this happens, and can indicate to me why this is not a bug, welcome.
This behavior is not a bug because it is clearly documented as the intended behavior: https://www.mathworks.com/help/matlab/ref/meshgrid.html. Specifically:
[X,Y,Z]= meshgrid(x,y,z) returns 3-D grid coordinates defined by the vectors x, y, and z. The grid represented by X, Y, and Z has size length(y)-by-length(x)-by-length(z).
Without speaking to the original authors, the exact motivation may be a bit obscure, but I suspect it has to do with the fact that the y-axis is generally associated with the rows of an image, while x is the columns.
Columns are either "j" or "x" in the documentation, rows are either "i" or "y".
Some functions deal with spatial coordinates. The documentation will refer to "x, y, z". These functions will thus take column values before row values as input arguments.
Some functions deal with array indices. The documentation will refer to "i, j" (or sometimes "i1, i2, i3, ..., in", or using specific names instead of "i" before the dimension number). These functions will thus take row values before column values as input arguments.
Yes, this can be confusing. But if you pay attention to the names of the variables in the documentation, you will quickly figure out the right order.
With meshgrid in particular, if the "x, y, ..." order of arguments is confusing, use ndgrid instead, which takes arguments in array indexing order.
I would like to have a better comprehension of Matlab mutidimensionnal arrays and the : operator with a quick question
So I ran this example
A = zeros(2,3,4,5);
size(A)
% ans = 2 3 4 5
%% 1.
size(A(:,:,1,1))
% ans = 2 3
%% 2.
size(A(1,1,:,:))
% ans = 1 1 4 5
%% 3.
size(reshape(A(1,1,:,:), 4, 5))
% ans = 4 5
1. is the behavior I actually expected for all operations.
I don't understand why do I kept unwanted dimension in 2.
Do I need to reshape like in 3. everytime I need a subarray ?
Matlab removes singleton trailing dimensions only, so what you see is normal.
In 1, you removed a 2D subset from a 4D array, but the first two dimensions were "row" and "column".
In 2, the "row" and "column" are both singleton, and the rest of the array is in the third and fourth dimensions, so Matlab keeps it that way.
Instead of reshapeing, you can squeeze(A(1,1,:,:)) to remove dimensions that have length one (except for dimensions 1 and 2, which are sort of hard-coded into Matlab).
You can use reshape or simply squeeze in this case.
MATLAB always removes trailing singleton dimensions (past the first two):
>> size(zeros(4,4,4,1,1))
ans =
4 4 4
But it also adds them when needed (or as Ander points out in the comment, they are always implicitly there):
>> a = zeros(4,4);
>> a(2,2,1,1); % is OK
>> size(a,100)
ans =
1
On the other hand, other singleton dimensions are kept. squeeze removes them.
For your particular application it makes sense to remove singleton dimensions, but other applications would have problems if this were the default behavior. Imagine code that extracts a certain sub-volume, and changing the direction of the data depending on how many rows or columns are selected. For example:
>> a(1:x,1:y,1:z)
would return an array of size (x,y,z) as long as x and y are larger than one. Make x=1, and now it's an array of size (y,z)? Bad idea!
I want to reduce a two dimensional matrix to row vector.
But using reshape with large matrices is really slow. The other alternative is to use colon, but i want matrix's transpose to be colon and not the matrix itself.
e.g.
A=magic(3)
A =
8 1 6
3 5 7
4 9 2
A(:) will stack up all the columns one by one. but i am looking for something like this:
AA=A(2:3,:)';
and then reshape or colon AA instead of A.
The issue is i dont want to define additional variable like AA.
Is there anyway to reduce dimension of two dimensional matrix without reshape?
You can avoid the additional variable by linear indexing. For your example:
A([2 5 8 3 6 9])
which gives
3 5 7 4 9 2
What's happening here is that you treat A as if it was already transformed into a vector, and the elements of this one-dimensional array are accessed through indices 1 through 9. Using the colon is a special case of linear indexing, A(:) is the same as A(1 : end).
Figuring out the right linear indices can be tricky, but sub2ind can help with that.
It is possible that this slightly speeds up the code, mainly because (as #Shai wrote) you avoid writing data to an intermediate variable. I wouldn't expect too much, though.
Try looking at subsref. For your example, you could use it as follows:
subsref(A',struct('type','()','subs',{{2:3,':'}}))
Update: I misunderstood the original question; I thought the OP wanted to select rows from 2:3 from the transposed A matrix keeping the columns as is. I will keep the previous answer in case it could be useful to others.
I think he/she could use the following to slice and flatten a matrix:
subsref(A(2:3,:)', struct('type','()','subs',{{':'}}))
This would give as output:
[3 5 7 4 9 2]'
I have this little problem and I hope that you can help me.
My question is about if there is someway to make this operation in MATLAB:
Suppose this matrix called A(4x3):
A=[1 2 3;4 5 6;7 8 9;8 9 1];
and this vector array called B (4x1):
B=[1;3;5;0];
Now the operation that I want to make is kinda simple: A+B=C, where C is:
A + B = C
C=[2 3 4;7 8 9;12 13 14;8 9 1];
As you can see, the first row of the matrix C is the sum between the first row of matrix A with the first value of the vector B, and it continues.
I know how to make it easily using a "for" but I want to know if there's a way to make it faster.
bsxfun [Apply element-by-element binary operation to two arrays with singleton expansion enabled] with a function handle #plus might just work for you. It lets B expand onto the second dimension as needed for operating with A which is already a 2D matrix and thus giving you the desired "summation" output -
bsxfun(#plus,A,B)
What is the best way to multiply integer-valued matrices in MATLAB?
I was surprised to learn that the following isn't accepted behavior:
>> x = int64([1, 2])
>> x * x'
Error using *
MTIMES is not fully supported for integer classes. At least one input must be scalar.
To compute elementwise TIMES, use TIMES (.*) instead.
I can always convert to double and back again. Is this the best solution? I'm using R2013b.
In this simple case, you could get by with using
sum(x.*x)
It seems times (.*) is supported properly for integer matrices, although mtimes ( *) is not.
For general matrix multiplication: let A and B be two matrices with suitable sizes so that A*B exists. Since times and sum are supported for integers, you can generalize the above trick, usingbsxfun and sum to compute all entries of the product matrix as follows.
Edit: As noted by #July, you need the 'native' flag in sum in order to keep the result of integer type. Thanks also for pointing out a problem that was caused by squeeze, now corrected by using a second permute.
permute(sum(bsxfun(#times, A.', permute(B, [1 3 2])), 1, 'native'), [2 3 1])
For example:
>> A = int64([1 2; 3 4])
A =
1 2
3 4
>> B = int64([5 7 9; 6 8 10])
B =
5 7 9
6 8 10
>> permute(sum(bsxfun(#times, A.', permute(B, [1 3 2])), 'native'), [2 3 1])
ans =
17 23 29
39 53 67
Anyway, the fastest alternative seems to be double(A)*double(B).
MATLAB does not support integer matrix-matrix multiplication due to the lack of industrial support.
MATLAB uses BLAS (more specifically, Intel's implementation of BLAS, i.e. MKL) to do matrix multiplication. At present, BLAS does not natively support multiplication of integer matrices. However, a good news is that MKL 2018 adds initial support for integer matrices. (cf. this slides)
As for your question, if you aim at performance and your matrices are not too small, sum(x.*x) is inferior to int64(double(x)*double(x.')).
Use native only when you are sure that overflow and underflow will not happen.
One extra note is that although native flag can keep the type of return value the same as that of input value. It may suffer from integer overflow or underflow. Check with the following snippet.
sum(int8(-ones(300,1)), 'native') % ans = -128 (of type int8)
sum(int8(ones(300,1)), 'native') % ans = 127 (of type int8)
sum(int8(ones(300,1))) % ans = 300 (of type double)
Although single and double can also overflows and underflows, they happens less frequently.