# Underflow occurred in compilation

This code shown below works well for n<=10, if n>11, Mathematica gives the message

CompiledFunction::cfne: Numerical error encountered; proceeding with uncompiled evaluation. >>.

So compilation failed, my questions is: How can I make it compilable?

cf = Compile[{{n, _Integer}},
With[{c = Table[j + i*I, {i, -1.2, 1.2, .006015}, {j, -1.8, 0.6, .006015}]},
Exp[-Abs@Nest[#^2 + c &, c, n]]]];

• Well to be fair, those numbers are in underflow territory... a "straightforward" way (but terribly slow) would be to use exact arithmetic (but you can't use Compile).
– rm -rf
May 22, 2013 at 15:46
• I don't think compiling failed. The message means that the function, which works in machine precision, detected an underflow condition and decided to continue with the more accurate symbolic version. May 22, 2013 at 15:46
• You can set a value as the infinity and for everything greater you set the Exp to zero. I assume that you are studying something about Julia sets so the divergence area is not the one that you are mainly interested at. May 22, 2013 at 19:10
• How about RuntimeOptions -> "Speed" ? May 24, 2013 at 16:32

The main error is that the numbers get too large in the Nest call, greater than is possible to represent as machine reals/complexes, and you get overflow. Here I just cap them at a large number 10^10, but small enough that Exp won't underflow.

cf = Compile[{{n, _Integer}},
With[{c = Table[j + i*I, {i, -1.2, 1.2, .006015}, {j, -1.8, 0.6, .006015}]},
Exp[-Abs @ Nest[Map[If[Norm[#] > 1.*^10, 1.*^10, #] &, #^2 + c, {2}] &, c, n]]],
RuntimeOptions -> "Speed"];


Same idea, but somewhat faster:

cf = Compile[{{n, _Integer}},
With[{c = Table[j + i*I, {i, -1.2, 1.2, .006015}, {j, -1.8, 0.6, .006015}]},
Exp[-Abs @
Nest[With[{u = UnitStep[1.*^10 - Abs[#]]}, u # + (1 - u) 1.*^10] &[#^2 + c] &,
c, n]]],
RuntimeOptions -> "Speed"]


Here we stop the iteration before the values get small enough to cause the underflow errors.

cf = Compile[{{n, _Integer}},
Table[Exp[-Abs@NestWhile[#^2 + j + i*I &, j + i*I, Abs[#] < 10. &, 1, n]],
{i, -1.2, 1.2, .006015}, {j, -1.8, 0.6, .006015}]];


Instead of Nest it uses NestWhile and the condition is Abs[#] < 10. & so it iterates up to n times, but stops iterating if the argument gets larger than 10, which means Exp[-Abs] is getting small. You might want to change this value. The other change was to not use With and the c variable; the reason for this change (using Table instead) is that the test didn't like having a whole matrix of values passed to it.