pyopencl 2025.2.5__cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyopencl might be problematic. Click here for more details.
- pyopencl/.libs/libOpenCL-83a5a7fd.so.1.0.0 +0 -0
- pyopencl/__init__.py +1995 -0
- pyopencl/_cl.cpython-313-x86_64-linux-gnu.so +0 -0
- pyopencl/_cl.pyi +2006 -0
- pyopencl/_cluda.py +57 -0
- pyopencl/_monkeypatch.py +1069 -0
- pyopencl/_mymako.py +17 -0
- pyopencl/algorithm.py +1454 -0
- pyopencl/array.py +3441 -0
- pyopencl/bitonic_sort.py +245 -0
- pyopencl/bitonic_sort_templates.py +597 -0
- pyopencl/cache.py +535 -0
- pyopencl/capture_call.py +200 -0
- pyopencl/characterize/__init__.py +463 -0
- pyopencl/characterize/performance.py +240 -0
- pyopencl/cl/pyopencl-airy.cl +324 -0
- pyopencl/cl/pyopencl-bessel-j-complex.cl +238 -0
- pyopencl/cl/pyopencl-bessel-j.cl +1084 -0
- pyopencl/cl/pyopencl-bessel-y.cl +435 -0
- pyopencl/cl/pyopencl-complex.h +303 -0
- pyopencl/cl/pyopencl-eval-tbl.cl +120 -0
- pyopencl/cl/pyopencl-hankel-complex.cl +444 -0
- pyopencl/cl/pyopencl-random123/array.h +325 -0
- pyopencl/cl/pyopencl-random123/openclfeatures.h +93 -0
- pyopencl/cl/pyopencl-random123/philox.cl +486 -0
- pyopencl/cl/pyopencl-random123/threefry.cl +864 -0
- pyopencl/clmath.py +282 -0
- pyopencl/clrandom.py +412 -0
- pyopencl/cltypes.py +202 -0
- pyopencl/compyte/.gitignore +21 -0
- pyopencl/compyte/__init__.py +0 -0
- pyopencl/compyte/array.py +241 -0
- pyopencl/compyte/dtypes.py +316 -0
- pyopencl/compyte/pyproject.toml +52 -0
- pyopencl/elementwise.py +1178 -0
- pyopencl/invoker.py +417 -0
- pyopencl/ipython_ext.py +70 -0
- pyopencl/py.typed +0 -0
- pyopencl/reduction.py +815 -0
- pyopencl/scan.py +1916 -0
- pyopencl/tools.py +1565 -0
- pyopencl/typing.py +61 -0
- pyopencl/version.py +11 -0
- pyopencl-2025.2.5.dist-info/METADATA +109 -0
- pyopencl-2025.2.5.dist-info/RECORD +47 -0
- pyopencl-2025.2.5.dist-info/WHEEL +6 -0
- pyopencl-2025.2.5.dist-info/licenses/LICENSE +104 -0
|
@@ -0,0 +1,1084 @@
|
|
|
1
|
+
// Pieced together from Boost C++ and Cephes by
|
|
2
|
+
// Andreas Kloeckner (C) 2012
|
|
3
|
+
//
|
|
4
|
+
// Pieces from:
|
|
5
|
+
//
|
|
6
|
+
// Copyright (c) 2006 Xiaogang Zhang, John Maddock
|
|
7
|
+
// Use, modification and distribution are subject to the
|
|
8
|
+
// Boost Software License, Version 1.0. (See
|
|
9
|
+
// http://www.boost.org/LICENSE_1_0.txt)
|
|
10
|
+
//
|
|
11
|
+
// Cephes Math Library Release 2.8: June, 2000
|
|
12
|
+
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
|
|
13
|
+
// What you see here may be used freely, but it comes with no support or
|
|
14
|
+
// guarantee.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
#pragma once
|
|
21
|
+
|
|
22
|
+
#include <pyopencl-eval-tbl.cl>
|
|
23
|
+
#include <pyopencl-airy.cl>
|
|
24
|
+
|
|
25
|
+
typedef double bessel_j_scalar_type;
|
|
26
|
+
// FIXME: T is really a bad name
|
|
27
|
+
typedef bessel_j_scalar_type T;
|
|
28
|
+
|
|
29
|
+
// {{{ bessel_j0
|
|
30
|
+
|
|
31
|
+
__constant const bessel_j_scalar_type bessel_j0_P1[] = {
|
|
32
|
+
-4.1298668500990866786e+11,
|
|
33
|
+
2.7282507878605942706e+10,
|
|
34
|
+
-6.2140700423540120665e+08,
|
|
35
|
+
6.6302997904833794242e+06,
|
|
36
|
+
-3.6629814655107086448e+04,
|
|
37
|
+
1.0344222815443188943e+02,
|
|
38
|
+
-1.2117036164593528341e-01
|
|
39
|
+
};
|
|
40
|
+
__constant const bessel_j_scalar_type bessel_j0_Q1[] = {
|
|
41
|
+
2.3883787996332290397e+12,
|
|
42
|
+
2.6328198300859648632e+10,
|
|
43
|
+
1.3985097372263433271e+08,
|
|
44
|
+
4.5612696224219938200e+05,
|
|
45
|
+
9.3614022392337710626e+02,
|
|
46
|
+
1.0,
|
|
47
|
+
0.0
|
|
48
|
+
};
|
|
49
|
+
__constant const bessel_j_scalar_type bessel_j0_P2[] = {
|
|
50
|
+
-1.8319397969392084011e+03,
|
|
51
|
+
-1.2254078161378989535e+04,
|
|
52
|
+
-7.2879702464464618998e+03,
|
|
53
|
+
1.0341910641583726701e+04,
|
|
54
|
+
1.1725046279757103576e+04,
|
|
55
|
+
4.4176707025325087628e+03,
|
|
56
|
+
7.4321196680624245801e+02,
|
|
57
|
+
4.8591703355916499363e+01
|
|
58
|
+
};
|
|
59
|
+
__constant const bessel_j_scalar_type bessel_j0_Q2[] = {
|
|
60
|
+
-3.5783478026152301072e+05,
|
|
61
|
+
2.4599102262586308984e+05,
|
|
62
|
+
-8.4055062591169562211e+04,
|
|
63
|
+
1.8680990008359188352e+04,
|
|
64
|
+
-2.9458766545509337327e+03,
|
|
65
|
+
3.3307310774649071172e+02,
|
|
66
|
+
-2.5258076240801555057e+01,
|
|
67
|
+
1.0
|
|
68
|
+
};
|
|
69
|
+
__constant const bessel_j_scalar_type bessel_j0_PC[] = {
|
|
70
|
+
2.2779090197304684302e+04,
|
|
71
|
+
4.1345386639580765797e+04,
|
|
72
|
+
2.1170523380864944322e+04,
|
|
73
|
+
3.4806486443249270347e+03,
|
|
74
|
+
1.5376201909008354296e+02,
|
|
75
|
+
8.8961548424210455236e-01
|
|
76
|
+
};
|
|
77
|
+
__constant const bessel_j_scalar_type bessel_j0_QC[] = {
|
|
78
|
+
2.2779090197304684318e+04,
|
|
79
|
+
4.1370412495510416640e+04,
|
|
80
|
+
2.1215350561880115730e+04,
|
|
81
|
+
3.5028735138235608207e+03,
|
|
82
|
+
1.5711159858080893649e+02,
|
|
83
|
+
1.0
|
|
84
|
+
};
|
|
85
|
+
__constant const bessel_j_scalar_type bessel_j0_PS[] = {
|
|
86
|
+
-8.9226600200800094098e+01,
|
|
87
|
+
-1.8591953644342993800e+02,
|
|
88
|
+
-1.1183429920482737611e+02,
|
|
89
|
+
-2.2300261666214198472e+01,
|
|
90
|
+
-1.2441026745835638459e+00,
|
|
91
|
+
-8.8033303048680751817e-03
|
|
92
|
+
};
|
|
93
|
+
__constant const bessel_j_scalar_type bessel_j0_QS[] = {
|
|
94
|
+
5.7105024128512061905e+03,
|
|
95
|
+
1.1951131543434613647e+04,
|
|
96
|
+
7.2642780169211018836e+03,
|
|
97
|
+
1.4887231232283756582e+03,
|
|
98
|
+
9.0593769594993125859e+01,
|
|
99
|
+
1.0
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
bessel_j_scalar_type bessel_j0(bessel_j_scalar_type x)
|
|
103
|
+
{
|
|
104
|
+
const bessel_j_scalar_type x1 = 2.4048255576957727686e+00,
|
|
105
|
+
x2 = 5.5200781102863106496e+00,
|
|
106
|
+
x11 = 6.160e+02,
|
|
107
|
+
x12 = -1.42444230422723137837e-03,
|
|
108
|
+
x21 = 1.4130e+03,
|
|
109
|
+
x22 = 5.46860286310649596604e-04;
|
|
110
|
+
|
|
111
|
+
bessel_j_scalar_type value, factor, r, rc, rs;
|
|
112
|
+
|
|
113
|
+
if (x < 0)
|
|
114
|
+
{
|
|
115
|
+
x = -x; // even function
|
|
116
|
+
}
|
|
117
|
+
if (x == 0)
|
|
118
|
+
{
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
if (x <= 4) // x in (0, 4]
|
|
122
|
+
{
|
|
123
|
+
bessel_j_scalar_type y = x * x;
|
|
124
|
+
r = boost_evaluate_rational(bessel_j0_P1, bessel_j0_Q1, y);
|
|
125
|
+
factor = (x + x1) * ((x - x11/256) - x12);
|
|
126
|
+
value = factor * r;
|
|
127
|
+
}
|
|
128
|
+
else if (x <= 8.0) // x in (4, 8]
|
|
129
|
+
{
|
|
130
|
+
bessel_j_scalar_type y = 1 - (x * x)/64;
|
|
131
|
+
r = boost_evaluate_rational(bessel_j0_P2, bessel_j0_Q2, y);
|
|
132
|
+
factor = (x + x2) * ((x - x21/256) - x22);
|
|
133
|
+
value = factor * r;
|
|
134
|
+
}
|
|
135
|
+
else // x in (8, \infty)
|
|
136
|
+
{
|
|
137
|
+
bessel_j_scalar_type y = 8 / x;
|
|
138
|
+
bessel_j_scalar_type y2 = y * y;
|
|
139
|
+
bessel_j_scalar_type z = x - 0.25f * M_PI;
|
|
140
|
+
rc = boost_evaluate_rational(bessel_j0_PC, bessel_j0_QC, y2);
|
|
141
|
+
rs = boost_evaluate_rational(bessel_j0_PS, bessel_j0_QS, y2);
|
|
142
|
+
factor = sqrt(2 / (x * M_PI));
|
|
143
|
+
value = factor * (rc * cos(z) - y * rs * sin(z));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// }}}
|
|
150
|
+
|
|
151
|
+
// {{{ bessel_j1
|
|
152
|
+
|
|
153
|
+
__constant const bessel_j_scalar_type bessel_j1_P1[] = {
|
|
154
|
+
-1.4258509801366645672e+11,
|
|
155
|
+
6.6781041261492395835e+09,
|
|
156
|
+
-1.1548696764841276794e+08,
|
|
157
|
+
9.8062904098958257677e+05,
|
|
158
|
+
-4.4615792982775076130e+03,
|
|
159
|
+
1.0650724020080236441e+01,
|
|
160
|
+
-1.0767857011487300348e-02
|
|
161
|
+
};
|
|
162
|
+
__constant const bessel_j_scalar_type bessel_j1_Q1[] = {
|
|
163
|
+
4.1868604460820175290e+12,
|
|
164
|
+
4.2091902282580133541e+10,
|
|
165
|
+
2.0228375140097033958e+08,
|
|
166
|
+
5.9117614494174794095e+05,
|
|
167
|
+
1.0742272239517380498e+03,
|
|
168
|
+
1.0,
|
|
169
|
+
0.0
|
|
170
|
+
};
|
|
171
|
+
__constant const bessel_j_scalar_type bessel_j1_P2[] = {
|
|
172
|
+
-1.7527881995806511112e+16,
|
|
173
|
+
1.6608531731299018674e+15,
|
|
174
|
+
-3.6658018905416665164e+13,
|
|
175
|
+
3.5580665670910619166e+11,
|
|
176
|
+
-1.8113931269860667829e+09,
|
|
177
|
+
5.0793266148011179143e+06,
|
|
178
|
+
-7.5023342220781607561e+03,
|
|
179
|
+
4.6179191852758252278e+00
|
|
180
|
+
};
|
|
181
|
+
__constant const bessel_j_scalar_type bessel_j1_Q2[] = {
|
|
182
|
+
1.7253905888447681194e+18,
|
|
183
|
+
1.7128800897135812012e+16,
|
|
184
|
+
8.4899346165481429307e+13,
|
|
185
|
+
2.7622777286244082666e+11,
|
|
186
|
+
6.4872502899596389593e+08,
|
|
187
|
+
1.1267125065029138050e+06,
|
|
188
|
+
1.3886978985861357615e+03,
|
|
189
|
+
1.0
|
|
190
|
+
};
|
|
191
|
+
__constant const bessel_j_scalar_type bessel_j1_PC[] = {
|
|
192
|
+
-4.4357578167941278571e+06,
|
|
193
|
+
-9.9422465050776411957e+06,
|
|
194
|
+
-6.6033732483649391093e+06,
|
|
195
|
+
-1.5235293511811373833e+06,
|
|
196
|
+
-1.0982405543459346727e+05,
|
|
197
|
+
-1.6116166443246101165e+03,
|
|
198
|
+
0.0
|
|
199
|
+
};
|
|
200
|
+
__constant const bessel_j_scalar_type bessel_j1_QC[] = {
|
|
201
|
+
-4.4357578167941278568e+06,
|
|
202
|
+
-9.9341243899345856590e+06,
|
|
203
|
+
-6.5853394797230870728e+06,
|
|
204
|
+
-1.5118095066341608816e+06,
|
|
205
|
+
-1.0726385991103820119e+05,
|
|
206
|
+
-1.4550094401904961825e+03,
|
|
207
|
+
1.0
|
|
208
|
+
};
|
|
209
|
+
__constant const bessel_j_scalar_type bessel_j1_PS[] = {
|
|
210
|
+
3.3220913409857223519e+04,
|
|
211
|
+
8.5145160675335701966e+04,
|
|
212
|
+
6.6178836581270835179e+04,
|
|
213
|
+
1.8494262873223866797e+04,
|
|
214
|
+
1.7063754290207680021e+03,
|
|
215
|
+
3.5265133846636032186e+01,
|
|
216
|
+
0.0
|
|
217
|
+
};
|
|
218
|
+
__constant const bessel_j_scalar_type bessel_j1_QS[] = {
|
|
219
|
+
7.0871281941028743574e+05,
|
|
220
|
+
1.8194580422439972989e+06,
|
|
221
|
+
1.4194606696037208929e+06,
|
|
222
|
+
4.0029443582266975117e+05,
|
|
223
|
+
3.7890229745772202641e+04,
|
|
224
|
+
8.6383677696049909675e+02,
|
|
225
|
+
1.0
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
bessel_j_scalar_type bessel_j1(bessel_j_scalar_type x)
|
|
230
|
+
{
|
|
231
|
+
const bessel_j_scalar_type x1 = 3.8317059702075123156e+00,
|
|
232
|
+
x2 = 7.0155866698156187535e+00,
|
|
233
|
+
x11 = 9.810e+02,
|
|
234
|
+
x12 = -3.2527979248768438556e-04,
|
|
235
|
+
x21 = 1.7960e+03,
|
|
236
|
+
x22 = -3.8330184381246462950e-05;
|
|
237
|
+
|
|
238
|
+
bessel_j_scalar_type value, factor, r, rc, rs, w;
|
|
239
|
+
|
|
240
|
+
w = fabs(x);
|
|
241
|
+
if (x == 0)
|
|
242
|
+
{
|
|
243
|
+
return 0;
|
|
244
|
+
}
|
|
245
|
+
if (w <= 4) // w in (0, 4]
|
|
246
|
+
{
|
|
247
|
+
bessel_j_scalar_type y = x * x;
|
|
248
|
+
r = boost_evaluate_rational(bessel_j1_P1, bessel_j1_Q1, y);
|
|
249
|
+
factor = w * (w + x1) * ((w - x11/256) - x12);
|
|
250
|
+
value = factor * r;
|
|
251
|
+
}
|
|
252
|
+
else if (w <= 8) // w in (4, 8]
|
|
253
|
+
{
|
|
254
|
+
bessel_j_scalar_type y = x * x;
|
|
255
|
+
r = boost_evaluate_rational(bessel_j1_P2, bessel_j1_Q2, y);
|
|
256
|
+
factor = w * (w + x2) * ((w - x21/256) - x22);
|
|
257
|
+
value = factor * r;
|
|
258
|
+
}
|
|
259
|
+
else // w in (8, \infty)
|
|
260
|
+
{
|
|
261
|
+
bessel_j_scalar_type y = 8 / w;
|
|
262
|
+
bessel_j_scalar_type y2 = y * y;
|
|
263
|
+
bessel_j_scalar_type z = w - 0.75f * M_PI;
|
|
264
|
+
rc = boost_evaluate_rational(bessel_j1_PC, bessel_j1_QC, y2);
|
|
265
|
+
rs = boost_evaluate_rational(bessel_j1_PS, bessel_j1_QS, y2);
|
|
266
|
+
factor = sqrt(2 / (w * M_PI));
|
|
267
|
+
value = factor * (rc * cos(z) - y * rs * sin(z));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (x < 0)
|
|
271
|
+
{
|
|
272
|
+
value *= -1; // odd function
|
|
273
|
+
}
|
|
274
|
+
return value;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// }}}
|
|
278
|
+
|
|
279
|
+
// {{{ bessel_recur
|
|
280
|
+
|
|
281
|
+
/* Reduce the order by backward recurrence.
|
|
282
|
+
* AMS55 #9.1.27 and 9.1.73.
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
#define BESSEL_BIG 1.44115188075855872E+17
|
|
286
|
+
|
|
287
|
+
double bessel_recur(double *n, double x, double *newn, int cancel )
|
|
288
|
+
{
|
|
289
|
+
double pkm2, pkm1, pk, qkm2, qkm1;
|
|
290
|
+
/* double pkp1; */
|
|
291
|
+
double k, ans, qk, xk, yk, r, t, kf;
|
|
292
|
+
const double big = BESSEL_BIG;
|
|
293
|
+
int nflag, ctr;
|
|
294
|
+
|
|
295
|
+
/* continued fraction for Jn(x)/Jn-1(x) */
|
|
296
|
+
if( *n < 0.0 )
|
|
297
|
+
nflag = 1;
|
|
298
|
+
else
|
|
299
|
+
nflag = 0;
|
|
300
|
+
|
|
301
|
+
fstart:
|
|
302
|
+
|
|
303
|
+
#if DEBUG
|
|
304
|
+
printf( "recur: n = %.6e, newn = %.6e, cfrac = ", *n, *newn );
|
|
305
|
+
#endif
|
|
306
|
+
|
|
307
|
+
pkm2 = 0.0;
|
|
308
|
+
qkm2 = 1.0;
|
|
309
|
+
pkm1 = x;
|
|
310
|
+
qkm1 = *n + *n;
|
|
311
|
+
xk = -x * x;
|
|
312
|
+
yk = qkm1;
|
|
313
|
+
ans = 1.0;
|
|
314
|
+
ctr = 0;
|
|
315
|
+
do
|
|
316
|
+
{
|
|
317
|
+
yk += 2.0;
|
|
318
|
+
pk = pkm1 * yk + pkm2 * xk;
|
|
319
|
+
qk = qkm1 * yk + qkm2 * xk;
|
|
320
|
+
pkm2 = pkm1;
|
|
321
|
+
pkm1 = pk;
|
|
322
|
+
qkm2 = qkm1;
|
|
323
|
+
qkm1 = qk;
|
|
324
|
+
if( qk != 0 )
|
|
325
|
+
r = pk/qk;
|
|
326
|
+
else
|
|
327
|
+
r = 0.0;
|
|
328
|
+
if( r != 0 )
|
|
329
|
+
{
|
|
330
|
+
t = fabs( (ans - r)/r );
|
|
331
|
+
ans = r;
|
|
332
|
+
}
|
|
333
|
+
else
|
|
334
|
+
t = 1.0;
|
|
335
|
+
|
|
336
|
+
if( ++ctr > 1000 )
|
|
337
|
+
{
|
|
338
|
+
//mtherr( "jv", UNDERFLOW );
|
|
339
|
+
pk = nan((uint)24);
|
|
340
|
+
|
|
341
|
+
goto done;
|
|
342
|
+
}
|
|
343
|
+
if( t < DBL_EPSILON )
|
|
344
|
+
goto done;
|
|
345
|
+
|
|
346
|
+
if( fabs(pk) > big )
|
|
347
|
+
{
|
|
348
|
+
pkm2 /= big;
|
|
349
|
+
pkm1 /= big;
|
|
350
|
+
qkm2 /= big;
|
|
351
|
+
qkm1 /= big;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
while( t > DBL_EPSILON );
|
|
355
|
+
|
|
356
|
+
done:
|
|
357
|
+
|
|
358
|
+
#if DEBUG
|
|
359
|
+
printf( "%.6e\n", ans );
|
|
360
|
+
#endif
|
|
361
|
+
|
|
362
|
+
/* Change n to n-1 if n < 0 and the continued fraction is small
|
|
363
|
+
*/
|
|
364
|
+
if( nflag > 0 )
|
|
365
|
+
{
|
|
366
|
+
if( fabs(ans) < 0.125 )
|
|
367
|
+
{
|
|
368
|
+
nflag = -1;
|
|
369
|
+
*n = *n - 1.0;
|
|
370
|
+
goto fstart;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
kf = *newn;
|
|
376
|
+
|
|
377
|
+
/* backward recurrence
|
|
378
|
+
* 2k
|
|
379
|
+
* J (x) = --- J (x) - J (x)
|
|
380
|
+
* k-1 x k k+1
|
|
381
|
+
*/
|
|
382
|
+
|
|
383
|
+
pk = 1.0;
|
|
384
|
+
pkm1 = 1.0/ans;
|
|
385
|
+
k = *n - 1.0;
|
|
386
|
+
r = 2 * k;
|
|
387
|
+
do
|
|
388
|
+
{
|
|
389
|
+
pkm2 = (pkm1 * r - pk * x) / x;
|
|
390
|
+
/* pkp1 = pk; */
|
|
391
|
+
pk = pkm1;
|
|
392
|
+
pkm1 = pkm2;
|
|
393
|
+
r -= 2.0;
|
|
394
|
+
/*
|
|
395
|
+
t = fabs(pkp1) + fabs(pk);
|
|
396
|
+
if( (k > (kf + 2.5)) && (fabs(pkm1) < 0.25*t) )
|
|
397
|
+
{
|
|
398
|
+
k -= 1.0;
|
|
399
|
+
t = x*x;
|
|
400
|
+
pkm2 = ( (r*(r+2.0)-t)*pk - r*x*pkp1 )/t;
|
|
401
|
+
pkp1 = pk;
|
|
402
|
+
pk = pkm1;
|
|
403
|
+
pkm1 = pkm2;
|
|
404
|
+
r -= 2.0;
|
|
405
|
+
}
|
|
406
|
+
*/
|
|
407
|
+
k -= 1.0;
|
|
408
|
+
}
|
|
409
|
+
while( k > (kf + 0.5) );
|
|
410
|
+
|
|
411
|
+
/* Take the larger of the last two iterates
|
|
412
|
+
* on the theory that it may have less cancellation error.
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
if( cancel )
|
|
416
|
+
{
|
|
417
|
+
if( (kf >= 0.0) && (fabs(pk) > fabs(pkm1)) )
|
|
418
|
+
{
|
|
419
|
+
k += 1.0;
|
|
420
|
+
pkm2 = pk;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
*newn = k;
|
|
424
|
+
#if DEBUG
|
|
425
|
+
printf( "newn %.6e rans %.6e\n", k, pkm2 );
|
|
426
|
+
#endif
|
|
427
|
+
return( pkm2 );
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// }}}
|
|
431
|
+
|
|
432
|
+
// {{{ bessel_jvs
|
|
433
|
+
|
|
434
|
+
#define BESSEL_MAXGAM 171.624376956302725
|
|
435
|
+
#define BESSEL_MAXLOG 7.09782712893383996843E2
|
|
436
|
+
|
|
437
|
+
/* Ascending power series for Jv(x).
|
|
438
|
+
* AMS55 #9.1.10.
|
|
439
|
+
*/
|
|
440
|
+
|
|
441
|
+
double bessel_jvs(double n, double x)
|
|
442
|
+
{
|
|
443
|
+
double t, u, y, z, k;
|
|
444
|
+
int ex;
|
|
445
|
+
int sgngam = 1;
|
|
446
|
+
|
|
447
|
+
z = -x * x / 4.0;
|
|
448
|
+
u = 1.0;
|
|
449
|
+
y = u;
|
|
450
|
+
k = 1.0;
|
|
451
|
+
t = 1.0;
|
|
452
|
+
|
|
453
|
+
while( t > DBL_EPSILON )
|
|
454
|
+
{
|
|
455
|
+
u *= z / (k * (n+k));
|
|
456
|
+
y += u;
|
|
457
|
+
k += 1.0;
|
|
458
|
+
if( y != 0 )
|
|
459
|
+
t = fabs( u/y );
|
|
460
|
+
}
|
|
461
|
+
#if DEBUG
|
|
462
|
+
printf( "power series=%.5e ", y );
|
|
463
|
+
#endif
|
|
464
|
+
t = frexp( 0.5*x, &ex );
|
|
465
|
+
ex = ex * n;
|
|
466
|
+
if( (ex > -1023)
|
|
467
|
+
&& (ex < 1023)
|
|
468
|
+
&& (n > 0.0)
|
|
469
|
+
&& (n < (BESSEL_MAXGAM-1.0)) )
|
|
470
|
+
{
|
|
471
|
+
t = pow( 0.5*x, n ) / tgamma( n + 1.0 );
|
|
472
|
+
#if DEBUG
|
|
473
|
+
printf( "pow(.5*x, %.4e)/gamma(n+1)=%.5e\n", n, t );
|
|
474
|
+
#endif
|
|
475
|
+
y *= t;
|
|
476
|
+
}
|
|
477
|
+
else
|
|
478
|
+
{
|
|
479
|
+
#if DEBUG
|
|
480
|
+
z = n * log(0.5*x);
|
|
481
|
+
k = lgamma( n+1.0 );
|
|
482
|
+
t = z - k;
|
|
483
|
+
printf( "log pow=%.5e, lgam(%.4e)=%.5e\n", z, n+1.0, k );
|
|
484
|
+
#else
|
|
485
|
+
t = n * log(0.5*x) - lgamma(n + 1.0);
|
|
486
|
+
#endif
|
|
487
|
+
if( y < 0 )
|
|
488
|
+
{
|
|
489
|
+
sgngam = -sgngam;
|
|
490
|
+
y = -y;
|
|
491
|
+
}
|
|
492
|
+
t += log(y);
|
|
493
|
+
#if DEBUG
|
|
494
|
+
printf( "log y=%.5e\n", log(y) );
|
|
495
|
+
#endif
|
|
496
|
+
if( t < -BESSEL_MAXLOG )
|
|
497
|
+
{
|
|
498
|
+
return( 0.0 );
|
|
499
|
+
}
|
|
500
|
+
if( t > BESSEL_MAXLOG )
|
|
501
|
+
{
|
|
502
|
+
// mtherr( "Jv", OVERFLOW );
|
|
503
|
+
return( DBL_MAX);
|
|
504
|
+
}
|
|
505
|
+
y = sgngam * exp( t );
|
|
506
|
+
}
|
|
507
|
+
return(y);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// }}}
|
|
511
|
+
|
|
512
|
+
// {{{ bessel_jnt
|
|
513
|
+
|
|
514
|
+
__constant const double bessel_jnt_PF2[] = {
|
|
515
|
+
-9.0000000000000000000e-2,
|
|
516
|
+
8.5714285714285714286e-2
|
|
517
|
+
};
|
|
518
|
+
__constant const double bessel_jnt_PF3[] = {
|
|
519
|
+
1.3671428571428571429e-1,
|
|
520
|
+
-5.4920634920634920635e-2,
|
|
521
|
+
-4.4444444444444444444e-3
|
|
522
|
+
};
|
|
523
|
+
__constant const double bessel_jnt_PF4[] = {
|
|
524
|
+
1.3500000000000000000e-3,
|
|
525
|
+
-1.6036054421768707483e-1,
|
|
526
|
+
4.2590187590187590188e-2,
|
|
527
|
+
2.7330447330447330447e-3
|
|
528
|
+
};
|
|
529
|
+
__constant const double bessel_jnt_PG1[] = {
|
|
530
|
+
-2.4285714285714285714e-1,
|
|
531
|
+
1.4285714285714285714e-2
|
|
532
|
+
};
|
|
533
|
+
__constant const double bessel_jnt_PG2[] = {
|
|
534
|
+
-9.0000000000000000000e-3,
|
|
535
|
+
1.9396825396825396825e-1,
|
|
536
|
+
-1.1746031746031746032e-2
|
|
537
|
+
};
|
|
538
|
+
__constant const double bessel_jnt_PG3[] = {
|
|
539
|
+
1.9607142857142857143e-2,
|
|
540
|
+
-1.5983694083694083694e-1,
|
|
541
|
+
6.3838383838383838384e-3
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
double bessel_jnt(double n, double x)
|
|
545
|
+
{
|
|
546
|
+
double z, zz, z3;
|
|
547
|
+
double cbn, n23, cbtwo;
|
|
548
|
+
double ai, aip, bi, bip; /* Airy functions */
|
|
549
|
+
double nk, fk, gk, pp, qq;
|
|
550
|
+
double F[5], G[4];
|
|
551
|
+
int k;
|
|
552
|
+
|
|
553
|
+
cbn = cbrt(n);
|
|
554
|
+
z = (x - n)/cbn;
|
|
555
|
+
cbtwo = cbrt( 2.0 );
|
|
556
|
+
|
|
557
|
+
/* Airy function */
|
|
558
|
+
zz = -cbtwo * z;
|
|
559
|
+
airy( zz, &ai, &aip, &bi, &bip );
|
|
560
|
+
|
|
561
|
+
/* polynomials in expansion */
|
|
562
|
+
zz = z * z;
|
|
563
|
+
z3 = zz * z;
|
|
564
|
+
F[0] = 1.0;
|
|
565
|
+
F[1] = -z/5.0;
|
|
566
|
+
F[2] = cephes_polevl( z3, bessel_jnt_PF2, 1 ) * zz;
|
|
567
|
+
F[3] = cephes_polevl( z3, bessel_jnt_PF3, 2 );
|
|
568
|
+
F[4] = cephes_polevl( z3, bessel_jnt_PF4, 3 ) * z;
|
|
569
|
+
G[0] = 0.3 * zz;
|
|
570
|
+
G[1] = cephes_polevl( z3, bessel_jnt_PG1, 1 );
|
|
571
|
+
G[2] = cephes_polevl( z3, bessel_jnt_PG2, 2 ) * z;
|
|
572
|
+
G[3] = cephes_polevl( z3, bessel_jnt_PG3, 2 ) * zz;
|
|
573
|
+
#if DEBUG
|
|
574
|
+
for( k=0; k<=4; k++ )
|
|
575
|
+
printf( "F[%d] = %.5E\n", k, F[k] );
|
|
576
|
+
for( k=0; k<=3; k++ )
|
|
577
|
+
printf( "G[%d] = %.5E\n", k, G[k] );
|
|
578
|
+
#endif
|
|
579
|
+
pp = 0.0;
|
|
580
|
+
qq = 0.0;
|
|
581
|
+
nk = 1.0;
|
|
582
|
+
n23 = cbrt( n * n );
|
|
583
|
+
|
|
584
|
+
for( k=0; k<=4; k++ )
|
|
585
|
+
{
|
|
586
|
+
fk = F[k]*nk;
|
|
587
|
+
pp += fk;
|
|
588
|
+
if( k != 4 )
|
|
589
|
+
{
|
|
590
|
+
gk = G[k]*nk;
|
|
591
|
+
qq += gk;
|
|
592
|
+
}
|
|
593
|
+
#if DEBUG
|
|
594
|
+
printf("fk[%d] %.5E, gk[%d] %.5E\n", k, fk, k, gk );
|
|
595
|
+
#endif
|
|
596
|
+
nk /= n23;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
fk = cbtwo * ai * pp/cbn + cbrt(4.0) * aip * qq/n;
|
|
600
|
+
return(fk);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// }}}
|
|
604
|
+
|
|
605
|
+
// {{{ bessel_jnx
|
|
606
|
+
|
|
607
|
+
__constant const double bessel_jnx_lambda[] = {
|
|
608
|
+
1.0,
|
|
609
|
+
1.041666666666666666666667E-1,
|
|
610
|
+
8.355034722222222222222222E-2,
|
|
611
|
+
1.282265745563271604938272E-1,
|
|
612
|
+
2.918490264641404642489712E-1,
|
|
613
|
+
8.816272674437576524187671E-1,
|
|
614
|
+
3.321408281862767544702647E+0,
|
|
615
|
+
1.499576298686255465867237E+1,
|
|
616
|
+
7.892301301158651813848139E+1,
|
|
617
|
+
4.744515388682643231611949E+2,
|
|
618
|
+
3.207490090890661934704328E+3
|
|
619
|
+
};
|
|
620
|
+
__constant const double bessel_jnx_mu[] = {
|
|
621
|
+
1.0,
|
|
622
|
+
-1.458333333333333333333333E-1,
|
|
623
|
+
-9.874131944444444444444444E-2,
|
|
624
|
+
-1.433120539158950617283951E-1,
|
|
625
|
+
-3.172272026784135480967078E-1,
|
|
626
|
+
-9.424291479571202491373028E-1,
|
|
627
|
+
-3.511203040826354261542798E+0,
|
|
628
|
+
-1.572726362036804512982712E+1,
|
|
629
|
+
-8.228143909718594444224656E+1,
|
|
630
|
+
-4.923553705236705240352022E+2,
|
|
631
|
+
-3.316218568547972508762102E+3
|
|
632
|
+
};
|
|
633
|
+
__constant const double bessel_jnx_P1[] = {
|
|
634
|
+
-2.083333333333333333333333E-1,
|
|
635
|
+
1.250000000000000000000000E-1
|
|
636
|
+
};
|
|
637
|
+
__constant const double bessel_jnx_P2[] = {
|
|
638
|
+
3.342013888888888888888889E-1,
|
|
639
|
+
-4.010416666666666666666667E-1,
|
|
640
|
+
7.031250000000000000000000E-2
|
|
641
|
+
};
|
|
642
|
+
__constant const double bessel_jnx_P3[] = {
|
|
643
|
+
-1.025812596450617283950617E+0,
|
|
644
|
+
1.846462673611111111111111E+0,
|
|
645
|
+
-8.912109375000000000000000E-1,
|
|
646
|
+
7.324218750000000000000000E-2
|
|
647
|
+
};
|
|
648
|
+
__constant const double bessel_jnx_P4[] = {
|
|
649
|
+
4.669584423426247427983539E+0,
|
|
650
|
+
-1.120700261622299382716049E+1,
|
|
651
|
+
8.789123535156250000000000E+0,
|
|
652
|
+
-2.364086914062500000000000E+0,
|
|
653
|
+
1.121520996093750000000000E-1
|
|
654
|
+
};
|
|
655
|
+
__constant const double bessel_jnx_P5[] = {
|
|
656
|
+
-2.8212072558200244877E1,
|
|
657
|
+
8.4636217674600734632E1,
|
|
658
|
+
-9.1818241543240017361E1,
|
|
659
|
+
4.2534998745388454861E1,
|
|
660
|
+
-7.3687943594796316964E0,
|
|
661
|
+
2.27108001708984375E-1
|
|
662
|
+
};
|
|
663
|
+
__constant const double bessel_jnx_P6[] = {
|
|
664
|
+
2.1257013003921712286E2,
|
|
665
|
+
-7.6525246814118164230E2,
|
|
666
|
+
1.0599904525279998779E3,
|
|
667
|
+
-6.9957962737613254123E2,
|
|
668
|
+
2.1819051174421159048E2,
|
|
669
|
+
-2.6491430486951555525E1,
|
|
670
|
+
5.7250142097473144531E-1
|
|
671
|
+
};
|
|
672
|
+
__constant const double bessel_jnx_P7[] = {
|
|
673
|
+
-1.9194576623184069963E3,
|
|
674
|
+
8.0617221817373093845E3,
|
|
675
|
+
-1.3586550006434137439E4,
|
|
676
|
+
1.1655393336864533248E4,
|
|
677
|
+
-5.3056469786134031084E3,
|
|
678
|
+
1.2009029132163524628E3,
|
|
679
|
+
-1.0809091978839465550E2,
|
|
680
|
+
1.7277275025844573975E0
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
double bessel_jnx(double n, double x)
|
|
684
|
+
{
|
|
685
|
+
double zeta, sqz, zz, zp, np;
|
|
686
|
+
double cbn, n23, t, z, sz;
|
|
687
|
+
double pp, qq, z32i, zzi;
|
|
688
|
+
double ak, bk, akl, bkl;
|
|
689
|
+
int sign, doa, dob, nflg, k, s, tk, tkp1, m;
|
|
690
|
+
double u[8];
|
|
691
|
+
double ai, aip, bi, bip;
|
|
692
|
+
|
|
693
|
+
/* Test for x very close to n.
|
|
694
|
+
* Use expansion for transition region if so.
|
|
695
|
+
*/
|
|
696
|
+
cbn = cbrt(n);
|
|
697
|
+
z = (x - n)/cbn;
|
|
698
|
+
if( fabs(z) <= 0.7 )
|
|
699
|
+
return( bessel_jnt(n,x) );
|
|
700
|
+
|
|
701
|
+
z = x/n;
|
|
702
|
+
zz = 1.0 - z*z;
|
|
703
|
+
if( zz == 0.0 )
|
|
704
|
+
return(0.0);
|
|
705
|
+
|
|
706
|
+
if( zz > 0.0 )
|
|
707
|
+
{
|
|
708
|
+
sz = sqrt( zz );
|
|
709
|
+
t = 1.5 * (log( (1.0+sz)/z ) - sz ); /* zeta ** 3/2 */
|
|
710
|
+
zeta = cbrt( t * t );
|
|
711
|
+
nflg = 1;
|
|
712
|
+
}
|
|
713
|
+
else
|
|
714
|
+
{
|
|
715
|
+
sz = sqrt(-zz);
|
|
716
|
+
t = 1.5 * (sz - acos(1.0/z));
|
|
717
|
+
zeta = -cbrt( t * t );
|
|
718
|
+
nflg = -1;
|
|
719
|
+
}
|
|
720
|
+
z32i = fabs(1.0/t);
|
|
721
|
+
sqz = cbrt(t);
|
|
722
|
+
|
|
723
|
+
/* Airy function */
|
|
724
|
+
n23 = cbrt( n * n );
|
|
725
|
+
t = n23 * zeta;
|
|
726
|
+
|
|
727
|
+
#if DEBUG
|
|
728
|
+
printf("zeta %.5E, Airy(%.5E)\n", zeta, t );
|
|
729
|
+
#endif
|
|
730
|
+
airy( t, &ai, &aip, &bi, &bip );
|
|
731
|
+
|
|
732
|
+
/* polynomials in expansion */
|
|
733
|
+
u[0] = 1.0;
|
|
734
|
+
zzi = 1.0/zz;
|
|
735
|
+
u[1] = cephes_polevl( zzi, bessel_jnx_P1, 1 )/sz;
|
|
736
|
+
u[2] = cephes_polevl( zzi, bessel_jnx_P2, 2 )/zz;
|
|
737
|
+
u[3] = cephes_polevl( zzi, bessel_jnx_P3, 3 )/(sz*zz);
|
|
738
|
+
pp = zz*zz;
|
|
739
|
+
u[4] = cephes_polevl( zzi, bessel_jnx_P4, 4 )/pp;
|
|
740
|
+
u[5] = cephes_polevl( zzi, bessel_jnx_P5, 5 )/(pp*sz);
|
|
741
|
+
pp *= zz;
|
|
742
|
+
u[6] = cephes_polevl( zzi, bessel_jnx_P6, 6 )/pp;
|
|
743
|
+
u[7] = cephes_polevl( zzi, bessel_jnx_P7, 7 )/(pp*sz);
|
|
744
|
+
|
|
745
|
+
#if DEBUG
|
|
746
|
+
for( k=0; k<=7; k++ )
|
|
747
|
+
printf( "u[%d] = %.5E\n", k, u[k] );
|
|
748
|
+
#endif
|
|
749
|
+
|
|
750
|
+
pp = 0.0;
|
|
751
|
+
qq = 0.0;
|
|
752
|
+
np = 1.0;
|
|
753
|
+
/* flags to stop when terms get larger */
|
|
754
|
+
doa = 1;
|
|
755
|
+
dob = 1;
|
|
756
|
+
akl = DBL_MAX;
|
|
757
|
+
bkl = DBL_MAX;
|
|
758
|
+
|
|
759
|
+
for( k=0; k<=3; k++ )
|
|
760
|
+
{
|
|
761
|
+
tk = 2 * k;
|
|
762
|
+
tkp1 = tk + 1;
|
|
763
|
+
zp = 1.0;
|
|
764
|
+
ak = 0.0;
|
|
765
|
+
bk = 0.0;
|
|
766
|
+
for( s=0; s<=tk; s++ )
|
|
767
|
+
{
|
|
768
|
+
if( doa )
|
|
769
|
+
{
|
|
770
|
+
if( (s & 3) > 1 )
|
|
771
|
+
sign = nflg;
|
|
772
|
+
else
|
|
773
|
+
sign = 1;
|
|
774
|
+
ak += sign * bessel_jnx_mu[s] * zp * u[tk-s];
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if( dob )
|
|
778
|
+
{
|
|
779
|
+
m = tkp1 - s;
|
|
780
|
+
if( ((m+1) & 3) > 1 )
|
|
781
|
+
sign = nflg;
|
|
782
|
+
else
|
|
783
|
+
sign = 1;
|
|
784
|
+
bk += sign * bessel_jnx_lambda[s] * zp * u[m];
|
|
785
|
+
}
|
|
786
|
+
zp *= z32i;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if( doa )
|
|
790
|
+
{
|
|
791
|
+
ak *= np;
|
|
792
|
+
t = fabs(ak);
|
|
793
|
+
if( t < akl )
|
|
794
|
+
{
|
|
795
|
+
akl = t;
|
|
796
|
+
pp += ak;
|
|
797
|
+
}
|
|
798
|
+
else
|
|
799
|
+
doa = 0;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if( dob )
|
|
803
|
+
{
|
|
804
|
+
bk += bessel_jnx_lambda[tkp1] * zp * u[0];
|
|
805
|
+
bk *= -np/sqz;
|
|
806
|
+
t = fabs(bk);
|
|
807
|
+
if( t < bkl )
|
|
808
|
+
{
|
|
809
|
+
bkl = t;
|
|
810
|
+
qq += bk;
|
|
811
|
+
}
|
|
812
|
+
else
|
|
813
|
+
dob = 0;
|
|
814
|
+
}
|
|
815
|
+
#if DEBUG
|
|
816
|
+
printf("a[%d] %.5E, b[%d] %.5E\n", k, ak, k, bk );
|
|
817
|
+
#endif
|
|
818
|
+
if( np < DBL_EPSILON )
|
|
819
|
+
break;
|
|
820
|
+
np /= n*n;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/* normalizing factor ( 4*zeta/(1 - z**2) )**1/4 */
|
|
824
|
+
t = 4.0 * zeta/zz;
|
|
825
|
+
t = sqrt( sqrt(t) );
|
|
826
|
+
|
|
827
|
+
t *= ai*pp/cbrt(n) + aip*qq/(n23*n);
|
|
828
|
+
return(t);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// }}}
|
|
832
|
+
|
|
833
|
+
// {{{ bessel_hankel
|
|
834
|
+
|
|
835
|
+
/* Hankel's asymptotic expansion
|
|
836
|
+
* for large x.
|
|
837
|
+
* AMS55 #9.2.5.
|
|
838
|
+
*/
|
|
839
|
+
|
|
840
|
+
double bessel_hankel( double n, double x )
|
|
841
|
+
{
|
|
842
|
+
double t, u, z, k, sign, conv;
|
|
843
|
+
double p, q, j, m, pp, qq;
|
|
844
|
+
int flag;
|
|
845
|
+
|
|
846
|
+
m = 4.0*n*n;
|
|
847
|
+
j = 1.0;
|
|
848
|
+
z = 8.0 * x;
|
|
849
|
+
k = 1.0;
|
|
850
|
+
p = 1.0;
|
|
851
|
+
u = (m - 1.0)/z;
|
|
852
|
+
q = u;
|
|
853
|
+
sign = 1.0;
|
|
854
|
+
conv = 1.0;
|
|
855
|
+
flag = 0;
|
|
856
|
+
t = 1.0;
|
|
857
|
+
pp = 1.0e38;
|
|
858
|
+
qq = 1.0e38;
|
|
859
|
+
|
|
860
|
+
while( t > DBL_EPSILON )
|
|
861
|
+
{
|
|
862
|
+
k += 2.0;
|
|
863
|
+
j += 1.0;
|
|
864
|
+
sign = -sign;
|
|
865
|
+
u *= (m - k * k)/(j * z);
|
|
866
|
+
p += sign * u;
|
|
867
|
+
k += 2.0;
|
|
868
|
+
j += 1.0;
|
|
869
|
+
u *= (m - k * k)/(j * z);
|
|
870
|
+
q += sign * u;
|
|
871
|
+
t = fabs(u/p);
|
|
872
|
+
if( t < conv )
|
|
873
|
+
{
|
|
874
|
+
conv = t;
|
|
875
|
+
qq = q;
|
|
876
|
+
pp = p;
|
|
877
|
+
flag = 1;
|
|
878
|
+
}
|
|
879
|
+
/* stop if the terms start getting larger */
|
|
880
|
+
if( (flag != 0) && (t > conv) )
|
|
881
|
+
{
|
|
882
|
+
#if DEBUG
|
|
883
|
+
printf( "Hankel: convergence to %.4E\n", conv );
|
|
884
|
+
#endif
|
|
885
|
+
goto hank1;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
hank1:
|
|
890
|
+
u = x - (0.5*n + 0.25) * M_PI;
|
|
891
|
+
t = sqrt( 2.0/(M_PI*x) ) * ( pp * cos(u) - qq * sin(u) );
|
|
892
|
+
#if DEBUG
|
|
893
|
+
printf( "hank: %.6e\n", t );
|
|
894
|
+
#endif
|
|
895
|
+
return( t );
|
|
896
|
+
}
|
|
897
|
+
// }}}
|
|
898
|
+
|
|
899
|
+
// {{{ bessel_jv
|
|
900
|
+
|
|
901
|
+
// SciPy says jn has no advantage over jv, so alias the two.
|
|
902
|
+
|
|
903
|
+
#define bessel_jn bessel_jv
|
|
904
|
+
|
|
905
|
+
double bessel_jv(double n, double x)
|
|
906
|
+
{
|
|
907
|
+
double k, q, t, y, an;
|
|
908
|
+
int i, sign, nint;
|
|
909
|
+
|
|
910
|
+
nint = 0; /* Flag for integer n */
|
|
911
|
+
sign = 1; /* Flag for sign inversion */
|
|
912
|
+
an = fabs( n );
|
|
913
|
+
y = floor( an );
|
|
914
|
+
if( y == an )
|
|
915
|
+
{
|
|
916
|
+
nint = 1;
|
|
917
|
+
i = an - 16384.0 * floor( an/16384.0 );
|
|
918
|
+
if( n < 0.0 )
|
|
919
|
+
{
|
|
920
|
+
if( i & 1 )
|
|
921
|
+
sign = -sign;
|
|
922
|
+
n = an;
|
|
923
|
+
}
|
|
924
|
+
if( x < 0.0 )
|
|
925
|
+
{
|
|
926
|
+
if( i & 1 )
|
|
927
|
+
sign = -sign;
|
|
928
|
+
x = -x;
|
|
929
|
+
}
|
|
930
|
+
if( n == 0.0 )
|
|
931
|
+
return( bessel_j0(x) );
|
|
932
|
+
if( n == 1.0 )
|
|
933
|
+
return( sign * bessel_j1(x) );
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
if( (x < 0.0) && (y != an) )
|
|
937
|
+
{
|
|
938
|
+
// mtherr( "Jv", DOMAIN );
|
|
939
|
+
// y = 0.0;
|
|
940
|
+
y = nan((uint)22);
|
|
941
|
+
goto done;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
y = fabs(x);
|
|
945
|
+
|
|
946
|
+
if( y < DBL_EPSILON )
|
|
947
|
+
goto underf;
|
|
948
|
+
|
|
949
|
+
k = 3.6 * sqrt(y);
|
|
950
|
+
t = 3.6 * sqrt(an);
|
|
951
|
+
if( (y < t) && (an > 21.0) )
|
|
952
|
+
return( sign * bessel_jvs(n,x) );
|
|
953
|
+
if( (an < k) && (y > 21.0) )
|
|
954
|
+
return( sign * bessel_hankel(n,x) );
|
|
955
|
+
|
|
956
|
+
if( an < 500.0 )
|
|
957
|
+
{
|
|
958
|
+
/* Note: if x is too large, the continued
|
|
959
|
+
* fraction will fail; but then the
|
|
960
|
+
* Hankel expansion can be used.
|
|
961
|
+
*/
|
|
962
|
+
if( nint != 0 )
|
|
963
|
+
{
|
|
964
|
+
k = 0.0;
|
|
965
|
+
q = bessel_recur( &n, x, &k, 1 );
|
|
966
|
+
if( k == 0.0 )
|
|
967
|
+
{
|
|
968
|
+
y = bessel_j0(x)/q;
|
|
969
|
+
goto done;
|
|
970
|
+
}
|
|
971
|
+
if( k == 1.0 )
|
|
972
|
+
{
|
|
973
|
+
y = bessel_j1(x)/q;
|
|
974
|
+
goto done;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if( an > 2.0 * y )
|
|
979
|
+
goto rlarger;
|
|
980
|
+
|
|
981
|
+
if( (n >= 0.0) && (n < 20.0)
|
|
982
|
+
&& (y > 6.0) && (y < 20.0) )
|
|
983
|
+
{
|
|
984
|
+
/* Recur backwards from a larger value of n
|
|
985
|
+
*/
|
|
986
|
+
rlarger:
|
|
987
|
+
k = n;
|
|
988
|
+
|
|
989
|
+
y = y + an + 1.0;
|
|
990
|
+
if( y < 30.0 )
|
|
991
|
+
y = 30.0;
|
|
992
|
+
y = n + floor(y-n);
|
|
993
|
+
q = bessel_recur( &y, x, &k, 0 );
|
|
994
|
+
y = bessel_jvs(y,x) * q;
|
|
995
|
+
goto done;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
if( k <= 30.0 )
|
|
999
|
+
{
|
|
1000
|
+
k = 2.0;
|
|
1001
|
+
}
|
|
1002
|
+
else if( k < 90.0 )
|
|
1003
|
+
{
|
|
1004
|
+
k = (3*k)/4;
|
|
1005
|
+
}
|
|
1006
|
+
if( an > (k + 3.0) )
|
|
1007
|
+
{
|
|
1008
|
+
if( n < 0.0 )
|
|
1009
|
+
k = -k;
|
|
1010
|
+
q = n - floor(n);
|
|
1011
|
+
k = floor(k) + q;
|
|
1012
|
+
if( n > 0.0 )
|
|
1013
|
+
q = bessel_recur( &n, x, &k, 1 );
|
|
1014
|
+
else
|
|
1015
|
+
{
|
|
1016
|
+
t = k;
|
|
1017
|
+
k = n;
|
|
1018
|
+
q = bessel_recur( &t, x, &k, 1 );
|
|
1019
|
+
k = t;
|
|
1020
|
+
}
|
|
1021
|
+
if( q == 0.0 )
|
|
1022
|
+
{
|
|
1023
|
+
underf:
|
|
1024
|
+
y = 0.0;
|
|
1025
|
+
goto done;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
else
|
|
1029
|
+
{
|
|
1030
|
+
k = n;
|
|
1031
|
+
q = 1.0;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/* boundary between convergence of
|
|
1035
|
+
* power series and Hankel expansion
|
|
1036
|
+
*/
|
|
1037
|
+
y = fabs(k);
|
|
1038
|
+
if( y < 26.0 )
|
|
1039
|
+
t = (0.0083*y + 0.09)*y + 12.9;
|
|
1040
|
+
else
|
|
1041
|
+
t = 0.9 * y;
|
|
1042
|
+
|
|
1043
|
+
if( x > t )
|
|
1044
|
+
y = bessel_hankel(k,x);
|
|
1045
|
+
else
|
|
1046
|
+
y = bessel_jvs(k,x);
|
|
1047
|
+
#if DEBUG
|
|
1048
|
+
printf( "y = %.16e, recur q = %.16e\n", y, q );
|
|
1049
|
+
#endif
|
|
1050
|
+
if( n > 0.0 )
|
|
1051
|
+
y /= q;
|
|
1052
|
+
else
|
|
1053
|
+
y *= q;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
else
|
|
1057
|
+
{
|
|
1058
|
+
/* For large n, use the uniform expansion
|
|
1059
|
+
* or the transitional expansion.
|
|
1060
|
+
* But if x is of the order of n**2,
|
|
1061
|
+
* these may blow up, whereas the
|
|
1062
|
+
* Hankel expansion will then work.
|
|
1063
|
+
*/
|
|
1064
|
+
if( n < 0.0 )
|
|
1065
|
+
{
|
|
1066
|
+
//mtherr( "Jv", TLOSS );
|
|
1067
|
+
//y = 0.0;
|
|
1068
|
+
y = nan((uint)23);
|
|
1069
|
+
goto done;
|
|
1070
|
+
}
|
|
1071
|
+
t = x/n;
|
|
1072
|
+
t /= n;
|
|
1073
|
+
if( t > 0.3 )
|
|
1074
|
+
y = bessel_hankel(n,x);
|
|
1075
|
+
else
|
|
1076
|
+
y = bessel_jnx(n,x);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
done: return( sign * y);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
// }}}
|
|
1083
|
+
|
|
1084
|
+
// vim: fdm=marker
|