Karim BELABAS on Fri, 12 Nov 1999 20:09:40 +0100 (MET)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: dilog() bug


[Michael Somos:]
> gp> polylog(2,10)
> %1 = 0.5363012873578627365501597698 - 7.233784412415464812490046550*I
> gp> dilog(10) 
> %2 = 0.5363012873578627365501597699 - 7.233784412415464812490046550*I
> gp> \ps3
>    seriesprecision = 3 significant terms
> gp> polylog(2,x)
> %3 = x + 1/4*x^2 + O(x^3)
> gp> dilog(x)
>   ***   incorrect type in comparison.
> 
> It seems to me that polylog(2,x) and dilog(x) shuould give essentially
> the same answer for any value of x. In fact, I would define it as follows:
> 
> dilog(x)=polylog(2,x)
> 
> Any reason why this is not the case?

The functional equation (relating values at x and 1/x) can be written in a
(slightly) more efficient way when m = 2. But in fact, the way it was
written, it became (slightly) _less_ efficient (to save 3 multiplications,
one ordinary logarithm had to be recomputed...).

I trivialized dilog() the way you suggested and special cased m = 2 in
polylog(), rewriting the optimization so that it works as intended (skipping
the log computation). The patch is big, since I cleaned up the neighbouring
code.

   Karim.

Index: src/basemath/trans3.c
===================================================================
RCS file: /home/megrez/cvsroot/pari/src/basemath/trans3.c,v
retrieving revision 1.2
diff -c -r1.2 trans3.c
*** src/basemath/trans3.c	1999/09/23 17:50:57	1.2
--- src/basemath/trans3.c	1999/11/12 19:05:00
***************
*** 809,885 ****
  GEN
  polylog(long m, GEN x, long prec)
  {
!   long av,av1,limpile,tetpil,l,e,sx,i;
!   GEN p1,p2,n,y,logx,logx2;
!   GEN *gptr[4];
  
    if (m<0) err(talker,"negative index in polylog");
    if (!m) return gneg(ghalf);
    if (gcmp0(x)) return gcopy(x);
!   av=avma;
    if (m==1)
!   {
!     p1=glog(gsub(gun,x),prec); tetpil=avma;
!     return gerepile(av,tetpil,gneg(p1));
!   }
!   l=precision(x);
    if (!l) { l=prec; x=gmul(x, realun(l)); }
!   e=gexpo(gnorm(x)); if (!e || e== -1) return cxpolylog(m,x,prec);
!   if (e>0)
    {
!     logx=glog(x,l); sx=gsigne(gimag(x));
      if (!sx)
      {
!       if (m&1)
!         sx = gsigne(greal(gsub(gun,x)));
!       else
!         sx = -gsigne(greal(x));
      }
!     x=ginv(x);
    }
    av1=avma; limpile=stack_lim(av1,1);
!   y=x; n=gun; p1=x;
!   do
    {
!     n=addsi(1,n); p1=gmul(x,p1); p2=gdiv(p1,gpuigs(n,m));
!     y=gadd(y,p2);
      if (low_stack(limpile, stack_lim(av1,1)))
!     {
        if(DEBUGMEM>1) err(warnmem,"polylog");
!       gptr[0]=&y; gptr[1]=&n; gptr[2]=&p1; gptr[3]=&p2;
!       gerepilemany(av1,gptr,4);
      }
    }
!   while (gexpo(p2) > -bit_accuracy(l));
!   tetpil=avma;
!   if (e<=0) return gerepile(av,tetpil,gcopy(y));
!   logx2=gsqr(logx); p1=gneg_i(ghalf);
!   for (i=m-2; i>=0; i-=2)
    {
!     p1 = gadd(izeta(m-i,l), gmul(p1,gdivgs(logx2,(i+1)*(i+2))));
    }
!   if (m&1) p1 = gmul(logx,p1);
!   p2=cgetg(3,t_COMPLEX); p2[1]=zero;
!   p2[2]=ldiv(gmulsg(sx,mppi(l)),mpfact(m-1));
!   p1=gadd(gmul2n(p1,1), gmul(p2,gpuigs(logx,m-1)));
!   if ((m&1) == 0) y = gneg_i(y);
!   tetpil=avma; return gerepile(av,tetpil,gadd(p1,y));
  }
  
  GEN
  dilog(GEN x, long prec)
  {
!   GEN p1,p2,p3,y;
!   long av=avma,tetpil;
! 
!   if (gcmpgs(gnorm(x),1)<1)
!   {
!     tetpil=avma; return gerepile(av,tetpil,polylog(2,x,prec));
!   }
!   y=gneg_i(polylog(2,ginv(x),prec)); p3=mppi(prec); p2=gdivgs(gsqr(p3),6);
!   p1=glog(gneg_i(x),prec); p1=gadd(p2,gmul2n(gsqr(p1),-1));
!   p1 = gneg_i(p1); tetpil=avma;
!   return gerepile(av,tetpil,gadd(y,p1));
  }
  
  GEN
