Blame view
fvn_fnlib/poch1.f
3.92 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 |
function poch1 (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 dimension bern(9), gbern(10) external cot, exprel, poch, psi, r1mach c c bern(i) is the 2*i bernoulli number divided by factorial(2*i). data bern( 1) / .8333333333 3333333e-01 / data bern( 2) / -.1388888888 8888889e-02 / data bern( 3) / .3306878306 8783069e-04 / data bern( 4) / -.8267195767 1957672e-06 / data bern( 5) / .2087675698 7868099e-07 / data bern( 6) / -.5284190138 6874932e-09 / data bern( 7) / .1338253653 0684679e-10 / data bern( 8) / -.3389680296 3225829e-12 / data bern( 9) / .8586062056 2778446e-14 / c data pi / 3.1415926535 8979324 e0 / data sqtbig, alneps / 2*0.0 / c if (sqtbig.ne.0.0) go to 10 sqtbig = 1.0/sqrt(24.0*r1mach(1)) alneps = alog(r1mach(3)) c 10 if (x.eq.0.0) poch1 = psi(a) if (x.eq.0.0) return c absx = abs(x) absa = abs(a) if (absx.gt.0.1*absa) go to 70 if (absx*alog(amax1(absa,2.0)).gt.0.1) go to 70 c bp = a if (a.lt.(-0.5)) bp = 1.0 - a - x incr = 0 if (bp.lt.10.0) incr = 11.0 - bp b = bp + float(incr) c var = b + 0.5*(x-1.0) alnvar = alog(var) q = x*alnvar c poly1 = 0.0 if (var.ge.sqtbig) go to 40 var2 = (1.0/var)**2 c rho = 0.5*(x+1.0) gbern(1) = 1.0 gbern(2) = -rho/12.0 term = var2 poly1 = gbern(2)*term c nterms = -0.5*alneps/alnvar + 1.0 if (nterms.gt.9) call seteru ( 1 49hpoch1 nterms is too big, maybe r1mach(3) is bad, 49, 1, 2) if (nterms.lt.2) go to 40 c do 30 k=2,nterms gbk = 0.0 do 20 j=1,k ndx = k - j + 1 gbk = gbk + bern(ndx)*gbern(j) 20 continue gbern(k+1) = -rho*gbk/float(k) c term = term * (float(2*k-2)-x)*(float(2*k-1)-x)*var2 poly1 = poly1 + gbern(k+1)*term 30 continue c 40 poly1 = (x-1.0)*poly1 poch1 = exprel(q)*(alnvar + q*poly1) + poly1 c if (incr.eq.0) go to 60 c c we have poch1(b,x). but bp is small, so we use backwards recursion c to obtain poch1(bp,x). c do 50 ii=1,incr i = incr - ii binv = 1.0/(bp+float(i)) poch1 = (poch1-binv)/(1.0+x*binv) 50 continue c 60 if (bp.eq.a) return c c we have poch1(bp,x), but a is lt -0.5. we therefore use a reflection c formula to obtain poch1(a,x). c sinpxx = sin(pi*x)/x sinpx2 = sin(0.5*pi*x) trig = sinpxx*cot(pi*b) - 2.0*sinpx2*(sinpx2/x) c poch1 = trig + (1.0 + x*trig) * poch1 return c 70 call entsrc (irold, 1) poch1 = poch (a, x) if (poch1.eq.0.0) call erroff call entsrc (irold2, irold) c poch1 = (poch1 - 1.0) / x return c end |