## Magnetic Whirl - struve.c

```    ```/*                                                      struve.c
*
*      Struve function
*
*
*
* SYNOPSIS:
*
* double v, x, y, struve();
*
* y = struve( v, x );
*
*
*
* DESCRIPTION:
*
* Computes the Struve function Hv(x) of order v, argument x.
* Negative x is rejected unless v is an integer.
*
* This module also contains the hypergeometric functions 1F2
* and 3F0 and a routine for the Bessel function Yv(x) with
* noninteger v.
*
*
*
* ACCURACY:
*
* Not accurately characterized, but spot checked against tables.
*
*/
/*
Cephes Math Library Release 2.81:  June, 2000
Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier
*/

static double stop=1.37e-17;
#define  MACHEP  1.11022302462515654042E-16

double onef2( double a, double b,double c,double x,double *err )
{
double n, a0, sum, t;
double an, bn, cn, max, z;
an = a;
bn = b;
cn = c;
a0 = 1.0;
sum = 1.0;
n = 1.0;
t = 1.0;
max = 0.0;
do
{
if( an == 0 )
goto done;
if( bn == 0 )
goto error;
if( cn == 0 )
goto error;
if( (a0 > 1.0e34) || (n > 200) )
goto error;
a0 *= (an * x) / (bn * cn * n);
sum += a0;
an += 1.0;
bn += 1.0;
cn += 1.0;
n += 1.0;
z = fabs( a0 );
if( z > max )
max = z;
if( sum != 0 )
t = fabs( a0 / sum );
else
t = z;
}
while( t > stop );

done:

*err = fabs(MACHEP * max / sum);

goto xit;

error:
*err = 1.0e38;

xit:
return(sum);
}

double threef0(double a, double b, double c, double x, double *err)
{
double n, a0, sum, t, conv, conv1;
double an, bn, cn, max, z;
an = a;
bn = b;
cn = c;
a0 = 1.0;
sum = 1.0;
n = 1.0;
t = 1.0;
max = 0.0;
conv = 1.0e38;
conv1 = conv;
do
{
if( an == 0.0 )
goto done;
if( bn == 0.0 )
goto done;
if( cn == 0.0 )
goto done;
if( (a0 > 1.0e34) || (n > 200) )
goto error;
a0 *= (an * bn * cn * x) / n;
an += 1.0;
bn += 1.0;
cn += 1.0;
n += 1.0;
z = fabs( a0 );
if( z > max )
max = z;
if( z >= conv )
{
if( (z < max) && (z > conv1) )
goto done;
}
conv1 = conv;
conv = z;
sum += a0;
if( sum != 0 )
t = fabs( a0 / sum );
else
t = z;
}
while( t > stop );
done:

t = fabs(MACHEP * max / sum);

max = fabs(conv / sum);
if (max > t)
t = max;

goto xit;

error:
t = 1.0e38;

xit:

*err = t;
return(sum);
}

/* Bessel function of noninteger order
*/
double yv(double v,double x )
{
double y, t;
int n;
y = floor( v );
if( y == v )
{
n = (int)(v);
y = sas_JN( n, x );
return( y );
}
t = M_PI * v;
y = (cos(t) * jv( v, x ) - jv( -v, x ))/sin(t);
return( y );
}

double struve( double v, double x )
{
double y, ya, f, g, h, t;
double onef2err, threef0err;
f = floor(v);
if( (v < 0) && ( v-f == 0.5 ) )
{
y = jv( -v, x );
f = 1.0 - f;
g =  2.0 * floor(f/2.0);
if( g != f )
y = -y;
return(y);
}
t = 0.25*x*x;
f = fabs(x);
g = 1.5 * fabs(v);
if( (f > 30.0) && (f > g) )
{
onef2err = 1.0e38;
y = 0.0;
}
else
{
y = onef2( 1.0, 1.5, 1.5+v, -t, &onef2err );
}
if( (f < 18.0) || (x < 0.0) )
{
threef0err = 1.0e38;
ya = 0.0;
}
else
{
ya = threef0( 1.0, 0.5, 0.5-v, -1.0/t, &threef0err );
}
f = sqrt( M_PI );
h = pow( 0.5*x, v-1.0 );
if( onef2err <= threef0err )
{
g = gam( v + 1.5 );
y = y * h * t / ( 0.5 * f * g );
return(y);
}
else
{
g = gam( v + 0.5 );
ya = ya * h / ( f * g );
ya = ya + yv( v, x );
return(ya);
}
}

/* Crossover points between ascending series and asymptotic series
* for Struve function
*
*       v       x
*
*       0      19.2
*       1      18.95
*       2      19.15
*       3      19.3
*       5      19.7
*      10      21.35
*      20      26.35
*      30      32.31
*      40      40.0
*/
```
```