MODULE FDist_BR
USE FDist_K

CONTAINS


FUNCTION alnrel(a) RESULT(fn_val)
!-----------------------------------------------------------------------
!            EVALUATION OF THE FUNCTION LN(1 + A)
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a
REAL (dp)             :: fn_val

! Local variables
REAL (dp) :: p1 = -.129418923021993D+01, p2 = .405303492862024D+00,  &
             p3 = -.178874546012214D-01, q1 = -.162752256355323D+01, &
             q2 = .747811014037616D+00, q3 = -.845104217945565D-01,  &
             t, t2, w, x, zero = 0.D0, half = 0.5D0, one = 1.D0, two = 2.D0
!--------------------------
IF (ABS(a) <= 0.375D0) THEN
  t = a/(a + two)
  t2 = t*t
  w = (((p3*t2 + p2)*t2 + p1)*t2 + one)/ (((q3*t2 + q2)*t2 + q1)*t2 + one)
  fn_val = two*t*w
ELSE
  x = one + a
  IF (a < zero) x = (a + half) + half
  fn_val = LOG(x)
END IF

RETURN
END FUNCTION alnrel



FUNCTION erf (x) RESULT(fn_val)
!-----------------------------------------------------------------------
!             EVALUATION OF THE REAL ERROR FUNCTION
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: x
REAL (dp)             :: fn_val

REAL (dp) :: a(5) = (/ .771058495001320D-04, -.133733772997339D-02,   &
                       .323076579225834D-01,  .479137145607681D-01,   &
                       .128379167095513D+00 /),   &
             b(3) = (/ .301048631703895D-02,  .538971687740286D-01,   &
                       .375795757275549D+00 /),   &
             p(8) = (/-1.36864857382717D-07,  5.64195517478974D-01, &
                       7.21175825088309D+00,  4.31622272220567D+01, &
                       1.52989285046940D+02,  3.39320816734344D+02, &
                       4.51918953711873D+02,  3.00459261020162D+02 /),  &
             q(8) = (/ 1.00000000000000D+00,  1.27827273196294D+01, &
                       7.70001529352295D+01,  2.77585444743988D+02, &
                       6.38980264465631D+02,  9.31354094850610D+02, &
                       7.90950925327898D+02,  3.00459260956983D+02 /),  &
             r(5) = (/ 2.10144126479064D+00,  2.62370141675169D+01, &
                       2.13688200555087D+01,  4.65807828718470D+00, &
                       2.82094791773523D-01 /),   &
             s(4) = (/ 9.41537750555460D+01,  1.87114811799590D+02, &
                       9.90191814623914D+01,  1.80124575948747D+01 /)
!-------------------------
REAL (dp) :: ax, bot, c = .564189583547756D0, t, top, x2
!-------------------------
ax = ABS(x)
IF (ax < 0.5D0) THEN
  t = x*x
  top = ((((a(1)*t + a(2))*t + a(3))*t + a(4))*t + a(5)) + 1.0D0
  bot = ((b(1)*t + b(2))*t + b(3))*t + 1.0D0
  fn_val = x*(top/bot)
  RETURN

ELSE IF (ax < 4.0D0) THEN
  top = ((((((p(1)*ax + p(2))*ax + p(3))*ax + p(4))*ax + p(5))*ax  &
        + p(6))*ax + p(7))*ax + p(8)
  bot = ((((((q(1)*ax + q(2))*ax + q(3))*ax + q(4))*ax + q(5))*ax  &
        + q(6))*ax + q(7))*ax + q(8)
  fn_val = 0.5D0 + (0.5D0 - EXP(-x*x)*top/bot)
  IF (x < 0.0D0) fn_val = -fn_val
  RETURN

ELSE IF (ax < 5.8D0) THEN
  x2 = x*x
  t = 1.0D0/x2
  top = (((r(1)*t + r(2))*t + r(3))*t + r(4))*t + r(5)
  bot = (((s(1)*t + s(2))*t + s(3))*t + s(4))*t + 1.0D0
  fn_val = (c - top/(x2*bot)) / ax
  fn_val = 0.5D0 + (0.5D0 - EXP(-x2)*fn_val)
  IF (x < 0.0D0) fn_val = -fn_val
  RETURN

ELSE
  fn_val = SIGN(1.0D0,x)
END IF

RETURN
END FUNCTION erf



FUNCTION erfc1 (ind, x) RESULT(fn_val)
!-----------------------------------------------------------------------
!         EVALUATION OF THE COMPLEMENTARY ERROR FUNCTION

!          ERFC1(IND,X) = ERFC(X)            IF IND = 0
!          ERFC1(IND,X) = EXP(X*X)*ERFC(X)   OTHERWISE
!-----------------------------------------------------------------------
IMPLICIT NONE
INTEGER, INTENT(IN)   :: ind
REAL (dp), INTENT(IN) :: x
REAL (dp)             :: fn_val

!-----------------------------------------------------------------------
REAL (dp) :: a(5) = (/ .771058495001320D-04, -.133733772997339D-02,  &
                       .323076579225834D-01,  .479137145607681D-01,  &
                       .128379167095513D+00 /),   &
             b(3) = (/ .301048631703895D-02,  .538971687740286D-01,  &
                       .375795757275549D+00 /),   &
             p(8) = (/-1.36864857382717D-07,  5.64195517478974D-01,  &
                       7.21175825088309D+00,  4.31622272220567D+01,  &
                       1.52989285046940D+02,  3.39320816734344D+02,  &
                       4.51918953711873D+02,  3.00459261020162D+02 /),  &
             q(8) = (/ 1.00000000000000D+00,  1.27827273196294D+01,  &
                       7.70001529352295D+01,  2.77585444743988D+02,  &
                       6.38980264465631D+02,  9.31354094850610D+02,  &
                       7.90950925327898D+02,  3.00459260956983D+02 /),  &
             r(5) = (/ 2.10144126479064D+00,  2.62370141675169D+01,  &
                       2.13688200555087D+01,  4.65807828718470D+00,  &
                       2.82094791773523D-01 /),   &
             s(4) = (/ 9.41537750555460D+01,  1.87114811799590D+02,  &
                       9.90191814623914D+01,  1.80124575948747D+01 /)
!-------------------------
REAL (dp) :: ax, bot, c = .564189583547756D0, e, t, top, w
!-------------------------

!                     ABS(X) <= 0.5

ax = ABS(x)
IF (ax > 0.5D0) GO TO 10
t = x*x
top = ((((a(1)*t + a(2))*t + a(3))*t + a(4))*t + a(5)) + 1.0D0
bot = ((b(1)*t + b(2))*t + b(3))*t + 1.0D0
fn_val = 0.5D0 + (0.5D0 - x*(top/bot))
IF (ind /= 0) fn_val = EXP(t) * fn_val
RETURN

!                  0.5 < ABS(X) <= 4

10 IF (ax > 4.0D0) GO TO 20
top = ((((((p(1)*ax + p(2))*ax + p(3))*ax + p(4))*ax + p(5))*ax  &
      + p(6))*ax + p(7))*ax + p(8)
bot = ((((((q(1)*ax + q(2))*ax + q(3))*ax + q(4))*ax + q(5))*ax  &
      + q(6))*ax + q(7))*ax + q(8)
fn_val = top/bot
GO TO 40

!                      ABS(X) > 4

20 IF (x <= -5.6D0) GO TO 50
IF (ind /= 0) GO TO 30
IF (x > 100.0D0) GO TO 60
IF (x*x > -dxparg(1)) GO TO 60

30 t = (1.0D0/x)**2
top = (((r(1)*t + r(2))*t + r(3))*t + r(4))*t + r(5)
bot = (((s(1)*t + s(2))*t + s(3))*t + s(4))*t + 1.0D0
fn_val = (c - t*top/bot)/ax

!                      FINAL ASSEMBLY

40 IF (ind /= 0) THEN
  IF (x < 0.0D0) fn_val = 2.0D0*EXP(x*x) - fn_val
  RETURN
END IF
w = x * x
t = w
e = w - t
fn_val = ((0.5D0 + (0.5D0 - e)) * EXP(-t)) * fn_val
IF (x < 0.0D0) fn_val = 2.0D0 - fn_val
RETURN

!             LIMIT VALUE FOR LARGE NEGATIVE X

50 fn_val = 2.0D0
IF (ind /= 0) fn_val = 2.0D0*EXP(x*x)
RETURN

!             LIMIT VALUE FOR LARGE POSITIVE X
!                       WHEN IND = 0

60 fn_val = 0.0D0
RETURN
END FUNCTION erfc1



