MathGroup Archive 2010

[Date Index] [Thread Index] [Author Index]

Search the Archive

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.



  • Prev by Date: Re: Simplifying complicated expressions
  • Next by Date: Help defining options; selecting particular version of a function;
  • Previous by thread: Compiled function not working
  • Next by thread: Bar chart style with ListPlot