/* qyn.c */ /* Bessel function of second kind yn(x). */ /* n need not be an integer. */ /* enable compilation of auxiliary functions */ #define AUXFUN 0 /* debugging */ #define ERRCK 0 #define DEBUG 0 #include #include "qhead.h" extern QELT qeul[], qone[], qtwo[], qpi[]; /* values computed by qhank() (see qjn.c): */ extern QELT hankc[]; extern QELT hanks[]; extern QELT hankpp[]; extern QELT hankqq[]; extern QELT hankzz[]; static QELT jn[NQ] = {0}; /* answer saved from qjn() */ #if AUXFUN static QELT yn[NQ] = {0}; /* answer saved from qyn() */ static QELT m[NQ] = {0}; static QELT j[NQ] = {0}; static QELT k[NQ] = {0}; #endif static QELT z[NQ] = {0}; #ifdef ANSIPROT int qhank( QELT *, QELT *, QELT * ); int qynrecur( long, long, QELT *, QELT * ); #else int qhank(), qynrecur(); int qlog(), qjn(); #endif static QELT nfac[NQ], nm1fac[NQ], f[NQ], a[NQ], psi1[NQ], psin[NQ]; static QELT g[NQ], h[NQ], s[NQ]; int qyn( qn, x, y ) QELT qn[], x[], y[]; { long i, k, n, sign, kpn; volatile double du, dn; #if ERRCK QELT bt; bt = 0; #endif qfloor( qn, h ); if( qcmp(qn, h) != 0 ) { /* y = (cos(PI*v) * jv( v, x ) - jv( -v, x ))/sin(PI*v); */ qjn( qn, x, g ); qmul( qpi, qn, a ); qcos( a, f ); qmul( f, g, g ); qmov( qn, f ); qneg( f ); qjn( f, x, h ); qsub( h, g, g ); qsin( a, f ); qdiv( f, g, y ); return 0; } qtoe( qn, (unsigned short *) &dn ); n = dn; if( n < 0 ) { n = -n; if( (n & 1) == 0 ) /* -1**n */ sign = 1; else sign = -1; } else sign = 1; if( x[1] == 0 ) { mtherr("qyn", OVERFLOW ); qinfin(y); return( 0 ); } qtoe( x, (unsigned short *) &du ); if( (du > 64.0) && (du > 0.95*dn) ) { /* Hankel expansion will be invoked. */ if( du > 1.4*dn ) { #if AUXFUN qjn( qn, x, jn ); #endif qhank( qn, x, g ); qmul( hankpp, hanks, g ); qmul( hankqq, hankc, h ); qadd( g, h, y ); qmul( hankzz, y, y ); goto qyndone; } else { k = 0.7 * du; qmov( x, g ); qynrecur( k, n, g, y ); goto qyndone; } } /* factorial of n */ qmov( qone, nfac); /*nfac = 1.0;*/ qclear( f ); /*f = 0;*/ for( i=0; i bt ) bt = h[1]; if( s[1] > bt ) bt = s[1]; #endif qadd( qone, f, f ); /*k += 1;*/ qadd( qone, g, g ); /*kpn += 1;*/ } while( ((int) s[1] - (int) a[1]) < (3*NBITS)/4 ); /*printf("infinite %.4E\n", s);*/ #if ERRCK /* estimate cancellation error */ i = bt - s[1]; if( i > NBITS/2 || DEBUG ) fprintf(stderr, "qyn pseries: %ld bits cancellation\n", i ); #endif /* qyn.c 3 */ /* finite sum */ qclear( f ); /*f = 0;*/ if( n > 0 ) { z[0] = 0; /*z = -z;*/ qmov( nm1fac, a ); /*a = nm1fac;*/ kpn = n - 1; qmov( a, f ); /*f = a;*/ ltoq( &kpn, g ); qmov( qone, h ); /* k = 1 */ for( k=1; k= min ) { printf( "qjmod converges to %d bits\n", qone[1] - term ); goto adone; } min = term; } adone: qmul( qx, qpi, t ); qdiv( t, ans, ans ); ans[1] += 1; qmov( ans, qy ); fdone: ; return 0; } #endif /* AUXFUN */