Exemplo n.º 1
0
def r8_beta(x, y):

    #*****************************************************************************80
    #
    ## R8_BETA returns the value of the Beta function.
    #
    #  Complaint:
    #
    #    Because of the MISERABLE local installation of Python, the gamma
    #    function is currently not accessible...
    #
    #  Discussion:
    #
    #    The formula is
    #
    #      BETA(X,Y) = ( GAMMA(X) * GAMMA(Y) ) / GAMMA(X+Y)
    #
    #    Both X and Y must be greater than 0.
    #
    #  Properties:
    #
    #    BETA(X,Y) = BETA(Y,X).
    #    BETA(X,Y) = Integral ( 0 <= T <= 1 ) T^(X-1) (1-T)^(Y-1) dT.
    #    BETA(X,Y) = GAMMA(X) * GAMMA(Y) / GAMMA(X+Y)
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    01 January 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, real X, Y, the two parameters that define the Beta function.
    #    X and Y must be greater than 0.
    #
    #    Output, real VALUE, the value of the Beta function.
    #
    from r8_gamma import r8_gamma
    from sys import exit

    if (x <= 0.0 or y <= 0.0):
        print ''
        print 'R8_BETA - Fatal error!'
        print '  Both X and Y must be greater than 0.'
        exit('R8_BETA - Fatal error!')

    value = r8_gamma(x) * r8_gamma(y) / r8_gamma(x + y)

    return value
Exemplo n.º 2
0
def r8_beta ( x, y ):

#*****************************************************************************80
#
## R8_BETA returns the value of the Beta function.
#
#  Complaint:
#
#    Because of the MISERABLE local installation of Python, the gamma
#    function is currently not accessible...
#
#  Discussion:
#
#    The formula is
#
#      BETA(X,Y) = ( GAMMA(X) * GAMMA(Y) ) / GAMMA(X+Y)
#
#    Both X and Y must be greater than 0.
#
#  Properties:
#
#    BETA(X,Y) = BETA(Y,X).
#    BETA(X,Y) = Integral ( 0 <= T <= 1 ) T^(X-1) (1-T)^(Y-1) dT.
#    BETA(X,Y) = GAMMA(X) * GAMMA(Y) / GAMMA(X+Y)
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    01 January 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, real X, Y, the two parameters that define the Beta function.
#    X and Y must be greater than 0.
#
#    Output, real VALUE, the value of the Beta function.
#
  from r8_gamma import r8_gamma
  from sys import exit

  if ( x <= 0.0 or y <= 0.0 ):
    print ''
    print 'R8_BETA - Fatal error!'
    print '  Both X and Y must be greater than 0.'
    exit ( 'R8_BETA - Fatal error!' )

  value = r8_gamma ( x ) * r8_gamma ( y ) / r8_gamma ( x + y )

  return value
Exemplo n.º 3
0
def r8_beta ( a, b ):

#*****************************************************************************80
#
## R8_BETA returns the value of the Beta function.
#
#  Discussion:
#
#    BETA(A,B) = ( GAMMA ( A ) * GAMMA ( B ) ) / GAMMA ( A + B )
#              = Integral ( 0 <= T <= 1 ) T^(A-1) (1-T)^(B-1) dT.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    02 September 2004
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, real A, B, the parameters of the function.
#    0.0D+00 < A,
#    0.0D+00 < B.
#
#    Output, real R8_BETA, the value of the function.
#
  import numpy as np
  from r8_gamma import r8_gamma
  from sys import exit

  if ( a <= 0.0 or b <= 0.0 ):
    print ( '' )
    print ( 'R8_BETA - Fatal error!' )
    print ( '  Both A and B must be greater than 0.' )
    exit ( 'R8_BETA - Fatal error!' )

  value = r8_gamma ( a ) * r8_gamma ( b ) / r8_gamma ( a + b )

  return value
Exemplo n.º 4
0
def beta_cdf_inv(cdf, p, q):

    #*****************************************************************************80
    #
    ## BETA_CDF_INV computes inverse of the incomplete Beta function.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    04 March 2016
    #
    #  Author:
    #
    #    Original FORTRAN77 version by GW Cran, KJ Martin, GE Thomas.
    #    Python version by John Burkardt.
    #
    #  Reference:
    #
    #    GW Cran, KJ Martin, GE Thomas,
    #    Remark AS R19 and Algorithm AS 109:
    #    A Remark on Algorithms AS 63: The Incomplete Beta Integral
    #    and AS 64: Inverse of the Incomplete Beta Integeral,
    #    Applied Statistics,
    #    Volume 26, Number 1, 1977, pages 111-114.
    #
    #  Parameters:
    #
    #    Input, real P, Q, the parameters of the incomplete
    #    Beta function.
    #
    #    Input, real CDF, the value of the incomplete Beta
    #    function.  0 <= CDF <= 1.
    #
    #    Output, real VALUE, the argument of the Beta CDF which produces
    #    the value CDF.
    #
    #  Local Parameters:
    #
    #    Local, real ( kind = 8 ) SAE, the most negative decimal exponent
    #    which does not cause an underflow.
    #
    import numpy as np
    from beta_inc import beta_inc
    from r8_gamma import r8_gamma
    from sys import exit

    sae = -37.0

    fpu = 10.0**sae
    #
    #  Test for admissibility of parameters.
    #
    if (p <= 0.0):
        print('')
        print('BETA_CDF_INV - Fatal error!')
        print('  P <= 0.')
        exit('BETA_CDF_INV - Fatal error!')

    if (q <= 0.0):
        print('')
        print('BETA_CDF_INV - Fatal error!')
        print('  Q <= 0.')
        exit('BETA_CDF_INV - Fatal error!')

    if (cdf < 0.0 or 1.0 < cdf):
        print('')
        print('BETA_CDF_INV - Fatal error!')
        print('  CDF < 0 or 1 < CDF.')
        exit('BETA_CDF_INV - Fatal error!')
#
#  If the value is easy to determine, return immediately.
#
    if (cdf == 0.0):
        value = 0.0
        return value

    if (cdf == 1.0):
        value = 1.0
        return value

    beta_log = np.log ( r8_gamma ( p ) ) + np.log ( r8_gamma ( q ) ) \
      - np.log ( r8_gamma ( p + q ) )
    #
    #  Change tail if necessary.
    #
    if (0.5 < cdf):
        a = 1.0 - cdf
        pp = q
        qq = p
        indx = 1
    else:
        a = cdf
        pp = p
        qq = q
        indx = 0
#
#  Calculate the initial approximation.
#
    r = np.sqrt(-np.log(a * a))

    y = r - ( 2.30753 + 0.27061 * r ) \
      / ( 1.0 + ( 0.99229 + 0.04481 * r ) * r )

    if (1.0 < pp and 1.0 < qq):

        r = (y * y - 3.0) / 6.0
        s = 1.0 / (pp + pp - 1.0)
        t = 1.0 / (qq + qq - 1.0)
        h = 2.0 / (s + t)
        w = y * np.sqrt ( h + r ) / h - ( t - s ) \
          * ( r + 5.0 / 6.0 - 2.0 / ( 3.0 * h ) )
        value = pp / (pp + qq * np.exp(w + w))

    else:

        r = qq + qq
        t = 1.0 / (9.0 * qq)
        t = r * (1.0 - t + y * np.sqrt(t))**3

        if (t <= 0.0):
            value = 1.0 - np.exp((np.log((1.0 - a) * qq) + beta_log) / qq)
        else:

            t = (4.0 * pp + r - 2.0) / t

            if (t <= 1.0):
                value = np.exp((np.log(a * pp) + beta_log) / pp)
            else:
                value = 1.0 - 2.0 / (t + 1.0)


