Re: Compiled function not working

*To*: mathgroup at smc.vnet.net*Subject*: [mg110462] Re: Compiled function not working*From*: Bill Rowe <readnews at sbcglobal.net>*Date*: Sat, 19 Jun 2010 07:49:03 -0400 (EDT)

On 6/18/10 at 7:44 AM, myname_with_a_dot_inbetween at 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.