I am trying to do something similar to this, namely to make a Compile
'd function outer
that itself calls a Compile
'd function inner
which accesses a variable defined in outer
. Copy-pasting the example Leonid gives in the link, I get no errors. However in my case, I want inner
to be a recursive function.
So far I have tried (the functions are toy examples):
Clear[inner];
inner = Compile[ {{i, _Integer}, {j, _Integer}},
If[i >= j, Return[], AppendTo[bag, list]; inner[i + 1, j]];
,CompilationOptions -> {"InlineExternalDefinitions" -> True,
"InlineCompiledFunctions" -> False} ]
and
Clear[outer];
outer = Compile[{{i, _Integer}},
Block[{list = Table[{0, 0}, {i}], bag},
bag = {list};
inner[1, i];
bag
]
, CompilationOptions -> {"InlineExternalDefinitions" -> True,
"InlineCompiledFunctions" -> True}
]
Trying to execute this last piece results in the error message:
Compile::cret : The type of return values in (...) are different.
Evaluation will use the uncompiled function.
I have a hard time interpreting the output of CompilePrint
in this case, so I cannot pinpoint the error in order to move further with this. Since I am able to create compiled recursive functions just fine in general, and the link provides a "hack" to make inner
see the variables in outer
, I think it should be possible to do this, but perhaps not...
EDIT: I have verified that the lingering MainEvaluate
is not due AppendTo
or some-such, by making the function inner
even more basic. I have also tried all possible combinations of True
/False
for the CompilationOptions
for both inner
and outer
with no success. So it seems to me that it's possible to compile either a recursive function, or a compiled function modifying a "global" variable when called from another compiled function, but not both =(
LevelsNeeded=Compile[ {{b,_Integer},{M,_Integer},{x,_Integer}}, If[M<=(x*b+Quotient[x(x-1),2]),x,LevelsNeeded[b,M,x+1]] ,{{_LevelsNeeded,_Integer}} ,CompilationOptions->{"InlineExternalDefinitions"->True,"InlineCompiledFunctions"->False} ,CompilationTarget->"C",RuntimeOptions->"Speed" ];
If I call this twice, I see no MainEvaluate-calls, and it's very fast. $\endgroup$LevelsNeeded = Compile[{{b, _Integer}, {M, _Integer}, {x, _Integer}}, If[M <= (x*b + Quotient[x (x - 1), 2]), x, LevelsNeeded[b, M, x + 1]], {{_LevelsNeeded, _Integer}}, CompilationOptions -> {"InlineExternalDefinitions" -> True}, CompilationTarget -> C];
. $\endgroup$