5
$\begingroup$

Here is a minimal example to the problem I face when using Compile with Block:

G1[x_, y_]:=Block[{ks = x y, id = Sin[x y]}, {(id - ks), (id + ks)}]
myFun = Compile[{{x, _Real}, {y, _Real}},Block[{f = G1[x, y]}, f[[1]] x + f[[2]]],
   CompilationTarget -> "C"];

Once I run this code I get this error:

Compile::part: Part specification f[[1]] cannot be compiled since the argument is not a tensor of sufficient rank. Evaluation will use the uncompiled function.

How can I get rid of it?

$\endgroup$
9
$\begingroup$

This is an old and rather often discussed issue. The output of

CompiledFunctionTools`CompilePrint[myFun]

contains

MainEvaluate[ Hold[G1][ R0, R1]]

and this tells us that G1 has not been inlined correctly. Best way to circumvent this issue is to use With for inlining:

G1[x_, y_] := Block[{ks = x y, id = Sin[x y]}, {(id - ks), (id + ks)}]
myFun = With[{f = G1[x, y]},
   Compile[{{x, _Real}, {y, _Real}},
    f[[1]] x + f[[2]],
    CompilationTarget -> "C"
    ]
   ];
$\endgroup$
6
  • $\begingroup$ Thanks a lot! Is it possible to use := with compile? like this myFun2[fun_] := With[{f = G1[x, y]},Compile[{{x, _Real}, {y, _Real}}, fun.(f[[1]] x + f[[2]]), CompilationTarget -> "C"]];. fun are many different long and complicated function with respect to (x,y) that I would like to compile each of them. $\endgroup$ – valar morghulis Jan 3 at 8:05
  • 1
    $\begingroup$ You're welcome. Well again, it should work if you use With for inlining. Like in myFun2[fun_] := With[{code = fun.(G1[x, y][[1]] x + G1[x, y][[2]])}, Compile[{{x, _Real}, {y, _Real}}, code, CompilationTarget -> "C"]];. $\endgroup$ – Henrik Schumacher Jan 3 at 8:18
  • $\begingroup$ Just one more question, please? How can I get the results for fun=x y and at point (x,y)=(1,1). $\endgroup$ – valar morghulis Jan 3 at 8:26
  • 1
    $\begingroup$ cf = myFun2[{x,y}] to get the compile function and then cf[1,1] to do the computation. $\endgroup$ – Henrik Schumacher Jan 3 at 8:28
  • 2
    $\begingroup$ Well, you wrote fun.(f[[1]] x + f[[2]]). . means Dot. So of course fun and f[[1]] x + f[[2]] have to be things that can be Dotted against each other, i.e., tensors. Obviously, fun = x is not a tensor -- you told your compiled function that x is a real scalar. $\endgroup$ – Henrik Schumacher Jan 3 at 9:17

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.