From: Fred Bartoli on
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
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.