Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  jv.c   Sprache: unbekannt

 
/* jv.c
 *
 * Bessel function of noninteger order
 *
 *
 *
 * SYNOPSIS:
 *
 * double v, x, y, jv();
 *
 * y = jv( v, x );
 *
 *
 *
 * DESCRIPTION:
 *
 * Returns Bessel function of order v of the argument,
 * where v is real.  Negative x is allowed if v is an integer.
 *
 * Several expansions are included: the ascending power
 * series, the Hankel expansion, and two transitional
 * expansions for large v.  If v is not too large, it
 * is reduced by recurrence to a region of best accuracy.
 * The transitional expansions give 12D accuracy for v > 500.
 *
 *
 *
 * ACCURACY:
 * Results for integer v are indicated by *, where x and v
 * both vary from -125 to +125.  Otherwise,
 * x ranges from 0 to 125, v ranges as indicated by "domain."
 * Error criterion is absolute, except relative when |jv()| > 1.
 *
 * arithmetic  v domain  x domain    # trials      peak       rms
 *    IEEE      0,125     0,125      100000      4.6e-15    2.2e-16
 *    IEEE   -125,0       0,125       40000      5.4e-11    3.7e-13
 *    IEEE      0,500     0,500       20000      4.4e-15    4.0e-16
 * Integer v:
 *    IEEE   -125,125   -125,125      50000      3.5e-15*   1.9e-16*
 *
 */



/*
Cephes Math Library Release 2.8:  June, 2000
Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
*/



#include "mconf.h"
#define DEBUG 0

#ifdef DEC
#define MAXGAM 34.84425627277176174
#else
#define MAXGAM 171.624376956302725
#endif

#ifdef ANSIPROT
extern int airy ( doubledouble *, double *, double *, double * );
extern double fabs ( double );
extern double floor ( double );
extern double frexp ( doubleint * );
extern double polevl ( doublevoid *, int );
extern double j0 ( double );
extern double j1 ( double );
extern double sqrt ( double );
extern double cbrt ( double );
extern double exp ( double );
extern double log ( double );
extern double sin ( double );
extern double cos ( double );
extern double acos ( double );
extern double pow ( doubledouble );
extern double gamma ( double );
extern double lgam ( double );
static double recur(double *, doubledouble *, int);
static double jvs(doubledouble);
static double hankel(doubledouble);
static double jnx(doubledouble);
static double jnt(doubledouble);
#else
int airy();
double fabs(), floor(), frexp(), polevl(), j0(), j1(), sqrt(), cbrt();
double exp(), log(), sin(), cos(), acos(), pow(), gamma(), lgam();
static double recur(), jvs(), hankel(), jnx(), jnt();
#endif

extern double MAXNUM, MACHEP, MINLOG, MAXLOG;
#define BIG  1.44115188075855872E+17

