-1

What would be the best way to simplify a function by getting rid of a loop?

function Q = gs(f, a, b)

X(4) = sqrt((3+2*sqrt(6/5))/7);
X(3) = sqrt((3-2*sqrt(6/5))/7);
X(2) = -sqrt((3-2*sqrt(6/5))/7);
X(1) = -sqrt((3+2*sqrt(6/5))/7);

W(4) = (18-sqrt(30))/36;
W(3) = (18+sqrt(30))/36;
W(2) = (18+sqrt(30))/36;
W(1) = (18-sqrt(30))/36;
Q = 0;
for i = 1:4
   W(i) = (W(i)*(b-a))/2;
   X(i) = ((b-a)*X(i)+(b+a))/2;
   Q = Q + W(i) * f(X(i));
end


end

Is there any way to use any vector-like solution instead of a for loop?

rayryeng
  • 102,964
  • 22
  • 184
  • 193
pawelen
  • 133
  • 1
  • 1
  • 5

1 Answers1

3

sum is your best friend here. Also, declaring some constants and creating vectors is useful:

function Q = gs(f, a, b)
c = sqrt((3+2*sqrt(6/5))/7);
d = sqrt((3-2*sqrt(6/5))/7);
e = (18-sqrt(30))/36;
g = (18+sqrt(30))/36;

X = [-c -d d c];
W = [e g g e];

W = ((b - a) / 2) * W;
X = ((b - a)*X + (b + a)) / 2;
Q = sum(W .* f(X));

end

Note that MATLAB loves to handle element-wise operations, so the key is to replace the for loop at the end with scaling all of the elements in W and X with those scaling factors seen in your loop. In addition, using the element-wise multiplication (.*) is key. This of course assumes that f can handle things in an element-wise fashion. If it doesn't, then there's no way to avoid the for loop.

I would highly recommend you consult the MATLAB tutorial on element-wise operations before you venture onwards on your MATLAB journey: https://www.mathworks.com/help/matlab/matlab_prog/array-vs-matrix-operations.html

rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • On line 5 of your code you assign a scalar numeric value to `f` but on the last line before `end` you write `f(X)` - is one of these a typo? – nekomatic Dec 21 '17 at 12:07
  • @nekomatic yes that was. Thanks. I've changed one of the variables – rayryeng Dec 21 '17 at 17:02
  • Also, if `f` can only handle scalar inputs you can still avoid an explicit loop with `Q = sum(W .* arrayfun(f, X))`. – nekomatic Dec 22 '17 at 09:14
  • @nekomatic I would still use a loop. `arrayfun` is slower performance wise. https://stackoverflow.com/q/12522888/3250829. You probably won't see it for this small array but for larger arrays you definitely see a performance hit. – rayryeng Dec 22 '17 at 09:32