Blame view

fvn_fnlib/dpoch1.f 5.26 KB
38581db0c   daniau   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