/src/r-source/src/nmath/rgamma.c
Line | Count | Source |
1 | | /* |
2 | | * Mathlib : A C Library of Special Functions |
3 | | * Copyright (C) 2000--2024 The R Core Team |
4 | | * Copyright (C) 1998 Ross Ihaka |
5 | | * |
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 |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, a copy is available at |
18 | | * https://www.R-project.org/Licenses/ |
19 | | * |
20 | | * SYNOPSIS |
21 | | * |
22 | | * #include <Rmath.h> |
23 | | * double rgamma(double a, double scale); |
24 | | * |
25 | | * DESCRIPTION |
26 | | * |
27 | | * Random variates from the gamma distribution. |
28 | | * |
29 | | * REFERENCES |
30 | | * |
31 | | * [1] Shape parameter a >= 1. Algorithm GD in: |
32 | | * |
33 | | * Ahrens, J.H. and Dieter, U. (1982). |
34 | | * Generating gamma variates by a modified |
35 | | * rejection technique. |
36 | | * Comm. ACM, 25, 47-54. |
37 | | * |
38 | | * |
39 | | * [2] Shape parameter 0 < a < 1. Algorithm GS in: |
40 | | * |
41 | | * Ahrens, J.H. and Dieter, U. (1974). |
42 | | * Computer methods for sampling from gamma, beta, |
43 | | * poisson and binomial distributions. |
44 | | * Computing, 12, 223-246. |
45 | | * |
46 | | * Input : a = 'shape' = alpha, |
47 | | * scale = 'scale' = 1/rate of the gamma distribution w/ mean E[.] = a * scale |
48 | | * Output: a variate from the gamma(a, scale)-distribution |
49 | | */ |
50 | | |
51 | | #include "nmath.h" |
52 | | |
53 | 0 | #define repeat for(;;) |
54 | | |
55 | | double rgamma(double a, double scale) |
56 | 0 | { |
57 | | /* Constants : */ |
58 | 0 | const static double sqrt32 = 5.656854; |
59 | 0 | const static double exp_m1 = 0.36787944117144232159;/* exp(-1) = 1/e */ |
60 | | |
61 | | /* Coefficients q[k] - for q0 = sum(q[k]*a^(-k)) |
62 | | * Coefficients a[k] - for q = q0+(t*t/2)*sum(a[k]*v^k) |
63 | | * Coefficients e[k] - for exp(q)-1 = sum(e[k]*q^k) |
64 | | */ |
65 | 0 | const static double q1 = 0.04166669; |
66 | 0 | const static double q2 = 0.02083148; |
67 | 0 | const static double q3 = 0.00801191; |
68 | 0 | const static double q4 = 0.00144121; |
69 | 0 | const static double q5 = -7.388e-5; |
70 | 0 | const static double q6 = 2.4511e-4; |
71 | 0 | const static double q7 = 2.424e-4; |
72 | |
|
73 | 0 | const static double a1 = 0.3333333; |
74 | 0 | const static double a2 = -0.250003; |
75 | 0 | const static double a3 = 0.2000062; |
76 | 0 | const static double a4 = -0.1662921; |
77 | 0 | const static double a5 = 0.1423657; |
78 | 0 | const static double a6 = -0.1367177; |
79 | 0 | const static double a7 = 0.1233795; |
80 | | |
81 | | /* State variables [FIXME for threading!] :*/ |
82 | 0 | static double aa = 0.; |
83 | 0 | static double aaa = 0.; |
84 | 0 | static double s, s2, d; /* no. 1 (step 1) */ |
85 | 0 | static double q0, b, si, c;/* no. 2 (step 4) */ |
86 | |
|
87 | 0 | double e, p, q, r, t, u, v, w, x, ret_val; |
88 | |
|
89 | 0 | if (ISNAN(a) || ISNAN(scale)) |
90 | 0 | ML_WARN_return_NAN; |
91 | 0 | if (a <= 0.0 || scale <= 0.0) { |
92 | 0 | if(scale == 0. || a == 0.) return 0.; |
93 | 0 | ML_WARN_return_NAN; |
94 | 0 | } |
95 | 0 | if(!R_FINITE(a) || !R_FINITE(scale)) return ML_POSINF; |
96 | | |
97 | 0 | if (a < 1.) { /* GS algorithm for parameters a < 1 */ |
98 | 0 | e = 1.0 + exp_m1 * a; |
99 | 0 | repeat { |
100 | 0 | p = e * unif_rand(); |
101 | 0 | if (p >= 1.0) { |
102 | 0 | x = -log((e - p) / a); |
103 | 0 | if (exp_rand() >= (1.0 - a) * log(x)) |
104 | 0 | break; |
105 | 0 | } else { /* p < 1 <==> log(p) < 0 */ |
106 | 0 | x = exp(log(p) / a); // exp(*) "often" underflows to 0 for small a (e.g. a = 1/1000) |
107 | 0 | if (exp_rand() >= x) |
108 | 0 | break; |
109 | 0 | } |
110 | 0 | } |
111 | 0 | return scale * x; |
112 | 0 | } |
113 | | |
114 | | /* --- a >= 1 : GD algorithm --- */ |
115 | | |
116 | | /* Step 1: Recalculations of s2, s, d if a has changed */ |
117 | 0 | if (a != aa) { |
118 | 0 | aa = a; |
119 | 0 | s2 = a - 0.5; |
120 | 0 | s = sqrt(s2); |
121 | 0 | d = sqrt32 - s * 12.0; |
122 | 0 | } |
123 | | /* Step 2: t = standard normal deviate, |
124 | | x = (s,1/2) -normal deviate. */ |
125 | | |
126 | | /* immediate acceptance (i) */ |
127 | 0 | t = norm_rand(); |
128 | 0 | x = s + 0.5 * t; |
129 | 0 | ret_val = x * x; |
130 | 0 | if (t >= 0.0) |
131 | 0 | return scale * ret_val; |
132 | | |
133 | | /* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */ |
134 | 0 | u = unif_rand(); |
135 | 0 | if (d * u <= t * t * t) |
136 | 0 | return scale * ret_val; |
137 | | |
138 | | /* Step 4: recalculations of q0, b, si, c if necessary */ |
139 | | |
140 | 0 | if (a != aaa) { |
141 | 0 | aaa = a; |
142 | 0 | r = 1.0 / a; |
143 | 0 | q0 = ((((((q7 * r + q6) * r + q5) * r + q4) * r + q3) * r |
144 | 0 | + q2) * r + q1) * r; |
145 | | |
146 | | /* Approximation depending on size of parameter a */ |
147 | | /* The constants in the expressions for b, si and c */ |
148 | | /* were established by numerical experiments */ |
149 | |
|
150 | 0 | if (a <= 3.686) { |
151 | 0 | b = 0.463 + s + 0.178 * s2; |
152 | 0 | si = 1.235; |
153 | 0 | c = 0.195 / s - 0.079 + 0.16 * s; |
154 | 0 | } else if (a <= 13.022) { |
155 | 0 | b = 1.654 + 0.0076 * s2; |
156 | 0 | si = 1.68 / s + 0.275; |
157 | 0 | c = 0.062 / s + 0.024; |
158 | 0 | } else { |
159 | 0 | b = 1.77; |
160 | 0 | si = 0.75; |
161 | 0 | c = 0.1515 / s; |
162 | 0 | } |
163 | 0 | } |
164 | | /* Step 5: no quotient test if x not positive */ |
165 | |
|
166 | 0 | if (x > 0.0) { |
167 | | /* Step 6: calculation of v and quotient q */ |
168 | 0 | v = t / (s + s); |
169 | 0 | if (fabs(v) <= 0.25) |
170 | 0 | q = q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v |
171 | 0 | + a3) * v + a2) * v + a1) * v; |
172 | 0 | else |
173 | 0 | q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v); |
174 | | |
175 | | |
176 | | /* Step 7: quotient acceptance (q) */ |
177 | 0 | if (log(1.0 - u) <= q) |
178 | 0 | return scale * ret_val; |
179 | 0 | } |
180 | | |
181 | 0 | repeat { |
182 | | /* Step 8: e = standard exponential deviate |
183 | | * u = 0,1 -uniform deviate |
184 | | * t = (b,si)-double exponential (laplace) sample */ |
185 | 0 | e = exp_rand(); |
186 | 0 | u = unif_rand(); |
187 | 0 | u = u + u - 1.0; |
188 | 0 | if (u < 0.0) |
189 | 0 | t = b - si * e; |
190 | 0 | else |
191 | 0 | t = b + si * e; |
192 | | /* Step 9: rejection if t < tau(1) = -0.71874483771719 */ |
193 | 0 | if (t >= -0.71874483771719) { |
194 | | /* Step 10: calculation of v and quotient q */ |
195 | 0 | v = t / (s + s); |
196 | 0 | if (fabs(v) <= 0.25) |
197 | 0 | q = q0 + 0.5 * t * t * |
198 | 0 | ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v |
199 | 0 | + a2) * v + a1) * v; |
200 | 0 | else |
201 | 0 | q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v); |
202 | | /* Step 11: hat acceptance (h) */ |
203 | | /* (if q not positive go to step 8) */ |
204 | 0 | if (q > 0.0) { |
205 | 0 | w = expm1(q); |
206 | | /* ^^^^^ original code had approximation with rel.err < 2e-7 */ |
207 | | /* if t is rejected sample again at step 8 */ |
208 | 0 | if (c * fabs(u) <= w * exp(e - 0.5 * t * t)) |
209 | 0 | break; |
210 | 0 | } |
211 | 0 | } |
212 | 0 | } /* repeat .. until `t' is accepted */ |
213 | 0 | x = s + 0.5 * t; |
214 | 0 | return scale * x * x; |
215 | 0 | } |