double jv( n, x )
double n, x;
{
double k, q, t, y, an;
int i, sign, nint;

nint = 0/* Flag for integer n */
sign = 1/* Flag for sign inversion */
an = fabs( n );
y = floor( an );
if( y == an )
 {
 nint = 1;
 i = an - 16384.0 * floor( an/16384.0 );
 if( n < 0.0 )
  {
  if( i & 1 )
   sign = -sign;
  n = an;
  }
 if( x < 0.0 )
  {
  if( i & 1 )
   sign = -sign;
  x = -x;
  }
 if( n == 0.0 )
  return( j0(x) );
 if( n == 1.0 )
  return( sign * j1(x) );
 }

if( (x < 0.0) && (y != an) )
 {
 mtherr( "Jv", DOMAIN );
 y = 0.0;
 goto done;
  }

y = fabs(x);

if( y < MACHEP )
 goto underf;

k = 3.6 * sqrt(y);
t = 3.6 * sqrt(an);
if( (y < t) && (an > 21.0) )
 return( sign * jvs(n,x) );
if( (an < k) && (y > 21.0) )
 return( sign * hankel(n,x) );

if( an < 500.0 )
 {
/* Note: if x is too large, the continued
 * fraction will fail; but then the
 * Hankel expansion can be used.
 */

 if( nint != 0 )
  {
  k = 0.0;
  q = recur( &n, x, &k, 1 );
  if( k == 0.0 )
   {
   y = j0(x)/q;
   goto done;
   }
  if( k == 1.0 )
   {
   y = j1(x)/q;
   goto done;
   }
  }

if( an > 2.0 * y )
 goto rlarger;

 if( (n >= 0.0) && (n < 20.0)
  && (y > 6.0) && (y < 20.0) )
  {
/* Recur backwards from a larger value of n
 */

rlarger:
  k = n;

  y = y + an + 1.0;
  if( y < 30.0 )
   y = 30.0;
  y = n + floor(y-n);
  q = recur( &y, x, &k, 0 );
  y = jvs(y,x) * q;
  goto done;
  }

 if( k <= 30.0 )
  {
  k = 2.0;
  }
 else if( k < 90.0 )
  {
  k = (3*k)/4;
  }
 if( an > (k + 3.0) )
  {
  if( n < 0.0 )
   k = -k;
  q = n - floor(n);
  k = floor(k) + q;
  if( n > 0.0 )
   q = recur( &n, x, &k, 1 );
  else
   {
   t = k;
   k = n;
   q = recur( &t, x, &k, 1 );
   k = t;
   }
  if( q == 0.0 )
   {
underf:
   y = 0.0;
   goto done;
   }
  }
 else
  {
  k = n;
  q = 1.0;
  }

/* boundary between convergence of
 * power series and Hankel expansion
 */

 y = fabs(k);
 if( y < 26.0 )
  t = (0.0083*y + 0.09)*y + 12.9;
 else
  t = 0.9 * y;

 if( x > t )
  y = hankel(k,x);
 else
  y = jvs(k,x);
#if DEBUG
printf( "y = %.16e, recur q = %.16e\n", y, q );
#endif
 if( n > 0.0 )
  y /= q;
 else
  y *= q;
 }

else
 {
/* For large n, use the uniform expansion
 * or the transitional expansion.
 * But if x is of the order of n**2,
 * these may blow up, whereas the
 * Hankel expansion will then work.
 */

 if( n < 0.0 )
  {
  mtherr( "Jv", TLOSS );
  y = 0.0;
  goto done;
  }
 t = x/n;
 t /= n;
 if( t > 0.3 )
  y = hankel(n,x);
 else
  y = jnx(n,x);
 }

done: return( sign * y);
}

/* Reduce the order by backward recurrence.
 * AMS55 #9.1.27 and 9.1.73.
 */


static double recur( n, x, newn, cancel )
double *n;
double x;
double *newn;
int cancel;
{
double pkm2, pkm1, pk, qkm2, qkm1;
/* double pkp1; */
double k, ans, qk, xk, yk, r, t, kf;
static double big = BIG;
int nflag, ctr;

/* continued fraction for Jn(x)/Jn-1(x)  */
if( *n < 0.0 )
 nflag = 1;
else
 nflag = 0;

fstart:

#if DEBUG
printf( "recur: n = %.6e, newn = %.6e, cfrac = ", *n, *newn );
#endif

pkm2 = 0.0;
qkm2 = 1.0;
pkm1 = x;
qkm1 = *n + *n;
xk = -x * x;
yk = qkm1;
ans = 1.0;
ctr = 0;
do
 {
 yk += 2.0;
 pk = pkm1 * yk +  pkm2 * xk;
 qk = qkm1 * yk +  qkm2 * xk;
 pkm2 = pkm1;
 pkm1 = pk;
 qkm2 = qkm1;
 qkm1 = qk;
 if( qk != 0 )
  r = pk/qk;
 else
  r = 0.0;
 if( r != 0 )
  {
  t = fabs( (ans - r)/r );
  ans = r;
  }
 else
  t = 1.0;

 if( ++ctr > 1000 )
  {
  mtherr( "jv", UNDERFLOW );
  goto done;
  }
 if( t < MACHEP )
  goto done;

 if( fabs(pk) > big )
  {
  pkm2 /= big;
  pkm1 /= big;
  qkm2 /= big;
  qkm1 /= big;
  }
 }
while( t > MACHEP );

done:

#if DEBUG
printf( "%.6e\n", ans );
#endif

/* Change n to n-1 if n < 0 and the continued fraction is small
 */

if( nflag > 0 )
 {
 if( fabs(ans) < 0.125 )
  {
  nflag = -1;
  *n = *n - 1.0;
  goto fstart;
  }
 }


kf = *newn;

/* backward recurrence
 *              2k
 *  J   (x)  =  --- J (x)  -  J   (x)
 *   k-1         x   k         k+1
 */


pk = 1.0;
pkm1 = 1.0/ans;
k = *n - 1.0;
r = 2 * k;
do
 {
 pkm2 = (pkm1 * r  -  pk * x) / x;
 /* pkp1 = pk; */
 pk = pkm1;
 pkm1 = pkm2;
 r -= 2.0;
/*
 t = fabs(pkp1) + fabs(pk);
 if( (k > (kf + 2.5)) && (fabs(pkm1) < 0.25*t) )
  {
  k -= 1.0;
  t = x*x;
  pkm2 = ( (r*(r+2.0)-t)*pk - r*x*pkp1 )/t;
  pkp1 = pk;
  pk = pkm1;
  pkm1 = pkm2;
  r -= 2.0;
  }
*/

 k -= 1.0;
 }
while( k > (kf + 0.5) );

/* Take the larger of the last two iterates
 * on the theory that it may have less cancellation error.
 */


if( cancel )
 {
 if( (kf >= 0.0) && (fabs(pk) > fabs(pkm1)) )
  {
  k += 1.0;
  pkm2 = pk;
  }
 }
*newn = k;
#if DEBUG
printf( "newn %.6e rans %.6e\n", k, pkm2 );
#endif
return( pkm2 );
}



