4
$\begingroup$

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?

$\endgroup$
2
  • 2
    $\begingroup$ Try applying Chop before returning the value. $\endgroup$ Aug 22, 2014 at 22:13
  • $\begingroup$ Please edit your question to clarify the issue Michael raises below. $\endgroup$
    – Mr.Wizard
    Aug 23, 2014 at 3:14

2 Answers 2

5
$\begingroup$

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.

From the documentation,

Chop[expr] replaces approximate real numbers in expr that are close to zero by the exact integer 0.

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} *)
$\endgroup$
3
$\begingroup$

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.

$\endgroup$
3
  • $\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$
    – MOON
    Aug 23, 2014 at 15:33
  • $\begingroup$ @yashar Doesn't this comment belong to the other question, then? $\endgroup$
    – Michael E2
    Aug 23, 2014 at 18:44
  • $\begingroup$ The other question was closed so I thought better to ask it as a new question. $\endgroup$
    – MOON
    Aug 23, 2014 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.