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.

Is there somewhere a list on the functions that Compile can compile, or the cases in which a particular function can be compiled that I haven't found? I'd be glad even with a list of some of them which surprisingly aren't compilable, and how to do without them.

I am not happy every time I have to rewrite or redesign code because it seems to make external calls for functions I didn't expect. I'd like to know how you handle all that, what you keep in mind.

share|improve this question

6 Answers 6

up vote 80 down vote accepted

Yes, but this only exists in version 8 and is undocumented:

Compile`CompilerFunctions[] // Sort

giving, for reference:

{Abs, AddTo, And, Append, AppendTo, Apply, ArcCos, ArcCosh, ArcCot,
ArcCoth, ArcCsc, ArcCsch, ArcSec, ArcSech, ArcSin, ArcSinh, ArcTan,
ArcTanh, Arg, Array, ArrayDepth, Internal`Bag, Internal`BagPart,
BitAnd, BitNot, BitOr, BitXor, Block, BlockRandom, Boole, Break,
Cases, Catch, Ceiling, Chop, Internal`CompileError,
System`Private`CompileSymbol, Complement, ComposeList,
CompoundExpression, Conjugate, ConjugateTranspose, Continue, Cos,
Cosh, Cot, Coth, Count, Csc, Csch, Decrement, Delete, DeleteCases,
Dimensions, Divide, DivideBy, Do, Dot, Drop, Equal, Erf, Erfc, EvenQ,
Exp, Fibonacci, First, FixedPoint, FixedPointList, Flatten,
NDSolve`FEM`FlattenAll, Floor, Fold, FoldList, For, FractionalPart,
FreeQ, Compile`GetElement, Goto, Greater, GreaterEqual, Gudermannian,
Haversine, If, Im, Implies, Increment, Inequality, Compile`InnerDo,
Insert, IntegerDigits, IntegerPart, Intersection,
InverseGudermannian, InverseHaversine, Compile`IteratorCount, Join,
Label, Last, Length, Less, LessEqual, List, Log, Log10, Log2, LucasL,
Map, MapAll, MapAt, MapIndexed, MapThread, NDSolve`FEM`MapThreadDot,
MatrixQ, Max, MemberQ, Min, Minus, Mod, Compile`Mod1, Module, Most,
N, Negative, Nest, NestList, NonNegative, Not, OddQ, Or, OrderedQ,
Out, Outer, Part, Partition, Piecewise, Plus, Position, Positive,
Power, PreDecrement, PreIncrement, Prepend, PrependTo, Product,
Quotient, Random, RandomChoice, RandomComplex, RandomInteger,
RandomReal, RandomSample, RandomVariate, Range, Re, ReplacePart,
Rest, Return, Reverse, RotateLeft, RotateRight, Round, RuleCondition,
SameQ, Scan, Sec, Sech, SeedRandom, Select, Set, SetDelayed,
Compile`SetIterate, Sign, Sin, Sinc, Sinh, Sort, Sqrt,
Internal`Square, Internal`StuffBag, Subtract, SubtractFrom, Sum,
Switch, Table, Take, Tan, Tanh, TensorRank, Throw, Times, TimesBy,
Tr, Transpose, Unequal, Union, Unitize, UnitStep, UnsameQ, VectorQ,
Which, While, With, Xor}

Edit: additional functions

I have just discovered the symbol Internal`CompileValues, which provides various definitions and function calls needed to compile further functions not in the list above. Using the following code,

Internal`CompileValues[]; (* to trigger auto-load *)
ClearAttributes[Internal`CompileValues, ReadProtected];
syms = DownValues[Internal`CompileValues] /. 
    HoldPattern[Verbatim[HoldPattern][Internal`CompileValues[sym_]] :> _] :>
        sym;
