1 /* cdf/hypergeometric.c
3 * Copyright (C) 2004 Free Software Foundation, Inc.
4 * Written by Jason H. Stover.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * Computes the cumulative distribution function for a hypergeometric
23 * random variable. A hypergeometric random variable X is the number
24 * of elements of type 0 in a sample of size t, drawn from a population
25 * of size n1 + n0, in which n1 are of type 1 and n0 are of type 0.
27 * This algorithm computes Pr( X <= k ) by summing the terms from
28 * the mass function, Pr( X = k ).
32 * T. Wu. An accurate computation of the hypergeometric distribution
33 * function. ACM Transactions on Mathematical Software. Volume 19, number 1,
35 * This algorithm is not used, since it requires factoring the
36 * numerator and denominator, then cancelling. It is more accurate
37 * than the algorithm used here, but the cancellation requires more
38 * time than the algorithm used here.
40 * W. Feller. An Introduction to Probability Theory and Its Applications,
41 * third edition. 1968. Chapter 2, section 6.
44 #include <gsl/gsl_math.h>
45 #include <gsl/gsl_errno.h>
46 #include <gsl/gsl_cdf.h>
47 #include <gsl/gsl_randist.h>
48 #include "gsl-extras.h"
54 gslextras_cdf_hypergeometric_P (const unsigned int k,
55 const unsigned int n0,
56 const unsigned int n1,
67 GSLEXTRAS_CDF_ERROR("t larger than population size",GSL_EDOM);
69 else if( k >= n0 || k >= t)
80 mode = (int) t*n0 / (n0+n1);
86 while(i != UINT_MAX && relerr > GSL_DBL_EPSILON && P < 1.0)
88 tmp = gsl_ran_hypergeometric_pdf(i, n0, n1, t);
98 while(i <= k && relerr > GSL_DBL_EPSILON && P < 1.0)
100 tmp = gsl_ran_hypergeometric_pdf(i, n0, n1, t);
107 while( i != UINT_MAX && relerr > GSL_DBL_EPSILON && P < 1.0)
109 tmp = gsl_ran_hypergeometric_pdf(i, n0, n1, t);
116 * Hack to get rid of a pesky error when the sum
117 * gets slightly above 1.0.
119 P = GSL_MIN_DBL (P, 1.0);
128 gslextras_cdf_hypergeometric_Q (const unsigned int k,
129 const unsigned int n0,
130 const unsigned int n1,
131 const unsigned int t)
141 GSLEXTRAS_CDF_ERROR("t larger than population size",GSL_EDOM);
143 else if( k >= n0 || k >= t)
154 mode = (int) t*n0 / (n0+n1);
160 while( i <= t && relerr > GSL_DBL_EPSILON && P < 1.0)
162 tmp = gsl_ran_hypergeometric_pdf(i, n0, n1, t);
169 while ( i > k && relerr > GSL_DBL_EPSILON && P < 1.0)
171 tmp = gsl_ran_hypergeometric_pdf(i, n0, n1, t);
180 while(i <= t && relerr > GSL_DBL_EPSILON && P < 1.0)
182 tmp = gsl_ran_hypergeometric_pdf(i, n0, n1, t);
189 * Hack to get rid of a pesky error when the sum
190 * gets slightly above 1.0.
192 P = GSL_MIN_DBL(P, 1.0);