```   1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
24  */
25 /*
27  * Use is subject to license terms.
28  */
29
30 #pragma weak jn = __jn
31 #pragma weak yn = __yn
32
33 /*
34  * floating point Bessel's function of the 1st and 2nd kind
35  * of order n: jn(n,x),yn(n,x);
36  *
37  * Special cases:
38  *      y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
39  *      y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
40  * Note 2. About jn(n,x), yn(n,x)
41  *      For n=0, j0(x) is called,
42  *      for n=1, j1(x) is called,
43  *      for n<x, forward recursion us used starting
44  *      from values of j0(x) and j1(x).
45  *      for n>x, a continued fraction approximation to
46  *      j(n,x)/j(n-1,x) is evaluated and then backward
47  *      recursion is used starting from a supposed value
48  *      for j(n,x). The resulting value of j(0,x) is
49  *      compared with the actual value to correct the
50  *      supposed value of j(n,x).
51  *
52  *      yn(n,x) is similar in all respects, except
53  *      that forward recursion is used for all
54  *      values of n>1.
55  *
56  */
57
58 #include "libm.h"
59 #include <float.h>        /* DBL_MIN */
60 #include <values.h>       /* X_TLOSS */
61 #include "xpg6.h"       /* __xpg6 */
62
63 #define GENERIC double
64
65 static const GENERIC
66         invsqrtpi = 5.641895835477562869480794515607725858441e-0001,
67         two     = 2.0,
68         zero    = 0.0,
69         one     = 1.0;
70
71 GENERIC
72 jn(int n, GENERIC x) {
73         int i, sgn;
74         GENERIC a, b, temp = 0;
75         GENERIC z, w, ox, on;
76
77         /*
78          * J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
79          * Thus, J(-n,x) = J(n,-x)
80          */
81         ox = x; on = (GENERIC)n;
82         if (n < 0) {
83                 n = -n;
84                 x = -x;
85         }
86         if (isnan(x))
87                 return (x*x);   /* + -> * for Cheetah */
88         if (!((int) _lib_version == libm_ieee ||
89                 (__xpg6 & _C99SUSv3_math_errexcept) != 0)) {
90             if (fabs(x) > X_TLOSS)
91                         return (_SVID_libm_err(on, ox, 38));
92         }
93         if (n == 0)
94                 return (j0(x));
95         if (n == 1)
96                 return (j1(x));
97         if ((n&1) == 0)
98                 sgn = 0;                        /* even n */
99         else
100                 sgn = signbit(x);       /* old n  */
101         x = fabs(x);
102         if (x == zero||!finite(x)) b = zero;
103         else if ((GENERIC)n <= x) {
104                                         /*
105                                          * Safe to use
106                                          *  J(n+1,x)=2n/x *J(n,x)-J(n-1,x)
107                                          */
108             if (x > 1.0e91) {
109                                 /*
110                                  * x >> n**2
111                                  *    Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
112                                  *   Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
113                                  *   Let s=sin(x), c=cos(x),
114                                  *      xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
115                                  *
116                                  *         n    sin(xn)*sqt2    cos(xn)*sqt2
117                                  *      ----------------------------------
118                                  *         0     s-c             c+s
119                                  *         1    -s-c            -c+s
120                                  *         2    -s+c            -c-s
121                                  *         3     s+c             c-s
122                                  */
123                 switch (n&3) {
124                     case 0: temp =  cos(x)+sin(x); break;
125                     case 1: temp = -cos(x)+sin(x); break;
126                     case 2: temp = -cos(x)-sin(x); break;
127                     case 3: temp =  cos(x)-sin(x); break;
128                 }
129                 b = invsqrtpi*temp/sqrt(x);
130             } else {
131                         a = j0(x);
132                         b = j1(x);
133                         for (i = 1; i < n; i++) {
134                     temp = b;
135                     b = b*((GENERIC)(i+i)/x) - a; /* avoid underflow */
136                     a = temp;
137                         }
138             }
139         } else {
140             if (x < 1e-9) {  /* use J(n,x) = 1/n!*(x/2)^n */
141                 b = pow(0.5*x, (GENERIC) n);
142                 if (b != zero) {
143                     for (a = one, i = 1; i <= n; i++) a *= (GENERIC)i;
144                     b = b/a;
145                 }
146             } else {
147                 /*
148                  * use backward recurrence
149                  *                      x         x^2     x^2
150                  *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
151                  *                      2n  - 2(n+1) - 2(n+2)
152                  *
153                  *                      1         1         1
154                  *  (for large x)   =  ----  ------   ------   .....
155                  *                      2n   2(n+1)   2(n+2)
156                  *                      -- - ------ - ------ -
157                  *                       x       x               x
158                  *
159                  * Let w = 2n/x and h = 2/x, then the above quotient
160                  * is equal to the continued fraction:
161                  *                  1
162                  *      = -----------------------
163                  *                         1
164                  *         w - -----------------
165                  *                        1
166                  *                      w+h - ---------
167                  *                         w+2h - ...
168                  *
169                  * To determine how many terms needed, let
170                  * Q(0) = w, Q(1) = w(w+h) - 1,
171                  * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
172                  * When Q(k) > 1e4   good for single
173                  * When Q(k) > 1e9   good for double
174                  * When Q(k) > 1e17  good for quaduple
175                  */
176             /* determin k */
177                 GENERIC t, v;
178                 double q0, q1, h, tmp; int k, m;
179                 w  = (n+n)/(double)x; h = 2.0/(double)x;
180                 q0 = w;  z = w + h; q1 = w*z - 1.0; k = 1;
181                 while (q1 < 1.0e9) {
182                         k += 1; z += h;
183                         tmp = z*q1 - q0;
184                         q0 = q1;
185                         q1 = tmp;
186                 }
187                 m = n+n;
188                 for (t = zero, i = 2*(n+k); i >= m; i -= 2) t = one/(i/x-t);
189                 a = t;
190                 b = one;
191                 /*
192                  * estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
193                  *  hence, if n*(log(2n/x)) > ...
194                  *  single 8.8722839355e+01
195                  *  double 7.09782712893383973096e+02
196                  *  long double 1.1356523406294143949491931077970765006170e+04
197                  *  then recurrent value may overflow and the result is
198                  *  likely underflow to zero
199                  */
200                 tmp = n;
201                 v = two/x;
202                 tmp = tmp*log(fabs(v*tmp));
203                 if (tmp < 7.09782712893383973096e+02) {
204                             for (i = n-1; i > 0; i--) {
205                                 temp = b;
206                                 b = ((i+i)/x)*b - a;
207                             a = temp;
208                                 }
209                 } else {
210                                 for (i = n-1; i > 0; i--) {
211                                     temp = b;
212                                     b = ((i+i)/x)*b - a;
213                                     a = temp;
214                                         if (b > 1e100) {
215                                                 a /= b;
216                                                 t /= b;
217                                                 b  = 1.0;
218                                         }
219                                 }
220                 }
221                         b = (t*j0(x)/b);
222             }
223         }
224         if (sgn == 1)
225                 return (-b);
226         else
227                 return (b);
228 }
229
230 GENERIC
231 yn(int n, GENERIC x) {
232         int i;
233         int sign;
234         GENERIC a, b, temp = 0, ox, on;
235
236         ox = x; on = (GENERIC)n;
237         if (isnan(x))
238                 return (x*x);   /* + -> * for Cheetah */
239         if (x <= zero) {
240                 if (x == zero) {
241                         /* return -one/zero; */
242                         return (_SVID_libm_err((GENERIC)n, x, 12));
243                 } else {
244                         /* return zero/zero; */
245                         return (_SVID_libm_err((GENERIC)n, x, 13));
246                 }
247         }
248         if (!((int) _lib_version == libm_ieee ||
249                 (__xpg6 & _C99SUSv3_math_errexcept) != 0)) {
250             if (x > X_TLOSS)
251                         return (_SVID_libm_err(on, ox, 39));
252         }
253         sign = 1;
254         if (n < 0) {
255                 n = -n;
256                 if ((n&1) == 1) sign = -1;
257         }
258         if (n == 0)
259                 return (y0(x));
260         if (n == 1)
261                 return (sign*y1(x));
262         if (!finite(x))
263                 return (zero);
264
265         if (x > 1.0e91) {
266                                 /*
267                                  * x >> n**2
268                                  *  Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
269                                  *  Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
270                                  *  Let s = sin(x), c = cos(x),
271                                  *  xn = x-(2n+1)*pi/4, sqt2 = sqrt(2), then
272                                  *
273                                  *    n sin(xn)*sqt2    cos(xn)*sqt2
274                                  *      ----------------------------------
275                                  *       0       s-c             c+s
276                                  *       1      -s-c            -c+s
277                                  *       2      -s+c            -c-s
278                                  *       3       s+c             c-s
279                                  */
280                 switch (n&3) {
281                     case 0: temp =  sin(x)-cos(x); break;
282                     case 1: temp = -sin(x)-cos(x); break;
283                     case 2: temp = -sin(x)+cos(x); break;
284                     case 3: temp =  sin(x)+cos(x); break;
285                 }
286                 b = invsqrtpi*temp/sqrt(x);
287         } else {
288                 a = y0(x);
289                 b = y1(x);
290                 /*
291                  * fix 1262058 and take care of non-default rounding
292                  */
293                 for (i = 1; i < n; i++) {
294                         temp = b;
295                         b *= (GENERIC) (i + i) / x;
296                         if (b <= -DBL_MAX)
297                                 break;
298                         b -= a;
299                         a = temp;
300                 }
301         }
302         if (sign > 0)
303                 return (b);
304         else
305                 return (-b);
306 }
```