FUNCTION gam1(a) RESULT(fn_val)
!-----------------------------------------------------------------------
!     COMPUTATION OF 1/GAMMA(A+1) - 1  FOR -0.5 <= A <= 1.5
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a
REAL (dp)             :: fn_val

REAL (dp) :: p(7) = (/  .577215664901533D+00, -.409078193005776D+00, &
                       -.230975380857675D+00,  .597275330452234D-01, &
                        .766968181649490D-02, -.514889771323592D-02, &
                        .589597428611429D-03 /),   &
             q(5) = (/  .100000000000000D+01,  .427569613095214D+00, &
                        .158451672430138D+00,  .261132021441447D-01, &
                        .423244297896961D-02 /),   &
             r(9) = (/ -.422784335098468D+00, -.771330383816272D+00, &
                       -.244757765222226D+00,  .118378989872749D+00, &
                        .930357293360349D-03, -.118290993445146D-01, &
                        .223047661158249D-02,  .266505979058923D-03, &
                       -.132674909766242D-03 /)
!------------------------
REAL (dp) :: bot, d, s1 = .273076135303957D+00, s2 = .559398236957378D-01,  &
             t, top, w
!------------------------
t = a
d = a - 0.5D0
IF (d > 0.0D0) t = d - 0.5D0

IF (t > 0.D0) THEN
  top = (((((p(7)*t + p(6))*t + p(5))*t + p(4))*t + p(3))*t + p(2))*t + p(1)
  bot = (((q(5)*t + q(4))*t + q(3))*t + q(2))*t + 1.0D0
  w = top/bot
  IF (d > 0.0D0) THEN
    fn_val = (t/a)*((w - 0.5D0) - 0.5D0)
  ELSE
    fn_val = a*w
  END IF
ELSE IF (t < 0.D0) THEN
  top = (((((((r(9)*t + r(8))*t + r(7))*t + r(6))*t + r(5))*t  &
           + r(4))*t + r(3))*t + r(2))*t + r(1)
  bot = (s2*t + s1)*t + 1.0D0
  w = top/bot
  IF (d > 0.0D0) THEN
    fn_val = t*w/a
  ELSE
    fn_val = a*((w + 0.5D0) + 0.5D0)
  END IF
ELSE
  fn_val = 0.0D0
END IF

RETURN
END FUNCTION gam1


FUNCTION algdiv (a, b) RESULT(fn_val)
!-----------------------------------------------------------------------

!     COMPUTATION OF LN(GAMMA(B)/GAMMA(A+B)) WHEN B >= 8

!                         --------

!     IN THIS ALGORITHM, DEL(X) IS THE FUNCTION DEFINED BY
!     LN(GAMMA(X)) = (X - 0.5)*LN(X) - X + 0.5*LN(2*PI) + DEL(X).

!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b
REAL (dp)             :: fn_val

! EXTERNAL   alnrel
REAL (dp) :: c, d, h, s11, s3, s5, s7, s9, t, u, v, w, x, x2
REAL (dp) :: c0 = .833333333333333D-01, c1 = -.277777777760991D-02, &
             c2 = .793650666825390D-03, c3 = -.595202931351870D-03, &
             c4 = .837308034031215D-03, c5 = -.165322962780713D-02
!------------------------
IF (a > b) THEN
  h = b/a
  c = 1.0D0/(1.0D0 + h)
  x = h/(1.0D0 + h)
  d = a + (b - 0.5D0)
ELSE
  h = a/b
  c = h/(1.0D0 + h)
  x = 1.0D0/(1.0D0 + h)
  d = b + (a - 0.5D0)
END IF

!                SET SN = (1 - X**N)/(1 - X)

x2 = x*x
s3 = 1.0D0 + (x + x2)
s5 = 1.0D0 + (x + x2*s3)
s7 = 1.0D0 + (x + x2*s5)
s9 = 1.0D0 + (x + x2*s7)
s11 = 1.0D0 + (x + x2*s9)

!                SET W = DEL(B) - DEL(A + B)

t = (1.0D0/b)**2
w = ((((c5*s11*t + c4*s9)*t + c3*s7)*t + c2*s5)*t + c1*s3)*t + c0
w = w*(c/b)

!                    COMBINE THE RESULTS

u = d*alnrel(a/b)
v = a*(LOG(b) - 1.0D0)
IF (u > v) THEN
  fn_val = (w - v) - u
ELSE
  fn_val = (w - u) - v
END IF

RETURN
END FUNCTION algdiv



FUNCTION rexp (x) RESULT(fn_val)
!-----------------------------------------------------------------------
!            EVALUATION OF THE FUNCTION EXP(X) - 1
!-----------------------------------------------------------------------
REAL (dp), INTENT(IN) :: x
REAL (dp)             :: fn_val

REAL (dp) :: e
REAL (dp) :: p1 =  .914041914819518D-09, p2 =  .238082361044469D-01, &
             q1 = -.499999999085958D+00, q2 =  .107141568980644D+00, &
             q3 = -.119041179760821D-01, q4 =  .595130811860248D-03
!-----------------------
IF (ABS(x) < 0.15D0) THEN
  fn_val = x*(((p2*x + p1)*x + 1.0D0)/((((q4*x + q3)*x + q2)*x + q1)*x + 1.0D0))
  RETURN
END IF

IF (x < 0.0D0) GO TO 20
e = EXP(x)
fn_val = e*(0.5D0 + (0.5D0 - 1.0D0/e))
RETURN

20 IF (x > -37.0D0) THEN
  fn_val = (EXP(x) - 0.5D0) - 0.5D0
  RETURN
END IF

fn_val = -1.0D0

RETURN
END FUNCTION rexp



SUBROUTINE bgrat (a, b, x, y, w, eps, ierr)
!-----------------------------------------------------------------------
!     ASYMPTOTIC EXPANSION FOR IX(A,B) WHEN A IS LARGER THAN B.
!     THE RESULT OF THE EXPANSION IS ADDED TO W. IT IS ASSUMED
!     THAT A <= 15 AND B <= 1.  EPS IS THE TOLERANCE USED.
!     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN)     :: a, b, x, y, eps
REAL (dp), INTENT(IN OUT) :: w
INTEGER, INTENT(OUT)      :: ierr

REAL (dp) :: c(30), d(30), j, l, lnx, nu, n2

INTEGER   :: n, i
REAL (dp) :: bm1, bp2n, cn, coef, dj, q, r, s, sum, t, tol, t2, u, v, z,  &
             zero = 0.D0, quarter = 0.25D0, half = 0.5D0, one = 1.D0

bm1 = (b - half) - half
nu = a + half*bm1
IF (y > 0.375D0) GO TO 10
lnx = alnrel(-y)
GO TO 11
10 lnx = LOG(x)
11 z = -nu*lnx
IF (b*z == zero) GO TO 100

!                 COMPUTATION OF THE EXPANSION
!                 SET R = EXP(-Z)*Z**B/GAMMA(B)

r = b*(one + gam1(b))*EXP(b*LOG(z))
r = r*EXP(a*lnx)*EXP(half*bm1*lnx)
u = algdiv(b,a) + b*LOG(nu)
u = r*EXP(-u)
IF (u == zero) GO TO 100
CALL grat1 (b, z, r, q=q, eps=eps)

tol = 15.0D0*eps
v = quarter*(one/nu)**2
t2 = quarter*lnx*lnx
l = w/u
j = q/r
sum = j
t = one
cn = one
n2 = zero
DO n = 1,30
  bp2n = b + n2
  j = (bp2n*(bp2n + one)*j + (z + bp2n + one)*t)*v
  n2 = n2 + 2.0D0
  t = t*t2
  cn = cn/(n2*(n2 + one))
  c(n) = cn
  s = zero
  IF (n == 1) GO TO 21
  coef = b - n
  DO i = 1, n-1
    s = s + coef*c(i)*d(n-i)
    coef = coef + b
  END DO
  21 d(n) = bm1*cn + s/n
  dj = d(n)*j
  sum = sum + dj
  IF (sum <= zero) GO TO 100
  IF (ABS(dj) <= tol*(sum + l)) GO TO 30
END DO

!                    ADD THE RESULTS TO W

30 ierr = 0
w = w + u*sum
RETURN

!               THE EXPANSION CANNOT BE COMPUTED

100 ierr = 1
RETURN
END SUBROUTINE bgrat



