Skip to content

Commit 157b396

Browse files
author
maechler
committed
s/ goto / do while() /; local declarations
git-svn-id: https://svn.r-project.org/R/trunk@87974 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 886ba5f commit 157b396

File tree

1 file changed

+117
-89
lines changed

1 file changed

+117
-89
lines changed

src/nmath/rhyper.c

Lines changed: 117 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Mathlib : A C Library of Special Functions
3-
* Copyright (C) 2000-2020 The R Core Team
3+
* Copyright (C) 2000-2025 The R Core Team
44
* Copyright (C) 2005-2020 The R Foundation
55
* Copyright (C) 1998 Ross Ihaka
66
*
@@ -84,21 +84,6 @@ double rhyper(double nn1in, double nn2in, double kkin)
8484
{
8585
/* extern double afc(int); */
8686

87-
int nn1, nn2, kk;
88-
int ix; // return value (coerced to double at the very end)
89-
bool setup1, setup2;
90-
91-
/* These should become 'thread_local globals' : */
92-
static int ks = -1, n1s = -1, n2s = -1;
93-
static int m, minjx, maxjx;
94-
static int k, n1, n2; // <- not allowing larger integer par
95-
static double N;
96-
97-
// II :
98-
static double w;
99-
// III:
100-
static double a, d, s, xl, xr, kl, kr, lamdl, lamdr, p1, p2, p3;
101-
10287
/* check parameter validity */
10388

10489
if(!R_FINITE(nn1in) || !R_FINITE(nn2in) || !R_FINITE(kkin))
@@ -113,6 +98,9 @@ double rhyper(double nn1in, double nn2in, double kkin)
11398
if (nn1in >= INT_MAX || nn2in >= INT_MAX || kkin >= INT_MAX) {
11499
/* large n -- evade integer overflow (and inappropriate algorithms)
115100
-------- */
101+
#ifdef DEBUG_rhyper
102+
REprintf("rhyper(nn1=%.0f, nn2=%.0f, kk=%.0f): 'large n' case\n", nn1in, nn2in, kkin);
103+
#endif
116104
// FIXME: Much faster to give rbinom() approx when appropriate; -> see Kuensch(1989)
117105
// Johnson, Kotz,.. p.258 (top) mention the *four* different binomial approximations
118106
if(kkin == 1.) { // Bernoulli
@@ -123,10 +111,19 @@ double rhyper(double nn1in, double nn2in, double kkin)
123111
/*lower_tail =*/ false, /*log_p = */ false);
124112
// lower_tail=false: a thinko, is still "correct" as equiv. to U <--> 1-U
125113
}
126-
nn1 = (int)nn1in;
127-
nn2 = (int)nn2in;
128-
kk = (int)kkin;
129114

115+
int
116+
nn1 = (int)nn1in,
117+
nn2 = (int)nn2in,
118+
kk = (int)kkin;
119+
120+
/* These should become 'thread_local globals' : */
121+
static int ks = -1, n1s = -1, n2s = -1;
122+
static int m, minjx, maxjx;
123+
static int k, n1, n2; // <- not allowing larger integer par
124+
static double N;
125+
126+
bool setup1, setup2;
130127
/* if new parameter values, initialize */
131128
if (nn1 != n1s || nn2 != n2s) { // n1 | n2 is changed: setup all
132129
setup1 = true; setup2 = true;
@@ -152,6 +149,7 @@ double rhyper(double nn1in, double nn2in, double kkin)
152149
} else {
153150
k = kk;
154151
}
152+
// now have k < N/2 = (n1+n2)/2
155153
}
156154
if (setup1 || setup2) {
157155
m = (int) ((k + 1.) * (n1 + 1.) / (N + 2.)); // m := floor(adjusted mean E[.])
@@ -162,7 +160,14 @@ double rhyper(double nn1in, double nn2in, double kkin)
162160
nn1, nn2, kk, m, minjx, maxjx);
163161
#endif
164162
}
165-
/* generate random variate --- Three basic cases */
163+
#ifdef DEBUG_rhyper
164+
else
165+
REprintf("rhyper(n1=%d, n2=%d, k=%d); setup UNchanged\n", nn1, nn2, kk);
166+
#endif
167+
168+
// generate random variate --- Three basic cases ---------------------------
169+
170+
int ix; // return value (coerced to double at the very end) .. FIXME?? what if overflows
166171