#
#  Solve for X by a modified Newton-Raphson method.
#
    r = 1.0 - pp
    t = 1.0 - qq
    yprev = 0.0
    sq = 1.0
    prev = 1.0

    if (value < 0.0001):
        value = 0.0001

    if (0.9999 < value):
        value = 0.9999

    iex = max(-5.0 / pp / pp - 1.0 / a**0.2 - 13.0, sae)

    acu = 10.0**iex

    while (True):

        y = beta_inc(pp, qq, value)

        xin = value
        y = (y - a) * np.exp(beta_log + r * np.log(xin) +
                             t * np.log(1.0 - xin))

        if (y * yprev <= 0.0):
            prev = max(sq, fpu)

        g = 1.0

        while (True):

            while (True):

                adj = g * y
                sq = adj * adj

                if (sq < prev):

                    tx = value - adj

                    if (0.0 <= tx and tx <= 1.0):
                        break

                g = g / 3.0

            if (prev <= acu):
                if (indx):
                    value = 1.0 - value
                return value

            if (y * y <= acu):
                if (indx):
                    value = 1.0 - value
                return value

            if (tx != 0.0 and tx != 1.0):
                break

            g = g / 3.0

        if (tx == value):
            break

        value = tx
        yprev = y

    if (indx):
        value = 1.0 - value

    return value
Exemplo n.º 5
0
def multinomial_coef1 ( nfactor, factor ):

#*****************************************************************************80
#
## MULTINOMIAL_COEF1 computes a multinomial coefficient.
#
#  Discussion:
#
#    The multinomial coefficient is a generalization of the binomial
#    coefficient.  It may be interpreted as the number of combinations of
#    N objects, where FACTOR(1) objects are indistinguishable of type 1,
#    ... and FACTOR(NFACTOR) are indistinguishable of type NFACTOR,
#    and N is the sum of FACTOR(1) through FACTOR(NFACTOR).
#
#    NCOMB = N! / ( FACTOR(1)! FACTOR(2)! ... FACTOR(NFACTOR)! )
#
#    The log of the gamma function is used, to avoid overflow.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    26 May 2015
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer NFACTOR, the number of factors.
#
#    Input, integer FACTOR(NFACTOR), contains the factors.
#    0 <= FACTOR(I)
#
#    Output, integer NCOMB, the value of the multinomial coefficient.
#
  from math import exp
  from math import log
  from r8_gamma import r8_gamma
# from math import lgamma
  from sys import exit
  from i4vec_sum import i4vec_sum
#
#  Each factor must be nonnegative.
#
  for i in range ( 0, nfactor ):

    if ( factor[i] < 0 ):
      print ''
      print 'MULTINOMIAL_COEF1 - Fatal error!'
      print '  Factor %d = %d' % ( i, factor[i] )
      print '  But this value must be nonnegative.'
      exit ( 'MULTINOMIAL_COEF1 - Fatal error!' )
#
#  The factors sum to N.
#
  n = i4vec_sum ( nfactor, factor )

  arg = float ( n + 1 )
#
#  Our obsolete version of Python doesn't have LGAMMA yet!
#
  facn = log ( r8_gamma ( arg ) )
# facn = lgamma ( arg )

  for i in range ( 0, nfactor ):

    arg = float ( factor[i] + 1 )
    fack = log ( r8_gamma ( arg ) )
#   fack = lgamma ( arg )
    facn = facn - fack

  ncomb = round ( exp ( facn ) )

  return ncomb
Exemplo n.º 6
0
def r8_hyper_2f1 ( a, b, c, x ):

