3
$\begingroup$

Suppose I have defined a numerical function F[x] that for each entry x, it takes a long time to calculate.

Suppose that now I want to define a new function using the previous one, say, G[x_] := F[x]^2 + 2*F[x] + 1.

My first question is, does Wolfram Mathematica calculate twice the value of F[x] to use it in G[x]? that is, first calculate the F[x] for F[x]^2 and then the F[x] for the 2*F[x]?

And if this is the case, how could I improve the way I define G[x] so that it only calculates F[x] once?

$\endgroup$
  • 1
    $\begingroup$ You can use memoization to evaluate it only once (F[x_] := F[x] = ...). $\endgroup$ – user541686 Oct 17 '19 at 10:50
6
$\begingroup$

Yes, putting the function call in twice will cause it to be evaluated twice. You can visualize this by putting a Print inside the function, for example:

f[x_] := (Print["In f"]; x)

g[x_] := f[x]^2 + 2*f[x] + 1

g[2]
 (* In f *)
 (* In f *)
 (* 2    *)

You can see that it went to f twice. To avoid that, you can assign a temp variable:

g2[x_] := Module[{t = f[x]}, t^2 + 2*t + 1]

g2[2]
 (* In f *)
 (* 2    *)

Changing f to something slow, to illustrate the difference in timing:

f[a_] := NIntegrate[{Sin[x + y]/(1 + x^4 + y^4), (Sin[x] + Cos[y])/(
   1 + x^4 + y^4)}, {x, 0, \[Infinity]}, {y, 0, \[Infinity]}]

g[1] // AbsoluteTiming
 (* {22.6585, {3.56334, 6.79898}} *)
g2[1] // AbsoluteTiming
 (* {11.2694, {3.56334, 6.79898}} *)
| improve this answer | |
$\endgroup$
  • $\begingroup$ With instead of Module can give additional speed-up. $\endgroup$ – Alx Oct 17 '19 at 2:12
  • $\begingroup$ @Alx With RepeatedTiming I get exactly the same answer using g3[x_] := With[{t = f[x]}, t^2 + 2*t + 1] and g2[x_] := Module[{t = f[x]}, t^2 + 2*t + 1]. Is there a better way to write it? $\endgroup$ – MelaGo Oct 17 '19 at 3:23
  • $\begingroup$ I meant general advice to use With as it does just direct replacement and does not create additional variables $smth like Module. But you are right, in this case there is no difference. $\endgroup$ – Alx Oct 17 '19 at 4:45
  • $\begingroup$ WOW it never clicked until now! WHAT! This is AN AWESOME ANSWER👏 $\endgroup$ – CA Trevillian Oct 18 '19 at 23:04
  • $\begingroup$ @CATrevillian Thanks! $\endgroup$ – MelaGo Oct 19 '19 at 21:26
4
$\begingroup$

You could do something like

G[x_] := a^2 + 2 a + 1 /. a -> F[x]

or

G[x_] := #^2 + 2 # + 1 &@F[x]
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.