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
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
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
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
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
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
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
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