source: sasview/src/sans/models/c_extension/cephes/psi.c @ 79d5b6c

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 79d5b6c was 230f479, checked in by Mathieu Doucet <doucetm@…>, 11 years ago

Rename C source dir for models (minor updates)

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/*                                                      psi.c
2 *
3 *      Psi (digamma) function
4 *
5 *
6 * SYNOPSIS:
7 *
8 * double x, y, psi();
9 *
10 * y = psi( x );
11 *
12 *
13 * DESCRIPTION:
14 *
15 *              d      -
16 *   psi(x)  =  -- ln | (x)
17 *              dx
18 *
19 * is the logarithmic derivative of the gamma function.
20 * For integer x,
21 *                   n-1
22 *                    -
23 * psi(n) = -EUL  +   >  1/k.
24 *                    -
25 *                   k=1
26 *
27 * This formula is used for 0 < n <= 10.  If x is negative, it
28 * is transformed to a positive argument by the reflection
29 * formula  psi(1-x) = psi(x) + pi cot(pi x).
30 * For general positive x, the argument is made greater than 10
31 * using the recurrence  psi(x+1) = psi(x) + 1/x.
32 * Then the following asymptotic expansion is applied:
33 *
34 *                           inf.   B
35 *                            -      2k
36 * psi(x) = log(x) - 1/2x -   >   -------
37 *                            -        2k
38 *                           k=1   2k x
39 *
40 * where the B2k are Bernoulli numbers.
41 *
42 * ACCURACY:
43 *    Relative error (except absolute when |psi| < 1):
44 * arithmetic   domain     # trials      peak         rms
45 *    DEC       0,30         2500       1.7e-16     2.0e-17
46 *    IEEE      0,30        30000       1.3e-15     1.4e-16
47 *    IEEE      -30,0       40000       1.5e-15     2.2e-16
48 *
49 * ERROR MESSAGES:
50 *     message         condition      value returned
51 * psi singularity    x integer <=0      MAXNUM
52 */
53
54/*
55Cephes Math Library Release 2.8:  June, 2000
56Copyright 1984, 1987, 1992, 2000 by Stephen L. Moshier
57*/
58
59#include "mconf.h"
60
61#ifdef UNK
62static double A[] = {
63 8.33333333333333333333E-2,
64-2.10927960927960927961E-2,
65 7.57575757575757575758E-3,
66-4.16666666666666666667E-3,
67 3.96825396825396825397E-3,
68-8.33333333333333333333E-3,
69 8.33333333333333333333E-2
70};
71#endif
72
73#ifdef DEC
74static unsigned short A[] = {
750037252,0125252,0125252,0125253,
760136654,0145314,0126312,0146255,
770036370,0037017,0101740,0174076,
780136210,0104210,0104210,0104211,
790036202,0004040,0101010,0020202,
800136410,0104210,0104210,0104211,
810037252,0125252,0125252,0125253
82};
83#endif
84
85#ifdef IBMPC
86static unsigned short A[] = {
870x5555,0x5555,0x5555,0x3fb5,
880x5996,0x9599,0x9959,0xbf95,
890x1f08,0xf07c,0x07c1,0x3f7f,
900x1111,0x1111,0x1111,0xbf71,
910x0410,0x1041,0x4104,0x3f70,
920x1111,0x1111,0x1111,0xbf81,
930x5555,0x5555,0x5555,0x3fb5
94};
95#endif
96
97#ifdef MIEEE
98static unsigned short A[] = {
990x3fb5,0x5555,0x5555,0x5555,
1000xbf95,0x9959,0x9599,0x5996,
1010x3f7f,0x07c1,0xf07c,0x1f08,
1020xbf71,0x1111,0x1111,0x1111,
1030x3f70,0x4104,0x1041,0x0410,
1040xbf81,0x1111,0x1111,0x1111,
1050x3fb5,0x5555,0x5555,0x5555
106};
107#endif
108
109#define EUL 0.57721566490153286061
110
111#ifdef ANSIPROT
112extern double floor ( double );
113extern double log ( double );
114extern double tan ( double );
115extern double polevl ( double, void *, int );
116#else
117double floor(), log(), tan(), polevl();
118#endif
119extern double PI, MAXNUM;
120
121
122double psi(x)
123double x;
124{
125double p, q, nz, s, w, y, z;
126int i, n, negative;
127
128negative = 0;
129nz = 0.0;
130
131if( x <= 0.0 )
132        {
133        negative = 1;
134        q = x;
135        p = floor(q);
136        if( p == q )
137                {
138                mtherr( "psi", SING );
139                return( MAXNUM );
140                }
141/* Remove the zeros of tan(PI x)
142 * by subtracting the nearest integer from x
143 */
144        nz = q - p;
145        if( nz != 0.5 )
146                {
147                if( nz > 0.5 )
148                        {
149                        p += 1.0;
150                        nz = q - p;
151                        }
152                nz = PI/tan(PI*nz);
153                }
154        else
155                {
156                nz = 0.0;
157                }
158        x = 1.0 - x;
159        }
160
161/* check for positive integer up to 10 */
162if( (x <= 10.0) && (x == floor(x)) )
163        {
164        y = 0.0;
165        n = x;
166        for( i=1; i<n; i++ )
167                {
168                w = i;
169                y += 1.0/w;
170                }
171        y -= EUL;
172        goto done;
173        }
174
175s = x;
176w = 0.0;
177while( s < 10.0 )
178        {
179        w += 1.0/s;
180        s += 1.0;
181        }
182
183if( s < 1.0e17 )
184        {
185        z = 1.0/(s * s);
186        y = z * polevl( z, A, 6 );
187        }
188else
189        y = 0.0;
190
191y = log(s)  -  (0.5/s)  -  y  -  w;
192
193done:
194
195if( negative )
196        {
197        y -= nz;
198        }
199
200return(y);
201}
Note: See TracBrowser for help on using the repository browser.