Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question
2  
Try applying Chop before returning the value. –  episanty Aug 22 at 22:13
    
Please edit your question to clarify the issue Michael raises below. –  Mr.Wizard Aug 23 at 3:14

2 Answers 2

up vote 4 down vote accepted

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} *)
share|improve this answer

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.

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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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