/* Ascending power series for Jv(x).
 * AMS55 #9.1.10.
 */


extern double PI;
extern int sgngam;

static double jvs( n, x )
double n, x;
{
double t, u, y, z, k;
int ex;

z = -x * x / 4.0;
u = 1.0;
y = u;
k = 1.0;
t = 1.0;

while( t > MACHEP )
 {
 u *= z / (k * (n+k));
 y += u;
 k += 1.0;
 if( y != 0 )
  t = fabs( u/y );
 }
#if DEBUG
printf( "power series=%.5e ", y );
#endif
t = frexp( 0.5*x, &ex );
ex = ex * n;
if(  (ex > -1023)
  && (ex < 1023
  && (n > 0.0)
  && (n < (MAXGAM-1.0)) )
 {
 t = pow( 0.5*x, n ) / gamma( n + 1.0 );
#if DEBUG
printf( "pow(.5*x, %.4e)/gamma(n+1)=%.5e\n", n, t );
#endif
 y *= t;
 }
else
 {
#if DEBUG
 z = n * log(0.5*x);
 k = lgam( n+1.0 );
 t = z - k;
 printf( "log pow=%.5e, lgam(%.4e)=%.5e\n", z, n+1.0, k );
#else
 t = n * log(0.5*x) - lgam(n + 1.0);
#endif
 if( y < 0 )
  {
  sgngam = -sgngam;
  y = -y;
  }
 t += log(y);
#if DEBUG
printf( "log y=%.5e\n", log(y) );
#endif
 if( t < -MAXLOG )
  {
  return0.0 );
  }
 if( t > MAXLOG )
  {
  mtherr( "Jv", OVERFLOW );
  return( MAXNUM );
  }
 y = sgngam * exp( t );
 }
return(y);
}

/* Hankel's asymptotic expansion
 * for large x.
 * AMS55 #9.2.5.
 */


static double hankel( n, x )
double n, x;
{
double t, u, z, k, sign, conv;
double p, q, j, m, pp, qq;
int flag;

m = 4.0*n*n;
j = 1.0;
z = 8.0 * x;
k = 1.0;
p = 1.0;
u = (m - 1.0)/z;
q = u;
sign = 1.0;
conv = 1.0;
flag = 0;
t = 1.0;
pp = 1.0e38;
qq = 1.0e38;

while( t > MACHEP )
 {
 k += 2.0;
 j += 1.0;
 sign = -sign;
 u *= (m - k * k)/(j * z);
 p += sign * u;
 k += 2.0;
 j += 1.0;
 u *= (m - k * k)/(j * z);
 q += sign * u;
 t = fabs(u/p);
 if( t < conv )
  {
  conv = t;
  qq = q;
  pp = p;
  flag = 1;
  }
/* stop if the terms start getting larger */
 if( (flag != 0) && (t > conv) )
  {
#if DEBUG
  printf( "Hankel: convergence to %.4E\n", conv );
#endif
  goto hank1;
  }
 } 

hank1:
u = x - (0.5*n + 0.25) * PI;
t = sqrt( 2.0/(PI*x) ) * ( pp * cos(u) - qq * sin(u) );
#if DEBUG
printf( "hank: %.6e\n", t );
#endif
return( t );
}


/* Asymptotic expansion for large n.
 * AMS55 #9.3.35.
 */


