# Plotting a defined function gives different results from plotting the function directly

Consider the following piece of code:

function[t_]:=Exp[-9 t^2];
LogLogPlot[{function[t],Exp[-9 t^2]},{t,.01,100}]


I expect the two plots to exactly overlap each other. However this is not the case and my result looks something like this:

Clearly using the direct expression is correct as the exponential tends to 0 for very large and negative arguments. Why is there a difference between plotting the defined function and plotting the expression directly? Is this a bug?

• I think HoldAll together with the veeeery small numbers is causing this, thus: LogLogPlot[Evaluate@{function[t], Exp[-t^2]}, {t, .01, 100}, PlotRange -> All] works. I am afraid I cannot offer any better explanation at the moment. Oct 8, 2013 at 22:00
• @Pinguin But unfortunately {LogLogPlot[function[t],{t, .01, 100}], LogLogPlot[Exp[-t^2], {t, .01, 100}]} gives different results. Of course the difference is almost infinitesimal, but I don't expect such difference. Furthermore, if g = Exp[-9 #^2] & is used, LogLogPlot[g@t, {t, .01, 100}] also displays correctly. And LogLogPlot does not seem to react to different vertical plot ranges... Oct 8, 2013 at 22:45
• If this helps at all, it indeed does seem like the extremely small numbers have something to do with this. For example, if I change the argument from -9 t^2 to say -5 t^2, then the 'step' in the defined function appears at a large value of time. So the jump appears to happen when the value that is to be plotted hits a particular value. Oct 8, 2013 at 23:12
• I suspect this somehow has to do with the bug appearing in LogPlot (for example see here) but can't come up a way to analyze it. A workaround for your problem is LogLogPlot[{function[t],Exp[-9 t^2]}, {t,.01,100}, WorkingPrecision -> 100] Oct 9, 2013 at 0:23

The problem arises when function returns a number smaller than $MinMachineNumber: function[t_] := Exp[-9 t^2]; LogLogPlot[function[t], {t, 8.8718, 8.872}, PlotRange -> All, GridLines -> {{{Sqrt[Log[1/$MinMachineNumber]]/3,
Directive[Thick, Dashed]}}, None}]
Show[%, Ticks -> Automatic]


For some reason LogLogPlot considers numbers smaller than $MinMachineNumber as having logarithm equal to 0, which is incorrect of course. The workaround suggested in the comments is to abandon machine numbers by switching to arbitrary precision arithmetics. Even if one sets WorkingPrecision much smaller than $MachinePrecision this bug completely disappears, but now another bug arises: the plot produced is not logarithmic in vertical scale and has incorrect vertical tick labels:

LogLogPlot[{function[t], Exp[-9 t^2]}, {t, .01, 100}, WorkingPrecision -> 3]


It is easy to see that the line computed with non-MachinePrecision WorkingPrecision is identical to the one generated by LogLinearPlot:

LogLogPlot[t^3, {t, 1/100, 100}, WorkingPrecision -> 3][[1]] ===
LogLinearPlot[t^3, {t, 1/100, 100}, WorkingPrecision -> 3][[1]]


True

Note that numbers which cannot be expressed as machine numbers are not affected when one tries to convert them to machine numbers:

SetPrecision[function[8.872], MachinePrecision] // Precision


12.9256

So another workaround would be to perform conversion of non-machine-size real numbers manually:

function[t_?NumberQ] :=
If[$MinMachineNumber < Exp[-9 t^2] <$MaxMachineNumber, Exp[-9 t^2],
Indeterminate]


Now LogLogPlot behaves as expected.

Even better way is to switch off generation of non-machine numbers:

SetSystemOptions["CatchMachineUnderflow" -> False]


This way completely removes discussed bug and does not introduce new bugs but it is strongly advisable to localize the effect of this setting as explained here.

Another workaround is suggested by halirutan.

And of course it is possible to switch to another function which has no bugs. In this case LogLinearPlot adaptive plotting capabilities can be utilized:

function[t_?NumberQ] := Exp[-9 t^2]
points = Reap[
LogLinearPlot[
Log@Last@Sow[{t, {function[t], Exp[-9 t^2]}}], {t, .01, 100}]][[2,
1]]
ListLogLogPlot[Sort /@ Transpose[Thread /@ points], Joined -> True]


• You put your finger on it: LogLogPlot[{function[t], Exp[-9 t^2]}, {t, .0120, 100}, WorkingPrecision -> 20] works (i.e., abandon machine numbers). Nov 25, 2013 at 12:20
• Just noticed @LeoFang commented on WorkingPrecision already. Note though that WorkingPrecision -> 3 still produces a pretty good graph. Nov 25, 2013 at 12:28
• @Michael Thanks, the trick with WorkingPrecision works. I'll add it to my answer. Nov 25, 2013 at 13:08
• @Michael I just checked it again and notice that WorkingPrecision actually introduces another bug: look at the vertical axis! When t goes to 0 the function must go to 1 but after setting WorkingPrecision we get value greater than 2! Nov 26, 2013 at 3:43
• How very odd! It seems to not plot Log of the function when WorkingPrecision is not MachinePrecision. Even for LogLogPlot[t^3, {t, 1/100, 100}, WorkingPrecision -> 3]. Nov 26, 2013 at 4:14

When tracing other plots, I often saw that plotting-related functions compile their arguments when possible. A quick look at the trace of your example suggests the same, because the Exp function is used only for the evaluation of function. This seems to indicate that your second argument Exp[-9 t^2] was already compiled down and doesn't show up when the numeric values for the plot are generated.

To support my hypothesis, let us change your example to create a plot that matches completely by compiling function down:

With[{cf = Compile[{{t, _Real}}, Exp[-9 t^2]]},
functionC[t_?NumericQ] := cf[t]
];

LogLogPlot[{functionC[t], Exp[-9 t^2]}, {t, .01, 100}]


Because LogLogPlot tries to analyze functionC, I wrapped the compiled function with ?NumericQ. The result shows two matching graphs:

If you now want to gain further inside, you can concentrate on the difference between the compiled function and the evaluatation of Exp[-9 t^2]`.