Prev: Floating point exception when taking a reciprocal of a list in v.
Next: Help defining options; selecting particular version of a function;
From: Fred Bartoli on 18 Jun 2010 07:44 Hello, I've a function that I need compiled for better performances. ZsNoR[n_]=(3 4^(1+n))/(2+4^(1+n)) cf=Compile[{{code,_Integer},{nb,_Integer}},Module[{SwList=Reverse(a)IntegerDigits[code,2,nb]},\!\( \*UnderoverscriptBox[\(\[Sum]\), \(i = 0\), \(nb - 1\)] \*FractionBox[\(1\), \(ZsNoR[Part[SwList, i + 1]]\)]\)]] cf[128,8] But when I evaluate cf I get a "CompiledFunction::cfse: Compiled expression 8/3 should be a machine-size integer" error message that make no sense to me. What am I doing wrong? -- Thanks, Fred.
From: Bill Rowe on 19 Jun 2010 07:48
On 6/18/10 at 7:44 AM, myname_with_a_dot_inbetween(a)free.fr (Fred Bartoli) wrote: >I've a function that I need compiled for better performances. >ZsNoR[n_]=(3 4^(1+n))/(2+4^(1+n)) >cf=Compile[{{code,_Integer},{nb,_Integer}},Module[{SwList=Reverse@ >IntegerDigits[code,2,nb]},\!\( \*UnderoverscriptBox[\(\[Sum]\), \(i >= 0\), \(nb - 1\)] \*FractionBox[\(1\), \(ZsNoR[Part[SwList, i + >1]]\)]\)]] >cf[128,8] >But when I evaluate cf I get a "CompiledFunction::cfse: Compiled >expression 8/3 should be a machine-size integer" error message that >make no sense to me. >What am I doing wrong? When I paste your code into a fresh session, I get a result of 31/8 and a warning stating the external function at step 9 could not be compiled and the evaluation was proceeding uncompiled. That is, I cannot reproduce the error message you are getting. Note, from a perspective of speed, your code has several inefficiencies. In the sum, you index from 0 to nb-1 then in Part you add 1. More efficient would be to index from 1 to nb and avoid adding 1. You also reverse the order of the digits returned by IntegerDigits. But the sum you are computing doesn't depend on order. So, there is no need for using Reverse. So your function cf could be re-written as: In[11]:= h = Compile[{{code, _Integer}, {nb, _Integer}}, Module[{sw = IntegerDigits[code, 2, nb]}, Sum[(4^(sw[[n]] + 1) + 2)/(3 4^(sw[[n]] + 1)), {n, nb}]]]; In[12]:= h[128, 8] Out[12]= 3.875 Here, I also eliminated the 1/ZsNor step by re-writing your ZsNor as the inverse. And by including the expression directly, the code compiles and evaluates as compiled since it no longer depends on an external function. Even further improvements can be made. Since you are converting one integer to binary digits, the ZsNor function can only be either 2 or 8/3. So, the sum can be re-written as 3 cnt/8 + (nb - cnt)/2 where cnt is the number of 1s in the binary representation. This last can be simplified to 1/8(4 nb - cnt) So, your compiled function can be re-written as: cf2 = Compile[{{code, _Integer}, {nb, _Integer}}, (4 nb - Total[IntegerDigits[code, 2, nb]])/8] This will execute faster since it takes avantage of Mathematica's vector processing and has Mathematica do less to get the same result. |