Reputation: 733
Say I have the following matrix
B = [1 2 3;4 5 6;7 8 9;10 11 12]
and another matrix
A = [a b c;d e f;g h i]
How do I multiply each row of matrix B by the matrix A (without using a for loop), i.e.
for i = 1:4
c(i) = B(i,:)*A*B(i,:)'
end
many thanks in advance.
Upvotes: 2
Views: 1176
Reputation: 112659
You can use:
c = diag(B*A*B.');
However, this computes a whole 4×4 matrix only to extract its diagonal, so it's not very efficient.
A more efficient way that only computes the desired values is:
c = sum(bsxfun(@times, permute(sum(bsxfun(@times, B, permute(A, [3 1 2])), 2), [1 3 2]), B), 2);
Here is a breakdown of the above code:
c1 = sum(bsxfun(@times, B, permute(A, [3 1 2])), 2); % B(i,:)*A
c = sum(bsxfun(@times, permute(c1, [1 3 2]), B), 2); % (B(i,:)*A)*B(i,:)'
The first permute
is used so that the number of columns in B matches the number of columns in A. Following the element-wise multiplication in bsxfun()
each row is summed up (remember, permute
shifted the rows into the 2nd-dimension), reproducing the effect of the vector-matrix multiplication B(i,:) * A occurring in the for
loop.
Following the first sum
, the 2nd-dimension is a singleton dimension. So, we use the second permute
to move the 2nd-dimension into the 3rd-dimension and produce a 2-D matrix. Now, both c1 and B are the same size. Following element-wise multiplication in the second bsxfun()
each column is summed up (remember, permute
shifted columns back into the 2nd-dimension), reproducing the effect of B(i,:) * A * B(i,:)'.
Take note of a hidden advantage in this approach. Since we are using element-wise multiplication to replicate the results of matrix multiplication, order of the arguments doesn't matter in the bsxfun()
calls. One less thing to worry about!
Or, from Matlab R2016b onwards, you can replace bsxfun(@times,...)
by .*
, thanks to implicit expansion:
c = sum(permute(sum(B.*permute(A, [3 1 2]), 2), [1 3 2]).*B, 2);
Upvotes: 4