Re: Re: Nested iterators in Compile

*To*: mathgroup at smc.vnet.net*Subject*: [mg55068] Re: [mg55032] Re: [mg55010] Nested iterators in Compile*From*: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>*Date*: Fri, 11 Mar 2005 04:20:44 -0500 (EST)*Sender*: owner-wri-mathgroup at wolfram.com

Hi Christoph, I'll give my comments interspersed >-----Original Message----- >From: Christoph Lhotka [mailto:lhotka at astro.univie.ac.at] To: mathgroup at smc.vnet.net >Sent: Thursday, March 10, 2005 11:25 AM >Subject: [mg55068] [mg55032] Re: [mg55010] Nested iterators in Compile > >Hello ! > >I would define your compiled function this way: > >In[..]:=g = Compile[{{n, _Integer}}, Module[{i, j, s = 0}, > Do[s += j, {i, n}, {j, i}]; > Print[s]], {{s, _Integer}, {i, _Integer}, {j, _Integer}}] > >(see Help Browser for more details on how to declare variables inside >subexpressions at the end of Compile) > Defining types for s,i,j wasn't the problem, the compiler can find out! >The problem is, that you will get a similar error message, >when you do not >define initial values for i and j, but the function worked, as >you can see >here: > >In[..]:= g[100] >Out[..]:=171700 > In contrast to Maxim, you got your errors at compile time, but the compiled code seemed to work. But never ignore error messages: in fact because of your declarations of i, j within module, the compiler wasn't abe to compile the loop at all, because the i of Module was chosen as the ending value for j of the inner loop and that had no value, so the compiler cave up and inserted a function call to the uncompiled Do-oop into the incompiled code. Be aware that the i,j in Module are different from the i,j in Do because of scoping for the iteration variables. Check out in the Book! In fact the compiler doesn't follow the correct scoping rules, seems to be the root of the problem! >To suppress the error message I defined a value for i and j, >which should not >be wrong, because, i and j are set inside the do - loop. But >there seems to be >a serious problem with it: > >In[..]:=In[..]:=g = Compile[{{n, _Integer}}, Module[{i=0, j=0, s = 0}, > Do[s += j, {i, n}, {j, i}]; > Print[s]], {{s, _Integer}, {i, _Integer}, {j, _Integer}}] > >any time, I use the function, it will nothing else return, but 0.. > >In[..]:=g[10/50/100/...] >Out[..]:=0 > >for any other initial value for i I get different results, so... > Yes this is because the i chosen by the compiler has a (constant) value, and compiles with that; the result is the (wrong) function you got. >HOW CAN THE INITIAL VALUE FOR I INFLUENCE THE RESULT OF THE DO - LOOP? > >as you can see in an uncompiled version, this should not >influence anything: > >In[..]:=G[n_] := Module[{i = 5, j = 3, s = 0}, Do[s += j, {i, >n}, {j, i}]; >Print[s]] > >In[..]:=G[100] >Out[..]:=171700 > >Can anyone give some more explanation to this problem, some >more information >on how the function compile really works? > > [...] Who knows? Here is my speculation (following Matt Cook, Mathematica Conference 1992): In[173]:= g = Compile[{{n, _Integer}}, Module[{s = 0}, Do[Do[s += j, {j, i}], {i, n}]; s]] Out[173]= CompiledFunction[{n}, Module[{s = 0}, Do[Do[s += j, {j, i}], {i, n}]; s], "-CompiledCode-"] In[174]:= g[[1]] Out[174]= {_Integer} A list of the types of the arguments. In[175]:= g[[2]] Out[175]= {{2, 0, 0}, {2, 0, 1}} interface definition: input integer dim 0 to reg (0); output integer dim from reg (1) In[176]:= g[[3]] Out[176]= {0, 7, 0, 0, 0} number of registers in use {boolean, integer, real, complex, ??} In[177]:= g[[4]] Out[177]= {{1, 4}, {4, 0, 1}, {9, 0, 2}, {4, 0, 3}, {81, 3, 2, 8}, {9, 3, 4}, {4, 0, 5}, {81, 5, 4, 4}, {24, 1, 5, 6}, {9, 6, 1}, {44, -3}, {44, -7}, {2}} compiled instructions In[178]:= g[[5]] Out[178]= Function[{n}, Module[{s = 0}, Do[Do[s += j, {j, i}], {i, n}]; s]] Uncompiled code In[182]:= g[3] Out[182]= 10 Now here my speculation: In[84]:= g[[4]] // ColumnForm (the input is in reg 0) begin #4 load const 0 into reg 1 move reg 0 to reg 2 load const 0 into reg 3 if ++reg 3 > reg 2 then jump +8 move reg 3 to reg 4 load const 0 into reg 5 if ++reg 5 > reg 4 then jump +4 add reg 1, regi 5 and store to reg 6 move reg 6 to reg 1 jump -3 jump -7 return (returned is reg 1) -- Hartmut Wolf