Rev 2 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Langage for Statistical Data Analysis* Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka** 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.*//** References:** [1] Shape parameter a >= 1. Algorithm GD in:** Ahrens, J.H. and Dieter, U. (1982).* Generating gamma variates by a modified* rejection technique.* Comm. ACM, 25, 47-54.*** [2] Shape parameter 0 < a < 1. Algorithm GS in:** Ahrens, J.H. and Dieter, U. (1974).* Computer methods for sampling from gamma, beta,* poisson and binomial distributions.* Computing, 12, 223-246. C** Input: a = parameter (mean) of the standard gamma distribution.* Output: a variate from the gamma(a)-distribution** Coefficients q(k) - for q0 = sum(q(k)*a**(-k))* Coefficients a(k) - for q = q0+(t*t/2)*sum(a(k)*v**k)* Coefficients e(k) - for exp(q)-1 = sum(e(k)*q**k)*/#include "Mathlib.h"static double a1 = 0.3333333;static double a2 = -0.250003;static double a3 = 0.2000062;static double a4 = -0.1662921;static double a5 = 0.1423657;static double a6 = -0.1367177;static double a7 = 0.1233795;static double e1 = 1.0;static double e2 = 0.4999897;static double e3 = 0.166829;static double e4 = 0.0407753;static double e5 = 0.010293;static double q1 = 0.04166669;static double q2 = 0.02083148;static double q3 = 0.00801191;static double q4 = 0.00144121;static double q5 = -7.388e-5;static double q6 = 2.4511e-4;static double q7 = 2.424e-4;static double sqrt32 = 5.656854;static double aa = 0.;static double aaa = 0.;#define repeat for(;;)double rgamma(double a, double scale){static double b, c, d, e, p, q, r, s, t, u, v, w, x;static double q0, s2, si;double ret_val;if (a < 1.0) {/* alternate method for parameters a below 1 *//* 0.36787944117144232159 = exp(-1) */aa = 0.0;b = 1.0 + 0.36787944117144232159 * a;repeat {p = b * sunif();if (p >= 1.0) {ret_val = -log((b - p) / a);if (sexp() >= (1.0 - a) * log(ret_val))break;} else {ret_val = exp(log(p) / a);if (sexp() >= ret_val)break;}}return scale * ret_val;}/* Step 1: Recalculations of s2, s, d if a has changed */if (a != aa) {aa = a;s2 = a - 0.5;s = sqrt(s2);d = sqrt32 - s * 12.0;}/* Step 2: t = standard normal deviate, *//* x = (s,1/2)-normal deviate. *//* immediate acceptance (i) */t = snorm();x = s + 0.5 * t;ret_val = x * x;if (t >= 0.0)return scale * ret_val;/* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */u = sunif();if (d * u <= t * t * t) {return scale * ret_val;}/* Step 4: recalculations of q0, b, si, c if necessary */if (a != aaa) {aaa = a;r = 1.0 / a;q0 = ((((((q7 * r + q6) * r + q5) * r + q4)* r + q3) * r + q2) * r + q1) * r;/* Approximation depending on size of parameter a *//* The constants in the expressions for b, si and *//* c were established by numerical experiments */if (a <= 3.686) {b = 0.463 + s + 0.178 * s2;si = 1.235;c = 0.195 / s - 0.079 + 0.16 * s;} else if (a <= 13.022) {b = 1.654 + 0.0076 * s2;si = 1.68 / s + 0.275;c = 0.062 / s + 0.024;} else {b = 1.77;si = 0.75;c = 0.1515 / s;}}/* Step 5: no quotient test if x not positive */if (x > 0.0) {/* Step 6: calculation of v and quotient q */v = t / (s + s);if (fabs(v) <= 0.25)q = q0 + 0.5 * t * t * ((((((a7 * v + a6)* v + a5) * v + a4) * v + a3)* v + a2) * v + a1) * v;elseq = q0 - s * t + 0.25 * t * t + (s2 + s2)* log(1.0 + v);/* Step 7: quotient acceptance (q) */if (log(1.0 - u) <= q)return scale * ret_val;}/* Step 8: e = standard exponential deviate *//* u= 0,1 -uniform deviate *//* t=(b,si)-double exponential (laplace) sample */repeat {e = sexp();u = sunif();u = u + u - 1.0;if (u < 0.0)t = b - si * e;elset = b + si * e;/* Step 9: rejection if t < tau(1) = -0.71874483771719 */if (t >= -0.71874483771719) {/* Step 10: calculation of v and quotient q */v = t / (s + s);if (fabs(v) <= 0.25)q = q0 + 0.5 * t * t * ((((((a7 * v + a6)* v + a5) * v + a4) * v + a3)* v + a2) * v + a1) * v;elseq = q0 - s * t + 0.25 * t * t + (s2 + s2)* log(1.0 + v);/* Step 11: hat acceptance (h) *//* (if q not positive go to step 8) */if (q > 0.0) {if (q <= 0.5)w = ((((e5 * q + e4) * q + e3)* q + e2) * q + e1) * q;elsew = exp(q) - 1.0;/* if t is rejected *//* sample again at step 8 */if (c * fabs(u) <= w * exp(e - 0.5 * t * t))break;}}}x = s + 0.5 * t;return scale * x * x;}