# Plotting the sum of curves without recalculation

I want to plot several curves of functions which are hard to calculate on the same plot. I would like to add to the same plot the sum of these functions without recalculating them twice at each point.

 Plot[{Sin[x], Sin[2 x], Sin[x] + Sin[2 x]}, {x, 0, 6 Pi}]


I would like somthing like

 Plot[{aa = Sin[x], bb = Sin[2 x], aa + bb}, {x, 0, 6 Pi}]

• precalculate points in advance and then use ListPlot? May 10 '16 at 15:06
• Try Plot[With[{aa = Sin[x], bb = Sin[2 x]}, {aa, bb, aa + bb}], {x, 0, 6 Pi}, Evaluated -> False] (untested). Might give three lines of a single colour. May 10 '16 at 15:11
• @Szabolcs wouldn't it recalculate aa? how will it choose sample rate? May 10 '16 at 15:14
• @Szabolcs It works just like you said (all three lines in the same color, though).
– Jens
May 10 '16 at 15:28
• "without recalculating them twice at each point." - due to the adaptive sampling, it is quite possible that Plot[] will evaluate the sum at points where neither of the components were evaluated, and vice versa. May 10 '16 at 18:27

f[x_] := Sin[x]
Plot[{#1, #2, #1 + #2} &[f[x], f[2 x]], {x, 0, 4}]


Strangely enough, this solution is slower that expected:

f[x_] := NIntegrate[Sin[1/y^2], {y, -x, x}] (*slow function*)

AbsoluteTiming[Plot[{f[x], f[2 x], f[x] + f[2 x]}, {x, 0, 1}]] (*naïve approach*)
AbsoluteTiming[Plot[{#1, #2, #1 + #2} &[f[x], f[2 x]], {x, 0, 1}]] (*my solution*)
AbsoluteTiming[Plot[With[{aa=f[x],bb=f[2x]},{aa,bb,aa+bb}],{x,0,1},Evaluated->False]] (*Szabolcs' comment*)

(*65.7*)
(*106.2*)
(*102.0*)


We do get a substantial improvement with memoization:

f[x_] := f[x] = NIntegrate[Sin[1/y^2], {y, -x, x}]
AbsoluteTiming[Plot[{f[x], f[2 x], f[x] + f[2 x]}, {x, 0, 1}]] (*naïve approach with memoization*)

(*40.5*)


Finally, the best approach so far is to follow BlacKow's suggestion and precalculate the function at discrete points:

f[x_] := NIntegrate[Sin[1/y^2], {y, -x, x}] (*two slow*)
g[x_] := NIntegrate[Cos[1/y^2], {y, -x, x}] (*functions*)

AbsoluteTiming[
points = Range[0, 1, .01];
F = f /@ points;
G = g /@ points;
ListPlot[{Transpose@{points, F}, Transpose@{points, G},
Transpose@{points, F + G}}, Joined -> True]
]

(*3.4*)


though it can get tricky to choose the appropriate spacing.

• newbie here any suggestion is very much appreciated :-) May 10 '16 at 16:10
• ListLinePlot[Transpose@{points, #} & /@ {F, G, F + G}] ... maybe? May 10 '16 at 22:52

A slight variation on AccidentalFourierTransform's version of BlacKow's suggestion.

f[x_] := NIntegrate[Sin[1/y^2], {y, -x, x}]

AbsoluteTiming[
pts1 = Table[{x, f[x]}, {x, Subdivide[0., 1., 101]}];
pts2 = Table[{x, f[2 x]}, {x, Subdivide[0., 1., 101]}];
pts3 = MapThread[{#1[[1]], #1[[2]] + #2[[2]]} &, {pts1, pts2}];
ListLinePlot[{pts1, pts2, pts3}]]


Since I am running on a six year old iMac, I don't think the slightly faster time is due to better processor speed.

• I get about 10% increase if calculate pts3 = Transpose@{pts1[[All, 1]], pts1[[All, 2]] + pts2[[All, 2]]}; May 10 '16 at 22:42