# How to use a list inside Compile—it says it should be a machine-size real number?

Super simple question, but I'm lost here.

f = Compile[{{a, _Real}, {b, _Real}, {c, _Real}},
x /. NSolve[a x^2 + b x + c == 0, {x}]]
f[1., -4., -5.]


gives the error

CompiledFunction::cfse: Compiled expression {-1.,5.} should be a machine-size real number.


But

g = Compile[{{a, _Real}, {b, _Real}, {c, _Real}},
x /. NSolve[a x^2 + b x + c == 0, {x}][[1]]]
g[1., -4., -5.]


works fine.

How do I type the result so that it knows it's a list. I haven't had any problems getting Compile to return a list before, and

h = Compile[{{a, _Real}, {b, _Real}, {c, _Real}},
sol = NSolve[a x^2 + b x + c == 0, {x}]; {x /. sol[[1]],
x /. sol[[2]]}]
h[1., -4., -5.]


gets around the issue, but there's got to be a better way than that.

This gives the same error, even though the output should be a real number. Somehow the list can't exist within the compiled function. I don't understand.

k = Compile[{{a, _Real}, {b, _Real}, {c, _Real}},
listofSolutions = x /. NSolve[a x^2 + b x + c == 0, {x}];
listofSolutions[[1]]]
k[1., -4., -5.]


Edited to add: I know NSolve isn't compilable; I'm trying to get the speed up from the typing of a, b, and c, among other things in my actual code.

• ReplaceAll and NSolve are not compilable. Just get rid of Compile. Jul 9 '20 at 19:00
• I don't know what speed-up you mean. Compile is likely to slow things down in this case. Compared to the slowness of NSolve, though, it will be negligible....Okay, I guess I can imagine a use-case that this would be reasonable. You should Block/Module/localize x, though, to protect the code when x has a global value. (And thanks for the accept. :) Jul 9 '20 at 19:25
• @MichaelE2 Maybe I'm mistaken, but I'm solving the same polynomial with different parameter values and I want to save that structure and feed in (typed) parameter values. I thought that Compile would help. And NSolve seems to take forever for sure. I've been trying to switch to Root with a few different starting points. Jul 9 '20 at 19:37
• You know about CompilePrint to inspect what the compiler is doing? (Needs@"CompiledFunctionTools"; CompilePrint[f]) Jul 9 '20 at 19:39

See my comment, but here goes:

f = Compile[{{a, _Real}, {b, _Real}, {c, _Real}},
x /. NSolve[a x^2 + b x + c == 0, {x}],
{{ReplaceAll[_, _], _Real, 1}}];  (* <-- return type declarations *)
f[1., -4., -5.]

(*  {-1., 5.}  *)


If you have many different kinds of calls to ReplaceAll, you can make more specific patterns. For example:

{{ReplaceAll[_, _NSolve], _Real, 1}}

• Thanks, I don't know how I could have figured that out on my own. Jul 9 '20 at 19:29
• @NathanRL You're welcome. It's the last paradigm at the top of the docs of Compile`, but it is documented elsewhere: See "External Calls" in the compiler tutorial Jul 9 '20 at 19:36