dchu.f 4.28 KB
double precision function dchu (a, b, x)
c august 1980 edition.  w. fullerton, c3, los alamos scientific lab.
c this routine is not valid when 1+a-b is close to zero if x is small.
      double precision a, b, x, aintb, alnx, a0, beps, b0, c0, eps,
     1  factor, gamri1, gamrni, pch1ai, pch1i, pi, pochai, sum, t,
     2  xeps1, xi, xi1, xn, xtoeps,  d1mach, dpoch, dgamma, dgamr,
     3  dpoch1, dexprl, d9chu, dint, dexp, dlog, dsin, dsqrt
      external d1mach, d9chu,  dexprl, dgamma, dgamr, 
     1  dpoch, dpoch1
      data pi / 3.1415926535 8979323846 2643383279 503 d0 /
      data eps / 0.0d0 /
c
      if (eps.eq.0.0d0) eps = d1mach(3)
c
      if (x.lt.0.0d0) call seteru (31hdchu    x is negative, use cchu,
     1  31, 1, 2)
c
      if (x.ne.0.0d0) go to 10
      if (b.ge.1.0d0) call seteru (
     1  35hchu     x=0, b ge 1 so chu infinite, 35, 2, 2)
      dchu = dgamma(1.0d0-b)/dgamma(1.0d0+a-b)
      return
c
 10   if (dmax1(dabs(a),1.0d0)*dmax1(dabs(1.0d0+a-b),1.0d0).lt.
     1  0.99d0*dabs(x)) go to 120
c
c the ascending series will be used, because the descending rational
c approximation (which is based on the asymptotic series) is unstable.
c
      if (dabs(1.0d0+a-b).lt.dsqrt(eps)) call seteru (
     1  60hdchu    algorithm is bad when 1+a-b is near zero for small x,
     2  60, 10, 2)
c
      if (b.ge.0.0d0) aintb = dint(b+0.5d0)
      if (b.lt.0.0d0) aintb = dint(b-0.5d0)
      beps = b - aintb
      n = aintb
c
      alnx = dlog(x)
      xtoeps = dexp (-beps*alnx)
c
c evaluate the finite sum.     -----------------------------------------
c
      if (n.ge.1) go to 40
c
c consider the case b .lt. 1.0 first.
c
      sum = 1.0d0
      if (n.eq.0) go to 30
c
      t = 1.0d0
      m = -n
      do 20 i=1,m
        xi1 = i - 1
        t = t*(a+xi1)*x/((b+xi1)*(xi1+1.0d0))
        sum = sum + t
 20   continue
c
 30   sum = dpoch(1.0d0+a-b, -a)*sum
      go to 70
c
c now consider the case b .ge. 1.0.
c
 40   sum = 0.0d0
      m = n - 2
      if (m.lt.0) go to 70
      t = 1.0d0
      sum = 1.0d0
      if (m.eq.0) go to 60
c
      do 50 i=1,m
        xi = i
        t = t * (a-b+xi)*x/((1.0d0-b+xi)*xi)
        sum = sum + t
 50   continue
c
 60   sum = dgamma(b-1.0d0) * dgamr(a) * x**(1-n) * xtoeps * sum
c
c next evaluate the infinite sum.     ----------------------------------
c
 70   istrt = 0
      if (n.lt.1) istrt = 1 - n
      xi = istrt
c
      factor = (-1.0d0)**n * dgamr(1.0d0+a-b) * x**istrt
      if (beps.ne.0.0d0) factor = factor * beps*pi/dsin(beps*pi)
c
      pochai = dpoch (a, xi)
      gamri1 = dgamr (xi+1.0d0)
      gamrni = dgamr (aintb+xi)
      b0 = factor * dpoch(a,xi-beps) * gamrni * dgamr(xi+1.0d0-beps)
c
      if (dabs(xtoeps-1.0d0).gt.0.5d0) go to 90
c
c x**(-beps) is close to 1.0d0, so we must be careful in evaluating the
c differences.
c
      pch1ai = dpoch1 (a+xi, -beps)
      pch1i = dpoch1 (xi+1.0d0-beps, beps)
      c0 = factor * pochai * gamrni * gamri1 * (
     1  -dpoch1(b+xi,-beps) + pch1ai - pch1i + beps*pch1ai*pch1i)
c
c xeps1 = (1.0 - x**(-beps))/beps = (x**(-beps) - 1.0)/(-beps)
      xeps1 = alnx*dexprl(-beps*alnx)
c
      dchu = sum + c0 + xeps1*b0
      xn = n
      do 80 i=1,1000
        xi = istrt + i
        xi1 = istrt + i - 1
        b0 = (a+xi1-beps)*b0*x/((xn+xi1)*(xi-beps))
        c0 = (a+xi1)*c0*x/((b+xi1)*xi)
     1    - ((a-1.0d0)*(xn+2.d0*xi-1.0d0) + xi*(xi-beps)) * b0
     2    / (xi*(b+xi1)*(a+xi1-beps))
        t = c0 + xeps1*b0
        dchu = dchu + t
        if (dabs(t).lt.eps*dabs(dchu)) go to 130
 80   continue
      call seteru (
     1  60hdchu    no convergence in 1000 terms of the ascending series,
     2  60, 3, 2)
c
c x**(-beps) is very different from 1.0, so the straightforward
c formulation is stable.
c
 90   a0 = factor * pochai * dgamr(b+xi) * gamri1 / beps
      b0 = xtoeps * b0 / beps
c
      dchu = sum + a0 - b0
      do 100 i=1,1000
        xi = istrt + i
        xi1 = istrt + i - 1
        a0 = (a+xi1)*a0*x/((b+xi1)*xi)
        b0 = (a+xi1-beps)*b0*x/((aintb+xi1)*(xi-beps))
        t = a0 - b0
        dchu = dchu + t
        if (dabs(t).lt.eps*dabs(dchu)) go to 130
 100  continue
      call seteru (
     1  60hdchu    no convergence in 1000 terms of the ascending series,
     2  60, 3, 2)
c
c use luke-s rational approximation in the asymptotic region.
c
 120  dchu = x**(-a) * d9chu(a,b,x)
c
 130  return
      end