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$

1 Answer 1

10
$\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$
    – MMA13
    Commented Jan 3, 2021 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$ Commented Jan 3, 2021 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$
    – MMA13
    Commented Jan 3, 2021 at 8:26
  • 1
    $\begingroup$ cf = myFun2[{x,y}] to get the compile function and then cf[1,1] to do the computation. $\endgroup$ Commented Jan 3, 2021 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$ Commented Jan 3, 2021 at 9:17

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.