SUBROUTINE grat1 (a, x, r, p, q, eps)
!-----------------------------------------------------------------------
!           EVALUATION OF P(A,X) AND Q(A,X) WHERE A <= 1 AND
!        THE INPUT ARGUMENT R HAS THE VALUE E**(-X)*X**A/GAMMA(A)
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN)            :: a, x, r, eps
REAL (dp), OPTIONAL, INTENT(OUT) :: p, q

REAL (dp) :: j, l
REAL (dp) :: an, a2n, a2nm1, b2n, b2nm1, c, g, h, sum, t, tol, w, z,  &
             zero = 0.D0, half = 0.5D0, one = 1.D0, two = 2.D0, three = 3.D0, &
             quarter = 0.25D0, pp, qq

IF (a*x == zero) GO TO 130
IF (a == half) GO TO 120
IF (x < 1.1D0) GO TO 10
GO TO 50

!             TAYLOR SERIES FOR P(A,X)/X**A

10 an = three
c = x
sum = x/(a + three)
tol = three*eps/(a + one)
11 an = an + one
c = -c*(x/an)
t = c/(a + an)
sum = sum + t
IF (ABS(t) > tol) GO TO 11
j = a*x*((sum/6.0D0 - half/(a + two))*x + one/(a + one))

z = a*LOG(x)
h = gam1(a)
g = one + h
IF (x < quarter) GO TO 20
IF (a < x/2.59D0) GO TO 40
GO TO 30
20 IF (z > -.13394D0) GO TO 40

30 w = EXP(z)
pp = w*g*(half + (half - j))
qq = half + (half - pp)
GO TO 500

40 l = rexp(z)
qq = ((half + (half + l))*j - l)*g - h
IF (qq <= zero) GO TO 110
pp = half + (half - qq)
GO TO 500

!              CONTINUED FRACTION EXPANSION

50 tol = 8.0D0*eps
a2nm1 = one
a2n = one
b2nm1 = x
b2n = x + (one - a)
c = one
DO
  a2nm1 = x*a2n + c*a2nm1
  b2nm1 = x*b2n + c*b2nm1
  c = c + one
  a2n = a2nm1 + (c - a)*a2n
  b2n = b2nm1 + (c - a)*b2n
  a2nm1 = a2nm1/b2n
  b2nm1 = b2nm1/b2n
  a2n = a2n/b2n
  b2n = one
  IF (ABS(a2n - a2nm1/b2nm1) < tol*a2n) EXIT
END DO

qq = r*a2n
pp = half + (half - qq)
GO TO 500

!                SPECIAL CASES

100 pp = zero
qq = one
GO TO 500

110 pp = one
qq = zero
GO TO 500

120 IF (x < quarter) THEN
  pp = erf(SQRT(x))
  qq = half + (half - pp)
  GO TO 500
ELSE
  qq = erfc1(0,SQRT(x))
  pp = half + (half - qq)
  GO TO 500
END IF

130 IF (x <= a) GO TO 100
GO TO 110

500 IF (PRESENT(p)) p = pp
IF (PRESENT(q)) q = qq

RETURN
END SUBROUTINE grat1



FUNCTION esum (mu, x) RESULT(fn_val)
!-----------------------------------------------------------------------
!                    EVALUATION OF EXP(MU + X)
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: x
INTEGER, INTENT(IN)   :: mu
REAL (dp)             :: fn_val

REAL (dp) :: w

IF (x > 0.0D0) GO TO 10

IF (mu < 0) GO TO 20
w = mu + x
IF (w > 0.0D0) GO TO 20
fn_val = EXP(w)
RETURN

10 IF (mu > 0) GO TO 20
w = mu + x
IF (w < 0.0D0) GO TO 20
fn_val = EXP(w)
RETURN

20 w = mu
fn_val = EXP(w)*EXP(x)

RETURN
END FUNCTION esum



FUNCTION rlog1(x) RESULT(fn_val)
!-----------------------------------------------------------------------
!             EVALUATION OF THE FUNCTION X - LN(1 + X)
!-----------------------------------------------------------------------
!     A = RLOG (0.7)
!     B = RLOG (4/3)
!------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: x
REAL (dp)             :: fn_val

REAL (dp) ::   a = .566749439387324D-01, b = .456512608815524D-01,  &
               p0 = .333333333333333D+00, p1 = -.224696413112536D+00, &
               p2 = .620886815375787D-02, q1 = -.127408923933623D+01, &
               q2 = .354508718369557D+00, r, t, u, up2, w, w1
!------------------------
IF (x < -0.39D0 .OR. x > 0.57D0) GO TO 100
IF (x < -0.18D0) GO TO 10
IF (x >  0.18D0) GO TO 20

!                 ARGUMENT REDUCTION

u = x
up2 = u + 2.0D0
w1 = 0.0D0
GO TO 30

10 u = (x + 0.3D0)/0.7D0
up2 = u + 2.0D0
w1 = a - u*0.3D0
GO TO 30

20 t = 0.75D0*x
u = t - 0.25D0
up2 = t + 1.75D0
w1 = b + u/3.0D0

!                  SERIES EXPANSION

30 r = u/up2
t = r*r
w = ((p2*t + p1)*t + p0)/((q2*t + q1)*t + 1.0D0)
fn_val = r*(u - 2.0D0*t*w) + w1
RETURN


100 w = (x + 0.5D0) + 0.5D0
fn_val = x - LOG(w)
RETURN
END FUNCTION rlog1



FUNCTION gamln (a) RESULT(fn_val)
!-----------------------------------------------------------------------
!            EVALUATION OF LN(GAMMA(A)) FOR POSITIVE A
!-----------------------------------------------------------------------
!     WRITTEN BY ALFRED H. MORRIS
!          NAVAL SURFACE WARFARE CENTER
!          DAHLGREN, VIRGINIA
!--------------------------
!     D = 0.5*(LN(2*PI) - 1)
!--------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a
REAL (dp)             :: fn_val

REAL (dp) :: c0 = .833333333333333D-01, c1 = -.277777777760991D-02,  &
             c2 = .793650666825390D-03, c3 = -.595202931351870D-03,  &
             c4 = .837308034031215D-03, c5 = -.165322962780713D-02,  &
             d = .418938533204673D0, t, w
INTEGER   :: i, n
!--------------------------
IF (a > 0.8D0) GO TO 10
fn_val = gamln1(a) - LOG(a)
RETURN
10 IF (a > 2.25D0) GO TO 20
t = (a - 0.5D0) - 0.5D0
fn_val = gamln1(t)
RETURN

20 IF (a >= 10.0D0) GO TO 30
n = a - 1.25D0
t = a
w = 1.0D0
DO i = 1, n
  t = t - 1.0D0
  w = t*w
END DO
fn_val = gamln1(t - 1.0D0) + LOG(w)
RETURN

30 t = (1.0D0/a)**2
w = (((((c5*t + c4)*t + c3)*t + c2)*t + c1)*t + c0)/a
fn_val = (d + w) + (a - 0.5D0)*(LOG(a) - 1.0D0)

RETURN
END FUNCTION gamln



FUNCTION gamln1 (a) RESULT(fn_val)
!-----------------------------------------------------------------------
!     EVALUATION OF LN(GAMMA(1 + A)) FOR -0.2 .LE. A .LE. 1.25
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a
REAL (dp)             :: fn_val

REAL (dp) :: w, x, &
             p0 =  .577215664901533D+00, p1 =  .844203922187225D+00,  &
             p2 = -.168860593646662D+00, p3 = -.780427615533591D+00,  &
             p4 = -.402055799310489D+00, p5 = -.673562214325671D-01,  &
             p6 = -.271935708322958D-02,   &
             q1 =  .288743195473681D+01, q2 =  .312755088914843D+01,  &
             q3 =  .156875193295039D+01, q4 =  .361951990101499D+00,  &
             q5 =  .325038868253937D-01, q6 =  .667465618796164D-03,  &
             r0 = .422784335098467D+00,  r1 = .848044614534529D+00,  &
             r2 = .565221050691933D+00,  r3 = .156513060486551D+00,  &
             r4 = .170502484022650D-01,  r5 = .497958207639485D-03,  &
             s1 = .124313399877507D+01,  s2 = .548042109832463D+00,  &
             s3 = .101552187439830D+00,  s4 = .713309612391000D-02,  &
             s5 = .116165475989616D-03
!----------------------
IF (a >= 0.6D0) GO TO 10
w = ((((((p6*a + p5)*a + p4)*a + p3)*a + p2)*a + p1)*a + p0)/  &
    ((((((q6*a + q5)*a + q4)*a + q3)*a + q2)*a + q1)*a + 1.0D0)
fn_val = -a*w
RETURN

10 x = (a - 0.5D0) - 0.5D0
w = (((((r5*x + r4)*x + r3)*x + r2)*x + r1)*x + r0)/  &
    (((((s5*x + s4)*x + s3)*x + s2)*x + s1)*x + 1.0D0)
fn_val = x*w
RETURN
END FUNCTION gamln1



FUNCTION psi(xx) RESULT(fn_val)
!---------------------------------------------------------------------

!                 EVALUATION OF THE DIGAMMA FUNCTION

!                           -----------

!     PSI(XX) IS ASSIGNED THE VALUE 0 WHEN THE DIGAMMA FUNCTION CANNOT
!     BE COMPUTED.

!     THE MAIN COMPUTATION INVOLVES EVALUATION OF RATIONAL CHEBYSHEV
!     APPROXIMATIONS PUBLISHED IN MATH. COMP. 27, 123-127(1973) BY
!     CODY, STRECOK AND THACHER.

!---------------------------------------------------------------------
!     PSI WAS WRITTEN AT ARGONNE NATIONAL LABORATORY FOR THE FUNPACK
!     PACKAGE OF SPECIAL FUNCTION SUBROUTINES. PSI WAS MODIFIED BY
!     A.H. MORRIS (NSWC).
!---------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: xx
REAL (dp)             :: fn_val

REAL (dp) :: dx0 = 1.461632144968362341262659542325721325D0
!---------------------------------------------------------------------

!     PIOV4 = PI/4
!     DX0 = ZERO OF PSI TO EXTENDED PRECISION

!---------------------------------------------------------------------
REAL (dp) :: aug, den, piov4 = .785398163397448D0, sgn, upper,  &
             w, x, xmax1, xmx0, xsmall, z
INTEGER   :: i, m, n, nq
!---------------------------------------------------------------------

!     COEFFICIENTS FOR RATIONAL APPROXIMATION OF
!     PSI(X) / (X - X0),  0.5 <= X <= 3.0

!---------------------------------------------------------------------
REAL (dp) :: p1(7) = (/ .895385022981970D-02, .477762828042627D+01,  &
                        .142441585084029D+03, .118645200713425D+04,  &
                        .363351846806499D+04, .413810161269013D+04,  &
                        .130560269827897D+04 /),   &
             q1(6) = (/ .448452573429826D+02, .520752771467162D+03,  &
                        .221000799247830D+04, .364127349079381D+04,  &
                        .190831076596300D+04, .691091682714533D-05 /)
!---------------------------------------------------------------------

!     COEFFICIENTS FOR RATIONAL APPROXIMATION OF
!     PSI(X) - LN(X) + 1 / (2*X),  X > 3.0

!---------------------------------------------------------------------
REAL (dp) :: p2(4) = (/ -.212940445131011D+01, -.701677227766759D+01,  &
                        -.448616543918019D+01, -.648157123766197D+00 /), &
             q2(4) = (/  .322703493791143D+02,  .892920700481861D+02,  &
                         .546117738103215D+02,  .777788548522962D+01 /)
!---------------------------------------------------------------------

!     MACHINE DEPENDENT CONSTANTS ...

!        XMAX1  = THE SMALLEST POSITIVE FLOATING POINT CONSTANT
!                 WITH ENTIRELY INTEGER REPRESENTATION.  ALSO USED
!                 AS NEGATIVE OF LOWER BOUND ON ACCEPTABLE NEGATIVE
!                 ARGUMENTS AND AS THE POSITIVE ARGUMENT BEYOND WHICH
!                 PSI MAY BE REPRESENTED AS ALOG(X).

!        XSMALL = ABSOLUTE ARGUMENT BELOW WHICH PI*COTAN(PI*X)
!                 MAY BE REPRESENTED BY 1/X.

!---------------------------------------------------------------------
xmax1 = ipmpar(3)
xmax1 = MIN(xmax1, 1.0D0/dpmpar(1))
xsmall = 1.d-9
!---------------------------------------------------------------------
x = xx
aug = 0.0D0
IF (x >= 0.5D0) GO TO 200
!---------------------------------------------------------------------
!     X .LT. 0.5,  USE REFLECTION FORMULA
!     PSI(1-X) = PSI(X) + PI * COTAN(PI*X)
!---------------------------------------------------------------------
IF (ABS(x) > xsmall) GO TO 100
IF (x == 0.0D0) GO TO 400
!---------------------------------------------------------------------
!     0 .LT. ABS(X) .LE. XSMALL.  USE 1/X AS A SUBSTITUTE
!     FOR  PI*COTAN(PI*X)
!---------------------------------------------------------------------
aug = -1.0D0 / x
GO TO 150
!---------------------------------------------------------------------
!     REDUCTION OF ARGUMENT FOR COTAN
!---------------------------------------------------------------------
100 w = - x
sgn = piov4
IF (w > 0.0D0) GO TO 120
w = - w
sgn = -sgn
!---------------------------------------------------------------------
!     MAKE AN ERROR EXIT IF X .LE. -XMAX1
!---------------------------------------------------------------------
120 IF (w >= xmax1) GO TO 400
nq = INT(w)
w = w - nq
nq = INT(w*4.0D0)
w = 4.0D0 * (w - nq * .25D0)
!---------------------------------------------------------------------
!     W IS NOW RELATED TO THE FRACTIONAL PART OF  4.0 * X.
!     ADJUST ARGUMENT TO CORRESPOND TO VALUES IN FIRST
!     QUADRANT AND DETERMINE SIGN
!---------------------------------------------------------------------
n = nq / 2
IF ((n+n) /= nq) w = 1.0D0 - w
z = piov4 * w
m = n / 2
IF ((m+m) /= n) sgn = - sgn
!---------------------------------------------------------------------
!     DETERMINE FINAL VALUE FOR  -PI*COTAN(PI*X)
!---------------------------------------------------------------------
n = (nq + 1) / 2
m = n / 2
m = m + m
IF (m /= n) GO TO 140
!---------------------------------------------------------------------
!     CHECK FOR SINGULARITY
!---------------------------------------------------------------------
IF (z == 0.0D0) GO TO 400
!---------------------------------------------------------------------
!     USE COS/SIN AS A SUBSTITUTE FOR COTAN, AND
!     SIN/COS AS A SUBSTITUTE FOR TAN
!---------------------------------------------------------------------
aug = sgn * ((COS(z) / SIN(z)) * 4.0D0)
GO TO 150
140 aug = sgn * ((SIN(z) / COS(z)) * 4.0D0)
150 x = 1.0D0 - x
200 IF (x > 3.0D0) GO TO 300
!---------------------------------------------------------------------
!     0.5 .LE. X .LE. 3.0
!---------------------------------------------------------------------
den = x
upper = p1(1) * x

DO i = 1, 5
  den = (den + q1(i)) * x
  upper = (upper + p1(i+1)) * x
END DO

den = (upper + p1(7)) / (den + q1(6))
xmx0 = x - dx0
fn_val = den * xmx0 + aug
RETURN
!---------------------------------------------------------------------
!     IF X .GE. XMAX1, PSI = LN(X)
!---------------------------------------------------------------------
300 IF (x >= xmax1) GO TO 350
!---------------------------------------------------------------------
!     3.0 .LT. X .LT. XMAX1
!---------------------------------------------------------------------
w = 1.0D0 / (x * x)
den = w
upper = p2(1) * w

DO i = 1, 3
  den = (den + q2(i)) * w
  upper = (upper + p2(i+1)) * w
END DO

aug = upper / (den + q2(4)) - 0.5D0 / x + aug
350 fn_val = aug + LOG(x)
RETURN
!---------------------------------------------------------------------
!     ERROR RETURN
!---------------------------------------------------------------------
400 fn_val = 0.0D0
RETURN
END FUNCTION psi



FUNCTION betaln (a0, b0) RESULT(fn_val)
!-----------------------------------------------------------------------
!     EVALUATION OF THE LOGARITHM OF THE BETA FUNCTION
!-----------------------------------------------------------------------
!     E = 0.5*LN(2*PI)
!--------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a0, b0
REAL (dp)             :: fn_val

