123 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  * See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
|  *
 | |
|  * Author: Ceriel J.H. Jacobs
 | |
|  */
 | |
| 
 | |
| /* $Header$ */
 | |
| 
 | |
| #include <math.h>
 | |
| #include <errno.h>
 | |
| 
 | |
| extern int errno;
 | |
| 
 | |
| double
 | |
| yn(n, x)
 | |
| 	double x;
 | |
| {
 | |
| 	/*	Use y0, y1, and the recurrence relation
 | |
| 		y(n+1,x) = 2*n*y(n,x)/x - y(n-1, x).
 | |
| 		According to Hart & Cheney, this is stable for all
 | |
| 		x, n.
 | |
| 		Also use: y(-n,x) = (-1)^n * y(n, x)
 | |
| 	*/
 | |
| 
 | |
| 	int negative = 0;
 | |
| 	extern double y0(), y1();
 | |
| 	double yn1, yn2;
 | |
| 	register int i;
 | |
| 
 | |
| 	if (x <= 0) {
 | |
| 		errno = EDOM;
 | |
| 		return -HUGE;
 | |
| 	}
 | |
| 
 | |
| 	if (n < 0) {
 | |
| 		n = -n;
 | |
| 		negative = (n % 2);
 | |
| 	}
 | |
| 
 | |
| 	if (n == 0) return y0(x);
 | |
| 	if (n == 1) return y1(x);
 | |
| 
 | |
| 	yn2 = y0(x);
 | |
| 	yn1 = y1(x);
 | |
| 	for (i = 1; i < n; i++) {
 | |
| 		double tmp = yn1;
 | |
| 		yn1 = (i*2)*yn1/x - yn2;
 | |
| 		yn2 = tmp;
 | |
| 	}
 | |
| 	if (negative) return -yn1;
 | |
| 	return yn1;
 | |
| }
 | |
| 
 | |
| double
 | |
| jn(n, x)
 | |
| 	double x;
 | |
| {
 | |
| 	/*	Unfortunately, according to Hart & Cheney, the recurrence
 | |
| 		j(n+1,x) = 2*n*j(n,x)/x - j(n-1,x) is unstable for
 | |
| 		increasing n, except when x > n.
 | |
| 		However, j(n,x)/j(n-1,x) = 2/(2*n-x*x/(2*(n+1)-x*x/( .... 
 | |
| 		(a continued fraction).
 | |
| 		We can use this to determine KJn and KJn-1, where K is a
 | |
| 		normalization constant not yet known. This enables us
 | |
| 		to determine KJn-2, ...., KJ1, KJ0. Now we can use the
 | |
| 		J0 or J1 approximation to determine K.
 | |
| 		Use: j(-n, x) = (-1)^n * j(n, x)
 | |
| 		     j(n, -x) = (-1)^n * j(n, x)
 | |
| 	*/
 | |
| 
 | |
| 	extern double j0(), j1();
 | |
| 
 | |
| 	if (n < 0) {
 | |
| 		n = -n;
 | |
| 		x = -x;
 | |
| 	}
 | |
| 
 | |
| 	if (n == 0) return j0(x);
 | |
| 	if (n == 1) return j1(x);
 | |
| 	if (x > n) {
 | |
| 		/* in this case, the recurrence relation is stable for
 | |
| 		   increasing n, so we use that.
 | |
| 		*/
 | |
| 		double jn2 = j0(x), jn1 = j1(x);
 | |
| 		register int i;
 | |
| 
 | |
| 		for (i = 1; i < n; i++) {
 | |
| 			double tmp = jn1;
 | |
| 			jn1 = (2*i)*jn1/x - jn2;
 | |
| 			jn2 = tmp;
 | |
| 		}
 | |
| 		return jn1;
 | |
| 	}
 | |
| 	{
 | |
| 		/* we first compute j(n,x)/j(n-1,x) */
 | |
| 		register int i;
 | |
| 		double quotient = 0.0;
 | |
| 		double xsqr = x*x;
 | |
| 		double jn1, jn2;
 | |
| 
 | |
| 		for (i = 20;	/* ??? how many do we need ??? */
 | |
| 		     i > 0; i--) {
 | |
| 			quotient = xsqr/(2*(i+n) - quotient);
 | |
| 		}
 | |
| 		quotient = x / (2*n - quotient);
 | |
| 
 | |
| 		jn1 = quotient;
 | |
| 		jn2 = 1.0;
 | |
| 		for (i = n-1; i > 0; i--) {
 | |
| 			/* recurrence relation is stable for decreasing n
 | |
| 			*/
 | |
| 			double tmp = jn2;
 | |
| 			jn2 = (2*i)*jn2/x - jn1;
 | |
| 			jn1 = tmp;
 | |
| 		}
 | |
| 		/* So, now we have K*Jn = quotient and K*J0 = jn2.
 | |
| 		   Now it is easy; compute real j0, this gives K = jn2/j0,
 | |
| 		   and this then gives Jn = quotient/K = j0 * quotient / jn2.
 | |
| 		*/
 | |
| 		return j0(x)*quotient/jn2;
 | |
| 	}
 | |
| }
 |