summaryrefslogtreecommitdiff
path: root/libm/ldouble/jnl.c
blob: 1b24c50c75238a06a6e976902d769a2cc581ed53 (plain)
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
/*							jnl.c
 *
 *	Bessel function of integer order
 *
 *
 *
 * SYNOPSIS:
 *
 * int n;
 * long double x, y, jnl();
 *
 * y = jnl( n, x );
 *
 *
 *
 * DESCRIPTION:
 *
 * Returns Bessel function of order n, where n is a
 * (possibly negative) integer.
 *
 * The ratio of jn(x) to j0(x) is computed by backward
 * recurrence.  First the ratio jn/jn-1 is found by a
 * continued fraction expansion.  Then the recurrence
 * relating successive orders is applied until j0 or j1 is
 * reached.
 *
 * If n = 0 or 1 the routine for j0 or j1 is called
 * directly.
 *
 *
 *
 * ACCURACY:
 *
 *                      Absolute error:
 * arithmetic   domain      # trials      peak         rms
 *    IEEE     -30, 30        5000       3.3e-19     4.7e-20
 *
 *
 * Not suitable for large n or x.
 *
 */

/*							jn.c
Cephes Math Library Release 2.0:  April, 1987
Copyright 1984, 1987 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
#include <math.h>

extern long double MACHEPL;
#ifdef ANSIPROT
extern long double fabsl ( long double );
extern long double j0l ( long double );
extern long double j1l ( long double );
#else
long double fabsl(), j0l(), j1l();
#endif

long double jnl( n, x )
int n;
long double x;
{
long double pkm2, pkm1, pk, xk, r, ans;
int k, sign;

if( n < 0 )
	{
	n = -n;
	if( (n & 1) == 0 )	/* -1**n */
		sign = 1;
	else
		sign = -1;
	}
else
	sign = 1;

if( x < 0.0L )
	{
	if( n & 1 )
		sign = -sign;
	x = -x;
	}


if( n == 0 )
	return( sign * j0l(x) );
if( n == 1 )
	return( sign * j1l(x) );
if( n == 2 )
	return( sign * (2.0L * j1l(x) / x  -  j0l(x)) );

if( x < MACHEPL )
	return( 0.0L );

/* continued fraction */
k = 53;
pk = 2 * (n + k);
ans = pk;
xk = x * x;

do
	{
	pk -= 2.0L;
	ans = pk - (xk/ans);
	}
while( --k > 0 );
ans = x/ans;

/* backward recurrence */

pk = 1.0L;
pkm1 = 1.0L/ans;
k = n-1;
r = 2 * k;

do
	{
	pkm2 = (pkm1 * r  -  pk * x) / x;
	pk = pkm1;
	pkm1 = pkm2;
	r -= 2.0L;
	}
while( --k > 0 );

if( fabsl(pk) > fabsl(pkm1) )
	ans = j1l(x)/pk;
else
	ans = j0l(x)/pkm1;
return( sign * ans );
}