Math-Cephes

 view release on metacpan or  search on metacpan

libmd/polylog.c  view on Meta::CPAN

static short A4[52] = {
0x3f9f,0x4b80,0x23b0,0x3d29,
0x3fd4,0xc179,0x0fb0,0x7fa6,
0x3fd2,0x6b10,0xa2eb,0x45a8,
0x3fb2,0x2755,0x5046,0x8d61,
0x3f7a,0x7c93,0x2883,0x71d4,
0x3f30,0x0ecf,0x118c,0x37ac,
0x3ed0,0xe8f4,0xfcf7,0x4b5c,
0x3e5e,0xf7f1,0x9edf,0xce99,
0x3dd7,0xdc0d,0xdc57,0xc710,
0x3d3c,0xe0fd,0x54c8,0xcd17,
0x3c88,0x677f,0x1c0f,0x7fe8,
0x3bb7,0x6b92,0xc6f8,0x96ab,
0x3ac0,0x6494,0x9f50,0xaa8e,
};
static short B4[48] = {
  /*0x3ff0,0x0000,0x0000,0x0000,*/
0x4006,0x91f2,0x05e7,0x2e77,
0x3ffc,0x7bc9,0x2570,0x37d6,
0x3fd8,0x2f54,0x9821,0x5c12,
0x3fa0,0x5a4a,0xa7af,0x4bce,
0x3f53,0x06a5,0x4a3a,0xfc75,
0x3ef3,0x94a9,0xa71a,0x7eb2,
0x3e81,0xb420,0xb4f6,0x00ce,
0x3dfb,0x182b,0x1c44,0xba10,
0x3d60,0x573c,0xe32c,0x40a9,
0x3cab,0x92f6,0xc77b,0x077b,
0x3bda,0x721c,0x6851,0xe1fe,
0x3ae2,0x81e1,0x5f6f,0xbc13,
};
#endif

#ifdef ANSIPROT
extern double spence ( double );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double zetac ( double );
extern double md_pow ( double, double );
extern double md_powi ( double, int );
extern double md_log ( double );
extern double fac ( int i );
extern double md_fabs (double);
double polylog (int, double);
#else
extern double spence(), polevl(), p1evl(), zetac();
extern double md_pow(), md_powi(), md_log();
extern double fac(); /* factorial */
extern double md_fabs();
double polylog();
#endif
extern double MACHEP;

double
polylog (n, x)
     int n;
     double x;
{
  double h, k, p, s, t, u, xc, z;
  int i, j;

/*  This recurrence provides formulas for n < 2.

    d                 1
    --   Li (x)  =   ---  Li   (x)  .
    dx     n          x     n-1

*/

  if (n == -1)
    {
      p  = 1.0 - x;
      u = x / p;
      s = u * u + u;
      return s;
    }

  if (n == 0)
    {
      s = x / (1.0 - x);
      return s;
    }

  /* Not implemented for n < -1.
     Not defined for x > 1.  Use cpolylog if you need that.  */
  if (x > 1.0 || n < -1)
    {
      mtherr("polylog", DOMAIN);
      return 0.0;
    }

  if (n == 1)
    {
      s = -md_log (1.0 - x);
      return s;
    }

  /* Argument +1 */
  if (x == 1.0 && n > 1)
    {
      s = zetac ((double) n) + 1.0;
      return s;
    }

  /* Argument -1.
                        1-n
     Li (-z)  = - (1 - 2   ) Li (z)
       n                       n
   */
  if (x == -1.0 && n > 1)
    {
      /* Li_n(1) = zeta(n) */
      s = zetac ((double) n) + 1.0;
      s = s * (md_powi (2.0, 1 - n) - 1.0);
      return s;
    }

/*  Inversion formula:
 *                                                   [n/2]   n-2r
 *                n                  1     n           -  md_log    (z)
 *  Li (-z) + (-1)  Li (-1/z)  =  - --- md_log (z)  +  2  >  ----------- Li  (-1)
 *    n               n              n!                -   (n - 2r)!    2r
 *                                                    r=1
 */
  if (x < -1.0 && n > 1)
    {
      double q, w;
      int r;

      w = md_log (-x);
      s = 0.0;
      for (r = 1; r <= n / 2; r++)
	{
	  j = 2 * r;
	  p = polylog (j, -1.0);
	  j = n - j;
	  if (j == 0)
	    {
	      s = s + p;
	      break;
	    }
	  q = (double) j;
	  q = md_pow (w, q) * p / fac (j);
	  s = s + q;
	}
      s = 2.0 * s;
      q = polylog (n, 1.0 / x);
      if (n & 1)
	q = -q;
      s = s - q;
      s = s - md_pow (w, (double) n) / fac (n);
      return s;
    }

  if (n == 2)
    {
      if (x < 0.0 || x > 1.0)
	return (spence (1.0 - x));
    }



  /*  The power series converges slowly when x is near 1.  For n = 3, this
      identity helps:

      Li (-x/(1-x)) + Li (1-x) + Li (x)
        3               3          3
                     2                               2                 3
       = Li (1) + (pi /6) md_log(1-x) - (1/2) md_log(x) md_log (1-x) + (1/6) md_log (1-x)
           3
  */

  if (n == 3)
    {
      p = x * x * x;
      if (x > 0.8)
	{
	  u = md_log(x);



( run in 1.170 second using v1.01-cache-2.11-cpan-39bf76dae61 )