source: sasmodels/sasmodels/models/lib/sas_JN.c @ 3f8584a2

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 3f8584a2 was 3f8584a2, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

clean separation between float/double bessel functions

  • Property mode set to 100644
File size: 3.5 KB
Line 
1/*                                                      jn.c
2 *
3 *      Bessel function of integer order
4 *
5 *
6 *
7 * SYNOPSIS:
8 *
9 * int n;
10 * double x, y, jn();
11 *
12 * y = jn( n, x );
13 *
14 *
15 *
16 * DESCRIPTION:
17 *
18 * Returns Bessel function of order n, where n is a
19 * (possibly negative) integer.
20 *
21 * The ratio of jn(x) to j0(x) is computed by backward
22 * recurrence.  First the ratio jn/jn-1 is found by a
23 * continued fraction expansion.  Then the recurrence
24 * relating successive orders is applied until j0 or j1 is
25 * reached.
26 *
27 * If n = 0 or 1 the routine for j0 or j1 is called
28 * directly.
29 *
30 *
31 *
32 * ACCURACY:
33 *
34 *                      Absolute error:
35 * arithmetic   range      # trials      peak         rms
36 *    DEC       0, 30        5500       6.9e-17     9.3e-18
37 *    IEEE      0, 30        5000       4.4e-16     7.9e-17
38 *
39 *
40 * Not suitable for large n or x. Use jv() instead.
41 *
42 */
43
44/*                                                      jn.c
45Cephes Math Library Release 2.8:  June, 2000
46Copyright 1984, 1987, 2000 by Stephen L. Moshier
47*/
48
49#if FLOAT_SIZE > 4
50
51double jn( int n, double x );
52double jn( int n, double x ) {
53
54    // PAK: seems to be machine epsilon/2
55    const double MACHEP = 1.11022302462515654042E-16;
56    double pkm2, pkm1, pk, xk, r, ans;
57    int k, sign;
58
59    if( n < 0 ) {
60        n = -n;
61        if( (n & 1) == 0 )      /* -1**n */
62            sign = 1;
63        else
64            sign = -1;
65    } else {
66        sign = 1;
67    }
68
69    if( x < 0.0 ) {
70        if( n & 1 )
71            sign = -sign;
72    x = -x;
73    }
74
75    if( n == 0 )
76        return( sign * j0(x) );
77    if( n == 1 )
78        return( sign * j1(x) );
79    if( n == 2 )
80        return( sign * (2.0 * j1(x) / x  -  j0(x)) );
81
82    if( x < MACHEP )
83        return( 0.0 );
84
85    k = 53;
86    pk = 2 * (n + k);
87    ans = pk;
88    xk = x * x;
89
90    do {
91        pk -= 2.0;
92        ans = pk - (xk/ans);
93    } while( --k > 0 );
94
95    /* backward recurrence */
96
97    pk = 1.0;
98
99    ans = x/ans;
100    pkm1 = 1.0/ans;
101
102    k = n-1;
103    r = 2 * k;
104
105    do {
106        pkm2 = (pkm1 * r  -  pk * x) / x;
107        pk = pkm1;
108        pkm1 = pkm2;
109        r -= 2.0;
110    } while( --k > 0 );
111
112    if( fabs(pk) > fabs(pkm1) )
113        ans = j1(x)/pk;
114    else
115        ans = j0(x)/pkm1;
116
117    return( sign * ans );
118}
119
120#else
121
122float jnf(int n, float x)
123{
124    // PAK: seems to be machine epsilon/2
125    const double MACHEP = 5.9604645e-08;
126    float pkm2, pkm1, pk, xk, r, ans;
127    int k, sign;
128
129    if( n < 0 ) {
130        n = -n;
131        if( (n & 1) == 0 ) /* -1**n */
132            sign = 1;
133        else
134            sign = -1;
135    } else {
136        sign = 1;
137    }
138
139    if( x < 0.0 ) {
140        if( n & 1 )
141            sign = -sign;
142        x = -x;
143    }
144
145    if( n == 0 )
146        return( sign * j0f(x) );
147    if( n == 1 )
148        return( sign * j1f(x) );
149    if( n == 2 )
150        return( sign * (2.0 * j1f(x) / x  -  j0f(x)) );
151
152    if( x < MACHEP )
153        return( 0.0 );
154
155    k = 24;
156    pk = 2 * (n + k);
157    ans = pk;
158    xk = x * x;
159
160    do {
161        pk -= 2.0;
162        ans = pk - (xk/ans);
163    } while( --k > 0 );
164
165    /* backward recurrence */
166
167    pk = 1.0;
168
169    const float xinv = 1.0/x;
170    pkm1 = ans * xinv;
171    k = n-1;
172    r = (float )(2 * k);
173
174    do {
175        pkm2 = (pkm1 * r  -  pk * x) * xinv;
176        pk = pkm1;
177        pkm1 = pkm2;
178        r -= 2.0;
179    } while( --k > 0 );
180
181    r = pk;
182    if( r < 0 )
183        r = -r;
184    ans = pkm1;
185    if( ans < 0 )
186        ans = -ans;
187
188    if( r > ans )  /* if( fabs(pk) > fabs(pkm1) ) */
189        ans = sign * j1f(x)/pk;
190    else
191        ans = sign * j0f(x)/pkm1;
192    return( ans );
193}
194#endif
195
196#if FLOAT_SIZE>4
197#define sas_JN jn
198#else
199#define sas_JN jnf
200#endif
Note: See TracBrowser for help on using the repository browser.