3
$\begingroup$

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.

$\endgroup$
4
  • 1
    $\begingroup$ ReplaceAll and NSolve are not compilable. Just get rid of Compile. $\endgroup$
    – Michael E2
    Jul 9 '20 at 19:00
  • $\begingroup$ 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. :) $\endgroup$
    – Michael E2
    Jul 9 '20 at 19:25
  • $\begingroup$ @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. $\endgroup$
    – NathanRL
    Jul 9 '20 at 19:37
  • 2
    $\begingroup$ You know about CompilePrint to inspect what the compiler is doing? (Needs@"CompiledFunctionTools`"; CompilePrint[f]) $\endgroup$
    – Michael E2
    Jul 9 '20 at 19:39
3
$\begingroup$

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}}
$\endgroup$
2
  • $\begingroup$ Thanks, I don't know how I could have figured that out on my own. $\endgroup$
    – NathanRL
    Jul 9 '20 at 19:29
  • 1
    $\begingroup$ @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 $\endgroup$
    – Michael E2
    Jul 9 '20 at 19:36

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.