static double lambda[] = {
  1.0,
  1.041666666666666666666667E-1,
  8.355034722222222222222222E-2,
  1.282265745563271604938272E-1,
  2.918490264641404642489712E-1,
  8.816272674437576524187671E-1,
  3.321408281862767544702647E+0,
  1.499576298686255465867237E+1,
  7.892301301158651813848139E+1,
  4.744515388682643231611949E+2,
  3.207490090890661934704328E+3
};
static double mu[] = {
  1.0,
 -1.458333333333333333333333E-1,
 -9.874131944444444444444444E-2,
 -1.433120539158950617283951E-1,
 -3.172272026784135480967078E-1,
 -9.424291479571202491373028E-1,
 -3.511203040826354261542798E+0,
 -1.572726362036804512982712E+1,
 -8.228143909718594444224656E+1,
 -4.923553705236705240352022E+2,
 -3.316218568547972508762102E+3
};
static double P1[] = {
 -2.083333333333333333333333E-1,
  1.250000000000000000000000E-1
};
static double P2[] = {
  3.342013888888888888888889E-1,
 -4.010416666666666666666667E-1,
  7.031250000000000000000000E-2
};
static double P3[] = {
 -1.025812596450617283950617E+0,
  1.846462673611111111111111E+0,
 -8.912109375000000000000000E-1,
  7.324218750000000000000000E-2
};
static double P4[] = {
  4.669584423426247427983539E+0,
 -1.120700261622299382716049E+1,
  8.789123535156250000000000E+0,
 -2.364086914062500000000000E+0,
  1.121520996093750000000000E-1
};
static double P5[] = {
 -2.8212072558200244877E1,
  8.4636217674600734632E1,
 -9.1818241543240017361E1,
  4.2534998745388454861E1,
 -7.3687943594796316964E0,
  2.27108001708984375E-1
};
static double P6[] = {
  2.1257013003921712286E2,
 -7.6525246814118164230E2,
  1.0599904525279998779E3,
 -6.9957962737613254123E2,
  2.1819051174421159048E2,
 -2.6491430486951555525E1,
  5.7250142097473144531E-1
};
static double P7[] = {
 -1.9194576623184069963E3,
  8.0617221817373093845E3,
 -1.3586550006434137439E4,
  1.1655393336864533248E4,
 -5.3056469786134031084E3,
  1.2009029132163524628E3,
 -1.0809091978839465550E2,
  1.7277275025844573975E0
};


static double jnx( n, x )
double n, x;
{
double zeta, sqz, zz, zp, np;
double cbn, n23, t, z, sz;
double pp, qq, z32i, zzi;
double ak, bk, akl, bkl;
int sign, doa, dob, nflg, k, s, tk, tkp1, m;
static double u[8];
static double ai, aip, bi, bip;

/* Test for x very close to n.
 * Use expansion for transition region if so.
 */

cbn = cbrt(n);
z = (x - n)/cbn;
if( fabs(z) <= 0.7 )
 return( jnt(n,x) );

z = x/n;
zz = 1.0 - z*z;
if( zz == 0.0 )
 return(0.0);

if( zz > 0.0 )
 {
 sz = sqrt( zz );
 t = 1.5 * (log( (1.0+sz)/z ) - sz ); /* zeta ** 3/2 */
 zeta = cbrt( t * t );
 nflg = 1;
 }
else
 {
 sz = sqrt(-zz);
 t = 1.5 * (sz - acos(1.0/z));
 zeta = -cbrt( t * t );
 nflg = -1;
 }
z32i = fabs(1.0/t);
sqz = cbrt(t);

/* Airy function */
n23 = cbrt( n * n );
t = n23 * zeta;

#if DEBUG
printf("zeta %.5E, Airy(%.5E)\n", zeta, t );
#endif
airy( t, &ai, &aip, &bi, &bip );

/* polynomials in expansion */
u[0] = 1.0;
zzi = 1.0/zz;
u[1] = polevl( zzi, P1, 1 )/sz;
u[2] = polevl( zzi, P2, 2 )/zz;
u[3] = polevl( zzi, P3, 3 )/(sz*zz);
pp = zz*zz;
u[4] = polevl( zzi, P4, 4 )/pp;
u[5] = polevl( zzi, P5, 5 )/(pp*sz);
pp *= zz;
u[6] = polevl( zzi, P6, 6 )/pp;
u[7] = polevl( zzi, P7, 7 )/(pp*sz);

#if DEBUG
for( k=0; k<=7; k++ )
 printf( "u[%d] = %.5E\n", k, u[k] );
#endif

pp = 0.0;
qq = 0.0;
np = 1.0;
/* flags to stop when terms get larger */
doa = 1;
dob = 1;
akl = MAXNUM;
bkl = MAXNUM;

for( k=0; k<=3; k++ )
 {
 tk = 2 * k;
 tkp1 = tk + 1;
 zp = 1.0;
 ak = 0.0;
 bk = 0.0;
 for( s=0; s<=tk; s++ )
  {
  if( doa )
   {
   if( (s & 3) > 1 )
    sign = nflg;
   else
    sign = 1;
   ak += sign * mu[s] * zp * u[tk-s];
   }

  if( dob )
   {
   m = tkp1 - s;
   if( ((m+1) & 3) > 1 )
    sign = nflg;
   else
    sign = 1;
   bk += sign * lambda[s] * zp * u[m];
   }
  zp *= z32i;
  }

 if( doa )
  {
  ak *= np;
  t = fabs(ak);
  if( t < akl )
   {
   akl = t;
   pp += ak;
   }
  else
   doa = 0;
  }

 if( dob )
  {
  bk += lambda[tkp1] * zp * u[0];
  bk *= -np/sqz;
  t = fabs(bk);
  if( t < bkl )
   {
   bkl = t;
   qq += bk;
   }
  else
   dob = 0;
  }
#if DEBUG
 printf("a[%d] %.5E, b[%d] %.5E\n", k, ak, k, bk );
#endif
 if( np < MACHEP )
  break;
 np /= n*n;
 }

/* normalizing factor ( 4*zeta/(1 - z**2) )**1/4 */
t = 4.0 * zeta/zz;
t = sqrt( sqrt(t) );

t *= ai*pp/cbrt(n)  +  aip*qq/(n23*n);
return(t);
}

