1

I came across this strange problem:

dd = Compile[{}, Abs[(10^-200 + 10^-200 I)/(10^-200 + I 10^-200)]^2, 
  CompilationTarget -> "C"]

dd[]

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

1

It is same with 10^-100, but these exponents cannot be out of bound with 64bit Visual Studio. What's the problem?

Here is the full code, with the corrected power, which still fails:

f = 
  Compile[{{σt, _Real, 1}, {sρ, _Complex, 1}, {dt, _Real, 1}, 
           {x, _Real}, {nnt, _Integer}},
  Module[{kz = 1/2 x, σ = σt, d = dt, i, kp, c, β, r, k, ρ = sρ * 10^-6, nn = nnt},
    kp = kz + 0. I;
    k = Sqrt[kz^2 - 4 π (ρ[[2]] - ρ[[1]])];
    r = (kp - k)/(kp + k) E^(-2 kp k σ[[1]]^2);
    c = {{1 + 0. I, r }, {r , 1 + 0.}};
    kp = k;
    For[i = 2, i < 2 nn + 2, i++,
      If[EvenQ[i], 
        k = Sqrt[kz^2 - 4 π (ρ[[3]] - ρ[[1]])];
        r = (kp - k)/(kp + k) E^(-2 kp k σ[[2]]^2); 
        β = I kp d[[1]],
        k = Sqrt[kz^2 - 4 π (ρ[[2]] - ρ[[1]])];
        r = (kp - k)/(kp + k) E^(-2 kp k σ[[3]]^2); 
        β = I kp d[[2]] 
      ];
      c = c.{{E^β, r E^β}, {r E^-β, E^-β}};
      (*previous k*)
      kp = k
    ];
    Abs[(c[[2, 1]] + 1*^-100 + I 1*^-200 )/(c[[1, 1]] + 1*^-100 + I 1*^-200)]^2]
  , CompilationTarget -> "C"]

f[{0, 0, 0}, {0, 24, 5}, {6, 4}, 0.025, 1000]

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

1.00000000000000

Update: I think what is happening is that the matrix c starts having components too large and at this point it fails. Giving a small imaginary component to \rho helps and the failure comes only at higher values of nnt. I assume this can't be fixed unless I put conditionals to handle the big values of c but this would defeat the purpose of compiling.

 In[67]:= AbsoluteTiming@
 f[{0, 0, 0}, {0, 24 + 47 I, 5 + 47 I}, {6, 4}, 0.025, 1000]

Out[67]= {0., 0.296593}

Compile gives two orders of magintude increase in speed!

Al Guy
  • 1,610
  • 1
  • 10
  • 15
  • 2
    Read the documentation. Try, e.g. Compile[{}, Module[{x = 10^10}, Floor[x]]][], (or 10^whatever for your machine arch.) then understand why... – ciao Aug 27 '15 at 05:59
  • Try using 1.*^-200 instead. – J. M.'s missing motivation Aug 27 '15 at 06:27
  • 1
    @Guesswhoitis. that appears to compile the result, i.e. CompilePrint[] just has one instruction, namely Return... – dr.blochwave Aug 27 '15 at 06:56
  • 2
    @blochwave That's compile-golf – Dr. belisarius Aug 27 '15 at 06:57
  • @bloch, as I thought. The numbers involved are after all within the range of $MinMachineNumber and $MaxMachineNumber – J. M.'s missing motivation Aug 27 '15 at 07:16
  • ρ = sρ*10^-6 should probably be ρ = sρ*1.*^-6 – m_goldberg Aug 27 '15 at 23:20
  • Read my comment carefully. Notice the dot? It's quite important… – J. M.'s missing motivation Aug 28 '15 at 01:17
  • I understood that compiling 10^-200 gives a multiline pow(10,-200) command, while 1.*^-200 is one liner in the compiled command, and doesn't overflow the 15 digits limit. I took that into account and that improved the convergence, however the code itself, is my understanding, should be modified to include pathologies when nnt is too large, which seems to be unsuitable for compilation. I should look to analytical asymptots of the recursion formula, they just don't convergen in low x limit. – Al Guy Aug 28 '15 at 03:49

1 Answers1

5

The reason for the error message is machine integer overflow. The largest machine integer on a 64-bit platform is 2^63 - 1

Developer`$MaxMachineInteger == 2^63 - 1

(* True *)

Compare the following examples where the second one overflows but the first one doesn't

cf1 = Compile[{}, Developer`$MaxMachineInteger];
cf1[]

(* 9223372036854775807 *)

cf2 = Compile[{}, Developer`$MaxMachineInteger + 1];
cf2[]

(* CompiledFunction::cfn: Numerical error encountered at instruction 2;
    proceeding with uncompiled evaluation. >> *)

 (* 9223372036854775808 *)

Turning off integer overflow checking will eliminate the error message but also give an unexpected result

cf3 = Compile[{}, Developer`$MaxMachineInteger + 1, 
     RuntimeOptions -> {"CatchMachineIntegerOverflow" -> False}];
cf3[]

(* 0 *)    

Inspecting the compiled code for the dd function shows where to expect an integer overflow

Needs["CompiledFunctionTools`"]

dd = Compile[{}, Abs[(10^-200 + 10^-200 I)/(10^-200 + I 10^-200)]^2 ];
CompilePrint[dd]

(*  No argument
    3 Integer registers
    4 Real registers
    4 Complex registers
    Underflow checking off
    Overflow checking off
    Integer overflow checking on
    RuntimeAttributes -> {}

    I1 = 200
    I0 = 10
    C0 = 0. + 1. I
    R2 = 0.
    Result = R3

1   I2 = Power[ I0, I1]
2   R0 = I2
3   R1 = Reciprocal[ R0]
4   C1 = R1 + R2 I
5   C1 = C1 * C0
6   C2 = R1 + R2 I
7   C2 = C2 + C1
8   C1 = R1 + R2 I
9   C3 = C0 * C1
10  C1 = R1 + R2 I
11  C1 = C1 + C3
12  C3 = Reciprocal[ C1]
13  C2 = C2 * C3
14  R0 = Abs[ C2]
15  R3 = Square[ R0]
16  Return *)

so the very first instruction is trying to compute 10^200 which exceeds 2^63 - 1.

The following version which uses machine floating point numbers instead of integers does not have an overflow problem, as mentioned in the comments, it directly returns 1.

ddd = Compile[{}, Abs[(10.^-200 + 10.^-200 I)/(10.^-200 + I 10.^-200)]^2 ];
ddd[]

(* 1. *)

See also the documentation for the CompiledFunction::cfn message and for RuntimeOptions.

ilian
  • 25,474
  • 4
  • 117
  • 186