REAL (dp) :: a, b, c, e = .918938533204673D0, h, u, v, w, z
INTEGER   :: i, n
!--------------------------
a = MIN(a0,b0)
b = MAX(a0,b0)
IF (a >= 8.0D0) GO TO 60
IF (a >= 1.0D0) GO TO 20
!-----------------------------------------------------------------------
!                   PROCEDURE WHEN A .LT. 1
!-----------------------------------------------------------------------
IF (b >= 8.0D0) GO TO 10
fn_val = gamln(a) + (gamln(b) - gamln(a + b))
RETURN
10 fn_val = gamln(a) + algdiv(a,b)
RETURN
!-----------------------------------------------------------------------
!                PROCEDURE WHEN 1 .LE. A .LT. 8
!-----------------------------------------------------------------------
20 IF (a > 2.0D0) GO TO 30
IF (b > 2.0D0) GO TO 21
fn_val = gamln(a) + gamln(b) - gsumln(a,b)
RETURN
21 w = 0.0D0
IF (b < 8.0D0) GO TO 40
fn_val = gamln(a) + algdiv(a,b)
RETURN

!                REDUCTION OF A WHEN B .LE. 1000

30 IF (b > 1000.0D0) GO TO 50
n = a - 1.0D0
w = 1.0D0
DO i = 1, n
  a = a - 1.0D0
  h = a/b
  w = w * (h/(1.0D0 + h))
END DO
w = LOG(w)
IF (b < 8.0D0) GO TO 40
fn_val = w + gamln(a) + algdiv(a,b)
RETURN

!                 REDUCTION OF B WHEN B .LT. 8

40 n = b - 1.0D0
z = 1.0D0
DO i = 1,n
  b = b - 1.0D0
  z = z * (b/(a + b))
END DO
fn_val = w + LOG(z) + (gamln(a) + (gamln(b) - gsumln(a,b)))
RETURN

!                REDUCTION OF A WHEN B .GT. 1000

50 n = a - 1.0D0
w = 1.0D0
DO i = 1,n
  a = a - 1.0D0
  w = w * (a/(1.0D0 + a/b))
END DO
fn_val = (LOG(w) - n*LOG(b)) + (gamln(a) + algdiv(a,b))
RETURN
!-----------------------------------------------------------------------
!                   PROCEDURE WHEN A .GE. 8
!-----------------------------------------------------------------------
60 w = bcorr(a,b)
h = a/b
c = h/(1.0D0 + h)
u = -(a - 0.5D0)*LOG(c)
v = b*alnrel(h)
IF (u <= v) GO TO 61
fn_val = (((-0.5D0*LOG(b) + e) + w) - v) - u
RETURN
61 fn_val = (((-0.5D0*LOG(b) + e) + w) - u) - v
RETURN
END FUNCTION betaln



FUNCTION gsumln (a, b) RESULT(fn_val)
!-----------------------------------------------------------------------
!          EVALUATION OF THE FUNCTION LN(GAMMA(A + B))
!          FOR 1 .LE. A .LE. 2  AND  1 .LE. B .LE. 2
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b
REAL (dp)             :: fn_val

REAL (dp) :: x
x = a + b - 2.d0
IF (x > 0.25D0) GO TO 10
fn_val = gamln1(1.0D0 + x)
RETURN
10 IF (x > 1.25D0) GO TO 20
fn_val = gamln1(x) + alnrel(x)
RETURN
20 fn_val = gamln1(x - 1.0D0) + LOG(x*(1.0D0 + x))
RETURN
END FUNCTION gsumln



FUNCTION bcorr (a0, b0) RESULT(fn_val)
!-----------------------------------------------------------------------

!     EVALUATION OF  DEL(A0) + DEL(B0) - DEL(A0 + B0)  WHERE
!     LN(GAMMA(A)) = (A - 0.5)*LN(A) - A + 0.5*LN(2*PI) + DEL(A).
!     IT IS ASSUMED THAT A0 .GE. 8 AND B0 .GE. 8.

!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a0, b0
REAL (dp)             :: fn_val

REAL (dp) :: a, b, c, h, s11, s3, s5, s7, s9, t, w, x, x2,         &
             c0 = .833333333333333D-01, c1 = -.277777777760991D-02,  &
             c2 = .793650666825390D-03, c3 = -.595202931351870D-03,  &
             c4 = .837308034031215D-03, c5 = -.165322962780713D-02
!------------------------
a = MIN(a0, b0)
b = MAX(a0, b0)

h = a/b
c = h/(1.0D0 + h)
x = 1.0D0/(1.0D0 + h)
x2 = x*x

!                SET SN = (1 - X**N)/(1 - X)

s3 = 1.0D0 + (x + x2)
s5 = 1.0D0 + (x + x2*s3)
s7 = 1.0D0 + (x + x2*s5)
s9 = 1.0D0 + (x + x2*s7)
s11 = 1.0D0 + (x + x2*s9)

!                SET W = DEL(B) - DEL(A + B)

t = (1.0D0/b)**2
w = ((((c5*s11*t + c4*s9)*t + c3*s7)*t + c2*s5)*t + c1*s3)*t + c0
w = w*(c/b)

!                   COMPUTE  DEL(A) + W

t = (1.0D0/a)**2
fn_val = (((((c5*t + c4)*t + c3)*t + c2)*t + c1)*t + c0)/a + w
RETURN
END FUNCTION bcorr



SUBROUTINE bratio (a, b, x, y, w, w1, ierr)
!-----------------------------------------------------------------------

!            EVALUATION OF THE INCOMPLETE BETA FUNCTION IX(A,B)

!                     --------------------

!     IT IS ASSUMED THAT A AND B ARE NONNEGATIVE, AND THAT X <= 1
!     AND Y = 1 - X.  BRATIO ASSIGNS W AND W1 THE VALUES

!                      W  = IX(A,B)
!                      W1 = 1 - IX(A,B)

!     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
!     IF NO INPUT ERRORS ARE DETECTED THEN IERR IS SET TO 0 AND
!     W AND W1 ARE COMPUTED. OTHERWISE, IF AN ERROR IS DETECTED,
!     THEN W AND W1 ARE ASSIGNED THE VALUE 0 AND IERR IS SET TO
!     ONE OF THE FOLLOWING VALUES ...

!        IERR = 1  IF A OR B IS NEGATIVE
!        IERR = 2  IF A = B = 0
!        IERR = 3  IF X .LT. 0 OR X .GT. 1
!        IERR = 4  IF Y .LT. 0 OR Y .GT. 1
!        IERR = 5  IF X + Y .NE. 1
!        IERR = 6  IF X = A = 0
!        IERR = 7  IF Y = B = 0

!--------------------
!     WRITTEN BY ALFRED H. MORRIS, JR.
!        NAVAL SURFACE WARFARE CENTER
!        DAHLGREN, VIRGINIA
!     REVISED ... APRIL 1993
!-----------------------------------------------------------------------
REAL (dp), INTENT(IN)  :: a, b, x, y
REAL (dp), INTENT(OUT) :: w, w1
INTEGER, INTENT(OUT)   :: ierr
!-----------------------------------------------------------------------

!     ****** EPS IS A MACHINE DEPENDENT CONSTANT. EPS IS THE SMALLEST
!            FLOATING POINT NUMBER FOR WHICH 1.0 + EPS .GT. 1.0

REAL (dp) :: lambda, a0, b0, eps, t, x0, y0, z
INTEGER   :: ierr1, ind, n

eps = dpmpar(1)

!-----------------------------------------------------------------------
w = 0.0D0
w1 = 0.0D0
IF (a < 0.0D0 .OR. b < 0.0D0) GO TO 300
IF (a == 0.0D0 .AND. b == 0.0D0) GO TO 310
IF (x < 0.0D0 .OR. x > 1.0D0) GO TO 320
IF (y < 0.0D0 .OR. y > 1.0D0) GO TO 330
z = ((x + y) - 0.5D0) - 0.5D0
IF (ABS(z) > 3.0D0*eps) GO TO 340

ierr = 0
IF (x == 0.0D0) GO TO 200
IF (y == 0.0D0) GO TO 210
IF (a == 0.0D0) GO TO 211
IF (b == 0.0D0) GO TO 201

eps = MAX(eps, 1.d-15)
IF (MAX(a,b) < 1.d-3*eps) GO TO 230

ind = 0
a0 = a
b0 = b
x0 = x
y0 = y
IF (MIN(a0, b0) > 1.0D0) GO TO 30

!             PROCEDURE FOR A0 .LE. 1 OR B0 .LE. 1

IF (x <= 0.5D0) GO TO 10
ind = 1
a0 = b
b0 = a
x0 = y
y0 = x

10 IF (b0 < MIN(eps,eps*a0)) GO TO 80
IF (a0 < MIN(eps,eps*b0) .AND. b0*x0 <= 1.0D0) GO TO 90
IF (MAX(a0, b0) > 1.0D0) GO TO 20
IF (a0 >= MIN(0.2D0, b0)) GO TO 100
IF (x0**a0 <= 0.9D0) GO TO 100
IF (x0 >= 0.3D0) GO TO 110
n = 20
GO TO 130

20 IF (b0 <= 1.0D0) GO TO 100
IF (x0 >= 0.3D0) GO TO 110
IF (x0 >= 0.1D0) GO TO 21
IF ((x0*b0)**a0 <= 0.7D0) GO TO 100
21 IF (b0 > 15.0D0) GO TO 131
n = 20
GO TO 130

!             PROCEDURE FOR A0 .GT. 1 AND B0 .GT. 1

30 IF (a > b) GO TO 31
lambda = a - (a + b)*x
GO TO 32
31 lambda = (a + b)*y - b
32 IF (lambda >= 0.0D0) GO TO 40
ind = 1
a0 = b
b0 = a
x0 = y
y0 = x
lambda = ABS(lambda)

40 IF (b0 < 40.0D0 .AND. b0*x0 <= 0.7D0) GO TO 100
IF (b0 < 40.0D0) GO TO 140
IF (a0 > b0) GO TO 50
IF (a0 <= 100.0D0) GO TO 120
IF (lambda > 0.03D0*a0) GO TO 120
GO TO 180
50 IF (b0 <= 100.0D0) GO TO 120
IF (lambda > 0.03D0*b0) GO TO 120
GO TO 180

!            EVALUATION OF THE APPROPRIATE ALGORITHM

80 w = fpser(a0, b0, x0, eps)
w1 = 0.5D0 + (0.5D0 - w)
GO TO 220

90 w1 = apser(a0, b0, x0, eps)
w = 0.5D0 + (0.5D0 - w1)
GO TO 220

100 w = bpser(a0, b0, x0, eps)
w1 = 0.5D0 + (0.5D0 - w)
GO TO 220

110 w1 = bpser(b0, a0, y0, eps)
w = 0.5D0 + (0.5D0 - w1)
GO TO 220

120 w = bfrac(a0, b0, x0, y0, lambda, 15.0D0*eps)
w1 = 0.5D0 + (0.5D0 - w)
GO TO 220

130 w1 = bup(b0, a0, y0, x0, n, eps)
b0 = b0 + n
131 CALL bgrat (b0, a0, y0, x0, w1, eps, ierr1)
IF (ierr1 > 0) STOP "Error in BGRAT"
w = 0.5D0 + (0.5D0 - w1)
GO TO 220

140 n = b0
b0 = b0 - n
IF (b0 /= 0.0D0) GO TO 141
n = n - 1
b0 = 1.0D0
141 w = bup(b0, a0, y0, x0, n, eps)
IF (x0 > 0.7D0) GO TO 150
w = w + bpser(a0, b0, x0, eps)
w1 = 0.5D0 + (0.5D0 - w)
GO TO 220

150 IF (a0 > 15.0D0) GO TO 151
n = 20
w = w + bup(a0, b0, x0, y0, n, eps)
a0 = a0 + n
151 CALL bgrat (a0, b0, x0, y0, w, eps, ierr1)
w1 = 0.5D0 + (0.5D0 - w)
GO TO 220

180 w = basym(a0, b0, lambda, 100.0D0*eps)
w1 = 0.5D0 + (0.5D0 - w)
GO TO 220

!               TERMINATION OF THE PROCEDURE

200 IF (a == 0.0D0) GO TO 350
201 w = 0.0D0
w1 = 1.0D0
RETURN

210 IF (b == 0.0D0) GO TO 360
211 w = 1.0D0
w1 = 0.0D0
RETURN

220 IF (ind == 0) RETURN
t = w
w = w1
w1 = t
RETURN

!           PROCEDURE FOR A AND B .LT. 1.E-3*EPS

230 w = b/(a + b)
w1 = a/(a + b)
RETURN

!                       ERROR RETURN

300 ierr = 1
RETURN
310 ierr = 2
RETURN
320 ierr = 3
RETURN
330 ierr = 4
RETURN
340 ierr = 5
RETURN
350 ierr = 6
RETURN
360 ierr = 7
RETURN
END SUBROUTINE bratio



FUNCTION fpser (a, b, x, eps) RESULT(fn_val)
!-----------------------------------------------------------------------

!                 EVALUATION OF I (A,B)
!                                X

!          FOR B .LT. MIN(EPS,EPS*A) AND X .LE. 0.5.

!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, eps
REAL (dp)             :: fn_val


!                  SET  FPSER = X**A

REAL (dp) :: an, c, s, t, tol

fn_val = 1.0D0
IF (a <= 1.d-3*eps) GO TO 10
fn_val = 0.0D0
t = a*LOG(x)
IF (t < dxparg(1)) RETURN
fn_val = EXP(t)

!                NOTE THAT 1/B(A,B) = B

10 fn_val = (b/a)*fn_val
tol = eps/a
an = a + 1.0D0
t = x
s = t/an
20    an = an + 1.0D0
t = x*t
c = t/an
s = s + c
IF (ABS(c) > tol) GO TO 20

fn_val = fn_val*(1.0D0 + a*s)
RETURN
END FUNCTION fpser



FUNCTION apser (a, b, x, eps) RESULT(fn_val)
!-----------------------------------------------------------------------
!     APSER YIELDS THE INCOMPLETE BETA RATIO I(SUB(1-X))(B,A) FOR
!     A .LE. MIN(EPS,EPS*B), B*X .LE. 1, AND X .LE. 0.5. USED WHEN
!     A IS VERY SMALL. USE ONLY IF ABOVE INEQUALITIES ARE SATISFIED.
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, eps
REAL (dp)             :: fn_val

REAL (dp) :: j
!--------------------
REAL (dp) :: aj, bx, c
REAL (dp) :: g = .577215664901533D0, s, t, tol
!--------------------
bx = b*x
t = x - bx
IF (b*eps > 2.d-2) GO TO 10
c = LOG(x) + psi(b) + g + t
GO TO 20
10 c = LOG(bx) + g + t

20 tol = 5.0D0*eps*ABS(c)
j = 1.0D0
s = 0.0D0
30    j = j + 1.0D0
t = t*(x - bx/j)
aj = t/j
s = s + aj
IF (ABS(aj) > tol) GO TO 30

fn_val = -a*(c + s)
RETURN
END FUNCTION apser



FUNCTION bpser (a, b, x, eps) RESULT(fn_val)
!-----------------------------------------------------------------------
!     POWER SERIES EXPANSION FOR EVALUATING IX(A,B) WHEN B .LE. 1
!     OR B*X .LE. 0.7.  EPS IS THE TOLERANCE USED.
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, eps
REAL (dp)             :: fn_val

INTEGER   :: i, m
REAL (dp) :: apb, a0, b0, c, n, sum, t, tol, u, w, z

fn_val = 0.0D0
IF (x == 0.0D0) RETURN
!-----------------------------------------------------------------------
!            COMPUTE THE FACTOR X**A/(A*BETA(A,B))
!-----------------------------------------------------------------------
a0 = MIN(a,b)
IF (a0 < 1.0D0) GO TO 10
z = a*LOG(x) - betaln(a,b)
fn_val = EXP(z)/a
GO TO 70
10 b0 = MAX(a,b)
IF (b0 >= 8.0D0) GO TO 60
IF (b0 > 1.0D0) GO TO 40

!            PROCEDURE FOR A0 .LT. 1 AND B0 .LE. 1

fn_val = x**a
IF (fn_val == 0.0D0) RETURN

apb = a + b
IF (apb > 1.0D0) GO TO 20
z = 1.0D0 + gam1(apb)
GO TO 30
20 u = a + b - 1.d0
z = (1.0D0 + gam1(u))/apb

30 c = (1.0D0 + gam1(a))*(1.0D0 + gam1(b))/z
fn_val = fn_val*c*(b/apb)
GO TO 70

!         PROCEDURE FOR A0 .LT. 1 AND 1 .LT. B0 .LT. 8

40 u = gamln1(a0)
m = b0 - 1.0D0
IF (m < 1) GO TO 50
c = 1.0D0
DO i = 1, m
  b0 = b0 - 1.0D0
  c = c*(b0/(a0 + b0))
END DO
u = LOG(c) + u

50 z = a*LOG(x) - u
b0 = b0 - 1.0D0
apb = a0 + b0
IF (apb > 1.0D0) GO TO 51
t = 1.0D0 + gam1(apb)
GO TO 52
51 u = a0 + b0 - 1.d0
t = (1.0D0 + gam1(u))/apb
52 fn_val = EXP(z)*(a0/a)*(1.0D0 + gam1(b0))/t
GO TO 70