Complement[syms, Compile`CompilerFunctions[]]

we get some more compilable functions as follows:

{Accumulate, ConstantArray, Cross, Depth, Det, DiagonalMatrix,
Differences, NDSolve`FEM`FEMDot, NDSolve`FEM`FEMHold,
NDSolve`FEM`FEMInverse, NDSolve`FEM`FEMPart, NDSolve`FEM`FEMTDot,
NDSolve`FEM`FEMTotalTimes, NDSolve`FEM`FEMZeroMatrix, FromDigits,
Identity, IdentityMatrix, Inverse, LinearSolve, Mean, Median, Nand,
NestWhile, NestWhileList, Nor, Norm, Ordering, PadLeft, PadRight,
Permutations, Ratios, Signature, SquareWave, StandardDeviation,
Tally, Total, TrueQ, Variance}

Looking at the definition of Internal`CompileValues[sym] for sym in the list above will provide some additional information about how these functions are compiled. This can range from type information (for e.g. Inverse), through to an implementation in terms of lower-level functions (e.g. NestWhileList). One can presumably also make one's own implementations of non-compilable functions using this mechanism, giving Compile the ability to compile a wider range of functions than it usually would be able to.

Edit 2: the meaning of the second list

In response to a recent question, I want to be clear that the presence of a function in the second list given above does not necessarily mean it can be compiled into a form free of MainEvaluate calls. If a top-level function is already highly optimized (as e.g. LinearSolve is), the purpose of Internal`CompileValues[func] may be solely to provide type information on the return value, assuming that this can be inferred from the types of the arguments or some other salient information. This mechanism allows more complex functions that call these highly-optimized top-level functions to be compiled more completely since there is no longer any question of what the return type may be and so further unnecessary MainEvaluate calls may be avoided. It does not imply that the use of MainEvaluate is unnecessary to call the function itself.

share|improve this answer
3  
Interesting, Total[] isn't compilable, but Plus and Apply are... –  J. M. Feb 1 '12 at 4:33
5  
It looks like you've found a counterexample. Indeed, MemberQ[Compile`CompilerFunctions[], Total] == False, but in practice Total gets compiled down to a call to the internal kernel function TotalAll. Why Total is not included in the list, I have no idea. –  Oleksandr R. Feb 1 '12 at 4:45
1  
@MikeHoneychurch, Ted Ersek posted the old list (version 3/4 vintage) on his website. See here. There have been quite a few changes since then, though. –  Oleksandr R. Feb 1 '12 at 23:47
5  
To whoever downvoted this: would you be so kind as to let me know what your concerns were and perhaps suggest how I could improve my answers in future? Many thanks. –  Oleksandr R. Aug 18 '12 at 23:10
1  
@telefunkenvf14 I think there is not much more to be said about System`Utilities`HashTable* beyond what I already wrote here. That object definitely isn't related to the Internal`Bag; they are totally different data structures (also, the HashTable cannot be used in compiled code). Hash tables and linked lists are well-known data structures in computer science, so you will find a lot of information already out there. Any more specific questions... just ask! –  Oleksandr R. Dec 9 '12 at 6:30

I believe there is such a list available but I can't remember the command off-hand. In the meantime, you can always load CompiledFunctionTools via.

<<CompiledFunctionTools`

And then use CompilePrint on a compiled function to see if MainEvaluate is present in the pseudocode. MainEvaluate tells us that something is going through the evaluator and wasn't compilable.

f=Compile[{{x,_Real,1}},
  Print[x];
  x
];

In[61]:= CompilePrint[f]

Out[61]= 
        1 argument
        1 Tensor register
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        T(R1)0 = A1
        Result = T(R1)0

1   V17 = MainEvaluate[ Function[{x}, Print[x]][ T(R1)0]]
2   Return

Notice the MainEvaluate in the call to Print. This means Print isn't compilable.

share|improve this answer

In addition to Oleks list, there is of course a way to study what happens under the hood.

f = Compile[{{x, _Integer, 1}},
   Accumulate[x]
   ];
<< CompiledFunctionTools`
CompilePrint[f]

(*

        1 argument
        1 Integer register
        2 Tensor registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

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

1   T(I1)1 = Accumulate[ T(I1)0, I0]]
2   Return
*)

Here you see, that Accumulate can be compiled down, the question is where does this come from? Since version 8 you can compile to C-code, so lets do this and check what happens

<< CCodeGenerator`
CCodeGenerate[f, "fun", "tmp.c"];
FilePrint["tmp.c"]

I won't copy the whole output, but inspecting the code shows you

FP0 = funStructCompile->getFunctionCallPointer("Accumulate");

So the library extracts a function pointer from another (the WolramRTL) library. This library is distributed with Mathematica and you should have it in your SystemFiles/Libraries/$SystemID directory. You can now study this library by using tools like nm (on *nix systems) showing you the exported symbols. This is a very long list of course and maybe a bit cryptic to those not used to C-programming, but it should be readable. Here a short snip

00000000003327d0 T _MTensor_outerList
0000000000336e10 T _MTensor_outerPlus
00000000003352a0 T _MTensor_outerTimes
000000000032d1f0 t _MTensor_pTranspose
00000000003291b0 T _MTensor_pad
000000000032a580 T _MTensor_position
0000000000326140 T _MTensor_reallocateAndCopyData
0000000000325750 t _MTensor_releaseData
00000000003263f0 T _MTensor_resetDimensions
0000000000328f90 T _MTensor_reverse
000000000032cc80 T _MTensor_rotate

The question is, can you get more insight (if wanted) when inspecting this together with the list provided by Olek? I think it depends, sometimes yes, sometimes no. In my opinion it is always nice to have a clue what's going on in the deep.

One example from the Compile`CompilerFunctions[] list is the function Outer. As you can see in the output above, this function does not directly exist, but is split into three forms, outerList, outerPlus and outerTimes. Regarding this, it seems Outer cannot be compiled in every form. Let's test this

