Initial import from FreeBSD RELENG_4:
[games.git] / lib / libm / common_source / jn.c
1 /*-
2  * Copyright (c) 1992, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)jn.c        8.2 (Berkeley) 11/30/93";
36 #endif /* not lint */
37
38 /*
39  * 16 December 1992
40  * Minor modifications by Peter McIlroy to adapt non-IEEE architecture.
41  */
42
43 /*
44  * ====================================================
45  * Copyright (C) 1992 by Sun Microsystems, Inc.
46  *
47  * Developed at SunPro, a Sun Microsystems, Inc. business.
48  * Permission to use, copy, modify, and distribute this
49  * software is freely granted, provided that this notice
50  * is preserved.
51  * ====================================================
52  *
53  * ******************* WARNING ********************
54  * This is an alpha version of SunPro's FDLIBM (Freely
55  * Distributable Math Library) for IEEE double precision
56  * arithmetic. FDLIBM is a basic math library written
57  * in C that runs on machines that conform to IEEE
58  * Standard 754/854. This alpha version is distributed
59  * for testing purpose. Those who use this software
60  * should report any bugs to
61  *
62  *              fdlibm-comments@sunpro.eng.sun.com
63  *
64  * -- K.C. Ng, Oct 12, 1992
65  * ************************************************
66  */
67
68 /*
69  * jn(int n, double x), yn(int n, double x)
70  * floating point Bessel's function of the 1st and 2nd kind
71  * of order n
72  *
73  * Special cases:
74  *      y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
75  *      y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
76  * Note 2. About jn(n,x), yn(n,x)
77  *      For n=0, j0(x) is called,
78  *      for n=1, j1(x) is called,
79  *      for n<x, forward recursion us used starting
80  *      from values of j0(x) and j1(x).
81  *      for n>x, a continued fraction approximation to
82  *      j(n,x)/j(n-1,x) is evaluated and then backward
83  *      recursion is used starting from a supposed value
84  *      for j(n,x). The resulting value of j(0,x) is
85  *      compared with the actual value to correct the
86  *      supposed value of j(n,x).
87  *
88  *      yn(n,x) is similar in all respects, except
89  *      that forward recursion is used for all
90  *      values of n>1.
91  *
92  */
93
94 #include <math.h>
95 #include <float.h>
96 #include <errno.h>
97
98 #if defined(vax) || defined(tahoe)
99 #define _IEEE   0
100 #else
101 #define _IEEE   1
102 #define infnan(x) (0.0)
103 #endif
104
105 static double
106 invsqrtpi= 5.641895835477562869480794515607725858441e-0001,
107 two  = 2.0,
108 zero = 0.0,
109 one  = 1.0;
110
111 double jn(n,x)
112         int n; double x;
113 {
114         int i, sgn;
115         double a, b, temp;
116         double z, w;
117
118     /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
119      * Thus, J(-n,x) = J(n,-x)
120      */
121     /* if J(n,NaN) is NaN */
122         if (_IEEE && isnan(x)) return x+x;
123         if (n<0){
124                 n = -n;
125                 x = -x;
126         }
127         if (n==0) return(j0(x));
128         if (n==1) return(j1(x));
129         sgn = (n&1)&(x < zero);         /* even n -- 0, odd n -- sign(x) */
130         x = fabs(x);
131         if (x == 0 || !finite (x))      /* if x is 0 or inf */
132             b = zero;
133         else if ((double) n <= x) {
134                         /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
135             if (_IEEE && x >= 8.148143905337944345e+090) {
136                                         /* x >= 2**302 */
137     /* (x >> n**2)
138      *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
139      *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
140      *      Let s=sin(x), c=cos(x),
141      *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
142      *
143      *             n    sin(xn)*sqt2    cos(xn)*sqt2
144      *          ----------------------------------
145      *             0     s-c             c+s
146      *             1    -s-c            -c+s
147      *             2    -s+c            -c-s
148      *             3     s+c             c-s
149      */
150                 switch(n&3) {
151                     case 0: temp =  cos(x)+sin(x); break;
152                     case 1: temp = -cos(x)+sin(x); break;
153                     case 2: temp = -cos(x)-sin(x); break;
154                     case 3: temp =  cos(x)-sin(x); break;
155                 }
156                 b = invsqrtpi*temp/sqrt(x);
157             } else {
158                 a = j0(x);
159                 b = j1(x);
160                 for(i=1;i<n;i++){
161                     temp = b;
162                     b = b*((double)(i+i)/x) - a; /* avoid underflow */
163                     a = temp;
164                 }
165             }
166         } else {
167             if (x < 1.86264514923095703125e-009) { /* x < 2**-29 */
168     /* x is tiny, return the first Taylor expansion of J(n,x)
169      * J(n,x) = 1/n!*(x/2)^n  - ...
170      */
171                 if (n > 33)     /* underflow */
172                     b = zero;
173                 else {
174                     temp = x*0.5; b = temp;
175                     for (a=one,i=2;i<=n;i++) {
176                         a *= (double)i;         /* a = n! */
177                         b *= temp;              /* b = (x/2)^n */
178                     }
179                     b = b/a;
180                 }
181             } else {
182                 /* use backward recurrence */
183                 /*                      x      x^2      x^2
184                  *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
185                  *                      2n  - 2(n+1) - 2(n+2)
186                  *
187                  *                      1      1        1
188                  *  (for large x)   =  ----  ------   ------   .....
189                  *                      2n   2(n+1)   2(n+2)
190                  *                      -- - ------ - ------ -
191                  *                       x     x         x
192                  *
193                  * Let w = 2n/x and h=2/x, then the above quotient
194                  * is equal to the continued fraction:
195                  *                  1
196                  *      = -----------------------
197                  *                     1
198                  *         w - -----------------
199                  *                        1
200                  *              w+h - ---------
201                  *                     w+2h - ...
202                  *
203                  * To determine how many terms needed, let
204                  * Q(0) = w, Q(1) = w(w+h) - 1,
205                  * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
206                  * When Q(k) > 1e4      good for single
207                  * When Q(k) > 1e9      good for double
208                  * When Q(k) > 1e17     good for quadruple
209                  */
210             /* determine k */
211                 double t,v;
212                 double q0,q1,h,tmp; int k,m;
213                 w  = (n+n)/(double)x; h = 2.0/(double)x;
214                 q0 = w;  z = w+h; q1 = w*z - 1.0; k=1;
215                 while (q1<1.0e9) {
216                         k += 1; z += h;
217                         tmp = z*q1 - q0;
218                         q0 = q1;
219                         q1 = tmp;
220                 }
221                 m = n+n;
222                 for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
223                 a = t;
224                 b = one;
225                 /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
226                  *  Hence, if n*(log(2n/x)) > ...
227                  *  single 8.8722839355e+01
228                  *  double 7.09782712893383973096e+02
229                  *  long double 1.1356523406294143949491931077970765006170e+04
230                  *  then recurrent value may overflow and the result will
231                  *  likely underflow to zero
232                  */
233                 tmp = n;
234                 v = two/x;
235                 tmp = tmp*log(fabs(v*tmp));
236                 for (i=n-1;i>0;i--){
237                         temp = b;
238                         b = ((i+i)/x)*b - a;
239                         a = temp;
240                     /* scale b to avoid spurious overflow */
241 #                       if defined(vax) || defined(tahoe)
242 #                               define BMAX 1e13
243 #                       else
244 #                               define BMAX 1e100
245 #                       endif /* defined(vax) || defined(tahoe) */
246                         if (b > BMAX) {
247                                 a /= b;
248                                 t /= b;
249                                 b = one;
250                         }
251                 }
252                 b = (t*j0(x)/b);
253             }
254         }
255         return ((sgn == 1) ? -b : b);
256 }
257 double yn(n,x)
258         int n; double x;
259 {
260         int i, sign;
261         double a, b, temp;
262
263     /* Y(n,NaN), Y(n, x < 0) is NaN */
264         if (x <= 0 || (_IEEE && x != x))
265                 if (_IEEE && x < 0) return zero/zero;
266                 else if (x < 0)     return (infnan(EDOM));
267                 else if (_IEEE)     return -one/zero;
268                 else                return(infnan(-ERANGE));
269         else if (!finite(x)) return(0);
270         sign = 1;
271         if (n<0){
272                 n = -n;
273                 sign = 1 - ((n&1)<<2);
274         }
275         if (n == 0) return(y0(x));
276         if (n == 1) return(sign*y1(x));
277         if(_IEEE && x >= 8.148143905337944345e+090) { /* x > 2**302 */
278     /* (x >> n**2)
279      *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
280      *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
281      *      Let s=sin(x), c=cos(x),
282      *          xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
283      *
284      *             n    sin(xn)*sqt2    cos(xn)*sqt2
285      *          ----------------------------------
286      *             0     s-c             c+s
287      *             1    -s-c            -c+s
288      *             2    -s+c            -c-s
289      *             3     s+c             c-s
290      */
291                 switch (n&3) {
292                     case 0: temp =  sin(x)-cos(x); break;
293                     case 1: temp = -sin(x)-cos(x); break;
294                     case 2: temp = -sin(x)+cos(x); break;
295                     case 3: temp =  sin(x)+cos(x); break;
296                 }
297                 b = invsqrtpi*temp/sqrt(x);
298         } else {
299             a = y0(x);
300             b = y1(x);
301         /* quit if b is -inf */
302             for (i = 1; i < n && !finite(b); i++){
303                 temp = b;
304                 b = ((double)(i+i)/x)*b - a;
305                 a = temp;
306             }
307         }
308         if (!_IEEE && !finite(b))
309                 return (infnan(-sign * ERANGE));
310         return ((sign > 0) ? b : -b);
311 }