Reputation: 295
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
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
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