Re: Pass by reference for compiled functions

*To*: mathgroup at smc.vnet.net*Subject*: [mg114317] Re: Pass by reference for compiled functions*From*: Leonid Shifrin <lshifr at gmail.com>*Date*: Wed, 1 Dec 2010 02:09:27 -0500 (EST)

Hi Eric, You can also kind of emulate pass-by-reference by inlining compiled functions, but this will only work if your caller function is also Compiled, and all the ingredients are compiled. Here is an example: Clear[primeQ ]; primeQ = Compile[{{n, _Integer}}, Total[1 - Unitize@Mod[n, Range[2, IntegerPart[Sqrt[n]] + 1]]] == 0]; ClearAll[primes]; primes = Compile[{}, list = Select[list, primeQ], CompilationOptions -> {"InlineExternalDefinitions" -> True, "InlineCompiledFunctions" -> True}]; test = Compile[{}, Module[{list = Range[100000]}, primes[]; list], CompilationOptions -> {"InlineExternalDefinitions" -> True, "InlineCompiledFunctions" -> True}]; In[87]:= test[]//Short//Timing Out[87]= {0.828,{1,3,5,7,11,13,17,19,23,29,31,<<9570>>,99871,99877,99881,99901,99907,99923,99929,99961,99971,99989,99991}} Note that the variable <list> has not been defined in <primes>, so <primes> works essentially like a macro. At the end, everything is inlined inside <test>, and for this to work, this must have happened before the variables are bound. So, we actually do change the variable <list> defined in <test>, even though it is done inside <primes>. At the same time, the global <list> does not acquire any value. But this would not work if <primes> would not have entirely compiled - for instance, if you change primeQ (compiled) to PrimeQ (uncompiled, built-in, external call). You can inspect the final compiled code for <test> by calling test[[6]] and see that it indeed did compile completely to byte-code. In particular, you should be able to compile to C if needed. So, this is not the true pass-by-reference since no arguments are passed explicitly, but this seems to give similar means of combining larger programs from smaller pieces without copying data, more like templates. I am not sure about the status of this "technique", I just discovered it recently - this looks more like a hack to me, but it seems to work. Hope this helps. Regards, Leonid On Mon, Nov 29, 2010 at 2:10 PM, Eric Michielssen <emichiel at eecs.umich.edu>wrote: > For noncompiled functions, one can pass arguments "by reference" and then > modify them inside the routine by assigning the function the attribute > HoldAll. > > This does not work for compiled functions: it does not appear possible to > modify arguments to compiled functions, even if they are passed as "global > variables". That is, Mathematica responds to > > Myfunction = Compile[ > {{var1,_Real}}, > Module[{}, > Modify var 1 or var2; > Return[]], {var2,_Real}]; > > With > > Compile::argset: The assignment to var1 is illegal; it is not valid to > assign a value to an argument. >> And something similar for var2. > > HoldAll does not seem to apply here... > > This makes it memory-inefficient to modify large arrays in compiled > functions, as one would have to operate on a copy of the array. > > Is there a workaround in Mathematica 8? > > Eric Michielssen > > > >