float liquid_gammaf(float _z) { if (_z < 0) { // use identities // (1) gamma(z)*gamma(-z) = -pi / (z*sin(pi*z)) // (2) z*gamma(z) = gamma(1+z) // // therefore: // gamma(z) = pi / ( gamma(1-z) * sin(pi*z) ) float t0 = liquid_gammaf(1.0 - _z); float t1 = sinf(M_PI*_z); if (t0==0 || t1==0) fprintf(stderr,"warning: liquid_gammaf(), divide by zero\n"); return M_PI / (t0 * t1); } else { return expf( liquid_lngammaf(_z) ); } }
// Gamma distribution cumulative distribution function // F(x) = gamma(a,x/b) / Gamma(a) // where // a = alpha, alpha > 0 // b = beta, beta > 0 // gamma(a,z) = lower incomplete gamma function // Gamma(z) = regular gamma function // float randgammaf_cdf(float _x, float _alpha, float _beta) { // validate input if (_alpha <= 0.0f) { fprintf(stderr,"error: randgammaf_cdf(), alpha must be greater than zero\n"); exit(1); } else if (_beta <= 0.0f) { fprintf(stderr,"error: randgammaf_cdf(), beta must be greater than zero\n"); exit(1); } if (_x <= 0.0f) return 0.0f; return liquid_lowergammaf(_alpha, _x/_beta) / liquid_gammaf(_alpha); }
// // AUTOTEST: Gamma // void autotest_gamma() { // error tolerance float tol = 1e-5f; // test vectors float v[12][2] = { {0.0001f, 9999.42288323161f }, {0.001f, 999.423772484595f }, {0.01f, 99.4325851191505f }, {0.1f, 9.51350769866873f }, {0.2f, 4.59084371199880f }, {0.5f, 1.77245385090552f }, {1.5f, 0.886226925452758f }, {2.5f, 1.329340388179140f }, {3.2f, 2.42396547993537f }, {4.1f, 6.81262286301667f }, {5.3f, 38.0779764499523f }, {12.0f, 39916800.0000000f }}; unsigned int i; for (i=0; i<12; i++) { // extract test vector float z = v[i][0]; float g = v[i][1]; // compute gamma float gamma = liquid_gammaf(z); // compute relative error float error = fabsf(gamma-g) / fabsf(g); // print results if (liquid_autotest_verbose) printf(" gamma(%12.4e) = %12.4e (expected %12.4e) %12.4e\n", z, gamma, g, error); // run test CONTEND_LESS_THAN(error, tol); } }
// Gamma distribution cumulative distribution function // x^(a-1) exp{-x/b) // f(x) = ------------------- // Gamma(a) b^a // where // a = alpha, a > 0 // b = beta, b > 0 // Gamma(z) = regular gamma function // x >= 0 float randgammaf_pdf(float _x, float _alpha, float _beta) { // validate input if (_alpha <= 0.0f) { fprintf(stderr,"error: randgammaf_pdf(), alpha must be greater than zero\n"); exit(1); } else if (_beta <= 0.0f) { fprintf(stderr,"error: randgammaf_pdf(), beta must be greater than zero\n"); exit(1); } if (_x <= 0.0f) return 0.0f; float t0 = powf(_x, _alpha-1.0f); float t1 = expf(-_x / _beta); float t2 = liquid_gammaf(_alpha); float t3 = powf(_beta, _alpha); return (t0*t1)/(t2*t3); }
// compute _n! float liquid_factorialf(unsigned int _n) { return fabsf(liquid_gammaf((float)(_n+1))); }
// ln( Gamma(z,alpha) ) : upper incomplete gamma function float liquid_lnuppergammaf(float _z, float _alpha) { return logf( liquid_gammaf(_z) - liquid_lowergammaf(_z,_alpha) ); }