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.

I would like to return two separate values from a compiled function, but Mathematica refuses to use the compiled version. Here is a narrowed-down example:

    cFunc = Compile[{{a, _Integer, 1}}, {a, a.a}];

(* 
  ==> CompiledFunction::cfex: Could not complete external evaluation at instruction 3; proceeding with uncompiled evaluation. >>

  ==> {{1, 1, 1}, 3}
*)

Here a and a.a are hypothetic intermediate results of some long computation, that must be externalized in order for computation to go on outside the compiled function. I assume it is not possible to return lists that are not uniform (data type and dimensions). Is there any way to return more than one results from a compiled computation?

share|improve this question
add comment

3 Answers 3

up vote 10 down vote accepted

What about making the result uniform inside Compile and constructing things back afterwards? Like

   cFunc = Compile[
       {{a, _Integer, 1}}, 
       Join @@ {a, {a . a}}]; 
cFunc[{1, 3}]
Function[z, {Most[z], 
       Last[z]}][%]

which has the nice feature of not calling MainEvaluate:

    Needs["CompiledFunctionTools`"]; cFunc // CompilePrint

(* 
==>
    1 argument
        2 Integer registers
        3 Tensor registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        T(I1)0 = A1
        I0 = 4
        Result = T(I1)2

1   I1 = DotVV[ T(I1)0, T(I1)0, I0]]
2   T(I1)1 ={ I1 }
3   T(I1)2 = Join[ T(I1)0, T(I1)1]]
4   Return

*)
share|improve this answer
2  
I think your code is going to break in this case: cFunc = Compile[{{a, _Integer, 1}}, Join @@ {1.*a, {a.a}}];It makes some assuptions about a, that may not be true. Also, a single call to MainEvaluate is not so much of an issue, as long as it is not in a loop. –  user21 Feb 15 '12 at 15:04
    
@ruebenko what is your analysis of my methods? –  Mr.Wizard Feb 15 '12 at 15:11
    
@ruebenko: Definitely it is in a loop... But then the problem with Rolf's code is that joining and retrieving partial results from z might not be that easy. –  István Zachar Feb 15 '12 at 23:55
    
why not? can you be more specific? –  Rolf Mertig Feb 16 '12 at 0:16
add comment

You can use a technique like this:

cf = Compile[{{n, _Integer}, {m, _Integer}}, 
   Module[{cpos = RandomSample[Range[n], m]},
    Set[pos, cpos];
    RandomReal[1, Length[cpos]]]];

{valres, posres} = Block[{pos}, {cf[10, 5], pos}]

The set works on a variable which is scoped with Block. Since this is done only once, the call to MainEvaluate is not a problem.

share|improve this answer
    
Am I correct in thinking that any solution must force a (one-time) call to MainEvaluate because compiled functions can only work with non-ragged arrays? –  Szabolcs Feb 15 '12 at 14:20
    
I think there are special cases where this is not the case (e.g. Listable compiled functions that returns arrays of different length), but to the best of my knowledge, yes, you need a call to MainEvaluate. –  user21 Feb 15 '12 at 14:24
    
@Szabolcs I guess it might be possible without the MainEvaluate call if in future support for passing Internal`Bags between the Mathematica VM and the interpreter is implemented. But for now, this is indeed the only way to do it as far as I know. –  Oleksandr R. Feb 15 '12 at 14:27
3  
@Szabolcs the problem there is that the error encountered by the VM, even though it occurs at the very end of the compiled code, forces a complete re-evaluation in the interpreter. Error control for compiled code isn't very sophisticated, unfortunately, so evaluation won't pick up in the interpreter where it left off in the VM. –  Oleksandr R. Feb 15 '12 at 14:39
2  
@Oleksandr I see. I wasn't sure if that was the case. cf = Compile[{a}, Print[a]]; cf[2] prints twice and shows that this is indeed what happens. But now it is not clear to me when MainEvaluate will force a complete re-evaluation and when it won't. –  Szabolcs Feb 15 '12 at 14:42
show 5 more comments

A couple of ideas:

cfun = Compile[{{a, _Integer, 1}}, x[1] = a; x[2] = a.a;]
fun[a_?VectorQ] :=
 Block[{x},
  cfun[a];
  {x[1], x[2]}
 ]

fun[{1,2,3,4,5}]
{{1, 2, 3, 4, 5}, 55}
cf2 = Compile[{{a, _Integer, 1}}, Sow[a]; Sow[a.a];];

Reap[cf2@{1, 2, 3, 4, 5}][[2, 1]]
{{1, 2, 3, 4, 5}, 55}
share|improve this answer
2  
which also calls MainEvaluate –  Rolf Mertig Feb 15 '12 at 14:37
    
@Rolf but it does not result in CompiledFunction::cfex isn't that the point? By the way I voted for yours; slick. –  Mr.Wizard Feb 15 '12 at 14:40
    
@Mr.Wizard: nice ideas from you, too! Voted for it. Just try to understand how things work and what are the differences. –  Rolf Mertig Feb 15 '12 at 14:42
    
@Rolf good point. I don't have CompilePrint in v7. I think your method will be the best if the function is low complexity. On a computationally complex function I think the overhead that my methods have will not matter, but I haven't tested that assertion. –  Mr.Wizard Feb 15 '12 at 14:45
    
@Mr.Wizard, I think your methods are fine, you need to call MainEvaluate one more time than with my approach. (That's the only thing I could think of...) –  user21 Feb 15 '12 at 15:36
show 4 more comments

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.