# Why is building a table of function values so much slower than just plotting the function?

Here is a function that take some time to evaluate:

n = 1000;
coeffs = RandomVariate[NormalDistribution[], n];
f[x_] := Sum[coeffs[[k]] Sin[k x]/k, {k, 1, n}];


If I just plot the function with 1000 sample points, it takes about 0.24 seconds on my machine:

Plot[Evaluate@f[x], {x, 0, 2 Pi}, PlotPoints -> n, MaxRecursion -> 0] // Timing


On the other hand, if I try to collect 1000 samples of the function into a table, it takes five times as long:

Table[Evaluate@f[x], {x, 0, 2 Pi, 2 Pi/n // N}] // Timing


(Without the // N Mathematica tries to evaluate things symbolically, which is even slower.)

What is going on, and how can I make the Table as fast as the Plot?

• You can save about one-third of the time by removing the redundant Evaluate from your Table expression. Also, this result is entirely dependent on the MaxRecursion setting. If you remove this, or leave it in but increase its value, the plot takes longer than the table. Aug 28, 2013 at 3:53
• I used MaxRecursion -> 0 expecting that the Plot would evaluate exactly 1000 regularly spaced sample points, just like the Table. (Well, the Table actually evaluates 1001 points, but close enough.) Is that not true?
– user484
Aug 28, 2013 at 4:01
• I've read in few places that Table can be slow. Not sure why now. Yes, you are right, MaxRecursion -> 0 makes sure no more points are taken. Aug 28, 2013 at 4:06

Try this:

n = 1000;
coeffs = RandomVariate[NormalDistribution[], n];
f[x_] := Sum[coeffs[[k]] Sin[k x]/k, {k, 1, n}];
Plot[Evaluate@f[x], {x, 0, 2. Pi}, PlotPoints -> n, MaxRecursion -> 0,
Mesh -> All] // Timing With[{n = 1000},
First@Timing[Table[Evaluate@f[x], {x, 0, 2. Pi, 2. Pi/n}]]
] 2 times as fast as plot. I remembered my own question difference-of-speed-in-making-a-table on tables some time ago and this trick of making Table much faster. The point is : to keep it packed, need to have all limits be numerics ! When you had n in there, the upper limit was not. So the table was not packed. Now it is.

You could just also write

Table[Evaluate@f[x], {x, 0, 2. Pi, 2. Pi/1000}]


## Another example

2000 points. Table still about 2 times faster: • Thanks! But for me it seems that the difference is not the presence of n or the addition of With. Doing First@Timing[Table[Evaluate@f[x], {x, 0, 2. Pi, 2. Pi/n}]] is fast while doing First@Timing[Table[Evaluate@f[x], {x, 0, 2 Pi, 2. Pi/n}]] as in my question is slow. (The difference is just one more decimal point.)
– user484
Aug 28, 2013 at 5:18
• @Rahul I'm using v7 so I can't check; is the output of RandomVariate a packed array of Real numbers? Aug 28, 2013 at 5:26
• @Mr.Wizard: I'm just learning about packed arrays just now, so let me know if this is not how to check: PackedArrayQ is True and the Head of the first element is Real, so yes?
– user484
Aug 28, 2013 at 5:34
• @RahulNarain That's correct. I added an answer that you'll have to test yourself but it might be informative. Aug 28, 2013 at 5:39
• Having read your linked question I see that With is necessary for multidimensional tables, which I will need in the future, so thanks for that too! Unfortunately I have already given you an upvote and a check mark, so all I can do now is leave an appreciative comment. :)
– user484
Aug 28, 2013 at 7:14