167172
if (minjx == maxjx) { /* I: degenerate distribution ---------------- */
168173
#ifdef DEBUG_rhyper
@@ -174,20 +179,28 @@ double rhyper(double nn1in, double nn2in, double kkin)
174179
} else if (m - minjx < 10) { // II: (Scaled) algorithm HIN (inverse transformation) ----
175180
const static double scale = 1e25; // scaling factor against (early) underflow
176181
const static double con = 57.5646273248511421;
177-
// 25*log(10) = log(scale) { <==> exp(con) == scale }
182+
// 25*log(10) = log(scale) { <==> exp(con) == scale }
183+
static double w,
184+
lw; // = log(w); w = exp(lw) * scale = exp(lw + log(scale)) = exp(lw + con)
178185
if (setup1 || setup2) {
179-
double lw; // log(w); w = exp(lw) * scale = exp(lw + log(scale)) = exp(lw + con)
186+
// NB: n1 <= n2 here
180187
if (k < n2) {
181188
lw = afc(n2) + afc(n1 + n2 - k) - afc(n2 - k) - afc(n1 + n2);
182189
} else {
183190
lw = afc(n1) + afc( k ) - afc(k - n2) - afc(n1 + n2);
184191
}
185192
w = exp(lw + con);
186193
}
187-
double p, u;
194+
188195
#ifdef DEBUG_rhyper
189-
REprintf("rhyper(), branch II; w = %g > 0\n", w);
196+
REprintf(" branch II; w = %g %s\n", w,
197+
(w > 0) ? "> 0" : "= 0 <==> Underflow __NOT GOOD__");
190198
#endif
199+
if(w <= 0.)
200+
MATHLIB_ERROR(_("w = %g <= 0: Underflow in rhyper() SHOULD NOT HAPPEN!"), w);
201+
// FIXME: MM has code "rhyper.c+M3" for switching to log space if w == 0
202+
203+
double p, u;
191204
L10:
192205
p = w;
193206
ix = minjx;
@@ -210,40 +223,49 @@ double rhyper(double nn1in, double nn2in, double kkin)
210223

211224
} else { /* III : H2PE Algorithm --------------------------------------- */
212225

213-
double u,v;
214-
226+
static double a, xl, xr, lamdl, lamdr, p1, p2, p3;
215227
if (setup1 || setup2) {
216-
s = sqrt((N - k) * k * n1 * n2 / (N - 1) / N / N);
217-
218-
/* remark: d is defined in reference without int. */
219-
/* the truncation centers the cell boundaries at 0.5 */
228+
double
229+
s = sqrt((N - k) * k * n1 * n2 / (N - 1) / N / N),
220230

221-
d = (int) (1.5 * s) + .5;
231+
/* remark: d is defined in reference without int. */
232+
/* the truncation centers the cell boundaries at 0.5 */
233+
d = (int) (1.5 * s) + .5;
222234
xl = m - d + .5;
223235
xr = m + d + .5;
224236
a = afc(m) + afc(n1 - m) + afc(k - m) + afc(n2 - k + m);
225-
kl = exp(a - afc((int) (xl)) - afc((int) (n1 - xl))
226-
- afc((int) (k - xl))
227-
- afc((int) (n2 - k + xl)));
228-
kr = exp(a - afc((int) (xr - 1))
229-
- afc((int) (n1 - xr + 1))
230-
- afc((int) (k - xr + 1))
231-
- afc((int) (n2 - k + xr - 1)));
237+
double
238+
kl = exp(a - afc((int) (xl)) - afc((int) (n1 - xl))
239+
- afc((int) (k - xl))
240+
- afc((int) (n2 - k + xl))),
241+
kr = exp(a - afc((int) (xr - 1))
242+
- afc((int) (n1 - xr + 1))
243+
- afc((int) (k - xr + 1))
244+
- afc((int) (n2 - k + xr - 1)));
232245
lamdl = -log(xl * (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1));
233246
lamdr = -log((n1 - xr + 1) * (k - xr + 1) / xr / (n2 - k + xr));
234247
p1 = d + d;
235248
p2 = p1 + kl / lamdl;
236249
p3 = p2 + kr / lamdr;
237-
}
238250
#ifdef DEBUG_rhyper
239-
REprintf("rhyper(), branch III {accept/reject}: (xl,xr)= (%g,%g); (lamdl,lamdr)= (%g,%g)\n",
240-
xl, xr, lamdl,lamdr);
241-
REprintf("-------- p123= c(%g,%g,%g)\n", p1,p2, p3);
251+
REprintf("rhyper(), branch III {accept/reject}: (xl,xr)= (%g,%g); lamdl,r = (%g,%g)\n",
252+
xl, xr, lamdl, lamdr);
253+
REprintf(" --------> (p1,p2,p3) = (%g,%g,%g)\n", p1,p2,p3);
254+
}
255+
else
256+
REprintf("rhyper(), branch III {accept/reject}: NO setup needed; lamdl,r = (%g,%g)\n",
257+
lamdl, lamdr);
258+
#else
259+
}
242260
#endif
243-
int n_uv = 0;
244-
L30:
245-
u = unif_rand() * p3;
246-
v = unif_rand();
261+
262+
/* acceptance/rejection test */
263+
bool reject = true;
264+
int n_uv = 0;
265+
do { // L30: -------------- acceptance / rejection : loop while reject=true -------------
266+
double
267+
u = unif_rand() * p3,
268+
v = unif_rand();
247269
n_uv++;
248270
if(n_uv >= 10000) {
249271
REprintf("rhyper(*, n1=%d, n2=%d, k=%d): branch III: giving up after %d rejections\n",
@@ -256,20 +278,29 @@ double rhyper(double nn1in, double nn2in, double kkin)
256278

257279
if (u < p1) { /* rectangular region */
258280
ix = (int) (xl + u);
281+
#ifdef DEBUG_rhyper
282+
REprintf(" rectangular: ix=%d\n", ix);
283+
#endif
259284
} else if (u <= p2) { /* left tail */
260285
ix = (int) (xl + log(v) / lamdl);
286+
#ifdef DEBUG_rhyper
287+
REprintf(" left tail: ix=%d %s", ix, (ix < minjx)? "< minjx (=> L30)\n" : ">= minjx;");
288+
#endif
261289
if (ix < minjx)
262-
goto L30;
290+
continue; // goto L30
263291
v = v * (u - p1) * lamdl;
264292
} else { /* right tail */
265293
ix = (int) (xr - log(v) / lamdr);
294+
#ifdef DEBUG_rhyper
295+
REprintf(" right tail: ix=%d %s", ix, (ix > maxjx)? "> maxjx (=> L30)\n" : "< maxjx;");
296+
#endif
266297
if (ix > maxjx)
267-
goto L30;
298+
continue; // goto L30
268299
v = v * (u - p2) * lamdr;
269300
}
270-
271-
/* acceptance/rejection test */
272-
bool reject = true;
301+
#ifdef DEBUG_rhyper
302+
if(u >= p1) REprintf(" new v = %g\n", v);
303+
#endif
273304

274305
if (m < 100 || ix <= 50) {
275306
/* explicit evaluation */
@@ -278,15 +309,17 @@ double rhyper(double nn1in, double nn2in, double kkin)
278309
in the (m > ix) case, but the definition of the
279310
recurrence relation on p134 shows that the +1 is
280311
needed. */
281-
int i;
282312
double f = 1.0;
283313
if (m < ix) {
284-
for (i = m + 1; i <= ix; i++)
314+
for (int i = m + 1; i <= ix; i++)
285315
f = f * (n1 - i + 1) * (k - i + 1) / (n2 - k + i) / i;
286316
} else if (m > ix) {
287-
for (i = ix + 1; i <= m; i++)
317+
for (int i = ix + 1; i <= m; i++)
288318
f = f * i * (n2 - k + i) / (n1 - i + 1) / (k - i + 1);
289319
}
320+
#ifdef DEBUG_rhyper
321+
REprintf(" small m or ix: f = %g\n", f);
322+
#endif
290323
if (v <= f) {
291324
reject = false;
292325
}
@@ -295,55 +328,50 @@ double rhyper(double nn1in, double nn2in, double kkin)
295328
const static double deltal = 0.0078;
296329
const static double deltau = 0.0034;
297330

298-
double e, g, r, t, y;
299-
double de, dg, dr, ds, dt, gl, gu, nk, nm, ub;
300-
double xk, xm, xn, y1, ym, yn, yk, alv;
301-
302331
#ifdef DEBUG_rhyper
303332
REprintf(" ... accept/reject 'large' case v=%g\n", v);
304333
#endif
305334
/* squeeze using upper and lower bounds */
306-
y = ix;
307-
y1 = y + 1.0;
308-
ym = y - m;
309-
yn = n1 - y + 1.0;
310-
yk = k - y + 1.0;
311-
nk = n2 - k + y1;
312-
r = -ym / y1;
313-
s = ym / yn;
314-
t = ym / yk;
315-
e = -ym / nk;
316-
g = yn * yk / (y1 * nk) - 1.0;
317-
dg = 1.0;
318-
if (g < 0.0)
319-
dg = 1.0 + g;
320-
gu = g * (1.0 + g * (-0.5 + g / 3.0));
321-
gl = gu - .25 * (g * g * g * g) / dg;
322-
xm = m + 0.5;
323-
xn = n1 - m + 0.5;
324-
xk = k - m + 0.5;
325-
nm = n2 - k + xm;
326-
ub = y * gu - m * gl + deltau
335+
double
336+
y = ix,
337+
y1 = y + 1.0,
338+
ym = y - m,
339+
yn = n1 - y + 1.0,
340+
yk = k - y + 1.0,
341+
nk = n2 - k + y1,
342+
r = -ym / y1,
343+
s = ym / yn,
344+
t = ym / yk,
345+
e = -ym / nk,
346+
g = yn * yk / (y1 * nk) - 1.0,
347+
dg = (g < 0.0) ? 1. + g : 1.,
348+
gu = g * (1.0 + g * (-0.5 + g / 3.0)),
349+
gl = gu - .25 * (g * g * g * g) / dg,
350+
xm = m + 0.5,
351+
xn = n1 - m + 0.5,
352+
xk = k - m + 0.5,
353+
nm = n2 - k + xm,
354+
ub = y * gu - m * gl + deltau
327355
+ xm * r * (1. + r * (-0.5 + r / 3.0))
328356
+ xn * s * (1. + s * (-0.5 + s / 3.0))
329357
+ xk * t * (1. + t * (-0.5 + t / 3.0))
330358
+ nm * e * (1. + e * (-0.5 + e / 3.0));
331359
/* test against upper bound */
332-
alv = log(v);
360+
double alv = log(v);
333361
if (alv > ub) {
334362
reject = true;
335363
} else {
336-
/* test against lower bound */
337-
dr = xm * (r * r * r * r);
338-
if (r < 0.0)
364+
/* test against lower bound */
365+
double dr = xm * (r * r * r * r);
366+
if (r < 0.)
339367
dr /= (1.0 + r);
340-
ds = xn * (s * s * s * s);
368+
double ds = xn * (s * s * s * s);
341369
if (s < 0.0)
342370
ds /= (1.0 + s);
343-
dt = xk * (t * t * t * t);
371+
double dt = xk * (t * t * t * t);
344372
if (t < 0.0)
345373
dt /= (1.0 + t);
346-
de = nm * (e * e * e * e);
374+
double de = nm * (e * e * e * e);
347375
if (e < 0.0)
348376
de /= (1.0 + e);
349377
if (alv < ub - 0.25 * (dr + ds + dt + de)
@@ -361,9 +389,9 @@ double rhyper(double nn1in, double nn2in, double kkin)
361389
}
362390
}
363391
}
364-
} // else
365-
if (reject)
366-
goto L30;
392+
} // end{ III "large" }
393+
394+
} while (reject);
367395

368396
} // end{branch III}
369397

0 commit comments

Comments
 (0)