#*****************************************************************************80
#
## R8_HYPER_2F1 evaluates the hypergeometric function F(A,B,C,X).
#
#  Discussion:
#
#    A minor bug was corrected.  The HW variable, used in several places as
#    the "old" value of a quantity being iteratively improved, was not
#    being initialized.  JVB, 11 February 2008.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license. 
#
#  Modified:
#
#    28 February 2015
#
#  Author:
#
#    Original FORTRAN77 version by Shanjie Zhang, Jianming Jin.
#    Python version by John Burkardt.
#
#    The F77 original version of this routine is copyrighted by
#    Shanjie Zhang and Jianming Jin.  However, they give permission to
#    incorporate this routine into a user program provided that the copyright
#    is acknowledged.
#
#  Reference:
#
#    Shanjie Zhang, Jianming Jin,
#    Computation of Special Functions,
#    Wiley, 1996,
#    ISBN: 0-471-11963-6,
#    LC: QA351.C45
#
#  Parameters:
#
#    Input, real A, B, C, X, the arguments of the function.
#    C must not be equal to a nonpositive integer.
#    X < 1.
#
#    Output, real VALUE, the value of the function.
#
  import numpy as np
  from r8_gamma import r8_gamma
  from r8_psi import r8_psi

  el = 0.5772156649015329

  l0 = ( c == int ( c ) ) and ( c < 0.0 )
  l1 = ( 1.0 - x < 1.0E-15 ) and ( c - a - b <= 0.0 )
  l2 = ( a == int ( a ) ) and ( a < 0.0 )
  l3 = ( b == int ( b ) ) and ( b < 0.0 )
  l4 = ( c - a == int ( c - a ) ) and ( c - a <= 0.0 )
  l5 = ( c - b == int ( c - b ) ) and ( c - b <= 0.0 )

  if ( l0 ):
    print ''
    print 'R8_HYPER_2F1 - Fatal error!'
    print '  The hypergeometric series is divergent.'
    print '  C is integral and negative.'
    print '  C = %f' % ( c )

  if ( l1 ):
    print ''
    print 'R8_HYPER_2F1 - Fatal error!'
    print '  The hypergeometric series is divergent.'
    print '  1 = X < 0, C - A - B <= 0.'
    print '  A = %f' % ( a )
    print '  B = %f' % ( b )
    print '  C = %f' % ( c )
    print '  X = %f' % ( x )

  if ( 0.95 < x ):
    eps = 1.0E-08
  else:
    eps = 1.0E-15

  if ( x == 0.0 or a == 0.0 or b == 0.0 ):

    value = 1.0
    return value

  elif ( 1.0 - x == eps and 0.0 < c - a - b ):

    gc = r8_gamma ( c )
    gcab = r8_gamma ( c - a - b )
    gca = r8_gamma ( c - a )
    gcb = r8_gamma ( c - b )
    value = gc * gcab / ( gca * gcb )
    return value

  elif ( 1.0 + x <= eps and abs ( c - a + b - 1.0 ) <= eps ):

    g0 = np.sqrt ( np.pi ) * 2.0 ** ( - a )
    g1 = r8_gamma ( c )
    g2 = r8_gamma ( 1.0 + a / 2.0 - b )
    g3 = r8_gamma ( 0.5 + 0.5 * a )
    value = g0 * g1 / ( g2 * g3 )
    return value

  elif ( l2 or l3 ):

    if ( l2 ):
      nm = int ( abs ( a ) )

    if ( l3 ):
      nm = int ( abs ( b ) )

    value = 1.0
    r = 1.0

    for k in range ( 1, nm + 1 ):
      r = r * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
        / ( float ( k ) * ( c + float ( k ) - 1.0 ) ) * x
      value = value + r

    return value

  elif ( l4 or l5 ):

    if ( l4 ):
      nm = int ( abs ( c - a ) )
 
    if ( l5 ):
      nm = int ( abs ( c - b ) )

    value = 1.0
    r  = 1.0
    for k in range ( 1, nm + 1 ):
      r = r * ( c - a + float ( k ) - 1.0 ) * ( c - b + float ( k ) - 1.0 ) \
        / ( float ( k ) * ( c + float ( k ) - 1.0 ) ) * x
      value = value + r
    value = ( 1.0 - x ) ** ( c - a - b ) * hf
    return value

  aa = a
  bb = b
  x1 = x

  if ( x < 0.0 ):
    x = x / ( x - 1.0 )
    if ( a < c and b < a and 0.0 < b ):
      a = bb
      b = aa
    b = c - b

  if ( 0.75 <= x ):

    gm = 0.0

    if ( abs ( c - a - b - int ( c - a - b ) ) < 1.0E-15 ):

      m = int ( c - a - b )
      ga = r8_gamma ( a )
      gb = r8_gamma ( b )
      gc = r8_gamma ( c )
      gam = r8_gamma ( a + float ( m ) )
      gbm = r8_gamma ( b + float ( m ) )

      pa = r8_psi ( a )
      pb = r8_psi ( b )

      if ( m != 0 ):
        gm = 1.0

      for j in range ( 1, abs ( m ) ):
        gm = gm * float ( j )

      rm = 1.0
      for j in range ( 1, abs ( m ) + 1 ):
        rm = rm * float ( j )
 
      f0 = 1.0
      r0 = 1.0
      r1 = 1.0
      sp0 = 0.0
      sp = 0.0

      if ( 0 <= m ):

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

        for k in range ( 1, m ):
          r0 = r0 * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
            / float ( k * ( k - m ) ) * ( 1.0 - x )
          f0 = f0 + r0
 
        for k in range ( 1, m + 1 ):
          sp0 = sp0 + 1.0 / ( a + float ( k ) - 1.0 ) \
            + 1.0 / ( b + float ( k ) - 1.0 ) - 1.0 / float ( k )

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

        for k in range ( 1, 251 ):

          sp = sp + ( 1.0 - a ) / ( float ( k ) * ( a + float ( k ) - 1.0 ) ) \
            + ( 1.0 - b ) / ( float ( k ) * ( b + float ( k ) - 1.0 ) )

          sm = 0.0
          for j in range ( 1, m + 1 ):
            sm = sm + ( 1.0 - a ) \
              / ( float ( j + k ) * ( a + float ( j + k ) - 1.0 ) ) \
              + 1.0 / ( b + float ( j + k ) - 1.0 )

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

          r1 = r1 * ( a + m + float ( k ) - 1.0 ) * ( b + m + float ( k ) - 1.0 ) \
            / ( float ( k ) * float ( m + k ) ) * ( 1.0 - x )

          f1 = f1 + r1 * rp

          if ( abs ( f1 - hw ) < abs ( f1 ) * eps ):
            break
 
          hw = f1

        value = f0 * c0 + f1 * c1

      elif ( m < 0 ):

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

        for k in range ( 1, m ):
          r0 = r0 * ( a - float ( m ) + float ( k ) - 1.0 ) \
            * ( b - float ( m ) + float ( k ) - 1.0 ) \
            / ( float ( k ) * float ( k - m ) ) * ( 1.0 - x )
          f0 = f0 + r0

        for k in range ( 1, m + 1 ):
          sp0 = sp0 + 1.0 / float ( k )

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

        for k in range ( 1, 251 ):

          sp = sp + ( 1.0 - a ) \
            / ( float ( k ) * ( a + float ( k ) - 1.0 ) ) \
            + ( 1.0 - b ) / ( float ( k ) * ( b + float ( k ) - 1.0 ) )

          sm = 0.0
          for j in range ( 1, m + 1 ):
            sm = sm + 1.0 / float ( j + k )

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

          r1 = r1 * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
            / float ( k * ( m + k ) ) * ( 1.0 - x )

          f1 = f1 + r1 * rp

          if ( abs ( f1 - hw ) < abs ( f1 ) * eps ):
            break

          hw = f1

        value = f0 * c0 + f1 * c1

    else:

      ga = r8_gamma ( a )
      gb = r8_gamma ( b )
      gc = r8_gamma ( c )
      gca = r8_gamma ( c - a )
      gcb = r8_gamma ( c - b )
      gcab = r8_gamma ( c - a - b )
      gabc = r8_gamma ( a + b - c )
      c0 = gc * gcab / ( gca * gcb )
      c1 = gc * gabc / ( ga * gb ) * ( 1.0 - x ) ** ( c - a - b )
      value = 0.0
      hw = value
      r0 = c0
      r1 = c1

      for k in range ( 1, 251 ):

        r0 = r0 * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
          / ( float ( k ) * ( a + b - c + float ( k ) ) ) * ( 1.0 - x )

        r1 = r1 * ( c - a + float ( k ) - 1.0 ) \
          * ( c - b + float ( k ) - 1.0 ) \
          / ( float ( k ) * ( c - a - b + float ( k ) ) ) * ( 1.0 - x )

        value = value + r0 + r1

        if ( abs ( value - hw ) < abs ( value ) * eps ):
          break

        hw = value

      value = value + c0 + c1

  else:

    a0 = 1.0

    if ( a < c and c < 2.0 * a and b < c and c < 2.0 * b ):

      a0 = ( 1.0 - x ) ** ( c - a - b )
      a = c - a
      b = c - b

    value = 1.0
    hw = value
    r = 1.0

    for k in range ( 1, 251 ):

      r = r * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
        / ( k * ( c + float ( k ) - 1.0 ) ) * x

      value = value + r

      if ( abs ( value - hw ) <= abs ( value ) * eps ):
        break

      hw = value

    value = a0 * value

  if ( x1 < 0.0 ):
    x = x1
    c0 = 1.0 / ( 1.0 - x ) ** aa
    value = c0 * value

  if ( 120 < k ):
    print ''
    print 'R8_HYPER_2F1 - Warning!'
    print '  A large number of iterations were needed.'
    print '  The accuracy of the results should be checked.'

  return value
