ack/lang/cem/libcc/math/jn.c
1994-06-24 14:02:31 +00:00

124 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;
}
}