/* Asymptotic expansion for transition region,
 * n large and x close to n.
 * AMS55 #9.3.23.
 */


static double PF2[] = {
 -9.0000000000000000000e-2,
  8.5714285714285714286e-2
};
static double PF3[] = {
  1.3671428571428571429e-1,
 -5.4920634920634920635e-2,
 -4.4444444444444444444e-3
};
static double PF4[] = {
  1.3500000000000000000e-3,
 -1.6036054421768707483e-1,
  4.2590187590187590188e-2,
  2.7330447330447330447e-3
};
static double PG1[] = {
 -2.4285714285714285714e-1,
  1.4285714285714285714e-2
};
static double PG2[] = {
 -9.0000000000000000000e-3,
  1.9396825396825396825e-1,
 -1.1746031746031746032e-2
};
static double PG3[] = {
  1.9607142857142857143e-2,
 -1.5983694083694083694e-1,
  6.3838383838383838384e-3
};


static double jnt( n, x )
double n, x;
{
double z, zz, z3;
double cbn, n23, cbtwo;
double ai, aip, bi, bip; /* Airy functions */
double nk, fk, gk, pp, qq;
double F[5], G[4];
int k;

cbn = cbrt(n);
z = (x - n)/cbn;
cbtwo = cbrt( 2.0 );

/* Airy function */
zz = -cbtwo * z;
airy( zz, &ai, &aip, &bi, &bip );

/* polynomials in expansion */
zz = z * z;
z3 = zz * z;
F[0] = 1.0;
F[1] = -z/5.0;
F[2] = polevl( z3, PF2, 1 ) * zz;
F[3] = polevl( z3, PF3, 2 );
F[4] = polevl( z3, PF4, 3 ) * z;
G[0] = 0.3 * zz;
G[1] = polevl( z3, PG1, 1 );
G[2] = polevl( z3, PG2, 2 ) * z;
G[3] = polevl( z3, PG3, 2 ) * zz;
#if DEBUG
for( k=0; k<=4; k++ )
 printf( "F[%d] = %.5E\n", k, F[k] );
for( k=0; k<=3; k++ )
 printf( "G[%d] = %.5E\n", k, G[k] );
#endif
pp = 0.0;
qq = 0.0;
nk = 1.0;
n23 = cbrt( n * n );

for( k=0; k<=4; k++ )
 {
 fk = F[k]*nk;
 pp += fk;
 if( k != 4 )
  {
  gk = G[k]*nk;
  qq += gk;
  }
#if DEBUG
 printf("fk[%d] %.5E, gk[%d] %.5E\n", k, fk, k, gk );
#endif
 nk /= n23;
 }

fk = cbtwo * ai * pp/cbn  +  cbrt(4.0) * aip * qq/n;
return(fk);
}

Messung V0.5 in Prozent
C=97 H=84 G=90

[Verzeichnis aufwärts0.25unsichere VerbindungÜbersetzung europäischer Sprachen durch Browser2026-06-18]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002