--- 809,883 ----
  GEN
  polylog(long m, GEN x, long prec)
  {
!   long av,av1,limpile,l,e,i,G;
!   GEN z,p1,p2,n,y,logx;
  
    if (m<0) err(talker,"negative index in polylog");
    if (!m) return gneg(ghalf);
    if (gcmp0(x)) return gcopy(x);
!   av = avma;
    if (m==1)
!     return gerepileupto(av, gneg(glog(gsub(gun,x), prec)));
! 
!   l = precision(x);
    if (!l) { l=prec; x=gmul(x, realun(l)); }
!   e = gexpo(gnorm(x)); if (!e || e== -1) return cxpolylog(m,x,prec);
!   if (e > 0)
    {
!     long sx = gsigne(gimag(x));
!     logx = glog(x,l);
      if (!sx)
      {
!       if (m&1) sx = gsigne(gsub(gun,greal(x)));
!       else     sx = - gsigne(greal(x));
      }
!     z = cgetg(3,t_COMPLEX);
!     z[1] = zero;
!     z[2] = ldivri(mppi(l), mpfact(m-1));
!     if (sx < 0) z[2] = lnegr((GEN)z[2]);
!     x = ginv(x);
    }
+   G = -bit_accuracy(l);
+   n = icopy(gun);
    av1=avma; limpile=stack_lim(av1,1);
!   y=x; p1=x;
!   for (i=2; ; i++)
    {
!     n[2] = i; p1 = gmul(x,p1); p2 = gdiv(p1,gpuigs(n,m));
!     y = gadd(y,p2);
!     if (gexpo(p2) <= G) break;
! 
      if (low_stack(limpile, stack_lim(av1,1)))
!     { GEN *gptr[2]; gptr[0]=&y; gptr[1]=&p1;
        if(DEBUGMEM>1) err(warnmem,"polylog");
!       gerepilemany(av1,gptr,2);
      }
    }
!   if (e < 0) return gerepileupto(av, y);
! 
!   if (m == 2)
!   { /* same formula as below, written more efficiently */
!     y = gneg_i(y);
!     p1 = gmul2n(gsqr(gsub(logx, z)), -1); /* = (log(-x))^2 / 2 */
!     p1 = gadd(divrs(gsqr(mppi(l)), 6), p1);
!     p1 = gneg_i(p1);
!   }
!   else
    {
!     GEN logx2 = gsqr(logx); p1 = gneg_i(ghalf);
!     for (i=m-2; i>=0; i-=2)
!       p1 = gadd(izeta(m-i,l), gmul(p1,gdivgs(logx2,(i+1)*(i+2))));
!     if (m&1) p1 = gmul(logx,p1); else y = gneg_i(y);
!     p1 = gadd(gmul2n(p1,1), gmul(z,gpuigs(logx,m-1)));
    }
! 
!   return gerepileupto(av, gadd(y,p1));
  }
  
  GEN
  dilog(GEN x, long prec)
  {
!   return gpolylog(2, x, prec);
  }
  
  GEN
__
Karim Belabas                    email: Karim.Belabas@math.u-psud.fr
Dep. de Mathematiques, Bat. 425
Universite Paris-Sud             Tel: (00 33) 1 69 15 57 48
F-91405 Orsay (France)           Fax: (00 33) 1 69 15 60 19
--
PARI/GP Home Page: http://hasse.mathematik.tu-muenchen.de/ntsw/pari/