f = Compile[{{x, _Integer, 1}},
   Outer[List, x, x]
   ];
CompilePrint[f]

(* 
  1 T(I3)1 = OuterList[ T(I1)0, T(I1)0, I0, I0]]
)*

This works as expected and we see the function OuterList is used. You can if you want inspect the c-code too. Let me skip this here and try the same function with a Divide as head

f = Compile[{{x, _Integer, 1}},
   Outer[Divide, x, x]
   ];
(*
Compile::cpapot: Compilation of Outer[Divide,x,x] is not supported 
for the function argument Complex. The only function arguments supported 
are Times, Plus, or List. Evaluation will use the uncompiled function. >>
*)

If the error message would not point out directly, that Outer is only possible with the 3 heads, one could argument, that Divide is a bad function anyway since integers are not closed under this operation. You can easily try it with Complex and get the same message.

To summarize: Usually you don't need any list of supported functions, because the rule of thumb is, that compile will not work with already optimized, complicated Mathematica-methods. This includes NIntegrate, FindRoot or NMinimize. Nevertheless, Compile can easily be used to make those function-calls really fast. What you have to do is to compile your target function, because the most time with stuff like NIntegrate is spent, evaluating the integrand. The same is true for FindRoot, NMinimize and many more methods.

Another good indicator to guess whether or not a function is supported is to look at the kinds of functions of Oleks list. There are exceptions to this rule but basically the list of supported functions can be divided into two classes. Simple numerical functions like Sin or Xor and functions which help you to work with tensors. I don't remember how often I wished I simply had Tally, Map or Fold in C. Even the addition or multiplication of tensors must be done by manually.

Therefore, if a Mathematica-function implements a complicated method, when it's not a mathematical function or when it does not help you working with tensors/lists, it is most probably not supported by Compile.

share|improve this answer
    
+1. Regarding your Outer example - which is good in this context - I just want to add that it is rather special. There are good reasons why it can only be compiled for the heads you named. In this answer: stackoverflow.com/questions/4973424/…, I show how to make compilation of Outer more flexible, and also discuss the reasons why compiling Outer is tricky. –  Leonid Shifrin Feb 1 '12 at 13:40
    
Yes, you are right. I scrolled through the list and was trying to find an really short example. It was the first catch my eye. –  halirutan Feb 1 '12 at 13:53

Warning: The SetSystemOptions method to detect failed compilation, described below, is not 100% reliable. Please see the comments (e.g. trC = Compile[{{a, _Integer, 2}}, Tr[a]] won't warn).


I assume you need the list of compilable functions to make sure that all of your code will be properly compiled, and it won't take any speed penalties (that why I was looking for this information before). People have shown you how to print the compiled code and check that there are no calls to MainEvaluate in it. There is an alternative and simpler way of working:

SetSystemOptions["CompileOptions" -> "CompileReportExternal" -> True]

After setting this, Compile will warn about uncompilable things:

In[4]:= cf1 = Compile[{x}, Total[x]]

During evaluation of In[4]:= Compile::extscalar: 
  Total[x] cannot be compiled and will be evaluated externally. 
  The result is assumed to be of type Real. >>

Out[4]= CompiledFunction[{x},Total[x],-CompiledCode-]

In[5]:= cf2 = Compile[{{x,_Integer,1}}, Total[x]]

Out[5]= CompiledFunction[{x},Total[x],-CompiledCode-]

This is better than just thinking about which function is compilable and which isn't because as you can see, whether something can be compiled also depends on context (Total in this example.)


For completeness, let me show that CompilePrint[cf1] gives

        R0 = A1
        Result = R1

1   R1 = MainEvaluate[ Hold[Total][ R0]]
2   Return

while CompilePrint[cf2] gives

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

1   I1 = TotalAll[ T(I1)0, I0]]
2   Return
share|improve this answer
    
Could you please comment on why trC = Compile[{{a, _Integer, 2}}, Tr[a]] calls MainEvaluate and why your method doesn't trigger an error message (after setting the appropriate system option)? –  István Zachar Aug 23 '13 at 15:02
    
@IstvánZachar Unfortunately, I cannot. It seems the method is not reliable. I should update the answer. –  Szabolcs Aug 23 '13 at 15:10
    
