3

I have n groups, each group has m vectors of dimension d. These are represented by a d*m*n matrix A.

I have n vectors of dimension d, represented by a d*n matrix B.

Now I would like to subtract all the m vectors in the group i by the corresponding vector i in B (and I do that for all i = 1,...,n).

This can be done simply like:

C = zeros(size(A));
for  i = 1:n
    for j = 1:m
        C(:,j,i) = A(:,j,i) - B(:,i);
    end
end

However, this is quite slow because of the loop. Could anybody please suggest me a very fast way to do that?

Thank you in advance for your help.

Divakar
  • 218,885
  • 19
  • 262
  • 358
f10w
  • 1,524
  • 4
  • 24
  • 39

2 Answers2

6

Perfect case for bsxfun -

C = bsxfun(@minus,A,permute(B,[1 3 2]))
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • 1
    @Nesbit Welcome! May I suggest a similar problem for multiplication case across multi-dimensional arrays - http://stackoverflow.com/questions/23807960/bsxfun-implementation-in-matrix-multiplication. In the solution there you might understand why/how `permute` is used - http://stackoverflow.com/a/23808285/3293881 – Divakar May 29 '14 at 18:33
  • Very nice, Divakar! bsxfun is so powerful, I must learn more about it :D – f10w May 29 '14 at 18:35
  • 1
    @Nesbit Can't stress enough on that! :) Keep coming with questions on them!! – Divakar May 29 '14 at 18:36
  • Thanks. (P/s: I so hate the "once every 90 minutes" thing :s) – f10w May 29 '14 at 18:43
  • 1
    @Nesbit Hahaha!! Well..I wish reps could be transferred or lent!! :) – Divakar May 29 '14 at 18:45
  • 1
    @Nesbit Give it a shot, ask me here..or better add to your question, it will be easier for you and me that way :) If it's my thing, I might do it. – Divakar May 29 '14 at 18:46
  • Very kind of you, Divakar. But do you mind if I ask a question that (I think) is not related to bsxfun (I have looked at the reference page of bsxfun and I think I should learn more on that before asking any stupid questions :D). – f10w May 29 '14 at 18:53
  • 1
    @Nesbit Sure, go ahead, again I can't guarantee that I will solve it, but would try! – Divakar May 29 '14 at 18:54
  • OK here it is :D I have a d*m*n matrix A (interpretation: for each n, there are m vectors of dimension d). I would like to extend each d-dimensional vector as follows: For each vector of dimension d: (1,2,...,d) (it's (x_1,x_2,...,x_d) but I removed the 'x_' for simplicity). The goal is to extend v to obtain a d*d vector of the form: (1,1,...,1,2,...,2,...,d,d,...,d) I guess there is a much faster way than using a loop and extending each vector at each iteration, right? – f10w May 29 '14 at 18:58
  • @Nesbit So A is of size dxmxn? What is v? – Divakar May 29 '14 at 19:11
  • Sorry it was a typo. It should read "For each vector v of dimension d:..." Yes, A is of size dxmxn. – f10w May 29 '14 at 19:12
  • @Nesbit So, the output would be `d*dxnxm`? – Divakar May 29 '14 at 19:14
  • @Nesbit Try this - `reshape(permute(repmat(permute(a1,[1 4 2 3]),[1 d]),[ 2 1 3 4]),d*d,m,n)` – Divakar May 29 '14 at 19:26
  • Not, but it is very close, Divakar. d = 2; m = 3; n = 4; A(:,:,1) = [1 5 3; 2 7 6]; A(:,:,2) = [-2 3 1; 0 5 6]; A(:,:,3) = [1 -1 0; 2 1 -1]; A(:,:,4) = [6 8 9; 1 7 5]; If we do reshape(repmat(permute(a1,[1 4 2 3]),[1 d]),d*d,m,n) then the first column of the first matrix gives [1 2 1 2]', but what I wanted is [1 1 2 2]'. – f10w May 29 '14 at 19:28
  • @Nesbit That was buggy, check out the updated code. I just removed the buggy code comment. – Divakar May 29 '14 at 19:29
  • Great! :D Have fun! Get to `200` soon!! – Divakar May 29 '14 at 19:32
  • I will post the question when I have the right to. Please post this answer so that I can give you credits :D – f10w May 29 '14 at 19:33
  • It's okay! You don't have to post it! :) – Divakar May 29 '14 at 19:34
  • Ha ha, I'm very far from that. I'll try to answer questions (not the ones on Matlab of course :P). Thank you again, Divakar! – f10w May 29 '14 at 19:34
  • I've already done :D http://stackoverflow.com/questions/23941536/matlab-extend-a-matrix-by-extending-its-vectors – f10w May 29 '14 at 19:35
3

Give this a shot:

B = repmat(reshape(B,[d 1 n]),[1 m 1]);
C = A - B;

EDIT

Divakar's solution is faster. For 100 runs with d=50;m=75;n=100; the average times were as follows:

Nesbit's - .0165s
Divakar's - .0013s
Mine - .0023s

David K
  • 1,296
  • 18
  • 39