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
a workaround could be to use LibraryFunctionLoad and use the "Shared"
attribute.
Oliver
>
> Eric Michielssen
>
>
>
>
Not to my knowledge. I agree this mutability would be a really nice
capability to have. I have wanted it myself since almost forever. Well,
at least since the time I posted the message at the URL below.
http://forums.wolfram.com/mathgroup/archive/2001/Feb/msg00195.html
We have discussed the desire for call-by-reference, or something else
that might allow for mutability of arrays, within Compile. People here
seem toa gree it could be very useful. But I do not know whether we will
attempt to go in this direction, or what might be the design or
implementation issues (I suspect neither is trivial).
One thing that might be new to version 8 is an ability to pass large
arrays in Compile and not have them automatically copied. It is only
when one needs to alter them that a copy is needed. So it is possible to
invoke what amount to subroutines (that is, Compile calling functions
that are also defined via Compile), using parge arrays as arguments, and
not suffering a time or memory penalty. But again, this only holds if
the arrays are not to be modified. I'm told some code along these lines
might appear in an upcoming Wolfram blog.
Daniel Lichtbau
Wolfram Research
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
<emic...@eecs.umich.edu>wrote: