LCOV - code coverage report
Current view: top level - src - beta_gamma_psi.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 31 883 3.5 %
Date: 2024-11-21 06:45:46 Functions: 3 25 12.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : MODULE beta_gamma_psi
      10             :    ! not tested in the case where dp would stand for single precision
      11             :    ! Routines for the beta function are untested
      12             : 
      13             :    USE kinds,                           ONLY: dp
      14             : #include "./base/base_uses.f90"
      15             : 
      16             :    IMPLICIT NONE
      17             : 
      18             :    PRIVATE
      19             : 
      20             :    PUBLIC :: psi
      21             : 
      22             : CONTAINS
      23             : 
      24             : ! **************************************************************************************************
      25             : !> \brief ...
      26             : !> \param i ...
      27             : !> \return ...
      28             : ! **************************************************************************************************
      29        7564 :    FUNCTION ipmpar(i) RESULT(fn_val)
      30             : !-----------------------------------------------------------------------
      31             : 
      32             : !     IPMPAR PROVIDES THE INTEGER MACHINE CONSTANTS FOR THE COMPUTER
      33             : !     THAT IS USED. IT IS ASSUMED THAT THE ARGUMENT I IS AN INTEGER
      34             : !     HAVING ONE OF THE VALUES 1-10. IPMPAR(I) HAS THE VALUE ...
      35             : 
      36             : !  INTEGERS.
      37             : 
      38             : !     ASSUME INTEGERS ARE REPRESENTED IN THE N-DIGIT, BASE-A FORM
      39             : 
      40             : !               SIGN ( X(N-1)*A**(N-1) + ... + X(1)*A + X(0) )
      41             : 
      42             : !               WHERE 0 .LE. X(I) .LT. A FOR I=0,...,N-1.
      43             : 
      44             : !     IPMPAR(1) = A, THE BASE (radix).
      45             : 
      46             : !     IPMPAR(2) = N, THE NUMBER OF BASE-A DIGITS (digits).
      47             : 
      48             : !     IPMPAR(3) = A**N - 1, THE LARGEST MAGNITUDE (huge).
      49             : 
      50             : !  FLOATING-POINT NUMBERS.
      51             : 
      52             : !     IT IS ASSUMED THAT THE SINGLE AND DOUBLE PRECISION FLOATING
      53             : !     POINT ARITHMETICS HAVE THE SAME BASE, SAY B, AND THAT THE
      54             : !     NONZERO NUMBERS ARE REPRESENTED IN THE FORM
      55             : 
      56             : !               SIGN (B**E) * (X(1)/B + ... + X(M)/B**M)
      57             : 
      58             : !               WHERE X(I) = 0,1,...,B-1 FOR I=1,...,M,
      59             : !               X(1) .GE. 1, AND EMIN .LE. E .LE. EMAX.
      60             : 
      61             : !     IPMPAR(4) = B, THE BASE.
      62             : 
      63             : !  SINGLE-PRECISION
      64             : 
      65             : !     IPMPAR(5) = M, THE NUMBER OF BASE-B DIGITS.
      66             : 
      67             : !     IPMPAR(6) = EMIN, THE SMALLEST EXPONENT E.
      68             : 
      69             : !     IPMPAR(7) = EMAX, THE LARGEST EXPONENT E.
      70             : 
      71             : !  DOUBLE-PRECISION
      72             : 
      73             : !     IPMPAR(8) = M, THE NUMBER OF BASE-B DIGITS.
      74             : 
      75             : !     IPMPAR(9) = EMIN, THE SMALLEST EXPONENT E.
      76             : 
      77             : !     IPMPAR(10) = EMAX, THE LARGEST EXPONENT E.
      78             : 
      79             : !-----------------------------------------------------------------------
      80             : 
      81             :       INTEGER, INTENT(IN)                                :: i
      82             :       INTEGER                                            :: fn_val
      83             : 
      84        7564 :       SELECT CASE (i)
      85             :       CASE (1)
      86           0 :          fn_val = RADIX(i)
      87             :       CASE (2)
      88           0 :          fn_val = DIGITS(i)
      89             :       CASE (3)
      90        7564 :          fn_val = HUGE(i)
      91             :       CASE (4)
      92           0 :          fn_val = RADIX(1.0)
      93             :       CASE (5)
      94           0 :          fn_val = DIGITS(1.0)
      95             :       CASE (6)
      96           0 :          fn_val = MINEXPONENT(1.0)
      97             :       CASE (7)
      98           0 :          fn_val = MAXEXPONENT(1.0)
      99             :       CASE (8)
     100           0 :          fn_val = DIGITS(1.0e0_dp)
     101             :       CASE (9)
     102           0 :          fn_val = MINEXPONENT(1.0e0_dp)
     103             :       CASE (10)
     104           0 :          fn_val = MAXEXPONENT(1.0e0_dp)
     105             :       CASE DEFAULT
     106        7564 :          CPABORT("unknown case")
     107             :       END SELECT
     108             : 
     109        7564 :    END FUNCTION ipmpar
     110             : 
     111             : ! **************************************************************************************************
     112             : !> \brief ...
     113             : !> \param i ...
     114             : !> \return ...
     115             : ! **************************************************************************************************
     116        7564 :    FUNCTION dpmpar(i) RESULT(fn_val)
     117             : !-----------------------------------------------------------------------
     118             : 
     119             : !     DPMPAR PROVIDES THE DOUBLE PRECISION MACHINE CONSTANTS FOR
     120             : !     THE COMPUTER BEING USED. IT IS ASSUMED THAT THE ARGUMENT
     121             : !     I IS AN INTEGER HAVING ONE OF THE VALUES 1, 2, OR 3. IF THE
     122             : !     DOUBLE PRECISION ARITHMETIC BEING USED HAS M BASE B DIGITS AND
     123             : !     ITS SMALLEST AND LARGEST EXPONENTS ARE EMIN AND EMAX, THEN
     124             : 
     125             : !        DPMPAR(1) = B**(1 - M), THE MACHINE PRECISION,
     126             : 
     127             : !        DPMPAR(2) = B**(EMIN - 1), THE SMALLEST MAGNITUDE,
     128             : 
     129             : !        DPMPAR(3) = B**EMAX*(1 - B**(-M)), THE LARGEST MAGNITUDE.
     130             : !-----------------------------------------------------------------------
     131             : 
     132             :       INTEGER, INTENT(IN)                                :: i
     133             :       REAL(dp)                                           :: fn_val
     134             : 
     135             :       REAL(dp), PARAMETER                                :: one = 1._dp
     136             : 
     137             : ! Local variable
     138             : 
     139       15128 :       SELECT CASE (i)
     140             :       CASE (1)
     141        7564 :          fn_val = EPSILON(one)
     142             :       CASE (2)
     143           0 :          fn_val = TINY(one)
     144             :       CASE (3)
     145        7564 :          fn_val = HUGE(one)
     146             :       END SELECT
     147             : 
     148        7564 :    END FUNCTION dpmpar
     149             : 
     150             : ! **************************************************************************************************
     151             : !> \brief ...
     152             : !> \param l ...
     153             : !> \return ...
     154             : ! **************************************************************************************************
     155           0 :    FUNCTION dxparg(l) RESULT(fn_val)
     156             : !--------------------------------------------------------------------
     157             : !     IF L = 0 THEN  DXPARG(L) = THE LARGEST POSITIVE W FOR WHICH
     158             : !     DEXP(W) CAN BE COMPUTED.
     159             : !
     160             : !     IF L IS NONZERO THEN  DXPARG(L) = THE LARGEST NEGATIVE W FOR
     161             : !     WHICH THE COMPUTED VALUE OF DEXP(W) IS NONZERO.
     162             : !
     163             : !     NOTE... ONLY AN APPROXIMATE VALUE FOR DXPARG(L) IS NEEDED.
     164             : !--------------------------------------------------------------------
     165             :       INTEGER, INTENT(IN)                                :: l
     166             :       REAL(dp)                                           :: fn_val
     167             : 
     168             :       REAL(dp), PARAMETER                                :: one = 1._dp
     169             : 
     170             : ! Local variable
     171             : 
     172           0 :       IF (l == 0) THEN
     173             :          fn_val = LOG(HUGE(one))
     174             :       ELSE
     175           0 :          fn_val = LOG(TINY(one))
     176             :       END IF
     177             : 
     178           0 :    END FUNCTION dxparg
     179             : 
     180             : ! **************************************************************************************************
     181             : !> \brief ...
     182             : !> \param a ...
     183             : !> \return ...
     184             : ! **************************************************************************************************
     185           0 :    FUNCTION alnrel(a) RESULT(fn_val)
     186             : !-----------------------------------------------------------------------
     187             : !            EVALUATION OF THE FUNCTION LN(1 + A)
     188             : !-----------------------------------------------------------------------
     189             :       REAL(dp), INTENT(IN)                               :: a
     190             :       REAL(dp)                                           :: fn_val
     191             : 
     192             :       REAL(dp), PARAMETER :: half = 0.5e0_dp, one = 1.e0_dp, p1 = -.129418923021993e+01_dp, &
     193             :          p2 = .405303492862024e+00_dp, p3 = -.178874546012214e-01_dp, &
     194             :          q1 = -.162752256355323e+01_dp, q2 = .747811014037616e+00_dp, &
     195             :          q3 = -.845104217945565e-01_dp, two = 2.e0_dp, zero = 0.e0_dp
     196             : 
     197             :       REAL(dp)                                           :: t, t2, w, x
     198             : 
     199             : !--------------------------
     200             : 
     201           0 :       IF (ABS(a) <= 0.375e0_dp) THEN
     202           0 :          t = a/(a + two)
     203           0 :          t2 = t*t
     204           0 :          w = (((p3*t2 + p2)*t2 + p1)*t2 + one)/(((q3*t2 + q2)*t2 + q1)*t2 + one)
     205           0 :          fn_val = two*t*w
     206             :       ELSE
     207           0 :          x = one + a
     208           0 :          IF (a < zero) x = (a + half) + half
     209           0 :          fn_val = LOG(x)
     210             :       END IF
     211             : 
     212           0 :    END FUNCTION alnrel
     213             : 
     214             : ! **************************************************************************************************
     215             : !> \brief ...
     216             : !> \param a ...
     217             : !> \return ...
     218             : ! **************************************************************************************************
     219           0 :    FUNCTION gam1(a) RESULT(fn_val)
     220             : !-----------------------------------------------------------------------
     221             : !     COMPUTATION OF 1/GAMMA(A+1) - 1  FOR -0.5 <= A <= 1.5
     222             : !-----------------------------------------------------------------------
     223             :       REAL(dp), INTENT(IN)                               :: a
     224             :       REAL(dp)                                           :: fn_val
     225             : 
     226             :       REAL(dp), PARAMETER :: p(7) = (/.577215664901533e+00_dp, -.409078193005776e+00_dp, &
     227             :          -.230975380857675e+00_dp, .597275330452234e-01_dp, .766968181649490e-02_dp, &
     228             :          -.514889771323592e-02_dp, .589597428611429e-03_dp/), q(5) = (/.100000000000000e+01_dp, &
     229             :          .427569613095214e+00_dp, .158451672430138e+00_dp, .261132021441447e-01_dp, &
     230             :          .423244297896961e-02_dp/), r(9) = (/-.422784335098468e+00_dp, -.771330383816272e+00_dp, &
     231             :          -.244757765222226e+00_dp, .118378989872749e+00_dp, .930357293360349e-03_dp, &
     232             :          -.118290993445146e-01_dp, .223047661158249e-02_dp, .266505979058923e-03_dp, &
     233             :          -.132674909766242e-03_dp/)
     234             :       REAL(dp), PARAMETER :: s1 = .273076135303957e+00_dp, s2 = .559398236957378e-01_dp
     235             : 
     236             :       REAL(dp)                                           :: bot, d, t, top, w
     237             : 
     238           0 :       t = a
     239           0 :       d = a - 0.5e0_dp
     240           0 :       IF (d > 0.0e0_dp) t = d - 0.5e0_dp
     241             : 
     242           0 :       IF (t > 0.e0_dp) THEN
     243           0 :          top = (((((p(7)*t + p(6))*t + p(5))*t + p(4))*t + p(3))*t + p(2))*t + p(1)
     244           0 :          bot = (((q(5)*t + q(4))*t + q(3))*t + q(2))*t + 1.0e0_dp
     245           0 :          w = top/bot
     246           0 :          IF (d > 0.0e0_dp) THEN
     247           0 :             fn_val = (t/a)*((w - 0.5e0_dp) - 0.5e0_dp)
     248             :          ELSE
     249           0 :             fn_val = a*w
     250             :          END IF
     251           0 :       ELSE IF (t < 0.e0_dp) THEN
     252             :          top = (((((((r(9)*t + r(8))*t + r(7))*t + r(6))*t + r(5))*t &
     253           0 :                   + r(4))*t + r(3))*t + r(2))*t + r(1)
     254           0 :          bot = (s2*t + s1)*t + 1.0e0_dp
     255           0 :          w = top/bot
     256           0 :          IF (d > 0.0e0_dp) THEN
     257           0 :             fn_val = t*w/a
     258             :          ELSE
     259           0 :             fn_val = a*((w + 0.5e0_dp) + 0.5e0_dp)
     260             :          END IF
     261             :       ELSE
     262             :          fn_val = 0.0e0_dp
     263             :       END IF
     264             : 
     265           0 :    END FUNCTION gam1
     266             : 
     267             : ! **************************************************************************************************
     268             : !> \brief ...
     269             : !> \param a ...
     270             : !> \param b ...
     271             : !> \return ...
     272             : ! **************************************************************************************************
     273           0 :    FUNCTION algdiv(a, b) RESULT(fn_val)
     274             : !-----------------------------------------------------------------------
     275             : 
     276             : !     COMPUTATION OF LN(GAMMA(B)/GAMMA(A+B)) WHEN B >= 8
     277             : 
     278             : !                         --------
     279             : 
     280             : !     IN THIS ALGORITHM, DEL(X) IS THE FUNCTION DEFINED BY
     281             : !     LN(GAMMA(X)) = (X - 0.5)*LN(X) - X + 0.5*LN(2*PI) + DEL(X).
     282             : 
     283             : !-----------------------------------------------------------------------
     284             :       REAL(dp), INTENT(IN)                               :: a, b
     285             :       REAL(dp)                                           :: fn_val
     286             : 
     287             :       REAL(dp), PARAMETER :: c0 = .833333333333333e-01_dp, c1 = -.277777777760991e-02_dp, &
     288             :          c2 = .793650666825390e-03_dp, c3 = -.595202931351870e-03_dp, &
     289             :          c4 = .837308034031215e-03_dp, c5 = -.165322962780713e-02_dp
     290             : 
     291             :       REAL(dp)                                           :: c, d, h, s11, s3, s5, s7, s9, t, u, v, &
     292             :                                                             w, x, x2
     293             : 
     294           0 :       IF (a > b) THEN
     295           0 :          h = b/a
     296           0 :          c = 1.0e0_dp/(1.0e0_dp + h)
     297           0 :          x = h/(1.0e0_dp + h)
     298           0 :          d = a + (b - 0.5e0_dp)
     299             :       ELSE
     300           0 :          h = a/b
     301           0 :          c = h/(1.0e0_dp + h)
     302           0 :          x = 1.0e0_dp/(1.0e0_dp + h)
     303           0 :          d = b + (a - 0.5e0_dp)
     304             :       END IF
     305             : 
     306             : !                SET SN = (1 - X**N)/(1 - X)
     307             : 
     308           0 :       x2 = x*x
     309           0 :       s3 = 1.0e0_dp + (x + x2)
     310           0 :       s5 = 1.0e0_dp + (x + x2*s3)
     311           0 :       s7 = 1.0e0_dp + (x + x2*s5)
     312           0 :       s9 = 1.0e0_dp + (x + x2*s7)
     313           0 :       s11 = 1.0e0_dp + (x + x2*s9)
     314             : 
     315             : !                SET W = DEL(B) - DEL(A + B)
     316             : 
     317           0 :       t = (1.0e0_dp/b)**2
     318           0 :       w = ((((c5*s11*t + c4*s9)*t + c3*s7)*t + c2*s5)*t + c1*s3)*t + c0
     319           0 :       w = w*(c/b)
     320             : 
     321             : !                    COMBINE THE RESULTS
     322             : 
     323           0 :       u = d*alnrel(a/b)
     324           0 :       v = a*(LOG(b) - 1.0e0_dp)
     325           0 :       IF (u > v) THEN
     326           0 :          fn_val = (w - v) - u
     327             :       ELSE
     328           0 :          fn_val = (w - u) - v
     329             :       END IF
     330             : 
     331           0 :    END FUNCTION algdiv
     332             : 
     333             : ! **************************************************************************************************
     334             : !> \brief ...
     335             : !> \param x ...
     336             : !> \return ...
     337             : ! **************************************************************************************************
     338           0 :    FUNCTION rexp(x) RESULT(fn_val)
     339             : !-----------------------------------------------------------------------
     340             : !            EVALUATION OF THE FUNCTION EXP(X) - 1
     341             : !-----------------------------------------------------------------------
     342             :       REAL(dp), INTENT(IN)                               :: x
     343             :       REAL(dp)                                           :: fn_val
     344             : 
     345             :       REAL(dp), PARAMETER :: p1 = .914041914819518e-09_dp, p2 = .238082361044469e-01_dp, &
     346             :          q1 = -.499999999085958e+00_dp, q2 = .107141568980644e+00_dp, &
     347             :          q3 = -.119041179760821e-01_dp, q4 = .595130811860248e-03_dp
     348             : 
     349             :       REAL(dp)                                           :: e
     350             : 
     351           0 :       IF (ABS(x) < 0.15e0_dp) THEN
     352           0 :          fn_val = x*(((p2*x + p1)*x + 1.0e0_dp)/((((q4*x + q3)*x + q2)*x + q1)*x + 1.0e0_dp))
     353           0 :          RETURN
     354             :       END IF
     355             : 
     356           0 :       IF (x < 0.0e0_dp) THEN
     357           0 :          IF (x > -37.0e0_dp) THEN
     358           0 :             fn_val = (EXP(x) - 0.5e0_dp) - 0.5e0_dp
     359             :          ELSE
     360             :             fn_val = -1.0e0_dp
     361             :          END IF
     362             :       ELSE
     363           0 :          e = EXP(x)
     364           0 :          fn_val = e*(0.5e0_dp + (0.5e0_dp - 1.0e0_dp/e))
     365             :       END IF
     366             : 
     367             :    END FUNCTION rexp
     368             : 
     369             : ! **************************************************************************************************
     370             : !> \brief ...
     371             : !> \param a ...
     372             : !> \param b ...
     373             : !> \param x ...
     374             : !> \param y ...
     375             : !> \param w ...
     376             : !> \param eps ...
     377             : !> \param ierr ...
     378             : ! **************************************************************************************************
     379           0 :    SUBROUTINE bgrat(a, b, x, y, w, eps, ierr)
     380             : !-----------------------------------------------------------------------
     381             : !     ASYMPTOTIC EXPANSION FOR IX(A,B) WHEN A IS LARGER THAN B.
     382             : !     THE RESULT OF THE EXPANSION IS ADDED TO W. IT IS ASSUMED
     383             : !     THAT A <= 15 AND B <= 1.  EPS IS THE TOLERANCE USED.
     384             : !     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
     385             : !-----------------------------------------------------------------------
     386             :       REAL(dp), INTENT(IN)                               :: a, b, x, y
     387             :       REAL(dp), INTENT(INOUT)                            :: w
     388             :       REAL(dp), INTENT(IN)                               :: eps
     389             :       INTEGER, INTENT(OUT)                               :: ierr
     390             : 
     391             :       REAL(dp), PARAMETER                                :: half = 0.5e0_dp, one = 1.e0_dp, &
     392             :                                                             quarter = 0.25e0_dp, zero = 0.e0_dp
     393             : 
     394             :       INTEGER                                            :: i, n
     395             :       REAL(dp)                                           :: bm1, bp2n, c(30), cn, coef, d(30), dj, &
     396             :                                                             j, l, lnx, n2, nu, q, r, s, sum, t, &
     397             :                                                             t2, tol, u, v, z
     398             : 
     399           0 :       bm1 = (b - half) - half
     400           0 :       nu = a + half*bm1
     401           0 :       IF (y > 0.375e0_dp) THEN
     402           0 :          lnx = LOG(x)
     403             :       ELSE
     404           0 :          lnx = alnrel(-y)
     405             :       END IF
     406           0 :       z = -nu*lnx
     407           0 :       IF (b*z == zero) THEN
     408             :          !               THE EXPANSION CANNOT BE COMPUTED
     409           0 :          ierr = 1
     410           0 :          RETURN
     411             :       END IF
     412             : 
     413             : !                 COMPUTATION OF THE EXPANSION
     414             : !                 SET R = EXP(-Z)*Z**B/GAMMA(B)
     415             : 
     416           0 :       r = b*(one + gam1(b))*EXP(b*LOG(z))
     417           0 :       r = r*EXP(a*lnx)*EXP(half*bm1*lnx)
     418           0 :       u = algdiv(b, a) + b*LOG(nu)
     419           0 :       u = r*EXP(-u)
     420           0 :       IF (u == zero) THEN
     421             :          !               THE EXPANSION CANNOT BE COMPUTED
     422           0 :          ierr = 1
     423           0 :          RETURN
     424             :       END IF
     425           0 :       CALL grat1(b, z, r, q=q, eps=eps)
     426             : 
     427           0 :       tol = 15.0e0_dp*eps
     428           0 :       v = quarter*(one/nu)**2
     429           0 :       t2 = quarter*lnx*lnx
     430           0 :       l = w/u
     431           0 :       j = q/r
     432           0 :       sum = j
     433           0 :       t = one
     434           0 :       cn = one
     435           0 :       n2 = zero
     436           0 :       DO n = 1, 30
     437           0 :          bp2n = b + n2
     438           0 :          j = (bp2n*(bp2n + one)*j + (z + bp2n + one)*t)*v
     439           0 :          n2 = n2 + 2.0e0_dp
     440           0 :          t = t*t2
     441           0 :          cn = cn/(n2*(n2 + one))
     442           0 :          c(n) = cn
     443           0 :          s = zero
     444           0 :          IF (.NOT. (n == 1)) THEN
     445           0 :             coef = b - n
     446           0 :             DO i = 1, n - 1
     447           0 :                s = s + coef*c(i)*d(n - i)
     448           0 :                coef = coef + b
     449             :             END DO
     450             :          END IF
     451           0 :          d(n) = bm1*cn + s/n
     452           0 :          dj = d(n)*j
     453           0 :          sum = sum + dj
     454           0 :          IF (sum <= zero) THEN
     455             :             !               THE EXPANSION CANNOT BE COMPUTED
     456           0 :             ierr = 1
     457           0 :             RETURN
     458             :          END IF
     459           0 :          IF (ABS(dj) <= tol*(sum + l)) EXIT
     460             :       END DO
     461             : 
     462             : !                    ADD THE RESULTS TO W
     463             : 
     464           0 :       ierr = 0
     465           0 :       w = w + u*sum
     466             : 
     467             :    END SUBROUTINE bgrat
     468             : 
     469             : ! **************************************************************************************************
     470             : !> \brief ...
     471             : !> \param a ...
     472             : !> \param x ...
     473             : !> \param r ...
     474             : !> \param p ...
     475             : !> \param q ...
     476             : !> \param eps ...
     477             : ! **************************************************************************************************
     478           0 :    SUBROUTINE grat1(a, x, r, p, q, eps)
     479             : !-----------------------------------------------------------------------
     480             : !           EVALUATION OF P(A,X) AND Q(A,X) WHERE A <= 1 AND
     481             : !        THE INPUT ARGUMENT R HAS THE VALUE E**(-X)*X**A/GAMMA(A)
     482             : !-----------------------------------------------------------------------
     483             :       REAL(dp), INTENT(IN)                               :: a, x, r
     484             :       REAL(dp), INTENT(OUT), OPTIONAL                    :: p, q
     485             :       REAL(dp), INTENT(IN)                               :: eps
     486             : 
     487             :       REAL(dp), PARAMETER                                :: half = 0.5e0_dp, one = 1.e0_dp, &
     488             :                                                             quarter = 0.25e0_dp, three = 3.e0_dp, &
     489             :                                                             two = 2.e0_dp, zero = 0.e0_dp
     490             : 
     491             :       REAL(dp)                                           :: a2n, a2nm1, an, b2n, b2nm1, c, g, h, j, &
     492             :                                                             l, pp, qq, sum, t, tol, w, z
     493             : 
     494           0 :       IF (a*x == zero) THEN
     495           0 :          IF (x <= a) THEN
     496             :             pp = zero
     497             :             qq = one
     498             :          ELSE
     499           0 :             pp = one
     500           0 :             qq = zero
     501             :          END IF
     502           0 :          IF (PRESENT(p)) p = pp
     503           0 :          IF (PRESENT(q)) q = qq
     504           0 :          RETURN
     505             :       END IF
     506           0 :       IF (a == half) THEN
     507           0 :       IF (x < quarter) THEN
     508           0 :          pp = ERF(SQRT(x))
     509           0 :          qq = half + (half - pp)
     510             :       ELSE
     511           0 :          qq = ERFC(SQRT(x))
     512           0 :          pp = half + (half - qq)
     513             :       END IF
     514           0 :       IF (PRESENT(p)) p = pp
     515           0 :       IF (PRESENT(q)) q = qq
     516           0 :       RETURN
     517             :       END IF
     518           0 :       IF (x < 1.1e0_dp) THEN
     519             :          !             TAYLOR SERIES FOR P(A,X)/X**A
     520             : 
     521           0 :          an = three
     522           0 :          c = x
     523           0 :          sum = x/(a + three)
     524           0 :          tol = three*eps/(a + one)
     525           0 :          an = an + one
     526           0 :          c = -c*(x/an)
     527           0 :          t = c/(a + an)
     528           0 :          sum = sum + t
     529           0 :          DO WHILE (ABS(t) > tol)
     530           0 :             an = an + one
     531           0 :             c = -c*(x/an)
     532           0 :             t = c/(a + an)
     533           0 :             sum = sum + t
     534             :          END DO
     535           0 :          j = a*x*((sum/6.0e0_dp - half/(a + two))*x + one/(a + one))
     536             : 
     537           0 :          z = a*LOG(x)
     538           0 :          h = gam1(a)
     539           0 :          g = one + h
     540           0 :          IF ((x < quarter .AND. z > -.13394e0_dp) .OR. a < x/2.59e0_dp) THEN
     541           0 :             l = rexp(z)
     542           0 :             qq = ((half + (half + l))*j - l)*g - h
     543           0 :             IF (qq <= zero) THEN
     544             :                pp = one
     545             :                qq = zero
     546             :             ELSE
     547           0 :                pp = half + (half - qq)
     548             :             END IF
     549             :          ELSE
     550           0 :             w = EXP(z)
     551           0 :             pp = w*g*(half + (half - j))
     552           0 :             qq = half + (half - pp)
     553             :          END IF
     554             :       ELSE
     555             :          !              CONTINUED FRACTION EXPANSION
     556             : 
     557           0 :          tol = 8.0e0_dp*eps
     558           0 :          a2nm1 = one
     559           0 :          a2n = one
     560           0 :          b2nm1 = x
     561           0 :          b2n = x + (one - a)
     562           0 :          c = one
     563             :          DO
     564           0 :             a2nm1 = x*a2n + c*a2nm1
     565           0 :             b2nm1 = x*b2n + c*b2nm1
     566           0 :             c = c + one
     567           0 :             a2n = a2nm1 + (c - a)*a2n
     568           0 :             b2n = b2nm1 + (c - a)*b2n
     569           0 :             a2nm1 = a2nm1/b2n
     570           0 :             b2nm1 = b2nm1/b2n
     571           0 :             a2n = a2n/b2n
     572           0 :             b2n = one
     573           0 :             IF (ABS(a2n - a2nm1/b2nm1) < tol*a2n) EXIT
     574             :          END DO
     575             : 
     576           0 :          qq = r*a2n
     577           0 :          pp = half + (half - qq)
     578             :       END IF
     579             : 
     580           0 :       IF (PRESENT(p)) p = pp
     581           0 :       IF (PRESENT(q)) q = qq
     582             : 
     583             :    END SUBROUTINE grat1
     584             : 
     585             : ! **************************************************************************************************
     586             : !> \brief ...
     587             : !> \param mu ...
     588             : !> \param x ...
     589             : !> \return ...
     590             : ! **************************************************************************************************
     591           0 :    FUNCTION esum(mu, x) RESULT(fn_val)
     592             : !-----------------------------------------------------------------------
     593             : !                    EVALUATION OF EXP(MU + X)
     594             : !-----------------------------------------------------------------------
     595             :       INTEGER, INTENT(IN)                                :: mu
     596             :       REAL(dp), INTENT(IN)                               :: x
     597             :       REAL(dp)                                           :: fn_val
     598             : 
     599             :       REAL(dp)                                           :: w
     600             : 
     601           0 :       IF (x > 0.0e0_dp) THEN
     602           0 :          IF (mu > 0 .OR. mu + x < 0.0_dp) THEN
     603           0 :             w = mu
     604           0 :             fn_val = EXP(w)*EXP(x)
     605             :          ELSE
     606           0 :             w = mu + x
     607           0 :             fn_val = EXP(w)
     608             :          END IF
     609             :       ELSE
     610           0 :          IF (mu < 0 .OR. mu + x < 0.0_dp) THEN
     611           0 :             w = mu
     612           0 :             fn_val = EXP(w)*EXP(x)
     613             :          ELSE
     614           0 :             w = mu + x
     615           0 :             fn_val = EXP(w)
     616             :          END IF
     617             :       END IF
     618             : 
     619           0 :    END FUNCTION esum
     620             : 
     621             : ! **************************************************************************************************
     622             : !> \brief ...
     623             : !> \param x ...
     624             : !> \return ...
     625             : ! **************************************************************************************************
     626           0 :    FUNCTION rlog1(x) RESULT(fn_val)
     627             : !-----------------------------------------------------------------------
     628             : !             EVALUATION OF THE FUNCTION X - LN(1 + X)
     629             : !-----------------------------------------------------------------------
     630             : !     A = RLOG (0.7)
     631             : !     B = RLOG (4/3)
     632             : !------------------------
     633             :       REAL(dp), INTENT(IN)                               :: x
     634             :       REAL(dp)                                           :: fn_val
     635             : 
     636             :       REAL(dp), PARAMETER :: a = .566749439387324e-01_dp, b = .456512608815524e-01_dp, &
     637             :          p0 = .333333333333333e+00_dp, p1 = -.224696413112536e+00_dp, &
     638             :          p2 = .620886815375787e-02_dp, q1 = -.127408923933623e+01_dp, q2 = .354508718369557e+00_dp
     639             : 
     640             :       REAL(dp)                                           :: r, t, u, up2, w, w1
     641             : 
     642           0 :       IF (x < -0.39e0_dp .OR. x > 0.57e0_dp) THEN
     643           0 :          w = (x + 0.5e0_dp) + 0.5e0_dp
     644           0 :          fn_val = x - LOG(w)
     645           0 :          RETURN
     646             :       END IF
     647             : 
     648             : !                 ARGUMENT REDUCTION
     649             : 
     650           0 :       IF (x < -0.18e0_dp) THEN
     651           0 :          u = (x + 0.3e0_dp)/0.7e0_dp
     652           0 :          up2 = u + 2.0e0_dp
     653           0 :          w1 = a - u*0.3e0_dp
     654           0 :       ELSEIF (x > 0.18e0_dp) THEN
     655           0 :          t = 0.75e0_dp*x
     656           0 :          u = t - 0.25e0_dp
     657           0 :          up2 = t + 1.75e0_dp
     658           0 :          w1 = b + u/3.0e0_dp
     659             :       ELSE
     660           0 :          u = x
     661           0 :          up2 = u + 2.0e0_dp
     662           0 :          w1 = 0.0e0_dp
     663             :       END IF
     664             : 
     665             : !                  SERIES EXPANSION
     666             : 
     667           0 :       r = u/up2
     668           0 :       t = r*r
     669           0 :       w = ((p2*t + p1)*t + p0)/((q2*t + q1)*t + 1.0e0_dp)
     670           0 :       fn_val = r*(u - 2.0e0_dp*t*w) + w1
     671             : 
     672           0 :    END FUNCTION rlog1
     673             : 
     674             : ! **************************************************************************************************
     675             : !> \brief ...
     676             : !> \param a ...
     677             : !> \return ...
     678             : ! **************************************************************************************************
     679           0 :    FUNCTION gamln1(a) RESULT(fn_val)
     680             : !-----------------------------------------------------------------------
     681             : !     EVALUATION OF LN(GAMMA(1 + A)) FOR -0.2 .LE. A .LE. 1.25
     682             : !-----------------------------------------------------------------------
     683             :       REAL(dp), INTENT(IN)                               :: a
     684             :       REAL(dp)                                           :: fn_val
     685             : 
     686             :       REAL(dp), PARAMETER :: p0 = .577215664901533e+00_dp, p1 = .844203922187225e+00_dp, &
     687             :          p2 = -.168860593646662e+00_dp, p3 = -.780427615533591e+00_dp, &
     688             :          p4 = -.402055799310489e+00_dp, p5 = -.673562214325671e-01_dp, &
     689             :          p6 = -.271935708322958e-02_dp, q1 = .288743195473681e+01_dp, &
     690             :          q2 = .312755088914843e+01_dp, q3 = .156875193295039e+01_dp, q4 = .361951990101499e+00_dp, &
     691             :          q5 = .325038868253937e-01_dp, q6 = .667465618796164e-03_dp, r0 = .422784335098467e+00_dp, &
     692             :          r1 = .848044614534529e+00_dp, r2 = .565221050691933e+00_dp, r3 = .156513060486551e+00_dp, &
     693             :          r4 = .170502484022650e-01_dp, r5 = .497958207639485e-03_dp
     694             :       REAL(dp), PARAMETER :: s1 = .124313399877507e+01_dp, s2 = .548042109832463e+00_dp, &
     695             :          s3 = .101552187439830e+00_dp, s4 = .713309612391000e-02_dp, s5 = .116165475989616e-03_dp
     696             : 
     697             :       REAL(dp)                                           :: w, x
     698             : 
     699           0 :       IF (a < 0.6e0_dp) THEN
     700             :          w = ((((((p6*a + p5)*a + p4)*a + p3)*a + p2)*a + p1)*a + p0)/ &
     701           0 :              ((((((q6*a + q5)*a + q4)*a + q3)*a + q2)*a + q1)*a + 1.0e0_dp)
     702           0 :          fn_val = -a*w
     703             :       ELSE
     704           0 :          x = (a - 0.5e0_dp) - 0.5e0_dp
     705             :          w = (((((r5*x + r4)*x + r3)*x + r2)*x + r1)*x + r0)/ &
     706           0 :              (((((s5*x + s4)*x + s3)*x + s2)*x + s1)*x + 1.0e0_dp)
     707           0 :          fn_val = x*w
     708             :       END IF
     709             : 
     710           0 :    END FUNCTION gamln1
     711             : 
     712             : ! **************************************************************************************************
     713             : !> \brief ...
     714             : !> \param xx ...
     715             : !> \return ...
     716             : ! **************************************************************************************************
     717        7564 :    FUNCTION psi(xx) RESULT(fn_val)
     718             : !---------------------------------------------------------------------
     719             : 
     720             : !                 EVALUATION OF THE DIGAMMA FUNCTION
     721             : 
     722             : !                           -----------
     723             : 
     724             : !     PSI(XX) IS ASSIGNED THE VALUE 0 WHEN THE DIGAMMA FUNCTION CANNOT
     725             : !     BE COMPUTED.
     726             : 
     727             : !     THE MAIN COMPUTATION INVOLVES EVALUATION OF RATIONAL CHEBYSHEV
     728             : !     APPROXIMATIONS PUBLISHED IN MATH. COMP. 27, 123-127(1973) BY
     729             : !     CODY, STRECOK AND THACHER.
     730             : 
     731             : !---------------------------------------------------------------------
     732             : !     PSI WAS WRITTEN AT ARGONNE NATIONAL LABORATORY FOR THE FUNPACK
     733             : !     PACKAGE OF SPECIAL FUNCTION SUBROUTINES. PSI WAS MODIFIED BY
     734             : !     A.H. MORRIS (NSWC).
     735             : !---------------------------------------------------------------------
     736             :       REAL(dp), INTENT(IN)                               :: xx
     737             :       REAL(dp)                                           :: fn_val
     738             : 
     739             :       REAL(dp), PARAMETER :: dx0 = 1.461632144968362341262659542325721325e0_dp, p1(7) = (/ &
     740             :          .895385022981970e-02_dp, .477762828042627e+01_dp, .142441585084029e+03_dp, &
     741             :          .118645200713425e+04_dp, .363351846806499e+04_dp, .413810161269013e+04_dp, &
     742             :          .130560269827897e+04_dp/), p2(4) = (/-.212940445131011e+01_dp, -.701677227766759e+01_dp, &
     743             :          -.448616543918019e+01_dp, -.648157123766197e+00_dp/), piov4 = .785398163397448e0_dp, q1(6)&
     744             :          = (/.448452573429826e+02_dp, .520752771467162e+03_dp, .221000799247830e+04_dp, &
     745             :          .364127349079381e+04_dp, .190831076596300e+04_dp, .691091682714533e-05_dp/)
     746             :       REAL(dp), PARAMETER :: q2(4) = (/.322703493791143e+02_dp, .892920700481861e+02_dp, &
     747             :          .546117738103215e+02_dp, .777788548522962e+01_dp/)
     748             : 
     749             :       INTEGER                                            :: i, m, n, nq
     750             :       REAL(dp)                                           :: aug, den, sgn, upper, w, x, xmax1, xmx0, &
     751             :                                                             xsmall, z
     752             : 
     753             : !---------------------------------------------------------------------
     754             : !     PIOV4 = PI/4
     755             : !     DX0 = ZERO OF PSI TO EXTENDED PRECISION
     756             : !---------------------------------------------------------------------
     757             : !---------------------------------------------------------------------
     758             : !     COEFFICIENTS FOR RATIONAL APPROXIMATION OF
     759             : !     PSI(X) / (X - X0),  0.5 <= X <= 3.0
     760             : !---------------------------------------------------------------------
     761             : !---------------------------------------------------------------------
     762             : !     COEFFICIENTS FOR RATIONAL APPROXIMATION OF
     763             : !     PSI(X) - LN(X) + 1 / (2*X),  X > 3.0
     764             : !---------------------------------------------------------------------
     765             : !---------------------------------------------------------------------
     766             : !     MACHINE DEPENDENT CONSTANTS ...
     767             : !        XMAX1  = THE SMALLEST POSITIVE FLOATING POINT CONSTANT
     768             : !                 WITH ENTIRELY INTEGER REPRESENTATION.  ALSO USED
     769             : !                 AS NEGATIVE OF LOWER BOUND ON ACCEPTABLE NEGATIVE
     770             : !                 ARGUMENTS AND AS THE POSITIVE ARGUMENT BEYOND WHICH
     771             : !                 PSI MAY BE REPRESENTED AS ALOG(X).
     772             : !        XSMALL = ABSOLUTE ARGUMENT BELOW WHICH PI*COTAN(PI*X)
     773             : !                 MAY BE REPRESENTED BY 1/X.
     774             : !---------------------------------------------------------------------
     775             : 
     776        7564 :       xmax1 = ipmpar(3)
     777        7564 :       xmax1 = MIN(xmax1, 1.0e0_dp/dpmpar(1))
     778        7564 :       xsmall = 1.e-9_dp
     779             : !---------------------------------------------------------------------
     780        7564 :       x = xx
     781        7564 :       aug = 0.0e0_dp
     782        7564 :       IF (x < 0.5e0_dp) THEN
     783             : !---------------------------------------------------------------------
     784             : !     X .LT. 0.5,  USE REFLECTION FORMULA
     785             : !     PSI(1-X) = PSI(X) + PI * COTAN(PI*X)
     786             : !---------------------------------------------------------------------
     787           0 :          IF (ABS(x) <= xsmall) THEN
     788           0 :             IF (x == 0.0e0_dp) THEN
     789             :                !     ERROR RETURN
     790        7564 :                fn_val = 0.0e0_dp
     791             :                RETURN
     792             :             END IF
     793             : !---------------------------------------------------------------------
     794             : !     0 .LT. ABS(X) .LE. XSMALL.  USE 1/X AS A SUBSTITUTE
     795             : !     FOR  PI*COTAN(PI*X)
     796             : !---------------------------------------------------------------------
     797           0 :             aug = -1.0e0_dp/x
     798           0 :             x = 1.0e0_dp - x
     799             :          ELSE
     800             : !---------------------------------------------------------------------
     801             : !     REDUCTION OF ARGUMENT FOR COTAN
     802             : !---------------------------------------------------------------------
     803           0 :             w = -x
     804           0 :             sgn = piov4
     805           0 :             IF (w <= 0.0e0_dp) THEN
     806           0 :                w = -w
     807           0 :                sgn = -sgn
     808             :             END IF
     809             : !---------------------------------------------------------------------
     810             : !     MAKE AN ERROR EXIT IF X .LE. -XMAX1
     811             : !---------------------------------------------------------------------
     812           0 :             IF (w >= xmax1) THEN
     813             :                !     ERROR RETURN
     814        7564 :                fn_val = 0.0e0_dp
     815             :                RETURN
     816             :             END IF
     817           0 :             nq = INT(w)
     818           0 :             w = w - nq
     819           0 :             nq = INT(w*4.0e0_dp)
     820           0 :             w = 4.0e0_dp*(w - nq*.25e0_dp)
     821             : !---------------------------------------------------------------------
     822             : !     W IS NOW RELATED TO THE FRACTIONAL PART OF  4.0 * X.
     823             : !     ADJUST ARGUMENT TO CORRESPOND TO VALUES IN FIRST
     824             : !     QUADRANT AND DETERMINE SIGN
     825             : !---------------------------------------------------------------------
     826           0 :             n = nq/2
     827           0 :             IF ((n + n) /= nq) w = 1.0e0_dp - w
     828           0 :             z = piov4*w
     829           0 :             m = n/2
     830           0 :             IF ((m + m) /= n) sgn = -sgn
     831             : !---------------------------------------------------------------------
     832             : !     DETERMINE FINAL VALUE FOR  -PI*COTAN(PI*X)
     833             : !---------------------------------------------------------------------
     834           0 :             n = (nq + 1)/2
     835           0 :             m = n/2
     836           0 :             m = m + m
     837           0 :             IF (m /= n) THEN
     838           0 :                aug = sgn*((SIN(z)/COS(z))*4.0e0_dp)
     839             :             ELSE
     840             :                !---------------------------------------------------------------------
     841             :                !     CHECK FOR SINGULARITY
     842             :                !---------------------------------------------------------------------
     843           0 :                IF (z == 0.0e0_dp) THEN
     844             :                   !     ERROR RETURN
     845        7564 :                   fn_val = 0.0e0_dp
     846             :                   RETURN
     847             :                END IF
     848             : !---------------------------------------------------------------------
     849             : !     USE COS/SIN AS A SUBSTITUTE FOR COTAN, AND
     850             : !     SIN/COS AS A SUBSTITUTE FOR TAN
     851             : !---------------------------------------------------------------------
     852           0 :                aug = sgn*((COS(z)/SIN(z))*4.0e0_dp)
     853             :             END IF
     854           0 :             x = 1.0e0_dp - x
     855             :          END IF
     856             :       END IF
     857        7564 :       IF (x <= 3.0e0_dp) THEN
     858             : !---------------------------------------------------------------------
     859             : !     0.5 .LE. X .LE. 3.0
     860             : !---------------------------------------------------------------------
     861           0 :          den = x
     862           0 :          upper = p1(1)*x
     863             : 
     864           0 :          DO i = 1, 5
     865           0 :             den = (den + q1(i))*x
     866           0 :             upper = (upper + p1(i + 1))*x
     867             :          END DO
     868             : 
     869           0 :          den = (upper + p1(7))/(den + q1(6))
     870           0 :          xmx0 = x - dx0
     871           0 :          fn_val = den*xmx0 + aug
     872           0 :          RETURN
     873             :       END IF
     874             : !---------------------------------------------------------------------
     875             : !     IF X .GE. XMAX1, PSI = LN(X)
     876             : !---------------------------------------------------------------------
     877        7564 :       IF (x < xmax1) THEN
     878             : !---------------------------------------------------------------------
     879             : !     3.0 .LT. X .LT. XMAX1
     880             : !---------------------------------------------------------------------
     881        7564 :          w = 1.0e0_dp/(x*x)
     882        7564 :          den = w
     883        7564 :          upper = p2(1)*w
     884             : 
     885       30256 :          DO i = 1, 3
     886       22692 :             den = (den + q2(i))*w
     887       30256 :             upper = (upper + p2(i + 1))*w
     888             :          END DO
     889             : 
     890        7564 :          aug = upper/(den + q2(4)) - 0.5e0_dp/x + aug
     891             :       END IF
     892        7564 :       fn_val = aug + LOG(x)
     893             : 
     894        7564 :    END FUNCTION psi
     895             : 
     896             : ! **************************************************************************************************
     897             : !> \brief ...
     898             : !> \param a0 ...
     899             : !> \param b0 ...
     900             : !> \return ...
     901             : ! **************************************************************************************************
     902           0 :    FUNCTION betaln(a0, b0) RESULT(fn_val)
     903             : !-----------------------------------------------------------------------
     904             : !     EVALUATION OF THE LOGARITHM OF THE BETA FUNCTION
     905             : !-----------------------------------------------------------------------
     906             : !     E = 0.5*LN(2*PI)
     907             : !--------------------------
     908             :       REAL(dp), INTENT(IN)                               :: a0, b0
     909             :       REAL(dp)                                           :: fn_val
     910             : 
     911             :       REAL(dp), PARAMETER                                :: e = .918938533204673e0_dp
     912             : 
     913             :       INTEGER                                            :: i, n
     914             :       REAL(dp)                                           :: a, b, c, h, u, v, w, z
     915             : 
     916             : !--------------------------
     917             : 
     918           0 :       a = MIN(a0, b0)
     919           0 :       b = MAX(a0, b0)
     920             : !-----------------------------------------------------------------------
     921             : !                   PROCEDURE WHEN A .GE. 8
     922             : !-----------------------------------------------------------------------
     923           0 :       IF (a >= 8.0e0_dp) THEN
     924           0 :          w = bcorr(a, b)
     925           0 :          h = a/b
     926           0 :          c = h/(1.0e0_dp + h)
     927           0 :          u = -(a - 0.5e0_dp)*LOG(c)
     928           0 :          v = b*alnrel(h)
     929           0 :          IF (u > v) THEN
     930           0 :             fn_val = (((-0.5e0_dp*LOG(b) + e) + w) - v) - u
     931             :          ELSE
     932           0 :             fn_val = (((-0.5e0_dp*LOG(b) + e) + w) - u) - v
     933             :          END IF
     934             : !-----------------------------------------------------------------------
     935             : !                   PROCEDURE WHEN A .LT. 1
     936             : !-----------------------------------------------------------------------
     937           0 :       ELSEIF (a < 1.0e0_dp) THEN
     938           0 :          IF (b < 8.0e0_dp) THEN
     939           0 :             fn_val = LOG_GAMMA(a) + (LOG_GAMMA(b) - LOG_GAMMA(a + b))
     940             :          ELSE
     941           0 :             fn_val = LOG_GAMMA(a) + algdiv(a, b)
     942             :          END IF
     943             : !-----------------------------------------------------------------------
     944             : !                PROCEDURE WHEN 1 .LE. A .LT. 8
     945             : !-----------------------------------------------------------------------
     946           0 :       ELSEIF (a <= 2.0e0_dp) THEN
     947           0 :          IF (b <= 2.0e0_dp) THEN
     948           0 :             fn_val = LOG_GAMMA(a) + LOG_GAMMA(b) - gsumln(a, b)
     949           0 :             RETURN
     950             :          END IF
     951           0 :          w = 0.0e0_dp
     952           0 :          IF (b < 8.0e0_dp) THEN
     953             :             !                 REDUCTION OF B WHEN B .LT. 8
     954             : 
     955           0 :             n = INT(b - 1.0e0_dp)
     956           0 :             z = 1.0e0_dp
     957           0 :             DO i = 1, n
     958           0 :                b = b - 1.0e0_dp
     959           0 :                z = z*(b/(a + b))
     960             :             END DO
     961           0 :             fn_val = w + LOG(z) + (LOG_GAMMA(a) + (LOG_GAMMA(b) - gsumln(a, b)))
     962           0 :             RETURN
     963             :          END IF
     964           0 :          fn_val = LOG_GAMMA(a) + algdiv(a, b)
     965             : !                REDUCTION OF A WHEN B .LE. 1000
     966           0 :       ELSEIF (b <= 1000.0e0_dp) THEN
     967           0 :          n = INT(a - 1.0e0_dp)
     968           0 :          w = 1.0e0_dp
     969           0 :          DO i = 1, n
     970           0 :             a = a - 1.0e0_dp
     971           0 :             h = a/b
     972           0 :             w = w*(h/(1.0e0_dp + h))
     973             :          END DO
     974           0 :          w = LOG(w)
     975           0 :          IF (b >= 8.0e0_dp) THEN
     976           0 :             fn_val = w + LOG_GAMMA(a) + algdiv(a, b)
     977           0 :             RETURN
     978             :          END IF
     979             : 
     980             :          !                 REDUCTION OF B WHEN B .LT. 8
     981             : 
     982           0 :          n = INT(b - 1.0e0_dp)
     983           0 :          z = 1.0e0_dp
     984           0 :          DO i = 1, n
     985           0 :             b = b - 1.0e0_dp
     986           0 :             z = z*(b/(a + b))
     987             :          END DO
     988           0 :          fn_val = w + LOG(z) + (LOG_GAMMA(a) + (LOG_GAMMA(b) - gsumln(a, b)))
     989             :       ELSE
     990             : !                REDUCTION OF A WHEN B .GT. 1000
     991             : 
     992           0 :          n = INT(a - 1.0e0_dp)
     993           0 :          w = 1.0e0_dp
     994           0 :          DO i = 1, n
     995           0 :             a = a - 1.0e0_dp
     996           0 :             w = w*(a/(1.0e0_dp + a/b))
     997             :          END DO
     998           0 :          fn_val = (LOG(w) - n*LOG(b)) + (LOG_GAMMA(a) + algdiv(a, b))
     999             :       END IF
    1000             : 
    1001             :    END FUNCTION betaln
    1002             : 
    1003             : ! **************************************************************************************************
    1004             : !> \brief ...
    1005             : !> \param a ...
    1006             : !> \param b ...
    1007             : !> \return ...
    1008             : ! **************************************************************************************************
    1009           0 :    FUNCTION gsumln(a, b) RESULT(fn_val)
    1010             : !-----------------------------------------------------------------------
    1011             : !          EVALUATION OF THE FUNCTION LN(GAMMA(A + B))
    1012             : !          FOR 1 .LE. A .LE. 2  AND  1 .LE. B .LE. 2
    1013             : !-----------------------------------------------------------------------
    1014             :       REAL(dp), INTENT(IN)                               :: a, b
    1015             :       REAL(dp)                                           :: fn_val
    1016             : 
    1017             :       REAL(dp)                                           :: x
    1018             : 
    1019           0 :       x = a + b - 2.e0_dp
    1020           0 :       IF (x <= 0.25e0_dp) THEN
    1021           0 :          fn_val = gamln1(1.0e0_dp + x)
    1022           0 :       ELSEIF (x <= 1.25e0_dp) THEN
    1023           0 :          fn_val = gamln1(x) + alnrel(x)
    1024             :       ELSE
    1025           0 :          fn_val = gamln1(x - 1.0e0_dp) + LOG(x*(1.0e0_dp + x))
    1026             :       END IF
    1027           0 :    END FUNCTION gsumln
    1028             : 
    1029             : ! **************************************************************************************************
    1030             : !> \brief ...
    1031             : !> \param a0 ...
    1032             : !> \param b0 ...
    1033             : !> \return ...
    1034             : ! **************************************************************************************************
    1035           0 :    FUNCTION bcorr(a0, b0) RESULT(fn_val)
    1036             : !-----------------------------------------------------------------------
    1037             : 
    1038             : !     EVALUATION OF  DEL(A0) + DEL(B0) - DEL(A0 + B0)  WHERE
    1039             : !     LN(GAMMA(A)) = (A - 0.5)*LN(A) - A + 0.5*LN(2*PI) + DEL(A).
    1040             : !     IT IS ASSUMED THAT A0 .GE. 8 AND B0 .GE. 8.
    1041             : 
    1042             : !-----------------------------------------------------------------------
    1043             :       REAL(dp), INTENT(IN)                               :: a0, b0
    1044             :       REAL(dp)                                           :: fn_val
    1045             : 
    1046             :       REAL(dp), PARAMETER :: c0 = .833333333333333e-01_dp, c1 = -.277777777760991e-02_dp, &
    1047             :          c2 = .793650666825390e-03_dp, c3 = -.595202931351870e-03_dp, &
    1048             :          c4 = .837308034031215e-03_dp, c5 = -.165322962780713e-02_dp
    1049             : 
    1050             :       REAL(dp)                                           :: a, b, c, h, s11, s3, s5, s7, s9, t, w, &
    1051             :                                                             x, x2
    1052             : 
    1053           0 :       a = MIN(a0, b0)
    1054           0 :       b = MAX(a0, b0)
    1055             : 
    1056           0 :       h = a/b
    1057           0 :       c = h/(1.0e0_dp + h)
    1058           0 :       x = 1.0e0_dp/(1.0e0_dp + h)
    1059           0 :       x2 = x*x
    1060             : 
    1061             : !                SET SN = (1 - X**N)/(1 - X)
    1062             : 
    1063           0 :       s3 = 1.0e0_dp + (x + x2)
    1064           0 :       s5 = 1.0e0_dp + (x + x2*s3)
    1065           0 :       s7 = 1.0e0_dp + (x + x2*s5)
    1066           0 :       s9 = 1.0e0_dp + (x + x2*s7)
    1067           0 :       s11 = 1.0e0_dp + (x + x2*s9)
    1068             : 
    1069             : !                SET W = DEL(B) - DEL(A + B)
    1070             : 
    1071           0 :       t = (1.0e0_dp/b)**2
    1072           0 :       w = ((((c5*s11*t + c4*s9)*t + c3*s7)*t + c2*s5)*t + c1*s3)*t + c0
    1073           0 :       w = w*(c/b)
    1074             : 
    1075             : !                   COMPUTE  DEL(A) + W
    1076             : 
    1077           0 :       t = (1.0e0_dp/a)**2
    1078           0 :       fn_val = (((((c5*t + c4)*t + c3)*t + c2)*t + c1)*t + c0)/a + w
    1079             :       RETURN
    1080             :    END FUNCTION bcorr
    1081             : 
    1082             : ! **************************************************************************************************
    1083             : !> \brief ...
    1084             : !> \param a ...
    1085             : !> \param b ...
    1086             : !> \param x ...
    1087             : !> \param y ...
    1088             : !> \param w ...
    1089             : !> \param w1 ...
    1090             : !> \param ierr ...
    1091             : ! **************************************************************************************************
    1092           0 :    SUBROUTINE bratio(a, b, x, y, w, w1, ierr)
    1093             : !-----------------------------------------------------------------------
    1094             : 
    1095             : !            EVALUATION OF THE INCOMPLETE BETA FUNCTION IX(A,B)
    1096             : 
    1097             : !                     --------------------
    1098             : 
    1099             : !     IT IS ASSUMED THAT A AND B ARE NONNEGATIVE, AND THAT X <= 1
    1100             : !     AND Y = 1 - X.  BRATIO ASSIGNS W AND W1 THE VALUES
    1101             : 
    1102             : !                      W  = IX(A,B)
    1103             : !                      W1 = 1 - IX(A,B)
    1104             : 
    1105             : !     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
    1106             : !     IF NO INPUT ERRORS ARE DETECTED THEN IERR IS SET TO 0 AND
    1107             : !     W AND W1 ARE COMPUTED. OTHERWISE, IF AN ERROR IS DETECTED,
    1108             : !     THEN W AND W1 ARE ASSIGNED THE VALUE 0 AND IERR IS SET TO
    1109             : !     ONE OF THE FOLLOWING VALUES ...
    1110             : 
    1111             : !        IERR = 1  IF A OR B IS NEGATIVE
    1112             : !        IERR = 2  IF A = B = 0
    1113             : !        IERR = 3  IF X .LT. 0 OR X .GT. 1
    1114             : !        IERR = 4  IF Y .LT. 0 OR Y .GT. 1
    1115             : !        IERR = 5  IF X + Y .NE. 1
    1116             : !        IERR = 6  IF X = A = 0
    1117             : !        IERR = 7  IF Y = B = 0
    1118             : 
    1119             : !--------------------
    1120             : !     WRITTEN BY ALFRED H. MORRIS, JR.
    1121             : !        NAVAL SURFACE WARFARE CENTER
    1122             : !        DAHLGREN, VIRGINIA
    1123             : !     REVISED ... APRIL 1993
    1124             : !-----------------------------------------------------------------------
    1125             :       REAL(dp), INTENT(IN)                               :: a, b, x, y
    1126             :       REAL(dp), INTENT(OUT)                              :: w, w1
    1127             :       INTEGER, INTENT(OUT)                               :: ierr
    1128             : 
    1129             :       INTEGER                                            :: ierr1, ind, n
    1130             :       REAL(dp)                                           :: a0, b0, eps, lambda, t, x0, y0, z
    1131             : 
    1132             : !-----------------------------------------------------------------------
    1133             : !     ****** EPS IS A MACHINE DEPENDENT CONSTANT. EPS IS THE SMALLEST
    1134             : !            FLOATING POINT NUMBER FOR WHICH 1.0 + EPS .GT. 1.0
    1135             : 
    1136           0 :       eps = dpmpar(1)
    1137             : 
    1138           0 :       w = 0.0e0_dp
    1139           0 :       w1 = 0.0e0_dp
    1140           0 :       IF (a < 0.0e0_dp .OR. b < 0.0e0_dp) THEN
    1141           0 :          ierr = 1
    1142           0 :          RETURN
    1143             :       END IF
    1144           0 :       IF (a == 0.0e0_dp .AND. b == 0.0e0_dp) THEN
    1145           0 :          ierr = 2
    1146           0 :          RETURN
    1147             :       END IF
    1148           0 :       IF (x < 0.0e0_dp .OR. x > 1.0e0_dp) THEN
    1149           0 :          ierr = 3
    1150           0 :          RETURN
    1151             :       END IF
    1152           0 :       IF (y < 0.0e0_dp .OR. y > 1.0e0_dp) THEN
    1153           0 :          ierr = 4
    1154           0 :          RETURN
    1155             :       END IF
    1156           0 :       z = ((x + y) - 0.5e0_dp) - 0.5e0_dp
    1157           0 :       IF (ABS(z) > 3.0e0_dp*eps) THEN
    1158           0 :          ierr = 5
    1159           0 :          RETURN
    1160             :       END IF
    1161             : 
    1162           0 :       ierr = 0
    1163             : 
    1164           0 :       IF (x == 0.0e0_dp .OR. a == 0.0e0_dp) THEN
    1165           0 :          IF (x == 0.0e0_dp .AND. a == 0.0e0_dp) THEN
    1166           0 :             ierr = 6
    1167             :          ELSE
    1168             :             w = 0.0e0_dp
    1169           0 :             w1 = 1.0e0_dp
    1170             :          END IF
    1171           0 :          RETURN
    1172             :       END IF
    1173             : 
    1174           0 :       IF (y == 0.0e0_dp .OR. b == 0.0e0_dp) THEN
    1175           0 :          IF (y == 0.0e0_dp .AND. b == 0.0e0_dp) THEN
    1176           0 :             ierr = 7
    1177             :          ELSE
    1178           0 :             w = 1.0e0_dp
    1179             :             w1 = 0.0e0_dp
    1180             :          END IF
    1181           0 :          RETURN
    1182             :       END IF
    1183             : 
    1184           0 :       eps = MAX(eps, 1.e-15_dp)
    1185           0 :       IF (MAX(a, b) < 1.e-3_dp*eps) THEN
    1186             : !           PROCEDURE FOR A AND B .LT. 1.E-3*EPS
    1187           0 :          w = b/(a + b)
    1188           0 :          w1 = a/(a + b)
    1189           0 :          RETURN
    1190             :       END IF
    1191             : 
    1192           0 :       ind = 0
    1193           0 :       a0 = a
    1194           0 :       b0 = b
    1195           0 :       x0 = x
    1196           0 :       y0 = y
    1197           0 :       IF (MIN(a0, b0) > 1.0e0_dp) GO TO 30
    1198             : 
    1199             : !             PROCEDURE FOR A0 .LE. 1 OR B0 .LE. 1
    1200             : 
    1201           0 :       IF (x > 0.5e0_dp) THEN
    1202           0 :          ind = 1
    1203           0 :          a0 = b
    1204           0 :          b0 = a
    1205           0 :          x0 = y
    1206           0 :          y0 = x
    1207             :       END IF
    1208             : 
    1209           0 :       IF (b0 < MIN(eps, eps*a0)) GO TO 80
    1210           0 :       IF (a0 < MIN(eps, eps*b0) .AND. b0*x0 <= 1.0e0_dp) GO TO 90
    1211           0 :       IF (MAX(a0, b0) > 1.0e0_dp) GO TO 20
    1212           0 :       IF (a0 >= MIN(0.2e0_dp, b0)) GO TO 100
    1213           0 :       IF (x0**a0 <= 0.9e0_dp) GO TO 100
    1214           0 :       IF (x0 >= 0.3e0_dp) GO TO 110
    1215           0 :       n = 20
    1216           0 :       GO TO 130
    1217             : 
    1218           0 : 20    IF (b0 <= 1.0e0_dp) GO TO 100
    1219           0 :       IF (x0 >= 0.3e0_dp) GO TO 110
    1220           0 :       IF (x0 < 0.1e0_dp .AND. (x0*b0)**a0 <= 0.7e0_dp) GO TO 100
    1221           0 :       IF (b0 > 15.0e0_dp) GO TO 131
    1222           0 :       n = 20
    1223           0 :       GO TO 130
    1224             : 
    1225             : !             PROCEDURE FOR A0 .GT. 1 AND B0 .GT. 1
    1226             : 
    1227           0 : 30    IF (a > b) THEN
    1228           0 :          lambda = (a + b)*y - b
    1229             :       ELSE
    1230           0 :          lambda = a - (a + b)*x
    1231             :       END IF
    1232             : 
    1233           0 :       IF (lambda < 0.0e0_dp) THEN
    1234           0 :          ind = 1
    1235           0 :          a0 = b
    1236           0 :          b0 = a
    1237           0 :          x0 = y
    1238           0 :          y0 = x
    1239           0 :          lambda = ABS(lambda)
    1240             :       END IF
    1241             : 
    1242           0 :       IF (b0 < 40.0e0_dp .AND. b0*x0 <= 0.7e0_dp) GO TO 100
    1243           0 :       IF (b0 < 40.0e0_dp) GO TO 140
    1244           0 :       IF (a0 > b0) GO TO 50
    1245           0 :       IF (a0 <= 100.0e0_dp) GO TO 120
    1246           0 :       IF (lambda > 0.03e0_dp*a0) GO TO 120
    1247           0 :       GO TO 180
    1248           0 : 50    IF (b0 <= 100.0e0_dp) GO TO 120
    1249           0 :       IF (lambda > 0.03e0_dp*b0) GO TO 120
    1250           0 :       GO TO 180
    1251             : 
    1252             : !            EVALUATION OF THE APPROPRIATE ALGORITHM
    1253             : 
    1254           0 : 80    w = fpser(a0, b0, x0, eps)
    1255           0 :       w1 = 0.5e0_dp + (0.5e0_dp - w)
    1256           0 :       GO TO 220
    1257             : 
    1258           0 : 90    w1 = apser(a0, b0, x0, eps)
    1259           0 :       w = 0.5e0_dp + (0.5e0_dp - w1)
    1260           0 :       GO TO 220
    1261             : 
    1262           0 : 100   w = bpser(a0, b0, x0, eps)
    1263           0 :       w1 = 0.5e0_dp + (0.5e0_dp - w)
    1264           0 :       GO TO 220
    1265             : 
    1266           0 : 110   w1 = bpser(b0, a0, y0, eps)
    1267           0 :       w = 0.5e0_dp + (0.5e0_dp - w1)
    1268           0 :       GO TO 220
    1269             : 
    1270           0 : 120   w = bfrac(a0, b0, x0, y0, lambda, 15.0e0_dp*eps)
    1271           0 :       w1 = 0.5e0_dp + (0.5e0_dp - w)
    1272           0 :       GO TO 220
    1273             : 
    1274           0 : 130   w1 = bup(b0, a0, y0, x0, n, eps)
    1275           0 :       b0 = b0 + n
    1276           0 : 131   CALL bgrat(b0, a0, y0, x0, w1, eps, ierr1)
    1277           0 :       IF (ierr1 > 0) CPABORT("Error in BGRAT")
    1278           0 :       w = 0.5e0_dp + (0.5e0_dp - w1)
    1279           0 :       GO TO 220
    1280             : 
    1281           0 : 140   n = INT(b0)
    1282           0 :       b0 = b0 - n
    1283           0 :       IF (b0 /= 0.0e0_dp) GO TO 141
    1284           0 :       n = n - 1
    1285           0 :       b0 = 1.0e0_dp
    1286           0 : 141   w = bup(b0, a0, y0, x0, n, eps)
    1287           0 :       IF (x0 > 0.7e0_dp) GO TO 150
    1288           0 :       w = w + bpser(a0, b0, x0, eps)
    1289           0 :       w1 = 0.5e0_dp + (0.5e0_dp - w)
    1290           0 :       GO TO 220
    1291             : 
    1292           0 : 150   IF (a0 > 15.0e0_dp) GO TO 151
    1293           0 :       n = 20
    1294           0 :       w = w + bup(a0, b0, x0, y0, n, eps)
    1295           0 :       a0 = a0 + n
    1296           0 : 151   CALL bgrat(a0, b0, x0, y0, w, eps, ierr1)
    1297           0 :       w1 = 0.5e0_dp + (0.5e0_dp - w)
    1298           0 :       GO TO 220
    1299             : 
    1300           0 : 180   w = basym(a0, b0, lambda, 100.0e0_dp*eps)
    1301           0 :       w1 = 0.5e0_dp + (0.5e0_dp - w)
    1302           0 :       GO TO 220
    1303             : 
    1304             : !               TERMINATION OF THE PROCEDURE
    1305             : 
    1306           0 : 220   IF (ind == 0) RETURN
    1307           0 :       t = w
    1308           0 :       w = w1
    1309           0 :       w1 = t
    1310             : 
    1311             :    END SUBROUTINE bratio
    1312             : 
    1313             : ! **************************************************************************************************
    1314             : !> \brief ...
    1315             : !> \param a ...
    1316             : !> \param b ...
    1317             : !> \param x ...
    1318             : !> \param eps ...
    1319             : !> \return ...
    1320             : ! **************************************************************************************************
    1321           0 :    FUNCTION fpser(a, b, x, eps) RESULT(fn_val)
    1322             : !-----------------------------------------------------------------------
    1323             : 
    1324             : !                 EVALUATION OF I (A,B)
    1325             : !                                X
    1326             : 
    1327             : !          FOR B .LT. MIN(EPS,EPS*A) AND X .LE. 0.5.
    1328             : 
    1329             : !-----------------------------------------------------------------------
    1330             :       REAL(dp), INTENT(IN)                               :: a, b, x, eps
    1331             :       REAL(dp)                                           :: fn_val
    1332             : 
    1333             :       REAL(dp)                                           :: an, c, s, t, tol
    1334             : 
    1335             : !                  SET  FPSER = X**A
    1336             : 
    1337           0 :       fn_val = 1.0e0_dp
    1338           0 :       IF (a > 1.e-3_dp*eps) THEN
    1339           0 :          fn_val = 0.0e0_dp
    1340           0 :          t = a*LOG(x)
    1341           0 :          IF (t < dxparg(1)) RETURN
    1342           0 :          fn_val = EXP(t)
    1343             :       END IF
    1344             : 
    1345             : !                NOTE THAT 1/B(A,B) = B
    1346             : 
    1347           0 :       fn_val = (b/a)*fn_val
    1348           0 :       tol = eps/a
    1349           0 :       an = a + 1.0e0_dp
    1350           0 :       t = x
    1351           0 :       s = t/an
    1352           0 :       an = an + 1.0e0_dp
    1353           0 :       t = x*t
    1354           0 :       c = t/an
    1355           0 :       s = s + c
    1356           0 :       DO WHILE (ABS(c) > tol)
    1357           0 :          an = an + 1.0e0_dp
    1358           0 :          t = x*t
    1359           0 :          c = t/an
    1360           0 :          s = s + c
    1361             :       END DO
    1362             : 
    1363           0 :       fn_val = fn_val*(1.0e0_dp + a*s)
    1364             : 
    1365           0 :    END FUNCTION fpser
    1366             : 
    1367             : ! **************************************************************************************************
    1368             : !> \brief ...
    1369             : !> \param a ...
    1370             : !> \param b ...
    1371             : !> \param x ...
    1372             : !> \param eps ...
    1373             : !> \return ...
    1374             : ! **************************************************************************************************
    1375           0 :    FUNCTION apser(a, b, x, eps) RESULT(fn_val)
    1376             : !-----------------------------------------------------------------------
    1377             : !     APSER YIELDS THE INCOMPLETE BETA RATIO I(SUB(1-X))(B,A) FOR
    1378             : !     A .LE. MIN(EPS,EPS*B), B*X .LE. 1, AND X .LE. 0.5. USED WHEN
    1379             : !     A IS VERY SMALL. USE ONLY IF ABOVE INEQUALITIES ARE SATISFIED.
    1380             : !-----------------------------------------------------------------------
    1381             :       REAL(dp), INTENT(IN)                               :: a, b, x, eps
    1382             :       REAL(dp)                                           :: fn_val
    1383             : 
    1384             :       REAL(dp), PARAMETER                                :: g = .577215664901533e0_dp
    1385             : 
    1386             :       REAL(dp)                                           :: aj, bx, c, j, s, t, tol
    1387             : 
    1388           0 :       bx = b*x
    1389           0 :       t = x - bx
    1390           0 :       IF (b*eps > 2.e-2_dp) THEN
    1391           0 :          c = LOG(bx) + g + t
    1392             :       ELSE
    1393           0 :          c = LOG(x) + psi(b) + g + t
    1394             :       END IF
    1395             : 
    1396           0 :       tol = 5.0e0_dp*eps*ABS(c)
    1397             :       j = 1.0e0_dp
    1398           0 :       s = 0.0e0_dp
    1399           0 :       j = j + 1.0e0_dp
    1400           0 :       t = t*(x - bx/j)
    1401           0 :       aj = t/j
    1402           0 :       s = s + aj
    1403           0 :       DO WHILE (ABS(aj) > tol)
    1404           0 :          t = t*(x - bx/j)
    1405           0 :          aj = t/j
    1406           0 :          s = s + aj
    1407             :       END DO
    1408             : 
    1409           0 :       fn_val = -a*(c + s)
    1410             : 
    1411           0 :    END FUNCTION apser
    1412             : 
    1413             : ! **************************************************************************************************
    1414             : !> \brief ...
    1415             : !> \param a ...
    1416             : !> \param b ...
    1417             : !> \param x ...
    1418             : !> \param eps ...
    1419             : !> \return ...
    1420             : ! **************************************************************************************************
    1421           0 :    FUNCTION bpser(a, b, x, eps) RESULT(fn_val)
    1422             : !-----------------------------------------------------------------------
    1423             : !     POWER SERIES EXPANSION FOR EVALUATING IX(A,B) WHEN B .LE. 1
    1424             : !     OR B*X .LE. 0.7.  EPS IS THE TOLERANCE USED.
    1425             : !-----------------------------------------------------------------------
    1426             :       REAL(dp), INTENT(IN)                               :: a, b, x, eps
    1427             :       REAL(dp)                                           :: fn_val
    1428             : 
    1429             :       INTEGER                                            :: i, m
    1430             :       REAL(dp)                                           :: a0, apb, b0, c, n, sum, t, tol, u, w, z
    1431             : 
    1432           0 :       fn_val = 0.0e0_dp
    1433           0 :       IF (x == 0.0e0_dp) RETURN
    1434             : !-----------------------------------------------------------------------
    1435             : !            COMPUTE THE FACTOR X**A/(A*BETA(A,B))
    1436             : !-----------------------------------------------------------------------
    1437           0 :       a0 = MIN(a, b)
    1438           0 :       b0 = MAX(a, b)
    1439           0 :       IF (a0 >= 1.0e0_dp) THEN
    1440           0 :          z = a*LOG(x) - betaln(a, b)
    1441           0 :          fn_val = EXP(z)/a
    1442           0 :       ELSEIF (b0 >= 8.0e0_dp) THEN
    1443           0 :          u = gamln1(a0) + algdiv(a0, b0)
    1444           0 :          z = a*LOG(x) - u
    1445           0 :          fn_val = (a0/a)*EXP(z)
    1446           0 :       ELSEIF (b0 > 1.0e0_dp) THEN
    1447             : !         PROCEDURE FOR A0 .LT. 1 AND 1 .LT. B0 .LT. 8
    1448             : 
    1449           0 :          u = gamln1(a0)
    1450           0 :          m = INT(b0 - 1.0e0_dp)
    1451           0 :          IF (m >= 1) THEN
    1452             :             c = 1.0e0_dp
    1453           0 :             DO i = 1, m
    1454           0 :                b0 = b0 - 1.0e0_dp
    1455           0 :                c = c*(b0/(a0 + b0))
    1456             :             END DO
    1457           0 :             u = LOG(c) + u
    1458             :          END IF
    1459             : 
    1460           0 :          z = a*LOG(x) - u
    1461           0 :          b0 = b0 - 1.0e0_dp
    1462           0 :          apb = a0 + b0
    1463           0 :          IF (apb > 1.0e0_dp) THEN
    1464           0 :             u = a0 + b0 - 1.e0_dp
    1465           0 :             t = (1.0e0_dp + gam1(u))/apb
    1466             :          ELSE
    1467           0 :             t = 1.0e0_dp + gam1(apb)
    1468             :          END IF
    1469           0 :          fn_val = EXP(z)*(a0/a)*(1.0e0_dp + gam1(b0))/t
    1470             :       ELSE
    1471             : 
    1472             :          !            PROCEDURE FOR A0 .LT. 1 AND B0 .LE. 1
    1473             : 
    1474           0 :          fn_val = x**a
    1475           0 :          IF (fn_val == 0.0e0_dp) RETURN
    1476             : 
    1477           0 :          apb = a + b
    1478           0 :          IF (apb > 1.0e0_dp) THEN
    1479           0 :             u = a + b - 1.e0_dp
    1480           0 :             z = (1.0e0_dp + gam1(u))/apb
    1481             :          ELSE
    1482           0 :             z = 1.0e0_dp + gam1(apb)
    1483             :          END IF
    1484             : 
    1485           0 :          c = (1.0e0_dp + gam1(a))*(1.0e0_dp + gam1(b))/z
    1486           0 :          fn_val = fn_val*c*(b/apb)
    1487             :       END IF
    1488             : 
    1489             : !            PROCEDURE FOR A0 .LT. 1 AND B0 .GE. 8
    1490             : 
    1491           0 :       IF (fn_val == 0.0e0_dp .OR. a <= 0.1e0_dp*eps) RETURN
    1492             : !-----------------------------------------------------------------------
    1493             : !                     COMPUTE THE SERIES
    1494             : !-----------------------------------------------------------------------
    1495           0 :       sum = 0.0e0_dp
    1496           0 :       n = 0.0e0_dp
    1497           0 :       c = 1.0e0_dp
    1498           0 :       tol = eps/a
    1499           0 :       n = n + 1.0e0_dp
    1500           0 :       c = c*(0.5e0_dp + (0.5e0_dp - b/n))*x
    1501           0 :       w = c/(a + n)
    1502           0 :       sum = sum + w
    1503           0 :       DO WHILE (ABS(w) > tol)
    1504           0 :          n = n + 1.0e0_dp
    1505           0 :          c = c*(0.5e0_dp + (0.5e0_dp - b/n))*x
    1506           0 :          w = c/(a + n)
    1507           0 :          sum = sum + w
    1508             :       END DO
    1509           0 :       fn_val = fn_val*(1.0e0_dp + a*sum)
    1510             : 
    1511           0 :    END FUNCTION bpser
    1512             : 
    1513             : ! **************************************************************************************************
    1514             : !> \brief ...
    1515             : !> \param a ...
    1516             : !> \param b ...
    1517             : !> \param x ...
    1518             : !> \param y ...
    1519             : !> \param n ...
    1520             : !> \param eps ...
    1521             : !> \return ...
    1522             : ! **************************************************************************************************
    1523           0 :    FUNCTION bup(a, b, x, y, n, eps) RESULT(fn_val)
    1524             : !-----------------------------------------------------------------------
    1525             : !     EVALUATION OF IX(A,B) - IX(A+N,B) WHERE N IS A POSITIVE INTEGER.
    1526             : !     EPS IS THE TOLERANCE USED.
    1527             : !-----------------------------------------------------------------------
    1528             :       REAL(dp), INTENT(IN)                               :: a, b, x, y
    1529             :       INTEGER, INTENT(IN)                                :: n
    1530             :       REAL(dp), INTENT(IN)                               :: eps
    1531             :       REAL(dp)                                           :: fn_val
    1532             : 
    1533             :       INTEGER                                            :: i, k, kp1, mu, nm1
    1534             :       REAL(dp)                                           :: ap1, apb, d, l, r, t, w
    1535             : 
    1536             : !          OBTAIN THE SCALING FACTOR EXP(-MU) AND
    1537             : !             EXP(MU)*(X**A*Y**B/BETA(A,B))/A
    1538             : 
    1539           0 :       apb = a + b
    1540           0 :       ap1 = a + 1.0e0_dp
    1541           0 :       mu = 0
    1542           0 :       d = 1.0e0_dp
    1543           0 :       IF (.NOT. (n == 1 .OR. a < 1.0e0_dp .OR. apb < 1.1e0_dp*ap1)) THEN
    1544           0 :          mu = INT(ABS(dxparg(1)))
    1545           0 :          k = INT(dxparg(0))
    1546           0 :          IF (k < mu) mu = k
    1547           0 :          t = mu
    1548           0 :          d = EXP(-t)
    1549             :       END IF
    1550             : 
    1551           0 :       fn_val = brcmp1(mu, a, b, x, y)/a
    1552           0 :       IF (n == 1 .OR. fn_val == 0.0e0_dp) RETURN
    1553           0 :       nm1 = n - 1
    1554           0 :       w = d
    1555             : 
    1556             : !          LET K BE THE INDEX OF THE MAXIMUM TERM
    1557             : 
    1558           0 :       k = 0
    1559           0 :       IF (b > 1.0e0_dp) THEN
    1560           0 :          IF (y <= 1.e-4_dp) THEN
    1561           0 :             k = nm1
    1562           0 :             DO i = 1, k
    1563           0 :                l = i - 1
    1564           0 :                d = ((apb + l)/(ap1 + l))*x*d
    1565           0 :                w = w + d
    1566             :             END DO
    1567             :             IF (k == nm1) THEN
    1568           0 :                fn_val = fn_val*w
    1569           0 :                RETURN
    1570             :             END IF
    1571             :          ELSE
    1572           0 :             r = (b - 1.0e0_dp)*x/y - a
    1573           0 :             IF (r >= 1.0e0_dp) THEN
    1574           0 :                k = nm1
    1575           0 :                t = nm1
    1576           0 :                IF (r < t) k = INT(r)
    1577             : 
    1578             : !          ADD THE INCREASING TERMS OF THE SERIES
    1579             : 
    1580           0 :                DO i = 1, k
    1581           0 :                   l = i - 1
    1582           0 :                   d = ((apb + l)/(ap1 + l))*x*d
    1583           0 :                   w = w + d
    1584             :                END DO
    1585           0 :                IF (k == nm1) THEN
    1586           0 :                   fn_val = fn_val*w
    1587           0 :                   RETURN
    1588             :                END IF
    1589             :             END IF
    1590             :          END IF
    1591             :       END IF
    1592             : 
    1593             : !          ADD THE REMAINING TERMS OF THE SERIES
    1594             : 
    1595           0 :       kp1 = k + 1
    1596           0 :       DO i = kp1, nm1
    1597           0 :          l = i - 1
    1598           0 :          d = ((apb + l)/(ap1 + l))*x*d
    1599           0 :          w = w + d
    1600           0 :          IF (d <= eps*w) EXIT
    1601             :       END DO
    1602             : 
    1603             : !               TERMINATE THE PROCEDURE
    1604             : 
    1605           0 :       fn_val = fn_val*w
    1606             : 
    1607           0 :    END FUNCTION bup
    1608             : 
    1609             : ! **************************************************************************************************
    1610             : !> \brief ...
    1611             : !> \param a ...
    1612             : !> \param b ...
    1613             : !> \param x ...
    1614             : !> \param y ...
    1615             : !> \param lambda ...
    1616             : !> \param eps ...
    1617             : !> \return ...
    1618             : ! **************************************************************************************************
    1619           0 :    FUNCTION bfrac(a, b, x, y, lambda, eps) RESULT(fn_val)
    1620             : !-----------------------------------------------------------------------
    1621             : !     CONTINUED FRACTION EXPANSION FOR IX(A,B) WHEN A,B .GT. 1.
    1622             : !     IT IS ASSUMED THAT  LAMBDA = (A + B)*Y - B.
    1623             : !-----------------------------------------------------------------------
    1624             :       REAL(dp), INTENT(IN)                               :: a, b, x, y, lambda, eps
    1625             :       REAL(dp)                                           :: fn_val
    1626             : 
    1627             :       REAL(dp)                                           :: alpha, an, anp1, beta, bn, bnp1, c, c0, &
    1628             :                                                             c1, e, n, p, r, r0, s, t, w, yp1
    1629             : 
    1630           0 :       fn_val = brcomp(a, b, x, y)
    1631           0 :       IF (fn_val == 0.0e0_dp) RETURN
    1632             : 
    1633           0 :       c = 1.0e0_dp + lambda
    1634           0 :       c0 = b/a
    1635           0 :       c1 = 1.0e0_dp + 1.0e0_dp/a
    1636           0 :       yp1 = y + 1.0e0_dp
    1637             : 
    1638           0 :       n = 0.0e0_dp
    1639           0 :       p = 1.0e0_dp
    1640           0 :       s = a + 1.0e0_dp
    1641           0 :       an = 0.0e0_dp
    1642           0 :       bn = 1.0e0_dp
    1643           0 :       anp1 = 1.0e0_dp
    1644           0 :       bnp1 = c/c1
    1645           0 :       r = c1/c
    1646             : 
    1647             : !        CONTINUED FRACTION CALCULATION
    1648             : 
    1649           0 :       DO WHILE (.TRUE.)
    1650           0 :          n = n + 1.0e0_dp
    1651           0 :          t = n/a
    1652           0 :          w = n*(b - n)*x
    1653           0 :          e = a/s
    1654           0 :          alpha = (p*(p + c0)*e*e)*(w*x)
    1655           0 :          IF (alpha <= 0.0e0_dp) THEN
    1656             : !                 TERMINATION
    1657           0 :             fn_val = fn_val*r
    1658           0 :             RETURN
    1659             :          END IF
    1660           0 :          e = (1.0e0_dp + t)/(c1 + t + t)
    1661           0 :          beta = n + w/s + e*(c + n*yp1)
    1662           0 :          p = 1.0e0_dp + t
    1663           0 :          s = s + 2.0e0_dp
    1664             : 
    1665             : !        UPDATE AN, BN, ANP1, AND BNP1
    1666             : 
    1667           0 :          t = alpha*an + beta*anp1
    1668           0 :          an = anp1
    1669           0 :          anp1 = t
    1670           0 :          t = alpha*bn + beta*bnp1
    1671           0 :          bn = bnp1
    1672           0 :          bnp1 = t
    1673           0 :          r0 = r
    1674           0 :          r = anp1/bnp1
    1675           0 :          IF (ABS(r - r0) <= eps*r) THEN
    1676             : !                 TERMINATION
    1677           0 :             fn_val = fn_val*r
    1678           0 :             RETURN
    1679             :          END IF
    1680             : 
    1681             : !        RESCALE AN, BN, ANP1, AND BNP1
    1682             : 
    1683           0 :          an = an/bnp1
    1684           0 :          bn = bn/bnp1
    1685           0 :          anp1 = r
    1686           0 :          bnp1 = 1.0e0_dp
    1687             :       END DO
    1688             : 
    1689             :    END FUNCTION bfrac
    1690             : 
    1691             : ! **************************************************************************************************
    1692             : !> \brief ...
    1693             : !> \param a ...
    1694             : !> \param b ...
    1695             : !> \param x ...
    1696             : !> \param y ...
    1697             : !> \return ...
    1698             : ! **************************************************************************************************
    1699           0 :    FUNCTION brcomp(a, b, x, y) RESULT(fn_val)
    1700             : !-----------------------------------------------------------------------
    1701             : !               EVALUATION OF X**A*Y**B/BETA(A,B)
    1702             : !-----------------------------------------------------------------------
    1703             :       REAL(dp), INTENT(IN)                               :: a, b, x, y
    1704             :       REAL(dp)                                           :: fn_val
    1705             : 
    1706             :       REAL(dp), PARAMETER                                :: const = 0.398942280401433e0_dp
    1707             : 
    1708             :       INTEGER                                            :: i, n
    1709             :       REAL(dp)                                           :: a0, apb, b0, c, e, h, lambda, lnx, lny, &
    1710             :                                                             t, u, v, x0, y0, z
    1711             : 
    1712             : !-----------------
    1713             : !     CONST = 1/SQRT(2*PI)
    1714             : !-----------------
    1715             : 
    1716           0 :       fn_val = 0.0e0_dp
    1717           0 :       IF (x == 0.0e0_dp .OR. y == 0.0e0_dp) RETURN
    1718           0 :       a0 = MIN(a, b)
    1719           0 :       IF (a0 >= 8.0e0_dp) THEN
    1720             : !-----------------------------------------------------------------------
    1721             : !              PROCEDURE FOR A .GE. 8 AND B .GE. 8
    1722             : !-----------------------------------------------------------------------
    1723           0 :          IF (a > b) THEN
    1724           0 :             h = b/a
    1725           0 :             x0 = 1.0e0_dp/(1.0e0_dp + h)
    1726           0 :             y0 = h/(1.0e0_dp + h)
    1727           0 :             lambda = (a + b)*y - b
    1728             :          ELSE
    1729           0 :             h = a/b
    1730           0 :             x0 = h/(1.0e0_dp + h)
    1731           0 :             y0 = 1.0e0_dp/(1.0e0_dp + h)
    1732           0 :             lambda = a - (a + b)*x
    1733             :          END IF
    1734             : 
    1735           0 :          e = -lambda/a
    1736           0 :          IF (ABS(e) > 0.6e0_dp) THEN
    1737           0 :             u = e - LOG(x/x0)
    1738             :          ELSE
    1739           0 :             u = rlog1(e)
    1740             :          END IF
    1741             : 
    1742           0 :          e = lambda/b
    1743           0 :          IF (ABS(e) > 0.6e0_dp) THEN
    1744           0 :             v = e - LOG(y/y0)
    1745             :          ELSE
    1746           0 :             v = rlog1(e)
    1747             :          END IF
    1748             : 
    1749           0 :          z = EXP(-(a*u + b*v))
    1750           0 :          fn_val = const*SQRT(b*x0)*z*EXP(-bcorr(a, b))
    1751           0 :          RETURN
    1752             :       END IF
    1753             : 
    1754           0 :       IF (x > 0.375e0_dp) THEN
    1755           0 :          IF (y > 0.375e0_dp) THEN
    1756           0 :             lnx = LOG(x)
    1757           0 :             lny = LOG(y)
    1758             :          ELSE
    1759           0 :             lnx = alnrel(-y)
    1760           0 :             lny = LOG(y)
    1761             :          END IF
    1762             :       ELSE
    1763           0 :          lnx = LOG(x)
    1764           0 :          lny = alnrel(-x)
    1765             :       END IF
    1766             : 
    1767           0 :       z = a*lnx + b*lny
    1768           0 :       IF (a0 >= 1.0e0_dp) THEN
    1769           0 :          z = z - betaln(a, b)
    1770           0 :          fn_val = EXP(z)
    1771           0 :          RETURN
    1772             :       END IF
    1773             : !-----------------------------------------------------------------------
    1774             : !              PROCEDURE FOR A .LT. 1 OR B .LT. 1
    1775             : !-----------------------------------------------------------------------
    1776           0 :       b0 = MAX(a, b)
    1777           0 :       IF (b0 >= 8.0e0_dp) THEN
    1778             : !                   ALGORITHM FOR B0 .GE. 8
    1779           0 :          u = gamln1(a0) + algdiv(a0, b0)
    1780           0 :          fn_val = a0*EXP(z - u)
    1781             :       END IF
    1782           0 :       IF (b0 <= 1.0e0_dp) THEN
    1783             : 
    1784             : !                   ALGORITHM FOR B0 .LE. 1
    1785             : 
    1786           0 :          fn_val = EXP(z)
    1787           0 :          IF (fn_val == 0.0e0_dp) RETURN
    1788             : 
    1789           0 :          apb = a + b
    1790           0 :          IF (apb > 1.0e0_dp) THEN
    1791           0 :             u = a + b - 1.e0_dp
    1792           0 :             z = (1.0e0_dp + gam1(u))/apb
    1793             :          ELSE
    1794           0 :             z = 1.0e0_dp + gam1(apb)
    1795             :          END IF
    1796             : 
    1797           0 :          c = (1.0e0_dp + gam1(a))*(1.0e0_dp + gam1(b))/z
    1798           0 :          fn_val = fn_val*(a0*c)/(1.0e0_dp + a0/b0)
    1799           0 :          RETURN
    1800             :       END IF
    1801             : 
    1802             : !                ALGORITHM FOR 1 .LT. B0 .LT. 8
    1803             : 
    1804           0 :       u = gamln1(a0)
    1805           0 :       n = INT(b0 - 1.0e0_dp)
    1806           0 :       IF (n >= 1) THEN
    1807             :          c = 1.0e0_dp
    1808           0 :          DO i = 1, n
    1809           0 :             b0 = b0 - 1.0e0_dp
    1810           0 :             c = c*(b0/(a0 + b0))
    1811             :          END DO
    1812           0 :          u = LOG(c) + u
    1813             :       END IF
    1814             : 
    1815           0 :       z = z - u
    1816           0 :       b0 = b0 - 1.0e0_dp
    1817           0 :       apb = a0 + b0
    1818           0 :       IF (apb > 1.0e0_dp) THEN
    1819           0 :          u = a0 + b0 - 1.e0_dp
    1820           0 :          t = (1.0e0_dp + gam1(u))/apb
    1821             :       ELSE
    1822           0 :          t = 1.0e0_dp + gam1(apb)
    1823             :       END IF
    1824           0 :       fn_val = a0*EXP(z)*(1.0e0_dp + gam1(b0))/t
    1825             : 
    1826           0 :    END FUNCTION brcomp
    1827             : 
    1828             : ! **************************************************************************************************
    1829             : !> \brief ...
    1830             : !> \param mu ...
    1831             : !> \param a ...
    1832             : !> \param b ...
    1833             : !> \param x ...
    1834             : !> \param y ...
    1835             : !> \return ...
    1836             : ! **************************************************************************************************
    1837           0 :    FUNCTION brcmp1(mu, a, b, x, y) RESULT(fn_val)
    1838             : !-----------------------------------------------------------------------
    1839             : !          EVALUATION OF  EXP(MU) * (X**A*Y**B/BETA(A,B))
    1840             : !-----------------------------------------------------------------------
    1841             :       INTEGER, INTENT(IN)                                :: mu
    1842             :       REAL(dp), INTENT(IN)                               :: a, b, x, y
    1843             :       REAL(dp)                                           :: fn_val
    1844             : 
    1845             :       REAL(dp), PARAMETER                                :: const = 0.398942280401433e0_dp
    1846             : 
    1847             :       INTEGER                                            :: i, n
    1848             :       REAL(dp)                                           :: a0, apb, b0, c, e, h, lambda, lnx, lny, &
    1849             :                                                             t, u, v, x0, y0, z
    1850             : 
    1851             : !-----------------
    1852             : !     CONST = 1/SQRT(2*PI)
    1853             : !-----------------
    1854             : 
    1855           0 :       a0 = MIN(a, b)
    1856           0 :       IF (a0 >= 8.0e0_dp) THEN
    1857             : !-----------------------------------------------------------------------
    1858             : !              PROCEDURE FOR A .GE. 8 AND B .GE. 8
    1859             : !-----------------------------------------------------------------------
    1860             :          IF (a > b) THEN
    1861           0 :             h = b/a
    1862           0 :             x0 = 1.0e0_dp/(1.0e0_dp + h)
    1863           0 :             y0 = h/(1.0e0_dp + h)
    1864           0 :             lambda = (a + b)*y - b
    1865             :          END IF
    1866           0 :          h = a/b
    1867           0 :          x0 = h/(1.0e0_dp + h)
    1868           0 :          y0 = 1.0e0_dp/(1.0e0_dp + h)
    1869           0 :          lambda = a - (a + b)*x
    1870             : 
    1871           0 :          e = -lambda/a
    1872           0 :          IF (ABS(e) > 0.6e0_dp) THEN
    1873           0 :             u = e - LOG(x/x0)
    1874             :          ELSE
    1875           0 :             u = rlog1(e)
    1876             :          END IF
    1877             : 
    1878           0 :          e = lambda/b
    1879           0 :          IF (ABS(e) <= 0.6e0_dp) THEN
    1880           0 :             v = rlog1(e)
    1881             :          ELSE
    1882           0 :             v = e - LOG(y/y0)
    1883             :          END IF
    1884             : 
    1885           0 :          z = esum(mu, -(a*u + b*v))
    1886           0 :          fn_val = const*SQRT(b*x0)*z*EXP(-bcorr(a, b))
    1887             :       END IF
    1888             : 
    1889           0 :       IF (x > 0.375e0_dp) THEN
    1890           0 :          IF (y > 0.375e0_dp) THEN
    1891           0 :             lnx = LOG(x)
    1892           0 :             lny = LOG(y)
    1893             :          ELSE
    1894           0 :             lnx = alnrel(-y)
    1895           0 :             lny = LOG(y)
    1896             :          END IF
    1897             :       ELSE
    1898           0 :          lnx = LOG(x)
    1899           0 :          lny = alnrel(-x)
    1900             :       END IF
    1901           0 :       z = a*lnx + b*lny
    1902           0 :       IF (a0 >= 1.0e0_dp) THEN
    1903           0 :          z = z - betaln(a, b)
    1904           0 :          fn_val = esum(mu, z)
    1905           0 :          RETURN
    1906             :       END IF
    1907             : !-----------------------------------------------------------------------
    1908             : !              PROCEDURE FOR A .LT. 1 OR B .LT. 1
    1909             : !-----------------------------------------------------------------------
    1910           0 :       b0 = MAX(a, b)
    1911           0 :       IF (b0 >= 8.0e0_dp) THEN
    1912             : !                   ALGORITHM FOR B0 .GE. 8
    1913             : 
    1914           0 :          u = gamln1(a0) + algdiv(a0, b0)
    1915           0 :          fn_val = a0*esum(mu, z - u)
    1916           0 :          RETURN
    1917             :       END IF
    1918           0 :       IF (b0 <= 1.0e0_dp) THEN
    1919             : 
    1920             : !                   ALGORITHM FOR B0 .LE. 1
    1921             : 
    1922           0 :          fn_val = esum(mu, z)
    1923           0 :          IF (fn_val == 0.0e0_dp) RETURN
    1924             : 
    1925           0 :          apb = a + b
    1926           0 :          IF (apb > 1.0e0_dp) THEN
    1927           0 :             u = a + b - 1.e0_dp
    1928           0 :             z = (1.0e0_dp + gam1(u))/apb
    1929             :          ELSE
    1930           0 :             z = 1.0e0_dp + gam1(apb)
    1931             :          END IF
    1932             : 
    1933           0 :          c = (1.0e0_dp + gam1(a))*(1.0e0_dp + gam1(b))/z
    1934           0 :          fn_val = fn_val*(a0*c)/(1.0e0_dp + a0/b0)
    1935           0 :          RETURN
    1936             :       END IF
    1937             : 
    1938             : !                ALGORITHM FOR 1 .LT. B0 .LT. 8
    1939             : 
    1940           0 :       u = gamln1(a0)
    1941           0 :       n = INT(b0 - 1.0e0_dp)
    1942           0 :       IF (n >= 1) THEN
    1943             :          c = 1.0e0_dp
    1944           0 :          DO i = 1, n
    1945           0 :             b0 = b0 - 1.0e0_dp
    1946           0 :             c = c*(b0/(a0 + b0))
    1947             :          END DO
    1948           0 :          u = LOG(c) + u
    1949             :       END IF
    1950             : 
    1951           0 :       z = z - u
    1952           0 :       b0 = b0 - 1.0e0_dp
    1953           0 :       apb = a0 + b0
    1954           0 :       IF (apb > 1.0e0_dp) THEN
    1955           0 :          u = a0 + b0 - 1.e0_dp
    1956           0 :          t = (1.0e0_dp + gam1(u))/apb
    1957             :       ELSE
    1958           0 :          t = 1.0e0_dp + gam1(apb)
    1959             :       END IF
    1960           0 :       fn_val = a0*esum(mu, z)*(1.0e0_dp + gam1(b0))/t
    1961             : 
    1962           0 :    END FUNCTION brcmp1
    1963             : 
    1964             : ! **************************************************************************************************
    1965             : !> \brief ...
    1966             : !> \param a ...
    1967             : !> \param b ...
    1968             : !> \param lambda ...
    1969             : !> \param eps ...
    1970             : !> \return ...
    1971             : ! **************************************************************************************************
    1972           0 :    FUNCTION basym(a, b, lambda, eps) RESULT(fn_val)
    1973             : !-----------------------------------------------------------------------
    1974             : !     ASYMPTOTIC EXPANSION FOR IX(A,B) FOR LARGE A AND B.
    1975             : !     LAMBDA = (A + B)*Y - B  AND EPS IS THE TOLERANCE USED.
    1976             : !     IT IS ASSUMED THAT LAMBDA IS NONNEGATIVE AND THAT
    1977             : !     A AND B ARE GREATER THAN OR EQUAL TO 15.
    1978             : !-----------------------------------------------------------------------
    1979             :       REAL(dp), INTENT(IN)                               :: a, b, lambda, eps
    1980             :       REAL(dp)                                           :: fn_val
    1981             : 
    1982             :       INTEGER, PARAMETER                                 :: num = 20
    1983             :       REAL(dp), PARAMETER                                :: e0 = 1.12837916709551e0_dp, &
    1984             :                                                             e1 = .353553390593274e0_dp
    1985             : 
    1986             :       INTEGER                                            :: i, im1, imj, j, m, mm1, mmj, n, np1
    1987             :       REAL(dp)                                           :: a0(21), b0(21), bsum, c(21), d(21), &
    1988             :                                                             dsum, f, h, h2, hn, j0, j1, r, r0, r1, &
    1989             :                                                             s, sum, t, t0, t1, u, w, w0, z, z0, &
    1990             :                                                             z2, zn, znm1
    1991             : 
    1992             : !------------------------
    1993             : !     ****** NUM IS THE MAXIMUM VALUE THAT N CAN TAKE IN THE DO LOOP
    1994             : !            ENDING AT STATEMENT 50. IT IS REQUIRED THAT NUM BE EVEN.
    1995             : !            THE ARRAYS A0, B0, C, D HAVE DIMENSION NUM + 1.
    1996             : !------------------------
    1997             : !     E0 = 2/SQRT(PI)
    1998             : !     E1 = 2**(-3/2)
    1999             : !------------------------
    2000             : 
    2001           0 :       fn_val = 0.0e0_dp
    2002           0 :       IF (a >= b) THEN
    2003           0 :          h = b/a
    2004           0 :          r0 = 1.0e0_dp/(1.0e0_dp + h)
    2005           0 :          r1 = (b - a)/a
    2006           0 :          w0 = 1.0e0_dp/SQRT(b*(1.0e0_dp + h))
    2007             :       ELSE
    2008           0 :          h = a/b
    2009           0 :          r0 = 1.0e0_dp/(1.0e0_dp + h)
    2010           0 :          r1 = (b - a)/b
    2011           0 :          w0 = 1.0e0_dp/SQRT(a*(1.0e0_dp + h))
    2012             :       END IF
    2013             : 
    2014           0 :       f = a*rlog1(-lambda/a) + b*rlog1(lambda/b)
    2015           0 :       t = EXP(-f)
    2016           0 :       IF (t == 0.0e0_dp) RETURN
    2017           0 :       z0 = SQRT(f)
    2018           0 :       z = 0.5e0_dp*(z0/e1)
    2019           0 :       z2 = f + f
    2020             : 
    2021           0 :       a0(1) = (2.0e0_dp/3.0e0_dp)*r1
    2022           0 :       c(1) = -0.5e0_dp*a0(1)
    2023           0 :       d(1) = -c(1)
    2024           0 :       j0 = (0.5e0_dp/e0)*ERFC_SCALED(z0)
    2025           0 :       j1 = e1
    2026           0 :       sum = j0 + d(1)*w0*j1
    2027             : 
    2028           0 :       s = 1.0e0_dp
    2029           0 :       h2 = h*h
    2030           0 :       hn = 1.0e0_dp
    2031           0 :       w = w0
    2032           0 :       znm1 = z
    2033           0 :       zn = z2
    2034           0 :       DO n = 2, num, 2
    2035           0 :          hn = h2*hn
    2036           0 :          a0(n) = 2.0e0_dp*r0*(1.0e0_dp + h*hn)/(n + 2.0e0_dp)
    2037           0 :          np1 = n + 1
    2038           0 :          s = s + hn
    2039           0 :          a0(np1) = 2.0e0_dp*r1*s/(n + 3.0e0_dp)
    2040             : 
    2041           0 :          DO i = n, np1
    2042           0 :             r = -0.5e0_dp*(i + 1.0e0_dp)
    2043           0 :             b0(1) = r*a0(1)
    2044           0 :             DO m = 2, i
    2045             :                bsum = 0.0e0_dp
    2046             :                mm1 = m - 1
    2047           0 :                DO j = 1, mm1
    2048           0 :                   mmj = m - j
    2049           0 :                   bsum = bsum + (j*r - mmj)*a0(j)*b0(mmj)
    2050             :                END DO
    2051           0 :                b0(m) = r*a0(m) + bsum/m
    2052             :             END DO
    2053           0 :             c(i) = b0(i)/(i + 1.0e0_dp)
    2054             : 
    2055           0 :             dsum = 0.0e0_dp
    2056           0 :             im1 = i - 1
    2057           0 :             DO j = 1, im1
    2058           0 :                imj = i - j
    2059           0 :                dsum = dsum + d(imj)*c(j)
    2060             :             END DO
    2061           0 :             d(i) = -(dsum + c(i))
    2062             :          END DO
    2063             : 
    2064           0 :          j0 = e1*znm1 + (n - 1.0e0_dp)*j0
    2065           0 :          j1 = e1*zn + n*j1
    2066           0 :          znm1 = z2*znm1
    2067           0 :          zn = z2*zn
    2068           0 :          w = w0*w
    2069           0 :          t0 = d(n)*w*j0
    2070           0 :          w = w0*w
    2071           0 :          t1 = d(np1)*w*j1
    2072           0 :          sum = sum + (t0 + t1)
    2073           0 :          IF ((ABS(t0) + ABS(t1)) <= eps*sum) EXIT
    2074             :       END DO
    2075             : 
    2076           0 :       u = EXP(-bcorr(a, b))
    2077           0 :       fn_val = e0*t*u*sum
    2078             : 
    2079           0 :    END FUNCTION basym
    2080             : 
    2081             : END MODULE beta_gamma_psi

Generated by: LCOV version 1.15