File: dpsifn.pd

package info (click to toggle)
r-pdl 0.2-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 10,848 kB
  • ctags: 5,599
  • sloc: ansic: 66,166; fortran: 3,810; sh: 2,561; perl: 1,930; yacc: 1,508; makefile: 623
file content (121 lines) | stat: -rw-r--r-- 4,546 bytes parent folder | download
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
=pod
#   void dpsifn(double x, int n, int kode, int m, double *ans, int *nz, int *ierr)
/*
 *  Purpose:  Compute Derivatives of the Psi Function.
 *
 *  Author:  Amos, D. E., (SNLA)
 *  C Translation by Ross Ihaka
 *
 *  The following definitions are used in dpsifn:
 *
 *  Definition 1
 *     psi(x) = d/dx (ln(gamma(x)), the first derivative of
 *              the log gamma function.
 *  Definition 2
 *                 k   k
 *     psi(k,x) = d /dx (psi(x)), the k-th derivative of psi(x).
 *
 *
 *  Dpsifn computes a sequence of scaled derivatives of
 *  the psi function; i.e. for fixed x and m it computes
 *  the m-member sequence
 *
 *                ((-1)**(k+1)/gamma(k+1))*psi(k,x)
 *                   for k = n,...,n+m-1
 *
 *  where psi(k,x) is as defined above.   For kode=1, dpsifn returns
 *  the scaled derivatives as described.  kode=2 is operative only
 *  when k=0 and in that case dpsifn returns -psi(x) + ln(x).  that
 *  is, the logarithmic behavior for large x is removed when kode=2
 *  and k=0.  when sums or differences of psi functions are computed
 *  the logarithmic terms can be combined analytically and computed
 *  separately to help retain significant digits.
 *
 *  Note that call dpsifn(x,0,1,1,ans) results in ans = -psi(x)
 *
 *  Input      x is double precision
 *        x      - argument, x .gt. 0.0d0
 *        n      - first member of the sequence, 0 .le. n .le. 100
 *                 n=0 gives ans(1) = -psi(x)       for kode=1
 *                                    -psi(x)+ln(x) for kode=2
 *        kode   - selection parameter
 *                 kode=1 returns scaled derivatives of the psi
 *                 function.
 *                 kode=2 returns scaled derivatives of the psi
 *                 function except when n=0. in this case,
 *                 ans(1) = -psi(x) + ln(x) is returned.
 *        m      - number of members of the sequence, m.ge.1
 *
 * Output     ans is double precision
 *        ans    - a vector of length at least m whose first m
 *                 components contain the sequence of derivatives
 *                 scaled according to kode.
 *        nz     - underflow flag
 *                 nz.eq.0, a normal return
 *                 nz.ne.0, underflow, last nz components of ans are
 *                          set to zero, ans(m-k+1)=0.0, k=1,...,nz
 *        ierr   - error flag
 *                 ierr=0, a normal return, computation completed
 *                 ierr=1, input error,     no computation
 *                 ierr=2, overflow,        x too small or n+m-1 too
 *                         large or both
 *                 ierr=3, error,           n too large. dimensioned
 *                         array trmr(nmax) is not large enough for n
 *
 *  The nominal computational accuracy is the maximum of unit
 *  roundoff (=d1mach(4)) and 1.0d-18 since critical constants
 *  are given to only 18 digits.
 *
 *  Long Description:
 *
 *  The basic method of evaluation is the asymptotic expansion
 *  for large x.ge.xmin followed by backward recursion on a two
 *  term recursion relation
 *
 *           w(x+1) + x**(-n-1) = w(x).
 *
 *  this is supplemented by a series
 *
 *           sum( (x+k)**(-n-1) , k=0,1,2,... )
 *
 *  which converges rapidly for large n. both xmin and the
 *  number of terms of the series are calculated from the unit
 *  roundoff of the machine environment.
 *
 *  References:
 *
 *  Handbook of Mathematical Functions,
 *  National Bureau of Standards Applied Mathematics Series 55,
 *  Edited by M. Abramowitz and I. A. Stegun, equations 6.3.5,
 *  6.3.18, 6.4.6, 6.4.9 and 6.4.10, pp.258-260, 1964.
 *
 *  D. E. Amos, A Portable Fortran Subroutine for Derivatives
 *  of the Psi Function, Algorithm 610,
 *  ACM Transactions on Mathematical Software 9, 4 (1983), pp. 494-502.
=cut
#   void dpsifn(double x, int n, int kode, int m, double *ans, int *nz, int *ierr)

pp_addpm(<<'EOD');

# This interface is OK , but it should be improved
sub dpsifn {
    my($x,$n,$kode,$m) = @_;
    my($ans) = zeroes(float(),$m);
    my ($b,$c) = (0,0);
    dpsifn_in($x,$n,$kode,$m,$ans,$b,$c);
    return ($ans,$b,$c);
}
EOD
   
pp_def("dpsifn_in",
       Pars => 'x(); n(); kode(); m(); [o]ans(n); int [o]nz(); int [o]ierr()',
       GenericTypes => [D],
       Code => '
            extern void dpsifn(double x, int n, int kode, int m, double *ans, int *nz, int *ierr);
            int ierro, nzo;
	    dpsifn((double)$x(),(int)$n(),(int)$kode(),(int)$m(),$P(ans),&nzo,&ierro);
	    $nz() = nzo;
	    $ierr() = ierro;
');