2
$\begingroup$

I am trying to speedup the computation of a longer function using Compile. For illustration consider the following short example:

procTest = Compile[{{x, _Real}},
    res = Log[-x];
    Im[res]
];

The input and output are both real valued. But Mathematica Compile seems to assume that this means that it can use the real Log function inside the routine. At least the following commands

procTest[-1.]
procTest[1.]

output reads

0
CompiledFunction::cfse:  Compiled expression 0. + 3.14159 I should be a machine-size real number.
CompiledFunction::cfex:  Could not complete external evaluation at instruction 2; proceeding with uncompiled evaluation.
3.141592653589793

Of course I can change the type _Real to _Complex which makes this example work, but the output is then a complex quantity with zero imaginary part. Is there a way to tell Compile that it should assume real input and outputs, but complex quantities can appear inside the function? If not, can I convert the output type from complex to real? I am worried about the output type because it seems to confuse other parts of my computation (not sure, but probably FindRoot tries to perform a complex root search if the arguments are not reals).

$\endgroup$

1 Answer 1

3
$\begingroup$

This seems to be a problem with the type-inferencer of Compile. Here is one way around this:

procTest =
  Compile[{{x, _Real}},
     Module[{res = 0 * I},
       res = -x;
       res = Log[res];
       Im[res]]];

In which case, both test cases work all right.

$\endgroup$
2
  • $\begingroup$ Of course, the intermediate variable res should be localized in a Module anyway. By incorporating res=0*I, you're essentially declaring res to be Complex. Is that correct? If so, I would have expected 0.0*I to make more sense. I guess that Module has the attribute HoldAll so that it sees the I anyway. $\endgroup$ Mar 7, 2014 at 14:11
  • $\begingroup$ @MarkMcClure My guess is that the type-inferencer inside Compile introspects internal Module anyway, and has its own means to determine the type, so I did not feel it necessary to use 0.0 * I - but in general you are probably right, 0.0 I should be safer. $\endgroup$ Mar 7, 2014 at 14:27

Your Answer

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

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