Re: Non-numeric arguments to Compile-d functions

*To*: mathgroup at smc.vnet.net*Subject*: [mg82131] Re: Non-numeric arguments to Compile-d functions*From*: Szabolcs Horvát <szhorvat at gmail.com>*Date*: Sat, 13 Oct 2007 03:44:42 -0400 (EDT)*References*: <fen75j$5bi$1@smc.vnet.net>

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