Exemplo n.º 7
0
def r8_hyper_2f1(a, b, c, x):

    #*****************************************************************************80
    #
    ## R8_HYPER_2F1 evaluates the hypergeometric function F(A,B,C,X).
    #
    #  Discussion:
    #
    #    A minor bug was corrected.  The HW variable, used in several places as
    #    the "old" value of a quantity being iteratively improved, was not
    #    being initialized.  JVB, 11 February 2008.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    28 February 2015
    #
    #  Author:
    #
    #    Original FORTRAN77 version by Shanjie Zhang, Jianming Jin.
    #    Python version by John Burkardt.
    #
    #    The F77 original version of this routine is copyrighted by
    #    Shanjie Zhang and Jianming Jin.  However, they give permission to
    #    incorporate this routine into a user program provided that the copyright
    #    is acknowledged.
    #
    #  Reference:
    #
    #    Shanjie Zhang, Jianming Jin,
    #    Computation of Special Functions,
    #    Wiley, 1996,
    #    ISBN: 0-471-11963-6,
    #    LC: QA351.C45
    #
    #  Parameters:
    #
    #    Input, real A, B, C, X, the arguments of the function.
    #    C must not be equal to a nonpositive integer.
    #    X < 1.
    #
    #    Output, real VALUE, the value of the function.
    #
    import numpy as np
    from r8_gamma import r8_gamma
    from r8_psi import r8_psi

    el = 0.5772156649015329

    l0 = (c == int(c)) and (c < 0.0)
    l1 = (1.0 - x < 1.0E-15) and (c - a - b <= 0.0)
    l2 = (a == int(a)) and (a < 0.0)
    l3 = (b == int(b)) and (b < 0.0)
    l4 = (c - a == int(c - a)) and (c - a <= 0.0)
    l5 = (c - b == int(c - b)) and (c - b <= 0.0)

    if (l0):
        print ''
        print 'R8_HYPER_2F1 - Fatal error!'
        print '  The hypergeometric series is divergent.'
        print '  C is integral and negative.'
        print '  C = %f' % (c)

    if (l1):
        print ''
        print 'R8_HYPER_2F1 - Fatal error!'
        print '  The hypergeometric series is divergent.'
        print '  1 = X < 0, C - A - B <= 0.'
        print '  A = %f' % (a)
        print '  B = %f' % (b)
        print '  C = %f' % (c)
        print '  X = %f' % (x)

    if (0.95 < x):
        eps = 1.0E-08
    else:
        eps = 1.0E-15

    if (x == 0.0 or a == 0.0 or b == 0.0):

        value = 1.0
        return value

    elif (1.0 - x == eps and 0.0 < c - a - b):

        gc = r8_gamma(c)
        gcab = r8_gamma(c - a - b)
        gca = r8_gamma(c - a)
        gcb = r8_gamma(c - b)
        value = gc * gcab / (gca * gcb)
        return value

    elif (1.0 + x <= eps and abs(c - a + b - 1.0) <= eps):

        g0 = np.sqrt(np.pi) * 2.0**(-a)
        g1 = r8_gamma(c)
        g2 = r8_gamma(1.0 + a / 2.0 - b)
        g3 = r8_gamma(0.5 + 0.5 * a)
        value = g0 * g1 / (g2 * g3)
        return value

    elif (l2 or l3):

        if (l2):
            nm = int(abs(a))

        if (l3):
            nm = int(abs(b))

        value = 1.0
        r = 1.0

        for k in range(1, nm + 1):
            r = r * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
              / ( float ( k ) * ( c + float ( k ) - 1.0 ) ) * x
            value = value + r

        return value

    elif (l4 or l5):

        if (l4):
            nm = int(abs(c - a))

        if (l5):
            nm = int(abs(c - b))

        value = 1.0
        r = 1.0
        for k in range(1, nm + 1):
            r = r * ( c - a + float ( k ) - 1.0 ) * ( c - b + float ( k ) - 1.0 ) \
              / ( float ( k ) * ( c + float ( k ) - 1.0 ) ) * x
            value = value + r
        value = (1.0 - x)**(c - a - b) * hf
        return value

    aa = a
    bb = b
    x1 = x

    if (x < 0.0):
        x = x / (x - 1.0)
        if (a < c and b < a and 0.0 < b):
            a = bb
            b = aa
        b = c - b

    if (0.75 <= x):

        gm = 0.0

        if (abs(c - a - b - int(c - a - b)) < 1.0E-15):

            m = int(c - a - b)
            ga = r8_gamma(a)
            gb = r8_gamma(b)
            gc = r8_gamma(c)
            gam = r8_gamma(a + float(m))
            gbm = r8_gamma(b + float(m))

            pa = r8_psi(a)
            pb = r8_psi(b)

            if (m != 0):
                gm = 1.0

            for j in range(1, abs(m)):
                gm = gm * float(j)

            rm = 1.0
            for j in range(1, abs(m) + 1):
                rm = rm * float(j)

            f0 = 1.0
            r0 = 1.0
            r1 = 1.0
            sp0 = 0.0
            sp = 0.0

            if (0 <= m):

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

                for k in range(1, m):
                    r0 = r0 * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
                      / float ( k * ( k - m ) ) * ( 1.0 - x )
                    f0 = f0 + r0

                for k in range(1, m + 1):
                    sp0 = sp0 + 1.0 / ( a + float ( k ) - 1.0 ) \
                      + 1.0 / ( b + float ( k ) - 1.0 ) - 1.0 / float ( k )

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

                for k in range(1, 251):

                    sp = sp + ( 1.0 - a ) / ( float ( k ) * ( a + float ( k ) - 1.0 ) ) \
                      + ( 1.0 - b ) / ( float ( k ) * ( b + float ( k ) - 1.0 ) )

                    sm = 0.0
                    for j in range(1, m + 1):
                        sm = sm + ( 1.0 - a ) \
                          / ( float ( j + k ) * ( a + float ( j + k ) - 1.0 ) ) \
                          + 1.0 / ( b + float ( j + k ) - 1.0 )

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

                    r1 = r1 * ( a + m + float ( k ) - 1.0 ) * ( b + m + float ( k ) - 1.0 ) \
                      / ( float ( k ) * float ( m + k ) ) * ( 1.0 - x )

                    f1 = f1 + r1 * rp

                    if (abs(f1 - hw) < abs(f1) * eps):
                        break

                    hw = f1

                value = f0 * c0 + f1 * c1

            elif (m < 0):

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

                for k in range(1, m):
                    r0 = r0 * ( a - float ( m ) + float ( k ) - 1.0 ) \
                      * ( b - float ( m ) + float ( k ) - 1.0 ) \
                      / ( float ( k ) * float ( k - m ) ) * ( 1.0 - x )
                    f0 = f0 + r0

                for k in range(1, m + 1):
                    sp0 = sp0 + 1.0 / float(k)

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

                for k in range(1, 251):

                    sp = sp + ( 1.0 - a ) \
                      / ( float ( k ) * ( a + float ( k ) - 1.0 ) ) \
                      + ( 1.0 - b ) / ( float ( k ) * ( b + float ( k ) - 1.0 ) )

                    sm = 0.0
                    for j in range(1, m + 1):
                        sm = sm + 1.0 / float(j + k)

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

                    r1 = r1 * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
                      / float ( k * ( m + k ) ) * ( 1.0 - x )

                    f1 = f1 + r1 * rp

                    if (abs(f1 - hw) < abs(f1) * eps):
                        break

                    hw = f1

                value = f0 * c0 + f1 * c1

        else:

            ga = r8_gamma(a)
            gb = r8_gamma(b)
            gc = r8_gamma(c)
            gca = r8_gamma(c - a)
            gcb = r8_gamma(c - b)
            gcab = r8_gamma(c - a - b)
            gabc = r8_gamma(a + b - c)
            c0 = gc * gcab / (gca * gcb)
            c1 = gc * gabc / (ga * gb) * (1.0 - x)**(c - a - b)
            value = 0.0
            hw = value
            r0 = c0
            r1 = c1

            for k in range(1, 251):

                r0 = r0 * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
                  / ( float ( k ) * ( a + b - c + float ( k ) ) ) * ( 1.0 - x )

                r1 = r1 * ( c - a + float ( k ) - 1.0 ) \
                  * ( c - b + float ( k ) - 1.0 ) \
                  / ( float ( k ) * ( c - a - b + float ( k ) ) ) * ( 1.0 - x )

                value = value + r0 + r1

                if (abs(value - hw) < abs(value) * eps):
                    break

                hw = value

            value = value + c0 + c1

    else:

        a0 = 1.0

        if (a < c and c < 2.0 * a and b < c and c < 2.0 * b):

            a0 = (1.0 - x)**(c - a - b)
            a = c - a
            b = c - b

        value = 1.0
        hw = value
        r = 1.0

        for k in range(1, 251):

            r = r * ( a + float ( k ) - 1.0 ) * ( b + float ( k ) - 1.0 ) \
              / ( k * ( c + float ( k ) - 1.0 ) ) * x

            value = value + r

            if (abs(value - hw) <= abs(value) * eps):
                break

            hw = value

        value = a0 * value

    if (x1 < 0.0):
        x = x1
        c0 = 1.0 / (1.0 - x)**aa
        value = c0 * value

    if (120 < k):
        print ''
        print 'R8_HYPER_2F1 - Warning!'
        print '  A large number of iterations were needed.'
        print '  The accuracy of the results should be checked.'

    return value
