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.

The smallest sample I can find to reproduce this problem is:

test = Compile[{}, If[True, 1]];
<< CompiledFunctionTools`
CompilePrint@test
…………
 1    R0 = MainEvaluate[ Function[{}, If[True, 1]][ ]]
 2    Return

The problem disappears when the If[] is followed by a semicolon:

test = Compile[{}, If[True, 1];];
CompilePrint@test
…………
1     if[ !B0] goto 3
2     goto 3
3     Return

or enclosed by a redundant Do[]:

test = Compile[{}, Do[If[True, 1], {1}]];
CompilePrint@test
…………
1   I1 = I0
2   I3 = I2
3   goto 6
4   if[ !B0] goto 6
5   goto 6
6   if[ ++ I3 < I1] goto 4
7   Return

while a redundant Table[] won't help:

test = Compile[{}, Table[If[True, 1], {1}]];
CompilePrint@test
…………

1   I1 = I0
2   I4 = I3
3   T(R1)0 = Table[ I1]
4   I2 = I3
5   goto 8
6   R1 = MainEvaluate[ Function[{}, If[True, 1]][ ]]
7   Element[ T(R1)0, I4] = R1
8   if[ ++ I2 < I1] goto 6
9   Return

This phenomenon may lead to a total failure of compilation when codes become more complicated:

ie = 200;
ez = ConstantArray[0., {ie + 1}];
hy = ConstantArray[0., {ie}];

f1 = Compile[{{steps}}, 
   Module[{ie = ie, ez = ez, hy = hy}, 
    Do[ez[[2 ;; ie]] = ez[[2 ;; ie]] + (hy[[2 ;; ie]] - hy[[1 ;; ie - 1]]);
     ez[[1]] = Sin[n/10];
     hy[[1 ;; ie]] = hy[[1 ;; ie]] + (ez[[2 ;; ie + 1]] - ez[[1 ;; ie]]), {n, steps}];
    ez]];

f2 = Compile[{{steps, _Integer}, {test, True | False}}, 
   Module[{ie = ie, ez = ez, hy = hy}, 
    Do[ez[[2 ;; ie]] = ez[[2 ;; ie]] + (hy[[2 ;; ie]] - hy[[1 ;; ie - 1]]);
     ez[[1]] = Sin[n/10];
     hy[[1 ;; ie]] = hy[[1 ;; ie]] + (ez[[2 ;; ie + 1]] - ez[[1 ;; ie]]), {n, steps}];
    If[test, ez]]];

f1[1500]; // AbsoluteTiming
{0.0250000, Null}
f2[1500, True]; // AbsoluteTiming

Warnings……

{0.5730000, Null}

So, as the title said, If won't compile when its output is the output of Compile?

Of course it can be easily circumvented, but I wonder if there's a universal rule behind this, or it's just another unreasonable behavior of Compile?

share|improve this question
3  
Identical issue, and solution, to those discussed in this question earlier today. In fact I'd be tempted to close this as a duplicate, except that I think it shows the issue a bit more clearly than the other question. –  Oleksandr R. Apr 18 at 13:26
    
@OleksandrR. In fact it's that question that motivate me to ask this one (I've noticed this behavior for some time), I read it but still failed to notice it's an identical issue 囧. –  xzczd Apr 18 at 13:33

1 Answer 1

up vote 8 down vote accepted

This is a type incompatibility problem. The compiler must make an assignment to the output of If in order to return a value. If[True, 1] is equivalent to If[True, 1, Null], and there is no type that can be assigned to both 1 and Null. You will get the same problem if you make an assignment to the If result when it isn't the final output of Compile:

CompilePrint @ Compile[{}, Block[{x}, x = If[True, 1]]; 2]
      I0 = 1
      I1 = 2
      B0 = True
      Result = I1

1 R0 = MainEvaluate[ Function[{}, If[True, 1]][ ]]
2 Return

I'm not sure why you don't get a message, in other cases you do:

CompilePrint @ Compile[{}, If[True, 1, {2, 3}]]

Compile::cif: The types of the two results in If[True,1,{2,3}] are incompatible because their ranks are different. Evaluation will use the uncompiled function. >>

      I0 = 1
      T(I1)0 = {2, 3}
      B0 = True
      Result = R0

1 R0 = MainEvaluate[ Function[{}, If[True, 1, {2, 3}]][ ]]
2 Return

Note that if both returns from If are Null there is no problem:

CompilePrint @ Compile[{}, If[True, Null]]
      B0 = True
      Result = V17

1 if[ !B0] goto 3
2 goto 3
3 Return
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.