Blame view
fvn_fnlib/dpoch1.f
5.26 KB
38581db0c git-svn-id: https... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
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, dpoch, dpsi 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 |