2

Given two vectors

a = 1:3;
b = 2:4;

it's well known that the element-wise mutiplication a.*b produces

[ 2  6  12 ]

Calling that result c, we have c(i) = a(i)*b(i)

But I don't understand how a.*b', b'.*a and b'*a all produce

[ 2     4     6
  3     6     9
  4     8    12 ]

For the matrix multiplication b'*a, we know c(i,j) = b(i)*a(j).
But why do the other two also produce the same result?

Wolfie
  • 27,562
  • 7
  • 28
  • 55
wsdzbm
  • 3,096
  • 3
  • 25
  • 28

2 Answers2

3

Due to implicit expansion (introduced in 2016b) it's essentially the same as using bsxfun.
But what does that mean?

Setup:

a = 1:3;
b = 2:4;
  • All MATLAB versions:

    c = a.*b; 
    % c = [2 6 12], element-wise multiplication c(j) = a(j)*b(j)
    
    c = b'*a;  
    % c = [2 4 5; 3 6 9; 4 8 12]
    % standard matrix multiplication of vectors
    % c(i,j) = a(i) + b(j)
    
    c = bsxfun(@times, b', a)
    % c = [2 4 5; 3 6 9; 4 8 12]
    % bsxfun applies the function (in this case @times) to b' and a
    

    By definition, bsxfun "applies the element-by-element binary operation specified by the function handle fun to arrays A and B, with singleton expansion enabled". This means that singleton dimensions (dimensions whose size is 1) are expanded row-wise/column-wise to match the size of the other argument supplied to bsxfun.

    So, bsxfun(@times, b', a) is equivalent to

     % b' in singleton in the 2nd dimension, a is singleton in the 1st dimension
     % Use repmat to perform the expansion to the correct size
     repmat(b', 1, size(a,2)) .* repmat(a, size(b',1), 1)
     % Equivalent to...
     repmat(b', 1, 3) .* repmat(a, 3, 1)
     % Equivalent to...
     [2 2 2; 3 3 3; 4 4 4] .* [1 2 3; 1 2 3; 1 2 3]   
     % = [2 4 5; 3 6 9; 4 8 12] the same as b'*a
    
  • Before R2016b

    c = a.*b'; % Error: Matrix dimensions must agree.
    c = b'.*a; % Error: Matrix dimensions must agree.
    
  • Since R2016b

    Newer MATLAB versions use implicit expansion, which basically means that a bsxfun equivalent is called 'under the hood' if necessary for a valid operation.

    c = a.*b'; % [2 4 5; 3 6 9; 4 8 12] the same as bsxfun(@times, a, b')
    c = b'.*a; % [2 4 5; 3 6 9; 4 8 12] the same as bsxfun(@times, b', a)
    % These two are equivalent also because order of operations is irrelevant
    % We can see this by thinking about the expansion discussed above
    

As you've noticed, this can be confusing if you don't keep track of your vector orientations! If you ever want to get a 1D output (without expansion), then you can ensure your inputs are 1D column vectors by using the colon operator like so

c = a(:).*b(:); % c = [2; 6; 12] always a column vector
Wolfie
  • 27,562
  • 7
  • 28
  • 55
1

The examples you listed are all element-wise multiplication.

a.*b' will give error in earlier matlab, while it performs

bsxfun(@times, a, b')

in Matlab since R2016b. This should explain the identical result for a.*b', b'.*a and b'*a.

a * b' will be matrix multiplication (inner dimension match).

Wolfie
  • 27,562
  • 7
  • 28
  • 55
Xiangrui Li
  • 2,386
  • 2
  • 13
  • 17
  • I guess you mean `R2016b`. I'm still not clear why results of `a.*b'` and `b'.*a` are not transposition of each other. – wsdzbm Nov 15 '17 at 05:16