Andrew Moylan wrote:
> Here's a compiled function that does some (made-up) operation on a
> real-valued function f:
>
> Compile[{},
> Do[If[f[i] < 0, Return[{i, f[i]}]], {i, 10}],
> {{f[_], _Real}}
> ]
>
> (It finds the first integer i such that f[i] is negative.)
>
> For the usual reasons of modularity, I would like to make compiled functions
> like this not refer to global variables named f. (We can't put f as one of
> the elements of the first argument to compile, because those must all be
> numeric scalars or arrays.)
>
> Here's one way to do this:
>
> Module[
> {f, compiledpart},
>
> compiledpart = Compile[{},
> Do[If[f[i] < 0, Return[{i, f[i]}]], {i, 10}],
> {{f[_], _Real}}
> ];
>
> findfirstnegative[tempf_] := (compiledpart /. f -> tempf)[]
> ]
>
> I don't really like this solution because we needed to use two names (f and
> tempf). Using two names per argument could get messy if there are several
> non-numeric arguments instead of just f.
>
> Is this the recommended method for compiling "as much of a function as
> possible"?
>
> Note that the following attempt (which doesn't need a tempf) doesn't work:
>
> With[{rhs = compiledpart}, findfirstnegative[f_] := rhs]
>
> It fails because Mathematica automatically renames the f in the
> CompiledFunction in compiledpart to *avoid* the very naming clash I am
> trying to create. The With statement effectively creates:
>
> findfirstnegative[f$_] := CompiledFunction[{},
> Do[If[f$851[i]<0, Return[{i,f$851[i]}]], {i,10}],
> -CompiledCode-
> ]
>
> What's the neatest, "right" way to make compiled functions that take
> non-numeric arguments?
>
>
Hi Andrew,
What's wrong with simply using the following?
fun[f_] = Compile[{}, Do[If[f[i] < 0, Return[{i, f[i]}]], {i, 10}],
{{f[_], _Real}}]
findfirstnegative[f_Function] := fun[f][]
Of course you have to make sure that 'f' is not defined before you issue
these definitions, but this is not a problem when you are developing a
package.
I believe that Module and With weren't meant to be used in this way
(i.e. to define new functions *inside* them). When you create packages,
use contexts to isolate those symbols which should not be exported.
But to be honest, I'm a bit tired now and it is possible that I
misunderstood your question ...
--
Szabolcs