Exemplo n.º 8
0
def hermite_ek_compute(n):

    #*****************************************************************************80
    #
    ## HERMITE_EK_COMPUTE computes a Gauss-Hermite quadrature rule.
    #
    #  Discussion:
    #
    #    The code uses an algorithm by Elhay and Kautsky.
    #
    #    The abscissas are the zeros of the N-th order Hermite polynomial.
    #
    #    The integral:
    #
    #      integral ( -oo < x < +oo ) exp ( - x * x ) * f(x) dx
    #
    #    The quadrature rule:
    #
    #      sum ( 1 <= i <= n ) w(i) * f ( x(i) )
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    15 June 2015
    #
    #  Author:
    #
    #    John Burkardt.
    #
    #  Reference:
    #
    #    Sylvan Elhay, Jaroslav Kautsky,
    #    Algorithm 655: IQPACK, FORTRAN Subroutines for the Weights of
    #    Interpolatory Quadrature,
    #    ACM Transactions on Mathematical Software,
    #    Volume 13, Number 4, December 1987, pages 399-415.
    #
    #  Parameters:
    #
    #    Input, integer N, the number of abscissas.
    #
    #    Output, real X(N), the abscissas.
    #
    #    Output, real W(N), the weights.
    #
    import numpy as np
    from imtqlx import imtqlx
    from r8_gamma import r8_gamma
    #
    #  Define the zero-th moment.
    #
    zemu = r8_gamma(0.5)
    #
    #  Define the Jacobi matrix.
    #
    bj = np.zeros(n)
    for i in range(0, n):
        bj[i] = np.sqrt(float(i + 1) / 2.0)

    x = np.zeros(n)

    w = np.zeros(n)
    w[0] = np.sqrt(zemu)
    #
    #  Diagonalize the Jacobi matrix.
    #
    x, w = imtqlx(n, x, bj, w)
    #
    #  If N is odd, force the center X to be exactly 0.
    #
    if ((n % 2) == 1):
        x[(n - 1) // 2] = 0.0

    for i in range(0, n):
        w[i] = w[i]**2

    return x, w