psi Subroutine

subroutine psi(x, ps)

************80

! PSI computes the PSI function.

Licensing:

The original FORTRAN77 version of this routine is copyrighted by
Shanjie Zhang and Jianming Jin.  However, they give permission to
incorporate this routine into a user program that the copyright
is acknowledged.

Modified:

08 September 2007

Author:

Original FORTRAN77 by Shanjie Zhang, Jianming Jin.
FORTRAN90 version by John Burkardt.

Reference:

Shanjie Zhang, Jianming Jin,
Computation of Special Functions,
Wiley, 1996,
ISBN: 0-471-11963-6,
LC: QA351.C45

Parameters:

Input, real ( kind = 8 ) X, the argument.

Output, real ( kind = 8 ) PS, the value of the PSI function.

Arguments

Type IntentOptional Attributes Name
real(kind=8) :: x
real(kind=8) :: ps

Source Code

subroutine cpsi ( x, y, psr, psi )

  !*****************************************************************************80
  !
  !! CPSI computes the psi function for a complex argument.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    16 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, Y, the real and imaginary parts 
  !    of the argument.
  !
  !    Output, real ( kind = 8 ) PSR, PSI, the real and imaginary parts
  !    of the function value.
  !
  implicit none

  real ( kind = 8 ), save, dimension ( 8 ) :: a = (/ &
       -0.8333333333333D-01, 0.83333333333333333D-02, &
       -0.39682539682539683D-02, 0.41666666666666667D-02, &
       -0.75757575757575758D-02, 0.21092796092796093D-01, &
       -0.83333333333333333D-01, 0.4432598039215686D+00 /)
  real ( kind = 8 ) ct2
  integer ( kind = 4 ) k
  integer ( kind = 4 ) n
  real ( kind = 8 ) pi
  real ( kind = 8 ) psi
  real ( kind = 8 ) psr
  real ( kind = 8 ) ri
  real ( kind = 8 ) rr
  real ( kind = 8 ) th
  real ( kind = 8 ) tm
  real ( kind = 8 ) tn
  real ( kind = 8 ) x
  real ( kind = 8 ) x0
  real ( kind = 8 ) x1
  real ( kind = 8 ) y
  real ( kind = 8 ) y1
  real ( kind = 8 ) z0
  real ( kind = 8 ) z2

  pi = 3.141592653589793D+00

  if ( y == 0.0D+00 .and. x == int ( x ) .and. x <= 0.0D+00 ) then

     psr = 1.0D+300
     psi = 0.0D+00

  else

     if ( x < 0.0D+00 ) then
        x1 = x
        y1 = y
        x = -x
        y = -y
     end if

     x0 = x

     if ( x < 8.0D+00 ) then
        n = 8 - int ( x )
        x0 = x + n
     end if

     if ( x0 == 0.0D+00 ) then
        if ( y /= 0.0D+00 ) then
           th = 0.5D+00 * pi
        else
           th = 0.0D+00
        end if
     else
        th = atan ( y / x0 )
     end if

     z2 = x0 * x0 + y * y
     z0 = sqrt ( z2 )
     psr = log ( z0 ) - 0.5D+00 * x0 / z2
     psi = th + 0.5D+00 * y / z2
     do k = 1, 8
        psr = psr + a(k) * z2 ** ( - k ) * cos ( 2.0D+00 * k * th )
        psi = psi - a(k) * z2 ** ( - k ) * sin ( 2.0D+00 * k * th )
     end do

     if ( x < 8.0D+00 ) then
        rr = 0.0D+00
        ri = 0.0D+00
        do k = 1, n
           rr = rr + ( x0 - k ) / ( ( x0 - k ) ** 2.0D+00 + y * y )
           ri = ri + y / ( ( x0 - k ) ** 2.0D+00 + y * y )
        end do
        psr = psr - rr
        psi = psi + ri
     end if

     if ( x1 < 0.0D+00 ) then
        tn = tan ( pi * x )
        tm = tanh ( pi * y )
        ct2 = tn * tn + tm * tm
        psr = psr + x / ( x * x + y * y ) + pi * ( tn - tn * tm * tm ) / ct2
        psi = psi - y / ( x * x + y * y ) - pi * tm * ( 1.0D+00 + tn * tn ) / ct2
        x = x1
        y = y1
     end if

  end if

  return
end subroutine cpsi
subroutine csphik ( n, z, nm, csi, cdi, csk, cdk )

  !*****************************************************************************80
  !
  !! CSPHIK: complex modified spherical Bessel functions and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    29 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  ! 
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of in(z) and kn(z).
  !
  !    Input, complex ( kind = 8 ) Z, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, complex ( kind = 8 ) CSI(0:N), CDI(0:N), CSK(0:N), CDK(0:N),
  !    the values of in(z), in'(z), kn(z), kn'(z).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) a0
  complex ( kind = 8 ) ccosh1
  complex ( kind = 8 ) cdi(0:n)
  complex ( kind = 8 ) cdk(0:n)
  complex ( kind = 8 ) cf
  complex ( kind = 8 ) cf0
  complex ( kind = 8 ) cf1
  complex ( kind = 8 ) ci
  complex ( kind = 8 ) cs
  complex ( kind = 8 ) csi(0:n)
  complex ( kind = 8 ) csi0
  complex ( kind = 8 ) csi1
  complex ( kind = 8 ) csinh1
  complex ( kind = 8 ) csk(0:n)
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  real ( kind = 8 ) pi
  complex ( kind = 8 ) z

  pi = 3.141592653589793D+00
  a0 = abs ( z )    
  nm = n

  if ( a0 < 1.0D-60 ) then
     do k = 0, n
        csi(k) = 0.0D+00
        cdi(k) = 0.0D+00
        csk(k) = 1.0D+300
        cdk(k) = -1.0D+300
     end do
     csi(0) = 1.0D+00
     cdi(1) = 0.3333333333333333D+00
     return
  end if

  ci = cmplx ( 0.0D+00, 1.0D+00, kind = 8 )
  csinh1 = sin ( ci * z ) / ci
  ccosh1 = cos ( ci * z )
  csi0 = csinh1 / z
  csi1 = ( - csinh1 / z + ccosh1 ) / z
  csi(0) = csi0
  csi(1) = csi1

  if ( 2 <= n ) then

     m = msta1 ( a0, 200 )
     if ( m < n ) then
        nm = m
     else
        m = msta2 ( a0, n, 15 )
     end if

     cf0 = 0.0D+00
     cf1 = 1.0D+00-100
     do k = m, 0, -1
        cf = ( 2.0D+00 * k + 3.0D+00 ) * cf1 / z + cf0
        if ( k <= nm ) then
           csi(k) = cf
        end if
        cf0 = cf1
        cf1 = cf
     end do

     if ( abs ( csi0 ) <= abs ( csi1 ) ) then
        cs = csi1 / cf0
     else
        cs = csi0 / cf
     end if

     do k = 0, nm
        csi(k) = cs * csi(k)
     end do

  end if

  cdi(0) = csi(1)
  do k = 1, nm
     cdi(k) = csi(k-1) - ( k + 1.0D+00 ) * csi(k) / z
  end do

  csk(0) = 0.5D+00 * pi / z * exp ( - z )
  csk(1) = csk(0) * ( 1.0D+00 + 1.0D+00 / z )
  do k = 2, nm
     if ( abs ( csi(k-2) ) < abs ( csi(k-1) ) ) then
        csk(k) = ( 0.5D+00 * pi / ( z * z ) - csi(k) * csk(k-1) ) / csi(k-1)
     else
        csk(k) = ( csi(k) * csk(k-2) + ( k - 0.5D+00 ) * pi / z ** 3 ) / csi(k-2)
     end if
  end do

  cdk(0) = -csk(1)
  do k = 1, nm
     cdk(k) = - csk(k-1) - ( k + 1.0D+00 ) * csk(k) / z
  end do

  return
end subroutine csphik
subroutine csphjy ( n, z, nm, csj, cdj, csy, cdy )

  !*****************************************************************************80
  !
  !! CSPHJY: spherical Bessel functions jn(z) and yn(z) for complex argument.
  !
  !  Discussion:
  !
  !    This procedure computes spherical Bessel functions jn(z) and yn(z)
  !    and their derivatives for a complex argument.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    01 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  ! 
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of jn(z) and yn(z).
  !
  !    Input, complex ( kind = 8 ) Z, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, complex ( kind = 8 ) CSJ(0:N0, CDJ(0:N), CSY(0:N), CDY(0:N),
  !    the values of jn(z), jn'(z), yn(z), yn'(z).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) a0
  complex ( kind = 8 ) csj(0:n)
  complex ( kind = 8 ) cdj(0:n)
  complex ( kind = 8 ) csy(0:n)
  complex ( kind = 8 ) cdy(0:n)
  complex ( kind = 8 ) cf
  complex ( kind = 8 ) cf0
  complex ( kind = 8 ) cf1
  complex ( kind = 8 ) cs
  complex ( kind = 8 ) csa
  complex ( kind = 8 ) csb
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  complex ( kind = 8 ) z

  a0 = abs ( z )
  nm = n

  if ( a0 < 1.0D-60 ) then
     do k = 0, n
        csj(k) = 0.0D+00
        cdj(k) = 0.0D+00
        csy(k) = -1.0D+300
        cdy(k) = 1.0D+300
     end do
     csj(0) = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     cdj(1) = cmplx ( 0.333333333333333D+00, 0.0D+00, kind = 8 )
     return
  end if

  csj(0) = sin ( z ) / z
  csj(1) = ( csj(0) - cos ( z ) ) / z

  if ( 2 <= n ) then
     csa = csj(0)
     csb = csj(1)
     m = msta1 ( a0, 200 )
     if ( m < n ) then
        nm = m
     else
        m = msta2 ( a0, n, 15 )
     end if
     cf0 = 0.0D+00
     cf1 = 1.0D+00-100
     do k = m, 0, -1
        cf = ( 2.0D+00 * k + 3.0D+00 ) * cf1 / z - cf0
        if ( k <= nm ) then
           csj(k) = cf
        end if
        cf0 = cf1
        cf1 = cf
     end do

     if ( abs ( csa ) <= abs ( csb ) ) then
        cs = csb / cf0
     else
        cs = csa / cf
     end if

     do k = 0, nm
        csj(k) = cs * csj(k)
     end do

  end if

  cdj(0) = ( cos ( z ) - sin ( z ) / z ) / z
  do k = 1, nm
     cdj(k) = csj(k-1) - ( k + 1.0D+00 ) * csj(k) / z
  end do
  csy(0) = - cos ( z ) / z
  csy(1) = ( csy(0) - sin ( z ) ) / z
  cdy(0) = ( sin ( z ) + cos ( z ) / z ) / z
  cdy(1) = ( 2.0D+00 * cdy(0) - cos ( z ) )  / z

  do k = 2, nm
     if ( abs ( csj(k-2) ) < abs ( csj(k-1) ) ) then 
        csy(k) = ( csj(k) * csy(k-1) - 1.0D+00 / ( z * z ) ) / csj(k-1)
     else
        csy(k) = ( csj(k) * csy(k-2) &
             - ( 2.0D+00 * k - 1.0D+00 ) / z ** 3 ) / csj(k-2)
     end if
  end do

  do k = 2, nm
     cdy(k) = csy(k-1) - ( k + 1.0D+00 ) * csy(k) / z
  end do

  return
end subroutine csphjy
subroutine cv0 ( kd, m, q, a0 )

  !*****************************************************************************80
  !
  !! CV0 computes the initial characteristic value of Mathieu functions.
  !
  !  Discussion:
  !
  !    This procedure computes the initial characteristic value of Mathieu 
  !    functions for m <= 12 or q <= 300 or q <= m*m.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !   03 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KD, the case code:
  !    1, for cem(x,q)  ( m = 0,2,4,...)
  !    2, for cem(x,q)  ( m = 1,3,5,...)
  !    3, for sem(x,q)  ( m = 1,3,5,...)
  !    4, for sem(x,q)  ( m = 2,4,6,...)
  !
  !    Input, integer ( kind = 4 ) M, the order of the functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the functions.
  !
  !    Output, real ( kind = 8 ) A0, the characteristic value.
  !
  implicit none

  real ( kind = 8 ) a0
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) m
  real ( kind = 8 ) q
  real ( kind = 8 ) q2

  q2 = q * q

  if ( m == 0 ) then

     if ( q <= 1.0D+00 ) then

        a0 = ((( &
             0.0036392D+00   * q2 &
             - 0.0125868D+00 ) * q2 &
             + 0.0546875D+00 ) * q2 &
             - 0.5D+00 )       * q2

     else if ( q <= 10.0D+00 ) then

        a0 = (( &
             3.999267D-03   * q &
             - 9.638957D-02 ) * q &
             - 0.88297D+00 )  * q &
             + 0.5542818D+00 

     else

        call cvql ( kd, m, q, a0 )

     end if

  else if ( m == 1 ) then

     if ( q <= 1.0D+00 .and. kd == 2 ) then

        a0 = ((( &
             - 6.51D-04 * q &
             - 0.015625D+00 ) *  q &
             - 0.125D+00 ) * q &
             + 1.0D+00 ) * q &
             + 1.0D+00 

     else if ( q <= 1.0D+00 .and. kd == 3 ) then

        a0 = ((( &
             - 6.51D-04 * q &
             + 0.015625D+00 ) * q &
             - 0.125D+00 ) * q &
             - 1.0D+00 ) * q &
             + 1.0D+00

     else if ( q <= 10.0D+00 .and. kd == 2 ) then

        a0 = ((( &
             - 4.94603D-04 * q &
             + 1.92917D-02 ) * q &
             - 0.3089229D+00 ) * q &
             + 1.33372D+00 ) * q &
             + 0.811752D+00 

     else if ( q <= 10.0D+00 .and. kd == 3 ) then

        a0 = (( &
             1.971096D-03 * q &
             - 5.482465D-02 ) * q &
             - 1.152218D+00 ) * q &
             + 1.10427D+00 

     else

        call cvql ( kd, m, q, a0 )

     end if

  else if ( m == 2 ) then

     if ( q <= 1.0D+00 .and. kd == 1 ) then

        a0 = ((( &
             - 0.0036391D+00   * q2 &
             + 0.0125888D+00 ) * q2 &
             - 0.0551939D+00 ) * q2 &
             + 0.416667D+00 )  * q2 + 4.0D+00 

     else if ( q <= 1.0D+00 .and. kd == 4 ) then

        a0 = (  &
             0.0003617D+00 * q2  &
             - 0.0833333D+00 ) * q2 + 4.0D+00 

     else if ( q <= 15.0D+00 .and. kd == 1 ) then

        a0 = ((( &
             3.200972D-04    * q &
             - 8.667445D-03 )  * q &
             - 1.829032D-04 )  * q &
             + 0.9919999D+00 ) * q &
             + 3.3290504D+00 

     else if ( q <= 10.0D+00 .and. kd == 4 ) then

        a0 = (( &
             2.38446D-03 * q &
             - 0.08725329D+00 ) * q &
             - 4.732542D-03 ) * q &
             + 4.00909D+00 

     else

        call cvql ( kd, m, q, a0 )

     end if

  else if ( m == 3 ) then

     if ( q <= 1.0D+00 .and. kd == 2 ) then
        a0 = (( &
             6.348D-04 * q &
             + 0.015625D+00 ) * q &
             + 0.0625 ) * q2  &
             + 9.0D+00 
     else if ( q <= 1.0D+00 .and. kd == 3 ) then
        a0 = (( &
             6.348D-04 * q &
             - 0.015625D+00 ) * q &
             + 0.0625D+00 ) * q2 &
             + 9.0D+00 
     else if ( q <= 20.0D+00 .and. kd == 2 ) then
        a0 = ((( &
             3.035731D-04 * q &
             - 1.453021D-02 ) * q &
             + 0.19069602D+00 ) * q &
             - 0.1039356D+00 ) * q &
             + 8.9449274D+00 
     else if ( q <= 15.0D+00 .and. kd == 3 ) then
        a0 = (( &
             9.369364D-05 * q &
             - 0.03569325D+00 ) * q &
             + 0.2689874D+00 ) * q &
             + 8.771735D+00 
     else
        call cvql ( kd, m, q, a0 )
     end if

  else if ( m == 4 ) then

     if ( q <= 1.0D+00 .and. kd == 1 ) then
        a0 = (( &
             - 2.1D-06 * q2 &
             + 5.012D-04 ) * q2 &
             + 0.0333333 ) * q2 &
             + 16.0D+00
     else if ( q <= 1.0D+00 .and. kd == 4 ) then
        a0 = (( &
             3.7D-06 * q2 &
             - 3.669D-04 ) * q2 &
             + 0.0333333D+00 ) * q2 &
             + 16.0D+00
     else if ( q <= 25.0D+00 .and. kd == 1 ) then
        a0 = ((( &
             1.076676D-04 * q &
             - 7.9684875D-03 ) * q &
             + 0.17344854D+00 ) * q &
             - 0.5924058D+00 ) * q &
             + 16.620847D+00
     else if ( q <= 20.0D+00 .and. kd == 4 ) then
        a0 = (( &
             - 7.08719D-04 * q &
             + 3.8216144D-03 ) * q &
             + 0.1907493D+00 ) * q &
             + 15.744D+00
     else
        call cvql ( kd, m, q, a0 )
     end if

  else if ( m == 5 ) then

     if ( q <= 1.0D+00 .and. kd == 2 ) then
        a0 = (( &
             6.8D-6 * q &
             + 1.42D-05 ) * q2 &
             + 0.0208333D+00 ) * q2 &
             + 25.0D+00
     else if ( q <= 1.0D+00 .and. kd == 3 ) then
        a0 = (( &
             - 6.8D-06 * q &
             + 1.42D-05 ) * q2 &
             + 0.0208333D+00 ) * q2 &
             + 25.0D+00
     else if ( q <= 35.0D+00 .and. kd == 2 ) then
        a0 = ((( &
             2.238231D-05 * q &
             - 2.983416D-03 ) * q &
             + 0.10706975D+00 ) * q &
             - 0.600205D+00 ) * q &
             + 25.93515D+00
     else if ( q <= 25.0D+00 .and. kd == 3 ) then
        a0 = (( &
             - 7.425364D-04 * q &
             + 2.18225D-02 ) * q &
             + 4.16399D-02 ) * q &
             + 24.897D+00
     else
        call cvql ( kd, m, q, a0 )
     end if

  else if ( m == 6 ) then

     if ( q <= 1.0D+00 ) then
        a0 = ( 0.4D-06 * q2 + 0.0142857 ) * q2 + 36.0D+00
     else if ( q <= 40.0D+00 .and. kd == 1 ) then
        a0 = ((( &
             - 1.66846D-05 * q &
             + 4.80263D-04 ) * q &
             + 2.53998D-02 ) * q &
             - 0.181233D+00 ) * q  &
             + 36.423D+00
     else if ( q <= 35.0D+00 .and. kd == 4 ) then
        a0 = (( &
             - 4.57146D-04 * q &
             + 2.16609D-02 ) * q &
             - 2.349616D-02 ) * q &
             + 35.99251D+00
     else
        call cvql ( kd, m, q, a0 )
     end if

  else if ( m == 7 ) then

     if ( q <= 10.0D+00 ) then
        call cvqm ( m, q, a0 )
     else if ( q <= 50.0D+00 .and. kd == 2 ) then
        a0 = ((( &
             - 1.411114D-05 * q &
             + 9.730514D-04 ) * q &
             - 3.097887D-03 ) * q &
             + 3.533597D-02 ) * q &
             + 49.0547D+00
     else if ( q <= 40.0D+00 .and. kd == 3 ) then
        a0 = (( &
             - 3.043872D-04 * q &
             + 2.05511D-02 ) * q &
             - 9.16292D-02 ) * q &
             + 49.19035D+00
     else
        call cvql ( kd, m, q, a0 )
     end if

  else if ( 8 <= m ) then

     if ( q <= 3.0D+00 * m ) then
        call cvqm ( m, q, a0 )
     else if ( m * m .lt. q ) then
        call cvql ( kd, m, q, a0 )
     else if ( m == 8 .and. kd == 1 ) then
        a0 = ((( &
             8.634308D-06 * q &
             - 2.100289D-03 ) * q &
             + 0.169072D+00 ) * q &
             - 4.64336D+00 ) * q &
             + 109.4211D+00
     else if ( m == 8 .and. kd == 4 ) then
        a0 = (( &
             - 6.7842D-05 * q &
             + 2.2057D-03 ) * q &
             + 0.48296D+00 ) * q &
             + 56.59D+00
     else if ( m == 9 .and. kd == 2 ) then
        a0 = ((( &
             2.906435D-06 * q &
             - 1.019893D-03 ) * q &
             + 0.1101965D+00 ) * q &
             - 3.821851D+00 ) * q &
             + 127.6098D+00
     else if ( m == 9 .and. kd == 3 ) then
        a0 = (( &
             - 9.577289D-05 * q &
             + 0.01043839D+00 ) * q &
             + 0.06588934D+00 ) * q &
             + 78.0198D+00
     else if ( m == 10 .and. kd == 1 ) then
        a0 = ((( &
             5.44927D-07 * q &
             - 3.926119D-04 ) * q &
             + 0.0612099D+00 ) * q &
             - 2.600805D+00 ) * q &
             + 138.1923D+00
     else if ( m == 10 .and. kd == 4 ) then
        a0 = (( &
             - 7.660143D-05 * q &
             + 0.01132506D+00 ) * q &
             - 0.09746023D+00 ) * q &
             + 99.29494D+00
     else if ( m == 11 .and. kd == 2 ) then
        a0 = ((( &
             - 5.67615D-07 * q &
             + 7.152722D-06 ) * q &
             + 0.01920291D+00 ) * q &
             - 1.081583D+00 ) * q &
             + 140.88D+00
     else if ( m == 11 .and. kd == 3 ) then
        a0 = (( &
             - 6.310551D-05 * q &
             + 0.0119247D+00 ) * q &
             - 0.2681195D+00 ) * q &
             + 123.667D+00 
     else if ( m == 12 .and. kd == 1 ) then
        a0 = ((( &
             - 2.38351D-07 * q &
             - 2.90139D-05 ) * q &
             + 0.02023088D+00 ) * q &
             - 1.289D+00 ) * q &
             + 171.2723D+00
     else if ( m == 12 .and. kd == 4 ) then
        a0 = ((( &
             3.08902D-07 * q &
             - 1.577869D-04 ) * q &
             + 0.0247911D+00 ) * q &
             - 1.05454D+00 ) * q  &
             + 161.471D+00

     end if

  end if

  return
end subroutine cv0
subroutine cva1 ( kd, m, q, cv )

  !*****************************************************************************80
  !
  !! CVA1 computes a sequence of characteristic values of Mathieu functions.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    25 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KD, the case code.
  !    1, for cem(x,q)  ( m = 0,2,4,... )
  !    2, for cem(x,q)  ( m = 1,3,5,... )
  !    3, for sem(x,q)  ( m = 1,3,5,... )
  !    4, for sem(x,q)  ( m = 2,4,6,... )
  !
  !    Input, integer ( kind = 4 ) M, the maximum order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the Mathieu functions.
  !
  !    Output, real ( kind = 8 ) CV(*), characteristic values.
  !    For KD = 1, CV(1), CV(2), CV(3),..., correspond to
  !    the characteristic values of cem for m = 0,2,4,...
  !    For KD = 2, CV(1), CV(2), CV(3),..., correspond to
  !    the characteristic values of cem for m = 1,3,5,...
  !    For KD = 3, CV(1), CV(2), CV(3),..., correspond to
  !    the characteristic values of sem for m = 1,3,5,...
  !    For KD = 4, CV(1), CV(2), CV(3),..., correspond to
  !    the characteristic values of sem for m = 0,2,4,...
  !       
  implicit none

  real ( kind = 8 ) cv(200)
  real ( kind = 8 ) d(500)
  real ( kind = 8 ) e(500)
  real ( kind = 8 ) eps
  real ( kind = 8 ) f(500)
  real ( kind = 8 ) g(200)
  real ( kind = 8 ) h(200)
  integer ( kind = 4 ) i
  integer ( kind = 4 ) ic
  integer ( kind = 4 ) icm
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k1
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) m
  integer ( kind = 4 ) nm
  integer ( kind = 4 ) nm1
  real ( kind = 8 ) q
  real ( kind = 8 ) s
  real ( kind = 8 ) t
  real ( kind = 8 ) t1
  real ( kind = 8 ) x1
  real ( kind = 8 ) xa
  real ( kind = 8 ) xb

  eps = 1.0D-14

  if ( kd == 4 ) then
     icm = m / 2
  else
     icm = int ( m / 2 ) + 1
  end if

  if ( q == 0.0D+00 ) then

     if ( kd == 1 ) then
        do ic = 1, icm
           cv(ic) = 4.0D+00 * ( ic - 1.0D+00 ) ** 2
        end do
     else if ( kd /= 4 ) then
        do ic = 1, icm
           cv(ic) = ( 2.0D+00 * ic - 1.0D+00 ) ** 2
        end do
     else
        do ic = 1, icm
           cv(ic) = 4.0D+00 * ic * ic
        end do
     end if

  else

     nm = int ( 10D+00 + 1.5D+00 * m + 0.5D+00 * q )
     e(1) = 0.0D+00
     f(1) = 0.0D+00

     if ( kd == 1 ) then

        d(1) = 0.0D+00
        do i = 2, nm
           d(i) = 4.0D+00 * ( i - 1.0D+00 ) ** 2
           e(i) = q
           f(i) = q * q
        end do
        e(2) = sqrt ( 2.0D+00 ) * q
        f(2) = 2.0D+00 * q * q

     else if ( kd /= 4 ) then

        d(1) = 1.0D+00 + ( -1.0D+00 ) ** kd * q
        do i = 2, nm
           d(i) = ( 2.0D+00 * i - 1.0D+00 ) ** 2
           e(i) = q
           f(i) = q * q
        end do

     else

        d(1) = 4.0D+00
        do i = 2, nm
           d(i) = 4.0D+00 * i * i
           e(i) = q
           f(i) = q * q
        end do

     end if

     xa = d(nm) + abs ( e(nm) )
     xb = d(nm) - abs ( e(nm) )

     nm1 = nm - 1
     do i = 1, nm1
        t = abs ( e(i) ) + abs ( e(i+1) )
        t1 = d(i) + t
        xa = max ( xa, t1 )
        t1 = d(i) - t
        xb = min ( xb, t1 )
     end do

     do i = 1, icm
        g(i) = xa
        h(i) = xb
     end do

     do k = 1, icm

        do k1 = k, icm
           if ( g(k1) < g(k) ) then
              g(k) = g(k1)
              exit
           end if
        end do

        if ( k /= 1 .and. h(k) < h(k-1) ) then
           h(k) = h(k-1)
        end if

        do

           x1 = ( g(k) + h(k) ) /2.0D+00
           cv(k) = x1

           if ( abs ( ( g(k) - h(k) ) / x1 ) < eps ) then
              exit
           end if

           j = 0
           s = 1.0D+00
           do i = 1, nm
              if ( s == 0.0D+00 ) then
                 s = s + 1.0D-30
              end if
              t = f(i) / s
              s = d(i) - t - x1
              if ( s < 0.0D+00 ) then
                 j = j + 1
              end if
           end do

           if ( j < k ) then
              h(k) = x1
           else
              g(k) = x1
              if ( icm <= j ) then
                 g(icm) = x1
              else
                 h(j+1) = max ( h(j+1), x1 )
                 g(j) = min ( g(j), x1 )
              end if
           end if

        end do

        cv(k) = x1

     end do

  end if

  return
end subroutine cva1
subroutine cva2 ( kd, m, q, a )

  !*****************************************************************************80
  !
  !! CVA2 computes a specific characteristic value of Mathieu functions.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    22 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KD, the case code:
  !    1, for cem(x,q)  ( m = 0,2,4,...)
  !    2, for cem(x,q)  ( m = 1,3,5,...)
  !    3, for sem(x,q)  ( m = 1,3,5,...)
  !    4, for sem(x,q)  ( m = 2,4,6,...)
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the Mathieu functions.
  !
  !    Output, real ( kind = 8 ) A, the characteristic value.
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) a1
  real ( kind = 8 ) a2
  real ( kind = 8 ) delta
  integer ( kind = 4 ) i
  integer ( kind = 4 ) iflag
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) m
  integer ( kind = 4 ) ndiv
  integer ( kind = 4 ) nn
  real ( kind = 8 ) q
  real ( kind = 8 ) q1
  real ( kind = 8 ) q2
  real ( kind = 8 ) qq

  if ( m <= 12 .or. q <= 3.0D+00 * m .or. m * m < q ) then

     call cv0 ( kd, m, q, a )

     if ( q /= 0.0D+00 ) then
        call refine ( kd, m, q, a, 1 )
     end if

  else

     ndiv = 10
     delta = ( m - 3.0D+00 ) * m / real ( ndiv, kind = 8 )

     if ( ( q - 3.0D+00 * m ) <= ( m * m - q ) ) then

        do

           nn = int ( ( q - 3.0D+00 * m ) / delta ) + 1
           delta = ( q - 3.0D+00 * m ) / nn
           q1 = 2.0D+00 * m
           call cvqm ( m, q1, a1 )
           q2 = 3.0D+00 * m
           call cvqm ( m, q2, a2 )
           qq = 3.0D+00 * m

           do i = 1, nn

              qq = qq + delta
              a = ( a1 * q2 - a2 * q1 + ( a2 - a1 ) * qq ) / ( q2 - q1 )

              if ( i == nn ) then
                 iflag = -1
              else
                 iflag = 1
              end if

              call refine ( kd, m, qq, a, iflag )
              q1 = q2
              q2 = qq
              a1 = a2
              a2 = a

           end do

           if ( iflag /= -10 ) then
              exit
           end if

           ndiv = ndiv * 2
           delta = ( m - 3.0D+00 ) * m / real ( ndiv, kind = 8 )

        end do

     else

        do

           nn = int ( ( m * m - q ) / delta ) + 1
           delta = ( m * m - q ) / nn
           q1 = m * ( m - 1.0D+00 )
           call cvql ( kd, m, q1, a1 )
           q2 = m * m
           call cvql ( kd, m, q2, a2 )
           qq = m * m

           do i = 1, nn

              qq = qq - delta
              a = ( a1 * q2 - a2 * q1 + ( a2 - a1 ) * qq ) / ( q2 - q1 )

              if ( i == nn ) then
                 iflag = -1
              else
                 iflag = 1
              end if

              call refine ( kd, m, qq, a, iflag )
              q1 = q2
              q2 = qq
              a1 = a2
              a2 = a

           end do

           if ( iflag /= -10 ) then
              exit
           end if

           ndiv = ndiv * 2
           delta = ( m - 3.0D+00 ) * m / real ( ndiv, kind = 8 )

        end do

     end if

  end if

  return
end subroutine cva2
subroutine cvf ( kd, m, q, a, mj, f )

  !*****************************************************************************80
  !
  !! CVF computes F for the characteristic equation of Mathieu functions.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    16 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KD, the case code:
  !    1, for cem(x,q)  ( m = 0,2,4,...)
  !    2, for cem(x,q)  ( m = 1,3,5,...)
  !    3, for sem(x,q)  ( m = 1,3,5,...)
  !    4, for sem(x,q)  ( m = 2,4,6,...)
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) A, the characteristic value.
  !
  !    Input, integer ( kind = 4 ) MJ, ?
  !
  !    Output, real ( kind = 8 ) F, the value of the function for the
  !    characteristic equation.
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) b
  real ( kind = 8 ) f
  integer ( kind = 4 ) ic
  integer ( kind = 4 ) j
  integer ( kind = 4 ) j0
  integer ( kind = 4 ) jf
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) l
  integer ( kind = 4 ) l0
  integer ( kind = 4 ) m
  integer ( kind = 4 ) mj
  real ( kind = 8 ) q
  real ( kind = 8 ) t0
  real ( kind = 8 ) t1
  real ( kind = 8 ) t2

  b = a
  ic = int ( m / 2 )
  l = 0
  l0 = 0
  j0 = 2
  jf = ic

  if ( kd == 1 ) then
     l0 = 2
     j0 = 3
  else if ( kd == 2 .or. kd == 3 ) then
     l = 1
  else if ( kd == 4 ) then
     jf = ic - 1
  end if

  t1 = 0.0D+00
  do j = mj, ic + 1, -1
     t1 = - q * q / ( ( 2.0D+00 * j + l ) ** 2 - b + t1 )
  end do

  if ( m <= 2 ) then

     t2 = 0.0D+00

     if ( kd == 1 ) then
        if ( m == 0 ) then
           t1 = t1 + t1
        else if ( m == 2 ) then
           t1 = - 2.0D+00 * q * q / ( 4.0D+00 - b + t1 ) - 4.0D+00
        end if
     else if ( kd == 2 ) then
        if ( m == 1 ) then
           t1 = t1 + q
        end if
     else if ( kd == 3 ) then
        if ( m == 1 ) then
           t1 = t1 - q
        end if
     end if

  else

     if ( kd == 1 ) then
        t0 = 4.0D+00 - b + 2.0D+00 * q * q / b
     else if ( kd == 2 ) then
        t0 = 1.0D+00 - b + q
     else if ( kd == 3 ) then
        t0 = 1.0D+00 - b - q
     else if ( kd == 4 ) then
        t0 = 4.0D+00 - b
     end if

     t2 = - q * q / t0
     do j = j0, jf
        t2 = - q * q / ( ( 2.0D+00 * j - l - l0 ) ** 2 - b + t2 )
     end do

  end if

  f = ( 2.0D+00 * ic + l ) ** 2 + t1 + t2 - b

  return
end subroutine cvf
subroutine cvql ( kd, m, q, a0 )

  !*****************************************************************************80
  !
  !! CVQL computes the characteristic value of Mathieu functions for q <= 3*m.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    10 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KD, the case code:
  !    1, for cem(x,q)  ( m = 0,2,4,...)
  !    2, for cem(x,q)  ( m = 1,3,5,...)
  !    3, for sem(x,q)  ( m = 1,3,5,...)
  !    4, for sem(x,q)  ( m = 2,4,6,...)
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter value.
  !
  !    Output, real ( kind = 8 ) A0, the initial characteristic value.
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) c1
  real ( kind = 8 ) cv1
  real ( kind = 8 ) cv2
  real ( kind = 8 ) d1
  real ( kind = 8 ) d2
  real ( kind = 8 ) d3
  real ( kind = 8 ) d4
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) m
  real ( kind = 8 ) p1
  real ( kind = 8 ) p2
  real ( kind = 8 ) q
  real ( kind = 8 ) w
  real ( kind = 8 ) w2
  real ( kind = 8 ) w3
  real ( kind = 8 ) w4
  real ( kind = 8 ) w6

  if ( kd == 1 .or. kd == 2 ) then
     w = 2.0D+00 * m + 1.0D+00
  else
     w = 2.0D+00 * m - 1.0D+00
  end if

  w2 = w * w
  w3 = w * w2
  w4 = w2 * w2
  w6 = w2 * w4
  d1 = 5.0D+00 + 34.0D+00 / w2 + 9.0D+00 / w4
  d2 = ( 33.0D+00 + 410.0D+00 / w2 + 405.0D+00 / w4 ) / w
  d3 = ( 63.0D+00 + 1260.0D+00 / w2 + 2943.0D+00 / w4 + 486.0D+00 / w6 ) / w2
  d4 = ( 527.0D+00 + 15617.0D+00 / w2 + 69001.0D+00 / w4 &
       + 41607.0D+00 / w6 ) / w3
  c1 = 128.0D+00
  p2 = q / w4
  p1 = sqrt ( p2 )
  cv1 = - 2.0D+00 * q + 2.0D+00 * w * sqrt ( q ) &
       - ( w2 + 1.0D+00 ) / 8.0D+00
  cv2 = ( w + 3.0D+00 / w ) + d1 / ( 32.0D+00 * p1 ) + d2 &
       / ( 8.0D+00 * c1 * p2 )
  cv2 = cv2 + d3 / ( 64.0D+00 * c1 * p1 * p2 ) + d4 &
       / ( 16.0D+00 * c1 * c1 * p2 * p2 )
  a0 = cv1 - cv2 / ( c1 * p1 )

  return
end subroutine cvql
subroutine cvqm ( m, q, a0 )

  !*****************************************************************************80
  !
  !! CVQM computes the characteristic value of Mathieu functions for q <= m*m.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    07 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter value.
  !
  !    Output, real ( kind = 8 ) A0, the initial characteristic value.
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) hm1
  real ( kind = 8 ) hm3
  real ( kind = 8 ) hm5
  integer ( kind = 4 ) m
  real ( kind = 8 ) q

  hm1 = 0.5D+00 * q / ( m * m - 1.0D+00 )
  hm3 = 0.25D+00 * hm1 ** 3 / ( m * m - 4.0D+00 )
  hm5 = hm1 * hm3 * q / ( ( m * m - 1.0D+00 ) * ( m * m - 9.0D+00 ) )
  a0 = m * m + q * ( hm1 + ( 5.0D+00 * m * m + 7.0D+00 ) * hm3 &
       + ( 9.0D+00 * m ** 4 + 58.0D+00 * m * m + 29.0D+00 ) * hm5 )

  return
end subroutine cvqm
subroutine cy01 ( kf, z, zf, zd )

  !*****************************************************************************80
  !
  !! CY01 computes complex Bessel functions Y0(z) and Y1(z) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    01 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer KF, the function choice.
  !    0 for ZF = Y0(z) and ZD = Y0'(z);
  !    1 for ZF = Y1(z) and ZD = Y1'(z);
  !    2 for ZF = Y1'(z) and ZD = Y1''(z).
  !
  !    Input, complex ( kind = 8 ) Z, the argument.
  !
  !    Output, complex ( kind = 8 ) ZF, ZD, the values of the requested function 
  !    and derivative.
  !
  implicit none

  real ( kind = 8 ), save, dimension(12) :: a = (/ &
       -0.703125D-01, 0.112152099609375D+00, &
       -0.5725014209747314D+00, 0.6074042001273483D+01, &
       -0.1100171402692467D+03, 0.3038090510922384D+04, &
       -0.1188384262567832D+06, 0.6252951493434797D+07, &
       -0.4259392165047669D+09, 0.3646840080706556D+11, &
       -0.3833534661393944D+13, 0.4854014686852901D+15 /)
  real ( kind = 8 ) a0
  real ( kind = 8 ), save, dimension(12) :: a1 = (/ &
       0.1171875D+00, -0.144195556640625D+00, &
       0.6765925884246826D+00, -0.6883914268109947D+01, &
       0.1215978918765359D+03, -0.3302272294480852D+04, &
       0.1276412726461746D+06, -0.6656367718817688D+07, &
       0.4502786003050393D+09, -0.3833857520742790D+11, &
       0.4011838599133198D+13, -0.5060568503314727D+15 /)
  real ( kind = 8 ), save, dimension(12) :: b = (/ &
       0.732421875D-01, -0.2271080017089844D+00, &
       0.1727727502584457D+01, -0.2438052969955606D+02, &
       0.5513358961220206D+03, -0.1825775547429318D+05, &
       0.8328593040162893D+06, -0.5006958953198893D+08, &
       0.3836255180230433D+10, -0.3649010818849833D+12, &
       0.4218971570284096D+14, -0.5827244631566907D+16 /)
  real ( kind = 8 ), save, dimension(12) :: b1 = (/ &
       -0.1025390625D+00, 0.2775764465332031D+00, &
       -0.1993531733751297D+01, 0.2724882731126854D+02, &
       -0.6038440767050702D+03, 0.1971837591223663D+05, &
       -0.8902978767070678D+06, 0.5310411010968522D+08, &
       -0.4043620325107754D+10, 0.3827011346598605D+12, &
       -0.4406481417852278D+14, 0.6065091351222699D+16 /)
  complex ( kind = 8 ) cbj0
  complex ( kind = 8 ) cbj1
  complex ( kind = 8 ) cby0
  complex ( kind = 8 ) cby1
  complex ( kind = 8 ) cdy0
  complex ( kind = 8 ) cdy1
  complex ( kind = 8 ) ci
  complex ( kind = 8 ) cp
  complex ( kind = 8 ) cp0
  complex ( kind = 8 ) cp1
  complex ( kind = 8 ) cq0
  complex ( kind = 8 ) cq1
  complex ( kind = 8 ) cr
  complex ( kind = 8 ) cs
  complex ( kind = 8 ) ct1
  complex ( kind = 8 ) ct2
  complex ( kind = 8 ) cu
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  integer ( kind = 4 ) kf
  real ( kind = 8 ) pi
  real ( kind = 8 ) rp2
  real ( kind = 8 ) w0
  real ( kind = 8 ) w1
  complex ( kind = 8 ) z
  complex ( kind = 8 ) z1
  complex ( kind = 8 ) z2
  complex ( kind = 8 ) zd
  complex ( kind = 8 ) zf

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00
  rp2 = 2.0D+00 / pi
  ci = cmplx ( 0.0D+00, 1.0D+00, kind = 8 )
  a0 = abs ( z )
  z2 = z * z
  z1 = z

  if ( a0 == 0.0D+00 ) then

     cbj0 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     cbj1 = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )
     cby0 = cmplx ( -1.0D+30, 0.0D+00, kind = 8 )
     cby1 = cmplx ( -1.0D+30, 0.0D+00, kind = 8 )
     cdy0 = cmplx ( 1.0D+30, 0.0D+00, kind = 8 )
     cdy1 = cmplx ( 1.0D+30, 0.0D+00, kind = 8 )

  else

     if ( real ( z, kind = 8 ) < 0.0D+00) then
        z1 = -z
     end if

     if ( a0 <= 12.0D+00 ) then

        cbj0 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        cr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do k = 1, 40
           cr = - 0.25D+00 * cr * z2 / ( k * k )
           cbj0 = cbj0 + cr
           if ( abs ( cr ) < abs ( cbj0 ) * 1.0D-15 ) then
              exit
           end if
        end do

        cbj1 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        cr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do k = 1, 40
           cr = -0.25D+00 * cr * z2 / ( k * ( k + 1.0D+00 ) )
           cbj1 = cbj1 + cr
           if ( abs ( cr ) < abs ( cbj1 ) * 1.0D-15 ) then
              exit
           end if
        end do

        cbj1 = 0.5D+00 * z1 * cbj1
        w0 = 0.0D+00
        cr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        cs = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )
        do k = 1, 40
           w0 = w0 + 1.0D+00 / k
           cr = -0.25D+00 * cr / ( k * k ) * z2
           cp = cr * w0
           cs = cs + cp
           if ( abs ( cp ) < abs ( cs ) * 1.0D-15 ) then
              exit
           end if
        end do

        cby0 = rp2 * ( log ( z1 / 2.0D+00 ) + el ) * cbj0 - rp2 * cs
        w1 = 0.0D+00
        cr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        cs = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do k = 1, 40
           w1 = w1 + 1.0D+00 / k
           cr = - 0.25D+00 * cr / ( k * ( k + 1 ) ) * z2
           cp = cr * ( 2.0D+00 * w1 + 1.0D+00 / ( k + 1.0D+00 ) )
           cs = cs + cp
           if ( abs ( cp ) < abs ( cs ) * 1.0D-15 ) then
              exit
           end if
        end do

        cby1 = rp2 * ( ( log ( z1 / 2.0D+00 ) + el ) * cbj1 &
             - 1.0D+00 / z1 - 0.25D+00 * z1 * cs )

     else

        if ( a0 < 35.0D+00 ) then
           k0 = 12
        else if ( a0 < 50.0D+00 ) then
           k0 = 10
        else
           k0 = 8
        end if

        ct1 = z1 - 0.25D+00 * pi
        cp0 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do k = 1, k0
           cp0 = cp0 + a(k) * z1 ** ( - 2 * k )
        end do
        cq0 = -0.125D+00 / z1
        do k = 1, k0
           cq0 = cq0 + b(k) * z1 ** ( - 2 * k - 1 )
        end do
        cu = sqrt ( rp2 / z1 )
        cbj0 = cu * ( cp0 * cos ( ct1 ) - cq0 * sin ( ct1 ) )
        cby0 = cu * ( cp0 * sin ( ct1 ) + cq0 * cos ( ct1 ) )
        ct2 = z1 - 0.75D+00 * pi
        cp1 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do k = 1, k0
           cp1 = cp1 + a1(k) * z1 ** ( - 2 * k )
        end do
        cq1 = 0.375D+00 / z1
        do k = 1, k0
           cq1 = cq1 + b1(k) * z1 ** ( - 2 * k - 1 )
        end do
        cbj1 = cu * ( cp1 * cos ( ct2 ) - cq1 * sin ( ct2 ) )
        cby1 = cu * ( cp1 * sin ( ct2 ) + cq1 * cos ( ct2 ) )

     end if

     if ( real ( z, kind = 8 ) < 0.0D+00 ) then

        if ( imag ( z ) < 0.0D+00 ) then
           cby0 = cby0 - 2.0D+00 * ci * cbj0
        else
           cby0 = cby0 + 2.0D+00 * ci * cbj0
        end if

        if ( imag ( z ) < 0.0D+00 ) then
           cby1 = - ( cby1 - 2.0D+00 * ci * cbj1 )
        else
           cby1 = - ( cby1 + 2.0D+00 * ci * cbj1 )
        end if
        cbj1 = - cbj1

     end if

     cdy0 = - cby1
     cdy1 = cby0 - 1.0D+00 / z * cby1

  end if

  if ( kf == 0 ) then
     zf = cby0
     zd = cdy0
  else if ( kf == 1 ) then
     zf = cby1
     zd = cdy1
  else if ( kf == 2 ) then
     zf = cdy1
     zd = - cdy1 / z - ( 1.0D+00 - 1.0D+00 / ( z * z ) ) * cby1
  end if

  return
end subroutine cy01
subroutine cyzo ( nt, kf, kc, zo, zv )

  !*****************************************************************************80
  !
  !! CYZO computes zeros of complex Bessel functions Y0(z) and Y1(z) and Y1'(z).
  !
  !  Parameters:
  !
  !    Ths procedure computes the complex zeros of Y0(z), Y1(z) and Y1'(z), 
  !    and their associated values at the zeros using the modified Newton's 
  !    iteration method.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    22 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) NT, the number of zeros.
  !
  !    Input, integer ( kind = 4 ) KF, the function choice.
  !    0 for Y0(z) and Y1(z0);
  !    1 for Y1(z) and Y0(z1);
  !    2 for Y1'(z) and Y1(z1').
  !
  !    Input, integer ( kind = 4 ) KC, complex/real choice.
  !    0, for complex roots;
  !    1, for real roots.
  !
  !    Output, real ( kind = 8 ) ZO(NT), ZV(NT), the zeros of Y0(z) or Y1(z) 
  !    or Y1'(z), and the value of Y0'(z) or Y1'(z) or Y1(z) at the L-th zero.
  !
  implicit none

  integer ( kind = 4 ) nt

  real ( kind = 8 ) h
  integer ( kind = 4 ) i
  integer ( kind = 4 ) it
  integer ( kind = 4 ) j
  integer ( kind = 4 ) kc
  integer ( kind = 4 ) kf
  integer ( kind = 4 ) nr
  real ( kind = 8 ) w
  real ( kind = 8 ) w0
  real ( kind = 8 ) x
  real ( kind = 8 ) y
  complex ( kind = 8 ) z
  complex ( kind = 8 ) zd
  complex ( kind = 8 ) zero
  complex ( kind = 8 ) zf
  complex ( kind = 8 ) zfd
  complex ( kind = 8 ) zgd
  complex ( kind = 8 ) zo(nt)
  complex ( kind = 8 ) zp
  complex ( kind = 8 ) zq
  complex ( kind = 8 ) zv(nt)
  complex ( kind = 8 ) zw

  if ( kc == 0 ) then
     x = -2.4D+00
     y = 0.54D+00
     h = 3.14D+00
  else if ( kc == 1 ) then
     x = 0.89D+00
     y = 0.0D+00
     h = -3.14D+00
  end if

  if ( kf == 1 ) then
     x = -0.503D+00
  else if ( kf == 2 ) then
     x = 0.577D+00
  end if

  zero = cmplx ( x, y, kind = 8 )

  do nr = 1, nt

     if ( nr == 1 ) then
        z = zero
     else
        z = zo(nr-1) - h
     end if

     it = 0

     do

        it = it + 1
        call cy01 ( kf, z, zf, zd )

        zp = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do i = 1, nr - 1
           zp = zp * ( z - zo(i) )
        end do

        zfd = zf / zp

        zq = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )
        do i = 1, nr - 1
           zw = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
           do j = 1, nr - 1
              if ( j /= i ) then
                 zw = zw * ( z - zo(j) )
              end if
           end do
           zq = zq + zw
        end do

        zgd = ( zd - zq * zfd ) / zp
        z = z - zfd / zgd
        w0 = w
        w = abs ( z )

        if ( 50 < it .or. abs ( ( w - w0 ) / w ) <= 1.0D-12 ) then
           exit
        end if

     end do

     zo(nr) = z

  end do

  do i = 1, nt
     z = zo(i)
     if ( kf == 0 .or. kf == 2 ) then
        call cy01 ( 1, z, zf, zd )
        zv(i) = zf
     else if ( kf == 1 ) then
        call cy01 ( 0, z, zf, zd )
        zv(i) = zf
     end if
  end do

  return
end subroutine cyzo
subroutine dvla ( va, x, pd )

  !*****************************************************************************80
  !
  !! DVLA computes parabolic cylinder functions Dv(x) for large argument.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    06 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  ! 
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Input, real ( kind = 8 ) VA, the order.
  !
  !    Output, real ( kind = 8 ) PD, the function value.
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) ep
  real ( kind = 8 ) eps
  real ( kind = 8 ) gl
  integer ( kind = 4 ) k
  real ( kind = 8 ) pd
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) va
  real ( kind = 8 ) vl
  real ( kind = 8 ) x
  real ( kind = 8 ) x1

  pi = 3.141592653589793D+00
  eps = 1.0D-12
  ep = exp ( -0.25D+00 * x * x )
  a0 = abs ( x ) ** va * ep
  r = 1.0D+00
  pd = 1.0D+00
  do k = 1, 16
     r = -0.5D+00 * r * ( 2.0D+00 * k - va - 1.0D+00 ) &
          * ( 2.0D+00 * k - va - 2.0D+00 ) / ( k * x * x )
     pd = pd + r
     if ( abs ( r / pd ) < eps ) then
        exit
     end if
  end do

  pd = a0 * pd

  if ( x < 0.0D+00 ) then
     x1 = - x
     call vvla ( va, x1, vl )
     call gammaf ( -va, gl )
     pd = pi * vl / gl + cos ( pi * va ) * pd
  end if

  return
end subroutine dvla
subroutine dvsa ( va, x, pd )

  !*****************************************************************************80
  !
  !! DVSA computes parabolic cylinder functions Dv(x) for small argument.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    07 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) VA, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) PD, the function value.
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) ep
  real ( kind = 8 ) eps
  real ( kind = 8 ) g0
  real ( kind = 8 ) g1
  real ( kind = 8 ) ga0
  real ( kind = 8 ) gm
  integer ( kind = 4 ) m
  real ( kind = 8 ) pd
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) r1
  real ( kind = 8 ) sq2
  real ( kind = 8 ) va
  real ( kind = 8 ) va0
  real ( kind = 8 ) vm
  real ( kind = 8 ) vt
  real ( kind = 8 ) x

  eps = 1.0D-15
  pi = 3.141592653589793D+00
  sq2 = sqrt ( 2.0D+00 )
  ep = exp ( -0.25D+00 * x * x )
  va0 = 0.5D+00 * ( 1.0D+00 - va )

  if ( va == 0.0D+00 ) then

     pd = ep

  else

     if ( x == 0.0D+00 ) then
        if ( va0 <= 0.0D+00 .and. va0 == int ( va0 ) ) then
           pd = 0.0D+00
        else
           call gammaf ( va0, ga0 )
           pd = sqrt ( pi ) / ( 2.0D+00 ** ( -0.5D+00 * va ) * ga0 )
        end if

     else

        call gammaf ( -va, g1 )
        a0 = 2.0D+00 ** ( -0.5D+00 * va - 1.0D+00 ) * ep / g1
        vt = -0.5D+00 * va
        call gammaf ( vt, g0 )
        pd = g0
        r = 1.0D+00
        do m = 1, 250
           vm = 0.5D+00 * ( m - va )
           call gammaf ( vm, gm )
           r = -r * sq2 * x / m
           r1 = gm * r
           pd = pd + r1
           if ( abs ( r1 ) < abs ( pd ) * eps ) then
              exit
           end if
        end do

        pd = a0 * pd

     end if

  end if

  return
end subroutine dvsa
subroutine e1xa ( x, e1 )

  !*****************************************************************************80
  !
  !! E1XA computes the exponential integral E1(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    06 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) E1, the function value.
  !
  implicit none

  real ( kind = 8 ) e1
  real ( kind = 8 ) es1
  real ( kind = 8 ) es2
  real ( kind = 8 ) x

  if ( x == 0.0D+00 ) then

     e1 = 1.0D+300

  else if ( x <= 1.0D+00 ) then

     e1 = - log ( x ) + (((( &
          1.07857D-03 * x &
          - 9.76004D-03 ) * x &
          + 5.519968D-02 ) * x &
          - 0.24991055D+00 ) * x &
          + 0.99999193D+00 ) * x &
          - 0.57721566D+00

  else

     es1 = ((( x &
          + 8.5733287401D+00 ) * x &
          +18.059016973D+00  ) * x &
          + 8.6347608925D+00 ) * x &
          + 0.2677737343D+00

     es2 = ((( x &
          +  9.5733223454D+00 ) * x &
          + 25.6329561486D+00 ) * x &
          + 21.0996530827D+00 ) * x &
          +  3.9584969228D+00

     e1 = exp ( - x ) / x * es1 / es2

  end if

  return
end subroutine e1xa
subroutine e1xb ( x, e1 )

  !*****************************************************************************80
  !
  !! E1XB computes the exponential integral E1(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    06 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) E1, the function value.
  !
  implicit none

  real ( kind = 8 ) e1
  real ( kind = 8 ) ga
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  real ( kind = 8 ) r
  real ( kind = 8 ) t
  real ( kind = 8 ) t0
  real ( kind = 8 ) x

  if ( x == 0.0D+00 ) then

     e1 = 1.0D+300

  else if ( x <= 1.0D+00 ) then

     e1 = 1.0D+00
     r = 1.0D+00

     do k = 1, 25
        r = -r * k * x / ( k + 1.0D+00 )**2
        e1 = e1 + r
        if ( abs ( r ) <= abs ( e1 ) * 1.0D-15 ) then
           exit
        end if
     end do

     ga = 0.5772156649015328D+00
     e1 = - ga - log ( x ) + x * e1

  else

     m = 20 + int ( 80.0D+00 / x )
     t0 = 0.0D+00
     do k = m, 1, -1
        t0 = k / ( 1.0D+00 + k / ( x + t0 ) )
     end do
     t = 1.0D+00 / ( x + t0 )
     e1 = exp ( -x ) * t

  end if

  return
end subroutine e1xb
subroutine e1z ( z, ce1 )

  !*****************************************************************************80
  !
  !! E1Z computes the complex exponential integral E1(z).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    16 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  ! 
  !  Parameters:
  !
  !    Input, complex ( kind = 8 ) Z, the argument.
  !
  !    Output, complex ( kind = 8 ) CE1, the function value.
  !
  implicit none

  real ( kind = 8 ) a0
  complex ( kind = 8 ) ce1
  complex ( kind = 8 ) cr
  complex ( kind = 8 ) ct
  complex ( kind = 8 ) ct0
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) x
  complex ( kind = 8 ) z

  pi = 3.141592653589793D+00
  el = 0.5772156649015328D+00
  x = real ( z, kind = 8 )
  a0 = abs ( z )

  if ( a0 == 0.0D+00 ) then
     ce1 = cmplx ( 1.0D+300, 0.0D+00, kind = 8 )
  else if ( a0 <= 10.0D+00 .or. &
       ( x < 0.0D+00 .and. a0 < 20.0D+00 ) ) then
     ce1 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     cr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     do k = 1, 150
        cr = - cr * k * z / ( k + 1.0D+00 )**2
        ce1 = ce1 + cr
        if ( abs ( cr ) <= abs ( ce1 ) * 1.0D-15 ) then
           exit
        end if
     end do

     ce1 = - el - log ( z ) + z * ce1

  else

     ct0 = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )
     do k = 120, 1, -1
        ct0 = k / ( 1.0D+00 + k / ( z + ct0 ) )
     end do
     ct = 1.0D+00 / ( z + ct0 )

     ce1 = exp ( - z ) * ct
     if ( x <= 0.0D+00 .and. imag ( z ) == 0.0D+00 ) then
        ce1 = ce1 - pi * cmplx ( 0.0D+00, 1.0D+00, kind = 8 )
     end if

  end if

  return
end subroutine e1z
subroutine eix ( x, ei )

  !*****************************************************************************80
  !
  !! EIX computes the exponential integral Ei(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    10 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) EI, the function value.
  !
  implicit none

  real ( kind = 8 ) ei
  real ( kind = 8 ) ga
  integer ( kind = 4 ) k
  real ( kind = 8 ) r
  real ( kind = 8 ) x

  if ( x == 0.0D+00 ) then

     ei = -1.0D+300

  else if ( x <= 40.0D+00 ) then

     ei = 1.0D+00
     r = 1.0D+00
     do k = 1, 100
        r = r * k * x / ( k + 1.0D+00 )**2
        ei = ei + r
        if ( abs ( r / ei ) <= 1.0D-15 ) then
           exit
        end if
     end do

     ga = 0.5772156649015328D+00
     ei = ga + log ( x ) + x * ei

  else

     ei = 1.0D+00
     r = 1.0D+00
     do k = 1, 20
        r = r * k / x
        ei = ei + r
     end do
     ei = exp ( x ) / x * ei

  end if

  return
end subroutine eix
subroutine elit ( hk, phi, fe, ee )

  !*****************************************************************************80
  !
  !! ELIT: complete and incomplete elliptic integrals F(k,phi) and E(k,phi).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    12 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) HK, the modulus, between 0 and 1.
  !
  !    Input, real ( kind = 8 ) PHI, the argument in degrees.
  !
  !    Output, real ( kind = 8 ) FE, EE, the values of F(k,phi) and E(k,phi).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) a0
  real ( kind = 8 ) b
  real ( kind = 8 ) b0
  real ( kind = 8 ) c
  real ( kind = 8 ) ce
  real ( kind = 8 ) ck
  real ( kind = 8 ) d
  real ( kind = 8 ) d0
  real ( kind = 8 ) ee
  real ( kind = 8 ) fac
  real ( kind = 8 ) fe
  real ( kind = 8 ) g
  real ( kind = 8 ) hk
  integer ( kind = 4 ) n
  real ( kind = 8 ) phi
  real ( kind = 8 ) pi
  real ( kind = 8 ) r

  g = 0.0D+00
  pi = 3.14159265358979D+00
  a0 = 1.0D+00
  b0 = sqrt ( 1.0D+00 - hk * hk )
  d0 = ( pi / 180.0D+00 ) * phi
  r = hk * hk

  if ( hk == 1.0D+00 .and. phi == 90.0D+00 ) then

     fe = 1.0D+300
     ee = 1.0D+00

  else if ( hk == 1.0D+00 ) then

     fe = log ( ( 1.0D+00 + sin ( d0 ) ) / cos ( d0 ) )
     ee = sin ( d0 )

  else

     fac = 1.0D+00
     do n = 1, 40
        a = ( a0 + b0 ) /2.0D+00
        b = sqrt ( a0 * b0 )
        c = ( a0 - b0 ) / 2.0D+00
        fac = 2.0D+00 * fac
        r = r + fac * c * c
        if ( phi /= 90.0D+00 ) then
           d = d0 + atan ( ( b0 / a0 ) * tan ( d0 ) )
           g = g + c * sin( d )
           d0 = d + pi * int ( d / pi + 0.5D+00 )
        end if
        a0 = a
        b0 = b
        if ( c < 1.0D-07 ) then
           exit
        end if
     end do

     ck = pi / ( 2.0D+00 * a )
     ce = pi * ( 2.0D+00 - r ) / ( 4.0D+00 * a )
     if ( phi == 90.0D+00 ) then
        fe = ck
        ee = ce
     else
        fe = d / ( fac * a )
        ee = fe * ce / ck + g
     end if

  end if

  return
end subroutine elit
subroutine elit3 ( phi, hk, c, el3 )

  !*****************************************************************************80
  !
  !! ELIT3 computes the elliptic integral of the third kind.
  !
  !  Discussion:
  !
  !    Gauss-Legendre quadrature is used.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    14 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) PHI, the argument in degrees.
  !
  !    Input, real ( kind = 8 ) HK, the modulus, between 0 and 1.
  !
  !    Input, real ( kind = 8 ) C, the parameter, between 0 and 1.
  !
  !    Output, real ( kind = 8 ) EL3, the value of the elliptic integral
  !    of the third kind.
  !
  implicit none

  real ( kind = 8 ) c
  real ( kind = 8 ) c0
  real ( kind = 8 ) c1
  real ( kind = 8 ) c2
  real ( kind = 8 ) el3
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  real ( kind = 8 ) hk
  integer ( kind = 4 ) i 
  logical lb1
  logical lb2
  real ( kind = 8 ) phi
  real ( kind = 8 ), dimension ( 10 ), save :: t = (/ &
       0.9931285991850949D+00, 0.9639719272779138D+00, &
       0.9122344282513259D+00, 0.8391169718222188D+00, &
       0.7463319064601508D+00, 0.6360536807265150D+00, &
       0.5108670019508271D+00, 0.3737060887154195D+00, &
       0.2277858511416451D+00, 0.7652652113349734D-01 /)
  real ( kind = 8 ) t1
  real ( kind = 8 ) t2
  real ( kind = 8 ), dimension ( 10 ), save :: w = (/ &
       0.1761400713915212D-01, 0.4060142980038694D-01, &
       0.6267204833410907D-01, 0.8327674157670475D-01, &
       0.1019301198172404D+00, 0.1181945319615184D+00, &
       0.1316886384491766D+00, 0.1420961093183820D+00, &
       0.1491729864726037D+00, 0.1527533871307258D+00 /)

  lb1 = ( hk == 1.0D+00 ) .and. ( abs ( phi - 90.0D+00 ) <= 1.0D-08 )

  lb2 = c == 1.0D+00 .and. abs ( phi - 90.0D+00 ) <= 1.0D-08

  if ( lb1 .or. lb2 ) then
     el3 = 1.0D+300
     return
  end if

  c1 = 0.87266462599716D-02 * phi
  c2 = c1

  el3 = 0.0D+00
  do i = 1, 10
     c0 = c2 * t(i)
     t1 = c1 + c0
     t2 = c1 - c0
     f1 = 1.0D+00 / ( ( 1.0D+00 - c * sin(t1) * sin(t1) ) &
          * sqrt ( 1.0D+00 - hk * hk * sin ( t1 ) * sin ( t1 ) ) )
     f2 = 1.0D+00 / ( ( 1.0D+00 - c * sin ( t2 ) * sin ( t2 ) ) &
          * sqrt( 1.0D+00 - hk * hk * sin ( t2 ) * sin ( t2 ) ) )
     el3 = el3 + w(i) * ( f1 + f2 )
  end do

  el3 = c1 * el3

  return
end subroutine elit3

function envj ( n, x )

  !*****************************************************************************80
  !
  !! ENVJ is a utility function used by MSTA1 and MSTA2.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    14 March 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, ?
  !
  !    Input, real ( kind = 8 ) X, ?
  !
  !    Output, real ( kind = 8 ) ENVJ, ?
  !
  implicit none

  real ( kind = 8 ) envj
  integer ( kind = 4 ) n
  real ( kind = 8 ) x

  envj = 0.5D+00 * log10 ( 6.28D+00 * n ) - n * log10 ( 1.36D+00 * x / n )

  return
end function envj

subroutine enxa ( n, x, en )

  !*****************************************************************************80
  !
  !! ENXA computes the exponential integral En(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    07 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) EN(0:N), the function values.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) e1
  real ( kind = 8 ) ek
  real ( kind = 8 ) en(0:n)
  integer ( kind = 4 ) k
  real ( kind = 8 ) x

  en(0) = exp ( - x ) / x 
  call e1xb ( x, e1 )

  en(1) = e1
  do k = 2, n
     ek = ( exp ( - x ) - x * e1 ) / ( k - 1.0D+00 )
     en(k) = ek
     e1 = ek
  end do

  return
end subroutine enxa
subroutine enxb ( n, x, en )

  !*****************************************************************************80
  !
  !! ENXB computes the exponential integral En(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    10 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) EN(0:N), the function values.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) en(0:n)
  real ( kind = 8 ) ens
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
  real ( kind = 8 ) ps
  real ( kind = 8 ) r
  real ( kind = 8 ) rp
  real ( kind = 8 ) s
  real ( kind = 8 ) s0
  real ( kind = 8 ) t
  real ( kind = 8 ) t0
  real ( kind = 8 ) x

  if ( x == 0.0D+00 ) then

     en(0) = 1.0D+300
     en(1) = 1.0D+300
     do k = 2, n
        en(k) = 1.0D+00 / ( k - 1.0D+00 )
     end do
     return

  else if ( x <= 1.0D+00 ) then

     en(0) = exp ( - x ) / x
     do l = 1, n
        rp = 1.0D+00
        do j = 1, l - 1
           rp = - rp * x / j
        end do
        ps = -0.5772156649015328D+00
        do m = 1, l - 1
           ps = ps + 1.0D+00 / m
        end do
        ens = rp * ( - log ( x ) + ps )
        s = 0.0D+00
        do m = 0, 20
           if ( m /= l - 1 ) then
              r = 1.0D+00
              do j = 1, m
                 r = - r * x / j
              end do
              s = s + r / ( m - l + 1.0D+00 )
              if ( abs ( s - s0 ) < abs ( s ) * 1.0D-15 ) then
                 exit
              end if
              s0 = s
           end if
        end do

        en(l) = ens - s

     end do

  else

     en(0) = exp ( - x ) / x
     m = 15 + int ( 100.0D+00 / x )
     do l = 1, n
        t0 = 0.0D+00
        do k = m, 1, -1
           t0 = ( l + k - 1.0D+00 ) / ( 1.0D+00 + k / ( x + t0 ) )
        end do
        t = 1.0D+00 / ( x + t0 )
        en(l) = exp ( - x ) * t
     end do

  end if

  return
end subroutine enxb

subroutine werror ( x, err )

  !*****************************************************************************80
  !
  !! WERROR evaluates the error function.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    07 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) ERR, the function value.
  !
  implicit none

  real ( kind = 8 ) c0
  real ( kind = 8 ) eps
  real ( kind = 8 ) er
  real ( kind = 8 ) err
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) x
  real ( kind = 8 ) x2

  eps = 1.0D-15
  pi = 3.141592653589793D+00
  x2 = x * x

  if ( abs ( x ) < 3.5D+00 ) then

     er = 1.0D+00
     r = 1.0D+00

     do k = 1, 50
        r = r * x2 / ( k + 0.5D+00 )
        er = er + r
        if ( abs ( r ) <= abs ( er ) * eps ) then
           exit
        end if
     end do

     c0 = 2.0D+00 / sqrt ( pi ) * x * exp ( - x2 )
     err = c0 * er

  else

     er = 1.0D+00
     r = 1.0D+00
     do k = 1, 12
        r = - r * ( k - 0.5D+00 ) / x2
        er = er + r
     end do

     c0 = exp ( - x2 ) / ( abs ( x ) * sqrt ( pi ) )

     err = 1.0D+00 - c0 * er
     if ( x < 0.0D+00 ) then
        err = -err
     end if

  end if

  return
end subroutine werror

subroutine eulera ( n, en )

  !*****************************************************************************80
  !
  !! EULERA computes the Euler number En.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    10 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the index of the highest value to compute.
  !
  !    Output, real ( kind = 8 ) EN(0:N), the Euler numbers up to the N-th value.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) en(0:n)
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  real ( kind = 8 ) r
  real ( kind = 8 ) s

  en(0) = 1.0D+00

  do m = 1, n / 2
     s = 1.0D+00
     do k = 1, m - 1
        r = 1.0D+00
        do j = 1, 2 * k
           r = r * ( 2.0D+00 * m - 2.0D+00 * k + j ) / j
        end do
        s = s + r * en(2*k)
     end do
     en(2*m) = -s
  end do

  return
end subroutine eulera
subroutine eulerb ( n, en )

  !*****************************************************************************80
  !
  !! EULERB computes the Euler number En.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    09 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the index of the highest value to compute.
  !
  !    Output, real ( kind = 8 ) EN(0:N), the Euler numbers up to the N-th value.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) en(0:n)
  real ( kind = 8 ) hpi
  real ( kind = 8 ) isgn
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  real ( kind = 8 ) r1
  real ( kind = 8 ) r2
  real ( kind = 8 ) s

  hpi = 2.0D+00 / 3.141592653589793D+00
  en(0) = 1.0D+00
  en(2) = -1.0D+00
  r1 = -4.0D+00 * hpi ** 3

  do m = 4, n, 2
     r1 = - r1 * ( m - 1 ) * m * hpi * hpi
     r2 = 1.0D+00
     isgn = 1.0D+00
     do k = 3, 1000, 2
        isgn = - isgn
        s = ( 1.0D+00 / k ) ** ( m + 1 )
        r2 = r2 + isgn * s
        if ( s < 1.0D-15 ) then
           exit
        end if
     end do

     en(m) = r1 * r2

  end do

  return
end subroutine eulerb
subroutine fcoef ( kd, m, q, a, fc )

  !*****************************************************************************80
  !
  !! FCOEF: expansion coefficients for Mathieu and modified Mathieu functions.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    01 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KD, the case code.
  !    1, for cem(x,q)  ( m = 0,2,4,...)
  !    2, for cem(x,q)  ( m = 1,3,5,...)
  !    3, for sem(x,q)  ( m = 1,3,5,...)
  !    4, for sem(x,q)  ( m = 2,4,6,...)
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu function.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) A, the characteristic value of the Mathieu
  !    functions for given m and q.
  !
  !    Output, real ( kind = 8 ) FC(*), the expansion coefficients of Mathieu
  !    functions ( k =  1,2,...,KM ).  FC(1),FC(2),FC(3),... correspond to
  !    A0,A2,A4,... for KD = 1 case, 
  !    A1,A3,A5,... for KD = 2 case,
  !    B1,B3,B5,... for KD = 3 case,
  !    B2,B4,B6,... for KD = 4 case.
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) f
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  real ( kind = 8 ) f3
  real ( kind = 8 ) fc(251)
  integer ( kind = 4 ) i
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kb
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) km
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
  real ( kind = 8 ) q
  real ( kind = 8 ) qm
  real ( kind = 8 ) s
  real ( kind = 8 ) s0
  real ( kind = 8 ) sp
  real ( kind = 8 ) ss
  real ( kind = 8 ) u
  real ( kind = 8 ) v

  if ( q <= 1.0D+00 ) then
     qm = 7.5D+00 + 56.1D+00 * sqrt ( q ) - 134.7D+00 * q &
          + 90.7D+00 * sqrt ( q ) * q
  else
     qm = 17.0D+00 + 3.1D+00 * sqrt ( q ) - 0.126D+00 * q &
          + 0.0037D+00 * sqrt ( q ) * q
  end if

  km = int ( qm + 0.5D+00 * m )

  if ( q == 0.0D+00 ) then

     do k = 1, km
        fc(k) = 0.0D+00
     end do

     if ( kd == 1 ) then
        fc((m+2)/2) = 1.0D+00
        if (m == 0 ) then
           fc(1) = 1.0D+00 / sqrt ( 2.0D+00 )
        end if
     else if ( kd == 4 ) then
        fc(m/2) = 1.0D+00
     else
        fc((m+1)/2) = 1.0D+00
     end if

     return

  end if

  kb = 0
  s = 0.0D+00
  f = 1.0D-100
  u = 0.0D+00
  fc(km) = 0.0D+00

  if ( kd == 1 ) then

     l = 0

     do k = km, 3, -1

        v = u
        u = f
        f = ( a - 4.0D+00 * k * k ) * u / q - v

        if ( abs ( f ) < abs ( fc(k+1) ) ) then

           kb = k
           fc(1) = 1.0D-100
           sp = 0.0D+00
           f3 = fc(k+1)
           fc(2) = a / q * fc(1)
           fc(3) = ( a - 4.0D+00 ) * fc(2) / q - 2.0D+00 * fc(1)
           u = fc(2)
           f1 = fc(3)

           do i = 3, kb
              v = u
              u = f1
              f1 = ( a - 4.0D+00 * ( i - 1.0D+00 ) ** 2 ) * u / q - v
              fc(i+1) = f1
              if ( i == kb ) then
                 f2 = f1
              else
                 sp = sp + f1 * f1
              end if
           end do

           sp = sp + 2.0D+00 * fc(1) ** 2 + fc(2) ** 2 + fc(3) ** 2
           ss = s + sp * ( f3 / f2 ) ** 2
           s0 = sqrt ( 1.0D+00 / ss )
           do j = 1, km
              if ( j <= kb + 1 ) then
                 fc(j) = s0 * fc(j) * f3 / f2
              else
                 fc(j) = s0 * fc(j)
              end if
           end do
           l = 1
           exit
        else
           fc(k) = f
           s = s + f * f
        end if

     end do

     if ( l == 0 ) then
        fc(2) = q * fc(3) / ( a - 4.0D+00 - 2.0D+00 * q * q / a )
        fc(1) = q / a * fc(2)
        s = s + 2.0D+00 * fc(1) ** 2 + fc(2) ** 2
        s0 = sqrt ( 1.0D+00 / s )
        do k = 1, km
           fc(k) = s0 * fc(k)
        end do
     end if

  else if ( kd == 2 .or. kd == 3 ) then

     l = 0

     do k = km, 3, -1

        v = u
        u = f
        f = ( a - ( 2.0D+00 * k - 1 ) ** 2 ) * u / q - v

        if ( abs ( fc(k) ) <= abs ( f ) ) then
           fc(k-1) = f
           s = s + f * f
        else
           kb = k
           f3 = fc(k)
           l = 1
           exit
        end if

     end do

     if ( l == 0 ) then

        fc(1) = q / ( a - 1.0D+00 - ( - 1 ) ** kd * q ) * fc(2)
        s = s + fc(1) * fc(1)
        s0 = sqrt ( 1.0D+00 / s )
        do k = 1, km
           fc(k) = s0 * fc(k)
        end do

     else

        fc(1) = 1.0D-100
        fc(2) = ( a - 1.0D+00 - ( - 1 ) ** kd * q ) / q * fc(1)
        sp = 0.0D+00
        u = fc(1)
        f1 = fc(2)
        do i = 2, kb - 1
           v = u
           u = f1
           f1 = ( a - ( 2.0D+00 * i - 1.0D+00 ) ** 2 ) * u / q - v
           if ( i /= kb - 1 ) then
              fc(i+1) = f1
              sp = sp + f1 * f1
           else
              f2 = f1
           end if
        end do

        sp = sp + fc(1) ** 2 + fc(2) ** 2
        ss = s + sp * ( f3 / f2 ) ** 2
        s0 = 1.0D+00 / sqrt ( ss )
        do j = 1, km
           if ( j < kb ) then
              fc(j) = s0 * fc(j) * f3 / f2
           else
              fc(j) = s0 * fc(j)
           end if
        end do

     end if

  else if ( kd == 4 ) then

     l = 0

     do k = km, 3, -1
        v = u
        u = f
        f = ( a - 4.0D+00 * k * k ) * u / q - v
        if ( abs ( fc(k) ) <= abs ( f ) ) then
           fc(k-1) = f
           s = s + f * f
        else
           kb = k
           f3 = fc(k)
           l = 1
           exit
        end if
     end do

     if ( l == 0 ) then

        fc(1) = q / ( a - 4.0D+00 ) * fc(2)
        s = s + fc(1) * fc(1)
        s0 = sqrt ( 1.0D+00 / s )
        do k = 1, km
           fc(k) = s0 * fc(k)
        end do

     else

        fc(1) = 1.0D-100
        fc(2) = ( a - 4.0D+00 ) / q * fc(1)
        sp = 0.0D+00
        u = fc(1)
        f1 = fc(2)

        do i = 2, kb - 1
           v = u
           u = f1
           f1 = ( a - 4.0D+00 * i * i ) * u / q - v
           if ( i /= kb - 1 ) then
              fc(i+1) = f1
              sp = sp + f1 * f1
           else
              f2 = f1
           end if
        end do

        sp = sp + fc(1) ** 2 + fc(2) ** 2
        ss = s + sp * ( f3 / f2 ) ** 2
        s0 = 1.0D+00 / sqrt ( ss )

        do j = 1, km
           if ( j < kb ) then
              fc(j) = s0 * fc(j) * f3 / f2
           else
              fc(j) = s0 * fc(j)
           end if
        end do

     end if

  end if

  if ( fc(1) < 0.0D+00 ) then
     do j = 1, km
        fc(j) = -fc(j)
     end do
  end if

  return
end subroutine fcoef
subroutine fcs ( x, c, s )

  !*****************************************************************************80
  !
  !! FCS computes Fresnel integrals C(x) and S(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    17 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  ! 
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) C, S, the function values.
  !
  implicit none

  real ( kind = 8 ) c
  real ( kind = 8 ) eps
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) g
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  real ( kind = 8 ) pi
  real ( kind = 8 ) px
  real ( kind = 8 ) q
  real ( kind = 8 ) r
  real ( kind = 8 ) s
  real ( kind = 8 ) su
  real ( kind = 8 ) t
  real ( kind = 8 ) t0
  real ( kind = 8 ) t2
  real ( kind = 8 ) x
  real ( kind = 8 ) xa

  eps = 1.0D-15
  pi = 3.141592653589793D+00
  xa = abs ( x )
  px = pi * xa
  t = 0.5D+00 * px * xa
  t2 = t * t

  if ( xa == 0.0D+00 ) then

     c = 0.0D+00
     s = 0.0D+00

  else if ( xa < 2.5D+00 ) then

     r = xa
     c = r
     do k = 1, 50
        r = -0.5D+00 * r * ( 4.0D+00 * k - 3.0D+00 ) / k &
             / ( 2.0D+00 * k - 1.0D+00 ) / ( 4.0D+00 * k + 1.0D+00 ) * t2
        c = c + r
        if ( abs ( r ) < abs ( c ) * eps ) then
           exit
        end if
     end do

     s = xa * t / 3.0D+00
     r = s
     do k = 1, 50
        r = - 0.5D+00 * r * ( 4.0D+00 * k - 1.0D+00 ) / k &
             / ( 2.0D+00 * k + 1.0D+00 ) / ( 4.0D+00 * k + 3.0D+00 ) * t2
        s = s + r
        if ( abs ( r ) < abs ( s ) * eps ) then
           if ( x < 0.0D+00 ) then
              c = -c
              s = -s
           end if
           return
        end if
     end do

  else if ( xa < 4.5D+00 ) then

     m = int ( 42.0D+00 + 1.75D+00 * t )
     su = 0.0D+00
     c = 0.0D+00
     s = 0.0D+00
     f1 = 0.0D+00
     f0 = 1.0D-100

     do k = m, 0, -1
        f = ( 2.0D+00 * k + 3.0D+00 ) * f0 / t - f1
        if ( k == int ( k / 2 ) * 2 ) then
           c = c + f
        else
           s = s + f
        end if
        su = su + ( 2.0D+00 * k + 1.0D+00 ) * f * f
        f1 = f0
        f0 = f
     end do

     q = sqrt ( su )
     c = c * xa / q
     s = s * xa / q

  else

     r = 1.0D+00
     f = 1.0D+00
     do k = 1, 20
        r = -0.25D+00 * r * ( 4.0D+00 * k - 1.0D+00 ) &
             * ( 4.0D+00 * k - 3.0D+00 ) / t2
        f = f + r
     end do
     r = 1.0D+00 / ( px * xa )
     g = r
     do k = 1, 12
        r = -0.25D+00 * r * ( 4.0D+00 * k + 1.0D+00 ) &
             * ( 4.0D+00 * k - 1.0D+00 ) / t2
        g = g + r
     end do

     t0 = t - int ( t / ( 2.0D+00 * pi ) ) * 2.0D+00 * pi
     c = 0.5D+00 + ( f * sin ( t0 ) - g * cos ( t0 ) ) / px
     s = 0.5D+00 - ( f * cos ( t0 ) + g * sin ( t0 ) ) / px

  end if

  if ( x < 0.0D+00 ) then
     c = -c
     s = -s
  end if

  return
end subroutine fcs
subroutine fcszo ( kf, nt, zo )

  !*****************************************************************************80
  !
  !! FCSZO computes complex zeros of Fresnel integrals C(x) or S(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    17 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KF, the function code.
  !    1 for C(z);
  !    2 for S(z)
  !
  !    Input, integer ( kind = 4 ) NT, the total number of zeros desired.
  !
  !    Output, complex ( kind = 8 ) Z0(NT), the zeros.
  !
  implicit none

  integer ( kind = 4 ) nt

  integer ( kind = 4 ) i
  integer ( kind = 4 ) it
  integer ( kind = 4 ) j
  integer ( kind = 4 ) kf
  integer ( kind = 4 ) nr
  real ( kind = 8 ) pi
  real ( kind = 8 ) psq
  real ( kind = 8 ) px
  real ( kind = 8 ) py
  real ( kind = 8 ) w
  real ( kind = 8 ) w0
  complex ( kind = 8 ) z
  complex ( kind = 8 ) zd
  complex ( kind = 8 ) zf
  complex ( kind = 8 ) zfd
  complex ( kind = 8 ) zgd
  complex ( kind = 8 ) zo(nt)
  complex ( kind = 8 ) zp
  complex ( kind = 8 ) zq
  complex ( kind = 8 ) zw

  pi = 3.141592653589793D+00

  do nr = 1, nt

     if ( kf == 1 ) then
        psq = sqrt ( 4.0D+00 * nr - 1.0D+00 )
     else
        psq = 2.0D+00 * sqrt ( real ( nr, kind = 8 ) )
     end if

     px = psq - log ( pi * psq ) / ( pi * pi * psq ** 3.0D+00 )
     py = log ( pi * psq ) / ( pi * psq )
     z = cmplx ( px, py )

     if ( kf == 2 ) then
        if ( nr == 2 ) then
           z = cmplx ( 2.8334D+00, 0.2443D+00 )
        else if ( nr == 3 ) then
           z = cmplx ( 3.4674D+00, 0.2185D+00 )
        else if ( nr == 4 ) then
           z = cmplx ( 4.0025D+00, 0.2008D+00 )
        end if
     end if

     it = 0

     do

        it = it + 1

        if ( kf == 1 ) then
           call cfc ( z, zf, zd )
        else
           call cfs ( z, zf, zd )
        end if

        zp = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do i = 1, nr - 1
           zp = zp * ( z - zo(i) )
        end do
        zfd = zf / zp
        zq = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )

        do i = 1, nr - 1
           zw = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
           do j = 1, nr - 1
              if ( j /= i ) then
                 zw = zw * ( z - zo(j) )
              end if
           end do
           zq = zq + zw
        end do

        zgd = ( zd - zq * zfd ) / zp
        z = z - zfd / zgd
        w0 = w
        w = cdabs ( z )

        if ( abs ( ( w - w0 ) / w ) <= 1.0D-12 ) then
           exit
        end if

        if ( 50 < it ) then
           exit
        end if

     end do

     zo(nr) = z

  end do

  return
end subroutine fcszo
subroutine ffk ( ks, x, fr, fi, fm, fa, gr, gi, gm, ga )

  !*****************************************************************************80
  !
  !! FFK computes modified Fresnel integrals F+/-(x) and K+/-(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    23 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KS, the sign code.
  !    0, to calculate F+(x) and K+(x);
  !    1, to calculate F_(x) and K_(x).
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) FR, FI, FM, FA, the values of
  !    Re[F+/-(x)], Im[F+/-(x)], |F+/-(x)|, Arg[F+/-(x)]  (Degs.).
  !
  !    Output, real ( kind = 8 ) GR, GI, GM, GA, the values of
  !    Re[K+/-(x)], Im[K+/-(x)], |K+/-(x)|, Arg[K+/-(x)]  (Degs.).
  !       
  implicit none

  real ( kind = 8 ) c1
  real ( kind = 8 ) cs
  real ( kind = 8 ) eps
  real ( kind = 8 ) fa
  real ( kind = 8 ) fi
  real ( kind = 8 ) fi0
  real ( kind = 8 ) fm
  real ( kind = 8 ) fr
  real ( kind = 8 ) ga
  real ( kind = 8 ) gi
  real ( kind = 8 ) gm
  real ( kind = 8 ) gr
  integer ( kind = 4 ) k
  integer ( kind = 4 ) ks
  integer ( kind = 4 ) m
  real ( kind = 8 ) p2p
  real ( kind = 8 ) pi
  real ( kind = 8 ) pp2
  real ( kind = 8 ) s1
  real ( kind = 8 ) srd
  real ( kind = 8 ) ss
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) x4
  real ( kind = 8 ) xa
  real ( kind = 8 ) xc
  real ( kind = 8 ) xf
  real ( kind = 8 ) xf0
  real ( kind = 8 ) xf1
  real ( kind = 8 ) xg
  real ( kind = 8 ) xp
  real ( kind = 8 ) xq
  real ( kind = 8 ) xq2
  real ( kind = 8 ) xr
  real ( kind = 8 ) xs
  real ( kind = 8 ) xsu
  real ( kind = 8 ) xw

  srd = 57.29577951308233D+00
  eps = 1.0D-15
  pi = 3.141592653589793D+00
  pp2 = 1.2533141373155D+00
  p2p = 0.7978845608028654D+00
  xa = abs ( x )
  x2 = x * x
  x4 = x2 * x2

  if ( x == 0.0D+00 ) then

     fr = 0.5D+00 * sqrt ( 0.5D+00 * pi )
     fi = ( -1.0D+00 ) ** ks * fr
     fm = sqrt ( 0.25D+00 * pi )
     fa = ( -1.0D+00 ) ** ks * 45.0D+00
     gr = 0.5D+00
     gi = 0.0D+00
     gm = 0.5D+00
     ga = 0.0D+00

  else

     if ( xa <= 2.5D+00 ) then

        xr = p2p * xa
        c1 = xr
        do k = 1, 50
           xr = -0.5D+00 * xr * ( 4.0D+00 * k - 3.0D+00 ) / k &
                / ( 2.0D+00 * k - 1.0D+00 ) &
                / ( 4.0D+00 * k + 1.0D+00 ) * x4
           c1 = c1 + xr
           if ( abs ( xr / c1 ) < eps ) then
              exit
           end if
        end do

        s1 = p2p * xa * xa * xa / 3.0D+00
        xr = s1
        do k = 1, 50
           xr = -0.5D+00 * xr * ( 4.0D+00 * k - 1.0D+00 ) &
                / k / ( 2.0D+00 * k + 1.0D+00 ) &
                / ( 4.0D+00 * k + 3.0D+00 ) * x4
           s1 = s1 + xr
           if ( abs ( xr / s1 ) < eps ) then
              exit
           end if
        end do

     else if ( xa < 5.5D+00 ) then

        m = int ( 42.0D+00 + 1.75D+00 * x2 )
        xsu = 0.0D+00
        xc = 0.0D+00
        xs = 0.0D+00
        xf1 = 0.0D+00
        xf0 = 1.0D-100
        do k = m, 0, -1
           xf = ( 2.0D+00 * k + 3.0D+00 ) * xf0 / x2 - xf1
           if ( k == 2 * int ( k / 2 ) )  then
              xc = xc + xf
           else
              xs = xs + xf
           end if
           xsu = xsu + ( 2.0D+00 * k + 1.0D+00 ) * xf * xf
           xf1 = xf0
           xf0 = xf
        end do
        xq = sqrt ( xsu )
        xw = p2p * xa / xq
        c1 = xc * xw
        s1 = xs * xw

     else

        xr = 1.0D+00
        xf = 1.0D+00
        do k = 1, 12
           xr = -0.25D+00 * xr * ( 4.0D+00 * k - 1.0D+00 ) &
                * ( 4.0D+00 * k - 3.0D+00 ) / x4
           xf = xf + xr
        end do
        xr = 1.0D+00 / ( 2.0D+00 * xa * xa )
        xg = xr
        do k = 1, 12
           xr = -0.25D+00 * xr * ( 4.0D+00 * k + 1.0D+00 ) &
                * ( 4.0D+00 * k - 1.0D+00 ) / x4
           xg = xg + xr
        end do
        c1 = 0.5D+00 + ( xf * sin ( x2 ) - xg * cos ( x2 ) ) &
             / sqrt ( 2.0D+00 * pi ) / xa
        s1 = 0.5D+00 - ( xf * cos ( x2 ) + xg * sin ( x2 ) ) &
             / sqrt ( 2.0D+00 * pi ) / xa

     end if

     fr = pp2 * ( 0.5D+00 - c1 )
     fi0 = pp2 * ( 0.5D+00 - s1 )
     fi = ( -1.0D+00 ) ** ks * fi0
     fm = sqrt ( fr * fr + fi * fi )

     if ( 0.0D+00 <= fr ) then
        fa = srd * atan ( fi / fr )
     else if ( 0.0D+00 < fi ) then
        fa = srd * ( atan ( fi / fr ) + pi )
     else if ( fi < 0.0D+00 ) then
        fa = srd * ( atan ( fi / fr ) - pi )
     end if

     xp = x * x + pi / 4.0D+00
     cs = cos ( xp )
     ss = sin ( xp )
     xq2 = 1.0D+00 / sqrt ( pi )
     gr = xq2 * ( fr * cs + fi0 * ss )
     gi = ( -1.0D+00 ) ** ks * xq2 * ( fi0 * cs - fr * ss )
     gm = sqrt ( gr * gr + gi * gi )

     if ( 0.0D+00 <= gr ) then
        ga = srd * atan ( gi / gr )
     else if ( 0.0D+00 < gi ) then
        ga = srd * ( atan ( gi / gr ) + pi )
     else if ( gi < 0.0D+00 ) then
        ga = srd * ( atan ( gi / gr ) - pi )
     end if

     if ( x < 0.0D+00 ) then
        fr = pp2 - fr
        fi = ( -1.0D+00 ) ** ks * pp2 - fi
        fm = sqrt ( fr * fr + fi * fi )
        fa = srd * atan ( fi / fr )
        gr = cos ( x * x ) - gr
        gi = - ( -1.0D+00 ) ** ks * sin ( x * x ) - gi
        gm = sqrt ( gr * gr + gi * gi )
        ga = srd * atan ( gi / gr )
     end if

  end if

  return
end subroutine ffk
subroutine gaih ( x, ga )

  !*****************************************************************************80
  !
  !! GAIH computes the GammaH function.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    09 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) GA, the function value.
  !
  implicit none

  real ( kind = 8 ) ga
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  integer ( kind = 4 ) m1
  real ( kind = 8 ) pi
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00

  if ( x == int ( x ) .and. 0.0 < x ) then
     ga = 1.0D+00
     m1 = int ( x - 1.0D+00 )
     do k = 2, m1
        ga = ga * k
     end do
  else if ( x + 0.5D+00 == int ( x + 0.5D+00) .and. 0.0D+00 < x ) then
     m = int ( x )
     ga = sqrt ( pi )
     do k = 1, m
        ga = 0.5D+00 * ga * ( 2.0D+00 * k - 1.0D+00 )
     end do
  end if

  return
end subroutine gaih
subroutine gam0 ( x, ga )

  !*****************************************************************************80
  !
  !! GAM0 computes the Gamma function for the LAMV function.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    09 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) GA, the function value.
  !   
  implicit none

  real ( kind = 8 ), dimension ( 25 ) :: g = (/ &
       1.0D+00, &
       0.5772156649015329D+00, &
       -0.6558780715202538D+00, &
       -0.420026350340952D-01, &
       0.1665386113822915D+00, &
       -0.421977345555443D-01, &
       -0.96219715278770D-02, &
       0.72189432466630D-02, &
       -0.11651675918591D-02, &
       -0.2152416741149D-03, &
       0.1280502823882D-03, &
       -0.201348547807D-04, &
       -0.12504934821D-05, &
       0.11330272320D-05, &
       -0.2056338417D-06, &
       0.61160950D-08, &
       0.50020075D-08, &
       -0.11812746D-08, &
       0.1043427D-09, &
       0.77823D-11, &
       -0.36968D-11, &
       0.51D-12, &
       -0.206D-13, &
       -0.54D-14, &
       0.14D-14 /)
  real ( kind = 8 ) ga
  real ( kind = 8 ) gr
  integer ( kind = 4 ) k
  real ( kind = 8 ) x

  gr = g(25)
  do k = 24, 1, -1
     gr = gr * x + g(k)
  end do

  ga = 1.0D+00 / ( gr * x )

  return
end subroutine gam0

subroutine gammaf ( x, ga )

  !*****************************************************************************80
  !
  !! GAMMA evaluates the Gamma function.
  !
  !  Licensing:
  !
  !    The original FORTRAN77 version of this routine is copyrighted by 
  !    Shanjie Zhang and Jianming Jin.  However, they give permission to 
  !    incorporate this routine into a user program that the copyright 
  !    is acknowledged.
  !
  !  Modified:
  !
  !    08 September 2007
  !
  !  Author:
  !
  !    Original FORTRAN77 version by Shanjie Zhang, Jianming Jin.
  !    FORTRAN90 version by John Burkardt.
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !    X must not be 0, or any negative integer.
  !
  !    Output, real ( kind = 8 ) GA, the value of the Gamma function.
  !
  implicit none

  real ( kind = 8 ), dimension ( 26 ) :: g = (/ &
       1.0D+00, &
       0.5772156649015329D+00, &
       -0.6558780715202538D+00, &
       -0.420026350340952D-01, &
       0.1665386113822915D+00, &
       -0.421977345555443D-01, &
       -0.96219715278770D-02, &
       0.72189432466630D-02, &
       -0.11651675918591D-02, &
       -0.2152416741149D-03, &
       0.1280502823882D-03, & 
       -0.201348547807D-04, &
       -0.12504934821D-05, &
       0.11330272320D-05, &
       -0.2056338417D-06, & 
       0.61160950D-08, &
       0.50020075D-08, &
       -0.11812746D-08, &
       0.1043427D-09, & 
       0.77823D-11, &
       -0.36968D-11, &
       0.51D-12, &
       -0.206D-13, &
       -0.54D-14, &
       0.14D-14, &
       0.1D-15 /)
  real ( kind = 8 ) ga
  real ( kind = 8 ) gr
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  integer ( kind = 4 ) m1
  real ( kind = 8 ), parameter :: pi = 3.141592653589793D+00
  real ( kind = 8 ) r
  real ( kind = 8 ) x
  real ( kind = 8 ) z

  if ( x == aint ( x ) ) then

     if ( 0.0D+00 < x ) then
        ga = 1.0D+00
        m1 = int ( x ) - 1
        do k = 2, m1
           ga = ga * k
        end do
     else
        ga = 1.0D+300
     end if

  else

     if ( 1.0D+00 < abs ( x ) ) then
        z = abs ( x )
        m = int ( z )
        r = 1.0D+00
        do k = 1, m
           r = r * ( z - real ( k, kind = 8 ) )
        end do
        z = z - real ( m, kind = 8 )
     else
        z = x
     end if

     gr = g(26)
     do k = 25, 1, -1
        gr = gr * z + g(k)
     end do

     ga = 1.0D+00 / ( gr * z )

     if ( 1.0D+00 < abs ( x ) ) then
        ga = ga * r
        if ( x < 0.0D+00 ) then
           ga = - pi / ( x* ga * sin ( pi * x ) )
        end if
     end if

  end if

  return
end subroutine gammaf
subroutine gmn ( m, n, c, x, bk, gf, gd )

  !*****************************************************************************80
  !
  !! GMN computes quantities for oblate radial functions with small argument.
  !
  !  Discussion:
  !
  !    This procedure computes Gmn(-ic,ix) and its derivative for oblate
  !    radial functions with a small argument.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    15 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) M, the mode parameter;  M = 0, 1, 2, ...
  !
  !    Input, integer ( kind = 4 ) N, mode parameter, N = M, M + 1, M + 2, ...
  !
  !    Input, real ( kind = 8 ) C, spheroidal parameter.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Input, real ( kind = 8 ) BK(*), coefficients.
  !
  !    Output, real ( kind = 8 ) GF, GD, the value of Gmn(-C,X) and Gmn'(-C,X).
  !
  implicit none

  real ( kind = 8 ) bk(200)
  real ( kind = 8 ) c
  real ( kind = 8 ) eps
  real ( kind = 8 ) gd
  real ( kind = 8 ) gd0
  real ( kind = 8 ) gd1
  real ( kind = 8 ) gf
  real ( kind = 8 ) gf0
  real ( kind = 8 ) gw
  integer ( kind = 4 ) ip
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  integer ( kind = 4 ) n
  integer ( kind = 4 ) nm
  real ( kind = 8 ) x
  real ( kind = 8 ) xm

  eps = 1.0D-14

  if ( n - m == 2 * int ( ( n - m ) / 2 ) ) then
     ip = 0
  else
     ip = 1
  end if

  nm = 25 + int ( 0.5D+00 * ( n - m ) + c )
  xm = ( 1.0D+00 + x * x ) ** ( -0.5D+00 * m )
  gf0 = 0.0D+00
  do k = 1, nm
     gf0 = gf0 + bk(k) * x ** ( 2.0D+00 * k - 2.0D+00 )
     if ( abs ( ( gf0 - gw ) / gf0 ) < eps .and. 10 <= k ) then
        exit
     end if
     gw = gf0
  end do

  gf = xm * gf0 * x ** ( 1 - ip )

  gd1 = - m * x / ( 1.0D+00 + x * x ) * gf
  gd0 = 0.0D+00

  do k = 1, nm

     if ( ip == 0 ) then
        gd0 = gd0 + ( 2.0D+00 * k - 1.0D+00 ) * bk(k) &
             * x ** ( 2.0D+00 * k - 2.0D+00 )
     else
        gd0 = gd0 + 2.0D+00 * k * bk(k+1) * x ** ( 2.0D+00 * k - 1.0D+00 )
     end if

     if ( abs ( ( gd0 - gw ) / gd0 ) < eps .and. 10 <= k ) then
        exit
     end if

     gw = gd0

  end do

  gd = gd1 + xm * gd0

  return
end subroutine gmn
subroutine herzo ( n, x, w )

  !*****************************************************************************80
  !
  !! HERZO computes the zeros the Hermite polynomial Hn(x).
  !
  !  Discussion:
  !
  !    This procedure computes the zeros of Hermite polynomial Ln(x)
  !    in the interval [-1,+1], and the corresponding
  !    weighting coefficients for Gauss-Hermite integration.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    15 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of the polynomial.
  !
  !    Output, real ( kind = 8 ) X(N), the zeros.
  !
  !    Output, real ( kind = 8 ) W(N), the corresponding weights.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) fd
  real ( kind = 8 ) gd
  real ( kind = 8 ) hd
  real ( kind = 8 ) hf
  real ( kind = 8 ) hn
  integer ( kind = 4 ) i
  integer ( kind = 4 ) it
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) nr
  real ( kind = 8 ) p
  real ( kind = 8 ) q
  real ( kind = 8 ) r
  real ( kind = 8 ) r1
  real ( kind = 8 ) r2
  real ( kind = 8 ) w(n)
  real ( kind = 8 ) wp
  real ( kind = 8 ) x(n)
  real ( kind = 8 ) x0
  real ( kind = 8 ) z
  real ( kind = 8 ) z0
  real ( kind = 8 ) zl

  hn = 1.0D+00 / n
  zl = -1.1611D+00 + 1.46D+00 * sqrt ( real ( n, kind = 8 ) )

  do nr = 1, n / 2

     if ( nr == 1 ) then
        z = zl
     else
        z = z - hn * ( n / 2 + 1 - nr )
     end if

     it = 0

     do

        it = it + 1
        z0 = z
        f0 = 1.0D+00
        f1 = 2.0D+00 * z
        do k = 2, n
           hf = 2.0D+00 * z * f1 - 2.0D+00 * ( k - 1.0D+00 ) * f0
           hd = 2.0D+00 * k * f1
           f0 = f1
           f1 = hf
        end do

        p = 1.0D+00
        do i = 1, nr - 1
           p = p * ( z - x(i) )
        end do
        fd = hf / p

        q = 0.0D+00
        do i = 1, nr - 1
           wp = 1.0D+00
           do j = 1, nr - 1
              if ( j /= i ) then
                 wp = wp * ( z - x(j) )
              end if
           end do
           q = q + wp
        end do

        gd = ( hd - q * fd ) / p
        z = z - fd / gd

        if ( 40 < it .or. abs ( ( z - z0 ) / z ) <= 1.0D-15 ) then
           exit
        end if

     end do

     x(nr) = z
     x(n+1-nr) = -z
     r = 1.0D+00
     do k = 1, n
        r = 2.0D+00 * r * k
     end do
     w(nr) = 3.544907701811D+00 * r / ( hd * hd )
     w(n+1-nr) = w(nr)

  end do

  if ( n /= 2 * int ( n / 2 ) ) then
     r1 = 1.0D+00
     r2 = 1.0D+00
     do j = 1, n
        r1 = 2.0D+00 * r1 * j
        if ( ( n + 1 ) / 2 <= j ) then
           r2 = r2 * j
        end if
     end do
     w(n/2+1) = 0.88622692545276D+00 * r1 / ( r2 * r2 )
     x(n/2+1) = 0.0D+00
  end if

  return
end subroutine herzo
subroutine hygfx ( a, b, c, x, hf )

  !*****************************************************************************80
  !
  !! HYGFX evaluates the hypergeometric function F(A,B,C,X).
  !
  !  Licensing:
  !
  !    The original FORTRAN77 version of this routine is copyrighted by 
  !    Shanjie Zhang and Jianming Jin.  However, they give permission to 
  !    incorporate this routine into a user program that the copyright 
  !    is acknowledged.
  !
  !  Modified:
  !
  !    08 September 2007
  !
  !  Author:
  !
  !    Original FORTRAN77 version by Shanjie Zhang, Jianming Jin.
  !    FORTRAN90 version by John Burkardt.
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) A, B, C, X, the arguments of the function.
  !    C must not be equal to a nonpositive integer.
  !    X < 1.
  !
  !    Output, real HF, the value of the function.
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) a0
  real ( kind = 8 ) aa
  real ( kind = 8 ) b
  real ( kind = 8 ) bb
  real ( kind = 8 ) c
  real ( kind = 8 ) c0
  real ( kind = 8 ) c1
  real ( kind = 8 ), parameter :: el = 0.5772156649015329D+00
  real ( kind = 8 ) eps
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) g0
  real ( kind = 8 ) g1
  real ( kind = 8 ) g2
  real ( kind = 8 ) g3
  real ( kind = 8 ) ga
  real ( kind = 8 ) gabc
  real ( kind = 8 ) gam
  real ( kind = 8 ) gb
  real ( kind = 8 ) gbm
  real ( kind = 8 ) gc
  real ( kind = 8 ) gca
  real ( kind = 8 ) gcab
  real ( kind = 8 ) gcb
  real ( kind = 8 ) gm
  real ( kind = 8 ) hf
  real ( kind = 8 ) hw
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  logical l0
  logical l1
  logical l2
  logical l3
  logical l4
  logical l5
  integer ( kind = 4 ) m
  integer ( kind = 4 ) nm
  real ( kind = 8 ) pa
  real ( kind = 8 ) pb
  real ( kind = 8 ), parameter :: pi = 3.141592653589793D+00
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) r1
  real ( kind = 8 ) rm
  real ( kind = 8 ) rp
  real ( kind = 8 ) sm
  real ( kind = 8 ) sp
  real ( kind = 8 ) sp0
  real ( kind = 8 ) x
  real ( kind = 8 ) x1

  l0 = ( c == aint ( c ) ) .and. ( c < 0.0D+00 )
  l1 = ( 1.0D+00 - x < 1.0D-15 ) .and. ( c - a - b <= 0.0D+00 )
  l2 = ( a == aint ( a ) ) .and. ( a < 0.0D+00 )
  l3 = ( b == aint ( b ) ) .and. ( b < 0.0D+00 )
  l4 = ( c - a == aint ( c - a ) ) .and. ( c - a <= 0.0D+00 )
  l5 = ( c - b == aint ( c - b ) ) .and. ( c - b <= 0.0D+00 )

  if ( l0 .or. l1 ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'HYGFX - Fatal error!'
     write ( *, '(a)' ) '  The hypergeometric series is divergent.'
     return
  end if

  if ( 0.95D+00 < x ) then 
     eps = 1.0D-08
  else
     eps = 1.0D-15
  end if

  if ( x == 0.0D+00 .or. a == 0.0D+00 .or. b == 0.0D+00 ) then

     hf = 1.0D+00
     return

  else if ( 1.0D+00 - x == eps .and. 0.0D+00 < c - a - b ) then

     call gammaf ( c, gc )
     call gammaf ( c - a - b, gcab )
     call gammaf ( c - a, gca )
     call gammaf ( c - b, gcb )
     hf = gc * gcab /( gca *gcb )
     return

  else if ( 1.0D+00 + x <= eps .and. abs ( c - a + b - 1.0D+00 ) <= eps ) then

     g0 = sqrt ( pi ) * 2.0D+00**( - a )
     call gammaf ( c, g1 )
     call gammaf ( 1.0D+00 + a / 2.0D+00 - b, g2 )
     call gammaf ( 0.5D+00 + 0.5D+00 * a, g3 )
     hf = g0 * g1 / ( g2 * g3 )
     return

  else if ( l2 .or. l3 ) then

     if ( l2 ) then
        nm = int ( abs ( a ) )
     end if

     if ( l3 ) then
        nm = int ( abs ( b ) )
     end if

     hf = 1.0D+00
     r = 1.0D+00

     do k = 1, nm
        r = r * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
             / ( k * ( c + k - 1.0D+00 ) ) * x
        hf = hf + r
     end do

     return

  else if ( l4 .or. l5 ) then

     if ( l4 ) then
        nm = int ( abs ( c - a ) )
     end if

     if ( l5 ) then
        nm = int ( abs ( c - b ) )
     end if

     hf = 1.0D+00
     r  = 1.0D+00
     do k = 1, nm
        r = r * ( c - a + k - 1.0D+00 ) * ( c - b + k - 1.0D+00 ) &
             / ( k * ( c + k - 1.0D+00 ) ) * x
        hf = hf + r
     end do
     hf = ( 1.0D+00 - x )**( c - a - b ) * hf
     return

  end if

  aa = a
  bb = b
  x1 = x
  !
  !  WARNING: ALTERATION OF INPUT ARGUMENTS A AND B, WHICH MIGHT BE CONSTANTS.
  !
  if ( x < 0.0D+00 ) then
     x = x / ( x - 1.0D+00 )
     if ( a < c .and. b < a .and. 0.0D+00 < b ) then
        a = bb
        b = aa
     end if
     b = c - b
  end if

  if ( 0.75D+00 <= x ) then

     gm = 0.0D+00

     if ( abs ( c - a - b - aint ( c - a - b ) ) < 1.0D-15 ) then

        m = int ( c - a - b )
        call gammaf ( a, ga )
        call gammaf ( b, gb )
        call gammaf ( c, gc )
        call gammaf ( a + m, gam )
        call gammaf ( b + m, gbm )
        call psi ( a, pa )
        call psi ( b, pb )

        if ( m /= 0 ) then
           gm = 1.0D+00
        end if

        do j = 1, abs ( m ) - 1
           gm = gm * j
        end do

        rm = 1.0D+00
        do j = 1, abs ( m )
           rm = rm * j
        end do

        f0 = 1.0D+00
        r0 = 1.0D+00
        r1 = 1.0D+00
        sp0 = 0.0D+00
        sp = 0.0D+00

        if ( 0 <= m ) then

           c0 = gm * gc / ( gam * gbm )
           c1 = - gc * ( x - 1.0D+00 )**m / ( ga * gb * rm )

           do k = 1, m - 1
              r0 = r0 * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                   / ( k * ( k - m ) ) * ( 1.0D+00 - x )
              f0 = f0 + r0
           end do

           do k = 1, m
              sp0 = sp0 + 1.0D+00 / ( a + k - 1.0D+00 ) &
                   + 1.0D+00 / ( b + k - 1.0D+00 ) - 1.0D+00 / real ( k, kind = 8 )
           end do

           f1 = pa + pb + sp0 + 2.0D+00 * el + log ( 1.0D+00 - x )
           hw = f1

           do k = 1, 250

              sp = sp + ( 1.0D+00 - a ) / ( k * ( a + k - 1.0D+00 ) ) &
                   + ( 1.0D+00 - b ) / ( k * ( b + k - 1.0D+00 ) )

              sm = 0.0D+00
              do j = 1, m
                 sm = sm + ( 1.0D+00 - a ) &
                      / ( ( j + k ) * ( a + j + k - 1.0D+00 ) ) &
                      + 1.0D+00 / ( b + j + k - 1.0D+00 )
              end do

              rp = pa + pb + 2.0D+00 * el + sp + sm + log ( 1.0D+00 - x )

              r1 = r1 * ( a + m + k - 1.0D+00 ) * ( b + m + k - 1.0D+00 ) &
                   / ( k * ( m + k ) ) * ( 1.0D+00 - x )

              f1 = f1 + r1 * rp

              if ( abs ( f1 - hw ) < abs ( f1 ) * eps ) then
                 exit
              end if

              hw = f1

           end do

           hf = f0 * c0 + f1 * c1

        else if ( m < 0 ) then

           m = - m
           c0 = gm * gc / ( ga * gb * ( 1.0D+00 - x )**m )
           c1 = - ( - 1 )**m * gc / ( gam * gbm * rm )

           do k = 1, m - 1
              r0 = r0 * ( a - m + k - 1.0D+00 ) * ( b - m + k - 1.0D+00 ) &
                   / ( k * ( k - m ) ) * ( 1.0D+00 - x )
              f0 = f0 + r0
           end do

           do k = 1, m
              sp0 = sp0 + 1.0D+00 / real ( k, kind = 8 )
           end do

           f1 = pa + pb - sp0 + 2.0D+00 * el + log ( 1.0D+00 - x )

           do k = 1, 250

              sp = sp + ( 1.0D+00 - a ) &
                   / ( k * ( a + k - 1.0D+00 ) ) &
                   + ( 1.0D+00 - b ) / ( k * ( b + k - 1.0D+00 ) )

              sm = 0.0D+00
              do j = 1, m
                 sm = sm + 1.0D+00 / real ( j + k, kind = 8 )
              end do

              rp = pa + pb + 2.0D+00 * el + sp - sm + log ( 1.0D+00 - x )

              r1 = r1 * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                   / ( k * ( m + k ) ) * ( 1.0D+00 - x )

              f1 = f1 + r1 * rp

              if ( abs ( f1 - hw ) < abs ( f1 ) * eps ) then
                 exit
              end if

              hw = f1

           end do

           hf = f0 * c0 + f1 * c1

        end if

     else

        call gammaf ( a, ga )
        call gammaf ( b, gb )
        call gammaf ( c, gc )
        call gammaf ( c - a, gca )
        call gammaf ( c - b, gcb )
        call gammaf ( c - a - b, gcab )
        call gammaf ( a + b - c, gabc )
        c0 = gc * gcab / ( gca * gcb )
        c1 = gc * gabc / ( ga * gb ) * ( 1.0D+00 - x )**( c - a - b )
        hf = 0.0D+00
        r0 = c0
        r1 = c1

        do k = 1, 250

           r0 = r0 * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                / ( k * ( a + b - c + k ) ) * ( 1.0D+00 - x )

           r1 = r1 * ( c - a + k - 1.0D+00 ) * ( c - b + k - 1.0D+00 ) &
                / ( k * ( c - a - b + k ) ) * ( 1.0D+00 - x )

           hf = hf + r0 + r1

           if ( abs ( hf - hw ) < abs ( hf ) * eps ) then
              exit
           end if

           hw = hf

        end do

        hf = hf + c0 + c1

     end if

  else

     a0 = 1.0D+00

     if ( a < c .and. c < 2.0D+00 * a .and. b < c .and. c < 2.0D+00 * b ) then

        a0 = ( 1.0D+00 - x )**( c - a - b )
        a = c - a
        b = c - b

     end if

     hf = 1.0D+00
     r = 1.0D+00

     do k = 1, 250

        r = r * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
             / ( k * ( c + k - 1.0D+00 ) ) * x

        hf = hf + r

        if ( abs ( hf - hw ) <= abs ( hf ) * eps ) then
           exit
        end if

        hw = hf

     end do

     hf = a0 * hf

  end if

  if ( x1 < 0.0D+00 ) then
     x = x1
     c0 = 1.0D+00 / ( 1.0D+00 - x )**aa
     hf = c0 * hf
  end if

  a = aa
  b = bb

  if ( 120 < k ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'HYGFX - Warning!'
     write ( *, '(a)' ) '  A large number of iterations were needed.'
     write ( *, '(a)' ) '  The accuracy of the results should be checked.'
  end if

  return
end subroutine hygfx
subroutine hygfz ( a, b, c, z, zhf )

  !*****************************************************************************80
  !
  !! HYGFZ computes the hypergeometric function F(a,b,c,x) for complex argument.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    03 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) A, B, C, parameters.
  !
  !    Input, complex ( kind = 8 ) Z, the argument.
  !
  !    Output, complex ( kind = 8 ) ZHF, the value of F(a,b,c,z).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) a0
  real ( kind = 8 ) aa
  real ( kind = 8 ) b
  real ( kind = 8 ) bb
  real ( kind = 8 ) c
  real ( kind = 8 ) ca
  real ( kind = 8 ) cb
  real ( kind = 8 ) el
  real ( kind = 8 ) eps
  real ( kind = 8 ) g0
  real ( kind = 8 ) g1
  real ( kind = 8 ) g2
  real ( kind = 8 ) g3
  real ( kind = 8 ) ga
  real ( kind = 8 ) gab
  real ( kind = 8 ) gabc
  real ( kind = 8 ) gam
  real ( kind = 8 ) gb
  real ( kind = 8 ) gba
  real ( kind = 8 ) gbm
  real ( kind = 8 ) gc
  real ( kind = 8 ) gca
  real ( kind = 8 ) gcab
  real ( kind = 8 ) gcb
  real ( kind = 8 ) gcbk
  real ( kind = 8 ) gm
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  logical l0
  logical l1
  logical l2
  logical l3
  logical l4
  logical l5
  logical l6
  integer ( kind = 4 ) m
  integer ( kind = 4 ) mab
  integer ( kind = 4 ) mcab
  integer ( kind = 4 ) nca
  integer ( kind = 4 ) ncb
  integer ( kind = 4 ) nm
  real ( kind = 8 ) pa
  real ( kind = 8 ) pac
  real ( kind = 8 ) pb
  real ( kind = 8 ) pca
  real ( kind = 8 ) pi
  real ( kind = 8 ) rk1
  real ( kind = 8 ) rk2
  real ( kind = 8 ) rm
  real ( kind = 8 ) sj1
  real ( kind = 8 ) sj2
  real ( kind = 8 ) sm
  real ( kind = 8 ) sp
  real ( kind = 8 ) sp0
  real ( kind = 8 ) sq
  real ( kind = 8 ) t0
  real ( kind = 8 ) w0
  real ( kind = 8 ) ws
  real ( kind = 8 ) x
  real ( kind = 8 ) y
  complex ( kind = 8 ) z
  complex ( kind = 8 ) z00
  complex ( kind = 8 ) z1
  complex ( kind = 8 ) zc0
  complex ( kind = 8 ) zc1
  complex ( kind = 8 ) zf0
  complex ( kind = 8 ) zf1
  complex ( kind = 8 ) zhf
  complex ( kind = 8 ) zp
  complex ( kind = 8 ) zp0
  complex ( kind = 8 ) zr
  complex ( kind = 8 ) zr0
  complex ( kind = 8 ) zr1
  complex ( kind = 8 ) zw

  x = real ( z, kind = 8 )
  y = imag ( z )
  eps = 1.0D-15
  l0 = c == int ( c ) .and. c < 0.0D+00
  l1 = abs ( 1.0D+00 - x ) < eps .and. y == 0.0D+00 .and. &
       c - a - b <= 0.0D+00
  l2 = abs ( z + 1.0D+00 ) < eps .and. &
       abs ( c - a + b - 1.0D+00 ) < eps
  l3 = a == int ( a ) .and. a < 0.0D+00
  l4 = b == int ( b ) .and. b < 0.0D+00
  l5 = c - a == int ( c - a ) .and. c - a <= 0.0D+00
  l6 = c - b == int ( c - b ) .and. c - b <= 0.0D+00
  aa = a
  bb = b
  a0 = abs ( z )
  if ( 0.95D+00 < a0 ) then
     eps = 1.0D-08
  end if
  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00

  if ( l0 .or. l1 ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'HYGFZ - Fatal error!'
     write ( *, '(a)' ) '  The hypergeometric series is divergent.'
     stop
  end if

  if ( a0 == 0.0D+00 .or. a == 0.0D+00 .or. b == 0.0D+00 ) then

     zhf = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )

  else if ( z == 1.0D+00.and. 0.0D+00 < c - a - b ) then

     call gammaf ( c, gc )
     call gammaf ( c - a - b, gcab )
     call gammaf ( c - a, gca )
     call gammaf ( c - b, gcb )
     zhf = gc * gcab / ( gca * gcb )

  else if ( l2 ) then

     g0 = sqrt ( pi ) * 2.0D+00 ** ( - a )
     call gammaf ( c, g1 )
     call gammaf ( 1.0D+00 + a / 2.0D+00 - b, g2 )
     call gammaf ( 0.5D+00 + 0.5D+00 * a, g3 )
     zhf = g0 * g1 / ( g2 * g3 )

  else if ( l3 .or. l4 ) then

     if ( l3 ) then
        nm = int ( abs ( a ) )
     end if

     if ( l4 ) then
        nm = int ( abs ( b ) )
     end if

     zhf = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     zr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     do k = 1, nm
        zr = zr * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
             / ( k * ( c + k - 1.0D+00 ) ) * z
        zhf = zhf + zr
     end do

  else if ( l5 .or. l6 ) then

     if ( l5 ) then
        nm = int ( abs ( c - a ) )
     end if

     if ( l6 ) then
        nm = int ( abs ( c - b ) )
     end if

     zhf = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     zr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
     do k = 1, nm
        zr = zr * ( c - a + k - 1.0D+00 ) * ( c - b + k - 1.0D+00 ) &
             / ( k * ( c + k - 1.0D+00 ) ) * z
        zhf = zhf + zr
     end do
     zhf = ( 1.0D+00 - z ) ** ( c - a - b ) * zhf

  else if ( a0 <= 1.0D+00 ) then

     if ( x < 0.0D+00 ) then

        z1 = z / ( z - 1.0D+00 )
        if ( a < c .and. b < a .and. 0.0D+00 < b ) then  
           a = bb
           b = aa
        end if
        zc0 = 1.0D+00 / ( ( 1.0D+00 - z ) ** a )
        zhf = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        zr0 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        do k = 1, 500
           zr0 = zr0 * ( a + k - 1.0D+00 ) * ( c - b + k - 1.0D+00 ) &
                / ( k * ( c + k - 1.0D+00 ) ) * z1
           zhf = zhf + zr0
           if ( abs ( zhf - zw ) < abs ( zhf ) * eps ) then
              exit
           end if
           zw = zhf
        end do

        zhf = zc0 * zhf

     else if ( 0.90D+00 <= a0 ) then

        gm = 0.0D+00
        mcab = int ( c - a - b + eps * sign ( 1.0D+00, c - a - b ) )

        if ( abs ( c - a - b - mcab ) < eps ) then

           m = int ( c - a - b )
           call gammaf ( a, ga )
           call gammaf ( b, gb )
           call gammaf ( c, gc )
           call gammaf ( a + m, gam )
           call gammaf ( b + m, gbm ) 
           call psi ( a, pa )
           call psi ( b, pb )
           if ( m /= 0 ) then
              gm = 1.0D+00
           end if
           do j = 1, abs ( m ) - 1
              gm = gm * j
           end do
           rm = 1.0D+00
           do j = 1, abs ( m )
              rm = rm * j
           end do
           zf0 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
           zr0 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
           zr1 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
           sp0 = 0.0D+00
           sp = 0.0D+00

           if ( 0 <= m ) then

              zc0 = gm * gc / ( gam * gbm )
              zc1 = - gc * ( z - 1.0D+00 ) ** m / ( ga * gb * rm )
              do k = 1, m - 1
                 zr0 = zr0 * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                      / ( k * ( k - m ) ) * ( 1.0D+00 - z )
                 zf0 = zf0 + zr0
              end do
              do k = 1, m
                 sp0 = sp0 + 1.0D+00 / ( a + k - 1.0D+00 ) &
                      + 1.0D+00 / ( b + k - 1.0D+00 ) - 1.0D+00 / k
              end do
              zf1 = pa + pb + sp0 + 2.0D+00 * el + log ( 1.0D+00 - z )
              do k = 1, 500
                 sp = sp + ( 1.0D+00 - a ) &
                      / ( k * ( a + k - 1.0D+00 ) ) + ( 1.0D+00 - b ) &
                      / ( k * ( b + k - 1.0D+00 ) )
                 sm = 0.0D+00
                 do j = 1, m
                    sm = sm + ( 1.0D+00 - a ) / ( ( j + k ) &
                         * ( a + j + k - 1.0D+00 ) ) &
                         + 1.0D+00 / ( b + j + k - 1.0D+00 )
                 end do
                 zp = pa + pb + 2.0D+00 * el + sp + sm  + log ( 1.0D+00 - z )
                 zr1 = zr1 * ( a + m + k - 1.0D+00 ) &
                      * ( b + m + k - 1.0D+00 ) / ( k * ( m + k ) ) &
                      * ( 1.0D+00 - z )
                 zf1 = zf1 + zr1 * zp
                 if ( abs ( zf1 - zw ) < abs ( zf1 ) * eps ) then
                    exit
                 end if
                 zw = zf1
              end do

              zhf = zf0 * zc0 + zf1 * zc1

           else if ( m < 0 ) then

              m = - m
              zc0 = gm * gc / ( ga * gb * ( 1.0D+00 - z ) ** m )
              zc1 = - ( - 1.0D+00 ) ** m * gc / ( gam * gbm * rm )
              do k = 1, m - 1
                 zr0 = zr0 * ( a - m + k - 1.0D+00 ) &
                      * ( b - m + k - 1.0D+00 ) / ( k * ( k - m ) ) &
                      * ( 1.0D+00 - z )
                 zf0 = zf0 + zr0
              end do

              do k = 1, m
                 sp0 = sp0 + 1.0D+00 / k
              end do

              zf1 = pa + pb - sp0 + 2.0D+00 * el + log ( 1.0D+00 - z )

              do k = 1, 500
                 sp = sp + ( 1.0D+00 - a ) / ( k * ( a + k - 1.0D+00 ) ) &
                      + ( 1.0D+00 - b ) / ( k * ( b + k - 1.0D+00 ) )
                 sm = 0.0D+00
                 do j = 1, m
                    sm = sm + 1.0D+00 / ( j + k )
                 end do
                 zp = pa + pb + 2.0D+00 * el + sp - sm + log ( 1.0D+00 - z )
                 zr1 = zr1 * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                      / ( k * ( m + k ) ) * ( 1.0D+00 - z )
                 zf1 = zf1 + zr1 * zp
                 if ( abs ( zf1 - zw ) < abs ( zf1 ) * eps ) then
                    exit
                 end if
                 zw = zf1

              end do

              zhf = zf0 * zc0 + zf1 * zc1

           end if

        else

           call gammaf ( a, ga )
           call gammaf ( b, gb )
           call gammaf ( c, gc )
           call gammaf ( c - a, gca )
           call gammaf ( c - b, gcb )
           call gammaf ( c - a - b, gcab )
           call gammaf ( a + b - c, gabc )
           zc0 = gc * gcab / ( gca * gcb )
           zc1 = gc * gabc / ( ga * gb ) * ( 1.0D+00 - z ) ** ( c - a - b )
           zhf = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )
           zr0 = zc0
           zr1 = zc1
           do k = 1, 500
              zr0 = zr0 * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                   / ( k * ( a + b - c + k ) ) * ( 1.0D+00 - z )
              zr1 = zr1 * ( c - a + k - 1.0D+00 ) &
                   * ( c - b + k - 1.0D+00 ) / ( k * ( c - a - b + k ) ) &
                   * ( 1.0D+00 - z )
              zhf = zhf + zr0 + zr1
              if ( abs ( zhf - zw ) < abs ( zhf ) * eps ) then
                 exit
              end if
              zw = zhf
           end do

           zhf = zhf + zc0 + zc1

        end if

     else

        z00 = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )

        if ( c - a < a .and. c - b < b ) then
           z00 = ( 1.0D+00 - z ) ** ( c - a - b )
           a = c - a
           b = c - b
        end if

        zhf = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )
        zr = cmplx ( 1.0D+00, 0.0D+00, kind = 8 )

        do k = 1, 1500
           zr = zr * ( a + k - 1.0D+00 ) * ( b + k - 1.0D+00 ) &
                / ( k * ( c + k - 1.0D+00 ) ) * z
           zhf = zhf + zr
           if ( abs ( zhf - zw ) <= abs ( zhf ) * eps ) then
              exit
           end if
           zw = zhf
        end do

        zhf = z00 * zhf

     end if

  else if ( 1.0D+00 < a0 ) then

     mab = int ( a - b + eps * sign ( 1.0D+00, a - b ) )

     if ( abs ( a - b - mab ) < eps .and. a0 <= 1.1D+00 ) then
        b = b + eps
     end if

     if ( eps < abs ( a - b - mab ) ) then

        call gammaf ( a, ga )
        call gammaf ( b, gb )
        call gammaf ( c, gc )
        call gammaf ( a - b, gab )
        call gammaf ( b - a, gba )
        call gammaf ( c - a, gca )
        call gammaf ( c - b, gcb )
        zc0 = gc * gba / ( gca * gb * ( - z ) ** a )
        zc1 = gc * gab / ( gcb * ga * ( - z ) ** b )
        zr0 = zc0
        zr1 = zc1
        zhf = cmplx ( 0.0D+00, 0.0D+00 )

        do k = 1, 500
           zr0 = zr0 * ( a + k - 1.0D+00 ) * ( a - c + k ) &
                / ( ( a - b + k ) * k * z )
           zr1 = zr1 * ( b + k - 1.0D+00 ) * ( b - c + k ) &
                / ( ( b - a + k ) * k * z )
           zhf = zhf + zr0 + zr1
           if ( abs ( ( zhf - zw ) / zhf ) <= eps ) then
              exit
           end if
           zw = zhf
        end do

        zhf = zhf + zc0 + zc1

     else

        if ( a - b < 0.0D+00 ) then
           a = bb
           b = aa
        end if

        ca = c - a
        cb = c - b
        nca = int ( ca + eps * sign ( 1.0D+00, ca ) )
        ncb = int ( cb + eps * sign ( 1.0D+00, cb ) )

        if ( abs ( ca - nca ) < eps .or. abs ( cb - ncb ) < eps ) then
           c = c + eps
        end if

        call gammaf ( a, ga )
        call gammaf ( c, gc )
        call gammaf ( c - b, gcb )
        call psi ( a, pa )
        call psi ( c - a, pca )
        call psi ( a - c, pac )
        mab = int ( a - b + eps )
        zc0 = gc / ( ga * ( - z ) ** b )
        call gammaf ( a - b, gm )
        zf0 = gm / gcb * zc0
        zr = zc0
        do k = 1, mab - 1
           zr = zr * ( b + k - 1.0D+00 ) / ( k * z )
           t0 = a - b - k
           call gammaf ( t0, g0 )
           call gammaf ( c - b - k, gcbk )
           zf0 = zf0 + zr * g0 / gcbk
        end do

        if ( mab == 0 ) then
           zf0 = cmplx ( 0.0D+00, 0.0D+00, kind = 8 )
        end if

        zc1 = gc / ( ga * gcb * ( - z ) ** a )
        sp = -2.0D+00 * el - pa - pca
        do j = 1, mab
           sp = sp + 1.0D+00 / j
        end do
        zp0 = sp + log ( - z )
        sq = 1.0D+00
        do j = 1, mab
           sq = sq * ( b + j - 1.0D+00 ) * ( b - c + j ) / j
        end do
        zf1 = ( sq * zp0 ) * zc1
        zr = zc1
        rk1 = 1.0D+00
        sj1 = 0.0D+00

        do k = 1, 10000
           zr = zr / z
           rk1 = rk1 * ( b + k - 1.0D+00 ) * ( b - c + k ) / ( k * k )
           rk2 = rk1
           do j = k + 1, k + mab
              rk2 = rk2 * ( b + j - 1.0D+00 ) * ( b - c + j ) / j
           end do
           sj1 = sj1 + ( a - 1.0D+00 ) / ( k * ( a + k - 1.0D+00 ) ) &
                + ( a - c - 1.0D+00 ) / ( k * ( a - c + k - 1.0D+00 ) )
           sj2 = sj1
           do j = k + 1, k + mab
              sj2 = sj2 + 1.0D+00 / j
           end do
           zp = -2.0D+00 * el - pa - pac + sj2 - 1.0D+00 / ( k + a - c ) &
                - pi / tan ( pi * ( k + a - c ) ) + log ( - z ) 
           zf1 = zf1 + rk2 * zr * zp
           ws = abs ( zf1 )
           if ( abs ( ( ws - w0 ) / ws ) < eps ) then
              exit
           end if
           w0 = ws
        end do

        zhf = zf0 + zf1

     end if

  end if

  a = aa
  b = bb
  if ( 150 < k ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'HYGFZ - Warning!'
     write ( *, '(a)' ) '  The solution returned may have low accuracy.'
  end if

  return
end subroutine hygfz
subroutine ik01a ( x, bi0, di0, bi1, di1, bk0, dk0, bk1, dk1 )

  !*****************************************************************************80
  !
  !! IK01A compute Bessel function I0(x), I1(x), K0(x), and K1(x).
  !
  !  Discussion:
  !
  !    This procedure computes modified Bessel functions I0(x), I1(x),
  !    K0(x) and K1(x), and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    16 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BI0, DI0, BI1, DI1, BK0, DK0, BK1, DK1, the
  !    values of I0(x), I0'(x), I1(x), I1'(x), K0(x), K0'(x), K1(x), K1'(x).
  !
  implicit none

  real ( kind = 8 ), save, dimension ( 12 ) :: a = (/ &
       0.125D+00, 7.03125D-02, &
       7.32421875D-02, 1.1215209960938D-01, &
       2.2710800170898D-01, 5.7250142097473D-01, &
       1.7277275025845D+00, 6.0740420012735D+00, &
       2.4380529699556D+01, 1.1001714026925D+02, &
       5.5133589612202D+02, 3.0380905109224D+03 /)
  real ( kind = 8 ), save, dimension ( 8 ) :: a1 = (/ &
       0.125D+00, 0.2109375D+00, &
       1.0986328125D+00, 1.1775970458984D+01, &
       2.1461706161499D+02, 5.9511522710323D+03, &
       2.3347645606175D+05, 1.2312234987631D+07 /)
  real ( kind = 8 ), save, dimension ( 12 ) :: b = (/ &
       -0.375D+00, -1.171875D-01, &
       -1.025390625D-01, -1.4419555664063D-01, &
       -2.7757644653320D-01, -6.7659258842468D-01, &
       -1.9935317337513D+00, -6.8839142681099D+00, &
       -2.7248827311269D+01, -1.2159789187654D+02, &
       -6.0384407670507D+02, -3.3022722944809D+03 /)
  real ( kind = 8 ) bi0
  real ( kind = 8 ) bi1
  real ( kind = 8 ) bk0
  real ( kind = 8 ) bk1
  real ( kind = 8 ) ca
  real ( kind = 8 ) cb
  real ( kind = 8 ) ct
  real ( kind = 8 ) di0
  real ( kind = 8 ) di1
  real ( kind = 8 ) dk0
  real ( kind = 8 ) dk1
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) w0
  real ( kind = 8 ) ww
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) xr
  real ( kind = 8 ) xr2

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00
  x2 = x * x

  if ( x == 0.0D+00 ) then

     bi0 = 1.0D+00
     bi1 = 0.0D+00
     bk0 = 1.0D+300
     bk1 = 1.0D+300
     di0 = 0.0D+00
     di1 = 0.5D+00
     dk0 = -1.0D+300
     dk1 = -1.0D+300
     return

  else if ( x <= 18.0D+00 ) then

     bi0 = 1.0D+00
     r = 1.0D+00
     do k = 1, 50
        r = 0.25D+00 * r * x2 / ( k * k )
        bi0 = bi0 + r
        if ( abs ( r / bi0 ) < 1.0D-15 ) then
           exit
        end if
     end do

     bi1 = 1.0D+00
     r = 1.0D+00
     do k = 1, 50
        r = 0.25D+00 * r * x2 / ( k * ( k + 1 ) )
        bi1 = bi1 + r
        if ( abs ( r / bi1 ) < 1.0D-15 ) then
           exit
        end if
     end do

     bi1 = 0.5D+00 * x * bi1

  else

     if ( x < 35.0D+00 ) then
        k0 = 12
     else if ( x < 50.0D+00 ) then
        k0 = 9
     else
        k0 = 7
     end if

     ca = exp ( x ) / sqrt ( 2.0D+00 * pi * x )
     bi0 = 1.0D+00
     xr = 1.0D+00 / x
     do k = 1, k0
        bi0 = bi0 + a(k) * xr ** k
     end do
     bi0 = ca * bi0
     bi1 = 1.0D+00
     do k = 1, k0
        bi1 = bi1 + b(k) * xr ** k
     end do
     bi1 = ca * bi1

  end if

  if ( x <= 9.0D+00 ) then

     ct = - ( log ( x / 2.0D+00 ) + el )
     bk0 = 0.0D+00
     w0 = 0.0D+00
     r = 1.0D+00
     do k = 1, 50
        w0 = w0 + 1.0D+00 / k
        r = 0.25D+00 * r / ( k * k ) * x2
        bk0 = bk0 + r * ( w0 + ct )
        if ( abs ( ( bk0 - ww ) / bk0 ) < 1.0D-15 ) then
           exit
        end if
        ww = bk0
     end do

     bk0 = bk0 + ct

  else

     cb = 0.5D+00 / x
     xr2 = 1.0D+00 / x2
     bk0 = 1.0D+00
     do k = 1, 8
        bk0 = bk0 + a1(k) * xr2 ** k
     end do
     bk0 = cb * bk0 / bi0

  end if

  bk1 = ( 1.0D+00 / x - bi1 * bk0 ) / bi0
  di0 = bi1
  di1 = bi0 - bi1 / x
  dk0 = - bk1
  dk1 = - bk0 - bk1 / x

  return
end subroutine ik01a
subroutine ik01b ( x, bi0, di0, bi1, di1, bk0, dk0, bk1, dk1 )

  !*****************************************************************************80
  !
  !! IK01B: Bessel functions I0(x), I1(x), K0(x), and K1(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    17 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BI0, DI0, BI1, DI1, BK0, DK0, BK1, DK1, the
  !    values of I0(x), I0'(x), I1(x), I1'(x), K0(x), K0'(x), K1(x), K1'(x).
  !
  implicit none

  real ( kind = 8 ) bi0
  real ( kind = 8 ) bi1
  real ( kind = 8 ) bk0
  real ( kind = 8 ) bk1
  real ( kind = 8 ) di0
  real ( kind = 8 ) di1
  real ( kind = 8 ) dk0
  real ( kind = 8 ) dk1
  real ( kind = 8 ) t
  real ( kind = 8 ) t2
  real ( kind = 8 ) x

  if ( x == 0.0D+00 ) then

     bi0 = 1.0D+00
     bi1 = 0.0D+00
     bk0 = 1.0D+300
     bk1 = 1.0D+300
     di0 = 0.0D+00
     di1 = 0.5D+00
     dk0 = -1.0D+300
     dk1 = -1.0D+300
     return

  else if ( x <= 3.75D+00 ) then

     t = x / 3.75D+00
     t2 = t * t

     bi0 = ((((( &
          0.0045813D+00   * t2 &
          + 0.0360768D+00 ) * t2 &
          + 0.2659732D+00 ) * t2 &
          + 1.2067492D+00 ) * t2 &
          + 3.0899424D+00 ) * t2 &
          + 3.5156229D+00 ) * t2 &
          + 1.0D+00

     bi1 = x * (((((( &
          0.00032411D+00   * t2 &
          + 0.00301532D+00 ) * t2 &
          + 0.02658733D+00 ) * t2 &
          + 0.15084934D+00 ) * t2 &
          + 0.51498869D+00 ) * t2 &
          + 0.87890594D+00 ) * t2 &
          + 0.5D+00 )

  else

     t = 3.75D+00 / x

     bi0 = (((((((( &
          0.00392377D+00   * t &
          - 0.01647633D+00 ) * t &
          + 0.02635537D+00 ) * t &
          - 0.02057706D+00 ) * t &
          + 0.916281D-02 ) * t &
          - 0.157565D-02 ) * t &
          + 0.225319D-02 ) * t &
          + 0.01328592D+00 ) * t &
          + 0.39894228D+00 ) * exp ( x ) / sqrt ( x )

     bi1 = (((((((( &
          - 0.420059D-02     * t &
          + 0.01787654D+00 ) * t &
          - 0.02895312D+00 ) * t &
          + 0.02282967D+00 ) * t &
          - 0.01031555D+00 ) * t &
          + 0.163801D-02 ) * t &
          - 0.00362018D+00 ) * t &
          - 0.03988024D+00 ) * t &
          + 0.39894228D+00 ) * exp ( x ) / sqrt ( x )

  end if

  if ( x <= 2.0D+00 ) then

     t = x / 2.0D+00
     t2 = t * t

     bk0 = ((((( &
          0.0000074D+00   * t2 &
          + 0.0001075D+00 ) * t2 &
          + 0.00262698D+00 ) * t2 &
          + 0.0348859D+00 ) * t2 &
          + 0.23069756D+00 ) * t2 &
          + 0.4227842D+00 ) * t2 &
          - 0.57721566D+00 - bi0 * log ( t )

     bk1 = (((((( &
          - 0.00004686D+00   * t2 &
          - 0.00110404D+00 ) * t2 &
          - 0.01919402D+00 ) * t2 &
          - 0.18156897D+00 ) * t2 &
          - 0.67278579D+00 ) * t2 &
          + 0.15443144D+00 ) * t2 &
          + 1.0D+00 ) / x + bi1 * log ( t )

  else

     t = 2.0D+00 / x
     t2 = t * t

     bk0 = (((((( &
          0.00053208D+00   * t &
          - 0.0025154D+00 )  * t &
          + 0.00587872D+00 ) * t &
          - 0.01062446D+00 ) * t &
          + 0.02189568D+00 ) * t &
          - 0.07832358D+00 ) * t &
          + 1.25331414D+00 ) * exp ( - x ) / sqrt ( x )

     bk1 = (((((( &
          - 0.00068245D+00   * t &
          + 0.00325614D+00 ) * t &
          - 0.00780353D+00 ) * t &
          + 0.01504268D+00 ) * t &
          - 0.0365562D+00  ) * t & 
          + 0.23498619D+00 ) * t &
          + 1.25331414D+00 ) * exp ( - x ) / sqrt ( x )

  end if

  di0 = bi1
  di1 = bi0 - bi1 / x
  dk0 = -bk1
  dk1 = -bk0 - bk1 / x

  return
end subroutine ik01b
subroutine ikna ( n, x, nm, bi, di, bk, dk )

  !*****************************************************************************80
  !
  !! IKNA compute Bessel function In(x) and Kn(x), and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    16 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of In(x) and Kn(x).
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BI(0:N), DI(0:N), BK(0:N), DK(0:N),
  !    the values of In(x), In'(x), Kn(x), Kn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) bi(0:n)
  real ( kind = 8 ) bi0
  real ( kind = 8 ) bi1
  real ( kind = 8 ) bk(0:n)
  real ( kind = 8 ) bk0
  real ( kind = 8 ) bk1
  real ( kind = 8 ) di(0:n)
  real ( kind = 8 ) di0
  real ( kind = 8 ) di1
  real ( kind = 8 ) dk(0:n)
  real ( kind = 8 ) dk0
  real ( kind = 8 ) dk1
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) g
  real ( kind = 8 ) g0
  real ( kind = 8 ) g1
  real ( kind = 8 ) h
  real ( kind = 8 ) h0
  real ( kind = 8 ) h1
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  real ( kind = 8 ) s0
  real ( kind = 8 ) x

  nm = n

  if ( x <= 1.0D-100 ) then
     do k = 0, n
        bi(k) = 0.0D+00
        di(k) = 0.0D+00
        bk(k) = 1.0D+300
        dk(k) = -1.0D+300
     end do
     bi(0) = 1.0D+00
     di(1) = 0.5D+00
     return
  end if

  call ik01a ( x, bi0, di0, bi1, di1, bk0, dk0, bk1, dk1 )
  bi(0) = bi0
  bi(1) = bi1
  bk(0) = bk0
  bk(1) = bk1
  di(0) = di0
  di(1) = di1
  dk(0) = dk0
  dk(1) = dk1

  if ( n <= 1 ) then
     return
  end if

  if ( 40.0D+00 < x .and. n < int ( 0.25D+00 * x ) ) then

     h0 = bi0
     h1 = bi1
     do k = 2, n
        h = -2.0D+00 * ( k - 1.0D+00 ) / x * h1 + h0
        bi(k) = h
        h0 = h1
        h1 = h
     end do

  else

     m = msta1 ( x, 200 )

     if ( m < n ) then
        nm = m
     else
        m = msta2 ( x, n, 15 )
     end if

     f0 = 0.0D+00
     f1 = 1.0D-100
     do k = m, 0, -1
        f = 2.0D+00 * ( k + 1.0D+00 ) * f1 / x + f0
        if ( k <= nm ) then
           bi(k) = f
        end if
        f0 = f1
        f1 = f
     end do
     s0 = bi0 / f
     do k = 0, nm
        bi(k) = s0 * bi(k)
     end do
  end if

  g0 = bk0
  g1 = bk1
  do k = 2, nm
     g = 2.0D+00 * ( k - 1.0D+00 ) / x * g1 + g0
     bk(k) = g
     g0 = g1
     g1 = g
  end do

  do k = 2, nm
     di(k) = bi(k-1) - k / x * bi(k)
     dk(k) = - bk(k-1) - k / x * bk(k)
  end do

  return
end subroutine ikna
subroutine iknb ( n, x, nm, bi, di, bk, dk )

  !*****************************************************************************80
  !
  !! IKNB compute Bessel function In(x) and Kn(x).
  !
  !  Discussion:
  !
  !    Compute modified Bessel functions In(x) and Kn(x),
  !    and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    17 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of In(x) and Kn(x).
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BI(0:N), DI(0:N), BK(0:N), DK(0:N),
  !    the values of In(x), In'(x), Kn(x), Kn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) a0
  real ( kind = 8 ) bi(0:n)
  real ( kind = 8 ) bk(0:n)
  real ( kind = 8 ) bkl
  real ( kind = 8 ) bs
  real ( kind = 8 ) di(0:n)
  real ( kind = 8 ) dk(0:n)
  real ( kind = 8 ) el
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) g
  real ( kind = 8 ) g0
  real ( kind = 8 ) g1
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) s0
  real ( kind = 8 ) sk0
  real ( kind = 8 ) vt
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00
  el = 0.5772156649015329d0
  nm = n

  if ( x <= 1.0D-100 ) then
     do k = 0, n
        bi(k) = 0.0D+00
        di(k) = 0.0D+00
        bk(k) = 1.0D+300
        dk(k) = -1.0D+300
     end do
     bi(0) = 1.0D+00
     di(1) = 0.5D+00
     return
  end if

  if ( n == 0 ) then
     nm = 1
  end if

  m = msta1 ( x, 200 )
  if ( m < nm ) then
     nm = m
  else
     m = msta2 ( x, nm, 15 )
  end if

  bs = 0.0D+00
  sk0 = 0.0D+00
  f0 = 0.0D+00
  f1 = 1.0D-100
  do k = m, 0, -1
     f = 2.0D+00 * ( k + 1.0D+00 ) / x * f1 + f0
     if ( k <= nm ) then
        bi(k) = f
     end if
     if ( k /= 0 .and. k == 2 * int ( k / 2 ) ) then
        sk0 = sk0 + 4.0D+00 * f / k
     end if
     bs = bs + 2.0D+00 * f
     f0 = f1
     f1 = f
  end do

  s0 = exp ( x ) / ( bs - f )
  do k = 0, nm
     bi(k) = s0 * bi(k)
  end do

  if ( x <= 8.0D+00 ) then
     bk(0) = - ( log ( 0.5D+00 * x ) + el ) * bi(0) + s0 * sk0
     bk(1) = ( 1.0D+00 / x - bi(1) * bk(0) ) / bi(0)
  else
     a0 = sqrt ( pi / ( 2.0D+00 * x ) ) * exp ( - x ) 

     if ( x < 25.0D+00 ) then
        k0 = 16
     else if ( x < 80.0D+00 ) then
        k0 = 10
     else if ( x < 200.0D+00 ) then
        k0 = 8
     else
        k0 = 6
     end if

     do l = 0, 1
        bkl = 1.0D+00
        vt = 4.0D+00 * l
        r = 1.0D+00
        do k = 1, k0
           r = 0.125D+00 * r * ( vt - ( 2.0D+00 * k - 1.0D+00 ) ** 2 ) / ( k * x )
           bkl = bkl + r
        end do
        bk(l) = a0 * bkl
     end do
  end if

  g0 = bk(0)
  g1 = bk(1)
  do k = 2, nm
     g = 2.0D+00 * ( k - 1.0D+00 ) / x * g1 + g0
     bk(k) = g
     g0 = g1
     g1 = g
  end do

  di(0) = bi(1)
  dk(0) = -bk(1)
  do k = 1, nm
     di(k) = bi(k-1) - k / x * bi(k)
     dk(k) = -bk(k-1) - k / x * bk(k)
  end do

  return
end subroutine iknb
subroutine ikv ( v, x, vm, bi, di, bk, dk )

  !*****************************************************************************80
  !
  !! IKV compute modified Bessel function Iv(x) and Kv(x) and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    17 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) V, the order of Iv(x) and Kv(x).
  !    V = N + V0.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) VM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BI(0:N), DI(0:N), BK(0:N), DK(0:N), the
  !    values of In+v0(x), In+v0'(x), Kn+v0(x), Kn+v0'(x).
  !
  implicit none

  real ( kind = 8 ) a1
  real ( kind = 8 ) a2
  real ( kind = 8 ) bi(0:*)
  real ( kind = 8 ) bi0
  real ( kind = 8 ) bk(0:*)
  real ( kind = 8 ) bk0
  real ( kind = 8 ) bk1
  real ( kind = 8 ) bk2
  real ( kind = 8 ) ca
  real ( kind = 8 ) cb
  real ( kind = 8 ) cs
  real ( kind = 8 ) ct
  real ( kind = 8 ) di(0:*)
  real ( kind = 8 ) dk(0:*)
  real ( kind = 8 ) f
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  real ( kind = 8 ) gan
  real ( kind = 8 ) gap
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) n
  real ( kind = 8 ) pi
  real ( kind = 8 ) piv
  real ( kind = 8 ) r
  real ( kind = 8 ) r1
  real ( kind = 8 ) r2
  real ( kind = 8 ) sum
  real ( kind = 8 ) v
  real ( kind = 8 ) v0
  real ( kind = 8 ) v0n
  real ( kind = 8 ) v0p
  real ( kind = 8 ) vm
  real ( kind = 8 ) vt
  real ( kind = 8 ) w0
  real ( kind = 8 ) wa
  real ( kind = 8 ) ww
  real ( kind = 8 ) x
  real ( kind = 8 ) x2

  pi = 3.141592653589793D+00
  x2 = x * x
  n = int ( v )
  v0 = v - n
  if ( n == 0 ) then
     n = 1
  end if

  if ( x < 1.0D-100 ) then

     do k = 0, n
        bi(k) = 0.0D+00
        di(k) = 0.0D+00
        bk(k) = -1.0D+300
        dk(k) = 1.0D+300
     end do

     if ( v == 0.0D+00 ) then
        bi(0) = 1.0D+00
        di(1) = 0.5D+00
     end if

     vm = v
     return

  end if

  piv = pi * v0
  vt = 4.0D+00 * v0 * v0

  if ( v0 == 0.0D+00 ) then
     a1 = 1.0D+00
  else
     v0p = 1.0D+00 + v0
     call gammaf ( v0p, gap )
     a1 = ( 0.5D+00 * x ) ** v0 / gap
  end if

  if ( x < 35.0D+00 ) then
     k0 = 14
  else if ( x < 50.0D+00 ) then
     k0 = 10
  else
     k0 = 8
  end if

  if ( x <= 18.0D+00 ) then

     bi0 = 1.0D+00
     r = 1.0D+00
     do k = 1, 30
        r = 0.25D+00 * r * x2 / ( k * ( k + v0 ) )
        bi0 = bi0 + r
        if ( abs ( r / bi0 ) < 1.0D-15 ) then
           exit
        end if
     end do

     bi0 = bi0 * a1

  else

     ca = exp ( x ) / sqrt ( 2.0D+00 * pi * x )
     sum = 1.0D+00
     r = 1.0D+00
     do k = 1, k0
        r = -0.125D+00 * r * ( vt - ( 2.0D+00 * k - 1.0D+00 ) ** 2 ) / ( k * x )
        sum = sum + r
     end do
     bi0 = ca * sum

  end if

  m = msta1 ( x, 200 )

  if ( m < n ) then
     n = m
  else
     m = msta2 ( x, n, 15 )
  end if

  f2 = 0.0D+00
  f1 = 1.0D-100
  do k = m, 0, -1
     f = 2.0D+00 * ( v0 + k + 1.0D+00 ) / x * f1 + f2
     if ( k <= n ) then
        bi(k) = f
     end if
     f2 = f1
     f1 = f
  end do

  cs = bi0 / f
  do k = 0, n
     bi(k) = cs * bi(k)
  end do

  di(0) = v0 / x * bi(0) + bi(1)
  do k = 1, n
     di(k) = - ( k + v0 ) / x * bi(k) + bi(k-1)
  end do

  if ( x <= 9.0D+00 ) then

     if ( v0 == 0.0D+00 ) then

        ct = - log ( 0.5D+00 * x ) - 0.5772156649015329D+00
        cs = 0.0D+00
        w0 = 0.0D+00
        r = 1.0D+00
        do k = 1, 50
           w0 = w0 + 1.0D+00 / k
           r = 0.25D+00 * r / ( k * k ) * x2
           cs = cs + r * ( w0 + ct )
           wa = abs ( cs )
           if ( abs ( ( wa - ww ) / wa ) < 1.0D-15 ) then
              exit
           end if
           ww = wa
        end do

        bk0 = ct + cs

     else

        v0n = 1.0D+00 - v0
        call gammaf ( v0n, gan )
        a2 = 1.0D+00 / ( gan * ( 0.5D+00 * x ) ** v0 )
        a1 = ( 0.5D+00 * x ) ** v0 / gap
        sum = a2 - a1
        r1 = 1.0D+00
        r2 = 1.0D+00
        do k = 1, 120
           r1 = 0.25D+00 * r1 * x2 / ( k * ( k - v0 ) )
           r2 = 0.25D+00 * r2 * x2 / ( k * ( k + v0 ) )
           sum = sum + a2 * r1 - a1 * r2
           wa = abs ( sum )
           if ( abs ( ( wa - ww ) / wa ) < 1.0D-15 ) then
              exit
           end if
           ww = wa
        end do

        bk0 = 0.5D+00 * pi * sum / sin ( piv )

     end if

  else

     cb = exp ( - x ) * sqrt ( 0.5D+00 * pi / x )
     sum = 1.0D+00
     r = 1.0D+00
     do k = 1, k0
        r = 0.125D+00 * r * ( vt - ( 2.0D+00 * k - 1.0D+00 ) ** 2 ) / ( k * x )
        sum = sum + r
     end do
     bk0 = cb * sum

  end if

  bk1 = ( 1.0D+00 / x - bi(1) * bk0 ) / bi(0)
  bk(0) = bk0
  bk(1) = bk1
  do k = 2, n
     bk2 = 2.0D+00 * ( v0 + k - 1.0D+00 ) / x * bk1 + bk0
     bk(k) = bk2
     bk0 = bk1
     bk1 = bk2
  end do

  dk(0) = v0 / x * bk(0) - bk(1)
  do k = 1, n
     dk(k) = - ( k + v0 ) / x * bk(k) - bk(k-1)
  end do

  vm = n + v0

  return
end subroutine ikv
subroutine incob ( a, b, x, bix )

  !*****************************************************************************80
  !
  !! INCOB computes the incomplete beta function Ix(a,b).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    22 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) A, B, parameters.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BIX, the function value.
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) b
  real ( kind = 8 ) bix
  real ( kind = 8 ) bt
  real ( kind = 8 ) dk(51)
  real ( kind = 8 ) fk(51)
  integer ( kind = 4 ) k
  real ( kind = 8 ) s0
  real ( kind = 8 ) t1
  real ( kind = 8 ) t2
  real ( kind = 8 ) ta
  real ( kind = 8 ) tb
  real ( kind = 8 ) x

  s0 = ( a + 1.0D+00 ) / ( a + b + 2.0D+00 )
  call betaf ( a, b, bt )

  if ( x <= s0 ) then

     do k = 1, 20
        dk(2*k) = k * ( b - k ) * x / &
             ( a + 2.0D+00 * k - 1.0D+00 ) / ( a + 2.0D+00 * k )
     end do

     do k = 0, 20
        dk(2*k+1) = - ( a + k ) * ( a + b + k ) * x &
             / ( a + 2.0D+00 * k ) / ( a + 2.0D+00 * k + 1.0D+00 )
     end do

     t1 = 0.0D+00
     do k = 20, 1, -1
        t1 = dk(k) / ( 1.0D+00 + t1 )
     end do
     ta = 1.0D+00 / ( 1.0D+00 + t1 )
     bix = x ** a * ( 1.0D+00 - x ) ** b / ( a * bt ) * ta

  else

     do k = 1, 20
        fk(2*k) = k * ( a - k ) * ( 1.0D+00 - x ) &
             / ( b + 2.0D+00 * k - 1.0D+00 ) / ( b + 2.0D+00 * k )
     end do

     do k = 0,20
        fk(2*k+1) = - ( b + k ) * ( a + b + k ) * ( 1.0D+00 - x ) &
             / ( b + 2.0D+00 * k ) / ( b + 2.0D+00 * k + 1.0D+00 )
     end do

     t2 = 0.0D+00
     do k = 20, 1, -1
        t2 = fk(k) / ( 1.0D+00 + t2 )
     end do
     tb = 1.0D+00 / ( 1.0D+00 + t2 )
     bix = 1.0D+00 - x ** a * ( 1.0D+00 - x ) ** b / ( b * bt ) * tb

  end if

  return
end subroutine incob
subroutine incog ( a, x, gin, gim, gip )

  !*****************************************************************************80
  !
  !! INCOG computes the incomplete gamma function r(a,x), Γ(a,x), P(a,x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    22 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) A, the parameter.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) GIN, GIM, GIP, the values of
  !    r(a,x), Γ(a,x), P(a,x).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) ga
  real ( kind = 8 ) gim
  real ( kind = 8 ) gin
  real ( kind = 8 ) gip
  integer ( kind = 4 ) k
  real ( kind = 8 ) r
  real ( kind = 8 ) s
  real ( kind = 8 ) t0
  real ( kind = 8 ) x
  real ( kind = 8 ) xam

  xam = -  x + a * log ( x )

  if ( 700.0D+00 < xam .or. 170.0D+00 < a ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'INCOG - Fatal error!'
     write ( *, '(a)' ) '  A and/or X is too large!'
     stop
  end if

  if ( x == 0.0D+00 ) then

     gin = 0.0D+00
     call gammaf ( a, ga )
     gim = ga
     gip = 0.0D+00

  else if ( x <= 1.0D+00 + a ) then

     s = 1.0D+00 / a
     r = s
     do k = 1, 60
        r = r * x / ( a + k )
        s = s + r
        if ( abs ( r / s ) < 1.0D-15 ) then
           exit
        end if
     end do

     gin = exp ( xam ) * s
     call gammaf ( a, ga )
     gip = gin / ga
     gim = ga - gin

  else if ( 1.0D+00 + a < x ) then

     t0 = 0.0D+00
     do k = 60, 1, -1
        t0 = ( k - a ) / ( 1.0D+00 + k / ( x + t0 ) )
     end do
     gim = exp ( xam ) / ( x + t0 )
     call gammaf ( a, ga )
     gin = ga - gim
     gip = 1.0D+00 - gim / ga

  end if

  return
end subroutine incog
subroutine itairy ( x, apt, bpt, ant, bnt )

  !****************************************************************************80
  !
  !! ITAIRY computes the integrals of Airy functions.
  !
  !  Discussion:
  !
  !    Compute the integrals of Airy functions with respect to t,
  !    from 0 and x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    19 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) APT, BPT, ANT, BNT, the integrals, from 0 to x,
  !    of Ai(t), Bi(t), Ai(-t), and Bi(-t).
  !       
  implicit none

  real ( kind = 8 ), save, dimension ( 16 ) :: a = (/ &
       0.569444444444444D+00, 0.891300154320988D+00, &
       0.226624344493027D+01, 0.798950124766861D+01, &
       0.360688546785343D+02, 0.198670292131169D+03, &
       0.129223456582211D+04, 0.969483869669600D+04, &
       0.824184704952483D+05, 0.783031092490225D+06, &
       0.822210493622814D+07, 0.945557399360556D+08, &
       0.118195595640730D+10, 0.159564653040121D+11, &
       0.231369166433050D+12, 0.358622522796969D+13 /)
  real ( kind = 8 ) ant
  real ( kind = 8 ) apt
  real ( kind = 8 ) bnt
  real ( kind = 8 ) bpt
  real ( kind = 8 ) c1
  real ( kind = 8 ) c2
  real ( kind = 8 ) eps
  real ( kind = 8 ) fx
  real ( kind = 8 ) gx
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  real ( kind = 8 ) pi
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) q2
  real ( kind = 8 ) r
  real ( kind = 8 ) sr3
  real ( kind = 8 ) su1
  real ( kind = 8 ) su2
  real ( kind = 8 ) su3
  real ( kind = 8 ) su4
  real ( kind = 8 ) su5
  real ( kind = 8 ) su6
  real ( kind = 8 ) x
  real ( kind = 8 ) xe
  real ( kind = 8 ) xp6
  real ( kind = 8 ) xr1
  real ( kind = 8 ) xr2

  eps = 1.0D-15
  pi = 3.141592653589793D+00
  c1 = 0.355028053887817D+00
  c2 = 0.258819403792807D+00
  sr3 = 1.732050807568877D+00

  if ( x == 0.0D+00 ) then

     apt = 0.0D+00
     bpt = 0.0D+00
     ant = 0.0D+00
     bnt = 0.0D+00

  else

     if ( abs ( x ) <= 9.25D+00 ) then

        do l = 0, 1

           x = ( -1.0D+00 ) ** l * x
           fx = x
           r = x

           do k = 1, 40
              r = r * ( 3.0D+00 * k - 2.0D+00 ) &
                   / ( 3.0D+00 * k + 1.0D+00 ) * x / ( 3.0D+00 * k ) &
                   * x / ( 3.0D+00 * k - 1.0D+00 ) * x 
              fx = fx + r
              if ( abs ( r ) < abs ( fx ) * eps ) then
                 exit
              end if
           end do

           gx = 0.5D+00 * x * x
           r = gx

           do k = 1, 40
              r = r * ( 3.0D+00 * k - 1.0D+00 ) &
                   / ( 3.0D+00 * k + 2.0D+00 ) * x / ( 3.0D+00 * k ) * x &
                   / ( 3.0D+00 * k + 1.0D+00 ) * x
              gx = gx + r
              if ( abs ( r ) < abs ( gx ) * eps ) then
                 exit
              end if
           end do

           ant = c1 * fx - c2 * gx
           bnt = sr3 * ( c1 * fx + c2 * gx )

           if ( l == 0 ) then
              apt = ant
              bpt = bnt
           else
              ant = -ant
              bnt = -bnt
              x = -x
           end if

        end do

     else

        q2 = 1.414213562373095D+00
        q0 = 0.3333333333333333D+00
        q1 = 0.6666666666666667D+00
        xe = x * sqrt ( x ) / 1.5D+00
        xp6 = 1.0D+00 / sqrt ( 6.0D+00 * pi * xe )
        su1 = 1.0D+00
        r = 1.0D+00
        xr1 = 1.0D+00 / xe
        do k = 1, 16
           r = - r * xr1
           su1 = su1 + a(k) * r
        end do
        su2 = 1.0D+00
        r = 1.0D+00
        do k = 1, 16
           r = r * xr1
           su2 = su2 + a(k) * r
        end do

        apt = q0 - exp ( - xe ) * xp6 * su1
        bpt = 2.0D+00 * exp ( xe ) * xp6 * su2
        su3 = 1.0D+00
        r = 1.0D+00
        xr2 = 1.0D+00 / ( xe * xe )
        do k = 1, 8
           r = - r * xr2
           su3 = su3 + a(2*k) * r
        end do
        su4 = a(1) * xr1
        r = xr1
        do k = 1, 7
           r = -r * xr2
           su4 = su4 + a(2*k+1) * r
        end do
        su5 = su3 + su4
        su6 = su3 - su4
        ant = q1 - q2 * xp6 * ( su5 * cos ( xe ) - su6 * sin ( xe ) )
        bnt = q2 * xp6 * ( su5 * sin ( xe ) + su6 * cos ( xe ) )

     end if

  end if

  return
end subroutine itairy
subroutine itika ( x, ti, tk )

  !*****************************************************************************80
  !
  !! ITIKA computes the integral of the modified Bessel functions I0(t) and K0(t).
  !
  !  Discussion:
  !
  !    This procedure integrates modified Bessel functions I0(t) and
  !    K0(t) with respect to t from 0 to x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    18 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) TI, TK, the integrals of I0(t) and K0(t)
  !    from 0 to X.
  !
  implicit none

  real ( kind = 8 ), save, dimension ( 10 ) :: a = (/ &
       0.625D+00,           1.0078125D+00, &
       2.5927734375D+00,    9.1868591308594D+00, &
       4.1567974090576D+01, 2.2919635891914D+02, &
       1.491504060477D+03,  1.1192354495579D+04, &
       9.515939374212D+04,  9.0412425769041D+05 /)
  real ( kind = 8 ) b1
  real ( kind = 8 ) b2
  real ( kind = 8 ) e0
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) rc1
  real ( kind = 8 ) rc2
  real ( kind = 8 ) rs
  real ( kind = 8 ) ti
  real ( kind = 8 ) tk
  real ( kind = 8 ) tw
  real ( kind = 8 ) x
  real ( kind = 8 ) x2

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00

  if ( x == 0.0D+00 ) then

     ti = 0.0D+00
     tk = 0.0D+00
     return

  else if ( x < 20.0D+00 ) then

     x2 = x * x
     ti = 1.0D+00
     r = 1.0D+00
     do k = 1, 50
        r = 0.25D+00 * r * ( 2 * k - 1.0D+00 ) / ( 2 * k + 1.0D+00 ) &
             / ( k * k ) * x2
        ti = ti + r
        if ( abs ( r / ti ) < 1.0D-12 ) then
           exit
        end if
     end do

     ti = ti * x

  else

     ti = 1.0D+00
     r = 1.0D+00
     do k = 1, 10
        r = r / x
        ti = ti + a(k) * r
     end do
     rc1 = 1.0D+00 / sqrt ( 2.0D+00 * pi * x )
     ti = rc1 * exp ( x ) * ti

  end if

  if ( x < 12.0D+00 ) then

     e0 = el + log ( x / 2.0D+00 )
     b1 = 1.0D+00 - e0
     b2 = 0.0D+00
     rs = 0.0D+00
     r = 1.0D+00
     do k = 1, 50
        r = 0.25D+00 * r * ( 2 * k - 1.0D+00 ) &
             / ( 2 * k + 1.0D+00 ) / ( k * k ) * x2
        b1 = b1 + r * ( 1.0D+00 / ( 2 * k + 1 ) - e0 )
        rs = rs + 1.0D+00 / k
        b2 = b2 + r * rs
        tk = b1 + b2
        if ( abs ( ( tk - tw ) / tk ) < 1.0D-12 ) then
           exit
        end if
        tw = tk
     end do

     tk = tk * x

  else

     tk = 1.0D+00
     r = 1.0D+00
     do k = 1, 10
        r = -r / x
        tk = tk + a(k) * r
     end do
     rc2 = sqrt ( pi / ( 2.0D+00 * x ) )
     tk = pi / 2.0D+00 - rc2 * tk * exp ( - x )

  end if

  return
end subroutine itika
subroutine itikb ( x, ti, tk )

  !*****************************************************************************80
  !
  !! ITIKB computes the integral of the Bessel functions I0(t) and K0(t).
  !
  !  Discussion:
  !
  !    This procedure integrates Bessel functions I0(t) and K0(t)
  !    with respect to t from 0 to x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    24 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  ! 
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) TI, TK, the integral of I0(t) and K0(t)
  !    from 0 to X.
  !
  implicit none

  real ( kind = 8 ) pi
  real ( kind = 8 ) t
  real ( kind = 8 ) t1
  real ( kind = 8 ) ti
  real ( kind = 8 ) tk
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00

  if ( x == 0.0D+00 ) then

     ti = 0.0D+00

  else if ( x < 5.0D+00 ) then

     t1 = x / 5.0D+00
     t = t1 * t1
     ti = (((((((( &
          0.59434D-03 * t &
          + 0.4500642D-02 ) * t &
          + 0.044686921D+00 ) * t &
          + 0.300704878D+00 ) * t &
          + 1.471860153D+00 ) * t &
          + 4.844024624D+00 ) * t &
          + 9.765629849D+00 ) * t &
          +10.416666367D+00 ) * t &
          + 5.0D+00 ) * t1

  else if ( 5.0D+00 <= x .and. x <= 8.0D+00 ) then

     t = 5.0D+00 / x
     ti = ((( &
          - 0.015166D+00 * t &
          - 0.0202292D+00 ) * t &
          + 0.1294122D+00 ) * t &
          - 0.0302912D+00 ) * t &
          + 0.4161224D+00
     ti = ti * exp ( x ) / sqrt ( x )

  else

     t = 8.0D+00 / x
     ti = ((((( &
          - 0.0073995D+00 * t &
          + 0.017744D+00 ) * t &
          - 0.0114858D+00 ) * t &
          + 0.55956D-02 ) * t &
          + 0.59191D-02 ) * t &
          + 0.0311734D+00 ) * t &
          + 0.3989423D+00
     ti = ti * exp ( x ) / sqrt ( x )

  end if

  if ( x == 0.0D+00 ) then

     tk = 0.0D+00

  else if ( x <= 2.0D+00 ) then

     t1 = x / 2.0D+00
     t = t1 * t1
     tk = (((((( &
          0.116D-05        * t &
          + 0.2069D-04 )     * t &
          + 0.62664D-03 )    * t &
          + 0.01110118D+00 ) * t &
          + 0.11227902D+00 ) * t &
          + 0.50407836D+00 ) * t &
          + 0.84556868D+00 ) * t1
     tk = tk - log ( x / 2.0D+00 ) * ti

  else if ( 2.0D+00 < x .and. x <= 4.0D+00 ) then

     t = 2.0D+00 / x
     tk = ((( &
          0.0160395D+00   * t &
          - 0.0781715D+00 ) * t &
          + 0.185984D+00 )  * t &
          - 0.3584641D+00 ) * t &
          + 1.2494934D+00
     tk = pi / 2.0D+00 - tk * exp ( - x ) / sqrt ( x )

  else if ( 4.0D+00 < x .and. x <= 7.0D+00 ) then

     t = 4.0D+00 / x
     tk = ((((( &
          0.37128D-02 * t &
          - 0.0158449D+00 ) * t &
          + 0.0320504D+00 ) * t &
          - 0.0481455D+00 ) * t &
          + 0.0787284D+00 ) * t &
          - 0.1958273D+00 ) * t &
          + 1.2533141D+00
     tk = pi / 2.0D+00 - tk * exp ( - x ) / sqrt ( x )

  else

     t = 7.0D+00 / x
     tk = ((((( &
          0.33934D-03      * t &
          - 0.163271D-02 )   * t &
          + 0.417454D-02 )   * t &
          - 0.933944D-02 )   * t &
          + 0.02576646D+00 ) * t &
          - 0.11190289D+00 ) * t &
          + 1.25331414D+00
     tk = pi / 2.0D+00 - tk * exp ( - x ) / sqrt ( x )

  end if

  return
end subroutine itikb
subroutine itjya ( x, tj, ty )

  !*****************************************************************************80
  !
  !! ITJYA computes integrals of Bessel functions J0(t) and Y0(t).
  !
  !  Discussion:
  !
  !    This procedure integrates Bessel functions J0(t) and Y0(t) with
  !    respect to t from 0 to x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    25 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) TJ, TY, the integrals of J0(t) and Y0(t) 
  !    from 0 to x.
  !
  implicit none

  real ( kind = 8 ) a(18)
  real ( kind = 8 ) a0
  real ( kind = 8 ) a1
  real ( kind = 8 ) af
  real ( kind = 8 ) bf
  real ( kind = 8 ) bg
  real ( kind = 8 ) el
  real ( kind = 8 ) eps
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) r2
  real ( kind = 8 ) rc
  real ( kind = 8 ) rs
  real ( kind = 8 ) tj
  real ( kind = 8 ) ty
  real ( kind = 8 ) ty1
  real ( kind = 8 ) ty2
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) xp

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00
  eps = 1.0D-12

  if ( x == 0.0D+00 ) then

     tj = 0.0D+00
     ty = 0.0D+00

  else if ( x <= 20.0D+00 ) then

     x2 = x * x
     tj = x
     r = x
     do k = 1, 60
        r = -0.25D+00 * r * ( 2 * k - 1.0D+00 ) / ( 2 * k + 1.0D+00 ) &
             / ( k * k ) * x2
        tj = tj + r
        if ( abs ( r ) < abs ( tj ) * eps ) then
           exit
        end if
     end do

     ty1 = ( el + log ( x / 2.0D+00 ) ) * tj
     rs = 0.0D+00
     ty2 = 1.0D+00
     r = 1.0D+00

     do k = 1, 60
        r = -0.25D+00 * r * ( 2 * k - 1.0D+00 ) / ( 2 * k + 1.0D+00 ) &
             / ( k * k ) * x2
        rs = rs + 1.0D+00 / k
        r2 = r * ( rs + 1.0D+00 / ( 2.0D+00 * k + 1.0D+00 ) )
        ty2 = ty2 + r2
        if ( abs ( r2 ) < abs ( ty2 ) * eps ) then
           exit
        end if
     end do

     ty = ( ty1 - x * ty2 ) * 2.0D+00 / pi

  else

     a0 = 1.0D+00
     a1 = 5.0D+00 / 8.0D+00
     a(1) = a1

     do k = 1, 16
        af = ( ( 1.5D+00 * ( k + 0.5D+00 ) * ( k + 5.0D+00 / 6.0D+00 ) &
             * a1 - 0.5D+00 * ( k + 0.5D+00 ) * ( k + 0.5D+00 )  &
             * ( k - 0.5D+00 ) * a0 ) ) / ( k + 1.0D+00 )
        a(k+1) = af
        a0 = a1
        a1 = af
     end do

     bf = 1.0D+00
     r = 1.0D+00
     do k = 1, 8
        r = -r / ( x * x )
        bf = bf + a(2*k) * r
     end do
     bg = a(1) / x
     r = 1.0D+00 / x
     do k = 1, 8
        r = -r / ( x * x )
        bg = bg + a(2*k+1) * r
     end do
     xp = x + 0.25D+00 * pi
     rc = sqrt ( 2.0D+00 / ( pi * x ) )
     tj = 1.0D+00 - rc * ( bf * cos ( xp ) + bg * sin ( xp ) )
     ty = rc * ( bg * cos ( xp ) - bf * sin ( xp ) )

  end if

  return
end subroutine itjya
subroutine itjyb ( x, tj, ty )

  !*****************************************************************************80
  !
  !! ITJYB computes integrals of Bessel functions J0(t) and Y0(t).
  !
  !  Discussion:
  !
  !    This procedure integrates Bessel functions J0(t) and Y0(t)
  !    with respect to t from 0 to x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    25 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) TJ, TY, the integrals of J0(t) and Y0(t) 
  !    from 0 to x.
  !
  implicit none

  real ( kind = 8 ) f0
  real ( kind = 8 ) g0
  real ( kind = 8 ) pi
  real ( kind = 8 ) t
  real ( kind = 8 ) tj
  real ( kind = 8 ) ty
  real ( kind = 8 ) x
  real ( kind = 8 ) x1
  real ( kind = 8 ) xt

  pi = 3.141592653589793D+00

  if ( x == 0.0D+00 ) then

     tj = 0.0D+00
     ty = 0.0D+00

  else if ( x <= 4.0D+00 ) then

     x1 = x / 4.0D+00
     t = x1 * x1

     tj = ((((((( &
          - 0.133718D-03      * t &
          + 0.2362211D-02 )   * t &
          - 0.025791036D+00 ) * t &
          + 0.197492634D+00 ) * t &
          - 1.015860606D+00 ) * t &
          + 3.199997842D+00 ) * t &
          - 5.333333161D+00 ) * t &
          + 4.0D+00 ) * x1

     ty = (((((((( &
          0.13351D-04       * t &
          - 0.235002D-03 )    * t &
          + 0.3034322d-02 )   * t &
          - 0.029600855D+00 ) * t &
          + 0.203380298D+00 ) * t &
          - 0.904755062D+00 ) * t &
          + 2.287317974D+00 ) * t &
          - 2.567250468D+00 ) * t &
          + 1.076611469D+00 ) * x1

     ty = 2.0D+00 / pi * log ( x / 2.0D+00 ) * tj - ty

  else if ( x <= 8.0D+00 ) then

     xt = x - 0.25D+00 * pi
     t = 16.0D+00 / ( x * x )

     f0 = (((((( &
          0.1496119D-02     * t &
          - 0.739083D-02 )    * t &
          + 0.016236617D+00 ) * t &
          - 0.022007499D+00 ) * t &
          + 0.023644978D+00 ) * t &
          - 0.031280848D+00 ) * t &
          + 0.124611058D+00 ) * 4.0D+00 / x

     g0 = ((((( &
          0.1076103D-02     * t &
          - 0.5434851D-02 )   * t &
          + 0.01242264D+00 )  * t &
          - 0.018255209D+00 ) * t &
          + 0.023664841D+00 ) * t &
          - 0.049635633D+00 ) * t &
          + 0.79784879D+00

     tj = 1.0D+00 - ( f0 * cos ( xt ) - g0 * sin ( xt ) ) / sqrt ( x )

     ty = - ( f0 * sin ( xt ) + g0 * cos ( xt ) ) / sqrt ( x )

  else

     t = 64.0D+00 / ( x * x )
     xt = x-0.25D+00 * pi

     f0 = ((((((( &
          - 0.268482D-04     * t &
          + 0.1270039D-03 )  * t &
          - 0.2755037D-03 )  * t &
          + 0.3992825D-03 )  * t &
          - 0.5366169D-03 )  * t &
          + 0.10089872D-02 ) * t &
          - 0.40403539D-02 ) * t &
          + 0.0623347304D+00 ) * 8.0D+00 / x

     g0 = (((((( &
          - 0.226238D-04        * t &
          + 0.1107299D-03 )     * t &
          - 0.2543955D-03 )     * t &
          + 0.4100676D-03 )     * t &
          - 0.6740148D-03 )     * t &
          + 0.17870944D-02 )    * t &
          - 0.01256424405D+00 ) * t &
          + 0.79788456D+00

     tj = 1.0D+00  - ( f0 * cos ( xt ) - g0 * sin ( xt ) ) / sqrt ( x )

     ty = - ( f0 * sin ( xt ) + g0 * cos ( xt ) ) / sqrt ( x )

  end if

  return
end subroutine itjyb
subroutine itsh0 ( x, th0 )

  !*****************************************************************************80
  !
  !! ITSH0 integrates the Struve function H0(t) from 0 to x.
  !
  !  Discussion:
  !
  !    This procedure evaluates the integral of Struve function
  !    H0(t) with respect to t from 0 and x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    25 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) TH0, the integral of H0(t) from 0 to x.
  !
  implicit none

  real ( kind = 8 ) a(25)
  real ( kind = 8 ) a0
  real ( kind = 8 ) a1
  real ( kind = 8 ) af
  real ( kind = 8 ) bf
  real ( kind = 8 ) bg
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) rd
  real ( kind = 8 ) s
  real ( kind = 8 ) s0
  real ( kind = 8 ) th0
  real ( kind = 8 ) ty
  real ( kind = 8 ) x
  real ( kind = 8 ) xp

  pi = 3.141592653589793D+00
  r = 1.0D+00            

  if ( x <= 30.0D+00 ) then

     s = 0.5D+00

     do k = 1, 100

        if ( k == 1 ) then
           rd = 0.5D+00
        else
           rd = 1.0D+00
        end if

        r = - r * rd * k / ( k + 1.0D+00 ) &
             * ( x / ( 2.0D+00 * k + 1.0D+00 ) ) ** 2
        s = s + r

        if ( abs ( r ) < abs ( s ) * 1.0D-12 ) then
           exit
        end if

     end do

     th0 = 2.0D+00 / pi * x * x * s

  else

     s = 1.0D+00
     do k = 1, 12
        r = - r * k / ( k + 1.0D+00 ) &
             * ( ( 2.0D+00 * k + 1.0D+00 ) / x ) ** 2
        s = s + r
        if ( abs ( r ) < abs ( s ) * 1.0D-12 ) then
           exit
        end if
     end do

     el = 0.57721566490153D+00
     s0 = s / ( pi * x * x ) + 2.0D+00 / pi &
          * ( log ( 2.0D+00 * x ) + el )
     a0 = 1.0D+00
     a1 = 5.0D+00 / 8.0D+00
     a(1) = a1
     do k = 1, 20
        af = ( ( 1.5D+00 * ( k + 0.5D+00 ) &
             * ( k + 5.0D+00 / 6.0D+00 ) * a1 - 0.5D+00 &
             * ( k + 0.5D+00 ) * ( k + 0.5D+00 ) &
             * ( k - 0.5D+00 ) * a0 ) ) / ( k + 1.0D+00 )
        a(k+1) = af
        a0 = a1
        a1 = af
     end do

     bf = 1.0D+00
     r = 1.0D+00
     do k = 1, 10
        r = - r / ( x * x )
        bf = bf + a(2*k) * r
     end do
     bg = a(1) / x
     r = 1.0D+00 / x
     do k = 1, 10
        r = - r / ( x * x ) 
        bg = bg + a(2*k+1) * r
     end do
     xp = x + 0.25D+00 * pi
     ty = sqrt ( 2.0D+00 / ( pi * x ) ) &
          * ( bg * cos ( xp ) - bf * sin ( xp ) )
     th0 = ty + s0

  end if

  return
end subroutine itsh0
subroutine itsl0 ( x, tl0 )

  !*****************************************************************************80
  !
  !! ITSL0 integrates the Struve function L0(t) from 0 to x.
  !
  !  Discussion:
  !
  !    This procedure evaluates the integral of modified Struve function
  !    L0(t) with respect to t from 0 to x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    31 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the upper limit of the integral.
  !
  !    Output, real ( kind = 8 ) TL0, the integral of L0(t) from 0 to x.
  !
  implicit none

  real ( kind = 8 ) a(18)
  real ( kind = 8 ) a0
  real ( kind = 8 ) a1
  real ( kind = 8 ) af
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) rd
  real ( kind = 8 ) s
  real ( kind = 8 ) s0
  real ( kind = 8 ) ti
  real ( kind = 8 ) tl0
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00
  r = 1.0D+00

  if ( x <= 20.0D+00 ) then

     s = 0.5D+00
     do k = 1, 100

        if ( k == 1 ) then
           rd = 0.5D+00
        else
           rd = 1.0D+00
        end if
        r = r * rd * k / ( k + 1.0D+00 ) &
             * ( x / ( 2.0D+00 * k + 1.0D+00 ) ) ** 2
        s = s + r
        if ( abs ( r / s ) < 1.0D-12 ) then
           exit
        end if
     end do

     tl0 = 2.0D+00 / pi * x * x * s

  else

     s = 1.0D+00
     do k = 1, 10
        r = r * k / ( k + 1.0D+00 ) &
             * ( ( 2.0D+00 * k + 1.0D+00 ) / x ) ** 2
        s = s + r
        if ( abs ( r / s ) < 1.0D-12 ) then
           exit
        end if
     end do

     el = 0.57721566490153D+00
     s0 = - s / ( pi * x * x ) + 2.0D+00 / pi &
          * ( log ( 2.0D+00 * x ) + el )
     a0 = 1.0D+00
     a1 = 5.0D+00 / 8.0D+00
     a(1) = a1
     do k = 1, 10
        af = ( ( 1.5D+00 * ( k + 0.50D+00 ) &
             * ( k + 5.0D+00 / 6.0D+00 ) * a1 - 0.5D+00 &
             * ( k + 0.5D+00 ) ** 2 * ( k -0.5D+00 ) * a0 ) ) &
             / ( k + 1.0D+00 )
        a(k+1) = af
        a0 = a1
        a1 = af
     end do

     ti = 1.0D+00
     r = 1.0D+00
     do k = 1, 11
        r = r / x
        ti = ti + a(k) * r
     end do
     tl0 = ti / sqrt ( 2.0D+00 * pi * x ) * exp ( x ) + s0

  end if

  return
end subroutine itsl0
subroutine itth0 ( x, tth )

  !*****************************************************************************80
  !
  !! ITTH0 integrates H0(t)/t from x to oo.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    23 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the lower limit of the integral.
  !
  !    Output, real ( kind = 8 ) TTH, the integral of H0(t)/t from x to oo.
  !
  implicit none

  real ( kind = 8 ) f0
  real ( kind = 8 ) g0
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) s
  real ( kind = 8 ) t
  real ( kind = 8 ) tth
  real ( kind = 8 ) tty
  real ( kind = 8 ) x
  real ( kind = 8 ) xt

  pi = 3.141592653589793D+00
  s = 1.0D+00
  r = 1.0D+00

  if ( x < 24.5D+00 ) then

     do k = 1, 60
        r = - r * x * x * ( 2.0D+00 * k - 1.0D+00 ) &
             / ( 2.0D+00 * k + 1.0D+00 ) ** 3
        s = s + r
        if ( abs ( r ) < abs ( s ) * 1.0D-12 ) then
           exit
        end if
     end do

     tth = pi / 2.0D+00 - 2.0D+00 / pi * x * s

  else

     do k = 1, 10
        r = - r * ( 2.0D+00 * k - 1.0D+00 ) ** 3 &
             / ( ( 2.0D+00 * k + 1.0D+00 ) * x * x )
        s = s + r
        if ( abs ( r ) < abs ( s ) * 1.0D-12 ) then
           exit
        end if
     end do

     tth = 2.0D+00 / ( pi * x ) * s
     t = 8.0D+00 / x
     xt = x + 0.25D+00 * pi
     f0 = ((((( &
          0.18118D-02 * t &
          - 0.91909D-02 ) * t &
          + 0.017033D+00 ) * t &
          - 0.9394D-03 ) * t &
          - 0.051445D+00 ) * t &
          - 0.11D-05 ) * t &
          + 0.7978846D+00
     g0 = ((((( &
          - 0.23731D-02 * t &
          + 0.59842D-02 ) * t &
          + 0.24437D-02 ) * t &
          - 0.0233178D+00 ) * t &
          + 0.595D-04 ) * t &
          + 0.1620695D+00 ) * t
     tty = ( f0 * sin ( xt ) - g0 * cos ( xt ) ) / ( sqrt ( x ) * x )
     tth = tth + tty

  end if

  return
end subroutine itth0
subroutine ittika ( x, tti, ttk )

  !*****************************************************************************80
  !
  !! ITTIKA integrates (I0(t)-1)/t from 0 to x, K0(t)/t from x to infinity.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    23 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the integral limit.
  !
  !    Output, real ( kind = 8 ) TTI, TTK, the integrals of [I0(t)-1]/t 
  !    from 0 to x, and of K0(t)/t from x to oo.
  !
  implicit none

  real ( kind = 8 ) b1
  real ( kind = 8 ), save, dimension ( 8 ) :: c = (/ &
       1.625D+00, 4.1328125D+00, &
       1.45380859375D+01, 6.553353881835D+01, &
       3.6066157150269D+02, 2.3448727161884D+03, &
       1.7588273098916D+04, 1.4950639538279D+05 /)
  real ( kind = 8 ) e0
  real ( kind = 8 ) el
  integer ( kind = 4 ) k
  real ( kind = 8 ) pi
  real ( kind = 8 ) r
  real ( kind = 8 ) r2
  real ( kind = 8 ) rc
  real ( kind = 8 ) rs
  real ( kind = 8 ) tti
  real ( kind = 8 ) ttk
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00

  if ( x == 0.0D+00 ) then
     tti = 0.0D+00
     ttk = 1.0D+300
     return
  end if

  if ( x < 40.0D+00 ) then
     tti = 1.0D+00
     r = 1.0D+00
     do k = 2, 50
        r = 0.25D+00 * r * ( k - 1.0D+00 ) / ( k * k * k ) * x * x
        tti = tti + r
        if ( abs ( r / tti ) < 1.0D-12 ) then
           exit
        end if
     end do

     tti = tti * 0.125D+00 * x * x

  else

     tti = 1.0D+00
     r = 1.0D+00
     do k = 1, 8
        r = r / x
        tti = tti + c(k) * r
     end do
     rc = x * sqrt ( 2.0D+00 * pi * x )
     tti = tti * exp ( x ) / rc

  end if

  if ( x <= 12.0D+00 ) then

     e0 = ( 0.5D+00 * log ( x / 2.0D+00 ) + el ) &
          * log ( x / 2.0D+00 ) + pi * pi / 24.0D+00 + 0.5D+00 * el * el
     b1 = 1.5D+00 - ( el + log ( x / 2.0D+00 ) )
     rs = 1.0D+00
     r = 1.0D+00
     do k = 2, 50
        r = 0.25D+00 * r * ( k - 1.0D+00 ) / ( k * k * k ) * x * x
        rs = rs + 1.0D+00 / k
        r2 = r * ( rs + 1.0D+00 / ( 2.0D+00 * k ) &
             - ( el + log ( x / 2.0D+00 ) ) )
        b1 = b1 + r2
        if ( abs ( r2 / b1 ) < 1.0D-12 ) then
           exit
        end if
     end do

     ttk = e0 - 0.125D+00 * x * x * b1

  else

     ttk = 1.0D+00
     r = 1.0D+00
     do k = 1, 8
        r = - r / x
        ttk = ttk + c(k) * r
     end do
     rc = x * sqrt ( 2.0D+00 / pi * x )
     ttk = ttk * exp ( - x ) / rc

  end if

  return
end subroutine ittika
subroutine ittikb ( x, tti, ttk )

  !*****************************************************************************80
  !
  !! ITTIKB integrates (I0(t)-1)/t from 0 to x, K0(t)/t from x to infinity.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    28 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the integral limit.
  !
  !    Output, real ( kind = 8 ) TTI, TTK, the integrals of
  !    [I0(t)-1]/t from 0 to x, and K0(t)/t from x to oo.
  !
  implicit none

  real ( kind = 8 ) e0
  real ( kind = 8 ) el
  real ( kind = 8 ) pi
  real ( kind = 8 ) t
  real ( kind = 8 ) t1
  real ( kind = 8 ) tti
  real ( kind = 8 ) ttk
  real ( kind = 8 ) x
  real ( kind = 8 ) x1

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00

  if ( x == 0.0D+00 ) then

     tti = 0.0D+00

  else if ( x <= 5.0D+00 ) then

     x1 = x / 5.0D+00
     t = x1 * x1
     tti = ((((((( &
          0.1263D-03       * t &
          + 0.96442D-03 )    * t &
          + 0.968217D-02 )   * t &
          + 0.06615507D+00 ) * t &
          + 0.33116853D+00 ) * t &
          + 1.13027241D+00 ) * t &
          + 2.44140746D+00 ) * t &
          + 3.12499991D+00 ) * t

  else

     t = 5.0D+00 / x
     tti = ((((((((( &
          2.1945464D+00   * t &
          -  3.5195009D+00 ) * t &
          - 11.9094395D+00 ) * t &
          + 40.394734D+00  ) * t &
          - 48.0524115D+00 ) * t &
          + 28.1221478D+00 ) * t &
          -  8.6556013D+00 ) * t &
          +  1.4780044D+00 ) * t &
          -  0.0493843D+00 ) * t &
          +  0.1332055D+00 ) * t &
          +  0.3989314D+00
     tti = tti * exp ( x ) / ( sqrt ( x ) * x )

  end if

  if ( x == 0.0D+00 ) then

     ttk = 1.0D+300

  else if ( x <= 2.0D+00 ) then

     t1 = x / 2.0D+00
     t = t1 * t1
     ttk = ((((( &
          0.77D-06         * t &
          + 0.1544D-04 )     * t &
          + 0.48077D-03 )    * t &
          + 0.925821D-02 )   * t &
          + 0.10937537D+00 ) * t &
          + 0.74999993D+00 ) * t
     e0 = el + log ( x / 2.0D+00 )
     ttk = pi * pi / 24.0D+00 + e0 * ( 0.5D+00 * e0 + tti ) - ttk

  else if ( x <= 4.0D+00 ) then

     t = 2.0D+00 / x
     ttk = ((( &
          0.06084D+00    * t &
          - 0.280367D+00 ) * t &
          + 0.590944D+00 ) * t &
          - 0.850013D+00 ) * t &
          + 1.234684D+00
     ttk = ttk * exp ( - x ) / ( sqrt ( x ) * x )

  else

     t = 4.0D+00 / x
     ttk = ((((( &
          0.02724D+00     * t &
          - 0.1110396D+00 ) * t &
          + 0.2060126D+00 ) * t &
          - 0.2621446D+00 ) * t &
          + 0.3219184D+00 ) * t &
          - 0.5091339D+00 ) * t &
          + 1.2533141D+00
     ttk = ttk * exp ( - x ) / ( sqrt ( x ) * x )

  end if

  return
end subroutine ittikb
subroutine ittjya ( x, ttj, tty )

  !*****************************************************************************80
  !
  !! ITTJYA integrates (1-J0(t))/t from 0 to x, and Y0(t)/t from x to infinity.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    28 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the integral limit.
  !
  !    Output, real ( kind = 8 ) TTJ, TTY, the integrals of [1-J0(t)]/t 
  !    from 0 to x and of Y0(t)/t from x to oo.
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) b1
  real ( kind = 8 ) bj0
  real ( kind = 8 ) bj1
  real ( kind = 8 ) by0
  real ( kind = 8 ) by1
  real ( kind = 8 ) e0
  real ( kind = 8 ) el
  real ( kind = 8 ) g0
  real ( kind = 8 ) g1
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  real ( kind = 8 ) pi
  real ( kind = 8 ) px
  real ( kind = 8 ) qx
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) r1
  real ( kind = 8 ) r2
  real ( kind = 8 ) rs
  real ( kind = 8 ) t
  real ( kind = 8 ) ttj
  real ( kind = 8 ) tty
  real ( kind = 8 ) vt
  real ( kind = 8 ) x
  real ( kind = 8 ) xk

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00

  if ( x == 0.0D+00 ) then

     ttj = 0.0D+00
     tty = -1.0D+300

  else if ( x <= 20.0D+00 ) then

     ttj = 1.0D+00
     r = 1.0D+00
     do k = 2, 100
        r = - 0.25D+00 * r * ( k - 1.0D+00 ) / ( k * k * k ) * x * x
        ttj = ttj + r
        if ( abs ( r ) < abs ( ttj ) * 1.0D-12 ) then
           exit
        end if
     end do

     ttj = ttj * 0.125D+00 * x * x
     e0 = 0.5D+00 * ( pi * pi / 6.0D+00 - el * el ) &
          - ( 0.5D+00 * log ( x / 2.0D+00 ) + el ) &
          * log ( x / 2.0D+00 )
     b1 = el + log ( x / 2.0D+00 ) - 1.5D+00
     rs = 1.0D+00
     r = -1.0D+00
     do k = 2, 100
        r = - 0.25D+00 * r * ( k - 1.0D+00 ) / ( k * k * k ) * x * x
        rs = rs + 1.0D+00 / k
        r2 = r * ( rs + 1.0D+00 / ( 2.0D+00 * k ) &
             - ( el + log ( x / 2.0D+00 ) ) ) 
        b1 = b1 + r2
        if ( abs ( r2 ) < abs ( b1 ) * 1.0D-12 ) then
           exit
        end if
     end do

     tty = 2.0D+00 / pi * ( e0 + 0.125D+00 * x * x * b1 )

  else

     a0 = sqrt ( 2.0D+00 / ( pi * x ) )

     do l = 0, 1

        vt = 4.0D+00 * l * l
        px = 1.0D+00
        r = 1.0D+00
        do k = 1, 14
           r = - 0.0078125D+00 * r &
                * ( vt - ( 4.0D+00 * k - 3.0D+00 ) ** 2 ) &
                / ( x * k ) * ( vt - ( 4.0D+00 * k - 1.0D+00 ) ** 2 ) &
                / ( ( 2.0D+00 * k - 1.0D+00 ) * x )
           px = px + r
           if ( abs ( r ) < abs ( px ) * 1.0D-12 ) then
              exit
           end if
        end do

        qx = 1.0D+00
        r = 1.0D+00
        do k = 1, 14
           r = -0.0078125D+00 * r &
                * ( vt - ( 4.0D+00 * k - 1.0D+00 ) ** 2 ) &
                / ( x * k ) * ( vt - ( 4.0D+00 * k + 1.0D+00 ) ** 2 ) &
                / ( 2.0D+00 * k + 1.0D+00 ) / x
           qx = qx + r
           if ( abs ( r ) < abs ( qx ) * 1.0D-12 ) then
              exit
           end if
        end do

        qx = 0.125D+00 * ( vt - 1.0D+00 ) / x * qx
        xk = x - ( 0.25D+00 + 0.5D+00 * l ) * pi
        bj1 = a0 * ( px * cos ( xk ) - qx * sin ( xk ) )
        by1 = a0 * ( px * sin ( xk ) + qx * cos ( xk ) )
        if ( l == 0 ) then
           bj0 = bj1
           by0 = by1
        end if

     end do

     t = 2.0D+00 / x
     g0 = 1.0D+00
     r0 = 1.0D+00
     do k = 1, 10
        r0 = - k * k * t * t *r0
        g0 = g0 + r0
     end do

     g1 = 1.0D+00
     r1 = 1.0D+00
     do k = 1, 10
        r1 = - k * ( k + 1.0D+00 ) * t * t * r1
        g1 = g1 + r1
     end do

     ttj = 2.0D+00 * g1 * bj0 / ( x * x ) - g0 * bj1 / x &
          + el + log ( x / 2.0D+00 )
     tty = 2.0D+00 * g1 * by0 / ( x * x ) - g0 * by1 / x

  end if

  return
end subroutine ittjya
subroutine ittjyb ( x, ttj, tty )

  !*****************************************************************************80
  !
  !! ITTJYB integrates (1-J0(t))/t from 0 to x, and Y0(t)/t from x to infinity.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    01 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the integral limit.
  !
  !    Output, real ( kind = 8 ) TTJ, TTY, the integrals of [1-J0(t)]/t 
  !    from 0 to x and of Y0(t)/t from x to oo.
  !
  implicit none

  real ( kind = 8 ) e0
  real ( kind = 8 ) el
  real ( kind = 8 ) f0
  real ( kind = 8 ) g0
  real ( kind = 8 ) pi
  real ( kind = 8 ) t
  real ( kind = 8 ) t1
  real ( kind = 8 ) ttj
  real ( kind = 8 ) tty
  real ( kind = 8 ) x
  real ( kind = 8 ) x1
  real ( kind = 8 ) xt

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00

  if ( x == 0.0D+00 ) then

     ttj = 0.0D+00
     tty = -1.0D+300

  else if ( x <= 4.0D+00 ) then

     x1 = x / 4.0D+00
     t = x1 * x1

     ttj = (((((( &
          0.35817D-04 * t &
          - 0.639765D-03 ) * t &
          + 0.7092535D-02 ) * t &
          - 0.055544803D+00 ) * t &
          + 0.296292677D+00 ) * t &
          - 0.999999326D+00 ) * t &
          + 1.999999936D+00 ) * t

     tty = ((((((( &
          - 0.3546D-05        * t &
          + 0.76217D-04 )     * t &
          - 0.1059499D-02 )   * t &
          + 0.010787555D+00 ) * t &
          - 0.07810271D+00 )  * t &
          + 0.377255736D+00 ) * t &
          - 1.114084491D+00 ) * t &
          + 1.909859297D+00 ) * t

     e0 = el + log ( x / 2.0D+00 )
     tty = pi / 6.0D+00 + e0 / pi * ( 2.0D+00 * ttj - e0 ) - tty

  else if ( x <= 8.0D+00 ) then

     xt = x + 0.25D+00 * pi
     t1 = 4.0D+00 / x
     t = t1 * t1

     f0 = ((((( &
          0.0145369D+00 * t &
          - 0.0666297D+00 ) * t &
          + 0.1341551D+00 ) * t &
          - 0.1647797D+00 ) * t &
          + 0.1608874D+00 ) * t &
          - 0.2021547D+00 ) * t &
          + 0.7977506D+00

     g0 = (((((( &
          0.0160672D+00   * t &
          - 0.0759339D+00 ) * t &
          + 0.1576116D+00 ) * t &
          - 0.1960154D+00 ) * t &
          + 0.1797457D+00 ) * t &
          - 0.1702778D+00 ) * t &
          + 0.3235819D+00 ) * t1

     ttj = ( f0 * cos ( xt ) + g0 * sin ( xt ) ) / ( sqrt ( x ) * x )
     ttj = ttj + el + log ( x / 2.0D+00 )
     tty = ( f0 * sin ( xt ) - g0 * cos ( xt ) ) / ( sqrt ( x ) * x )

  else

     t = 8.0D+00 / x
     xt = x + 0.25D+00 * pi

     f0 = ((((( &
          0.18118D-02    * t &
          - 0.91909D-02 )  * t &
          + 0.017033D+00 ) * t &
          - 0.9394D-03 )   * t &
          - 0.051445D+00 ) * t &
          - 0.11D-05 )     * t &
          + 0.7978846D+00

     g0 = ((((( &
          - 0.23731D-02     * t &
          + 0.59842D-02 )   * t &
          + 0.24437D-02 )   * t &
          - 0.0233178D+00 ) * t &
          + 0.595D-04 )     * t &
          + 0.1620695D+00 ) * t

     ttj = ( f0 * cos ( xt ) + g0 * sin ( xt ) )  &
          / ( sqrt ( x ) * x ) + el + log ( x / 2.0D+00 )
     tty = ( f0 * sin ( xt ) - g0 * cos ( xt ) )  &
          / ( sqrt ( x ) * x )

  end if

  return
end subroutine ittjyb
subroutine jdzo ( nt, n, m, p, zo )

  !*****************************************************************************80
  !
  !! JDZO computes the zeros of Bessel functions Jn(x) and Jn'(x).
  !
  !  Discussion:
  !
  !    This procedure computes the zeros of Bessel functions Jn(x) and
  !    Jn'(x), and arrange them in the order of their magnitudes.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    01 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) NT, the number of zeros.
  !
  !    Output, integer ( kind = 4 ) N(*), the  order of Jn(x) or Jn'(x) associated
  !    with the L-th zero.
  !
  !    Output, integer ( kind = 4 ) M(*), the serial number of the zeros of Jn(x)
  !    or Jn'(x) associated with the L-th zero ( L is the serial number of all the
  !    zeros of Jn(x) and Jn'(x) ).
  !
  !    Output, character ( len = 4 ) P(L), 'TM' or 'TE', a code for designating 
  !    the zeros of Jn(x)  or Jn'(x).  In the waveguide applications, the zeros
  !    of Jn(x) correspond to TM modes and those of Jn'(x) correspond to TE modes.
  !
  !    Output, real ( kind = 8 ) ZO(*), the zeros of Jn(x) and Jn'(x).
  !
  implicit none

  real ( kind = 8 ) bj(101)
  real ( kind = 8 ) dj(101)
  real ( kind = 8 ) fj(101)
  integer ( kind = 4 ) i
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  integer ( kind = 4 ) l0
  integer ( kind = 4 ) l1
  integer ( kind = 4 ) l2
  integer ( kind = 4 ) m(1400)
  integer ( kind = 4 ) m1(70)
  integer ( kind = 4 ) mm
  integer ( kind = 4 ) n(1400)
  integer ( kind = 4 ) n1(70)
  integer ( kind = 4 ) nm
  integer ( kind = 4 ) nt
  character ( len = 4 ) p(1400)
  character ( len = 4 ) p1(70)
  real ( kind = 8 ) x
  real ( kind = 8 ) x0
  real ( kind = 8 ) x1
  real ( kind = 8 ) x2
  real ( kind = 8 ) xm
  real ( kind = 8 ) zo(1400)
  real ( kind = 8 ) zoc(70)

  if ( nt < 600 ) then
     xm = -1.0D+00 + 2.248485D+00 * real ( nt, kind = 8 ) ** 0.5D+00 &
          - 0.0159382D+00 * nt + 3.208775D-04 * real ( nt, kind = 8 ) ** 1.5D+00
     nm = int ( 14.5D+00 + 0.05875D+00 * nt )
     mm = int ( 0.02D+00 * nt ) + 6
  else
     xm = 5.0D+00 + 1.445389D+00 * ( real ( nt, kind = 8 ) ) ** 0.5D+00 &
          + 0.01889876D+00 * nt &
          - 2.147763D-04 * ( real ( nt, kind = 8 ) ) ** 1.5D+00
     nm = int ( 27.8D+00 + 0.0327D+00 * nt )
     mm = int ( 0.01088D+00 * nt ) + 10
  end if

  l0 = 0

  do i = 1,nm

     x1 = 0.407658D+00 + 0.4795504D+00 &
          * ( real ( i - 1, kind = 8 ) ) ** 0.5D+00 + 0.983618D+00 * ( i - 1 )
     x2 = 1.99535D+00 + 0.8333883 * ( real ( i - 1, kind = 8 ) ) ** 0.5D+00 &
          + 0.984584D+00 * ( i - 1 )
     l1 = 0

     do j = 1, mm

        if ( i == 1 .and. j == 1 ) then

           l1 = l1 + 1
           n1(l1) = i - 1
           m1(l1) = j
           if ( i == 1 ) then
              m1(l1) = j - 1
           end if
           p1(l1) = 'TE'
           zoc(l1) = x

           if ( i <= 15 ) then
              x1 = x + 3.057D+00 + 0.0122D+00 * ( i - 1 ) &
                   + ( 1.555D+00 + 0.41575D+00 * ( i - 1 ) ) / ( j + 1 ) ** 2
           else
              x1 = x + 2.918D+00 + 0.01924D+00 * ( i - 1 ) &
                   + ( 6.26D+00 + 0.13205D+00 * ( i - 1 ) ) / ( j + 1 ) ** 2
           end if

        else

           x = x1

           do

              call bjndd ( i, x, bj, dj, fj )
              x0 = x
              x = x - dj(i) / fj(i)

              if ( xm < x1 ) then
                 exit
              end if

              if ( abs ( x - x0 ) <= 1.0D-10 ) then
                 l1 = l1 + 1
                 n1(l1) = i - 1
                 m1(l1) = j
                 if ( i == 1 ) then
                    m1(l1) = j - 1
                 end if
                 p1(l1) = 'TE'
                 zoc(l1) = x

                 if ( i <= 15 ) then
                    x1 = x + 3.057D+00 + 0.0122D+00 * ( i - 1 ) &
                         + ( 1.555D+00 + 0.41575D+00 * ( i - 1 ) ) / ( j + 1 ) ** 2
                 else
                    x1 = x + 2.918D+00 + 0.01924D+00 * ( i - 1 ) &
                         + ( 6.26D+00 + 0.13205D+00 * ( i - 1 ) ) / ( j + 1 ) ** 2
                 end if
                 exit
              end if

           end do

        end if

        x = x2

        do

           call bjndd ( i, x, bj, dj, fj )
           x0 = x
           x = x - bj(i) / dj(i)

           if ( xm < x ) then
              exit
           end if

           if ( abs ( x - x0 ) <= 1.0D-10 ) then
              exit
           end if

        end do

        if ( x <= xm ) then

           l1 = l1 + 1
           n1(l1) = i - 1
           m1(l1) = j
           p1(l1) = 'TM'
           zoc(l1) = x
           if ( i <= 15 ) then
              x2 = x + 3.11D+00 + 0.0138D+00 * ( i - 1 ) &
                   + ( 0.04832D+00 + 0.2804D+00 * ( i - 1 ) ) / ( j + 1 ) ** 2
           else
              x2 = x + 3.001D+00 + 0.0105D+00 * ( i - 1 ) &
                   + ( 11.52D+00 + 0.48525D+00 * ( i - 1 ) ) / ( j + 3 ) ** 2
           end if

        end if

     end do

     l = l0 + l1
     l2 = l

     do

        if ( l0 == 0 ) then
           do k = 1, l
              zo(k) = zoc(k)
              n(k) = n1(k)
              m(k) = m1(k)
              p(k) = p1(k)
           end do
           l1 = 0
        else if ( l0 /= 0 ) then
           if ( zoc(l1) .le. zo(l0) ) then
              zo(l0+l1) = zo(l0)
              n(l0+l1) = n(l0)
              m(l0+l1) = m(l0)
              p(l0+l1) = p(l0)
              l0 = l0 - 1
           else
              zo(l0+l1) = zoc(l1)
              n(l0+l1) = n1(l1)
              m(l0+l1) = m1(l1)
              p(l0+l1) = p1(l1)
              l1 = l1 - 1
           end if
        end if

        if ( l1 == 0 ) then
           exit 
        end if

     end do

     l0 = l2

  end do

  return
end subroutine jdzo
subroutine jelp ( u, hk, esn, ecn, edn, eph )

  !*****************************************************************************80
  !
  !! JELP computes Jacobian elliptic functions SN(u), CN(u), DN(u).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    08 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) U, the argument.
  !
  !    Input, real ( kind = 8 ) HK, the modulus, between 0 and 1.
  !
  !    Output, real ( kind = 8 ) ESN, ECN, EDN, EPH, the values of
  !    sn(u), cn(u), dn(u), and phi (in degrees).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) a0
  real ( kind = 8 ) b
  real ( kind = 8 ) b0
  real ( kind = 8 ) c
  real ( kind = 8 ) d
  real ( kind = 8 ) dn
  real ( kind = 8 ) ecn
  real ( kind = 8 ) edn
  real ( kind = 8 ) eph
  real ( kind = 8 ) esn
  real ( kind = 8 ) hk
  integer ( kind = 4 ) j
  integer ( kind = 4 ) n 
  real ( kind = 8 ) pi
  real ( kind = 8 ) r(40)
  real ( kind = 8 ) sa
  real ( kind = 8 ) t
  real ( kind = 8 ) u

  pi = 3.14159265358979D+00
  a0 = 1.0D+00
  b0 = sqrt ( 1.0D+00 - hk * hk )

  do n = 1, 40

     a = ( a0 + b0 ) / 2.0D+00
     b = sqrt ( a0 * b0 )
     c = ( a0 - b0 ) / 2.0D+00
     r(n) = c / a

     if ( c < 1.0D-07 ) then
        exit
     end if

     a0 = a
     b0 = b

  end do

  dn = 2.0D+00 ** n * a * u

  do j = n, 1, -1
     t = r(j) * sin ( dn )
     sa = atan ( t / sqrt ( abs ( 1.0D+00 - t * t )))
     d = 0.5D+00 * ( dn + sa )
     dn = d
  end do

  eph = d * 180.0D+00 / pi
  esn = sin ( d )
  ecn = cos ( d )
  edn = sqrt ( 1.0D+00 - hk * hk * esn * esn )

  return
end subroutine jelp
subroutine jy01a ( x, bj0, dj0, bj1, dj1, by0, dy0, by1, dy1 )

  !*****************************************************************************80
  !
  !! JY01A computes Bessel functions J0(x), J1(x), Y0(x), Y1(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    01 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BJ0, DJ0, BJ1, DJ1, BY0, DY0, BY1, DY1,
  !    the values of J0(x), J0'(x), J1(x), J1'(x), Y0(x), Y0'(x), Y1(x), Y1'(x).
  !
  implicit none

  real ( kind = 8 ), save, dimension(12) :: a = (/ &
       -0.7031250000000000D-01, 0.1121520996093750D+00, &
       -0.5725014209747314D+00, 0.6074042001273483D+01, &
       -0.1100171402692467D+03, 0.3038090510922384D+04, &
       -0.1188384262567832D+06, 0.6252951493434797D+07, &
       -0.4259392165047669D+09, 0.3646840080706556D+11, &
       -0.3833534661393944D+13, 0.4854014686852901D+15 /)
  real ( kind = 8 ), save, dimension(12) :: a1 = (/ &
       0.1171875000000000D+00, -0.1441955566406250D+00, &
       0.6765925884246826D+00, -0.6883914268109947D+01, &
       0.1215978918765359D+03, -0.3302272294480852D+04, &
       0.1276412726461746D+06, -0.6656367718817688D+07, &
       0.4502786003050393D+09, -0.3833857520742790D+11, &
       0.4011838599133198D+13, -0.5060568503314727D+15 /)
  real ( kind = 8 ), save, dimension(12) :: b = (/ &
       0.7324218750000000D-01, -0.2271080017089844D+00, &
       0.1727727502584457D+01, -0.2438052969955606D+02, &
       0.5513358961220206D+03, -0.1825775547429318D+05, &
       0.8328593040162893D+06, -0.5006958953198893D+08, &
       0.3836255180230433D+10, -0.3649010818849833D+12, &
       0.4218971570284096D+14, -0.5827244631566907D+16 /)
  real ( kind = 8 ), save, dimension(12) :: b1 = (/ &
       -0.1025390625000000D+00, 0.2775764465332031D+00, &
       -0.1993531733751297D+01, 0.2724882731126854D+02, &
       -0.6038440767050702D+03, 0.1971837591223663D+05, &
       -0.8902978767070678D+06, 0.5310411010968522D+08, &
       -0.4043620325107754D+10, 0.3827011346598605D+12, &
       -0.4406481417852278D+14, 0.6065091351222699D+16 /)
  real ( kind = 8 ) bj0
  real ( kind = 8 ) bj1
  real ( kind = 8 ) by0
  real ( kind = 8 ) by1
  real ( kind = 8 ) cs0
  real ( kind = 8 ) cs1
  real ( kind = 8 ) cu
  real ( kind = 8 ) dj0
  real ( kind = 8 ) dj1
  real ( kind = 8 ) dy0
  real ( kind = 8 ) dy1
  real ( kind = 8 ) ec
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  real ( kind = 8 ) p0
  real ( kind = 8 ) p1
  real ( kind = 8 ) pi
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) r1
  real ( kind = 8 ) rp2
  real ( kind = 8 ) t1
  real ( kind = 8 ) t2
  real ( kind = 8 ) w0
  real ( kind = 8 ) w1
  real ( kind = 8 ) x
  real ( kind = 8 ) x2

  pi = 3.141592653589793D+00
  rp2 = 0.63661977236758D+00
  x2 = x * x

  if ( x == 0.0D+00 ) then
     bj0 = 1.0D+00
     bj1 = 0.0D+00
     dj0 = 0.0D+00
     dj1 = 0.5D+00
     by0 = -1.0D+300
     by1 = -1.0D+300
     dy0 = 1.0D+300
     dy1 = 1.0D+300
     return
  end if

  if ( x <= 12.0D+00 ) then

     bj0 = 1.0D+00
     r = 1.0D+00
     do k = 1,30
        r = -0.25D+00 * r * x2 / ( k * k )
        bj0 = bj0 + r
        if ( abs ( r ) < abs ( bj0 ) * 1.0D-15 ) then
           exit
        end if
     end do

     bj1 = 1.0D+00
     r = 1.0D+00
     do k = 1, 30
        r = -0.25D+00 * r * x2 / ( k * ( k + 1.0D+00 ) )
        bj1 = bj1 + r
        if ( abs ( r ) < abs ( bj1 ) * 1.0D-15 ) then
           exit
        end if
     end do

     bj1 = 0.5D+00 * x * bj1
     ec = log ( x / 2.0D+00 ) + 0.5772156649015329D+00
     cs0 = 0.0D+00
     w0 = 0.0D+00
     r0 = 1.0D+00
     do k = 1, 30
        w0 = w0 + 1.0D+00 / k
        r0 = -0.25D+00 * r0 / ( k * k ) * x2
        r = r0 * w0
        cs0 = cs0 + r
        if ( abs ( r ) < abs ( cs0 ) * 1.0D-15 ) then
           exit
        end if
     end do

     by0 = rp2 * ( ec * bj0 - cs0 )
     cs1 = 1.0D+00
     w1 = 0.0D+00
     r1 = 1.0D+00
     do k = 1, 30
        w1 = w1 + 1.0D+00 / k
        r1 = -0.25D+00 * r1 / ( k * ( k + 1 ) ) * x2
        r = r1 * ( 2.0D+00 * w1 + 1.0D+00 / ( k + 1.0D+00 ) )
        cs1 = cs1 + r
        if ( abs ( r ) < abs ( cs1 ) * 1.0D-15 ) then
           exit
        end if
     end do

     by1 = rp2 * ( ec * bj1 - 1.0D+00 / x - 0.25D+00 * x * cs1 )

  else

     if ( x < 35.0D+00 ) then
        k0 = 12
     else if ( x < 50.0D+00 ) then
        k0 = 10
     else
        k0 = 8
     end if

     t1 = x - 0.25D+00 * pi
     p0 = 1.0D+00
     q0 = -0.125D+00 / x
     do k = 1, k0
        p0 = p0 + a(k) * x ** ( - 2 * k )
        q0 = q0 + b(k) * x ** ( - 2 * k - 1 )
     end do
     cu = sqrt ( rp2 / x )
     bj0 = cu * ( p0 * cos ( t1 ) - q0 * sin ( t1 ) )
     by0 = cu * ( p0 * sin ( t1 ) + q0 * cos ( t1 ) )
     t2 = x - 0.75D+00 * pi
     p1 = 1.0D+00
     q1 = 0.375D+00 / x
     do k = 1, k0
        p1 = p1 + a1(k) * x ** ( - 2 * k )
        q1 = q1 + b1(k) * x ** ( - 2 * k - 1 )
     end do
     cu = sqrt ( rp2 / x )
     bj1 = cu * ( p1 * cos ( t2 ) - q1 * sin ( t2 ) )
     by1 = cu * ( p1 * sin ( t2 ) + q1 * cos ( t2 ) )

  end if

  dj0 = - bj1
  dj1 = bj0 - bj1 / x
  dy0 = - by1
  dy1 = by0 - by1 / x

  return
end subroutine jy01a
subroutine jy01b ( x, bj0, dj0, bj1, dj1, by0, dy0, by1, dy1 )

  !*****************************************************************************80
  !
  !! JY01B computes Bessel functions J0(x), J1(x), Y0(x), Y1(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    02 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BJ0, DJ0, BJ1, DJ1, BY0, DY0, BY1, DY1,
  !    the values of J0(x), J0'(x), J1(x), J1'(x), Y0(x), Y0'(x), Y1(x), Y1'(x).
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) bj0
  real ( kind = 8 ) bj1
  real ( kind = 8 ) by0
  real ( kind = 8 ) by1
  real ( kind = 8 ) dj0
  real ( kind = 8 ) dj1
  real ( kind = 8 ) dy0
  real ( kind = 8 ) dy1
  real ( kind = 8 ) p0
  real ( kind = 8 ) p1
  real ( kind = 8 ) pi
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) t
  real ( kind = 8 ) t2
  real ( kind = 8 ) ta0
  real ( kind = 8 ) ta1
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00

  if ( x == 0.0D+00 ) then

     bj0 = 1.0D+00
     bj1 = 0.0D+00
     dj0 = 0.0D+00
     dj1 = 0.5D+00
     by0 = -1.0D+300
     by1 = -1.0D+300
     dy0 = 1.0D+300
     dy1 = 1.0D+300
     return

  else if ( x <= 4.0D+00 ) then

     t = x / 4.0D+00
     t2 = t * t

     bj0 = (((((( &
          - 0.5014415D-03 * t2 &
          + 0.76771853D-02 ) * t2 &
          - 0.0709253492D+00 ) * t2 &
          + 0.4443584263D+00 ) * t2 &
          - 1.7777560599D+00 ) * t2 &
          + 3.9999973021D+00 ) * t2 &
          - 3.9999998721D+00 ) * t2 &
          + 1.0D+00

     bj1 = t * ((((((( &
          - 0.1289769D-03 * t2 &
          + 0.22069155D-02 ) * t2 &
          - 0.0236616773D+00 ) * t2 &
          + 0.1777582922D+00 ) * t2 &
          - 0.8888839649D+00 ) * t2 &
          + 2.6666660544D+00 ) * t2 &
          - 3.9999999710D+00 ) * t2 &
          + 1.9999999998D+00 )

     by0 = ((((((( &
          - 0.567433D-04 * t2 &
          + 0.859977D-03 ) * t2 &
          - 0.94855882D-02 ) * t2 &
          + 0.0772975809D+00 ) * t2 &
          - 0.4261737419D+00 ) * t2 &
          + 1.4216421221D+00 ) * t2 &
          - 2.3498519931D+00 ) * t2 &
          + 1.0766115157D+00 ) * t2 &
          + 0.3674669052D+00

     by0 = 2.0D+00 / pi * log ( x / 2.0D+00 ) * bj0 + by0

     by1 = (((((((( &
          0.6535773D-03 * t2 &
          - 0.0108175626D+00 ) * t2 &
          + 0.107657606D+00 ) * t2 &
          - 0.7268945577D+00 ) * t2 &
          + 3.1261399273D+00 ) * t2 &
          - 7.3980241381D+00 ) * t2 &
          + 6.8529236342D+00 ) * t2 &
          + 0.3932562018D+00 ) * t2 &
          - 0.6366197726D+00 ) / x

     by1 = 2.0D+00 / pi * log ( x / 2.0D+00 ) * bj1 + by1

  else

     t = 4.0D+00 / x
     t2 = t * t
     a0 = sqrt ( 2.0D+00 / ( pi * x ) )

     p0 = (((( &
          - 0.9285D-05 * t2 &
          + 0.43506D-04 ) * t2 &
          - 0.122226D-03 ) * t2 &
          + 0.434725D-03 ) * t2 &
          - 0.4394275D-02 ) * t2 &
          + 0.999999997D+00

     q0 = t * ((((( &
          0.8099D-05 * t2 &
          - 0.35614D-04 ) * t2 &
          + 0.85844D-04 ) * t2 &
          - 0.218024D-03 ) * t2 &
          + 0.1144106D-02 ) * t2 &
          - 0.031249995D+00 )

     ta0 = x - 0.25D+00 * pi
     bj0 = a0 * ( p0 * cos ( ta0 ) - q0 * sin ( ta0 ) )
     by0 = a0 * ( p0 * sin ( ta0 ) + q0 * cos ( ta0 ) )

     p1 = (((( &
          0.10632D-04 * t2 &
          - 0.50363D-04 ) * t2 &
          + 0.145575D-03 ) * t2 &
          - 0.559487D-03 ) * t2 &
          + 0.7323931D-02 ) * t2 &
          + 1.000000004D+00

     q1 = t * ((((( &
          - 0.9173D-05      * t2 &
          + 0.40658D-04 )   * t2 &
          - 0.99941D-04 )   * t2 &
          + 0.266891D-03 )  * t2 &
          - 0.1601836D-02 ) * t2 &
          + 0.093749994D+00 )

     ta1 = x - 0.75D+00 * pi
     bj1 = a0 * ( p1 * cos ( ta1 ) - q1 * sin ( ta1 ) )
     by1 = a0 * ( p1 * sin ( ta1 ) + q1 * cos ( ta1 ) )

  end if

  dj0 = - bj1
  dj1 = bj0 - bj1 / x
  dy0 = - by1
  dy1 = by0 - by1 / x

  return
end subroutine jy01b
subroutine jyna ( n, x, nm, bj, dj, by, dy )

  !*****************************************************************************80
  !
  !! JYNA computes Bessel functions Jn(x) and Yn(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    29 April 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BJ(0:N), DJ(0:N), BY(0:N), DY(0:N), the values
  !    of Jn(x), Jn'(x), Yn(x), Yn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) bj(0:n)
  real ( kind = 8 ) bj0
  real ( kind = 8 ) bj1
  real ( kind = 8 ) bjk
  real ( kind = 8 ) by(0:n)
  real ( kind = 8 ) by0
  real ( kind = 8 ) by1
  real ( kind = 8 ) cs
  real ( kind = 8 ) dj(0:n)
  real ( kind = 8 ) dj0
  real ( kind = 8 ) dj1
  real ( kind = 8 ) dy(0:n)
  real ( kind = 8 ) dy0
  real ( kind = 8 ) dy1
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  real ( kind = 8 ) x

  nm = n

  if ( x < 1.0D-100 ) then

     do k = 0, n
        bj(k) = 0.0D+00
        dj(k) = 0.0D+00
        by(k) = -1.0D+300
        dy(k) = 1.0D+300
     end do
     bj(0) = 1.0D+00
     dj(1) = 0.5D+00
     return

  end if

  call jy01b ( x, bj0, dj0, bj1, dj1, by0, dy0, by1, dy1 )
  bj(0) = bj0
  bj(1) = bj1
  by(0) = by0
  by(1) = by1
  dj(0) = dj0
  dj(1) = dj1
  dy(0) = dy0
  dy(1) = dy1

  if ( n <= 1 ) then
     return
  end if

  if ( n < int ( 0.9D+00 * x) ) then

     do k = 2, n
        bjk = 2.0D+00 * ( k - 1.0D+00 ) / x * bj1 - bj0
        bj(k) = bjk
        bj0 = bj1
        bj1 = bjk
     end do

  else

     m = msta1 ( x, 200 )

     if ( m < n ) then
        nm = m
     else
        m = msta2 ( x, n, 15 )
     end if

     f2 = 0.0D+00
     f1 = 1.0D-100
     do k = m, 0, -1
        f = 2.0D+00 * ( k + 1.0D+00 ) / x * f1 - f2
        if ( k <= nm ) then
           bj(k) = f
        end if
        f2 = f1
        f1 = f
     end do

     if ( abs ( bj1 ) < abs ( bj0 ) ) then
        cs = bj0 / f
     else
        cs = bj1 / f2
     end if

     do k = 0, nm
        bj(k) = cs * bj(k)
     end do

  end if

  do k = 2, nm
     dj(k) = bj(k-1) - k / x * bj(k)
  end do

  f0 = by(0)
  f1 = by(1)
  do k = 2, nm
     f = 2.0D+00 * ( k - 1.0D+00 ) / x * f1 - f0
     by(k) = f
     f0 = f1
     f1 = f
  end do

  do k = 2, nm
     dy(k) = by(k-1) - k * by(k) / x
  end do

  return
end subroutine jyna
subroutine jynb ( n, x, nm, bj, dj, by, dy )

  !*****************************************************************************80
  !
  !! JYNB computes Bessel functions Jn(x) and Yn(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    02 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BJ(0:N), DJ(0:N), BY(0:N), DY(0:N), the values
  !    of Jn(x), Jn'(x), Yn(x), Yn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ), save, dimension ( 4 ) :: a = (/ &
       -0.7031250000000000D-01, 0.1121520996093750D+00, &
       -0.5725014209747314D+00, 0.6074042001273483D+01 /)
  real ( kind = 8 ), save, dimension ( 4 ) :: a1 = (/ &
       0.1171875000000000D+00, -0.1441955566406250D+00, &
       0.6765925884246826D+00, -0.6883914268109947D+01 /)
  real ( kind = 8 ), save, dimension ( 4 ) :: b = (/ &
       0.7324218750000000D-01, -0.2271080017089844D+00, &
       0.1727727502584457D+01, -0.2438052969955606D+02 /)
  real ( kind = 8 ), save, dimension ( 4 ) :: b1 = (/ &
       -0.1025390625000000D+00, 0.2775764465332031D+00, &
       -0.1993531733751297D+01, 0.2724882731126854D+02 /)
  real ( kind = 8 ) bj(0:n)
  real ( kind = 8 ) bj0
  real ( kind = 8 ) bj1
  real ( kind = 8 ) bjk
  real ( kind = 8 ) bs
  real ( kind = 8 ) by(0:n)
  real ( kind = 8 ) by0
  real ( kind = 8 ) by1
  real ( kind = 8 ) byk
  real ( kind = 8 ) cu
  real ( kind = 8 ) dj(0:n)
  real ( kind = 8 ) dy(0:n)
  real ( kind = 8 ) ec
  real ( kind = 8 ) f
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  real ( kind = 8 ) p0
  real ( kind = 8 ) p1
  real ( kind = 8 ) pi
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) r2p
  real ( kind = 8 ) s0
  real ( kind = 8 ) su
  real ( kind = 8 ) sv
  real ( kind = 8 ) t1
  real ( kind = 8 ) t2
  real ( kind = 8 ) x

  pi = 3.141592653589793D+00
  r2p = 0.63661977236758D+00
  nm = n

  if ( x < 1.0D-100 ) then
     do k = 0, n
        bj(k) = 0.0D+00
        dj(k) = 0.0D+00
        by(k) = -1.0D+300
        dy(k) = 1.0D+300
     end do
     bj(0) = 1.0D+00
     dj(1) = 0.5D+00
     return
  end if

  if ( x <= 300.0D+00 .or. int ( 0.9D+00 * x ) < n ) then

     if ( n == 0 ) then
        nm = 1
     end if

     m = msta1 ( x, 200 )

     if ( m < nm ) then
        nm = m
     else
        m = msta2 ( x, nm, 15 )
     end if

     bs = 0.0D+00
     su = 0.0D+00
     sv = 0.0D+00
     f2 = 0.0D+00
     f1 = 1.0D-100

     do k = m, 0, -1
        f = 2.0D+00 * ( k + 1.0D+00 ) / x * f1 - f2
        if ( k <= nm ) then
           bj(k) = f
        end if
        if ( k == 2 * int ( k / 2 ) .and. k /= 0 ) then
           bs = bs + 2.0D+00 * f
           su = su + ( -1.0D+00 ) ** ( k / 2 ) * f / k
        else if ( 1 < k ) then
           sv = sv + ( -1.0D+00 ) ** ( k / 2 ) * k / ( k * k - 1.0D+00 ) * f
        end if
        f2 = f1
        f1 = f
     end do

     s0 = bs + f
     do k = 0, nm
        bj(k) = bj(k) / s0
     end do

     ec = log ( x / 2.0D+00 ) + 0.5772156649015329D+00
     by0 = r2p * ( ec * bj(0) - 4.0D+00 * su / s0 )
     by(0) = by0
     by1 = r2p * ( ( ec - 1.0D+00 ) * bj(1) - bj(0) / x - 4.0D+00 * sv / s0 )
     by(1) = by1

  else

     t1 = x - 0.25D+00 * pi
     p0 = 1.0D+00
     q0 = -0.125D+00 / x
     do k = 1, 4
        p0 = p0 + a(k) * x ** ( - 2 * k )
        q0 = q0 + b(k) * x ** ( - 2 * k - 1 )
     end do
     cu = sqrt ( r2p / x )
     bj0 = cu * ( p0 * cos ( t1 ) - q0 * sin ( t1 ) )
     by0 = cu * ( p0 * sin ( t1 ) + q0 * cos ( t1 ) )
     bj(0) = bj0
     by(0) = by0
     t2 = x - 0.75D+00 * pi
     p1 = 1.0D+00
     q1 = 0.375D+00 / x
     do k = 1, 4
        p1 = p1 + a1(k) * x ** ( - 2 * k )
        q1 = q1 + b1(k) * x ** ( - 2 * k - 1 )
     end do
     bj1 = cu * ( p1 * cos ( t2 ) - q1 * sin ( t2 ) )
     by1 = cu * ( p1 * sin ( t2 ) + q1 * cos ( t2 ) )
     bj(1) = bj1
     by(1) = by1
     do k = 2, nm
        bjk = 2.0D+00 * ( k - 1.0D+00 ) / x * bj1 - bj0
        bj(k) = bjk
        bj0 = bj1
        bj1 = bjk
     end do
  end if

  dj(0) = -bj(1)
  do k = 1, nm
     dj(k) = bj(k-1) - k / x * bj(k)
  end do

  do k = 2, nm
     byk = 2.0D+00 * ( k - 1.0D+00 ) * by1 / x - by0
     by(k) = byk
     by0 = by1
     by1 = byk
  end do

  dy(0) = -by(1)
  do k = 1, nm
     dy(k) = by(k-1) - k * by(k) / x
  end do

  return
end subroutine jynb
subroutine jyndd ( n, x, bjn, djn, fjn, byn, dyn, fyn )

  !*****************************************************************************80
  !
  !! JYNDD: Bessel functions Jn(x) and Yn(x), first and second derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    02 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BJN, DJN, FJN, BYN, DYN, FYN, the values of
  !    Jn(x), Jn'(x), Jn"(x), Yn(x), Yn'(x), Yn"(x).
  !
  implicit none

  real ( kind = 8 ) bj(102)
  real ( kind = 8 ) bjn
  real ( kind = 8 ) byn
  real ( kind = 8 ) bs
  real ( kind = 8 ) by(102)
  real ( kind = 8 ) djn
  real ( kind = 8 ) dyn
  real ( kind = 8 ) e0
  real ( kind = 8 ) ec
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) fjn
  real ( kind = 8 ) fyn
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  integer ( kind = 4 ) mt
  integer ( kind = 4 ) n
  integer ( kind = 4 ) nt
  real ( kind = 8 ) s1
  real ( kind = 8 ) su
  real ( kind = 8 ) x

  do nt = 1, 900
     mt = int ( 0.5D+00 * log10 ( 6.28D+00 * nt ) &
          - nt * log10 ( 1.36D+00 * abs ( x ) / nt ) )
     if ( 20 < mt ) then
        exit
     end if
  end do

  m = nt
  bs = 0.0D+00
  f0 = 0.0D+00
  f1 = 1.0D-35
  su = 0.0D+00
  do k = m, 0, -1
     f = 2.0D+00 * ( k + 1.0D+00 ) * f1 / x - f0
     if ( k <= n + 1 ) then
        bj(k+1) = f
     end if
     if ( k == 2 * int ( k / 2 ) ) then
        bs = bs + 2.0D+00 * f
        if ( k /= 0 ) then
           su = su + ( -1.0D+00 ) ** ( k / 2 ) * f / k
        end if
     end if
     f0 = f1
     f1 = f
  end do

  do k = 0, n + 1
     bj(k+1) = bj(k+1) / ( bs - f )
  end do

  bjn = bj(n+1)
  ec = 0.5772156649015329D+00
  e0 = 0.3183098861837907D+00
  s1 = 2.0D+00 * e0 * ( log ( x / 2.0D+00 ) + ec ) * bj(1)
  f0 = s1 - 8.0D+00 * e0 * su / ( bs - f )
  f1 = ( bj(2) * f0 - 2.0D+00 * e0 / x ) / bj(1)

  by(1) = f0
  by(2) = f1
  do k = 2, n + 1 
     f = 2.0D+00 * ( k - 1.0D+00 ) * f1 / x - f0
     by(k+1) = f
     f0 = f1
     f1 = f
  end do

  byn = by(n+1)
  djn = - bj(n+2) + n * bj(n+1) / x
  dyn = - by(n+2) + n * by(n+1) / x
  fjn = ( n * n / ( x * x ) - 1.0D+00 ) * bjn - djn / x
  fyn = ( n * n / ( x * x ) - 1.0D+00 ) * byn - dyn / x

  return
end subroutine jyndd
subroutine jyv ( v, x, vm, bj, dj, by, dy )

  !*****************************************************************************80
  !
  !! JYV computes Bessel functions Jv(x) and Yv(x) and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    02 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) V, the order of Jv(x) and Yv(x).
  !
  !    Input, real ( kind = 8 ) X, the argument of Jv(x) and Yv(x).
  !
  !    Output, real ( kind = 8 ) VM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BJ(0:N), DJ(0:N), BY(0:N), DY(0:N),
  !    the values of Jn+v0(x), Jn+v0'(x), Yn+v0(x), Yn+v0'(x).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) a0
  real ( kind = 8 ) b
  real ( kind = 8 ) bj(0:*)
  real ( kind = 8 ) bju0
  real ( kind = 8 ) bju1
  real ( kind = 8 ) bjv0
  real ( kind = 8 ) bjv1
  real ( kind = 8 ) bjvl
  real ( kind = 8 ) by(0:*)
  real ( kind = 8 ) byv0
  real ( kind = 8 ) byv1
  real ( kind = 8 ) byvk
  real ( kind = 8 ) ck
  real ( kind = 8 ) cs
  real ( kind = 8 ) cs0
  real ( kind = 8 ) cs1
  real ( kind = 8 ) dj(0:*)
  real ( kind = 8 ) dy(0:*)
  real ( kind = 8 ) ec
  real ( kind = 8 ) el
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  real ( kind = 8 ) ga
  real ( kind = 8 ) gb
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) n
  real ( kind = 8 ) pi
  real ( kind = 8 ) pv0
  real ( kind = 8 ) pv1
  real ( kind = 8 ) px
  real ( kind = 8 ) qx
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) r1
  real ( kind = 8 ) rp
  real ( kind = 8 ) rp2
  real ( kind = 8 ) rq
  real ( kind = 8 ) sk
  real ( kind = 8 ) v
  real ( kind = 8 ) v0
  real ( kind = 8 ) vg
  real ( kind = 8 ) vl
  real ( kind = 8 ) vm
  real ( kind = 8 ) vv
  real ( kind = 8 ) w0
  real ( kind = 8 ) w1
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) xk

  el = 0.5772156649015329D+00
  pi = 3.141592653589793D+00
  rp2 = 0.63661977236758D+00
  x2 = x * x
  n = int ( v )
  v0 = v - n

  if ( x < 1.0D-100 ) then

     do k = 0, n
        bj(k) = 0.0D+00
        dj(k) = 0.0D+00
        by(k) = -1.0D+300
        dy(k) = 1.0D+300
     end do

     if ( v0 == 0.0D+00 ) then
        bj(0) = 1.0D+00
        dj(1) = 0.5D+00
     else
        dj(0) = 1.0D+300
     end if
     vm = v  
     return

  end if

  if ( x <= 12.0D+00 ) then

     do l = 0, 1
        vl = v0 + l
        bjvl = 1.0D+00
        r = 1.0D+00
        do k = 1, 40
           r = -0.25D+00 * r * x2 / ( k * ( k + vl ) )
           bjvl = bjvl + r
           if ( abs ( r ) < abs ( bjvl ) * 1.0D-15 ) then
              exit
           end if
        end do

        vg = 1.0D+00 + vl
        call gammaf ( vg, ga )
        a = ( 0.5D+00 * x ) ** vl / ga

        if ( l == 0 ) then
           bjv0 = bjvl * a
        else
           bjv1 = bjvl * a
        end if

     end do

  else

     if ( x < 35.0D+00 ) then
        k0 = 11
     else if ( x < 50.0D+00 ) then
        k0 = 10
     else
        k0 = 8
     end if

     do j = 0, 1

        vv = 4.0D+00 * ( j + v0 ) * ( j + v0 )
        px = 1.0D+00
        rp = 1.0D+00
        do k = 1, k0
           rp = -0.78125D-02 * rp &
                * ( vv - ( 4.0D+00 * k - 3.0D+00 ) ** 2 ) &
                * ( vv - ( 4.0D+00 * k - 1.0D+00 ) ** 2 ) &
                / ( k * ( 2.0D+00 * k - 1.0D+00 ) * x2 )
           px = px + rp
        end do
        qx = 1.0D+00
        rq = 1.0D+00
        do k = 1, k0
           rq = -0.78125D-02 * rq &
                * ( vv - ( 4.0D+00 * k - 1.0D+00 ) ** 2 ) &
                * ( vv - ( 4.0D+00 * k + 1.0D+00 ) ** 2 ) &
                / ( k * ( 2.0D+00 * k + 1.0D+00 ) * x2 )
           qx = qx + rq
        end do
        qx = 0.125D+00 * ( vv - 1.0D+00 ) * qx / x
        xk = x - ( 0.5D+00 * ( j + v0 ) + 0.25D+00 ) * pi
        a0 = sqrt ( rp2 / x )
        ck = cos ( xk )
        sk = sin ( xk )
        if ( j == 0 ) then
           bjv0 = a0 * ( px * ck - qx * sk )
           byv0 = a0 * ( px * sk + qx * ck )
        else if ( j == 1 ) then
           bjv1 = a0 * ( px * ck - qx * sk )
           byv1 = a0 * ( px * sk + qx * ck )
        end if

     end do

  end if

  bj(0) = bjv0
  bj(1) = bjv1
  dj(0) = v0 / x * bj(0) - bj(1)
  dj(1) = - ( 1.0D+00 + v0 ) / x * bj(1) + bj(0)

  if ( 2 <= n .and. n <= int ( 0.9D+00 * x ) ) then
     f0 = bjv0
     f1 = bjv1
     do k = 2, n
        f = 2.0D+00 * ( k + v0 - 1.0D+00 ) / x * f1 - f0
        bj(k) = f
        f0 = f1
        f1 = f
     end do
  else if ( 2 <= n ) then
     m = msta1 ( x, 200 )
     if ( m < n ) then
        n = m
     else
        m = msta2 ( x, n, 15 )
     end if
     f2 = 0.0D+00
     f1 = 1.0D-100
     do k = m, 0, -1
        f = 2.0D+00 * ( v0 + k + 1.0D+00 ) / x * f1 - f2
        if ( k <= n ) then
           bj(k) = f
        end if
        f2 = f1
        f1 = f
     end do

     if ( abs ( bjv1 ) < abs ( bjv0 ) ) then
        cs = bjv0 / f
     else
        cs = bjv1 / f2
     end if
     do k = 0, n
        bj(k) = cs * bj(k)
     end do
  end if

  do k = 2, n
     dj(k) = - ( k + v0 ) / x * bj(k) + bj(k-1)
  end do

  if ( x <= 12.0D+00 ) then

     if ( v0 /= 0.0D+00 ) then

        do l = 0, 1

           vl = v0 + l
           bjvl = 1.0D+00
           r = 1.0D+00
           do k = 1, 40
              r = -0.25D+00 * r * x2 / ( k * ( k - vl ) )
              bjvl = bjvl + r
              if ( abs ( r ) < abs ( bjvl ) * 1.0D-15 ) then
                 exit
              end if
           end do

           vg = 1.0D+00 - vl
           call gammaf ( vg, gb )
           b = ( 2.0D+00 / x ) ** vl / gb

           if ( l == 0 ) then
              bju0 = bjvl * b
           else
              bju1 = bjvl * b
           end if

        end do

        pv0 = pi * v0
        pv1 = pi * ( 1.0D+00 + v0 )
        byv0 = ( bjv0 * cos ( pv0 ) - bju0 ) / sin ( pv0 )
        byv1 = ( bjv1 * cos ( pv1 ) - bju1 ) / sin ( pv1 )

     else

        ec = log ( x / 2.0D+00 ) + el
        cs0 = 0.0D+00
        w0 = 0.0D+00
        r0 = 1.0D+00
        do k = 1, 30
           w0 = w0 + 1.0D+00 / k
           r0 = -0.25D+00 * r0 / ( k * k ) * x2
           cs0 = cs0 + r0 * w0
        end do
        byv0 = rp2 * ( ec * bjv0 - cs0 )
        cs1 = 1.0D+00
        w1 = 0.0D+00
        r1 = 1.0D+00
        do k = 1, 30
           w1 = w1 + 1.0D+00 / k
           r1 = -0.25D+00 * r1 / ( k * ( k + 1 ) ) * x2
           cs1 = cs1 + r1 * ( 2.0D+00 * w1 + 1.0D+00 / ( k + 1.0D+00 ) )
        end do
        byv1 = rp2 * ( ec * bjv1 - 1.0D+00 / x - 0.25D+00 * x * cs1 )

     end if

  end if

  by(0) = byv0
  by(1) = byv1
  do k = 2, n
     byvk = 2.0D+00 * ( v0 + k - 1.0D+00 ) / x * byv1 - byv0
     by(k) = byvk
     byv0 = byv1
     byv1 = byvk
  end do

  dy(0) = v0 / x * by(0) - by(1)
  do k = 1, n
     dy(k) = - ( k + v0 ) / x * by(k) + by(k-1)
  end do

  vm = n + v0

  return
end subroutine jyv
subroutine jyzo ( n, nt, rj0, rj1, ry0, ry1 )

  !*****************************************************************************80
  !
  !! JYZO computes the zeros of Bessel functions Jn(x), Yn(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    28 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of the Bessel functions.
  !
  !    Input, integer ( kind = 4 ) NT, the number of zeros.
  !
  !    Output, real ( kind = 8 ) RJ0(NT), RJ1(NT), RY0(NT), RY1(NT), the zeros 
  !    of Jn(x), Jn'(x), Yn(x), Yn'(x).
  !
  implicit none

  integer ( kind = 4 ) nt

  real ( kind = 8 ) bjn
  real ( kind = 8 ) byn
  real ( kind = 8 ) djn
  real ( kind = 8 ) dyn
  real ( kind = 8 ) fjn
  real ( kind = 8 ) fyn
  integer ( kind = 4 ) l
  integer ( kind = 4 ) n
  real ( kind = 8 ) n_r8
  real ( kind = 8 ) rj0(nt)
  real ( kind = 8 ) rj1(nt)
  real ( kind = 8 ) ry0(nt)
  real ( kind = 8 ) ry1(nt)
  real ( kind = 8 ) x
  real ( kind = 8 ) x0

  n_r8 = real ( n, kind = 8 )

  if ( n <= 20 ) then
     x = 2.82141D+00 + 1.15859D+00 * n_r8 
  else
     x = n + 1.85576D+00 * n_r8 ** 0.33333D+00 &
          + 1.03315D+00 / n_r8 ** 0.33333D+00
  end if

  l = 0

  do

     x0 = x
     call jyndd ( n, x, bjn, djn, fjn, byn, dyn, fyn )
     x = x - bjn / djn

     if ( 1.0D-09 < abs ( x - x0 ) ) then
        cycle
     end if

     l = l + 1
     rj0(l) = x
     x = x + 3.1416D+00 + ( 0.0972D+00 + 0.0679D+00 * n_r8 &
          - 0.000354D+00 * n_r8 ** 2 ) / l

     if ( nt <= l ) then
        exit
     end if

  end do

  if ( n <= 20 ) then
     x = 0.961587D+00 + 1.07703D+00 * n_r8 
  else
     x = n_r8 + 0.80861D+00 * n_r8 ** 0.33333D+00 &
          + 0.07249D+00 / n_r8 ** 0.33333D+00
  end if

  if ( n == 0 ) then
     x = 3.8317D+00
  end if

  l = 0

  do

     x0 = x
     call jyndd ( n, x, bjn, djn, fjn, byn, dyn, fyn )
     x = x - djn / fjn
     if ( 1.0D-09 < abs ( x - x0 ) ) then
        cycle
     end if
     l = l + 1
     rj1(l) = x
     x = x + 3.1416D+00 + ( 0.4955D+00 + 0.0915D+00 * n_r8 &
          - 0.000435D+00 * n_r8 ** 2 ) / l

     if ( nt <= l ) then
        exit
     end if

  end do

  if ( n <= 20 ) then
     x = 1.19477D+00 + 1.08933D+00 * n_r8 
  else
     x = n_r8 + 0.93158D+00 * n_r8 ** 0.33333D+00 &
          + 0.26035D+00 / n_r8 ** 0.33333D+00
  end if

  l = 0

  do

     x0 = x
     call jyndd ( n, x, bjn, djn, fjn, byn, dyn, fyn )
     x = x - byn / dyn

     if ( 1.0D-09 < abs ( x - x0 ) ) then
        cycle
     end if

     l = l + 1
     ry0(l) = x 
     x = x + 3.1416D+00 + ( 0.312D+00 + 0.0852D+00 * n_r8 &
          - 0.000403D+00 * n_r8 ** 2 ) / l

     if ( nt <= l ) then
        exit
     end if

  end do

  if ( n <= 20 ) then
     x = 2.67257D+00 + 1.16099D+00 * n_r8 
  else
     x = n_r8 + 1.8211D+00 * n_r8 ** 0.33333D+00 &
          + 0.94001D+00 / n_r8 ** 0.33333D+00
  end if

  l = 0

  do

     x0 = x
     call jyndd ( n, x, bjn, djn, fjn, byn, dyn, fyn )
     x = x - dyn / fyn

     if ( 1.0D-09 < abs ( x - x0 ) ) then
        cycle
     end if

     l = l + 1
     ry1(l) = x
     x = x + 3.1416D+00 + ( 0.197D+00 + 0.0643D+00 * n_r8 &
          -0.000286D+00 * n_r8 ** 2 ) / l 

     if ( nt <= l ) then
        exit
     end if

  end do

  return
end subroutine jyzo
subroutine klvna ( x, ber, bei, ger, gei, der, dei, her, hei )

  !*****************************************************************************80
  !
  !! KLVNA: Kelvin functions ber(x), bei(x), ker(x), and kei(x), and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    03 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BER, BEI, GER, GEI, DER, DEI, HER, HEI, 
  !    the values of ber x, bei x, ker x, kei x, ber'x, bei'x, ker'x, kei'x.
  !
  implicit none

  real ( kind = 8 ) bei
  real ( kind = 8 ) ber
  real ( kind = 8 ) cn0
  real ( kind = 8 ) cp0
  real ( kind = 8 ) cs
  real ( kind = 8 ) dei
  real ( kind = 8 ) der
  real ( kind = 8 ) el
  real ( kind = 8 ) eps
  real ( kind = 8 ) fac
  real ( kind = 8 ) gei
  real ( kind = 8 ) ger
  real ( kind = 8 ) gs
  real ( kind = 8 ) hei
  real ( kind = 8 ) her
  integer ( kind = 4 ) k
  integer ( kind = 4 ) km
  integer ( kind = 4 ) m
  real ( kind = 8 ) pi
  real ( kind = 8 ) pn0
  real ( kind = 8 ) pn1
  real ( kind = 8 ) pp0
  real ( kind = 8 ) pp1
  real ( kind = 8 ) qn0
  real ( kind = 8 ) qn1
  real ( kind = 8 ) qp0
  real ( kind = 8 ) qp1
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) r1
  real ( kind = 8 ) rc
  real ( kind = 8 ) rs
  real ( kind = 8 ) sn0
  real ( kind = 8 ) sp0
  real ( kind = 8 ) ss
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) x4
  real ( kind = 8 ) xc1
  real ( kind = 8 ) xc2
  real ( kind = 8 ) xd
  real ( kind = 8 ) xe1
  real ( kind = 8 ) xe2
  real ( kind = 8 ) xt

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00
  eps = 1.0D-15

  if ( x == 0.0D+00 ) then
     ber = 1.0D+00
     bei = 0.0D+00
     ger = 1.0D+300
     gei = -0.25D+00 * pi
     der = 0.0D+00
     dei = 0.0D+00
     her = -1.0D+300
     hei = 0.0D+00
     return
  end if

  x2 = 0.25D+00 * x * x
  x4 = x2 * x2

  if ( abs ( x ) < 10.0D+00 ) then

     ber = 1.0D+00
     r = 1.0D+00
     do m = 1, 60
        r = -0.25D+00 * r / ( m * m ) / ( 2.0D+00 * m - 1.0D+00 ) ** 2 * x4
        ber = ber + r
        if ( abs ( r ) < abs ( ber ) * eps ) then
           exit
        end if
     end do

     bei = x2
     r = x2
     do m = 1, 60
        r = -0.25D+00 * r / ( m * m ) / ( 2.0D+00 * m + 1.0D+00 ) ** 2 * x4
        bei = bei + r
        if ( abs ( r ) < abs ( bei ) * eps ) then
           exit
        end if
     end do

     ger = - ( log ( x / 2.0D+00 ) + el ) * ber + 0.25D+00 * pi * bei
     r = 1.0D+00
     gs = 0.0D+00
     do m = 1, 60
        r = -0.25D+00 * r / ( m * m ) / ( 2.0D+00 * m - 1.0D+00 ) ** 2 * x4
        gs = gs + 1.0D+00 / ( 2.0D+00 * m - 1.0D+00 ) + 1.0D+00 / ( 2.0D+00 * m )
        ger = ger + r * gs
        if ( abs ( r * gs ) < abs ( ger ) * eps ) then
           exit
        end if
     end do

     gei = x2 - ( log ( x / 2.0D+00 ) + el ) * bei - 0.25D+00 * pi * ber
     r = x2
     gs = 1.0D+00
     do m = 1, 60
        r = -0.25D+00 * r / ( m * m ) / ( 2.0D+00 * m + 1.0D+00 ) ** 2 * x4
        gs = gs + 1.0D+00 / ( 2.0D+00 * m ) + 1.0D+00 / ( 2.0D+00 * m + 1.0D+00 )
        gei = gei + r * gs
        if ( abs ( r * gs ) < abs ( gei ) * eps ) then
           exit
        end if
     end do

     der = -0.25D+00 * x * x2
     r = der
     do m = 1, 60
        r = -0.25D+00 * r / m / ( m + 1.0D+00 ) &
             / ( 2.0D+00 * m + 1.0D+00 ) ** 2 * x4
        der = der + r
        if ( abs ( r ) < abs ( der ) * eps ) then
           exit
        end if
     end do

     dei = 0.5D+00 * x
     r = dei
     do m = 1, 60
        r = -0.25D+00 * r / ( m * m ) / ( 2.0D+00 * m - 1.0D+00 ) &
             / ( 2.0D+00 * m + 1.0D+00 ) * x4
        dei = dei + r
        if ( abs ( r ) < abs ( dei ) * eps ) then
           exit
        end if
     end do

     r = -0.25D+00 * x * x2
     gs = 1.5D+00
     her = 1.5D+00 * r - ber / x &
          - ( log ( x / 2.0D+00 ) + el ) * der + 0.25D+00 * pi * dei
     do m = 1, 60
        r = -0.25D+00 * r / m / ( m + 1.0D+00 ) &
             / ( 2.0D+00 * m + 1.0D+00 ) ** 2 * x4
        gs = gs + 1.0D+00 / ( 2 * m + 1.0D+00 ) + 1.0D+00 &
             / ( 2 * m + 2.0D+00 )
        her = her + r * gs
        if ( abs ( r * gs ) < abs ( her ) * eps ) then
           exit
        end if
     end do

     r = 0.5D+00 * x
     gs = 1.0D+00
     hei = 0.5D+00 * x - bei / x &
          - ( log ( x / 2.0D+00 ) + el ) * dei - 0.25D+00 * pi * der
     do m = 1, 60
        r = -0.25D+00 * r / ( m * m ) / ( 2 * m - 1.0D+00 ) &
             / ( 2 * m + 1.0D+00 ) * x4
        gs = gs + 1.0D+00 / ( 2.0D+00 * m ) + 1.0D+00 &
             / ( 2 * m + 1.0D+00 )
        hei = hei + r * gs
        if ( abs ( r * gs ) < abs ( hei ) * eps ) then 
           return
        end if
     end do

  else

     pp0 = 1.0D+00
     pn0 = 1.0D+00
     qp0 = 0.0D+00
     qn0 = 0.0D+00
     r0 = 1.0D+00

     if ( abs ( x ) < 40.0D+00 ) then
        km = 18
     else
        km = 10
     end if

     fac = 1.0D+00
     do k = 1, km
        fac = -fac
        xt = 0.25D+00 * k * pi - int ( 0.125D+00 * k ) * 2.0D+00 * pi
        cs = cos ( xt )
        ss = sin ( xt )
        r0 = 0.125D+00 * r0 * ( 2.0D+00 * k - 1.0D+00 ) ** 2 / k / x
        rc = r0 * cs
        rs = r0 * ss
        pp0 = pp0 + rc
        pn0 = pn0 + fac * rc
        qp0 = qp0 + rs
        qn0 = qn0 + fac * rs
     end do

     xd = x / sqrt (2.0D+00 )
     xe1 = exp ( xd )
     xe2 = exp ( - xd )
     xc1 = 1.0D+00 / sqrt ( 2.0D+00 * pi * x )
     xc2 = sqrt ( 0.5D+00 * pi / x )
     cp0 = cos ( xd + 0.125D+00 * pi )
     cn0 = cos ( xd - 0.125D+00 * pi )
     sp0 = sin ( xd + 0.125D+00 * pi )
     sn0 = sin ( xd - 0.125D+00 * pi )
     ger = xc2 * xe2 * (  pn0 * cp0 - qn0 * sp0 )
     gei = xc2 * xe2 * ( -pn0 * sp0 - qn0 * cp0 )
     ber = xc1 * xe1 * (  pp0 * cn0 + qp0 * sn0 ) - gei / pi
     bei = xc1 * xe1 * (  pp0 * sn0 - qp0 * cn0 ) + ger / pi
     pp1 = 1.0D+00
     pn1 = 1.0D+00
     qp1 = 0.0D+00
     qn1 = 0.0D+00
     r1 = 1.0D+00
     fac = 1.0D+00

     do k = 1, km
        fac = -fac
        xt = 0.25D+00 * k * pi - int ( 0.125D+00 * k ) * 2.0D+00 * pi
        cs = cos ( xt )
        ss = sin ( xt )
        r1 = 0.125D+00 * r1 &
             * ( 4.0D+00 - ( 2.0D+00 * k - 1.0D+00 ) ** 2 ) / k / x
        rc = r1 * cs
        rs = r1 * ss
        pp1 = pp1 + fac * rc
        pn1 = pn1 + rc
        qp1 = qp1 + fac * rs
        qn1 = qn1 + rs
     end do

     her = xc2 * xe2 * ( - pn1 * cn0 + qn1 * sn0 )
     hei = xc2 * xe2 * (   pn1 * sn0 + qn1 * cn0 )
     der = xc1 * xe1 * (   pp1 * cp0 + qp1 * sp0 ) - hei / pi
     dei = xc1 * xe1 * (   pp1 * sp0 - qp1 * cp0 ) + her / pi

  end if

  return
end subroutine klvna
subroutine klvnb ( x, ber, bei, ger, gei, der, dei, her, hei )

  !*****************************************************************************80
  !
  !! KLVNB: Kelvin functions ber(x), bei(x), ker(x), and kei(x), and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    03 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) BER, BEI, GER, GEI, DER, DEI, HER, HEI, 
  !    the values of ber x, bei x, ker x, kei x, ber'x, bei'x, ker'x, kei'x.
  !
  implicit none

  real ( kind = 8 ) bei
  real ( kind = 8 ) ber
  real ( kind = 8 ) csn
  real ( kind = 8 ) csp
  real ( kind = 8 ) dei
  real ( kind = 8 ) der
  real ( kind = 8 ) fxi
  real ( kind = 8 ) fxr
  real ( kind = 8 ) gei
  real ( kind = 8 ) ger
  real ( kind = 8 ) hei
  real ( kind = 8 ) her
  integer ( kind = 4 ) l
  real ( kind = 8 ) pi
  real ( kind = 8 ) pni
  real ( kind = 8 ) pnr
  real ( kind = 8 ) ppi
  real ( kind = 8 ) ppr
  real ( kind = 8 ) ssn
  real ( kind = 8 ) ssp
  real ( kind = 8 ) t
  real ( kind = 8 ) t2
  real ( kind = 8 ) tni
  real ( kind = 8 ) tnr
  real ( kind = 8 ) tpi
  real ( kind = 8 ) tpr
  real ( kind = 8 ) u
  real ( kind = 8 ) v
  real ( kind = 8 ) x
  real ( kind = 8 ) yc1
  real ( kind = 8 ) yc2
  real ( kind = 8 ) yci
  real ( kind = 8 ) ye1
  real ( kind = 8 ) ye2
  real ( kind = 8 ) yei
  real ( kind = 8 ) yd

  pi = 3.141592653589793D+00

  if ( x == 0.0D+00 ) then

     ber = 1.0D+00
     bei = 0.0D+00
     ger = 1.0D+300
     gei = -0.25D+00 * pi
     der = 0.0D+00
     dei = 0.0D+00
     her = -1.0D+300
     hei = 0.0D+00

  else if ( x < 8.0D+00 ) then

     t = x / 8.0D+00
     t2 = t * t
     u = t2 * t2

     ber = (((((( &
          - 0.901D-05 * u &
          + 0.122552D-02 ) * u &
          - 0.08349609D+00 ) * u &
          + 2.64191397D+00 ) * u &
          - 32.36345652D+00 ) * u &
          + 113.77777774D+00 ) * u &
          - 64.0D+00 ) * u &
          + 1.0D+00

     bei = t * t * (((((( &
          0.11346D-03 * u &
          - 0.01103667D+00 ) * u &
          + 0.52185615D+00 ) * u &
          - 10.56765779D+00 ) * u &
          + 72.81777742D+00 ) * u &
          - 113.77777774D+00 ) * u &
          + 16.0D+00 )

     ger = (((((( &
          - 0.2458D-04 * u &
          + 0.309699D-02 ) * u &
          - 0.19636347D+00 ) * u &
          + 5.65539121D+00 ) * u &
          - 60.60977451D+00 ) * u &
          + 171.36272133D+00 ) * u &
          - 59.05819744D+00 ) * u &
          - 0.57721566D+00

     ger = ger - log ( 0.5D+00 * x ) * ber + 0.25D+00 * pi * bei

     gei = t2 * (((((( &
          0.29532D-03 * u &
          - 0.02695875D+00 ) * u &
          + 1.17509064D+00 ) * u &
          - 21.30060904D+00 ) * u &
          + 124.2356965D+00 ) * u &
          - 142.91827687D+00 ) * u &
          + 6.76454936D+00 )

     gei = gei - log ( 0.5D+00 * x ) * bei - 0.25D+00 * pi * ber

     der = x * t2 * (((((( &
          - 0.394D-05 * u &
          + 0.45957D-03 ) * u &
          - 0.02609253D+00 ) * u &
          + 0.66047849D+00 ) * u &
          - 6.0681481D+00 ) * u &
          + 14.22222222D+00 ) * u &
          - 4.0D+00 )

     dei = x * (((((( &
          0.4609D-04 * u &
          - 0.379386D-02 ) * u &
          + 0.14677204D+00 ) * u &
          - 2.31167514D+00 ) * u &
          + 11.37777772D+00 ) * u &
          - 10.66666666D+00 ) * u &
          + 0.5D+00 ) 

     her = x * t2 * (((((( &
          - 0.1075D-04 * u &
          + 0.116137D-02 ) * u &
          - 0.06136358D+00 ) * u &
          + 1.4138478D+00 ) * u &
          - 11.36433272D+00 ) * u &
          + 21.42034017D+00 ) * u &
          - 3.69113734D+00 )

     her = her - log ( 0.5D+00 * x ) * der - ber / x  &
          + 0.25D+00 * pi * dei

     hei = x * (((((( &
          0.11997D-03 * u &
          - 0.926707D-02 ) * u &
          + 0.33049424D+00 ) * u &
          - 4.65950823D+00 ) * u &
          + 19.41182758D+00 ) * u &
          - 13.39858846D+00 ) * u &
          + 0.21139217D+00 )

     hei = hei - log ( 0.5D+00 * x ) * dei - bei / x  &
          - 0.25D+00 * pi * der

  else

     t = 8.0D+00 / x

     do l = 1, 2

        v = ( -1.0D+00 ) ** l * t

        tpr = (((( &
             0.6D-06 * v &
             - 0.34D-05 ) * v &
             - 0.252D-04 ) * v &
             - 0.906D-04 ) * v * v &
             + 0.0110486D+00 ) * v

        tpi = (((( &
             0.19D-05 * v &
             + 0.51D-05 ) * v * v &
             - 0.901D-04 ) * v &
             - 0.9765D-03 ) * v &
             - 0.0110485D+00 ) * v &
             - 0.3926991D+00

        if ( l == 1 ) then
           tnr = tpr
           tni = tpi
        end if

     end do

     yd = x / sqrt ( 2.0D+00 )
     ye1 = exp ( yd + tpr )
     ye2 = exp ( - yd + tnr )
     yc1 = 1.0D+00 / sqrt ( 2.0D+00 * pi * x )
     yc2 = sqrt ( pi / ( 2.0D+00 * x ) )
     csp = cos ( yd + tpi )
     ssp = sin ( yd + tpi )
     csn = cos ( - yd + tni )
     ssn = sin ( - yd + tni )
     ger = yc2 * ye2 * csn
     gei = yc2 * ye2 * ssn
     fxr = yc1 * ye1 * csp
     fxi = yc1 * ye1 * ssp
     ber = fxr - gei / pi
     bei = fxi + ger / pi

     do l = 1, 2

        v = ( -1.0D+00 ) ** l * t

        ppr = ((((( &
             0.16D-05 * v &
             + 0.117D-04 ) * v &
             + 0.346D-04 ) * v &
             + 0.5D-06 ) * v &
             - 0.13813D-02 ) * v &
             - 0.0625001D+00 ) * v &
             + 0.7071068D+00

        ppi = ((((( &
             - 0.32D-05 * v &
             - 0.24D-05 ) * v &
             + 0.338D-04 ) * v &
             + 0.2452D-03 ) * v &
             + 0.13811D-02 ) * v &
             - 0.1D-06 ) * v &
             + 0.7071068D+00

        if ( l == 1 ) then
           pnr = ppr
           pni = ppi
        end if

     end do

     her =     gei * pni - ger * pnr
     hei = - ( gei * pnr + ger * pni )
     der = fxr * ppr - fxi * ppi - hei / pi
     dei = fxi * ppr + fxr * ppi + her / pi

  end if

  return
end subroutine klvnb
subroutine klvnzo ( nt, kd, zo )

  !*****************************************************************************80
  !
  !! KLVNZO computes zeros of the Kelvin functions.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    15 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) NT, the number of zeros.
  !
  !    Input, integer ( kind = 4 ) KD, the function code.
  !    1 for ber x, 
  !    2 for bei x,
  !    3 for ker x, 
  !    4 for kei x,
  !    5 for ber' x, 
  !    6 for bei' x,
  !    7 for ker' x, 
  !    8 for kei' x.
  !
  !    Output, real ( kind = 8 ) ZO(NT), the zeros of the given Kelvin function.
  !
  implicit none

  integer ( kind = 4 ) nt

  real ( kind = 8 ) bei
  real ( kind = 8 ) ber
  real ( kind = 8 ) ddi
  real ( kind = 8 ) ddr
  real ( kind = 8 ) dei
  real ( kind = 8 ) der
  real ( kind = 8 ) gdi
  real ( kind = 8 ) gdr
  real ( kind = 8 ) gei
  real ( kind = 8 ) ger
  real ( kind = 8 ) hei
  real ( kind = 8 ) her
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) m
  real ( kind = 8 ) rt
  real ( kind = 8 ) rt0(8)
  real ( kind = 8 ) zo(nt)

  rt0(1) = 2.84891D+00
  rt0(2) = 5.02622D+00
  rt0(3) = 1.71854D+00
  rt0(4) = 3.91467D+00
  rt0(5) = 6.03871D+00
  rt0(6) = 3.77268D+00
  rt0(7) = 2.66584D+00
  rt0(8) = 4.93181D+00

  rt = rt0(kd)

  do m = 1, nt

     do

        call klvna ( rt, ber, bei, ger, gei, der, dei, her, hei )

        if ( kd == 1 ) then
           rt = rt - ber / der
        else if ( kd == 2 ) then
           rt = rt - bei / dei
        else if ( kd == 3 ) then
           rt = rt - ger / her
        else if ( kd == 4 ) then
           rt = rt - gei / hei
        else if ( kd == 5 ) then
           ddr = - bei - der / rt
           rt = rt - der / ddr
        else if ( kd == 6 ) then
           ddi = ber - dei / rt
           rt = rt - dei / ddi
        else if ( kd == 7 ) then
           gdr = - gei - her / rt
           rt = rt - her / gdr
        else
           gdi = ger - hei / rt
           rt = rt - hei / gdi
        end if

        if ( abs ( rt - rt0(kd) ) <= 5.0D-10 ) then
           exit
        end if

        rt0(kd) = rt

     end do

     zo(m) = rt
     rt = rt + 4.44D+00

  end do

  return
end subroutine klvnzo
subroutine kmn ( m, n, c, cv, kd, df, dn, ck1, ck2 )

  !*****************************************************************************80
  !
  !! KMN: expansion coefficients of prolate or oblate spheroidal functions.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    02 August 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) M, the mode parameter;  M = 0, 1, 2, ...
  !
  !    Input, integer ( kind = 4 ) N, mode parameter, N = M, M + 1, M + 2, ...
  !
  !    Input, real ( kind = 8 ) C, spheroidal parameter.
  !
  !    Input, real ( kind = 8 ) CV, the characteristic value.
  !
  !    Input, integer ( kind = 4 ) KD, the function code.
  !    1, the prolate function.
  !    -1, the oblate function.
  !
  !    Input, real ( kind = 8 ) DF(*), the expansion coefficients.
  !
  implicit none

  real ( kind = 8 ) c
  real ( kind = 8 ) ck1
  real ( kind = 8 ) ck2
  real ( kind = 8 ) cs
  real ( kind = 8 ) cv
  real ( kind = 8 ) df(200)
  real ( kind = 8 ) dn(200)
  real ( kind = 8 ) dnp
  real ( kind = 8 ) g0
  real ( kind = 8 ) gk0
  real ( kind = 8 ) gk1
  real ( kind = 8 ) gk2
  real ( kind = 8 ) gk3
  integer ( kind = 4 ) i
  integer ( kind = 4 ) ip
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
  integer ( kind = 4 ) n
  integer ( kind = 4 ) nm
  integer ( kind = 4 ) nm1
  integer ( kind = 4 ) nn
  real ( kind = 8 ) r
  real ( kind = 8 ) r1
  real ( kind = 8 ) r2
  real ( kind = 8 ) r3
  real ( kind = 8 ) r4
  real ( kind = 8 ) r5
  real ( kind = 8 ) rk(200)
  real ( kind = 8 ) sa0
  real ( kind = 8 ) sb0
  real ( kind = 8 ) su0
  real ( kind = 8 ) sw
  real ( kind = 8 ) t
  real ( kind = 8 ) tp(200)
  real ( kind = 8 ) u(200)
  real ( kind = 8 ) v(200)
  real ( kind = 8 ) w(200)

  nm = 25 + int ( 0.5D+00 * ( n - m ) + c )
  nn = nm + m
  cs = c * c * kd

  if ( n - m == 2 * int ( ( n - m ) / 2 ) ) then
     ip = 0
  else
     ip = 1
  end if

  do i = 1, nn + 3

     if ( ip == 0 ) then
        k = - 2 * ( i - 1 )
     else
        k = - ( 2 * i - 3 )
     end if

     gk0 = 2.0D+00 * m + k
     gk1 = ( m + k ) * ( m + k + 1.0D+00 )
     gk2 = 2.0D+00 * ( m + k ) - 1.0D+00
     gk3 = 2.0D+00 * ( m + k ) + 3.0D+00
     u(i) = gk0 * ( gk0 - 1.0D+00 ) * cs / ( gk2 * ( gk2 + 2.0D+00 ) )
     v(i) = gk1 - cv + ( 2.0D+00 * ( gk1 - m * m ) - 1.0D+00 ) * cs &
          / ( gk2 * gk3 )
     w(i) = ( k + 1.0D+00 ) * ( k + 2.0D+00 ) * cs / ( ( gk2 + 2.0D+00 ) * gk3 )

  end do

  do k = 1, m
     t = v(m+1)
     do l = 0, m - k - 1
        t = v(m-l) - w(m-l+1) * u(m-l) / t
     end do
     rk(k) = -u(k) / t
  end do

  r = 1.0D+00
  do k = 1, m
     r = r * rk(k)
     dn(k) = df(1) * r
  end do

  tp(nn) = v(nn+1)
  do k = nn - 1, m + 1,-1
     tp(k) = v(k+1) - w(k+2) * u(k+1) / tp(k+1)
     if ( m + 1 < k ) then
        rk(k) = -u(k) / tp(k)
     end if
  end do

  if ( m == 0 ) then
     dnp = df(1)
  else
     dnp = dn(m)
  end if

  dn(m+1) = ( - 1.0D+00 ) ** ip * dnp * cs &
       / ( ( 2.0D+00 * m - 1.0D+00 ) &
       * ( 2.0D+00 * m + 1.0D+00 - 4.0D+00 * ip ) * tp(m+1) )
  do k = m + 2, nn
     dn(k) = rk(k) * dn(k-1)
  end do

  r1 = 1.0D+00
  do j = 1, ( n + m + ip ) / 2
     r1 = r1 * ( j + 0.5D+00 * ( n + m + ip ) )
  end do
  nm1 = ( n - m ) / 2
  r = 1.0D+00
  do j = 1, 2 * m + ip
     r = r * j
  end do
  su0 = r * df(1)

  do k = 2, nm
     r = r * ( m + k - 1.0D+00 ) * ( m + k + ip - 1.5D+00 ) &
          / ( k - 1.0D+00 ) / ( k + ip - 1.5D+00 )
     su0 = su0 + r * df(k)
     if ( nm1 < k .and. &
          abs ( ( su0 - sw ) / su0 ) < 1.0D-14 ) then
        exit
     end if
     sw = su0
  end do

  if ( kd /= 1 ) then

     r2 = 1.0D+00
     do j = 1,m
        r2 = 2.0D+00 * c * r2 * j
     end do
     r3 = 1.0D+00
     do j = 1, ( n - m - ip ) / 2
        r3 = r3 * j
     end do
     sa0 = ( 2.0D+00 * ( m + ip ) + 1.0D+00 ) * r1 &
          / ( 2.0D+00 ** n * c ** ip * r2 * r3 * df(1) )
     ck1 = sa0 * su0

     if ( kd == -1 ) then
        return
     end if

  end if

  r4 = 1.0D+00
  do j = 1, ( n - m - ip ) / 2
     r4 = 4.0D+00 * r4 * j
  end do
  r5 = 1.0D+00
  do j = 1, m
     r5 = r5 * ( j + m ) / c
  end do

  if ( m == 0 ) then
     g0 = df(1)
  else
     g0 = dn(m)
  end if

  sb0 = ( ip + 1.0D+00 ) * c ** ( ip + 1 ) &
       / ( 2.0D+00 * ip * ( m - 2.0D+00 ) + 1.0D+00 ) &
       / ( 2.0D+00 * m - 1.0D+00 )

  ck2 = ( -1 ) ** ip * sb0 * r4 * r5 * g0 / r1 * su0

  return
end subroutine kmn
subroutine lagzo ( n, x, w )

  !*****************************************************************************80
  !
  !! LAGZO computes zeros of the Laguerre polynomial, and integration weights.
  !
  !  Discussion:
  !
  !    This procedure computes the zeros of Laguerre polynomial Ln(x) in the 
  !    interval [0,∞], and the corresponding weighting coefficients for 
  !    Gauss-Laguerre integration.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    07 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of the Laguerre polynomial.
  !
  !    Output, real ( kind = 8 ) X(N), the zeros of the Laguerre polynomial.
  !
  !    Output, real ( kind = 8 ) W(N), the weighting coefficients.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) fd
  real ( kind = 8 ) gd
  real ( kind = 8 ) hn
  integer ( kind = 4 ) i
  integer ( kind = 4 ) it
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) nr
  real ( kind = 8 ) p
  real ( kind = 8 ) pd
  real ( kind = 8 ) pf
  real ( kind = 8 ) q
  real ( kind = 8 ) w(n)
  real ( kind = 8 ) wp
  real ( kind = 8 ) x(n)
  real ( kind = 8 ) z
  real ( kind = 8 ) z0

  hn = 1.0D+00 / real ( n, kind = 8 )

  do nr = 1, n

     if ( nr == 1 ) then
        z = hn
     else
        z = x(nr-1) + hn * nr ** 1.27D+00
     end if

     it = 0

     do

        it = it + 1
        z0 = z
        p = 1.0D+00
        do i = 1, nr - 1
           p = p * ( z - x(i) )
        end do

        f0 = 1.0D+00
        f1 = 1.0D+00 - z
        do k = 2, n
           pf = (( 2.0D+00 * k - 1.0D+00 - z ) * f1 &
                - ( k - 1.0D+00 ) * f0 ) / k
           pd = k / z * ( pf - f1 )
           f0 = f1
           f1 = pf
        end do

        fd = pf / p

        q = 0.0D+00
        do i = 1, nr - 1
           wp = 1.0D+00
           do j = 1, nr - 1
              if ( j /= i ) then
                 wp = wp * ( z - x(j) )
              end if
           end do
           q = q + wp
        end do

        gd = ( pd - q * fd ) / p
        z = z - fd / gd

        if ( 40 < it .or. abs ( ( z - z0 ) / z ) <= 1.0D-15 ) then
           exit
        end if

     end do

     x(nr) = z
     w(nr) = 1.0D+00 / ( z * pd * pd )

  end do

  return
end subroutine lagzo
subroutine lamn ( n, x, nm, bl, dl )

  !*****************************************************************************80
  !
  !! LAMN computes lambda functions and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    14 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, integer ( kind = 4 ) NM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) BL(0:N), DL(0:N), the
  !    value of the lambda function and its derivative of orders 0 through N.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) bg
  real ( kind = 8 ) bk
  real ( kind = 8 ) bl(0:n)
  real ( kind = 8 ) bs
  real ( kind = 8 ) dl(0:n)
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  integer ( kind = 4 ) i
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) nm
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) uk
  real ( kind = 8 ) x
  real ( kind = 8 ) x2

  nm = n

  if ( abs ( x ) < 1.0D-100 ) then
     do k = 0, n
        bl(k) = 0.0D+00
        dl(k) = 0.0D+00
     end do
     bl(0) = 1.0D+00
     dl(1) = 0.5D+00
     return
  end if

  if ( x <= 12.0D+00 ) then

     x2 = x * x

     do k = 0, n
        bk = 1.0D+00
        r = 1.0D+00
        do i = 1, 50
           r = -0.25D+00 * r * x2 / ( i * ( i + k ) )
           bk = bk + r
           if ( abs ( r ) < abs ( bk ) * 1.0D-15 ) then
              exit
           end if
        end do

        bl(k) = bk
        if ( 1 <= k ) then
           dl(k-1) = - 0.5D+00 * x / k * bk
        end if

     end do

     uk = 1.0D+00
     r = 1.0D+00
     do i = 1, 50
        r = -0.25D+00 * r * x2 / ( i * ( i + n + 1.0D+00 ) )
        uk = uk + r
        if ( abs ( r ) < abs ( uk ) * 1.0D-15 ) then
           exit
        end if
     end do

     dl(n) = -0.5D+00 * x / ( n + 1.0D+00 ) * uk
     return

  end if

  if ( n == 0 ) then
     nm = 1
  end if

  m = msta1 ( x, 200 )

  if ( m < nm ) then
     nm = m
  else
     m = msta2 ( x, nm, 15 )
  end if

  bs = 0.0D+00
  f0 = 0.0D+00
  f1 = 1.0D-100
  do k = m, 0, -1
     f = 2.0D+00 * ( k + 1.0D+00 ) * f1 / x - f0
     if ( k <= nm ) then
        bl(k) = f
     end if
     if ( k == 2 * int ( k / 2 ) ) then
        bs = bs + 2.0D+00 * f
     end if
     f0 = f1
     f1 = f
  end do

  bg = bs - f
  do k = 0, nm
     bl(k) = bl(k) / bg
  end do

  r0 = 1.0D+00
  do k = 1, nm
     r0 = 2.0D+00 * r0 * k / x
     bl(k) = r0 * bl(k)
  end do

  dl(0) = -0.5D+00 * x * bl(1)
  do k = 1, nm
     dl(k) = 2.0D+00 * k / x * ( bl(k-1) - bl(k) )
  end do

  return
end subroutine lamn
subroutine lamv ( v, x, vm, vl, dl )

  !*****************************************************************************80
  !
  !! LAMV computes lambda functions and derivatives of arbitrary order.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    31 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) V, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) VM, the highest order computed.
  !
  !    Output, real ( kind = 8 ) VL(0:*), DL(0:*), the Lambda function and 
  !    derivative, of orders N+V0.
  !
  implicit none

  real ( kind = 8 ) v

  real ( kind = 8 ) a0
  real ( kind = 8 ) bjv0
  real ( kind = 8 ) bjv1
  real ( kind = 8 ) bk
  real ( kind = 8 ) ck
  real ( kind = 8 ) cs
  real ( kind = 8 ) dl(0:int(v))
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  real ( kind = 8 ) fac
  real ( kind = 8 ) ga
  integer ( kind = 4 ) i
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) k0
  integer ( kind = 4 ) m
    ! integer ( kind = 4 ) msta1
  ! integer ( kind = 4 ) msta2
  integer ( kind = 4 ) n
  real ( kind = 8 ) pi
  real ( kind = 8 ) px
  real ( kind = 8 ) qx
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) rc
  real ( kind = 8 ) rp
  real ( kind = 8 ) rp2
  real ( kind = 8 ) rq
  real ( kind = 8 ) sk
  real ( kind = 8 ) uk
  real ( kind = 8 ) v0
  real ( kind = 8 ) vk
  real ( kind = 8 ) vl(0:int(v))
  real ( kind = 8 ) vm
  real ( kind = 8 ) vv
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) xk

  pi = 3.141592653589793D+00
  rp2 = 0.63661977236758D+00
  x = abs ( x )
  x2 = x * x
  n = int ( v )
  v0 = v - n
  vm = v

  if ( x <= 12.0D+00 ) then

     do k = 0, n

        vk = v0 + k
        bk = 1.0D+00
        r = 1.0D+00

        do i = 1, 50
           r = -0.25D+00 * r * x2 / ( i * ( i + vk ) )
           bk = bk + r
           if ( abs ( r ) < abs ( bk ) * 1.0D-15 ) then
              exit
           end if
        end do

        vl(k) = bk
        uk = 1.0D+00
        r = 1.0D+00
        do i = 1, 50
           r = -0.25D+00 * r * x2 / ( i * ( i + vk + 1.0D+00 ))
           uk = uk + r
           if ( abs ( r ) < abs ( uk ) * 1.0D-15 ) then
              exit
           end if
        end do

        dl(k) = - 0.5D+00 * x / ( vk + 1.0D+00 ) * uk

     end do

     return

  end if

  if ( x < 35.0D+00 ) then
     k0 = 11
  else if ( x < 50.0D+00 ) then
     k0 = 10
  else
     k0 = 8
  end if

  do j = 0, 1
     vv = 4.0D+00 * ( j + v0 ) * ( j + v0 )
     px = 1.0D+00
     rp = 1.0D+00
     do k = 1, k0
        rp = - 0.78125D-02 * rp * ( vv - ( 4.0D+00 * k - 3.0D+00 ) ** 2 ) &
             * ( vv - ( 4.0D+00 * k - 1.0D+00 ) ** 2 ) &
             / ( k * ( 2.0 * k - 1.0D+00 ) * x2 )
        px = px + rp
     end do
     qx = 1.0D+00
     rq = 1.0D+00
     do k = 1, k0
        rq = - 0.78125D-02 * rq * ( vv - ( 4.0D+00 * k - 1.0D+00 ) ** 2 ) &
             * ( vv - ( 4.0D+00 * k + 1.0D+00 ) ** 2 ) &
             / ( k * ( 2.0D+00 * k + 1.0D+00 ) * x2 )
        qx = qx + rq
     end do
     qx = 0.125D+00 * ( vv - 1.0D+00 ) * qx / x
     xk = x - ( 0.5D+00 * ( j + v0 ) + 0.25D+00 ) * pi
     a0 = sqrt ( rp2 / x )
     ck = cos ( xk )
     sk = sin ( xk )
     if ( j == 0 ) then
        bjv0 = a0 * ( px * ck - qx * sk )
     else
        bjv1 = a0 * ( px * ck - qx * sk )
     end if
  end do

  if ( v0 == 0.0D+00 ) then
     ga = 1.0D+00
  else
     call gam0 ( v0, ga )
     ga = v0 * ga
  end if

  fac = ( 2.0D+00 / x ) ** v0 * ga
  vl(0) = bjv0
  dl(0) = - bjv1 + v0 / x * bjv0
  vl(1) = bjv1
  dl(1) = bjv0 - ( 1.0D+00 + v0 ) / x * bjv1
  r0 = 2.0D+00 * ( 1.0D+00 + v0 ) / x

  if ( n <= 1 ) then
     vl(0) = fac * vl(0)
     dl(0) = fac * dl(0) - v0 / x * vl(0)
     vl(1) = fac * r0 * vl(1)
     dl(1) = fac * r0 * dl(1) - ( 1.0D+00 + v0 ) / x * vl(1)
     return
  end if

  if ( 2 <= n .and. n <= int ( 0.9D+00 * x ) ) then

     f0 = bjv0
     f1 = bjv1
     do k = 2, n
        f = 2.0D+00 * ( k + v0 - 1.0D+00 ) / x * f1 - f0
        f0 = f1
        f1 = f
        vl(k) = f
     end do

  else if ( 2 <= n ) then

     m = msta1 ( x, 200 )
     if ( m < n ) then
        n = m
     else
        m = msta2 ( x, n, 15 )
     end if
     f2 = 0.0D+00
     f1 = 1.0D-100
     do k = m, 0, -1
        f = 2.0D+00 * ( v0 + k + 1.0D+00 ) / x * f1 - f2
        if ( k <= n ) then
           vl(k) = f
        end if
        f2 = f1
        f1 = f
     end do

     if ( abs ( bjv0 ) <= abs ( bjv1 ) ) then
        cs = bjv1 / f2
     else
        cs = bjv0 / f
     end if

     do k = 0, n
        vl(k) = cs * vl(k)
     end do

  end if

  vl(0) = fac * vl(0)
  do j = 1, n
     rc = fac * r0
     vl(j) = rc * vl(j)
     dl(j-1) = - 0.5D+00 * x / ( j + v0 ) * vl(j)
     r0 = 2.0D+00 * ( j + v0 + 1 ) / x * r0
  end do
  dl(n) = 2.0D+00 * ( v0 + n ) * ( vl(n-1) - vl(n) ) / x
  vm = n + v0

  return
end subroutine lamv
subroutine legzo ( n, x, w )

  !*****************************************************************************80
  !
  !! LEGZO computes the zeros of Legendre polynomials, and integration weights.
  !
  !  Discussion:
  !
  !    This procedure computes the zeros of Legendre polynomial Pn(x) in the 
  !    interval [-1,1], and the corresponding weighting coefficients for 
  !    Gauss-Legendre integration.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    13 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the order of the polynomial.
  !
  !    Output, real ( kind = 8 ) X(N), W(N), the zeros of the polynomial,
  !    and the corresponding weights.
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) fd
  real ( kind = 8 ) gd
  integer ( kind = 4 ) i
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) n0
  integer ( kind = 4 ) nr
  real ( kind = 8 ) p
  real ( kind = 8 ) pd
  real ( kind = 8 ) pf
  real ( kind = 8 ) q
  real ( kind = 8 ) w(n)
  real ( kind = 8 ) wp
  real ( kind = 8 ) x(n)
  real ( kind = 8 ) z
  real ( kind = 8 ) z0

  n0 = ( n + 1 ) / 2

  do nr = 1, n0

     z = cos ( 3.1415926D+00 * ( nr - 0.25D+00 ) / n )

     do

        z0 = z
        p = 1.0D+00
        do i = 1, nr - 1
           p = p * ( z - x(i))
        end do
        f0 = 1.0D+00
        if ( nr == n0 .and. n /= 2 * int ( n / 2 ) ) then
           z = 0.0D+00
        end if
        f1 = z
        do k = 2, n
           pf = ( 2.0D+00 - 1.0D+00 / k ) * z * f1 &
                - ( 1.0D+00 - 1.0D+00 / k ) * f0
           pd = k * ( f1 - z * pf ) / ( 1.0D+00 - z * z )
           f0 = f1
           f1 = pf
        end do

        if ( z == 0.0D+00 ) then
           exit
        end if

        fd = pf / p
        q = 0.0D+00
        do i = 1, nr - 1
           wp = 1.0D+00
           do j = 1, nr - 1
              if ( j /= i ) then
                 wp = wp * ( z - x(j) )
              end if
           end do
           q = q + wp
        end do
        gd = ( pd - q * fd ) / p
        z = z - fd / gd

        if ( abs ( z - z0 ) < abs ( z ) * 1.0D-15 ) then
           exit
        end if

     end do

     x(nr) = z
     x(n+1-nr) = - z
     w(nr) = 2.0D+00 / ( ( 1.0D+00 - z * z ) * pd * pd )
     w(n+1-nr) = w(nr)

  end do

  return
end subroutine legzo
subroutine lgama ( kf, x, gl )

  !*****************************************************************************80
  !
  !! LGAMA computes the gamma function or its logarithm.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    15 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KF, the argument code.
  !    1, for gamma(x);
  !    2, for ln(gamma(x)).
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) GL, the function value.
  !
  implicit none

  real ( kind = 8 ), save, dimension ( 10 ) :: a = (/ &
       8.333333333333333D-02, &
       -2.777777777777778D-03, &
       7.936507936507937D-04, &
       -5.952380952380952D-04, &
       8.417508417508418D-04, &
       -1.917526917526918D-03, &
       6.410256410256410D-03, &
       -2.955065359477124D-02, &
       1.796443723688307D-01, &
       -1.39243221690590D+00 /)
  real ( kind = 8 ) gl
  real ( kind = 8 ) gl0
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kf
  integer ( kind = 4 ) n
  real ( kind = 8 ) x
  real ( kind = 8 ) x0
  real ( kind = 8 ) x2
  real ( kind = 8 ) xp

  x0 = x

  if ( x == 1.0D+00 .or. x == 2.0D+00 ) then
     gl = 0.0D+00
     if ( kf == 1 ) then
        gl = 1.0D+00
     end if
     return
  else if ( x <= 7.0D+00 ) then
     n = int ( 7.0D+00 - x )
     x0 = x + n
  end if

  x2 = 1.0D+00 / ( x0 * x0 )
  xp = 6.283185307179586477D+00
  gl0 = a(10)

  do k = 9, 1, -1
     gl0 = gl0 * x2 + a(k)
  end do

  gl = gl0 / x0 + 0.5D+00 * log ( xp ) + ( x0 - 0.5D+00 ) * log ( x0 ) - x0

  if ( x <= 7.0D+00 ) then
     do k = 1, n
        gl = gl - log ( x0 - 1.0D+00 )
        x0 = x0 - 1.0D+00
     end do
  end if

  if ( kf == 1 ) then
     gl = exp ( gl )
  end if

  return
end subroutine lgama
subroutine lpmn ( mm, m, n, x, pm, pd )

  !*****************************************************************************80
  !
  !! LPMN computes associated Legendre functions Pmn(X) and derivatives P'mn(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    19 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) MM, the leading dimension of PM and PD.
  !
  !    Input, integer ( kind = 4 ) M, the order of Pmn(x).
  !
  !    Input, integer ( kind = 4 ) N, the degree of Pmn(x).
  !
  !    Input, real ( kind = 8 ) X, the argument of Pmn(x).
  !
  !    Output, real ( kind = 8 ) PM(0:MM,0:N), PD(0:MM,0:N), the
  !    values of Pmn(x) and Pmn'(x).
  !
  implicit none

  integer ( kind = 4 ) mm
  integer ( kind = 4 ) n

  integer ( kind = 4 ) i
  integer ( kind = 4 ) j
  integer ( kind = 4 ) ls
  integer ( kind = 4 ) m
  real ( kind = 8 ) pd(0:mm,0:n)
  real ( kind = 8 ) pm(0:mm,0:n)
  real ( kind = 8 ) x
  real ( kind = 8 ) xq
  real ( kind = 8 ) xs

  do i = 0, n
     do j = 0, m
        pm(j,i) = 0.0D+00
        pd(j,i) = 0.0D+00
     end do
  end do

  pm(0,0) = 1.0D+00

  if ( abs ( x ) == 1.0D+00 ) then

     do i = 1, n
        pm(0,i) = x ** i
        pd(0,i) = 0.5D+00 * i * ( i + 1.0D+00 ) * x ** ( i + 1 )
     end do

     do j = 1, n
        do i = 1, m
           if ( i == 1 ) then
              pd(i,j) = 1.0D+300
           else if ( i == 2 ) then
              pd(i,j) = -0.25D+00 * ( j + 2 ) * ( j + 1 ) * j &
                   * ( j - 1 ) * x ** ( j + 1 )
           end if
        end do
     end do

     return

  end if

  if ( 1.0D+00 < abs ( x ) ) then
     ls = -1
  else
     ls = +1
  end if

  xq = sqrt ( ls * ( 1.0D+00 - x * x ) )
  xs = ls * ( 1.0D+00 - x * x )
  do i = 1, m
     pm(i,i) = - ls * ( 2.0D+00 * i - 1.0D+00 ) * xq * pm(i-1,i-1)
  end do

  do i = 0, m
     pm(i,i+1) = ( 2.0D+00 * i + 1.0D+00 ) * x * pm(i,i)
  end do

  do i = 0, m
     do j = i + 2, n
        pm(i,j) = ( ( 2.0D+00 * j - 1.0D+00 ) * x * pm(i,j-1) - &
             ( i + j - 1.0D+00 ) * pm(i,j-2) ) / ( j - i )
     end do
  end do

  pd(0,0) = 0.0D+00
  do j = 1, n
     pd(0,j) = ls * j * ( pm(0,j-1) - x * pm(0,j) ) / xs
  end do

  do i = 1, m
     do j = i, n
        pd(i,j) = ls * i * x * pm(i,j) / xs + ( j + i ) &
             * ( j - i + 1.0D+00 ) / xq * pm(i-1,j)
     end do
  end do

  return
end subroutine lpmn
subroutine lpmns ( m, n, x, pm, pd )

  !*****************************************************************************80
  !
  !! LPMNS computes associated Legendre functions Pmn(X) and derivatives P'mn(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    18 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) M, the order of Pmn(x).
  !
  !    Input, integer ( kind = 4 ) N, the degree of Pmn(x).
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) PM(0:N), PD(0:N), the values and derivatives
  !    of the function from degree 0 to N.
  !
  implicit none

  integer ( kind = 4 ) n

  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  real ( kind = 8 ) pm(0:n)
  real ( kind = 8 ) pm0
  real ( kind = 8 ) pm1
  real ( kind = 8 ) pm2
  real ( kind = 8 ) pmk
  real ( kind = 8 ) pd(0:n)
  real ( kind = 8 ) x
  real ( kind = 8 ) x0

  do k = 0, n
     pm(k) = 0.0D+00
     pd(k) = 0.0D+00
  end do

  if ( abs ( x ) == 1.0D+00 ) then

     do k = 0, n
        if ( m == 0 ) then
           pm(k) = 1.0D+00
           pd(k) = 0.5D+00 * k * ( k + 1.0D+00 )
           if ( x < 0.0D+00 ) then
              pm(k) = ( -1.0D+00 ) ** k * pm(k)
              pd(k) = ( -1.0D+00 ) ** ( k + 1 ) * pd(k)
           end if
        else if ( m == 1 ) then
           pd(k) = 1.0D+300
        else if ( m == 2 ) then
           pd(k) = -0.25D+00 * ( k + 2.0D+00 ) * ( k + 1.0D+00 ) &
                * k * ( k - 1.0D+00 )
           if ( x < 0.0D+00 ) then
              pd(k) = ( -1.0D+00 ) ** ( k + 1 ) * pd(k)
           end if
        end if
     end do
     return
  end if

  x0 = abs ( 1.0D+00 - x * x )
  pm0 = 1.0D+00
  pmk = pm0
  do k = 1, m
     pmk = ( 2.0D+00 * k - 1.0D+00 ) * sqrt ( x0 ) * pm0
     pm0 = pmk
  end do
  pm1 = ( 2.0D+00 * m + 1.0D+00 ) * x * pm0
  pm(m) = pmk
  pm(m+1) = pm1
  do k = m + 2, n
     pm2 = ( ( 2.0D+00 * k - 1.0D+00 ) * x * pm1 &
          - ( k + m - 1.0D+00 ) * pmk ) / ( k - m )
     pm(k) = pm2
     pmk = pm1
     pm1 = pm2
  end do

  pd(0) = ( ( 1.0D+00 - m ) * pm(1) - x * pm(0) ) &
       / ( x * x - 1.0D+00 )  
  do k = 1, n
     pd(k) = ( k * x * pm(k) - ( k + m ) * pm(k-1) ) &
          / ( x * x - 1.0D+00 )
  end do

  return
end subroutine lpmns
subroutine lpmv ( v, m, x, pmv )

  !*****************************************************************************80
  !
  !! LPMV computes associated Legendre functions Pmv(X) with arbitrary degree.
  !
  !  Discussion:
  !
  !    Compute the associated Legendre function Pmv(x) with an integer order 
  !    and an arbitrary nonnegative degree v.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    19 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) V, the degree of Pmv(x).
  !
  !    Input, integer ( kind = 4 ) M, the order of Pmv(x).
  !
  !    Input, real ( kind = 8 ) X, the argument of Pm(x).
  !
  !    Output, real ( kind = 8 ) PMV, the value of Pm(x).
  !
  implicit none

  real ( kind = 8 ) c0
  real ( kind = 8 ) el
  real ( kind = 8 ) eps
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) m
  integer ( kind = 4 ) nv
  real ( kind = 8 ) pa
  real ( kind = 8 ) pi
  real ( kind = 8 ) pmv
  real ( kind = 8 ) pss
  real ( kind = 8 ) psv
  real ( kind = 8 ) pv0
  real ( kind = 8 ) qr
  real ( kind = 8 ) r
  real ( kind = 8 ) r0
  real ( kind = 8 ) r1
  real ( kind = 8 ) r2
  real ( kind = 8 ) rg
  real ( kind = 8 ) s
  real ( kind = 8 ) s0
  real ( kind = 8 ) s1
  real ( kind = 8 ) s2
  real ( kind = 8 ) v
  real ( kind = 8 ) v0
  real ( kind = 8 ) vs
  real ( kind = 8 ) x
  real ( kind = 8 ) xq

  pi = 3.141592653589793D+00
  el = 0.5772156649015329D+00
  eps = 1.0D-14
  nv = int ( v )
  v0 = v - nv

  if ( x == -1.0D+00 .and. v /= nv ) then
     if ( m == 0 ) then
        pmv = -1.0D+300
     else
        pmv = 1.0D+300
     end if
     return
  end if

  c0 = 1.0D+00

  if ( m /= 0 ) then

     rg = v * ( v + m )
     do j = 1, m - 1 
        rg = rg * ( v * v - j * j )
     end do
     xq = sqrt ( 1.0D+00 - x * x )
     r0 = 1.0D+00
     do j = 1, m
        r0 = 0.5D+00 * r0 * xq / j
     end do
     c0 = r0 * rg

  end if

  if ( v0 == 0.0D+00 ) then

     pmv = 1.0D+00
     r = 1.0D+00
     do k = 1, nv - m
        r = 0.5D+00 * r * ( - nv + m + k - 1.0D+00 ) &
             * ( nv + m + k ) / ( k * ( k + m ) ) * ( 1.0D+00 + x )
        pmv = pmv + r
     end do
     pmv = ( -1.0D+00 ) ** nv * c0 * pmv

  else

     if ( -0.35D+00 <= x ) then

        pmv = 1.0D+00
        r = 1.0D+00
        do k = 1, 100
           r = 0.5D+00 * r * ( - v + m + k - 1.0D+00 ) &
                * ( v + m + k ) / ( k * ( m + k ) ) * ( 1.0D+00 - x )
           pmv = pmv + r
           if ( 12 < k .and. abs ( r / pmv ) < eps ) then
              exit
           end if
        end do

        pmv = ( -1.0D+00 ) ** m * c0 * pmv

     else

        vs = sin ( v * pi ) / pi
        pv0 = 0.0D+00

        if ( m /= 0 ) then

           qr = sqrt ( ( 1.0D+00 - x ) / ( 1.0D+00 + x ) )
           r2 = 1.0D+00
           do j = 1, m
              r2 = r2 * qr * j
           end do
           s0 = 1.0D+00
           r1 = 1.0D+00
           do k = 1, m - 1 
              r1 = 0.5D+00 * r1 * ( - v + k - 1 ) * ( v + k ) &
                   / ( k * ( k - m ) ) * ( 1.0D+00 + x )
              s0 = s0 + r1
           end do
           pv0 = - vs * r2 / m * s0

        end if

        call psi ( v, psv )
        pa = 2.0D+00 * ( psv + el ) + pi / tan ( pi * v ) &
             + 1.0D+00 / v

        s1 = 0.0D+00
        do j = 1, m
           s1 = s1 + ( j * j + v * v ) / ( j * ( j * j - v * v ) )
        end do

        pmv = pa + s1 - 1.0D+00 / ( m - v ) &
             + log ( 0.5D+00 * ( 1.0D+00 + x ) )
        r = 1.0D+00
        do k = 1, 100
           r = 0.5D+00 * r * ( - v + m + k - 1.0D+00 ) * ( v + m + k ) &
                / ( k * ( k + m ) ) * ( 1.0D+00 + x )
           s = 0.0D+00
           do j = 1, m
              s = s + ( ( k + j ) ** 2 + v * v ) &
                   / ( ( k + j ) * ( ( k + j ) ** 2 - v * v ) )
           end do
           s2 = 0.0D+00
           do j = 1, k
              s2 = s2 + 1.0D+00 / ( j * ( j * j - v * v ) )
           end do
           pss = pa + s + 2.0D+00 * v * v * s2 &
                - 1.0D+00 / ( m + k - v ) &
                + log ( 0.5D+00 * ( 1.0D+00 + x ) )
           r2 = pss * r
           pmv = pmv + r2
           if ( abs ( r2 / pmv ) < eps ) then
              exit
           end if
        end do

        pmv = pv0 + pmv * vs * c0

     end if

  end if

  return
end subroutine lpmv
subroutine lpn ( n, x, pn, pd )

  !*****************************************************************************80
  !
  !! LPN computes Legendre polynomials Pn(x) and derivatives Pn'(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    07 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the maximum degree.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) PN(0:N), PD(0:N), the values and derivatives
  !    of the polyomials of degrees 0 to N at X.
  !
  implicit none

  integer ( kind = 4 ) n

  integer ( kind = 4 ) k
  real ( kind = 8 ) p0
  real ( kind = 8 ) p1
  real ( kind = 8 ) pd(0:n)
  real ( kind = 8 ) pf
  real ( kind = 8 ) pn(0:n)
  real ( kind = 8 ) x

  pn(0) = 1.0D+00
  pn(1) = x
  pd(0) = 0.0D+00
  pd(1) = 1.0D+00
  p0 = 1.0D+00
  p1 = x

  do k = 2, n

     pf = ( 2.0D+00 * k - 1.0D+00 ) / k * x * p1 &
          - ( k - 1.0D+00 ) / k * p0
     pn(k) = pf

     if ( abs ( x ) == 1.0D+00 ) then
        pd(k) = 0.5D+00 * x ** ( k + 1 ) * k * ( k + 1.0D+00 )
     else
        pd(k) = k * ( p1 - x * pf ) / ( 1.0D+00 - x * x )
     end if

     p0 = p1
     p1 = pf

  end do

  return
end subroutine lpn
subroutine lpni ( n, x, pn, pd, pl )

  !*****************************************************************************80
  !
  !! LPNI computes Legendre polynomials Pn(x), derivatives, and integrals.
  !
  !  Discussion:
  !
  !    This routine computes Legendre polynomials Pn(x), Pn'(x)
  !    and the integral of Pn(t) from 0 to x.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    13 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the maximum degree.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) PN(0:N), PD(0:N), PL(0:N), the values, 
  !    derivatives and integrals of the polyomials of degrees 0 to N at X.
  !
  implicit none

  integer ( kind = 4 ) n

  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) n1
  real ( kind = 8 ) p0
  real ( kind = 8 ) p1
  real ( kind = 8 ) pd(0:n)
  real ( kind = 8 ) pf
  real ( kind = 8 ) pl(0:n)
  real ( kind = 8 ) pn(0:n)
  real ( kind = 8 ) r
  real ( kind = 8 ) x

  pn(0) = 1.0D+00
  pn(1) = x
  pd(0) = 0.0D+00
  pd(1) = 1.0D+00
  pl(0) = x
  pl(1) = 0.5D+00 * x * x
  p0 = 1.0D+00
  p1 = x

  do k = 2, n

     pf = ( 2.0D+00 * k - 1.0D+00 ) / k * x * p1 - ( k - 1.0D+00 ) / k * p0
     pn(k) = pf

     if ( abs ( x ) == 1.0D+00 ) then
        pd(k) = 0.5D+00 * x ** ( k + 1 ) * k * ( k + 1.0D+00 )
     else
        pd(k) = k * ( p1 - x * pf ) / ( 1.0D+00 - x * x )
     end if

     pl(k) = ( x * pn(k) - pn(k-1) ) / ( k + 1.0D+00 )
     p0 = p1
     p1 = pf

     if ( k /= 2 * int ( k / 2 ) ) then

        r = 1.0D+00 / ( k + 1.0D+00 )
        n1 = ( k - 1 ) / 2
        do j = 1, n1
           r = ( 0.5D+00 / j - 1.0D+00 ) * r
        end do
        pl(k) = pl(k) + r

     end if

  end do

  return
end subroutine lpni
subroutine lqmn ( mm, m, n, x, qm, qd )

  !*****************************************************************************80
  !
  !! LQMN computes associated Legendre functions Qmn(x) and derivatives.
  !
  !  Discussion:
  !
  !    This routine computes the associated Legendre functions of the
  !    second kind, Qmn(x) and Qmn'(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    13 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) MM, determines the leading dimension 
  !    of QM and QD.
  !
  !    Input, integer ( kind = 4 ) M, the order of Qmn(x).
  !
  !    Input, integer ( kind = 4 ) N, the degree of Qmn(x).
  !
  !    Output, real ( kind = 8 ) QM(0:MM,0:N), QD(0:MM,0:N), contains the values
  !    of Qmn(x) and Qmn'(x).
  !
  implicit none

  integer ( kind = 4 ) mm
  integer ( kind = 4 ) n

  integer ( kind = 4 ) i
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) km
  integer ( kind = 4 ) ls
  integer ( kind = 4 ) m
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) q10
  real ( kind = 8 ) qd(0:mm,0:n)
  real ( kind = 8 ) qf
  real ( kind = 8 ) qf0
  real ( kind = 8 ) qf1
  real ( kind = 8 ) qf2
  real ( kind = 8 ) qm(0:mm,0:n)
  real ( kind = 8 ) x
  real ( kind = 8 ) xq
  real ( kind = 8 ) xs

  if ( abs ( x ) == 1.0D+00 ) then
     do i = 0, m
        do j = 0, n
           qm(i,j) = 1.0D+300
           qd(i,j) = 1.0D+300
        end do
     end do
     return
  end if

  if ( 1.0D+00 < abs ( x ) ) then
     ls = -1
  else
     ls = 1
  end if

  xs = ls * ( 1.0D+00 - x * x )
  xq = sqrt ( xs )
  q0 = 0.5D+00 * log ( abs ( ( x + 1.0D+00 ) / ( x - 1.0D+00 ) ) )

  if ( abs ( x ) < 1.0001D+00 ) then
     qm(0,0) = q0
     qm(0,1) = x * q0 - 1.0D+00
     qm(1,0) = -1.0D+00 / xq
     qm(1,1) = -xq * ( q0 + x / ( 1.0D+00 - x * x ) )
     do i = 0, 1
        do j = 2, n
           qm(i,j) = ( ( 2.0D+00 * j - 1.0D+00 ) * x * qm(i,j-1) &
                - ( j + i - 1.0D+00 ) * qm(i,j-2))/ ( j - i )
        end do
     end do

     do j = 0, n
        do i = 2, m
           qm(i,j) = -2.0D+00 * ( i - 1.0D+00 ) * x / xq * qm(i-1,j) &
                - ls * ( j + i - 1.0D+00 ) * ( j - i + 2.0D+00 ) * qm(i-2,j)
        end do
     end do

  else

     if ( 1.1D+00 < abs ( x ) ) then
        km = 40 + m + n
     else
        km = ( 40 + m + n ) &
             * int ( -1.0D+00 - 1.8D+00 * log ( x - 1.0D+00 ) )
     end if

     qf2 = 0.0D+00
     qf1 = 1.0D+00
     do k = km, 0, -1
        qf0 = ( ( 2 * k + 3.0D+00 ) * x * qf1 &
             - ( k + 2.0D+00 ) * qf2 ) / ( k + 1.0D+00 )
        if ( k <= n ) then
           qm(0,k) = qf0
        end if
        qf2 = qf1
        qf1 = qf0
     end do

     do k = 0, n
        qm(0,k) = q0 * qm(0,k) / qf0
     end do

     qf2 = 0.0D+00
     qf1 = 1.0D+00
     do k = km, 0, -1
        qf0 = ( ( 2 * k + 3.0D+00 ) * x * qf1 &
             - ( k + 1.0D+00 ) * qf2 ) / ( k + 2.0D+00 )
        if ( k <= n ) then
           qm(1,k) = qf0
        end if
        qf2 = qf1
        qf1 = qf0
     end do

     q10 = -1.0D+00 / xq
     do k = 0, n
        qm(1,k) = q10 * qm(1,k) / qf0
     end do

     do j = 0, n
        q0 = qm(0,j)
        q1 = qm(1,j)
        do i = 0, m - 2
           qf = -2.0D+00 * ( i + 1 ) * x / xq * q1 &
                + ( j - i ) * ( j + i + 1.0D+00 ) * q0
           qm(i+2,j) = qf
           q0 = q1
           q1 = qf
        end do
     end do

  end if

  qd(0,0) = ls / xs
  do j = 1, n
     qd(0,j) = ls * j * ( qm(0,j-1) - x * qm(0,j) ) / xs
  end do

  do j = 0, n
     do i = 1, m
        qd(i,j) = ls * i * x / xs * qm(i,j) &
             + ( i + j ) * ( j - i + 1.0D+00 ) / xq * qm(i-1,j)
     end do
  end do

  return
end subroutine lqmn
subroutine lqmns ( m, n, x, qm, qd )

  !*****************************************************************************80
  !
  !! LQMNS computes associated Legendre functions Qmn(x) and derivatives Qmn'(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    28 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) M, the order.
  !
  !    Input, integer ( kind = 4 ) N, the degree.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) QM(0:N), QD(0:N), the values of Qmn(x) 
  !    and Qmn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  integer ( kind = 4 ) k
  integer ( kind = 4 ) km
  integer ( kind = 4 ) l
  integer ( kind = 4 ) ls
  integer ( kind = 4 ) m
  real ( kind = 8 ) q0
  real ( kind = 8 ) q00
  real ( kind = 8 ) q01
  real ( kind = 8 ) q0l
  real ( kind = 8 ) q10
  real ( kind = 8 ) q11
  real ( kind = 8 ) q1l
  real ( kind = 8 ) qd(0:n)
  real ( kind = 8 ) qf0
  real ( kind = 8 ) qf1
  real ( kind = 8 ) qf2
  real ( kind = 8 ) qg0
  real ( kind = 8 ) qg1
  real ( kind = 8 ) qh0
  real ( kind = 8 ) qh1
  real ( kind = 8 ) qh2
  real ( kind = 8 ) qm(0:n)
  real ( kind = 8 ) qm0
  real ( kind = 8 ) qm1
  real ( kind = 8 ) qmk
  real ( kind = 8 ) x
  real ( kind = 8 ) xq

  do k = 0, n
     qm(k) = 0.0D+00
     qd(k) = 0.0D+00
  end do

  if ( abs ( x ) == 1.0D+00 ) then
     do k = 0, n
        qm(k) = 1.0D+300
        qd(k) = 1.0D+300
     end do
     return
  end if

  if ( 1.0D+00 < abs ( x ) ) then
     ls = -1
  else
     ls = +1
  end if

  xq = sqrt ( ls * ( 1.0D+00 - x * x ) )
  q0 = 0.5D+00 * log ( abs ( ( x + 1.0D+00 ) / ( x - 1.0D+00 ) ) )
  q00 = q0
  q10 = -1.0D+00 / xq
  q01 = x * q0 - 1.0D+00
  q11 = - ls * xq * ( q0 + x / ( 1.0D+00 - x * x ) )
  qf0 = q00
  qf1 = q10
  do k = 2, m
     qm0 = -2.0D+00 * ( k - 1.0D+00 ) / xq * x * qf1 &
          - ls * ( k - 1.0D+00 ) * ( 2.0D+00 - k ) * qf0
     qf0 = qf1
     qf1 = qm0
  end do

  if ( m == 0 ) then
     qm0 = q00
  else if ( m == 1 ) then
     qm0 = q10
  end if

  qm(0) = qm0

  if ( abs ( x ) < 1.0001D+00 ) then

     if ( m == 0 .and. 0 < n ) then

        qf0 = q00
        qf1 = q01
        do k = 2, n
           qf2 = ( ( 2.0D+00 * k - 1.0D+00 ) * x * qf1 &
                - ( k - 1.0D+00 ) * qf0 ) / k
           qm(k) = qf2
           qf0 = qf1
           qf1 = qf2
        end do

     end if
     qg0 = q01
     qg1 = q11
     do k = 2, m
        qm1 = - 2.0D+00 * ( k - 1.0D+00 ) / xq * x * qg1 &
             - ls * k * ( 3.0D+00 - k ) * qg0
        qg0 = qg1
        qg1 = qm1
     end do

     if ( m == 0 ) then
        qm1 = q01
     else if ( m == 1 ) then
        qm1 = q11
     end if
     qm(1) = qm1

     if ( m == 1 .and. 1 < n ) then

        qh0 = q10
        qh1 = q11
        do k = 2, n
           qh2 = ( ( 2.0D+00 * k - 1.0D+00 ) * x * qh1 - k * qh0 ) &
                / ( k - 1.0D+00 )
           qm(k) = qh2
           qh0 = qh1
           qh1 = qh2
        end do

     else if ( 2 <= m ) then

        qg0 = q00
        qg1 = q01
        qh0 = q10
        qh1 = q11

        do l = 2, n
           q0l = ( ( 2.0D+00 * l - 1.0D+00 ) * x * qg1 &
                - ( l - 1.0D+00 ) * qg0 ) / l
           q1l = ( ( 2.0D+00 * l - 1.0D+00 ) * x * qh1 - l * qh0 ) &
                / ( l - 1.0D+00 )
           qf0 = q0l
           qf1 = q1l
           do k = 2, m
              qmk = - 2.0D+00 * ( k - 1.0D+00 ) / xq * x * qf1 &
                   - ls * ( k + l - 1.0D+00 ) * ( l + 2.0D+00 - k ) * qf0
              qf0 = qf1
              qf1 = qmk
           end do
           qm(l) = qmk
           qg0 = qg1
           qg1 = q0l
           qh0 = qh1
           qh1 = q1l
        end do

     end if

  else

     if ( 1.1D+00 < abs ( x ) ) then
        km = 40 + m + n
     else
        km = ( 40 + m + n ) * int ( - 1.0D+00 - 1.8D+00 * log ( x - 1.0D+00 ) )
     end if

     qf2 = 0.0D+00
     qf1 = 1.0D+00
     do k = km, 0, -1
        qf0 = ( ( 2.0D+00 * k + 3.0D+00 ) * x * qf1 &
             - ( k + 2.0D+00 - m ) * qf2 ) / ( k + m + 1.0D+00 )
        if ( k <= n ) then
           qm(k) = qf0
        end if
        qf2 = qf1
        qf1 = qf0
     end do

     do k = 0, n
        qm(k) = qm(k) * qm0 / qf0
     end do

  end if

  if ( abs ( x ) < 1.0D+00 ) then
     do k = 0, n
        qm(k) = ( -1 ) ** m * qm(k)
     end do
  end if

  qd(0) = ( ( 1.0D+00 - m ) * qm(1) - x * qm(0) )  / ( x * x - 1.0D+00 )
  do k = 1, n
     qd(k) = ( k * x * qm(k) - ( k + m ) * qm(k-1) ) / ( x * x - 1.0D+00 )
  end do

  return
end subroutine lqmns
subroutine lqna ( n, x, qn, qd )

  !*****************************************************************************80
  !
  !! LQNA computes Legendre function Qn(x) and derivatives Qn'(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    19 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the degree of Qn(x).
  !
  !    Input, real ( kind = 8 ) X, the argument of Qn(x).
  !
  !    Output, real ( kind = 8 ) QN(0:N), QD(0:N), the values of
  !    Qn(x) and Qn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  integer ( kind = 4 ) k
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) qd(0:n)
  real ( kind = 8 ) qf
  real ( kind = 8 ) qn(0:n)
  real ( kind = 8 ) x

  if ( abs ( x ) == 1.0D+00 ) then

     do k = 0, n
        qn(k) = 1.0D+300
        qd(k) = -1.0D+300
     end do

  else if ( abs ( x ) < 1.0D+00 ) then

     q0 = 0.5D+00 * log ( ( 1.0D+00 + x ) / ( 1.0D+00 - x ) )
     q1 = x * q0 - 1.0D+00
     qn(0) = q0
     qn(1) = q1
     qd(0) = 1.0D+00 / ( 1.0D+00 - x * x )
     qd(1) = qn(0) + x * qd(0)
     do k = 2, n
        qf = ( ( 2 * k - 1 ) * x * q1 - ( k - 1 ) * q0 ) / k
        qn(k) = qf
        qd(k) = ( qn(k-1) - x * qf ) * k / ( 1.0D+00 - x * x )
        q0 = q1
        q1 = qf
     end do

  end if

  return
end subroutine lqna
subroutine lqnb ( n, x, qn, qd )

  !*****************************************************************************80
  !
  !! LQNB computes Legendre function Qn(x) and derivatives Qn'(x).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    19 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) N, the degree of Qn(x).
  !
  !    Input, real ( kind = 8 ) X, the argument of Qn(x).
  !
  !    Output, real ( kind = 8 ) QN(0:N), QD(0:N), the values of
  !    Qn(x) and Qn'(x).
  !
  implicit none

  integer ( kind = 4 ) n

  real ( kind = 8 ) eps
  integer ( kind = 4 ) j
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  integer ( kind = 4 ) nl
  real ( kind = 8 ) q0
  real ( kind = 8 ) q1
  real ( kind = 8 ) qc1
  real ( kind = 8 ) qc2
  real ( kind = 8 ) qd(0:n)
  real ( kind = 8 ) qf
  real ( kind = 8 ) qf0
  real ( kind = 8 ) qf1
  real ( kind = 8 ) qf2
  real ( kind = 8 ) qn(0:n)
  real ( kind = 8 ) qr
  real ( kind = 8 ) x
  real ( kind = 8 ) x2

  eps = 1.0D-14

  if ( abs ( x ) == 1.0D+00 ) then
     do k = 0, n
        qn(k) = 1.0D+300
        qd(k) = 1.0D+300
     end do
     return
  end if

  if ( x <= 1.021D+00 ) then

     x2 = abs ( ( 1.0D+00 + x ) / ( 1.0D+00 - x ) )
     q0 = 0.5D+00 * log ( x2 )
     q1 = x * q0 - 1.0D+00
     qn(0) = q0
     qn(1) = q1
     qd(0) = 1.0D+00 / ( 1.0D+00 - x * x )
     qd(1) = qn(0) + x * qd(0)
     do k = 2, n
        qf = ( ( 2.0D+00 * k - 1.0D+00 ) * x * q1 &
             - ( k - 1.0D+00 ) * q0 ) / k
        qn(k) = qf
        qd(k) = ( qn(k-1) - x * qf ) * k / ( 1.0D+00 - x * x )
        q0 = q1
        q1 = qf
     end do

  else

     qc2 = 1.0D+00 / x
     do j = 1, n
        qc2 = qc2 * j / ( ( 2.0D+00 * j + 1.0D+00 ) * x )
        if ( j == n - 1 ) then
           qc1 = qc2
        end if
     end do

     do l = 0, 1

        nl = n + l
        qf = 1.0D+00
        qr = 1.0D+00
        do k = 1, 500
           qr = qr * ( 0.5D+00 * nl + k - 1.0D+00 ) &
                * ( 0.5D+00 * ( nl - 1 ) + k ) &
                / ( ( nl + k - 0.5D+00 ) * k * x * x )
           qf = qf + qr
           if ( abs ( qr / qf ) < eps ) then
              exit
           end if
        end do

        if ( l == 0 ) then
           qn(n-1) = qf * qc1
        else
           qn(n) = qf * qc2
        end if

     end do

     qf2 = qn(n)
     qf1 = qn(n-1)
     do k = n, 2, -1
        qf0 = ( ( 2.0D+00 * k - 1.0D+00 ) * x * qf1 - k * qf2 ) / ( k - 1.0D+00 )
        qn(k-2) = qf0
        qf2 = qf1
        qf1 = qf0
     end do

     qd(0) = 1.0D+00 / ( 1.0D+00 - x * x )
     do k = 1, n
        qd(k) = k * ( qn(k-1) - x * qn(k) ) / ( 1.0D+00 - x * x )
     end do

  end if

  return
end subroutine lqnb
function msta1 ( x, mp )

  !*****************************************************************************80
  !
  !! MSTA1 determines a backward recurrence starting point for Jn(x).
  !
  !  Discussion:
  !
  !    This procedure determines the starting point for backward  
  !    recurrence such that the magnitude of    
  !    Jn(x) at that point is about 10^(-MP).
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    08 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Input, integer ( kind = 4 ) MP, the negative logarithm of the 
  !    desired magnitude.
  !
  !    Output, integer ( kind = 4 ) MSTA1, the starting point.
  !
  implicit none

  real ( kind = 8 ) a0
  ! real ( kind = 8 ) envj
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  integer ( kind = 4 ) it
  integer ( kind = 4 ) mp
  integer ( kind = 4 ) msta1
  integer ( kind = 4 ) n0
  integer ( kind = 4 ) n1
  integer ( kind = 4 ) nn
  real ( kind = 8 ) x

  a0 = abs ( x )
  n0 = int ( 1.1D+00 * a0 ) + 1
  f0 = envj ( n0, a0 ) - mp
  n1 = n0 + 5
  f1 = envj ( n1, a0 ) - mp
  do it = 1, 20       
     nn = n1 - ( n1 - n0 ) / ( 1.0D+00 - f0 / f1 )                  
     f = envj ( nn, a0 ) - mp
     if ( abs ( nn - n1 ) < 1 ) then
        exit
     end if
     n0 = n1
     f0 = f1
     n1 = nn
     f1 = f
  end do

  msta1 = nn

  return
end function msta1

function msta2 ( x, n, mp )

  !*****************************************************************************80
  !
  !! MSTA2 determines a backward recurrence starting point for Jn(x).
  !
  !  Discussion:
  !
  !    This procedure determines the starting point for a backward
  !    recurrence such that all Jn(x) has MP significant digits.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    08 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument of Jn(x).
  !
  !    Input, integer ( kind = 4 ) N, the order of Jn(x).
  !
  !    Input, integer ( kind = 4 ) MP, the number of significant digits.
  !
  !    Output, integer ( kind = 4 ) MSTA2, the starting point.
  !
  implicit none

  real ( kind = 8 ) a0
  real ( kind = 8 ) ejn
  ! real ( kind = 8 ) envj
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  real ( kind = 8 ) hmp
  integer ( kind = 4 ) it
  integer ( kind = 4 ) mp
  integer ( kind = 4 ) msta2
  integer ( kind = 4 ) n
  integer ( kind = 4 ) n0
  integer ( kind = 4 ) n1
  integer ( kind = 4 ) nn
  real ( kind = 8 ) obj
  real ( kind = 8 ) x

  a0 = abs ( x )
  hmp = 0.5D+00 * mp
  ejn = envj ( n, a0 )

  if ( ejn <= hmp ) then
     obj = mp
     n0 = int ( 1.1D+00 * a0 )
  else
     obj = hmp + ejn
     n0 = n
  end if

  f0 = envj ( n0, a0 ) - obj
  n1 = n0 + 5
  f1 = envj ( n1, a0 ) - obj

  do it = 1, 20
     nn = n1 - ( n1 - n0 ) / ( 1.0D+00 - f0 / f1 )
     f = envj ( nn, a0 ) - obj
     if ( abs ( nn - n1 ) < 1 ) then
        exit
     end if
     n0 = n1
     f0 = f1
     n1 = nn
     f1 = f
  end do

  msta2 = nn + 10

  return
end function msta2
subroutine mtu0 ( kf, m, q, x, csf, csd )

  !*****************************************************************************80
  !
  !! MTU0 computes Mathieu functions CEM(x,q) and SEM(x,q) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    20 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KF, the function code.
  !    1 for computing cem(x,q) and cem'(x,q)
  !    2 for computing sem(x,q) and sem'(x,q).
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) X, the argument of the Mathieu functions,
  !    in degrees.
  !
  !    Output, real ( kind = 8 ) CSF, CSD, the values of cem(x,q) and cem'(x,q),
  !    or of sem(x,q) and sem'(x,q).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) csd
  real ( kind = 8 ) csf
  real ( kind = 8 ) eps
  real ( kind = 8 ) fg(251)
  integer ( kind = 4 ) ic
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) kf
  integer ( kind = 4 ) km
  integer ( kind = 4 ) m
  real ( kind = 8 ) q
  real ( kind = 8 ) qm
  real ( kind = 8 ) rd
  real ( kind = 8 ) x
  real ( kind = 8 ) xr

  eps = 1.0D-14

  if ( kf == 1 ) then

     if ( m == 2 * int ( m / 2 ) ) then
        kd = 1
     else
        kd = 2
     end if

  else

     if ( m /= 2 * int ( m / 2 ) ) then
        kd = 3
     else
        kd = 4
     end if

  end if

  call cva2 ( kd, m, q, a )

  if ( q <= 1.0D+00 ) then
     qm = 7.5D+00 + 56.1D+00 * sqrt ( q ) - 134.7D+00 * q &
          + 90.7D+00 * sqrt ( q ) * q
  else
     qm = 17.0D+00 + 3.1D+00 * sqrt ( q ) - 0.126D+00 * q &
          + 0.0037D+00 * sqrt ( q ) * q
  end if

  km = int ( qm + 0.5D+00 * m )
  call fcoef ( kd, m, q, a, fg )
  ic = int ( m / 2 ) + 1
  rd = 1.74532925199433D-02
  xr = x * rd

  csf = 0.0D+00

  do k = 1, km

     if ( kd == 1 ) then
        csf = csf + fg(k) * cos ( ( 2.0D+00 * k - 2.0D+00 ) * xr )
     else if ( kd == 2 ) then
        csf = csf + fg(k) * cos ( ( 2.0D+00 * k - 1.0D+00 ) * xr )
     else if ( kd == 3 ) then
        csf = csf + fg(k) * sin ( ( 2.0D+00 * k - 1.0D+00 ) * xr )
     else if ( kd == 4 ) then
        csf = csf + fg(k) * sin ( 2.0D+00 * k * xr )
     end if

     if ( ic <= k .and. abs ( fg(k) ) < abs ( csf ) * eps ) then
        exit
     end if

  end do

  csd = 0.0D+00

  do k = 1, km

     if ( kd == 1 ) then
        csd = csd - ( 2 * k - 2 ) * fg(k) * sin ( ( 2 * k - 2 ) * xr )
     else if ( kd == 2 ) then
        csd = csd - ( 2 * k - 1 ) * fg(k) * sin ( ( 2 * k - 1 ) * xr )
     else if ( kd == 3 ) then
        csd = csd + ( 2 * k - 1 ) * fg(k) * cos ( ( 2 * k - 1 ) * xr )
     else if ( kd == 4 ) then
        csd = csd + 2.0D+00 * k * fg(k) * cos ( 2 * k * xr )
     end if

     if ( ic <= k .and. abs ( fg(k) ) < abs ( csd ) * eps ) then
        exit
     end if

  end do

  return
end subroutine mtu0
subroutine mtu12 ( kf, kc, m, q, x, f1r, d1r, f2r, d2r )

  !*****************************************************************************80
  !
  !! MTU12 computes modified Mathieu functions of the first and second kind.
  !
  !  Discussion:
  !
  !    This procedure computes modified Mathieu functions of the first and
  !    second kinds, Mcm(1)(2)(x,q) and Msm(1)(2)(x,q),
  !    and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    31 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KF, the function code.
  !    1 for computing Mcm(x,q);
  !    2 for computing Msm(x,q).
  !
  !    Input, integer ( kind = 4 ) KC, the function code.
  !    1, for computing the first kind
  !    2, for computing the second kind or Msm(2)(x,q) and Msm(2)'(x,q)
  !    3, for computing both the first and second kinds.
  !
  !    Input, integer ( kind = 4 ) M, the order of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) Q, the parameter of the Mathieu functions.
  !
  !    Input, real ( kind = 8 ) X, the argument of the Mathieu functions.
  !
  !    Output, real ( kind = 8 ) F1R, D1R, F2R, D2R, the values of 
  !    Mcm(1)(x,q) or Msm(1)(x,q), Derivative of Mcm(1)(x,q) or Msm(1)(x,q),
  !    Mcm(2)(x,q) or Msm(2)(x,q), Derivative of Mcm(2)(x,q) or Msm(2)(x,q).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) bj1(0:251)
  real ( kind = 8 ) bj2(0:251)
  real ( kind = 8 ) by1(0:251)
  real ( kind = 8 ) by2(0:251)
  real ( kind = 8 ) c1
  real ( kind = 8 ) c2
  real ( kind = 8 ) d1r
  real ( kind = 8 ) d2r
  real ( kind = 8 ) dj1(0:251)
  real ( kind = 8 ) dj2(0:251)
  real ( kind = 8 ) dy1(0:251)
  real ( kind = 8 ) dy2(0:251)
  real ( kind = 8 ) eps
  real ( kind = 8 ) f1r
  real ( kind = 8 ) f2r
  real ( kind = 8 ) fg(251)
  integer ( kind = 4 ) ic
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kc
  integer ( kind = 4 ) kd
  integer ( kind = 4 ) kf
  integer ( kind = 4 ) km
  integer ( kind = 4 ) m
  integer ( kind = 4 ) nm
  real ( kind = 8 ) q
  real ( kind = 8 ) qm
  real ( kind = 8 ) u1
  real ( kind = 8 ) u2
  real ( kind = 8 ) w1
  real ( kind = 8 ) w2
  real ( kind = 8 ) x

  eps = 1.0D-14

  if ( kf == 1 ) then
     if ( m == 2 * int ( m / 2 ) ) then
        kd = 1
     else
        kd = 2
     end if
  else
     if ( m /= 2 * int ( m / 2 ) ) then
        kd = 3
     else
        kd = 4
     end if
  end if

  call cva2 ( kd, m, q, a )

  if ( q <= 1.0D+00 ) then
     qm = 7.5D+00 + 56.1D+00 * sqrt ( q ) - 134.7D+00 * q &
          + 90.7D+00 * sqrt ( q ) * q
  else
     qm = 17.0D+00 + 3.1D+00 * sqrt ( q ) - 0.126D+00 * q &
          + 0.0037D+00 * sqrt ( q ) * q
  end if

  km = int ( qm + 0.5D+00 * m )              
  call fcoef ( kd, m, q, a, fg )

  if ( kd == 4 ) then
     ic = m / 2
  else
     ic = int ( m / 2 ) + 1
  end if

  c1 = exp ( - x )
  c2 = exp ( x )
  u1 = sqrt ( q ) * c1
  u2 = sqrt ( q ) * c2

  call jynb ( km, u1, nm, bj1, dj1, by1, dy1 )
  call jynb ( km, u2, nm, bj2, dj2, by2, dy2 )

  if ( kc == 1 ) then

     f1r = 0.0D+00

     do k = 1, km

        if ( kd == 1 ) then
           f1r = f1r + ( - 1.0D+00 ) ** ( ic + k ) * fg(k) * bj1(k-1) * bj2(k-1)
        else if ( kd == 2 .or. kd == 3 ) then
           f1r = f1r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) * ( bj1(k-1) * bj2(k) &
                + ( - 1.0D+00 ) ** kd * bj1(k) * bj2(k-1) )
        else
           f1r = f1r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( bj1(k-1) * bj2(k+1) - bj1(k+1) * bj2(k-1) )
        end if

        if ( 5 <= k .and. abs ( f1r - w1 ) < abs ( f1r ) * eps ) then
           exit
        end if

        w1 = f1r

     end do

     f1r = f1r / fg(1)
     d1r = 0.0D+00
     do k = 1, km
        if ( kd == 1 ) then
           d1r = d1r + ( - 1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( c2 * bj1(k-1) * dj2(k-1) - c1 * dj1(k-1) * bj2(k-1) )
        else if ( kd == 2 .or. kd == 3 ) then
           d1r = d1r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( c2 * ( bj1(k-1) * dj2(k) &
                + ( -1.0D+00 ) ** kd * bj1(k) * dj2(k-1) ) &
                - c1 * ( dj1(k-1) * bj2(k) &
                + ( -1.0D+00 ) ** kd * dj1(k) * bj2(k-1) ) )
        else
           d1r = d1r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( c2 * ( bj1(k-1) * dj2(k+1) - bj1(k+1) * dj2(k-1) ) &
                - c1 * ( dj1(k-1) * bj2(k+1) - dj1(k+1) * bj2(k-1) ) )
        end if
        if ( 5 <= k .and. abs ( d1r - w2 ) < abs ( d1r ) * eps ) then
           exit
        end if
        w2 = d1r
     end do

     d1r = d1r * sqrt ( q ) / fg(1)

  else

     f2r = 0.0D+00

     do k = 1, km
        if ( kd == 1 ) then
           f2r = f2r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * bj1(k-1) * by2(k-1)
        else if ( kd == 2 .or. kd == 3 ) then
           f2r = f2r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) * ( bj1(k-1) * by2(k) &
                + ( -1.0D+00 ) ** kd * bj1(k) * by2(k-1) )
        else
           f2r = f2r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( bj1(k-1) * by2(k+1) - bj1(k+1) * by2(k-1) )
        end if
        if ( 5 <= k .and. abs ( f2r - w1 ) < abs ( f2r ) * eps ) then
           exit
        end if
        w1 = f2r
     end do

     f2r = f2r / fg(1)
     d2r = 0.0D+00

     do k = 1, km
        if ( kd == 1 ) then
           d2r = d2r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( c2 * bj1(k-1) * dy2(k-1) - c1 * dj1(k-1) * by2(k-1) )
        else if ( kd == 2 .or. kd == 3 ) then
           d2r = d2r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( c2 * ( bj1(k-1) * dy2(k) &
                + ( -1.0D+00 ) ** kd * bj1(k) * dy2(k-1) ) &
                - c1 * ( dj1(k-1) * by2(k) + ( -1.0D+00 ) ** kd &
                * dj1(k) * by2(k-1) ) )
        else
           d2r = d2r + ( -1.0D+00 ) ** ( ic + k ) * fg(k) &
                * ( c2 * ( bj1(k-1) * dy2(k+1) - bj1(k+1) * dy2(k-1) ) &
                - c1 * ( dj1(k-1) * by2(k+1) - dj1(k+1) * by2(k-1) ) )
        end if

        if ( 5 <= k .and. abs ( d2r - w2 ) < abs ( d2r ) * eps ) then
           exit
        end if

        w2 = d2r

     end do

     d2r = d2r * sqrt ( q ) / fg(1)

  end if

  return
end subroutine mtu12
subroutine othpl ( kf, n, x, pl, dpl )

  !*****************************************************************************80
  !
  !! OTHPL computes orthogonal polynomials Tn(x), Un(x), Ln(x) or Hn(x).
  !
  !  Discussion:
  !
  !    This procedure computes orthogonal polynomials: Tn(x) or Un(x),
  !    or Ln(x) or Hn(x), and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    08 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, integer ( kind = 4 ) KT, the function code:
  !    1 for Chebyshev polynomial Tn(x)
  !    2 for Chebyshev polynomial Un(x)
  !    3 for Laguerre polynomial Ln(x)
  !    4 for Hermite polynomial Hn(x)
  !
  !    Input, integer ( kind = 4 ) N, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) PL(0:N), DPL(0:N), the value and derivative of
  !    the polynomials of order 0 through N at X.
  !
  implicit none

  integer n

  real ( kind = 8 ) a
  real ( kind = 8 ) b
  real ( kind = 8 ) c
  real ( kind = 8 ) dpl(0:n)
  real ( kind = 8 ) dy0
  real ( kind = 8 ) dy1
  real ( kind = 8 ) dyn
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kf
  real ( kind = 8 ) pl(0:n)
  real ( kind = 8 ) x
  real ( kind = 8 ) y0
  real ( kind = 8 ) y1
  real ( kind = 8 ) yn

  a = 2.0D+00
  b = 0.0D+00
  c = 1.0D+00
  y0 = 1.0D+00
  y1 = 2.0D+00 * x
  dy0 = 0.0D+00
  dy1 = 2.0D+00
  pl(0) = 1.0D+00
  pl(1) = 2.0D+00 * x
  dpl(0) = 0.0D+00
  dpl(1) = 2.0D+00

  if ( kf == 1 ) then
     y1 = x
     dy1 = 1.0D+00
     pl(1) = x
     dpl(1) = 1.0D+00
  else if ( kf == 3 ) then
     y1 = 1.0D+00 - x
     dy1 = -1.0D+00
     pl(1) = 1.0D+00 - x
     dpl(1) = -1.0D+00
  end if

  do k = 2, n

     if ( kf == 3 ) then
        a = -1.0D+00 / k
        b = 2.0D+00 + a
        c = 1.0D+00 + a
     else if ( kf == 4 ) then
        c = 2.0D+00 * ( k - 1.0D+00 )
     end if

     yn = ( a * x + b ) * y1 - c * y0
     dyn = a * y1 + ( a * x + b ) * dy1 - c * dy0
     pl(k) = yn
     dpl(k) = dyn
     y0 = y1
     y1 = yn
     dy0 = dy1
     dy1 = dyn

  end do

  return
end subroutine othpl
subroutine pbdv ( v, x, dv, dp, pdf, pdd )

  !*****************************************************************************80
  !
  !! PBDV computes parabolic cylinder functions Dv(x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    29 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) V, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) DV(0:*), DP(0:*), the values of
  !    Dn+v0(x), Dn+v0'(x).
  !
  !    Output, real ( kind = 8 ) PDF, PDD, the values of Dv(x) and Dv'(x).
  !
  implicit none

  real ( kind = 8 ) dp(0:*)
  real ( kind = 8 ) dv(0:*)
  real ( kind = 8 ) ep
  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  integer ( kind = 4 ) ja
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
  integer ( kind = 4 ) na
  integer ( kind = 4 ) nk
  integer ( kind = 4 ) nv
  real ( kind = 8 ) pd
  real ( kind = 8 ) pd0
  real ( kind = 8 ) pd1
  real ( kind = 8 ) pdd
  real ( kind = 8 ) pdf
  real ( kind = 8 ) s0
  real ( kind = 8 ) v
  real ( kind = 8 ) v0
  real ( kind = 8 ) v1
  real ( kind = 8 ) v2
  real ( kind = 8 ) vh
  real ( kind = 8 ) x
  real ( kind = 8 ) xa

  xa = abs ( x )
  vh = v
  v = v + sign ( 1.0D+00, v )
  nv = int ( v )
  v0 = v - nv
  na = abs ( nv )
  ep = exp ( -0.25D+00 * x * x )

  if ( 1 <= na ) then
     ja = 1
  end if

  if ( 0.0D+00 <= v ) then
     if ( v0 == 0.0D+00 ) then
        pd0 = ep
        pd1 = x * ep
     else
        do l = 0, ja
           v1 = v0 + l
           if ( xa <= 5.8D+00 ) then
              call dvsa ( v1, x, pd1 )
           else
              call dvla ( v1, x, pd1 )
           end if
           if ( l == 0 ) then
              pd0 = pd1
           end if
        end do
     end if

     dv(0) = pd0
     dv(1) = pd1
     do k = 2, na
        pdf = x * pd1 - ( k + v0 - 1.0D+00 ) * pd0
        dv(k) = pdf
        pd0 = pd1
        pd1 = pdf
     end do

  else

     if ( x <= 0.0D+00 ) then

        if ( xa <= 5.8D+00 )  then
           call dvsa ( v0, x, pd0 )
           v1 = v0 - 1.0D+00
           call dvsa ( v1, x, pd1 )
        else
           call dvla ( v0, x, pd0 )
           v1 = v0 - 1.0D+00
           call dvla ( v1, x, pd1 )
        end if

        dv(0) = pd0
        dv(1) = pd1
        do k = 2, na
           pd = ( - x * pd1 + pd0 ) / ( k - 1.0D+00 - v0 )
           dv(k) = pd
           pd0 = pd1
           pd1 = pd
        end do

     else if ( x <= 2.0D+00 ) then

        v2 = nv + v0
        if ( nv == 0 ) then
           v2 = v2 - 1.0D+00
        end if

        nk = int ( - v2 )
        call dvsa ( v2, x, f1 )
        v1 = v2 + 1.0D+00
        call dvsa ( v1, x, f0 )
        dv(nk) = f1
        dv(nk-1) = f0
        do k = nk - 2, 0, -1
           f = x * f0 + ( k - v0 + 1.0D+00 ) * f1
           dv(k) = f
           f1 = f0
           f0 = f
        end do

     else

        if ( xa <= 5.8D+00 ) then
           call dvsa ( v0, x, pd0 )
        else
           call dvla ( v0, x, pd0 )
        end if

        dv(0) = pd0
        m = 100 + na
        f1 = 0.0D+00
        f0 = 1.0D-30
        do k = m, 0, -1
           f = x * f0 + ( k - v0 + 1.0D+00 ) * f1
           if ( k <= na ) then
              dv(k) = f
           end if
           f1 = f0
           f0 = f
        end do
        s0 = pd0 / f
        do k = 0, na
           dv(k) = s0 * dv(k)
        end do

     end if

  end if

  do k = 0, na - 1
     v1 = abs ( v0 ) + k
     if ( 0.0D+00 <= v ) then
        dp(k) = 0.5D+00 * x * dv(k) - dv(k+1)
     else
        dp(k) = -0.5D+00 * x * dv(k) - v1 * dv(k+1)
     end if
  end do

  pdf = dv(na-1)
  pdd = dp(na-1)
  v = vh

  return
end subroutine pbdv
subroutine pbvv ( v, x, vv, vp, pvf, pvd )

  !*****************************************************************************80
  !
  !! PBVV computes parabolic cylinder functions Vv(x) and their derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    29 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) V, the order.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) VV(0:*), VP(0:*), the values of Vv(x), Vv'(x).
  !
  !    Output, real ( kind = 8 ) PVF, PVD, the values of Vv(x) and Vv'(x).
  !
  implicit none

  real ( kind = 8 ) f
  real ( kind = 8 ) f0
  real ( kind = 8 ) f1
  integer ( kind = 4 ) ja
  integer ( kind = 4 ) k
  integer ( kind = 4 ) kv
  integer ( kind = 4 ) l
  integer ( kind = 4 ) m
  integer ( kind = 4 ) na
  integer ( kind = 4 ) nv
  real ( kind = 8 ) pi
  real ( kind = 8 ) pv0
  real ( kind = 8 ) pvd
  real ( kind = 8 ) pvf
  real ( kind = 8 ) q2p
  real ( kind = 8 ) qe
  real ( kind = 8 ) s0
  real ( kind = 8 ) v
  real ( kind = 8 ) v0
  real ( kind = 8 ) v1
  real ( kind = 8 ) v2
  real ( kind = 8 ) vh
  real ( kind = 8 ) vp(0:*)
  real ( kind = 8 ) vv(0:*)
  real ( kind = 8 ) x
  real ( kind = 8 ) xa

  pi = 3.141592653589793D+00
  xa = abs ( x )
  vh = v
  v = v + sign ( 1.0D+00, v )
  nv = int ( v )
  v0 = v - nv
  na = abs ( nv )
  qe = exp ( 0.25D+00 * x * x )
  q2p = sqrt ( 2.0D+00 / pi )

  if ( 1 <= na ) then
     ja = 1
  end if

  if ( v <= 0.0D+00 ) then

     if ( v0 == 0.0D+00 ) then

        if ( xa <= 7.5D+00 ) then 
           call vvsa ( v0, x, pv0 )
        else
           call vvla ( v0, x, pv0 )
        end if

        f0 = q2p * qe
        f1 = x * f0
        vv(0) = pv0
        vv(1) = f0
        vv(2) = f1

     else

        do l = 0, ja
           v1 = v0 - l
           if ( xa <= 7.5D+00 ) then
              call vvsa ( v1, x, f1 )
           else
              call vvla ( v1, x, f1 )
           end if
           if ( l == 0 ) then
              f0 = f1
           end if
        end do

        vv(0) = f0
        vv(1) = f1

     end if

     if ( v0 == 0.0D+00 ) then
        kv = 3
     else
        kv = 2
     end if

     do k = kv, na
        f = x * f1 + ( k - v0 - 2.0D+00 ) * f0
        vv(k) = f
        f0 = f1
        f1 = f
     end do

  else

     if ( 0.0D+00 <= x .and. x <= 7.5D+00 ) then

        v2 = v
        if ( v2 < 1.0D+00 ) then
           v2 = v2 + 1.0D+00
        end if

        call vvsa ( v2, x, f1 )
        v1 = v2 - 1.0D+00
        kv = int ( v2 )
        call vvsa ( v1, x, f0 )
        vv(kv) = f1
        vv(kv-1) = f0
        do k = kv - 2, 0, - 1
           f = x * f0 - ( k + v0 + 2.0D+00 ) * f1
           if ( k <= na ) then
              vv(k) = f
           end if
           f1 = f0
           f0 = f
        end do

     else if ( 7.5D+00 < x ) then

        call vvla ( v0, x, pv0 )
        m = 100 + abs ( na )
        vv(1) = pv0
        f1 = 0.0D+00
        f0 = 1.0D-40
        do k = m, 0, -1
           f = x * f0 - ( k + v0 + 2.0D+00 ) * f1
           if ( k <= na ) then
              vv(k) = f
           end if
           f1 = f0
           f0 = f
        end do
        s0 = pv0 / f
        do k = 0, na
           vv(k) = s0 * vv(k)
        end do

     else

        if ( xa <= 7.5D+00 ) then
           call vvsa ( v0, x, f0 )
           v1 = v0 + 1.0D+00
           call vvsa ( v1, x, f1 )
        else
           call vvla ( v0, x, f0 )
           v1 = v0 + 1.0D+00
           call vvla ( v1, x, f1 )
        end if

        vv(0) = f0
        vv(1) = f1
        do k = 2, na
           f = ( x * f1 - f0 ) / ( k + v0 )
           vv(k) = f
           f0 = f1
           f1 = f
        end do

     end if

  end if

  do k = 0, na - 1
     v1 = v0 + k
     if ( 0.0D+00 <= v ) then
        vp(k) = 0.5D+00 * x * vv(k) - ( v1 + 1.0D+00 ) * vv(k+1)
     else
        vp(k) = - 0.5D+00 * x * vv(k) + vv(k+1)
     end if
  end do

  pvf = vv(na-1)
  pvd = vp(na-1)
  v = vh

  return
end subroutine pbvv
subroutine pbwa ( a, x, w1f, w1d, w2f, w2d )

  !*****************************************************************************80
  !
  !! PBWA computes parabolic cylinder functions W(a,x) and derivatives.
  !
  !  Licensing:
  !
  !    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However, 
  !    they give permission to incorporate this routine into a user program 
  !    provided that the copyright is acknowledged.
  !
  !  Modified:
  !
  !    29 July 2012
  !
  !  Author:
  !
  !    Shanjie Zhang, Jianming Jin
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) A, the parameter.
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) W1F, W1D, W2F, W2D, the values of
  !    W(a,x), W'(a,x), W(a,-x), W'(a,-x).
  !
  implicit none

  real ( kind = 8 ) a
  real ( kind = 8 ) d(100)
  real ( kind = 8 ) d1
  real ( kind = 8 ) d2
  real ( kind = 8 ) dl
  real ( kind = 8 ) eps
  real ( kind = 8 ) f1
  real ( kind = 8 ) f2
  real ( kind = 8 ) g1
  real ( kind = 8 ) g2
  real ( kind = 8 ) h(100)
  real ( kind = 8 ) h0
  real ( kind = 8 ) h1
  real ( kind = 8 ) hl
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l1
  integer ( kind = 4 ) l2
  integer ( kind = 4 ) m
  real ( kind = 8 ) p0
  real ( kind = 8 ) r
  real ( kind = 8 ) r1
  real ( kind = 8 ) ugi
  real ( kind = 8 ) ugr
  real ( kind = 8 ) vgi
  real ( kind = 8 ) vgr
  real ( kind = 8 ) w1d
  real ( kind = 8 ) w1f
  real ( kind = 8 ) w2d
  real ( kind = 8 ) w2f
  real ( kind = 8 ) x
  real ( kind = 8 ) x1
  real ( kind = 8 ) x2
  real ( kind = 8 ) y1
  real ( kind = 8 ) y1d
  real ( kind = 8 ) y1f
  real ( kind = 8 ) y2d
  real ( kind = 8 ) y2f

  eps = 1.0D-15
  p0 = 0.59460355750136D+00

  if ( a == 0.0D+00 ) then
     g1 = 3.625609908222D+00
     g2 = 1.225416702465D+00
  else
     x1 = 0.25D+00
     y1 = 0.5D+00 * a
     call cgama ( x1, y1, 1, ugr, ugi )
     g1 = sqrt ( ugr * ugr + ugi * ugi )
     x2 = 0.75D+00
     call cgama ( x2, y1, 1, vgr, vgi )
     g2 = sqrt ( vgr * vgr + vgi * vgi )
  end if

  f1 = sqrt ( g1 / g2 )
  f2 = sqrt ( 2.0D+00 * g2 / g1 )
  h0 = 1.0D+00
  h1 = a
  h(1) = a
  do l1 = 4, 200, 2
     m = l1 / 2
     hl = a * h1 - 0.25D+00 * ( l1 - 2.0D+00 ) * ( l1 - 3.0D+00 ) * h0
     h(m) = hl
     h0 = h1
     h1 = hl
  end do
  y1f = 1.0D+00
  r = 1.0D+00
  do k = 1, 100
     r = 0.5D+00 * r * x * x / ( k * ( 2.0D+00 * k - 1.0D+00 ) )
     r1 = h(k) * r
     y1f = y1f + r1
     if ( abs ( r1 / y1f ) <= eps .and. 30 < k ) then
        exit
     end if
  end do

  y1d = a
  r = 1.0D+00
  do k = 1, 100
     r = 0.5D+00 * r * x * x / ( k * ( 2.0D+00 * k + 1.0D+00 ) )
     r1 = h(k+1) * r
     y1d = y1d + r1
     if ( abs ( r1 / y1d ) <= eps .and. 30 < k ) then
        exit
     end if
  end do

  y1d = x * y1d
  d1 = 1.0D+00
  d2 = a
  d(1) = 1.0D+00
  d(2) = a
  do l2 = 5, 160, 2
     m = ( l2 + 1 ) / 2
     dl = a * d2 - 0.25D+00 * ( l2 - 2.0D+00 ) * ( l2 - 3.0D+00 ) * d1
     d(m) = dl
     d1 = d2
     d2 = dl
  end do

  y2f = 1.0D+00
  r = 1.0D+00
  do k = 1, 100
     r = 0.5D+00 * r * x * x / ( k * ( 2.0D+00 * k + 1.0D+00 ) )
     r1 = d(k+1) * r
     y2f = y2f + r1
     if ( abs ( r1 / y2f ) <= eps .and. 30 < k ) then
        exit
     end if
  end do

  y2f = x * y2f
  y2d = 1.0D+00
  r = 1.0D+00
  do k = 1, 100
     r = 0.5D+00 * r * x * x / ( k * ( 2.0D+00 * k - 1.0D+00 ) )
     r1 = d(k+1) * r
     y2d = y2d + r1
     if ( abs ( r1 / y2d ) <= eps .and. 30 < k ) then
        exit
     end if
  end do

  w1f = p0 * ( f1 * y1f - f2 * y2f )
  w2f = p0 * ( f1 * y1f + f2 * y2f )
  w1d = p0 * ( f1 * y1d - f2 * y2d )
  w2d = p0 * ( f1 * y1d + f2 * y2d )

  return
end subroutine pbwa
subroutine psi ( x, ps )

  !*****************************************************************************80
  !
  !! PSI computes the PSI function.
  !
  !  Licensing:
  !
  !    The original FORTRAN77 version of this routine is copyrighted by 
  !    Shanjie Zhang and Jianming Jin.  However, they give permission to 
  !    incorporate this routine into a user program that the copyright 
  !    is acknowledged.
  !
  !  Modified:
  !
  !    08 September 2007
  !
  !  Author:
  !
  !    Original FORTRAN77 by Shanjie Zhang, Jianming Jin.
  !    FORTRAN90 version by John Burkardt.
  !
  !  Reference:
  !
  !    Shanjie Zhang, Jianming Jin,
  !    Computation of Special Functions,
  !    Wiley, 1996,
  !    ISBN: 0-471-11963-6,
  !    LC: QA351.C45
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) X, the argument.
  !
  !    Output, real ( kind = 8 ) PS, the value of the PSI function.
  !
  implicit none

  real ( kind = 8 ), parameter :: a1 = -0.83333333333333333D-01
  real ( kind = 8 ), parameter :: a2 =  0.83333333333333333D-02
  real ( kind = 8 ), parameter :: a3 = -0.39682539682539683D-02
  real ( kind = 8 ), parameter :: a4 =  0.41666666666666667D-02
  real ( kind = 8 ), parameter :: a5 = -0.75757575757575758D-02
  real ( kind = 8 ), parameter :: a6 =  0.21092796092796093D-01
  real ( kind = 8 ), parameter :: a7 = -0.83333333333333333D-01
  real ( kind = 8 ), parameter :: a8 =  0.4432598039215686D+00
  real ( kind = 8 ), parameter :: el = 0.5772156649015329D+00
  integer ( kind = 4 ) k
  integer ( kind = 4 ) n
  real ( kind = 8 ), parameter :: pi = 3.141592653589793D+00
  real ( kind = 8 ) ps
  real ( kind = 8 ) s
  real ( kind = 8 ) x
  real ( kind = 8 ) x2
  real ( kind = 8 ) xa

  xa = abs ( x )
  s = 0.0D+00

  if ( x == aint ( x ) .and. x <= 0.0D+00 ) then

     ps = 1.0D+300
     return

  else if ( xa == aint ( xa ) ) then

     n = int ( xa )
     do k = 1, n - 1
        s = s + 1.0D+00 / real ( k, kind = 8 )
     end do

     ps = - el + s

  else if ( xa + 0.5D+00 == aint ( xa + 0.5D+00 ) ) then

     n = int ( xa - 0.5D+00 )

     do k = 1, n
        s = s + 1.0D+00 / real ( 2 * k - 1, kind = 8 )
     end do

     ps = - el + 2.0D+00 * s - 1.386294361119891D+00

  else

     if ( xa < 10.0D+00 ) then

        n = 10 - int ( xa )
        do k = 0, n - 1
           s = s + 1.0D+00 / ( xa + real ( k, kind = 8 ) )
        end do

        xa = xa + real ( n, kind = 8 )

     end if

     x2 = 1.0D+00 / ( xa * xa )

     ps = log ( xa ) - 0.5D+00 / xa + x2 * ((((((( &
          a8   &
          * x2 + a7 ) &
          * x2 + a6 ) &
          * x2 + a5 ) &
          * x2 + a4 ) &
          * x2 + a3 ) &
          * x2 + a2 ) &
          * x2 + a1 )

     ps = ps - s

  end if

  if ( x < 0.0D+00 ) then
     ps = ps - pi * cos ( pi * x ) / sin ( pi * x ) - 1.0D+00 / x
  end if

  return
end subroutine psi