# Dealing with InterpolatingFunction in Compile

I have rather large equations that profit a lot from compiling, unfortunately they require input from external numerics and need to be interpolated.

In the end this costs a lot of performance as InterpolatingFunction triggers a MainEvaluate.

A minimal example:

testInt = Interpolation[{{0., 0.}, {2.5, 2.5}, {5., 5.}, {10., 10.}, {15.,
15.}}];

testCompile = With[{testInt = testInt},
Compile[{{x, _Real}, {a, _Real}},
testInt[a*x], CompilationTarget -> "C",
"RuntimeOptions" -> "Speed",
CompilationOptions -> {"InlineExternalDefinitions" -> True,
"InlineCompiledFunctions" -> True},
RuntimeAttributes -> {Listable}, Parallelization -> False
]];

CompilePrint[testCompile]

Out[3]= "
2 arguments
4 Real registers
Underflow checking off
Overflow checking off
Integer overflow checking off
RuntimeAttributes -> {Listable}

R0 = A1
R1 = A2
Result = R3

1   R2 = R1 * R0
2   R3 = MainEvaluate[ Hold[InterpolatingFunction[{{0., 15.}}, <>]][ R2]]
3   Return
"


The options are set as in the case of my application.

Is there any way to access circumvent this the non compilabilty of InterpolatingFunction by accessing for example the resulting piece wise polynomial?

• Have you seen this? Of course there are other methods of interpolation that InterpolatingFunction supports. Commented Mar 20, 2017 at 1:48
• Possibly you could rearrange your code such that all interpolation is done before passing that result as a packed array to the compiled function? Commented Mar 20, 2017 at 10:33
• @MichaelE2 sort of, it would boil down to writing my own compiled interpolation, which i will probably end up with. Commented Mar 20, 2017 at 12:26
• @user21 I don't quite understand what you mean. Commented Mar 20, 2017 at 12:26
• Yes, to be more specific the data/interpolation serves as an input for solving a differential equation and is only loaded once in the beginning. Commented Mar 20, 2017 at 14:43

Using existing code from here to extract the piece-wise polynomial from the interpolation and compile it.

data = MapIndexed[
Flatten[{#2, #1}] &, {2, 5, 9, 15, 22, 33, 50, 70, 100, 145, 200, 280, 375, 495, 635, 800, 1000, 1300, 1600, 2000, 2450, 3050, 3750, 4600, 5650, 6950}];

intF = Interpolation@data;
pwF[x_] = Piecewise[MapIndexed[{InterpolatingPolynomial[#1, x], x < 1 First[#2] + 2} &, Most[#]], InterpolatingPolynomial[Last@#1, x]] &@Partition[data, 4, 1];
compF = With[{}, Compile[{{x, _Real}}, Evaluate[N[pwf[x]]], CompilationTarget -> "C", "RuntimeOptions" -> "Speed", RuntimeAttributes -> {Listable}, CompilationOptions -> {"InlineExternalDefinitions" -> True}]];

compF[1.]//AbsoluteTiming
pwF[1.]//AbsoluteTiming
intF[1.]//AbsoluteTiming
{7.38984*10^-6,2.}
{0.0000640453,2.}
{0.0000225801,2.}


This solves the problem at hand and even speeds up the evaluation.

• Unfortunately, at least for me in 11.2, CompilePrint shows this too is bailing out to MainEvaluate Commented Jan 8, 2018 at 20:17
• @b3m2a1 wF = Which @@ Flatten[List[ MapIndexed[{x < 1 First[#2] + 2, InterpolatingPolynomial[#1, x]} &, Most[#]], {True, InterpolatingPolynomial[Last@#1, x]}] &@ Partition[data, 4, 1]]; then compF = With[{wF = wF}, Compile[{{x, _Real}}, wF, CompilationTarget -> "WVM", "RuntimeOptions" -> "Speed", RuntimeAttributes -> {Listable}, CompilationOptions -> {"InlineExternalDefinitions" -> True}]] Commented Jan 24, 2018 at 21:25