When I compile a very big function and give it input the function returns error. I realized that this is because the value of the function becomes smaller than the smallest machine number. Is it possible to tell MMA that when I compile a function if the output of the function becomes smaller than the smallest machine number it should return the smallest machine number or zero?
2 Answers
As @episanty says in a comment, try applying Chop
to your data before you return the value. It's compilable, according to List of compilable functions, which means it is appropriate for you here.
Chop[expr]
replaces approximate real numbers inexpr
that are close to zero by the exact integer0
.
The default tolerance is $10^{-10}$. You can use an extra argument if numbers smaller than this are important to you, e.g.
Chop[expr, $MachineEpsilon]
will only replace numbers smaller than $MachineEpsilon.
list = 1.*10^-# & /@ Range[1, 20]
(* {0.1, 0.01, 0.001, 0.0001, 0.00001, 1.*10^-6, 1.*10^-7, 1.*10^-8,
1.*10^-9, 1.*10^-10, 1.*10^-11, 1.*10^-12, 1.*10^-13, 1.*10^-14,
1.*10^-15, 1.*10^-16, 1.*10^-17, 1.*10^-18, 1.*10^-19, 1.*10^-20} *)
Chop[list]
(* {0.1, 0.01, 0.001, 0.0001, 0.00001, 1.*10^-6, 1.*10^-7, 1.*10^-8,
1.*10^-9, 1.*10^-10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} *)
$MachineEpsilon
(* 2.22045*10^-16 *)
Chop[list, $MachineEpsilon]
(* {0.1, 0.01, 0.001, 0.0001, 0.00001, 1.*10^-6, 1.*10^-7, 1.*10^-8,
1.*10^-9, 1.*10^-10, 1.*10^-11, 1.*10^-12, 1.*10^-13, 1.*10^-14,
1.*10^-15, 0, 0, 0, 0, 0} *)
By default, in compiled functions, underflow is not caught and becomes zero automatically.
cf = Compile[x,
Module[{z = x, y = x},
While[y > 0, z = y; y = y/2]; {y, z}]];
cf[1.]
(* {0., 5.*10^-324} *)
Such a number as the number 5.*10^-324
achieved just before underflow is a subnormal machine number. The minimum machine number with full machine precision of almost 16 decimal places is $MinMachineNumber
or 2.22507*10^-308
.
I merely wish to point out that there is a little ambiguity in the question as to what is meant by the "smallest machine number." On the one hand, compiled functions automatically convert underflow to zero. On the other hand, they also allow subnormal numbers with the accompanying loss of precision, which loss could be detrimental to the accuracy of some functions. I don't know of a convenient way to check at each step in a computation whether a result is less than $MinMachineNumber
; however, the OP asks about only the final result, which may be done as @blochwave points out.
-
$\begingroup$ This question is related to this one mathematica.stackexchange.com/questions/57388/… See your comment there. I compiled a function and it returned an error. I checked and I think that the function does not return big numbers and you told that the minimum of the output may exceeds a machine number. $\endgroup$– MOONAug 23, 2014 at 15:33
-
$\begingroup$ @yashar Doesn't this comment belong to the other question, then? $\endgroup$ Aug 23, 2014 at 18:44
-
$\begingroup$ The other question was closed so I thought better to ask it as a new question. $\endgroup$– MOONAug 23, 2014 at 20:37