1

I have a 4D array A size(l,k,s,r) and a cell array B size(i,j) where in each cell a different 4D array of coefficients size(l,k,s,r) is stored.

I want to make changes in the given array C of size(i,j) = C(i,j) + sum(sum(sum(sum(A.*B{i,j})))) without for loop.

in other words I need to extract one by one all arrays out of cell array B and multiply with A.

with the for loop i do it this way:

for i=1:length_of_first_dimension
    for j=1:length_of_second_dimension
        B_4D=B{i,j};       % extraction of 4D array
        dummy(i,j)=sum(sum(sum(sum(B_4D.*A))));
    end
end
C=C+dummy;

can anyone help me with that?

Shai
  • 111,146
  • 38
  • 238
  • 371
VVV
  • 25
  • 2
  • could you please give more detailed information about the way i can do that? what exactly should i reshape? – VVV Dec 02 '14 at 10:13
  • It is [best not to use `i` and `j` as variable names in Matlab](http://stackoverflow.com/questions/14790740/using-i-and-j-as-variables-in-matlab). – Shai Dec 02 '14 at 10:20

1 Answers1

2

first, reshape B into a (length_of_first_dimension*length_of_second_dimension)-by-l*k*s*r 2D matrix

rB = cellfun( @(x) x(:).', B, 'uni', 0 ); %'
rB = vertcat(rB{:});

Now, reshape A into a l*k*s*r-by-1 column vector

rA = A(:);

And simply multiply them

rDummy = rB * rA; %// does the elem-wise product and summation quite quickly.  

Reshape the result

dummy = reshape(rDummy, size(B) );
C = C + dummy;

As pointed by Divakar a more efficient way to reshape B would be

rB = reshape( cat( 5, B{:} ), numel(A), [] ).';

And a small benchmark can be found here.

Community
  • 1
  • 1
Shai
  • 111,146
  • 38
  • 238
  • 371
  • 1
    Should be pretty efficient. – Divakar Dec 02 '14 at 12:27
  • @Divakar thanks. `reshaping` should be quite efficient, but I'm afraid `vertcat` might lead to large memory copy. It might be worth while considering reshaping and arranging so that the dot-product would be `rA*rB`... – Shai Dec 02 '14 at 12:43
  • 1
    I actually think you can avoid that `cellfun` which might be one of the slowest parts with this - `rB = reshape(cat(5,B{:}),numel(A),[]).';`. And you have to use one of the `cat`s somewhere anyway. After you have this `rB`, rest of your code should just take care of it. – Divakar Dec 02 '14 at 12:54
  • @Divakar I was afraid of `cat`ing along 5th or 6th dimension and then transposing - it doesn't feel right, I fear it might entail a lot of memory copying. – Shai Dec 02 '14 at 13:09
  • 1
    That's the trade of course. But for me, I try to get off cell arrays as soon as possible if there are numeric computations involved. So I thought even the cat in the 5th dim could be worth the effort. This got me curious and here are some quick runtime results - https://ideone.com/SI59SI – Divakar Dec 02 '14 at 13:20
  • @Divakar can you post it as a new answer - I'll upvote. – Shai Dec 02 '14 at 13:22
  • Oh no! When I saw the question, I started with `bsxfun(@times`, which would had been really inefficient and then I saw your answer and that led me to this cat in 5th dim idea, which I think is a minor adjustment to your solution. So it won't be fair :) – Divakar Dec 02 '14 at 13:24