double precision function dpoch1 (a, x) c august 1980 edition. w. fullerton, c3, los alamos scientific lab. c c evaluate a generalization of pochhammer-s symbol for special c situations that require especially accurate values when x is small in c poch1(a,x) = (poch(a,x)-1)/x c = (gamma(a+x)/gamma(a) - 1.0)/x . c this specification is particularly suited for stably computing c expressions such as c (gamma(a+x)/gamma(a) - gamma(b+x)/gamma(b))/x c = poch1(a,x) - poch1(b,x) c note that poch1(a,0.0) = psi(a) c c when abs(x) is so small that substantial cancellation will occur if c the straightforward formula is used, we use an expansion due c to fields and discussed by y. l. luke, the special functions and their c approximations, vol. 1, academic press, 1969, page 34. c c the ratio poch(a,x) = gamma(a+x)/gamma(a) is written by luke as c (a+(x-1)/2)**x * polynomial in (a+(x-1)/2)**(-2) . c in order to maintain significance in poch1, we write for positive+ a c (a+(x-1)/2)**x = exp(x*alog(a+(x-1)/2)) = exp(q) c = 1.0 + q*exprel(q) . c likewise the polynomial is written c poly = 1.0 + x*poly1(a,x) . c thus, c poch1(a,x) = (poch(a,x) - 1) / x c = exprel(q)*(q/x + q*poly1(a,x)) + poly1(a,x) c double precision a, x, absa, absx, alneps, alnvar, b, bern(20), 1 binv, bp, gbern(21), gbk, pi, poly1, q, rho, sinpxx, sinpx2, 2 sqtbig, term, trig, var, var2, d1mach, dpsi, dexprl, dcot, 3 dpoch, dlog, dsin, dsqrt external d1mach, dcot, dexprl, dlog, dpoch, dpsi, dsin, dsqrt c c bern(i) is the 2*i bernoulli number divided by factorial(2*i). data bern ( 1) / +.8333333333 3333333333 3333333333 333 d-1 / data bern ( 2) / -.1388888888 8888888888 8888888888 888 d-2 / data bern ( 3) / +.3306878306 8783068783 0687830687 830 d-4 / data bern ( 4) / -.8267195767 1957671957 6719576719 576 d-6 / data bern ( 5) / +.2087675698 7868098979 2100903212 014 d-7 / data bern ( 6) / -.5284190138 6874931848 4768220217 955 d-9 / data bern ( 7) / +.1338253653 0684678832 8269809751 291 d-10 / data bern ( 8) / -.3389680296 3225828668 3019539124 944 d-12 / data bern ( 9) / +.8586062056 2778445641 3590545042 562 d-14 / data bern ( 10) / -.2174868698 5580618730 4151642386 591 d-15 / data bern ( 11) / +.5509002828 3602295152 0265260890 225 d-17 / data bern ( 12) / -.1395446468 5812523340 7076862640 635 d-18 / data bern ( 13) / +.3534707039 6294674716 9322997780 379 d-20 / data bern ( 14) / -.8953517427 0375468504 0261131811 274 d-22 / data bern ( 15) / +.2267952452 3376830603 1095073886 816 d-23 / data bern ( 16) / -.5744724395 2026452383 4847971943 400 d-24 / data bern ( 17) / +.1455172475 6148649018 6626486727 132 d-26 / data bern ( 18) / -.3685994940 6653101781 8178247990 866 d-28 / data bern ( 19) / +.9336734257 0950446720 3255515278 562 d-30 / data bern ( 20) / -.2365022415 7006299345 5963519636 983 d-31 / c data pi / 3.1415926535 8979323846 2643383279 503 d0 / data sqtbig, alneps / 2*0.0d0 / c if (sqtbig.ne.0.0d0) go to 10 sqtbig = 1.0d0/dsqrt(24.0d0*d1mach(1)) alneps = dlog(d1mach(3)) c 10 if (x.eq.0.0d0) dpoch1 = dpsi(a) if (x.eq.0.0d0) return c absx = dabs(x) absa = dabs(a) if (absx.gt.0.1d0*absa) go to 70 if (absx*dlog(dmax1(absa,2.0d0)).gt.0.1d0) go to 70 c bp = a if (a.lt.(-0.5d0)) bp = 1.0d0 - a - x incr = 0 if (bp.lt.10.0d0) incr = 11.0d0 - bp b = bp + dble(float(incr)) c var = b + 0.5d0*(x-1.0d0) alnvar = dlog(var) q = x*alnvar c poly1 = 0.0d0 if (var.ge.sqtbig) go to 40 var2 = (1.0d0/var)**2 c rho = 0.5d0*(x+1.0d0) gbern(1) = 1.0d0 gbern(2) = -rho/12.0d0 term = var2 poly1 = gbern(2)*term c nterms = -0.5d0*alneps/alnvar + 1.0d0 if (nterms.gt.20) call seteru ( 1 49hdpoch1 nterms is too big, maybe d1mach(3) is bad, 49, 1, 2) if (nterms.lt.2) go to 40 c do 30 k=2,nterms gbk = 0.0d0 do 20 j=1,k ndx = k - j + 1 gbk = gbk + bern(ndx)*gbern(j) 20 continue gbern(k+1) = -rho*gbk/dble(float(k)) c term = term * (dble(float(2*k-2))-x)*(dble(float(2*k-1))-x)*var2 poly1 = poly1 + gbern(k+1)*term 30 continue c 40 poly1 = (x-1.0d0)*poly1 dpoch1 = dexprl(q)*(alnvar+q*poly1) + poly1 c if (incr.eq.0) go to 60 c c we have dpoch1(b,x), but bp is small, so we use backwards recursion c to obtain dpoch1(bp,x). c do 50 ii=1,incr i = incr - ii binv = 1.0d0/(bp+dble(float(i))) dpoch1 = (dpoch1 - binv) / (1.0d0 + x*binv) 50 continue c 60 if (bp.eq.a) return c c we have dpoch1(bp,x), but a is lt -0.5. we therefore use a reflection c formula to obtain dpoch1(a,x). c sinpxx = dsin(pi*x)/x sinpx2 = dsin(0.5d0*pi*x) trig = sinpxx*dcot(pi*b) - 2.0d0*sinpx2*(sinpx2/x) c dpoch1 = trig + (1.0d0 + x*trig)*dpoch1 return c 70 call entsrc (irold, 1) dpoch1 = dpoch (a, x) if (dpoch1.eq.0.0d0) call erroff call entsrc (irold2, irold) c dpoch1 = (dpoch1 - 1.0d0) / x return c end