# 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. –  Pinguin Dirk Oct 8 '13 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... –  István Zachar Oct 8 '13 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. –  G. H. Hardly Oct 8 '13 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] –  Leo Fang Oct 9 '13 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). –  Michael E2 Nov 25 '13 at 12:20
Just noticed @LeoFang commented on WorkingPrecision already. Note though that WorkingPrecision -> 3 still produces a pretty good graph. –  Michael E2 Nov 25 '13 at 12:28
@Michael Thanks, the trick with WorkingPrecision works. I'll add it to my answer. –  Alexey Popkov Nov 25 '13 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! –  Alexey Popkov Nov 26 '13 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]. –  Michael E2 Nov 26 '13 at 4:14
show 1 more comment

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]`.

-