@IstvánZachar For lack of time, I'll just put a warning at the top of the answer now. If you have other suggestions, please let me know. –  Szabolcs Aug 23 '13 at 15:13
    
@Oleksandr, Szabolcs I think the problem of not throwing an error is covered here, though why Tr cannot be compiled primarily without ME eludes me. –  István Zachar Aug 27 '13 at 15:35
    
@IstvánZachar Fortunately it's relatively easy to create a compiled Tr alternative. –  Szabolcs Aug 27 '13 at 17:45

The following additional functions are compilable in Mathematica 9.

{Gamma, LogGamma, Internal`ReciprocalSqrt}
share|improve this answer

A bit late to the discussion but I had the chance to ask Wolfram's North America sales manager about this. I had forwarded him the list of compilable functions "Compile`CompilerFunctions[]".

He asked one of his engineers about this. They came back with some information that I thought would add to this question.

I don't think that is the correct interpretation of the list Sort[Compile`CompilerFunctions[]]. This list consists of those system functions that are pre-compiled. But any numerical function can be compiled to C and basically any user defined function that does not use a purely symbolic function can be compiled to C, for eg:

In[1]:= square=Compile[{x},x^2]  
Out[1]= CompiledFunction[{x},x^2,-CompiledCode-]   

In[2]:= square /@ {1.3,3.5,6.7} 
Out[2]= {1.69,12.25,44.89}   

And even for symbolic functions, you can get them to evaluate before compilation using CompileEvaluate[..]

Mathematica's compiler is more powerful than other programs because it also allows for checking of types in the compiled expression.

....

MORE FROM WOLFRAM

As I mentioned in a comment to Oleksandr, I went back to the sales manager for a clarification. He forwarded the issue to a senior developer. The reply just came back and follows (with some minor formatting):

It (compiling) is not as simple as just a list of functions.

For a number of functions, some uses of the function are supported and others are not.

Thus, the list of functions is a starting point, but does not give the whole story. The following function is a simple test that tells you if a function can be compiled to stand alone C or not:

Needs["CCodeGenerator`"];

SetAttributes[CCompileQ, HoldAll];
CCompileQ[args__] := Module[{cf = Compile[args]},
   Check[CCodeStringGenerate[cf, "test",
     "CodeTarget" -> "WolframRTL"]; True, False, CCodeGenerate::wmreq]]

examples:

In[37]:= CCompileQ[{x}, x^2]
Out[37]= True

In[38]:= CCompileQ[{x}, f[x]]
Out[38]= False

During evaluation of In[38]:= CCodeGenerate::wmreq: The expression f requires Mathematica to be evaluated. The function will be generated but can be expected to fail with a nonzero error code when executed.

Note that the message will give one instance of something in the expression that could not be compiled to C.

share|improve this answer
    
Interesting response, but this engineer seems to be wrong. Are you sure the sales manager didn't write this (especially the last sentence) while claiming that an engineer has passed on the information? ;) Some of the listed functions are pre-compiled in the sense that there's a corresponding function in the Mathematica RTL that can be called directly from the VM, but there are counterexamples (e.g. Total which is missing from the first list even though it compiles down to a call to the internal function TotalAll) that show that this isn't a sufficient condition for their inclusion. –  Oleksandr R. Feb 7 '13 at 0:16
    
Also, many of the special functions, though numerical, cannot be compiled. MathieuCPrime is one that comes immediately to mind--and it even has the NumericFunction attribute. –  Oleksandr R. Feb 7 '13 at 0:25
    
@OleksandrR. -- I can go back to the sales manager with your thoughts. I'll also ask if the engineer can visit this question. –  Jagra Feb 7 '13 at 2:44
    
that would be very useful, because although I don't really have any doubts about the applicability of the list as an answer to this question, it's not clear to me how it's used internally by the compiler and whether every compilable function is given by either Compile`CompilerFunctions[] or as a downvalue of Internal`CompileValues. Information on how to modify the latter to enable the compilation of additional functions would be particularly helpful. I'm not sure who wrote the compiler but I think either Mark Sofroniou or Rob Knapp will probably be good people to ask. –  Oleksandr R. Feb 7 '13 at 14:38
3  
So, we've progressed from "the list isn't meaningful since anything can be compiled" to "only some functions are compilable, but the list is a partial description". That's better, although I had hoped for some information to be provided that we didn't know already. Anyway, thanks very much for taking the time to inquire! (BTW, I'm not sure why they focus so much on compilation to C. Not all compilable functions can be translated to C, e.g. Compile[{}, Label[1]; Goto[1]], which fails due to a bug in the CCodeGenerator` package.) –  Oleksandr R. Mar 5 '13 at 14:02

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.