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

📄 tdist.c

📁 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY without ev
💻 C
字号:
/* cdf/tdist.c * * Copyright (C) 2002 Jason H. Stover. * * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. *//* * Computes the Student's t cumulative distribution function using * the method detailed in  *  * W.J. Kennedy and J.E. Gentle, "Statistical Computing." 1980.  * Marcel Dekker. ISBN 0-8247-6898-1. * * G.W. Hill and A.W. Davis. "Generalized asymptotic expansions * of Cornish-Fisher type." Annals of Mathematical Statistics,  * vol. 39, 1264-1273. 1968. * * G.W. Hill. "Algorithm 395: Student's t-distribution," Communications * of the ACM, volume 13, number 10, page 617. October 1970. * * G.W. Hill, "Remark on algorithm 395: Student's t-distribution," * Transactions on Mathematical Software, volume 7, number 2, page * 247. June 1982. */#include <config.h>#include <gsl/gsl_cdf.h>#include <gsl/gsl_sf_gamma.h>#include <gsl/gsl_math.h>#include <gsl/gsl_errno.h>#include "beta_inc.c"static doublepoly_eval (const double c[], unsigned int n, double x){  unsigned int i;  double y = c[0] * x;  for (i = 1; i < n; i++)    {      y = x * (y + c[i]);    }  y += c[n];  return y;}/*  * Use the Cornish-Fisher asymptotic expansion to find a point u such * that gsl_cdf_gauss(y) = tcdf(t). *  */static doublecornish_fisher (double t, double n){  const double coeffs6[10] = {    0.265974025974025974026,    5.449696969696969696970,    122.20294372294372294372,    2354.7298701298701298701,    37625.00902597402597403,    486996.1392857142857143,    4960870.65,    37978595.55,    201505390.875,    622437908.625  };  const double coeffs5[8] = {    0.2742857142857142857142,    4.499047619047619047619,    78.45142857142857142857,    1118.710714285714285714,    12387.6,    101024.55,    559494.0,    1764959.625  };  const double coeffs4[6] = {    0.3047619047619047619048,    3.752380952380952380952,    46.67142857142857142857,    427.5,    2587.5,    8518.5  };  const double coeffs3[4] = {    0.4,    3.3,    24.0,    85.5  };  double a = n - 0.5;  double b = 48.0 * a * a;  double z2 = a * log1p (t * t / n);  double z = sqrt (z2);  double p5 = z * poly_eval (coeffs6, 9, z2);  double p4 = -z * poly_eval (coeffs5, 7, z2);  double p3 = z * poly_eval (coeffs4, 5, z2);  double p2 = -z * poly_eval (coeffs3, 3, z2);  double p1 = z * (z2 + 3.0);  double p0 = z;  double y = p5;  y = (y / b) + p4;  y = (y / b) + p3;  y = (y / b) + p2;  y = (y / b) + p1;  y = (y / b) + p0;  if (t < 0)    y *= -1;  return y;}#if 0/* * Series approximation for t > 4.0. This needs to be fixed; * it shouldn't subtract the result from 1.0. A better way is * to use two different series expansions. Figuring this out * means rummaging through Fisher's paper in Metron, v5, 1926,  * "Expansion of Student's integral in powers of n^{-1}." */#define MAXI 40static doublenormal_approx (const double x, const double nu){  double y;  double num;  double diff;  double q;  int i;  double lg1, lg2;  y = 1 / sqrt (1 + x * x / nu);  num = 1.0;  q = 0.0;  diff = 2 * GSL_DBL_EPSILON;  for (i = 2; (i < MAXI) && (diff > GSL_DBL_EPSILON); i += 2)    {      diff = q;      num *= y * y * (i - 1) / i;      q += num / (nu + i);      diff = q - diff;    }  q += 1 / nu;  lg1 = gsl_sf_lngamma (nu / 2.0);  lg2 = gsl_sf_lngamma ((nu + 1.0) / 2.0);  diff = lg2 - lg1;  q *= pow (y, nu) * exp (diff) / sqrt (M_PI);  return q;}#endifdoublegsl_cdf_tdist_P (const double x, const double nu){  double P;  double x2 = x * x;  if (nu > 30 && x2 < 10 * nu)    {      double u = cornish_fisher (x, nu);      P = gsl_cdf_ugaussian_P (u);      return P;    }  if (x2 < nu)    {      double u = x2 / nu;      double eps = u / (1 + u);      if (x >= 0)        {          P = beta_inc_AXPY (0.5, 0.5, 0.5, nu / 2.0, eps);        }      else        {          P = beta_inc_AXPY (-0.5, 0.5, 0.5, nu / 2.0, eps);        }    }  else    {      double v = nu / (x * x);      double eps = v / (1 + v);      if (x >= 0)        {          P = beta_inc_AXPY (-0.5, 1.0, nu / 2.0, 0.5, eps);        }      else        {          P = beta_inc_AXPY (0.5, 0.0, nu / 2.0, 0.5, eps);        }    }  return P;}doublegsl_cdf_tdist_Q (const double x, const double nu){  double Q;  double x2 = x * x;  if (nu > 30 && x2 < 10 * nu)    {      double u = cornish_fisher (x, nu);      Q = gsl_cdf_ugaussian_Q (u);      return Q;    }  if (x2 < nu)    {      double u = x2 / nu;      double eps = u / (1 + u);      if (x >= 0)        {          Q = beta_inc_AXPY (-0.5, 0.5, 0.5, nu / 2.0, eps);        }      else        {          Q = beta_inc_AXPY (0.5, 0.5, 0.5, nu / 2.0, eps);        }    }  else    {      double v = nu / (x * x);      double eps = v / (1 + v);      if (x >= 0)        {          Q = beta_inc_AXPY (0.5, 0.0, nu / 2.0, 0.5, eps);        }      else        {          Q = beta_inc_AXPY (-0.5, 1.0, nu / 2.0, 0.5, eps);        }    }  return Q;}

⌨️ 快捷键说明

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