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
 | 
						|
 */
 | 
						|
 | 
						|
/* $Id$ */
 | 
						|
 | 
						|
#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;
 | 
						|
	}
 | 
						|
}
 |