⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamma_inc.c

📁 该文件为c++的数学函数库!是一个非常有用的编程工具.它含有各种数学函数,为科学计算、工程应用等程序编写提供方便!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* specfunc/gamma_inc.c *  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Author:  G. Jungman */#include <config.h>#include <gsl/gsl_math.h>#include <gsl/gsl_errno.h>#include <gsl/gsl_sf_erf.h>#include <gsl/gsl_sf_exp.h>#include <gsl/gsl_sf_log.h>#include <gsl/gsl_sf_gamma.h>#include <gsl/gsl_sf_expint.h>#include "error.h"/* The dominant part, * D(a,x) := x^a e^(-x) / Gamma(a+1) */staticintgamma_inc_D(const double a, const double x, gsl_sf_result * result){  if(a < 10.0) {    double lnr;    gsl_sf_result lg;    gsl_sf_lngamma_e(a+1.0, &lg);    lnr = a * log(x) - x - lg.val;    result->val = exp(lnr);    result->err = 2.0 * GSL_DBL_EPSILON * (fabs(lnr) + 1.0) * fabs(result->val);    return GSL_SUCCESS;  }  else {    gsl_sf_result gstar;    gsl_sf_result ln_term;    double term1;    if (x < a) {      double u = x/a;      ln_term.val = log(u) - u + 1.0;      ln_term.err = ln_term.val * GSL_DBL_EPSILON;    } else {      double mu = (x-a)/a;      gsl_sf_log_1plusx_mx_e(mu, &ln_term);  /* log(1+mu) - mu */    };    gsl_sf_gammastar_e(a, &gstar);    term1 = exp(a*ln_term.val)/sqrt(2.0*M_PI*a);    result->val  = term1/gstar.val;    result->err  = 2.0 * GSL_DBL_EPSILON * (fabs(a*ln_term.val) + 1.0) * fabs(result->val);    result->err += gstar.err/fabs(gstar.val) * fabs(result->val);    return GSL_SUCCESS;  }    }/* P series representation. */staticintgamma_inc_P_series(const double a, const double x, gsl_sf_result * result){  const int nmax = 5000;  gsl_sf_result D;  int stat_D = gamma_inc_D(a, x, &D);  double sum  = 1.0;  double term = 1.0;  int n;  for(n=1; n<nmax; n++) {    term *= x/(a+n);    sum  += term;    if(fabs(term/sum) < GSL_DBL_EPSILON) break;  }  result->val  = D.val * sum;  result->err  = D.err * fabs(sum);  result->err += (1.0 + n) * GSL_DBL_EPSILON * fabs(result->val);  if(n == nmax)    GSL_ERROR ("error", GSL_EMAXITER);  else    return stat_D;}/* Q large x asymptotic */staticintgamma_inc_Q_large_x(const double a, const double x, gsl_sf_result * result){  const int nmax = 5000;  gsl_sf_result D;  const int stat_D = gamma_inc_D(a, x, &D);  double sum  = 1.0;  double term = 1.0;  double last = 1.0;  int n;  for(n=1; n<nmax; n++) {    term *= (a-n)/x;    if(fabs(term/last) > 1.0) break;    if(fabs(term/sum)  < GSL_DBL_EPSILON) break;    sum  += term;    last  = term;  }  result->val  = D.val * (a/x) * sum;  result->err  = D.err * fabs((a/x) * sum);  result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);  if(n == nmax)    GSL_ERROR ("error in large x asymptotic", GSL_EMAXITER);  else    return stat_D;}/* Uniform asymptotic for x near a, a and x large. * See [Temme, p. 285] * FIXME: need c1 coefficient */staticintgamma_inc_Q_asymp_unif(const double a, const double x, gsl_sf_result * result){  const double rta = sqrt(a);  const double eps = (x-a)/a;  gsl_sf_result ln_term;  const int stat_ln = gsl_sf_log_1plusx_mx_e(eps, &ln_term);  /* log(1+eps) - eps */  const double eta  = eps * sqrt(-2.0*ln_term.val/(eps*eps));  gsl_sf_result erfc;  double R;  double c0, c1;  gsl_sf_erfc_e(eta*M_SQRT2*rta, &erfc);  if(fabs(eps) < GSL_ROOT5_DBL_EPSILON) {    c0 = -1.0/3.0 + eps*(1.0/12.0 - eps*(23.0/540.0 - eps*(353.0/12960.0 - eps*589.0/30240.0)));    c1 = 0.0;  }  else {    double rt_term;    rt_term = sqrt(-2.0 * ln_term.val/(eps*eps));    c0 = (1.0 - 1.0/rt_term)/eps;    c1 = 0.0;  }  R = exp(-0.5*a*eta*eta)/(M_SQRT2*M_SQRTPI*rta) * (c0 + c1/a);  result->val  = 0.5 * erfc.val + R;  result->err  = GSL_DBL_EPSILON * fabs(R * 0.5 * a*eta*eta) + 0.5 * erfc.err;  result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);  return stat_ln;}/* Continued fraction which occurs in evaluation * of Q(a,x) or Gamma(a,x). * *              1   (1-a)/x  1/x  (2-a)/x   2/x  (3-a)/x *   F(a,x) =  ---- ------- ----- -------- ----- -------- ... *             1 +   1 +     1 +   1 +      1 +   1 + * * Hans E. Plesser, 2002-01-22 (hans dot plesser at itf dot nlh dot no). * * Split out from gamma_inc_Q_CF() by GJ [Tue Apr  1 13:16:41 MST 2003]. * See gamma_inc_Q_CF() below. * */static intgamma_inc_F_CF(const double a, const double x, gsl_sf_result * result){  const int    nmax  =  5000;  const double small =  gsl_pow_3 (GSL_DBL_EPSILON);  double hn = 1.0;           /* convergent */  double Cn = 1.0 / small;  double Dn = 1.0;  int n;  /* n == 1 has a_1, b_1, b_0 independent of a,x,      so that has been done by hand                */  for ( n = 2 ; n < nmax ; n++ )  {    double an;    double delta;    if(GSL_IS_ODD(n))      an = 0.5*(n-1)/x;    else      an = (0.5*n-a)/x;    Dn = 1.0 + an * Dn;    if ( fabs(Dn) < small )      Dn = small;    Cn = 1.0 + an/Cn;    if ( fabs(Cn) < small )      Cn = small;    Dn = 1.0 / Dn;    delta = Cn * Dn;    hn *= delta;    if(fabs(delta-1.0) < GSL_DBL_EPSILON) break;  }  result->val = hn;  result->err = 2.0*GSL_DBL_EPSILON * fabs(hn);  result->err += GSL_DBL_EPSILON * (2.0 + 0.5*n) * fabs(result->val);  if(n == nmax)    GSL_ERROR ("error in CF for F(a,x)", GSL_EMAXITER);  else    return GSL_SUCCESS;}/* Continued fraction for Q. * * Q(a,x) = D(a,x) a/x F(a,x) * * Hans E. Plesser, 2002-01-22 (hans dot plesser at itf dot nlh dot no): * * Since the Gautschi equivalent series method for CF evaluation may lead  * to singularities, I have replaced it with the modified Lentz algorithm * given in * * I J Thompson and A R Barnett * Coulomb and Bessel Functions of Complex Arguments and Order * J Computational Physics 64:490-509 (1986) * * In consequence, gamma_inc_Q_CF_protected() is now obsolete and has been  * removed.  * * Identification of terms between the above equation for F(a, x) and * the first equation in the appendix of Thompson&Barnett is as follows: * *    b_0 = 0, b_n = 1 for all n > 0 * *    a_1 = 1 *    a_n = (n/2-a)/x    for n even *    a_n = (n-1)/(2x)   for n odd * */staticintgamma_inc_Q_CF(const double a, const double x, gsl_sf_result * result){  gsl_sf_result D;  gsl_sf_result F;  const int stat_D = gamma_inc_D(a, x, &D);  const int stat_F = gamma_inc_F_CF(a, x, &F);  result->val  = D.val * (a/x) * F.val;  result->err  = D.err * fabs((a/x) * F.val) + fabs(D.val * a/x * F.err);  return GSL_ERROR_SELECT_2(stat_F, stat_D);}/* Useful for small a and x. Handles the subtraction analytically. */staticintgamma_inc_Q_series(const double a, const double x, gsl_sf_result * result){  double term1;  /* 1 - x^a/Gamma(a+1) */  double sum;    /* 1 + (a+1)/(a+2)(-x)/2! + (a+1)/(a+3)(-x)^2/3! + ... */  int stat_sum;  double term2;  /* a temporary variable used at the end */  {    /* Evaluate series for 1 - x^a/Gamma(a+1), small a     */    const double pg21 = -2.404113806319188570799476;  /* PolyGamma[2,1] */    const double lnx  = log(x);    const double el   = M_EULER+lnx;    const double c1 = -el;    const double c2 = M_PI*M_PI/12.0 - 0.5*el*el;    const double c3 = el*(M_PI*M_PI/12.0 - el*el/6.0) + pg21/6.0;    const double c4 = -0.04166666666666666667                       * (-1.758243446661483480 + lnx)                       * (-0.764428657272716373 + lnx)                       * ( 0.723980571623507657 + lnx)                       * ( 4.107554191916823640 + lnx);    const double c5 = -0.0083333333333333333                       * (-2.06563396085715900 + lnx)                       * (-1.28459889470864700 + lnx)                       * (-0.27583535756454143 + lnx)                       * ( 1.33677371336239618 + lnx)                       * ( 5.17537282427561550 + lnx);    const double c6 = -0.0013888888888888889                       * (-2.30814336454783200 + lnx)                       * (-1.65846557706987300 + lnx)                       * (-0.88768082560020400 + lnx)                       * ( 0.17043847751371778 + lnx)                       * ( 1.92135970115863890 + lnx)                       * ( 6.22578557795474900 + lnx);    const double c7 = -0.00019841269841269841                       * (-2.5078657901291800 + lnx)                       * (-1.9478900888958200 + lnx)                       * (-1.3194837322612730 + lnx)                       * (-0.5281322700249279 + lnx)                       * ( 0.5913834939078759 + lnx)                       * ( 2.4876819633378140 + lnx)                       * ( 7.2648160783762400 + lnx);    const double c8 = -0.00002480158730158730                       * (-2.677341544966400 + lnx)                       * (-2.182810448271700 + lnx)                       * (-1.649350342277400 + lnx)                       * (-1.014099048290790 + lnx)                       * (-0.191366955370652 + lnx)                       * ( 0.995403817918724 + lnx)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -