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
  • 1
    $\begingroup$ You can use memoization to evaluate it only once (F[x_] := F[x] = ...). $\endgroup$
    – user541686
    Commented Oct 17, 2019 at 10:50

2 Answers 2

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}} *)
$\endgroup$
5
  • $\begingroup$ With instead of Module can give additional speed-up. $\endgroup$
    – Alx
    Commented Oct 17, 2019 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
    Commented Oct 17, 2019 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
    Commented Oct 17, 2019 at 4:45
  • $\begingroup$ WOW it never clicked until now! WHAT! This is AN AWESOME ANSWER👏 $\endgroup$ Commented Oct 18, 2019 at 23:04
  • $\begingroup$ @CATrevillian Thanks! $\endgroup$
    – MelaGo
    Commented Oct 19, 2019 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]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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