2
$\begingroup$

I'm sure there is an easy solution to this, but I have beaten my head against a wall for a couple of days, so I hope someone can help.

I have compiled functions. For a minimal example let's take:

fn1 = Compile[{{t, _Real}, {x, _Real}}, Sin[t x]];
fn2 = Compile[{{t, _Real}, {x, _Real}}, Cos[t x]];

The list of functions I want to plot is dynamic, so I cannot explicitly list them. We can model this using Through, though there are many ways to do this:

Plot[Through[{fn1, fn2}[3, x]], {x, 0, 10}]

But this plots both curves with the same color because with the Hold attribute of Plot, the head Through evaluates as a single item. The standard way to fix this problem is to use Evaluate:

Plot[Evaluate@Through[{fn1, fn2}[3, x]], {x, 0, 10}]

But this gives errors:

CompiledFunction: Argument x at position 2 should be a machine-size real number.

Clearly this is because MMA is trying to Evaluate the x before a value has been assigned to it by Plot. How can we avoid this problem (other than just suppressing the warning messages)?

$\endgroup$

2 Answers 2

4
$\begingroup$

You could try using Inactive/Activate, e.g.:

With[{in = {fn1, fn2} /. CompiledFunction -> Inactive[CompiledFunction]},
    Activate @ Inactive[Plot][Through[in[3, x]], {x, 0, 10}]
]

enter image description here

$\endgroup$
1
  • $\begingroup$ Very nice! This opens up a whole new world for me! $\endgroup$ Commented Aug 28, 2019 at 21:50
0
$\begingroup$

And the power of the post.

Plot[Evaluate@(Hold[#[3, x]] & /@ {fn1, fn2}), {x, 0, 10}]
$\endgroup$
1
  • 1
    $\begingroup$ This relies on the undocumented feature that Hold wrappers get automatically stripped by Plot. There is no guarantee that this feature will not be removed in the future. $\endgroup$
    – Carl Woll
    Commented Aug 28, 2019 at 21:36

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.