Re: multiple outputs from compiled function

*To*: mathgroup at smc.vnet.net*Subject*: [mg114698] Re: multiple outputs from compiled function*From*: Oliver Ruebenkoenig <ruebenko at wolfram.com>*Date*: Mon, 13 Dec 2010 03:53:24 -0500 (EST)

On Thu, 2 Dec 2010, Daniel Lichtblau wrote: > Eric Michielssen wrote: >> Thanks for the suggestion. >> >> I was thinking more about a routine that populates a huge sparse matrix, say >> for finite element analysis. SparseArray does not work within Compile, and >> that's understandable. >> >> So the next best thing would be to have a compiled function generate a long >> list of positions ( pos = {pos1,pos2,pos3...} with posi = {n1,n2} ) and a >> list of values ( val = {val1,val2,val3,...} ), and then construct the >> SparseArray externally to a compiled function. >> >> But how do I get my compiled function to return both pos and val? Upon >> reaching Return[{pos,val}], Mathematica reverts to the noncompiled function, >> in essence starting over from scratch. (I can only think of a few not so >> elegant solutions, none of which would apply in situations more complex than >> the above). >> >> Eric > > Seems weird, but you might just do the setting via external variable(s). > Here is a brief example. Notice that the list 'll' is not defined within > Compile, but it is used in a Part assignment therein. > > In[1]:= ll = {2., 3., 4.}; > > In[2]:= c = Compile[{{x}, {y}}, ll[[1]] = x; y]; > > In[3]:= c[4.5, 5.6] > Out[3]= 5.6 > > In[4]:= ll > Out[4]= {4.5, 3., 4.} > > Daniel Lichtblau > Wolfram Research > > To be quite honest I pretty much completely missed the point and implications of Daniel's post and only "got it" when I received another email from a colleague. So I thought I share what I leaned perhaps this is useful to others too. cf = Compile[{{n, _Integer}, {m, _Integer}}, Module[ {cpos = RandomSample[Range[n], m]}, Set[pos, cpos]; RandomReal[1, Length[cpos]] ] ]; The above compiled function computes some function and stores the result in cpos. Then pos - which is a variable not in the Module scope - is set to cpos and some other result is returned from the compiled function. Wrapping the compiled function in, say, a Block {valres, posres} = Block[{pos}, {cf[10, 5], pos}] allows for two multiple values to be returned. Map[Developer`PackedArrayQ, %] if we look at this compiled function << "CompiledFunctionTools`" CompilePrint[cf] We see a call to MainEvaluate. Here the main cost is the copy of the cpos data and in a big function that would be negligible. It needs to copy the cpos since you could have something like this: cf = Compile[{{n, _Integer}, {m, _Integer}}, Module[{cpos = RandomSample[Range[n], m]}, Set[pos, cpos]; cpos[[1]] = 1; RandomReal[1, Length[cpos]]]]; This is mechanism that allows for multiple values to be returned from a compiled function. Hope this helps, Oliver