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 thinking on the workaround for this LogLogPlot bug suggested by halirutan I noticed that CompiledFunction actually can return machine numbers smaller than $MinMachineNumber. Consider:

f = Compile[{{t, _Real}}, Exp[-9 t^2]];
num = f[8.872]
num < $MinMachineNumber
MachineNumberQ[num]
MachineNumberQ[num2 = ToExpression[ToString[num, StandardForm]]]

2.191864698767832`*^-308

True

True

False

As you see, num is smaller than $MinMachineNumber BUT MachineNumberQ returns True. Conversion of this number into String and backward returns arbitrary-precision number.

Moreover, CompiledFunction accepts such numbers and works with them correctly:

f2 = Compile[{{x, _Real}}, Sqrt@x];
f2[num]

1.480494747970364`*^-154

How this behavior could be explained? Does it mean that CompiledFunction actually CAN work with arbitrary-precision numbers?

P.S. I use Mathematica 8.0.4 under Windows 7 x64.

share|improve this question

2 Answers 2

up vote 14 down vote accepted

Congratulations! You find one of subnormal positive double :)

Another example

f = Compile[{{t, _Real}}, 2.0^t];

f[-1074]
f[-1075]
5.*10^-324
0
MachineNumberQ@f[-1074]
True

This doesn't mean that CompiledFunction can work with arbitrary-precision numbers.

Update

Normally Mathematica prevents such numbers

2.^-1074.
% // MachineNumberQ
4.940656458413*10^-324
False

But after a "hack" we can create subnormal positive double manually

SetSystemOptions["CatchMachineUnderflow" -> False];
2.^-1074.
% // MachineNumberQ
5.*10^-324
True

See also Improving speed of Exp[].

Note that Mathematica displays only the first digit of this number (a little bug). All digits:

RealDigits[%%]
{{4, 9, 4, 0, 6, 5, 6, 4, 5, 8, 4, 1, 2, 4, 6, 5}, -323}
share|improve this answer
    
Good old floating-point magic :) –  ssch Nov 25 '13 at 15:03
2  
@AlexeyPopkov Yes, they are machine numbers (they satisfy IEEE 754 double-precision standard). Therefore, MachineNumberQ returns True. –  ybeltukov Nov 25 '13 at 15:39
    
How can I enter a subnormal positive double by hands? Entering 5.*^-324 gives arbitrary-precision number. –  Alexey Popkov Nov 25 '13 at 15:48
    
@AlexeyPopkov It doesn't fit in the comment so I post it in the update of my answer. –  ybeltukov Nov 25 '13 at 15:59
2  
Subnormals are normally handled (slowly) by microcode or in software rather than by the floating-point unit directly. I wonder, is there any way to switch on flush-to-zero? –  Oleksandr R. Nov 25 '13 at 23:15

In addition to @ybeltukov's excellent answer, I thought it would be worth noting the behaviour of RuntimeOptions, when compiling to either the Wolfram Virtual Machine (WVM) or to C, for these subnormal positive doubles.

f = Compile[{{t, _Real}}, Exp[-9 t^2]];

Needs["GeneralUtilities`"]
f[1.]    (* = 0.00012341 *)
f[8.872] (* = 2.191*10^-308 *)

Do[f[1.], {i, 10000}] // AccurateTiming
(* 0.0066 seconds *)

Do[f[8.872], {i, 10000}] // AccurateTiming
(* 0.0652 seconds *)

The difference in timings is an interesting one because of the subnormal result of f[8.872] - take a look at this plot to see.

range = {6., 7., 8., 8.871, 8.872, 9., 10., 11., 12.};
times = AccurateTiming[Do[f[#], {i, 10000}]] & /@ range;
ListPlot[Transpose[{range,times}]]

enter image description here

The default for "RuntimeOptions" is to not catch machine underflow. This can be turned on e.g.

f2 = Compile[{{t, _Real}}, Exp[-9 t^2],
                RuntimeOptions -> {"CatchMachineUnderflow" -> True}];
f2[1.]    (* all fine as before *)
f2[8.872] (* uh-oh! CompiledFunction::cfne *)

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

This error has an associated performance hit, as it jumps out to uncompiled evaluation.

Do[f2[1.], {i, 10000}] // AccurateTiming
(* 0.0063 seconds *)

Do[f2[8.872], {i, 10000}] // AccurateTiming
(* 0.3324 seconds *)

Now look at the timing performance when the underflow is caught. Again, the sub-normal f2[8.872] is a tricky one to handle compared to subsequent results.

enter image description here

share|improve this answer

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.