I have simple function I would like to compile, but I get a warning and a call to MainEvaluate. I would like to avoid both.

MakeInPeriodicCell = 
  Compile[{x, cellwidth}, 
   First@Sort[{x, x - cellwidth, x + cellwidth}, Abs[#1] < Abs[#2] &]];

(*Compile::noinfo: No information is available for compilation of 
Sort[{x,x cellwidth,x+cellwidth},Abs[#1]<Abs[#2]&]. 
The compiler will use an external evaluation and make assumptions about the return type.*)

5   T(R1)2 = MainEvaluate[ Function[{x, cellwidth}, Sort[{x, x - \
cellwidth, x + cellwidth}, Abs[#1] < Abs[#2] & ]][ R0, R1]]


(I got the correct syntax for the subexpression from an answer that got deleted?) I tried setting the type of a subexpression like this:

MakeInPeriodicCell = 
 Compile[{x, cellwidth}, 
  First@Sort[{x, x - cellwidth, x + cellwidth}, 
    Abs[#1] < Abs[#2] &], {{Sort[_,_], _Real,1}}]

This gets rid of the warning, but the call to MainEvaluate remains.

Can this snippet be compiled without a call to MainEvaluate?


Since compile is always about speed, here is some benchmark info. (the code is here, as it clutters the question a bit)

data = RandomReal[{-100, 100}, 100000];
(*Original implementation*)
m0 = MakeInPeriodicCellOrig[data, 30]; // AbsoluteTiming (*0.8370473*)
(*my revritten*)
m1 = MakeInPeriodicCellImp[data, 30]; // AbsoluteTiming  (*0.0360021*)
(*F'x answer*)
m2 = MakeInPeriodicCellFx[data, 30]; // AbsoluteTiming   (*0.0140008*)

m0 == m1 == m2 (*True*)

So getting read of MainEvaluate gives you about 20x speed-up and changing to a better algorithm another 3x. I usually have a million to ten million points, so the speed-up is very welcome.

  • $\begingroup$ If you set SetSystemOptions["CompileOptions" -> "CompileReportExternal" -> True] the warning does not go away. Out of curiosity, have you read these two questions? $\endgroup$
    – rcollyer
    Apr 5, 2012 at 15:36
  • $\begingroup$ @rcollyer But of course I have read the two questions:) $\endgroup$
    – Ajasja
    Apr 5, 2012 at 15:39
  • $\begingroup$ I had to ask. :) $\endgroup$
    – rcollyer
    Apr 5, 2012 at 15:41
  • $\begingroup$ I did figure out what the problem is: Function[] is not in the compilable list. But I didn't notice it before, since it was hidden in the short form &. Should I post the answer or just delete the whole question? $\endgroup$
    – Ajasja
    Apr 5, 2012 at 15:43
  • $\begingroup$ @Ajasja one could post a workaround as an answer; I don't see why to delete the question $\endgroup$
    – acl
    Apr 5, 2012 at 15:44

2 Answers 2


I think Leonid’s comment is spot on. You could work around the issue with a completely different approach:

MakeInPeriodicCell = Compile[{{x, _Real}, {cellwidth, _Real}},
   If[x < -(cellwidth/2.), x + cellwidth, 
    If[x > cellwidth/2., x - cellwidth, x]]
  • 2
    $\begingroup$ Could also use Ordering and order Abs of your list, and then extract elements - this way one can use default comparison function and compile. $\endgroup$ Apr 5, 2012 at 15:48

It appears that in this case Function[] can not be compiled without a call to MainEvaluate.

This is my workaround, but I like F'x much better:)

MakeInPeriodicCell = Compile[{x, cellwidth},
  With[{  l = {x, x - cellwidth, x + cellwidth}},
   Sort[Transpose[{Abs[l], l}]][[1, 2]]
  • 1
    $\begingroup$ This is not a problem of Function not being compiled, this is a problem of type-inferencing inside Sort. I suspect that this is a flaw or limitation of how compilation of Sort was implemented, and has nothing to do directly with abilities of Compile to compile pure functions. $\endgroup$ Apr 5, 2012 at 15:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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