!            PROCEDURE FOR A0 .LT. 1 AND B0 .GE. 8

60 u = gamln1(a0) + algdiv(a0,b0)
z = a*LOG(x) - u
fn_val = (a0/a)*EXP(z)
70 IF (fn_val == 0.0D0 .OR. a <= 0.1D0*eps) RETURN
!-----------------------------------------------------------------------
!                     COMPUTE THE SERIES
!-----------------------------------------------------------------------
sum = 0.0D0
n = 0.0D0
c = 1.0D0
tol = eps/a
100    n = n + 1.0D0
c = c*(0.5D0 + (0.5D0 - b/n))*x
w = c/(a + n)
sum = sum + w
IF (ABS(w) > tol) GO TO 100
fn_val = fn_val*(1.0D0 + a*sum)
RETURN
END FUNCTION bpser



FUNCTION bup (a, b, x, y, n, eps) RESULT(fn_val)
!-----------------------------------------------------------------------
!     EVALUATION OF IX(A,B) - IX(A+N,B) WHERE N IS A POSITIVE INTEGER.
!     EPS IS THE TOLERANCE USED.
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, y, eps
INTEGER, INTENT(IN)   :: n
REAL (dp)             :: fn_val

!          OBTAIN THE SCALING FACTOR EXP(-MU) AND
!             EXP(MU)*(X**A*Y**B/BETA(A,B))/A

REAL (dp) :: apb, ap1, d, l, r, t, w
INTEGER   :: i, k, kp1, mu, nm1

apb = a + b
ap1 = a + 1.0D0
mu = 0
d = 1.0D0
IF (n == 1 .OR. a < 1.0D0) GO TO 10
IF (apb < 1.1D0*ap1) GO TO 10
mu = ABS(dxparg(1))
k = dxparg(0)
IF (k < mu) mu = k
t = mu
d = EXP(-t)

10 fn_val = brcmp1(mu,a,b,x,y)/a
IF (n == 1 .OR. fn_val == 0.0D0) RETURN
nm1 = n - 1
w = d

!          LET K BE THE INDEX OF THE MAXIMUM TERM

k = 0
IF (b <= 1.0D0) GO TO 40
IF (y > 1.d-4) GO TO 20
k = nm1
GO TO 30
20 r = (b - 1.0D0)*x/y - a
IF (r < 1.0D0) GO TO 40
k = nm1
t = nm1
IF (r < t) k = r

!          ADD THE INCREASING TERMS OF THE SERIES

30 DO i = 1,k
  l = i - 1
  d = ((apb + l)/(ap1 + l))*x*d
  w = w + d
END DO
IF (k == nm1) GO TO 50

!          ADD THE REMAINING TERMS OF THE SERIES

40 kp1 = k + 1
DO i = kp1,nm1
  l = i - 1
  d = ((apb + l)/(ap1 + l))*x*d
  w = w + d
  IF (d <= eps*w) GO TO 50
END DO

!               TERMINATE THE PROCEDURE

50 fn_val = fn_val*w
RETURN
END FUNCTION bup



FUNCTION bfrac (a, b, x, y, lambda, eps) RESULT(fn_val)
!-----------------------------------------------------------------------
!     CONTINUED FRACTION EXPANSION FOR IX(A,B) WHEN A,B .GT. 1.
!     IT IS ASSUMED THAT  LAMBDA = (A + B)*Y - B.
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, y, lambda, eps
REAL (dp)             :: fn_val

REAL (dp) :: alpha, an, anp1, beta, bn, bnp1, c, c0, c1, e, n, p, r, r0, s,  &
             t, w, yp1

fn_val = brcomp(a,b,x,y)
IF (fn_val == 0.0D0) RETURN

c = 1.0D0 + lambda
c0 = b/a
c1 = 1.0D0 + 1.0D0/a
yp1 = y + 1.0D0

n = 0.0D0
p = 1.0D0
s = a + 1.0D0
an = 0.0D0
bn = 1.0D0
anp1 = 1.0D0
bnp1 = c/c1
r = c1/c

!        CONTINUED FRACTION CALCULATION

10    n = n + 1.0D0
t = n/a
w = n*(b - n)*x
e = a/s
alpha = (p*(p + c0)*e*e)*(w*x)
IF (alpha <= 0.0D0) GO TO 20
e = (1.0D0 + t)/(c1 + t + t)
beta = n + w/s + e*(c + n*yp1)
p = 1.0D0 + t
s = s + 2.0D0

!        UPDATE AN, BN, ANP1, AND BNP1

t = alpha*an + beta*anp1
an = anp1
anp1 = t
t = alpha*bn + beta*bnp1
bn = bnp1
bnp1 = t
r0 = r
r = anp1/bnp1
IF (ABS(r - r0) <= eps*r) GO TO 20

!        RESCALE AN, BN, ANP1, AND BNP1

an = an/bnp1
bn = bn/bnp1
anp1 = r
bnp1 = 1.0D0
GO TO 10

!                 TERMINATION

20 fn_val = fn_val*r
RETURN
END FUNCTION bfrac



FUNCTION brcomp (a, b, x, y) RESULT(fn_val)
!-----------------------------------------------------------------------
!               EVALUATION OF X**A*Y**B/BETA(A,B)
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, y
REAL (dp)             :: fn_val

REAL (dp) :: lambda, lnx, lny
!-----------------
!     CONST = 1/SQRT(2*PI)
!-----------------
REAL (dp) :: apb, a0, b0, c, const = .398942280401433D0, e, h, t, u,  &
             v, x0, y0, z
INTEGER   :: i, n

fn_val = 0.0D0
IF (x == 0.0D0 .OR. y == 0.0D0) RETURN
a0 = MIN(a,b)
IF (a0 >= 8.0D0) GO TO 100

IF (x > 0.375D0) GO TO 10
lnx = LOG(x)
lny = alnrel(-x)
GO TO 20
10 IF (y > 0.375D0) GO TO 11
lnx = alnrel(-y)
lny = LOG(y)
GO TO 20
11 lnx = LOG(x)
lny = LOG(y)

20 z = a*lnx + b*lny
IF (a0 < 1.0D0) GO TO 30
z = z - betaln(a,b)
fn_val = EXP(z)
RETURN
!-----------------------------------------------------------------------
!              PROCEDURE FOR A .LT. 1 OR B .LT. 1
!-----------------------------------------------------------------------
30 b0 = MAX(a,b)
IF (b0 >= 8.0D0) GO TO 80
IF (b0 > 1.0D0) GO TO 60

!                   ALGORITHM FOR B0 .LE. 1

fn_val = EXP(z)
IF (fn_val == 0.0D0) RETURN

apb = a + b
IF (apb > 1.0D0) GO TO 40
z = 1.0D0 + gam1(apb)
GO TO 50
40 u = a + b - 1.d0
z = (1.0D0 + gam1(u))/apb

50 c = (1.0D0 + gam1(a))*(1.0D0 + gam1(b))/z
fn_val = fn_val*(a0*c)/(1.0D0 + a0/b0)
RETURN

!                ALGORITHM FOR 1 .LT. B0 .LT. 8

60 u = gamln1(a0)
n = b0 - 1.0D0
IF (n < 1) GO TO 70
c = 1.0D0
DO i = 1, n
  b0 = b0 - 1.0D0
  c = c*(b0/(a0 + b0))
END DO
u = LOG(c) + u

70 z = z - u
b0 = b0 - 1.0D0
apb = a0 + b0
IF (apb > 1.0D0) GO TO 71
t = 1.0D0 + gam1(apb)
GO TO 72
71 u = a0 + b0 - 1.d0
t = (1.0D0 + gam1(u))/apb
72 fn_val = a0*EXP(z)*(1.0D0 + gam1(b0))/t
RETURN

!                   ALGORITHM FOR B0 .GE. 8

80 u = gamln1(a0) + algdiv(a0,b0)
fn_val = a0*EXP(z - u)
RETURN
!-----------------------------------------------------------------------
!              PROCEDURE FOR A .GE. 8 AND B .GE. 8
!-----------------------------------------------------------------------
100 IF (a > b) GO TO 101
h = a/b
x0 = h/(1.0D0 + h)
y0 = 1.0D0/(1.0D0 + h)
lambda = a - (a + b)*x
GO TO 110
101 h = b/a
x0 = 1.0D0/(1.0D0 + h)
y0 = h/(1.0D0 + h)
lambda = (a + b)*y - b

