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?


4 Answers 4


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], 

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

  • 2
    $\begingroup$ 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. $\endgroup$
    – user21
    Commented Feb 15, 2012 at 15:04
  • $\begingroup$ @ruebenko what is your analysis of my methods? $\endgroup$
    – Mr.Wizard
    Commented Feb 15, 2012 at 15:11
  • $\begingroup$ @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. $\endgroup$ Commented Feb 15, 2012 at 23:55
  • $\begingroup$ why not? can you be more specific? $\endgroup$ Commented Feb 16, 2012 at 0:16
  • $\begingroup$ I couldn't be more specific because your method is the one that I'm still using regularly, 4 years later : ) $\endgroup$ Commented Jul 21, 2016 at 17:23

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.

  • $\begingroup$ 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? $\endgroup$
    – Szabolcs
    Commented Feb 15, 2012 at 14:20
  • $\begingroup$ 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. $\endgroup$
    – user21
    Commented Feb 15, 2012 at 14:24
  • $\begingroup$ @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. $\endgroup$ Commented Feb 15, 2012 at 14:27
  • 3
    $\begingroup$ @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. $\endgroup$ Commented Feb 15, 2012 at 14:39
  • 2
    $\begingroup$ @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. $\endgroup$
    – Szabolcs
    Commented Feb 15, 2012 at 14:42

I have been encountering this problem a lot recently. Since many related questions are linked to this post and I will share my solution here.


  • Can return multiple results (not necessarily have the same shape)

  • Can return ragged lists

  • Does not call MainEvaluate

Basic idea

Flatten all the tensors into one single list, and include enough information to reconstruct them.

The first element of my list is the number of tensors / variables to return.

The $2$nd to $2 + var - 1$ th element corresponds to the rank of each tensor

The $2 + var$ to the $2 + var + rank_i -1$ th elements corresponds to the dimension of each tensor

Construction inside Compile

1. Multiple return with different-dimension tensors (of different types)

Note:In my example there is no Complex or True|False, but since Re, Im and Boole are all compilable, they can be transformed to a real tensor and a integer tensor respectively.

This example illustrates returning 3 tensors with different dimensions.


2. Return a ragged list (of arbitrary length)

This is a common case when a collection of Positions should be returned. This example illustrates adding 1D list of arbitrary length to the result programmatically.


Neither of the examples have MainEvaluate when examining with CompilePrint.

Extracting the lists

extractLists[list_?VectorQ] := 
 Module[{vars = Round@First@list, rank, dim}, 
  rank = Round@list[[2 ;; 1 + vars]]; 
  dim = Round@
     list[[2 + vars ;; 1 + vars + Total@rank]], rank]; 
   ArrayReshape, {Internal`PartitionRagged[
     list[[2 + vars + Total@rank ;;]], Times @@@ dim], dim}]]

The results (the result of cf2 is random):

(*{{{0., 8., 1., 7.}, {1., 9., 2., 6.}}, {0.301, 
  0.98}, {{{1., 0.}, {2., 7.}}, {{2., 0.}, {0., 0.}}}}*)
(*{{0.895086, 0.716247, 0.626751, 0.457065, 0.709812, 0.118539, 
  0.504491, 0.40369}, {0.2376}, {0.159539, 0.398285, 0.0233042, 
  0.246191, 0.351316, 0.580408}}*)


The type of the result is not conserved (Integer is converted to Real). This can be implemented by adding extra parameter before the rank info (I did not include it because it's not useful for my cases). Also I am not sure whether the performance of the code inside Compile is optimal. Feel free to edit if there are improvements.

  • $\begingroup$ Hmm... Isn't this the same method Rolf has suggested in his answer? I.e. flatten internal results and reconstruct outside the Compile. $\endgroup$ Commented Jul 21, 2016 at 17:24
  • $\begingroup$ @IstvánZachar true for your original problem. I meant to solve a general one. $\endgroup$
    – vapor
    Commented Jul 21, 2016 at 17:27
  • 1
    $\begingroup$ Yes, but still, the general idea was quite clear from Rolf's post. Well, it's nevertheless nice to have a more general approach, so here goes my +1. $\endgroup$ Commented Jul 21, 2016 at 17:34

A couple of ideas:

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

{{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}
  • 2
    $\begingroup$ which also calls MainEvaluate $\endgroup$ Commented Feb 15, 2012 at 14:37
  • $\begingroup$ @Rolf but it does not result in CompiledFunction::cfex isn't that the point? By the way I voted for yours; slick. $\endgroup$
    – Mr.Wizard
    Commented Feb 15, 2012 at 14:40
  • $\begingroup$ @Mr.Wizard: nice ideas from you, too! Voted for it. Just try to understand how things work and what are the differences. $\endgroup$ Commented Feb 15, 2012 at 14:42
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Commented Feb 15, 2012 at 14:45
  • $\begingroup$ @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...) $\endgroup$
    – user21
    Commented Feb 15, 2012 at 15:36

Your Answer

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

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