user3482383
user3482383

Reputation: 295

omitting the for loops in matlab

I am going to compute the following equation in which there are four different variables. Is there any possible way to omit the for loops for computing this equation?

 Z = p1 * sqrt(q1^2 + q2^2 * p2^2)

in which the variables are:

p=[(1,1) (1,2) (1,3) (1,4)
   (2,1) (2,2) (2,3) (2,4)
   (3,1) (3,2) (3,3) (3,4)
   (4,1) (4,2) (4,3) (4,4)];

in which the first number is p1 and the second will be p2(e.g. in (1,2), p1=1, p2=2). and:

q=[(5,5) (5,6) (5,7) (5,8)
   (6,5) (6,6) (6,7) (6,8)
   (7,5) (7,6) (7,7) (7,8)
   (8,5) (8,6) (8,7) (8,8)]

again the first number will be q1 and second one will be q2.

How can i comput Z for each of them without for loop?

Upvotes: 0

Views: 114

Answers (2)

Divakar
Divakar

Reputation: 221514

I am assuming your nested loops look like this -

Z = zeros(length(p1),length(p2),length(q1),length(q2));
for i=1:length(p1)
    for j=1:length(p2)
        for m = 1:length(q1)
            for n = 1:length(q2)
                Z(i,j,m,n) = p1(i) * sqrt(q1(m)^2 + q2(n)^2 * p2(j)^2);
            end
        end
    end
end

Note: numel or size would be a better parameter to use than length, but keeping length here as used in your codes, before you did revisions with your question.

Now, in p1, q1, p2 and q2 you have grid data and thus many identical values, which can be used for code optimization and thus vectorization. Here's a vectorized solution with bsxfun -

impvals = bsxfun(@times,p1(:,1)',sqrt(q1(:,1).^2+(p2(1)*q2(1))^2)); %//'
Z = repmat(permute(impvals,[2 3 1 4]),[1 4 1 4]);

I ran this with your given 4x4 data for each of those four 2D arrays for 100000 times (for a better runtime measurement) and this were the runtimes -

Elapsed time (with for-loops) is 5.684010 seconds.
Elapsed time (with bsxfun) is 4.441675 seconds.

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112659

To compute for each combination of the four variables without for loops, use ndgrid:

[pp1 pp2 qq1 qq2] = ndgrid(p1,p2,q1,q2);
Z = pp1 .* sqrt(qq1.^2 + qq2.^2 + pp2.^2);

For your example, this produces a result Z of size 16 x 16 x 16 x 16. First index of Z refers to p1, second to p2, third to q1 and fourth to q2.

BTW, in your code you would need to replace length to numel; as it stands you are not taking all elements from each matrix.


After question edit: To compute for each combination of p1 and q1, with the index of p2 being the same as that of p1 and the index of q2 being the same as that of q1:

[ii jj] = ndgrid(1:numel(p1), 1:numel(q1));
Z = pp1(ii) .* sqrt(qq1(jj).^2 + qq2(jj).^2 + pp2(ii).^2);

which gives Z of size 16 x 16 in your case.

Upvotes: 2

Related Questions