110 e = -lambda/a
IF (ABS(e) > 0.6D0) GO TO 111
u = rlog1(e)
GO TO 120
111 u = e - LOG(x/x0)

120 e = lambda/b
IF (ABS(e) > 0.6D0) GO TO 121
v = rlog1(e)
GO TO 130
121 v = e - LOG(y/y0)

130 z = EXP(-(a*u + b*v))
fn_val = const*SQRT(b*x0)*z*EXP(-bcorr(a,b))
RETURN
END FUNCTION brcomp



FUNCTION brcmp1 (mu, a, b, x, y) RESULT(fn_val)
!-----------------------------------------------------------------------
!          EVALUATION OF  EXP(MU) * (X**A*Y**B/BETA(A,B))
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, x, y
INTEGER, INTENT(IN)   :: mu
REAL (dp)             :: fn_val

REAL (dp) :: lambda, lnx, lny
!-----------------
!     CONST = 1/SQRT(2*PI)
!-----------------
REAL (dp) :: apb, a0, b0, c, const = .398942280401433D0, e, h, t, u, v,  &
             x0, y0, z
INTEGER   :: i, n

a0 = MIN(a,b)
IF (a0 >= 8.0D0) GO TO 100

IF (x > 0.375D0) GO TO 10
lnx = LOG(x)
lny = alnrel(-x)
GO TO 20
10 IF (y > 0.375D0) GO TO 11
lnx = alnrel(-y)
lny = LOG(y)
GO TO 20
11 lnx = LOG(x)
lny = LOG(y)

20 z = a*lnx + b*lny
IF (a0 < 1.0D0) GO TO 30
z = z - betaln(a,b)
fn_val = esum(mu,z)
RETURN
!-----------------------------------------------------------------------
!              PROCEDURE FOR A .LT. 1 OR B .LT. 1
!-----------------------------------------------------------------------
30 b0 = MAX(a,b)
IF (b0 >= 8.0D0) GO TO 80
IF (b0 > 1.0D0) GO TO 60

!                   ALGORITHM FOR B0 .LE. 1

fn_val = esum(mu,z)
IF (fn_val == 0.0D0) RETURN

apb = a + b
IF (apb > 1.0D0) GO TO 40
z = 1.0D0 + gam1(apb)
GO TO 50
40 u = a + b - 1.d0
z = (1.0D0 + gam1(u))/apb

50 c = (1.0D0 + gam1(a))*(1.0D0 + gam1(b))/z
fn_val = fn_val*(a0*c)/(1.0D0 + a0/b0)
RETURN

!                ALGORITHM FOR 1 .LT. B0 .LT. 8

60 u = gamln1(a0)
n = b0 - 1.0D0
IF (n < 1) GO TO 70
c = 1.0D0
DO i = 1, n
  b0 = b0 - 1.0D0
  c = c*(b0/(a0 + b0))
END DO
u = LOG(c) + u

70 z = z - u
b0 = b0 - 1.0D0
apb = a0 + b0
IF (apb > 1.0D0) GO TO 71
t = 1.0D0 + gam1(apb)
GO TO 72
71 u = a0 + b0 - 1.d0
t = (1.0D0 + gam1(u))/apb
72 fn_val = a0*esum(mu,z)*(1.0D0 + gam1(b0))/t
RETURN

!                   ALGORITHM FOR B0 .GE. 8

80 u = gamln1(a0) + algdiv(a0,b0)
fn_val = a0*esum(mu,z - u)
RETURN
!-----------------------------------------------------------------------
!              PROCEDURE FOR A .GE. 8 AND B .GE. 8
!-----------------------------------------------------------------------
100 IF (a > b) GO TO 101
h = a/b
x0 = h/(1.0D0 + h)
y0 = 1.0D0/(1.0D0 + h)
lambda = a - (a + b)*x
GO TO 110
101 h = b/a
x0 = 1.0D0/(1.0D0 + h)
y0 = h/(1.0D0 + h)
lambda = (a + b)*y - b

110 e = -lambda/a
IF (ABS(e) > 0.6D0) GO TO 111
u = rlog1(e)
GO TO 120
111 u = e - LOG(x/x0)

120 e = lambda/b
IF (ABS(e) > 0.6D0) GO TO 121
v = rlog1(e)
GO TO 130
121 v = e - LOG(y/y0)

130 z = esum(mu,-(a*u + b*v))
fn_val = const*SQRT(b*x0)*z*EXP(-bcorr(a,b))
RETURN
END FUNCTION brcmp1



FUNCTION basym (a, b, lambda, eps) RESULT(fn_val)
!-----------------------------------------------------------------------
!     ASYMPTOTIC EXPANSION FOR IX(A,B) FOR LARGE A AND B.
!     LAMBDA = (A + B)*Y - B  AND EPS IS THE TOLERANCE USED.
!     IT IS ASSUMED THAT LAMBDA IS NONNEGATIVE AND THAT
!     A AND B ARE GREATER THAN OR EQUAL TO 15.
!-----------------------------------------------------------------------
IMPLICIT NONE
REAL (dp), INTENT(IN) :: a, b, lambda, eps
REAL (dp)             :: fn_val

REAL (dp) :: j0, j1
REAL (dp) :: a0(21), b0(21), c(21), d(21)
!------------------------
!     ****** NUM IS THE MAXIMUM VALUE THAT N CAN TAKE IN THE DO LOOP
!            ENDING AT STATEMENT 50. IT IS REQUIRED THAT NUM BE EVEN.
!            THE ARRAYS A0, B0, C, D HAVE DIMENSION NUM + 1.

REAL (dp) :: bsum, dsum, e0 = 1.12837916709551D0, e1 = .353553390593274D0,  &
             f, h, hn, h2, r, r0, r1, s, sum, t, t0, t1, u, w, w0, z, zn,  &
             znm1, z0, z2
INTEGER   :: i, im1, imj, j, m, mm1, mmj, n, np1, num = 20
!------------------------
!     E0 = 2/SQRT(PI)
!     E1 = 2**(-3/2)
!------------------------
fn_val = 0.0D0
IF (a >= b) GO TO 10
h = a/b
r0 = 1.0D0/(1.0D0 + h)
r1 = (b - a)/b
w0 = 1.0D0/SQRT(a*(1.0D0 + h))
GO TO 20
10 h = b/a
r0 = 1.0D0/(1.0D0 + h)
r1 = (b - a)/a
w0 = 1.0D0/SQRT(b*(1.0D0 + h))

20 f = a*rlog1(-lambda/a) + b*rlog1(lambda/b)
t = EXP(-f)
IF (t == 0.0D0) RETURN
z0 = SQRT(f)
z = 0.5D0*(z0/e1)
z2 = f + f

a0(1) = (2.0D0/3.0D0)*r1
c(1) = - 0.5D0*a0(1)
d(1) = - c(1)
j0 = (0.5D0/e0)*erfc1(1,z0)
j1 = e1
sum = j0 + d(1)*w0*j1

s = 1.0D0
h2 = h*h
hn = 1.0D0
w = w0
znm1 = z
zn = z2
DO n = 2, num, 2
  hn = h2*hn
  a0(n) = 2.0D0*r0*(1.0D0 + h*hn)/(n + 2.0D0)
  np1 = n + 1
  s = s + hn
  a0(np1) = 2.0D0*r1*s/(n + 3.0D0)
  
  DO i = n, np1
    r = -0.5D0*(i + 1.0D0)
    b0(1) = r*a0(1)
    DO m = 2, i
      bsum = 0.0D0
      mm1 = m - 1
      DO j = 1, mm1
        mmj = m - j
        bsum = bsum + (j*r - mmj)*a0(j)*b0(mmj)
      END DO
      b0(m) = r*a0(m) + bsum/m
    END DO
    c(i) = b0(i)/(i + 1.0D0)
    
    dsum = 0.0D0
    im1 = i - 1
    DO j = 1, im1
      imj = i - j
      dsum = dsum + d(imj)*c(j)
    END DO
    d(i) = -(dsum + c(i))
  END DO
  
  j0 = e1*znm1 + (n - 1.0D0)*j0
  j1 = e1*zn + n*j1
  znm1 = z2*znm1
  zn = z2*zn
  w = w0*w
  t0 = d(n)*w*j0
  w = w0*w
  t1 = d(np1)*w*j1
  sum = sum + (t0 + t1)
  IF ((ABS(t0) + ABS(t1)) <= eps*sum) GO TO 60
END DO

60 u = EXP(-bcorr(a,b))
fn_val = e0*t*u*sum
RETURN
END FUNCTION basym


END MODULE FDist_BR
