1
// Pieced together from Boost C++ and Cephes by
2
// Andreas Kloeckner (C) 2012
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)
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
22
#include <pyopencl-cephes.cl>
23
#include <pyopencl-airy.cl>
27
// {{{ evaluate_rational
29
T evaluate_rational_backend(__constant const T* num, __constant const T* denom, T z, int count)
36
for(int i = (int)count - 2; i >= 0; --i)
49
for(unsigned i = 1; i < count; ++i)
62
#define evaluate_rational(num, denom, z) \
63
evaluate_rational_backend(num, denom, z, sizeof(num)/sizeof(T))
67
__constant const T bessel_j0_P1[] = {
68
-4.1298668500990866786e+11,
69
2.7282507878605942706e+10,
70
-6.2140700423540120665e+08,
71
6.6302997904833794242e+06,
72
-3.6629814655107086448e+04,
73
1.0344222815443188943e+02,
74
-1.2117036164593528341e-01
76
__constant const T bessel_j0_Q1[] = {
77
2.3883787996332290397e+12,
78
2.6328198300859648632e+10,
79
1.3985097372263433271e+08,
80
4.5612696224219938200e+05,
81
9.3614022392337710626e+02,
85
__constant const T bessel_j0_P2[] = {
86
-1.8319397969392084011e+03,
87
-1.2254078161378989535e+04,
88
-7.2879702464464618998e+03,
89
1.0341910641583726701e+04,
90
1.1725046279757103576e+04,
91
4.4176707025325087628e+03,
92
7.4321196680624245801e+02,
93
4.8591703355916499363e+01
95
__constant const T bessel_j0_Q2[] = {
96
-3.5783478026152301072e+05,
97
2.4599102262586308984e+05,
98
-8.4055062591169562211e+04,
99
1.8680990008359188352e+04,
100
-2.9458766545509337327e+03,
101
3.3307310774649071172e+02,
102
-2.5258076240801555057e+01,
105
__constant const T bessel_j0_PC[] = {
106
2.2779090197304684302e+04,
107
4.1345386639580765797e+04,
108
2.1170523380864944322e+04,
109
3.4806486443249270347e+03,
110
1.5376201909008354296e+02,
111
8.8961548424210455236e-01
113
__constant const T bessel_j0_QC[] = {
114
2.2779090197304684318e+04,
115
4.1370412495510416640e+04,
116
2.1215350561880115730e+04,
117
3.5028735138235608207e+03,
118
1.5711159858080893649e+02,
121
__constant const T bessel_j0_PS[] = {
122
-8.9226600200800094098e+01,
123
-1.8591953644342993800e+02,
124
-1.1183429920482737611e+02,
125
-2.2300261666214198472e+01,
126
-1.2441026745835638459e+00,
127
-8.8033303048680751817e-03
129
__constant const T bessel_j0_QS[] = {
130
5.7105024128512061905e+03,
131
1.1951131543434613647e+04,
132
7.2642780169211018836e+03,
133
1.4887231232283756582e+03,
134
9.0593769594993125859e+01,
140
const T x1 = 2.4048255576957727686e+00,
141
x2 = 5.5200781102863106496e+00,
143
x12 = -1.42444230422723137837e-03,
145
x22 = 5.46860286310649596604e-04;
147
T value, factor, r, rc, rs;
151
x = -x; // even function
157
if (x <= 4) // x in (0, 4]
160
r = evaluate_rational(bessel_j0_P1, bessel_j0_Q1, y);
161
factor = (x + x1) * ((x - x11/256) - x12);
164
else if (x <= 8.0) // x in (4, 8]
166
T y = 1 - (x * x)/64;
167
r = evaluate_rational(bessel_j0_P2, bessel_j0_Q2, y);
168
factor = (x + x2) * ((x - x21/256) - x22);
171
else // x in (8, \infty)
175
T z = x - 0.25f * M_PI;
176
rc = evaluate_rational(bessel_j0_PC, bessel_j0_QC, y2);
177
rs = evaluate_rational(bessel_j0_PS, bessel_j0_QS, y2);
178
factor = sqrt(2 / (x * M_PI));
179
value = factor * (rc * cos(z) - y * rs * sin(z));
189
__constant const T bessel_j1_P1[] = {
190
-1.4258509801366645672e+11,
191
6.6781041261492395835e+09,
192
-1.1548696764841276794e+08,
193
9.8062904098958257677e+05,
194
-4.4615792982775076130e+03,
195
1.0650724020080236441e+01,
196
-1.0767857011487300348e-02
198
__constant const T bessel_j1_Q1[] = {
199
4.1868604460820175290e+12,
200
4.2091902282580133541e+10,
201
2.0228375140097033958e+08,
202
5.9117614494174794095e+05,
203
1.0742272239517380498e+03,
207
__constant const T bessel_j1_P2[] = {
208
-1.7527881995806511112e+16,
209
1.6608531731299018674e+15,
210
-3.6658018905416665164e+13,
211
3.5580665670910619166e+11,
212
-1.8113931269860667829e+09,
213
5.0793266148011179143e+06,
214
-7.5023342220781607561e+03,
215
4.6179191852758252278e+00
217
__constant const T bessel_j1_Q2[] = {
218
1.7253905888447681194e+18,
219
1.7128800897135812012e+16,
220
8.4899346165481429307e+13,
221
2.7622777286244082666e+11,
222
6.4872502899596389593e+08,
223
1.1267125065029138050e+06,
224
1.3886978985861357615e+03,
227
__constant const T bessel_j1_PC[] = {
228
-4.4357578167941278571e+06,
229
-9.9422465050776411957e+06,
230
-6.6033732483649391093e+06,
231
-1.5235293511811373833e+06,
232
-1.0982405543459346727e+05,
233
-1.6116166443246101165e+03,
236
__constant const T bessel_j1_QC[] = {
237
-4.4357578167941278568e+06,
238
-9.9341243899345856590e+06,
239
-6.5853394797230870728e+06,
240
-1.5118095066341608816e+06,
241
-1.0726385991103820119e+05,
242
-1.4550094401904961825e+03,
245
__constant const T bessel_j1_PS[] = {
246
3.3220913409857223519e+04,
247
8.5145160675335701966e+04,
248
6.6178836581270835179e+04,
249
1.8494262873223866797e+04,
250
1.7063754290207680021e+03,
251
3.5265133846636032186e+01,
254
__constant const T bessel_j1_QS[] = {
255
7.0871281941028743574e+05,
256
1.8194580422439972989e+06,
257
1.4194606696037208929e+06,
258
4.0029443582266975117e+05,
259
3.7890229745772202641e+04,
260
8.6383677696049909675e+02,
267
const T x1 = 3.8317059702075123156e+00,
268
x2 = 7.0155866698156187535e+00,
270
x12 = -3.2527979248768438556e-04,
272
x22 = -3.8330184381246462950e-05;
274
T value, factor, r, rc, rs, w;
281
if (w <= 4) // w in (0, 4]
284
r = evaluate_rational(bessel_j1_P1, bessel_j1_Q1, y);
285
factor = w * (w + x1) * ((w - x11/256) - x12);
288
else if (w <= 8) // w in (4, 8]
291
r = evaluate_rational(bessel_j1_P2, bessel_j1_Q2, y);
292
factor = w * (w + x2) * ((w - x21/256) - x22);
295
else // w in (8, \infty)
299
T z = w - 0.75f * M_PI;
300
rc = evaluate_rational(bessel_j1_PC, bessel_j1_QC, y2);
301
rs = evaluate_rational(bessel_j1_PS, bessel_j1_QS, y2);
302
factor = sqrt(2 / (w * M_PI));
303
value = factor * (rc * cos(z) - y * rs * sin(z));
308
value *= -1; // odd function
317
/* Reduce the order by backward recurrence.
318
* AMS55 #9.1.27 and 9.1.73.
321
#define BESSEL_BIG 1.44115188075855872E+17
323
double bessel_recur(double *n, double x, double *newn, int cancel )
325
double pkm2, pkm1, pk, qkm2, qkm1;
327
double k, ans, qk, xk, yk, r, t, kf;
328
const double big = BESSEL_BIG;
331
/* continued fraction for Jn(x)/Jn-1(x) */
340
printf( "recur: n = %.6e, newn = %.6e, cfrac = ", *n, *newn );
354
pk = pkm1 * yk + pkm2 * xk;
355
qk = qkm1 * yk + qkm2 * xk;
366
t = fabs( (ans - r)/r );
374
//mtherr( "jv", UNDERFLOW );
379
if( t < DBL_EPSILON )
390
while( t > DBL_EPSILON );
395
printf( "%.6e\n", ans );
398
/* Change n to n-1 if n < 0 and the continued fraction is small
402
if( fabs(ans) < 0.125 )
413
/* backward recurrence
415
* J (x) = --- J (x) - J (x)
425
pkm2 = (pkm1 * r - pk * x) / x;
431
t = fabs(pkp1) + fabs(pk);
432
if( (k > (kf + 2.5)) && (fabs(pkm1) < 0.25*t) )
436
pkm2 = ( (r*(r+2.0)-t)*pk - r*x*pkp1 )/t;
445
while( k > (kf + 0.5) );
447
/* Take the larger of the last two iterates
448
* on the theory that it may have less cancellation error.
453
if( (kf >= 0.0) && (fabs(pk) > fabs(pkm1)) )
461
printf( "newn %.6e rans %.6e\n", k, pkm2 );
470
#define BESSEL_MAXGAM 171.624376956302725
471
#define BESSEL_MAXLOG 7.09782712893383996843E2
473
/* Ascending power series for Jv(x).
477
double bessel_jvs(double n, double x)
479
double t, u, y, z, k;
489
while( t > DBL_EPSILON )
491
u *= z / (k * (n+k));
498
printf( "power series=%.5e ", y );
500
t = frexp( 0.5*x, &ex );
505
&& (n < (BESSEL_MAXGAM-1.0)) )
507
t = pow( 0.5*x, n ) / tgamma( n + 1.0 );
509
printf( "pow(.5*x, %.4e)/gamma(n+1)=%.5e\n", n, t );
519
printf( "log pow=%.5e, lgam(%.4e)=%.5e\n", z, n+1.0, k );
521
t = n * log(0.5*x) - lgamma(n + 1.0);
530
printf( "log y=%.5e\n", log(y) );
532
if( t < -BESSEL_MAXLOG )
536
if( t > BESSEL_MAXLOG )
538
// mtherr( "Jv", OVERFLOW );
541
y = sgngam * exp( t );
550
__constant const double bessel_jnt_PF2[] = {
551
-9.0000000000000000000e-2,
552
8.5714285714285714286e-2
554
__constant const double bessel_jnt_PF3[] = {
555
1.3671428571428571429e-1,
556
-5.4920634920634920635e-2,
557
-4.4444444444444444444e-3
559
__constant const double bessel_jnt_PF4[] = {
560
1.3500000000000000000e-3,
561
-1.6036054421768707483e-1,
562
4.2590187590187590188e-2,
563
2.7330447330447330447e-3
565
__constant const double bessel_jnt_PG1[] = {
566
-2.4285714285714285714e-1,
567
1.4285714285714285714e-2
569
__constant const double bessel_jnt_PG2[] = {
570
-9.0000000000000000000e-3,
571
1.9396825396825396825e-1,
572
-1.1746031746031746032e-2
574
__constant const double bessel_jnt_PG3[] = {
575
1.9607142857142857143e-2,
576
-1.5983694083694083694e-1,
577
6.3838383838383838384e-3
580
double bessel_jnt(double n, double x)
583
double cbn, n23, cbtwo;
584
double ai, aip, bi, bip; /* Airy functions */
585
double nk, fk, gk, pp, qq;
595
airy( zz, &ai, &aip, &bi, &bip );
597
/* polynomials in expansion */
602
F[2] = cephes_polevl( z3, bessel_jnt_PF2, 1 ) * zz;
603
F[3] = cephes_polevl( z3, bessel_jnt_PF3, 2 );
604
F[4] = cephes_polevl( z3, bessel_jnt_PF4, 3 ) * z;
606
G[1] = cephes_polevl( z3, bessel_jnt_PG1, 1 );
607
G[2] = cephes_polevl( z3, bessel_jnt_PG2, 2 ) * z;
608
G[3] = cephes_polevl( z3, bessel_jnt_PG3, 2 ) * zz;
610
for( k=0; k<=4; k++ )
611
printf( "F[%d] = %.5E\n", k, F[k] );
612
for( k=0; k<=3; k++ )
613
printf( "G[%d] = %.5E\n", k, G[k] );
620
for( k=0; k<=4; k++ )
630
printf("fk[%d] %.5E, gk[%d] %.5E\n", k, fk, k, gk );
635
fk = cbtwo * ai * pp/cbn + cbrt(4.0) * aip * qq/n;
643
__constant const double bessel_jnx_lambda[] = {
645
1.041666666666666666666667E-1,
646
8.355034722222222222222222E-2,
647
1.282265745563271604938272E-1,
648
2.918490264641404642489712E-1,
649
8.816272674437576524187671E-1,
650
3.321408281862767544702647E+0,
651
1.499576298686255465867237E+1,
652
7.892301301158651813848139E+1,
653
4.744515388682643231611949E+2,
654
3.207490090890661934704328E+3
656
__constant const double bessel_jnx_mu[] = {
658
-1.458333333333333333333333E-1,
659
-9.874131944444444444444444E-2,
660
-1.433120539158950617283951E-1,
661
-3.172272026784135480967078E-1,
662
-9.424291479571202491373028E-1,
663
-3.511203040826354261542798E+0,
664
-1.572726362036804512982712E+1,
665
-8.228143909718594444224656E+1,
666
-4.923553705236705240352022E+2,
667
-3.316218568547972508762102E+3
669
__constant const double bessel_jnx_P1[] = {
670
-2.083333333333333333333333E-1,
671
1.250000000000000000000000E-1
673
__constant const double bessel_jnx_P2[] = {
674
3.342013888888888888888889E-1,
675
-4.010416666666666666666667E-1,
676
7.031250000000000000000000E-2
678
__constant const double bessel_jnx_P3[] = {
679
-1.025812596450617283950617E+0,
680
1.846462673611111111111111E+0,
681
-8.912109375000000000000000E-1,
682
7.324218750000000000000000E-2
684
__constant const double bessel_jnx_P4[] = {
685
4.669584423426247427983539E+0,
686
-1.120700261622299382716049E+1,
687
8.789123535156250000000000E+0,
688
-2.364086914062500000000000E+0,
689
1.121520996093750000000000E-1
691
__constant const double bessel_jnx_P5[] = {
692
-2.8212072558200244877E1,
693
8.4636217674600734632E1,
694
-9.1818241543240017361E1,
695
4.2534998745388454861E1,
696
-7.3687943594796316964E0,
697
2.27108001708984375E-1
699
__constant const double bessel_jnx_P6[] = {
700
2.1257013003921712286E2,
701
-7.6525246814118164230E2,
702
1.0599904525279998779E3,
703
-6.9957962737613254123E2,
704
2.1819051174421159048E2,
705
-2.6491430486951555525E1,
706
5.7250142097473144531E-1
708
__constant const double bessel_jnx_P7[] = {
709
-1.9194576623184069963E3,
710
8.0617221817373093845E3,
711
-1.3586550006434137439E4,
712
1.1655393336864533248E4,
713
-5.3056469786134031084E3,
714
1.2009029132163524628E3,
715
-1.0809091978839465550E2,
716
1.7277275025844573975E0
719
double bessel_jnx(double n, double x)
721
double zeta, sqz, zz, zp, np;
722
double cbn, n23, t, z, sz;
723
double pp, qq, z32i, zzi;
724
double ak, bk, akl, bkl;
725
int sign, doa, dob, nflg, k, s, tk, tkp1, m;
727
double ai, aip, bi, bip;
729
/* Test for x very close to n.
730
* Use expansion for transition region if so.
735
return( bessel_jnt(n,x) );
745
t = 1.5 * (log( (1.0+sz)/z ) - sz ); /* zeta ** 3/2 */
746
zeta = cbrt( t * t );
752
t = 1.5 * (sz - acos(1.0/z));
753
zeta = -cbrt( t * t );
764
printf("zeta %.5E, Airy(%.5E)\n", zeta, t );
766
airy( t, &ai, &aip, &bi, &bip );
768
/* polynomials in expansion */
771
u[1] = cephes_polevl( zzi, bessel_jnx_P1, 1 )/sz;
772
u[2] = cephes_polevl( zzi, bessel_jnx_P2, 2 )/zz;
773
u[3] = cephes_polevl( zzi, bessel_jnx_P3, 3 )/(sz*zz);
775
u[4] = cephes_polevl( zzi, bessel_jnx_P4, 4 )/pp;
776
u[5] = cephes_polevl( zzi, bessel_jnx_P5, 5 )/(pp*sz);
778
u[6] = cephes_polevl( zzi, bessel_jnx_P6, 6 )/pp;
779
u[7] = cephes_polevl( zzi, bessel_jnx_P7, 7 )/(pp*sz);
782
for( k=0; k<=7; k++ )
783
printf( "u[%d] = %.5E\n", k, u[k] );
789
/* flags to stop when terms get larger */
795
for( k=0; k<=3; k++ )
802
for( s=0; s<=tk; s++ )
810
ak += sign * bessel_jnx_mu[s] * zp * u[tk-s];
816
if( ((m+1) & 3) > 1 )
820
bk += sign * bessel_jnx_lambda[s] * zp * u[m];
840
bk += bessel_jnx_lambda[tkp1] * zp * u[0];
852
printf("a[%d] %.5E, b[%d] %.5E\n", k, ak, k, bk );
854
if( np < DBL_EPSILON )
859
/* normalizing factor ( 4*zeta/(1 - z**2) )**1/4 */
863
t *= ai*pp/cbrt(n) + aip*qq/(n23*n);
871
/* Hankel's asymptotic expansion
876
double bessel_hankel( double n, double x )
878
double t, u, z, k, sign, conv;
879
double p, q, j, m, pp, qq;
896
while( t > DBL_EPSILON )
901
u *= (m - k * k)/(j * z);
905
u *= (m - k * k)/(j * z);
915
/* stop if the terms start getting larger */
916
if( (flag != 0) && (t > conv) )
919
printf( "Hankel: convergence to %.4E\n", conv );
926
u = x - (0.5*n + 0.25) * M_PI;
927
t = sqrt( 2.0/(M_PI*x) ) * ( pp * cos(u) - qq * sin(u) );
929
printf( "hank: %.6e\n", t );
937
// SciPy says jn has no advantage over jv, so alias the two.
939
#define bessel_jn bessel_jv
941
double bessel_jv(double n, double x)
943
double k, q, t, y, an;
946
nint = 0; /* Flag for integer n */
947
sign = 1; /* Flag for sign inversion */
953
i = an - 16384.0 * floor( an/16384.0 );
967
return( bessel_j0(x) );
969
return( sign * bessel_j1(x) );
972
if( (x < 0.0) && (y != an) )
974
// mtherr( "Jv", DOMAIN );
982
if( y < DBL_EPSILON )
987
if( (y < t) && (an > 21.0) )
988
return( sign * bessel_jvs(n,x) );
989
if( (an < k) && (y > 21.0) )
990
return( sign * bessel_hankel(n,x) );
994
/* Note: if x is too large, the continued
995
* fraction will fail; but then the
996
* Hankel expansion can be used.
1001
q = bessel_recur( &n, x, &k, 1 );
1017
if( (n >= 0.0) && (n < 20.0)
1018
&& (y > 6.0) && (y < 20.0) )
1020
/* Recur backwards from a larger value of n
1029
q = bessel_recur( &y, x, &k, 0 );
1030
y = bessel_jvs(y,x) * q;
1042
if( an > (k + 3.0) )
1049
q = bessel_recur( &n, x, &k, 1 );
1054
q = bessel_recur( &t, x, &k, 1 );
1070
/* boundary between convergence of
1071
* power series and Hankel expansion
1075
t = (0.0083*y + 0.09)*y + 12.9;
1080
y = bessel_hankel(k,x);
1082
y = bessel_jvs(k,x);
1084
printf( "y = %.16e, recur q = %.16e\n", y, q );
1094
/* For large n, use the uniform expansion
1095
* or the transitional expansion.
1096
* But if x is of the order of n**2,
1097
* these may blow up, whereas the
1098
* Hankel expansion will then work.
1102
//mtherr( "Jv", TLOSS );
1110
y = bessel_hankel(n,x);
1112
y = bessel_jnx(n,x);
1115
done: return( sign * y);