0

Possible Duplicate:
How to Add a row vector to a column vector like matrix multiplication

I have a nx1 vector and a 1xn vector. I want to add them in a special manner like matrix multiplication in an efficient manner (vectorized):

Example:

A=[1 2 3]'

B=[4 5 6]

A \odd_add B = 
[1+4 1+5 1+6
 2+4 2+5 2+6
 3+4 3+5 3+6
]

I have used bsxfun in MATLAB, but I think it is slow. Please help me...

Community
  • 1
  • 1
remo
  • 880
  • 2
  • 14
  • 32
  • 2
    This is exactly the same as your previous question http://stackoverflow.com/questions/11690743/how-to-add-a-row-vector-to-a-column-vector-like-matrix-multiplication – mathematician1975 Jul 27 '12 at 19:29
  • Sorry, But the speed was the problem. I answered your comment there. – remo Jul 28 '12 at 02:16

4 Answers4

2

As mentioned by @b3. this would be an appropriate place to use repmat. However in general, and especially if you are dealing with very large matrices, bsxfun normally makes a better substitute. In this case:

>> bsxfun(@plus, [1,2,3]', [4,5,6])

returns the same result, using about a third the memory in the large-matrix limit.

bsxfun basically applies the function in the first argument to every combination of items in the second and third arguments, placing the results in a matrix according to the shape of the input vectors.

Isaac
  • 3,586
  • 1
  • 18
  • 20
2

I present a comparison of the different methods mentioned here. I am using the TIMEIT function to get robust estimates (takes care of warming up the code, average timing on multiple runs, ..):

function testBSXFUN(N)
    %# data
    if nargin < 1
        N = 500;        %# N = 10, 100, 1000, 10000
    end
    A = (1:N)';
    B = (1:N);

    %# functions
    f1 = @() funcRepmat(A,B);
    f2 = @() funcTonyTrick(A,B);
    f3 = @() funcBsxfun(A,B);

    %# timeit
    t(1) = timeit( f1 );
    t(2) = timeit( f2 );
    t(3) = timeit( f3 );

    %# time results
    fprintf('N = %d\n', N);
    fprintf('REPMAT: %f, TONY_TRICK: %f, BSXFUN: %f\n', t);

    %# validation
    v{1} = f1();
    v{2} = f2();
    v{3} = f3();
    assert( isequal(v{:}) )
end

where

function C = funcRepmat(A,B)
    N = numel(A);
    C = repmat(A,1,N) + repmat(B,N,1);
end

function C = funcTonyTrick(A,B)
    N = numel(A);
    C = A(:,ones(N,1)) + B(ones(N,1),:);
end

function C = funcBsxfun(A,B)
    C = bsxfun(@plus, A, B);
end

The timings:

>> for N=[10 100 1000 5000], testBSXFUN(N); end
N = 10
REPMAT: 0.000065, TONY_TRICK: 0.000013, BSXFUN: 0.000031
N = 100
REPMAT: 0.000120, TONY_TRICK: 0.000065, BSXFUN: 0.000085
N = 1000
REPMAT: 0.032988, TONY_TRICK: 0.032947, BSXFUN: 0.010185
N = 5000
REPMAT: 0.810218, TONY_TRICK: 0.824297, BSXFUN: 0.258774

BSXFUN is a clear winner.

Amro
  • 123,847
  • 25
  • 243
  • 454
  • Thank you for your answer. Would you please test my solution also. it is based on regular matrix multiplication. first use exp(), then C=A*B and finally result=log(C). As I want to examine negative values in the final result, it would be possible to ignore the last command (log). – remo Jul 30 '12 at 00:37
  • @remo: while your solution is mathematically correct `C = log(exp(A)*exp(B))`, it is not always numerically usable. For instance if you type `exp(750)` in MATLAB, you will simply get `Inf` (too big a number to be represented in double-precision floating points)... – Amro Jul 30 '12 at 01:17
  • @remo: for what its worth, I just tested it with `N=350`, it was slower than all the above methods (larger values for `N` had `Inf` in the result). I guess `exp` and `log` are not cheap operations – Amro Jul 30 '12 at 01:24
1

In matlab vectorization, there is no substitute for Tony's Trick in terms of speed in comparison to repmat or any other built in Matlab function for that matter. I am sure that the following code must be fastest for your purpose.

>> A = [1 2 3]';
>> B = [4 5 6];
>> AB_sum = A(:,ones(3,1)) + B(ones(3,1),:);

The speed differential will be much more apparent (at LEAST an order of magnitude) for larger size of A and B. See this test I conducted some time ago to ascertain the superiority of Tony's Trick over repmatin terms of time consumption.

Community
  • 1
  • 1
Abhinav
  • 1,882
  • 1
  • 18
  • 34
  • While `Tony's trick` is better than REPMAT most of the times (as you've show in your linked answer), in this case BSXFUN has an advantage over both in terms of time and space consumption (since it doesnt actually require replicating the two vectors in memory). Just as you previously did, I posted a performance comparison to back-up my claims :) – Amro Jul 29 '12 at 19:03
  • @Amro Thanks for the empirical results.. . – Abhinav Aug 01 '12 at 06:51
0

REPMAT is your friend:

>> A = [1 2 3]';
>> B = [4 5 6];
>> AplusB = repmat(A, 1, 3) + repmat(B, 3, 1)

AplusB =

     5     6     7
     6     7     8
     7     8     9
b3.
  • 7,094
  • 2
  • 33
  • 48