/src/r-source/src/main/RNG.c
Line | Count | Source |
1 | | /* |
2 | | * R : A Computer Language for Statistical Data Analysis |
3 | | * Copyright (C) 1997--2026 The R Core Team |
4 | | * Copyright (C) 1995, 1996 Robert Gentleman and 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 | | |
21 | | |
22 | | #ifdef HAVE_CONFIG_H |
23 | | #include <config.h> |
24 | | #endif |
25 | | |
26 | | #include <Defn.h> |
27 | | #include <Internal.h> |
28 | | #include <R_ext/Random.h> |
29 | | |
30 | | /* Normal generator is not actually set here but in ../nmath/snorm.c */ |
31 | 0 | #define RNG_DEFAULT MERSENNE_TWISTER |
32 | 0 | #define N01_DEFAULT INVERSION |
33 | 0 | #define Sample_DEFAULT REJECTION |
34 | 0 | #define Binom_DEFAULT BTPE |
35 | | |
36 | | |
37 | | #include <R_ext/Rdynload.h> |
38 | | |
39 | | static DL_FUNC User_unif_fun, User_unif_nseed, |
40 | | User_unif_seedloc; |
41 | | typedef void (*UnifInitFun)(Int32); |
42 | | |
43 | | UnifInitFun User_unif_init = NULL; /* some picky compilers */ |
44 | | |
45 | | DL_FUNC User_norm_fun = NULL; /* also in ../nmath/snorm.c */ |
46 | | |
47 | | static RNGtype RNG_kind = RNG_DEFAULT; |
48 | | #include "nmath2.h" /* ../nmath/nmath2.h : */ |
49 | | // extern N01type N01_kind; /* from ../nmath/snorm.c */ |
50 | | // extern double BM_norm_keep; /* ../nmath/snorm.c */ |
51 | | // extern Binomtype Binom_kind ; /* ../nmath/rbinom.c */ |
52 | | static Sampletype Sample_kind = Sample_DEFAULT; |
53 | | |
54 | | |
55 | | |
56 | | /* typedef unsigned int Int32; in Random.h */ |
57 | | |
58 | | /* .Random.seed == (RNGkind, i_seed[0],i_seed[1],..,i_seed[n_seed-1]) |
59 | | * or == (RNGkind) or missing [--> Randomize] |
60 | | * where RNGkind := RNG_kind + 100 * N01_kind + 10000 * Sample_kind + 100'000 * Binom_kind |
61 | | * currently in outer(outer(outer(0:7, 100*(0:5), "+"), 10000*(0:1), "+"), 100000*(0:1), "+") |
62 | | */ |
63 | | |
64 | | typedef struct { |
65 | | RNGtype kind; |
66 | | N01type Nkind; |
67 | | char *name; /* print name */ |
68 | | int n_seed; /* length of seed vector */ |
69 | | Int32 *i_seed; |
70 | | } RNGTAB; |
71 | | |
72 | | |
73 | | static Int32 dummy[628]; // allow for optimizing compilers to read over bound |
74 | | static |
75 | | RNGTAB RNG_Table[] = |
76 | | { |
77 | | /* kind Nkind name n_seed i_seed */ |
78 | | { WICHMANN_HILL, BUGGY_KINDERMAN_RAMAGE, "Wichmann-Hill", 3, dummy}, |
79 | | { MARSAGLIA_MULTICARRY, BUGGY_KINDERMAN_RAMAGE, "Marsaglia-MultiCarry", 2, dummy}, |
80 | | { SUPER_DUPER, BUGGY_KINDERMAN_RAMAGE, "Super-Duper", 2, dummy}, |
81 | | { MERSENNE_TWISTER, BUGGY_KINDERMAN_RAMAGE, "Mersenne-Twister", 1+624, dummy}, |
82 | | { KNUTH_TAOCP, BUGGY_KINDERMAN_RAMAGE, "Knuth-TAOCP", 1+100, dummy}, |
83 | | { USER_UNIF, BUGGY_KINDERMAN_RAMAGE, "User-supplied", 0, dummy}, |
84 | | { KNUTH_TAOCP2, BUGGY_KINDERMAN_RAMAGE, "Knuth-TAOCP-2002", 1+100, dummy}, |
85 | | { LECUYER_CMRG, BUGGY_KINDERMAN_RAMAGE, "L'Ecuyer-CMRG", 6, dummy}, |
86 | | }; |
87 | | |
88 | | |
89 | | #define d2_32 4294967296./* = (double) */ |
90 | 0 | #define i2_32m1 2.328306437080797e-10/* = 1/(2^32 - 1) */ |
91 | 0 | #define KT 9.31322574615479e-10 /* = 2^-30 */ |
92 | | |
93 | 0 | #define I1 (RNG_Table[RNG_kind].i_seed[0]) |
94 | 0 | #define I2 (RNG_Table[RNG_kind].i_seed[1]) |
95 | 0 | #define I3 (RNG_Table[RNG_kind].i_seed[2]) |
96 | | |
97 | | static void Randomize(RNGtype kind); |
98 | | static double MT_genrand(void); |
99 | | static Int32 KT_next(void); |
100 | | static void RNG_Init_R_KT(Int32); |
101 | | static void RNG_Init_KT2(Int32); |
102 | 0 | #define KT_pos (RNG_Table[KNUTH_TAOCP].i_seed[100]) |
103 | | |
104 | | static double fixup(double x) |
105 | 0 | { |
106 | | /* ensure 0 and 1 are never returned */ |
107 | 0 | if(x <= 0.0) return 0.5*i2_32m1; |
108 | 0 | if((1.0 - x) <= 0.0) return 1.0 - 0.5*i2_32m1; |
109 | 0 | return x; |
110 | 0 | } |
111 | | |
112 | | |
113 | | double unif_rand(void) |
114 | 0 | { |
115 | 0 | double value; |
116 | |
|
117 | 0 | switch(RNG_kind) { |
118 | | |
119 | 0 | case WICHMANN_HILL: |
120 | 0 | I1 = I1 * 171 % 30269; |
121 | 0 | I2 = I2 * 172 % 30307; |
122 | 0 | I3 = I3 * 170 % 30323; |
123 | 0 | value = I1 / 30269.0 + I2 / 30307.0 + I3 / 30323.0; |
124 | 0 | return fixup(value - (int) value);/* in [0,1) */ |
125 | | |
126 | 0 | case MARSAGLIA_MULTICARRY:/* 0177777(octal) == 65535(decimal)*/ |
127 | 0 | I1= 36969*(I1 & 0177777) + (I1>>16); |
128 | 0 | I2= 18000*(I2 & 0177777) + (I2>>16); |
129 | 0 | return fixup(((I1 << 16)^(I2 & 0177777)) * i2_32m1); /* in [0,1) */ |
130 | | |
131 | 0 | case SUPER_DUPER: |
132 | | /* This is Reeds et al (1984) implementation; |
133 | | * modified using __unsigned__ seeds instead of signed ones |
134 | | */ |
135 | 0 | I1 ^= ((I1 >> 15) & 0377777); /* Tausworthe */ |
136 | 0 | I1 ^= I1 << 17; |
137 | 0 | I2 *= 69069; /* Congruential */ |
138 | 0 | return fixup((I1^I2) * i2_32m1); /* in [0,1) */ |
139 | | |
140 | 0 | case MERSENNE_TWISTER: |
141 | 0 | return fixup(MT_genrand()); |
142 | | |
143 | 0 | case KNUTH_TAOCP: |
144 | 0 | case KNUTH_TAOCP2: |
145 | 0 | return fixup(KT_next() * KT); |
146 | | |
147 | 0 | case USER_UNIF: |
148 | 0 | return *((double *) User_unif_fun()); |
149 | | |
150 | 0 | case LECUYER_CMRG: |
151 | 0 | { |
152 | | /* Based loosely on the GPL-ed version of |
153 | | http://www.iro.umontreal.ca/~lecuyer/myftp/streams00/c2010/RngStream.c |
154 | | but using int_least64_t, which C99 guarantees. |
155 | | */ |
156 | 0 | int k; |
157 | 0 | int_least64_t p1, p2; |
158 | |
|
159 | 0 | #define II(i) (RNG_Table[RNG_kind].i_seed[i]) |
160 | 0 | #define m1 4294967087 |
161 | 0 | #define m2 4294944443 |
162 | 0 | #define normc 2.328306549295727688e-10 |
163 | 0 | #define a12 (int_least64_t)1403580 |
164 | 0 | #define a13n (int_least64_t)810728 |
165 | 0 | #define a21 (int_least64_t)527612 |
166 | 0 | #define a23n (int_least64_t)1370589 |
167 | |
|
168 | 0 | p1 = a12 * (unsigned int)II(1) - a13n * (unsigned int)II(0); |
169 | | /* p1 % m1 would surely do */ |
170 | 0 | k = (int) (p1 / m1); |
171 | 0 | p1 -= k * m1; |
172 | 0 | if (p1 < 0) p1 += m1; |
173 | 0 | II(0) = II(1); II(1) = II(2); II(2) = (int) p1; |
174 | |
|
175 | 0 | p2 = a21 * (unsigned int)II(5) - a23n * (unsigned int)II(3); |
176 | 0 | k = (int) (p2 / m2); |
177 | 0 | p2 -= k * m2; |
178 | 0 | if (p2 < 0) p2 += m2; |
179 | 0 | II(3) = II(4); II(4) = II(5); II(5) = (int) p2; |
180 | |
|
181 | 0 | return (double)((p1 > p2) ? (p1 - p2) : (p1 - p2 + m1)) * normc; |
182 | 0 | } |
183 | 0 | default: |
184 | 0 | error(_("unif_rand: unimplemented RNG kind %d"), RNG_kind); |
185 | 0 | return -1.; |
186 | 0 | } |
187 | 0 | } |
188 | | |
189 | | /* we must mask global variable here, as I1-I3 hide RNG_kind |
190 | | and we want the argument */ |
191 | | static void FixupSeeds(RNGtype RNG_kind, int initial) |
192 | 0 | { |
193 | | /* Depending on RNG, set 0 values to non-0, etc. */ |
194 | |
|
195 | 0 | int j, notallzero = 0; |
196 | | |
197 | | /* Set 0 to 1 : |
198 | | for(j = 0; j <= RNG_Table[RNG_kind].n_seed - 1; j++) |
199 | | if(!RNG_Table[RNG_kind].i_seed[j]) RNG_Table[RNG_kind].i_seed[j]++; */ |
200 | |
|
201 | 0 | switch(RNG_kind) { |
202 | 0 | case WICHMANN_HILL: |
203 | 0 | I1 = I1 % 30269; I2 = I2 % 30307; I3 = I3 % 30323; |
204 | | |
205 | | /* map values equal to 0 mod modulus to 1. */ |
206 | 0 | if(I1 == 0) I1 = 1; |
207 | 0 | if(I2 == 0) I2 = 1; |
208 | 0 | if(I3 == 0) I3 = 1; |
209 | 0 | return; |
210 | | |
211 | 0 | case SUPER_DUPER: |
212 | 0 | if(I1 == 0) I1 = 1; |
213 | | /* I2 = Congruential: must be ODD */ |
214 | 0 | I2 |= 1; |
215 | 0 | break; |
216 | | |
217 | 0 | case MARSAGLIA_MULTICARRY: |
218 | 0 | if(I1 == 0) I1 = 1; |
219 | 0 | if(I2 == 0) I2 = 1; |
220 | 0 | break; |
221 | | |
222 | 0 | case MERSENNE_TWISTER: |
223 | 0 | if(initial) I1 = 624; |
224 | | /* No action unless user has corrupted .Random.seed */ |
225 | 0 | if(I1 <= 0) I1 = 624; |
226 | | /* check for all zeroes */ |
227 | 0 | for (j = 1; j <= 624; j++) |
228 | 0 | if(RNG_Table[RNG_kind].i_seed[j] != 0) { |
229 | 0 | notallzero = 1; |
230 | 0 | break; |
231 | 0 | } |
232 | 0 | if(!notallzero) Randomize(RNG_kind); |
233 | 0 | break; |
234 | | |
235 | 0 | case KNUTH_TAOCP: |
236 | 0 | case KNUTH_TAOCP2: |
237 | 0 | if(KT_pos <= 0) KT_pos = 100; |
238 | | /* check for all zeroes */ |
239 | 0 | for (j = 0; j < 100; j++) |
240 | 0 | if(RNG_Table[RNG_kind].i_seed[j] != 0) { |
241 | 0 | notallzero = 1; |
242 | 0 | break; |
243 | 0 | } |
244 | 0 | if(!notallzero) Randomize(RNG_kind); |
245 | 0 | break; |
246 | 0 | case USER_UNIF: |
247 | 0 | break; |
248 | 0 | case LECUYER_CMRG: |
249 | | /* first set: not all zero, in [0, m1) |
250 | | second set: not all zero, in [0, m2) */ |
251 | 0 | { |
252 | 0 | unsigned int tmp; |
253 | 0 | int allOK = 1; |
254 | 0 | for (j = 0; j < 3; j++) { |
255 | 0 | tmp = RNG_Table[RNG_kind].i_seed[j]; |
256 | 0 | if(tmp != 0) notallzero = 1; |
257 | 0 | if (tmp >= m1) allOK = 0; |
258 | 0 | } |
259 | 0 | if(!notallzero || !allOK) Randomize(RNG_kind); |
260 | 0 | for (j = 3; j < 6; j++) { |
261 | 0 | tmp = RNG_Table[RNG_kind].i_seed[j]; |
262 | 0 | if(tmp != 0) notallzero = 1; |
263 | 0 | if (tmp >= m2) allOK = 0; |
264 | 0 | } |
265 | 0 | if(!notallzero || !allOK) Randomize(RNG_kind); |
266 | 0 | } |
267 | 0 | break; |
268 | 0 | default: |
269 | 0 | error(_("FixupSeeds: unimplemented RNG kind %d"), RNG_kind); |
270 | 0 | } |
271 | 0 | } |
272 | | |
273 | | static void RNG_Init(RNGtype kind, Int32 seed) |
274 | 0 | { |
275 | 0 | int j; |
276 | |
|
277 | 0 | BM_norm_keep = 0.0; /* zap Box-Muller history */ |
278 | | |
279 | | /* Initial scrambling */ |
280 | 0 | for(j = 0; j < 50; j++) |
281 | 0 | seed = (69069 * seed + 1); |
282 | 0 | switch(kind) { |
283 | 0 | case WICHMANN_HILL: |
284 | 0 | case MARSAGLIA_MULTICARRY: |
285 | 0 | case SUPER_DUPER: |
286 | 0 | case MERSENNE_TWISTER: |
287 | | /* i_seed[0] is mti, *but* this is needed for historical consistency */ |
288 | 0 | for(j = 0; j < RNG_Table[kind].n_seed; j++) { |
289 | 0 | seed = (69069 * seed + 1); |
290 | 0 | RNG_Table[kind].i_seed[j] = seed; |
291 | 0 | } |
292 | 0 | FixupSeeds(kind, 1); |
293 | 0 | break; |
294 | 0 | case KNUTH_TAOCP: |
295 | 0 | RNG_Init_R_KT(seed); |
296 | 0 | break; |
297 | 0 | case KNUTH_TAOCP2: |
298 | 0 | RNG_Init_KT2(seed); |
299 | 0 | break; |
300 | 0 | case LECUYER_CMRG: |
301 | 0 | for(j = 0; j < RNG_Table[kind].n_seed; j++) { |
302 | 0 | seed = (69069 * seed + 1); |
303 | 0 | while(seed >= m2) seed = (69069 * seed + 1); |
304 | 0 | RNG_Table[kind].i_seed[j] = seed; |
305 | 0 | } |
306 | 0 | break; |
307 | 0 | case USER_UNIF: |
308 | 0 | User_unif_fun = R_FindSymbol("user_unif_rand", "", NULL); |
309 | 0 | if (!User_unif_fun) error(_("'user_unif_rand' not in load table")); |
310 | 0 | User_unif_init = (UnifInitFun) R_FindSymbol("user_unif_init", "", NULL); |
311 | 0 | if (User_unif_init) (void) User_unif_init(seed); |
312 | 0 | User_unif_nseed = R_FindSymbol("user_unif_nseed", "", NULL); |
313 | 0 | User_unif_seedloc = R_FindSymbol("user_unif_seedloc", "", NULL); |
314 | 0 | if (User_unif_seedloc) { |
315 | 0 | int ns = 0; |
316 | 0 | if (!User_unif_nseed) { |
317 | 0 | warning(_("cannot read seeds unless 'user_unif_nseed' is supplied")); |
318 | 0 | break; |
319 | 0 | } |
320 | 0 | ns = *((int *) User_unif_nseed()); |
321 | 0 | if (ns < 0 || ns > 625) { |
322 | 0 | warning(_("seed length must be in 0...625; ignored")); |
323 | 0 | break; |
324 | 0 | } |
325 | 0 | RNG_Table[kind].n_seed = ns; |
326 | 0 | RNG_Table[kind].i_seed = (Int32 *) User_unif_seedloc(); |
327 | 0 | } |
328 | 0 | break; |
329 | 0 | default: |
330 | 0 | error(_("RNG_Init: unimplemented RNG kind %d"), kind); |
331 | 0 | } |
332 | 0 | } |
333 | | |
334 | | static SEXP GetSeedsFromVar(void) |
335 | 0 | { |
336 | 0 | SEXP seeds = R_findVarInFrame(R_GlobalEnv, R_SeedsSymbol); |
337 | 0 | if (TYPEOF(seeds) == PROMSXP) |
338 | 0 | seeds = eval(R_SeedsSymbol, R_GlobalEnv); |
339 | 0 | return seeds; |
340 | 0 | } |
341 | | |
342 | | static void Randomize(RNGtype kind) |
343 | 0 | { |
344 | | /* called by GetRNGstate() when there is no .Random.seed, also from FixupSeeds() */ |
345 | 0 | RNG_Init(kind, TimeToSeed()); |
346 | 0 | } |
347 | | |
348 | | static bool GetRNGkind(SEXP seeds) |
349 | 0 | { |
350 | | /* Load RNG_kind, N01_kind, Sample_kind, Binom_kind from .Random.seed if present */ |
351 | |
|
352 | 0 | if (isNull(seeds)) |
353 | 0 | seeds = GetSeedsFromVar(); |
354 | 0 | if (seeds == R_UnboundValue) return TRUE; |
355 | 0 | if (!isInteger(seeds)) { |
356 | 0 | if (seeds == R_MissingArg) /* How can this happen? */ |
357 | 0 | R_MissingArgError(R_SeedsSymbol, R_CurrentExpression, |
358 | 0 | "getRNGError"); |
359 | 0 | warning(_("'.Random.seed' is not an integer vector but of type '%s', so ignored"), |
360 | 0 | R_typeToChar(seeds)); |
361 | 0 | goto invalid; |
362 | 0 | } |
363 | 0 | int *is = INTEGER(seeds), |
364 | 0 | tmp = is[0]; |
365 | | /* avoid overflow here: max current value is 110507 */ |
366 | 0 | if (tmp == NA_INTEGER || tmp < 0 || tmp > 111000) { |
367 | 0 | warning(_("'.Random.seed[1]' is not a valid integer, so ignored")); |
368 | 0 | goto invalid; |
369 | 0 | } |
370 | 0 | RNGtype newRNG = (RNGtype) (tmp % 100); |
371 | 0 | N01type newN01 = (N01type) (tmp % 10000 / 100); |
372 | 0 | Sampletype newSample = (Sampletype) (tmp % 100000 / 10000); |
373 | 0 | Binomtype newBinom = (Binomtype) (tmp / 100000); |
374 | 0 | if (newN01 > KINDERMAN_RAMAGE || newSample > REJECTION || newBinom > BTPE) { |
375 | 0 | warning(_("'.Random.seed[1]' is not a valid Normal | Sample | Binom type, so ignored")); |
376 | 0 | goto invalid; |
377 | 0 | } |
378 | 0 | switch(newRNG) { |
379 | 0 | case WICHMANN_HILL: |
380 | 0 | case MARSAGLIA_MULTICARRY: |
381 | 0 | case SUPER_DUPER: |
382 | 0 | case MERSENNE_TWISTER: |
383 | 0 | case KNUTH_TAOCP: |
384 | 0 | case KNUTH_TAOCP2: |
385 | 0 | case LECUYER_CMRG: |
386 | 0 | break; |
387 | 0 | case USER_UNIF: |
388 | 0 | if(!User_unif_fun) { |
389 | 0 | warning(_("'.Random.seed[1] %% 100 = 5' but no user-supplied generator, so ignored")); |
390 | 0 | goto invalid; |
391 | 0 | } |
392 | 0 | break; |
393 | 0 | default: |
394 | 0 | warning(_("'.Random.seed[1] %% 100' is not a valid RNG kind so ignored")); |
395 | 0 | goto invalid; |
396 | 0 | } |
397 | 0 | RNG_kind = newRNG; N01_kind = newN01; Sample_kind = newSample; Binom_kind = newBinom; |
398 | 0 | return false; |
399 | 0 | invalid: |
400 | 0 | RNG_kind = RNG_DEFAULT; N01_kind = N01_DEFAULT; Sample_kind = Sample_DEFAULT; Binom_kind = Binom_DEFAULT; |
401 | |
|
402 | 0 | Randomize(RNG_kind); |
403 | 0 | PutRNGstate(); // write out to .Random.seed |
404 | 0 | return true; |
405 | 0 | } |
406 | | |
407 | | static void copy_seeds_in(Int32 *i_seed, SEXP seeds, int len_seed) |
408 | 0 | { |
409 | 0 | int *p = INTEGER(seeds); // will warn if R INTEGER type changes |
410 | 0 | memcpy(i_seed, p + 1, sizeof(Int32) * len_seed); |
411 | 0 | } |
412 | | |
413 | | void GetRNGstate(void) |
414 | 0 | { |
415 | | /* Get .Random.seed into proper variables */ |
416 | |
|
417 | 0 | SEXP seeds = GetSeedsFromVar(); |
418 | 0 | if (seeds == R_UnboundValue) |
419 | 0 | Randomize(RNG_kind); |
420 | 0 | else { |
421 | | /* this might re-set the generator */ |
422 | 0 | if(GetRNGkind(seeds)) return; |
423 | 0 | int len_seed = RNG_Table[RNG_kind].n_seed; |
424 | | /* Not sure whether this test is needed: wrong for USER_UNIF */ |
425 | 0 | if(LENGTH(seeds) > 1 && LENGTH(seeds) < len_seed + 1) |
426 | 0 | error(_("'.Random.seed' has wrong length")); |
427 | 0 | if(LENGTH(seeds) == 1 && RNG_kind != USER_UNIF) |
428 | 0 | Randomize(RNG_kind); |
429 | 0 | else { |
430 | 0 | copy_seeds_in(RNG_Table[RNG_kind].i_seed, seeds, len_seed); |
431 | 0 | FixupSeeds(RNG_kind, 0); |
432 | 0 | } |
433 | 0 | } |
434 | 0 | } |
435 | | |
436 | | static R_INLINE void copy_seeds_out(SEXP seeds, Int32 *i_seed, int len_seed) |
437 | 0 | { |
438 | 0 | int *p = INTEGER(seeds) + 1; // will warn if R INTEGER type changes |
439 | 0 | memcpy(p, i_seed, sizeof(Int32) * len_seed); |
440 | 0 | } |
441 | | |
442 | | void PutRNGstate(void) |
443 | 0 | { |
444 | 0 | if (RNG_kind > LECUYER_CMRG || N01_kind > KINDERMAN_RAMAGE || |
445 | 0 | Sample_kind > REJECTION || Binom_kind > BTPE) { |
446 | 0 | warning("Internal .Random.seed is corrupt: not saving"); |
447 | 0 | return; |
448 | 0 | } |
449 | | |
450 | | /* Copy out seeds to .Random.seed */ |
451 | 0 | int len_seed = RNG_Table[RNG_kind].n_seed; |
452 | 0 | int kinds = RNG_kind + 100 * N01_kind + 10000 * Sample_kind + 100000 * Binom_kind; |
453 | |
|
454 | 0 | SEXP seeds = R_findVarInFrame(R_GlobalEnv, R_SeedsSymbol); |
455 | 0 | if (NOT_SHARED(seeds) && ATTRIB(seeds) == R_NilValue && |
456 | 0 | TYPEOF(seeds) == INTSXP && XLENGTH(seeds) == len_seed + 1) { |
457 | | /* it is safe to reuse the existing .Random.seed vector */ |
458 | 0 | INTEGER(seeds)[0] = kinds; |
459 | 0 | copy_seeds_out(seeds, RNG_Table[RNG_kind].i_seed, len_seed); |
460 | 0 | } |
461 | 0 | else { |
462 | | /* need to allocate a fresh .Random.seed vector */ |
463 | 0 | seeds = PROTECT(allocVector(INTSXP, len_seed + 1)); |
464 | 0 | INTEGER(seeds)[0] = kinds; |
465 | 0 | copy_seeds_out(seeds, RNG_Table[RNG_kind].i_seed, len_seed); |
466 | | |
467 | | /* assign only in the workspace */ |
468 | 0 | defineVar(R_SeedsSymbol, seeds, R_GlobalEnv); |
469 | 0 | INCREMENT_NAMED(seeds); |
470 | 0 | UNPROTECT(1); |
471 | 0 | } |
472 | 0 | } |
473 | | |
474 | | static void RNGkind(RNGtype newkind) |
475 | 0 | { |
476 | | /* Choose a new kind of RNG. |
477 | | * Initialize its seed by calling the old RNG's unif_rand() |
478 | | */ |
479 | 0 | if (newkind == (RNGtype)-1) newkind = RNG_DEFAULT; |
480 | 0 | switch(newkind) { |
481 | 0 | case MARSAGLIA_MULTICARRY: |
482 | 0 | warning(_("RNGkind: Marsaglia-Multicarry has poor statistical properties")); |
483 | 0 | case WICHMANN_HILL: |
484 | 0 | case SUPER_DUPER: |
485 | 0 | case MERSENNE_TWISTER: |
486 | 0 | case KNUTH_TAOCP: |
487 | 0 | case USER_UNIF: |
488 | 0 | case KNUTH_TAOCP2: |
489 | 0 | case LECUYER_CMRG: |
490 | 0 | break; |
491 | 0 | default: |
492 | 0 | error(_("RNGkind: unimplemented RNG kind %d"), newkind); |
493 | 0 | } |
494 | 0 | GetRNGstate(); |
495 | | // precaution against corruption as per package randtoolbox |
496 | 0 | double u = unif_rand(); |
497 | 0 | if (u < 0.0 || u > 1.0) { |
498 | 0 | warning("someone corrupted the random-number generator: re-initializing"); |
499 | 0 | RNG_Init(newkind, TimeToSeed()); |
500 | 0 | } else |
501 | 0 | RNG_Init(newkind, (Int32) (u * UINT_MAX)); |
502 | 0 | RNG_kind = newkind; |
503 | 0 | PutRNGstate(); |
504 | 0 | } |
505 | | |
506 | | static void Norm_kind(N01type kind) |
507 | 0 | { |
508 | | /* N01type is an enumeration type, so this will probably get |
509 | | mapped to an unsigned integer type. */ |
510 | 0 | if (kind == KINDERMAN_RAMAGE && RNG_kind == MARSAGLIA_MULTICARRY) { |
511 | 0 | warning(_("RNGkind: severe deviations from normality for Kinderman-Ramage + Marsaglia-Multicarry")); |
512 | 0 | } |
513 | 0 | if (kind == AHRENS_DIETER && RNG_kind == MARSAGLIA_MULTICARRY) { |
514 | 0 | warning(_("RNGkind: deviations from normality for Ahrens-Dieter + Marsaglia-Multicarry")); |
515 | 0 | } |
516 | 0 | if (kind == (N01type)-1) kind = N01_DEFAULT; |
517 | 0 | if (kind > KINDERMAN_RAMAGE) |
518 | 0 | error(_("invalid Normal type in 'RNGkind'")); |
519 | 0 | if (kind == USER_NORM) { |
520 | 0 | User_norm_fun = R_FindSymbol("user_norm_rand", "", NULL); |
521 | 0 | if (!User_norm_fun) error(_("'user_norm_rand' not in load table")); |
522 | 0 | } |
523 | 0 | GetRNGstate(); /* might not be initialized */ |
524 | 0 | if (kind == BOX_MULLER) |
525 | 0 | BM_norm_keep = 0.0; /* zap Box-Muller history */ |
526 | 0 | N01_kind = kind; |
527 | 0 | PutRNGstate(); |
528 | 0 | } |
529 | | |
530 | | static void Samp_kind(Sampletype kind) |
531 | 0 | { |
532 | | /* Sampletype is an enumeration type, so this will probably get |
533 | | mapped to an unsigned integer type. */ |
534 | 0 | if (kind == (Sampletype)-1) kind = Sample_DEFAULT; |
535 | 0 | if (kind > REJECTION) |
536 | 0 | error(_("invalid sample type in 'RNGkind'")); |
537 | 0 | GetRNGstate(); /* might not be initialized */ |
538 | 0 | Sample_kind = kind; |
539 | 0 | PutRNGstate(); |
540 | 0 | } |
541 | | |
542 | | static void Bin_kind(Binomtype kind) |
543 | 0 | { |
544 | | /* Binomtype is an enumeration type, so this will probably get |
545 | | mapped to an unsigned integer type. */ |
546 | 0 | if (kind == (Binomtype)-1) kind = Binom_DEFAULT; |
547 | 0 | if (kind > BTPE) |
548 | 0 | error(_("invalid binom type in 'RNGkind'")); |
549 | 0 | GetRNGstate(); /* might not be initialized */ |
550 | 0 | Binom_kind = kind; |
551 | 0 | PutRNGstate(); |
552 | 0 | } |
553 | | |
554 | | |
555 | | /*------ .Internal interface ------------------------*/ |
556 | | |
557 | | attribute_hidden SEXP do_RNGkind (SEXP call, SEXP op, SEXP args, SEXP env) |
558 | 0 | { |
559 | 0 | checkArity(op,args); |
560 | 0 | GetRNGstate(); /* might not be initialized */ |
561 | 0 | SEXP ans = PROTECT(allocVector(INTSXP, 4)); |
562 | 0 | INTEGER(ans)[0] = RNG_kind; |
563 | 0 | INTEGER(ans)[1] = N01_kind; |
564 | 0 | INTEGER(ans)[2] = Sample_kind; |
565 | 0 | INTEGER(ans)[3] = Binom_kind; |
566 | 0 | SEXP rng = CAR(args), |
567 | 0 | norm = CADR(args), |
568 | 0 | sample = CADDR(args), |
569 | 0 | binom = CADDDR(args); |
570 | 0 | GetRNGkind(R_NilValue); /* pull from .Random.seed if present */ |
571 | 0 | if(!isNull(rng)) { /* set a new RNG kind */ |
572 | 0 | RNGkind((RNGtype) asInteger(rng)); |
573 | 0 | } |
574 | 0 | if(!isNull(norm)) { /* set a new normal kind */ |
575 | 0 | Norm_kind((N01type) asInteger(norm)); |
576 | 0 | } |
577 | 0 | if(!isNull(sample)) { /* set a new sample kind */ |
578 | 0 | Samp_kind((Sampletype) asInteger(sample)); |
579 | 0 | } |
580 | 0 | if(!isNull(binom)) { /* set a new binom kind */ |
581 | 0 | Bin_kind((Binomtype) asInteger(binom)); |
582 | 0 | } |
583 | 0 | UNPROTECT(1); |
584 | 0 | return ans; |
585 | 0 | } |
586 | | |
587 | | |
588 | | attribute_hidden SEXP do_setseed (SEXP call, SEXP op, SEXP args, SEXP env) |
589 | 0 | { |
590 | 0 | checkArity(op, args); |
591 | 0 | int seed; |
592 | 0 | if(!isNull(CAR(args))) { |
593 | 0 | seed = asInteger(CAR(args)); |
594 | 0 | if (seed == NA_INTEGER) |
595 | 0 | error(_("supplied seed is not a valid integer")); |
596 | 0 | } else seed = TimeToSeed(); |
597 | 0 | SEXP skind = CADR(args), |
598 | 0 | nkind = CADDR(args), |
599 | 0 | sampkind = CADDDR(args), |
600 | 0 | binomkind= CAD4R(args); |
601 | | /* pull RNG_kind, N01_kind, ... from .Random.seed if present: */ |
602 | 0 | GetRNGkind(R_NilValue); |
603 | 0 | if (!isNull(skind)) RNGkind((RNGtype) asInteger(skind)); |
604 | 0 | if (!isNull(nkind)) Norm_kind((N01type) asInteger(nkind)); |
605 | 0 | if(!isNull(sampkind)) Samp_kind((Sampletype) asInteger(sampkind)); |
606 | 0 | if(!isNull(binomkind)) Bin_kind((Binomtype) asInteger(binomkind)); |
607 | 0 | RNG_Init(RNG_kind, (Int32) seed); /* zaps BM history */ |
608 | 0 | PutRNGstate(); |
609 | 0 | return R_NilValue; |
610 | 0 | } |
611 | | |
612 | | |
613 | | /* S COMPATIBILITY */ |
614 | | |
615 | | /* The following entry points provide compatibility with S. */ |
616 | | /* These entry points should not be used by new R code. */ |
617 | | /* These entry points are now hidden */ |
618 | | |
619 | | attribute_hidden |
620 | | void seed_in(long *ignored) |
621 | 0 | { |
622 | 0 | GetRNGstate(); |
623 | 0 | } |
624 | | |
625 | | attribute_hidden |
626 | | void seed_out(long *ignored) |
627 | 0 | { |
628 | 0 | PutRNGstate(); |
629 | 0 | } |
630 | | |
631 | | /* =================== Mersenne Twister ========================== */ |
632 | | /* From http://www.math.keio.ac.jp/~matumoto/emt.html */ |
633 | | /* New URL (accessed 2018-11-08): |
634 | | http://www.math.sci.hiroshima-u.ac.jp/~m-mat/eindex.html |
635 | | |
636 | | The initialization method in the 1998 code and paper had a minor |
637 | | issue that was addressed with new initialization approaches in an |
638 | | update in 2002. R has always used a different initialization |
639 | | approach and is not affected by that issue. |
640 | | */ |
641 | | |
642 | | /* A C-program for MT19937: Real number version([0,1)-interval) |
643 | | (1999/10/28) |
644 | | genrand() generates one pseudorandom real number (double) |
645 | | which is uniformly distributed on [0,1)-interval, for each |
646 | | call. sgenrand(seed) sets initial values to the working area |
647 | | of 624 words. Before genrand(), sgenrand(seed) must be |
648 | | called once. (seed is any 32-bit integer.) |
649 | | Integer generator is obtained by modifying two lines. |
650 | | Coded by Takuji Nishimura, considering the suggestions by |
651 | | Topher Cooper and Marc Rieffel in July-Aug. 1997. |
652 | | |
653 | | Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura. |
654 | | When you use this, send an email to: matumoto@math.keio.ac.jp |
655 | | with an appropriate reference to your work. |
656 | | |
657 | | REFERENCE |
658 | | M. Matsumoto and T. Nishimura, |
659 | | "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform |
660 | | Pseudo-Random Number Generator", |
661 | | ACM Transactions on Modeling and Computer Simulation, |
662 | | Vol. 8, No. 1, January 1998, pp 3--30. |
663 | | */ |
664 | | |
665 | | /* Period parameters */ |
666 | 0 | #define N 624 |
667 | 0 | #define M 397 |
668 | 0 | #define MATRIX_A 0x9908b0df /* constant vector a */ |
669 | 0 | #define UPPER_MASK 0x80000000 /* most significant w-r bits */ |
670 | 0 | #define LOWER_MASK 0x7fffffff /* least significant r bits */ |
671 | | |
672 | | /* Tempering parameters */ |
673 | 0 | #define TEMPERING_MASK_B 0x9d2c5680 |
674 | 0 | #define TEMPERING_MASK_C 0xefc60000 |
675 | 0 | #define TEMPERING_SHIFT_U(y) (y >> 11) |
676 | 0 | #define TEMPERING_SHIFT_S(y) (y << 7) |
677 | 0 | #define TEMPERING_SHIFT_T(y) (y << 15) |
678 | 0 | #define TEMPERING_SHIFT_L(y) (y >> 18) |
679 | | |
680 | | static Int32 *mt = dummy+1; /* the array for the state vector */ |
681 | | static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ |
682 | | |
683 | | /* Initializing the array with a seed */ |
684 | | static void |
685 | | MT_sgenrand(Int32 seed) |
686 | 0 | { |
687 | 0 | int i; |
688 | |
|
689 | 0 | for (i = 0; i < N; i++) { |
690 | 0 | mt[i] = seed & 0xffff0000; |
691 | 0 | seed = 69069 * seed + 1; |
692 | 0 | mt[i] |= (seed & 0xffff0000) >> 16; |
693 | 0 | seed = 69069 * seed + 1; |
694 | 0 | } |
695 | 0 | mti = N; |
696 | 0 | } |
697 | | |
698 | | /* Initialization by "sgenrand()" is an example. Theoretically, |
699 | | there are 2^19937-1 possible states as an initial state. |
700 | | Essential bits in "seed_array[]" is following 19937 bits: |
701 | | (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1]. |
702 | | (seed_array[0]&LOWER_MASK) is discarded. |
703 | | Theoretically, |
704 | | (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1] |
705 | | can take any values except all zeros. */ |
706 | | |
707 | | static double MT_genrand(void) |
708 | 0 | { |
709 | 0 | Int32 y; |
710 | 0 | static Int32 mag01[2]={0x0, MATRIX_A}; |
711 | | /* mag01[x] = x * MATRIX_A for x=0,1 */ |
712 | |
|
713 | 0 | mti = dummy[0]; |
714 | |
|
715 | 0 | if (mti >= N) { /* generate N words at one time */ |
716 | 0 | int kk; |
717 | |
|
718 | 0 | if (mti == N+1) /* if sgenrand() has not been called, */ |
719 | 0 | MT_sgenrand(4357); /* a default initial seed is used */ |
720 | |
|
721 | 0 | for (kk = 0; kk < N - M; kk++) { |
722 | 0 | y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); |
723 | 0 | mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; |
724 | 0 | } |
725 | 0 | for (; kk < N - 1; kk++) { |
726 | 0 | y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); |
727 | 0 | mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; |
728 | 0 | } |
729 | 0 | y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); |
730 | 0 | mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; |
731 | |
|
732 | 0 | mti = 0; |
733 | 0 | } |
734 | |
|
735 | 0 | y = mt[mti++]; |
736 | 0 | y ^= TEMPERING_SHIFT_U(y); |
737 | 0 | y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; |
738 | 0 | y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; |
739 | 0 | y ^= TEMPERING_SHIFT_L(y); |
740 | 0 | dummy[0] = mti; |
741 | |
|
742 | 0 | return ( (double)y * 2.3283064365386963e-10 ); /* reals: [0,1)-interval */ |
743 | 0 | } |
744 | | |
745 | | /* |
746 | | The following code was taken from earlier versions of |
747 | | http://www-cs-faculty.stanford.edu/~knuth/programs/rng.c-old |
748 | | http://www-cs-faculty.stanford.edu/~knuth/programs/rng.c |
749 | | */ |
750 | | |
751 | | |
752 | | /* This define may give a warning with clang, but is needed to comply |
753 | | with the prohibition on changing the code. */ |
754 | | #ifdef __clang__ |
755 | | #pragma clang diagnostic push |
756 | | #pragma clang diagnostic ignored "-Wkeyword-macro" |
757 | | #endif |
758 | 0 | #define long Int32 |
759 | | #ifdef __clang__ |
760 | | #pragma clang diagnostic pop |
761 | | #endif |
762 | | |
763 | 0 | #define ran_arr_buf R_KT_ran_arr_buf |
764 | 0 | #define ran_arr_cycle R_KT_ran_arr_cycle |
765 | 0 | #define ran_arr_ptr R_KT_ran_arr_ptr |
766 | 0 | #define ran_arr_sentinel R_KT_ran_arr_sentinel |
767 | 0 | #define ran_x dummy |
768 | | |
769 | 0 | #define KK 100 /* the long lag */ |
770 | 0 | #define LL 37 /* the short lag */ |
771 | 0 | #define MM (1L<<30) /* the modulus */ |
772 | 0 | #define TT 70 /* guaranteed separation between streams */ |
773 | 0 | #define mod_diff(x,y) (((x)-(y))&(MM-1)) /* subtraction mod MM */ |
774 | 0 | #define is_odd(x) ((x)&1) /* units bit of x */ |
775 | | static void ran_array(long aa[],int n) /* put n new random numbers in aa */ |
776 | 0 | { |
777 | 0 | register int i,j; |
778 | 0 | for (j=0;j<KK;j++) aa[j]=ran_x[j]; |
779 | 0 | for (;j<n;j++) aa[j]=mod_diff(aa[j-KK],aa[j-LL]); |
780 | 0 | for (i=0;i<LL;i++,j++) ran_x[i]=mod_diff(aa[j-KK],aa[j-LL]); |
781 | 0 | for (;i<KK;i++,j++) ran_x[i]=mod_diff(aa[j-KK],ran_x[i-LL]); |
782 | 0 | } |
783 | 0 | #define QUALITY 1009 /* recommended quality level for high-res use */ |
784 | | static long ran_arr_buf[QUALITY]; |
785 | | static long ran_arr_sentinel=(long)-1; |
786 | | static long *ran_arr_ptr=&ran_arr_sentinel; /* the next random number, or -1 */ |
787 | | |
788 | | static long ran_arr_cycle(void) |
789 | 0 | { |
790 | 0 | ran_array(ran_arr_buf,QUALITY); |
791 | 0 | ran_arr_buf[KK]=(long)(-1); |
792 | 0 | ran_arr_ptr=ran_arr_buf+1; |
793 | 0 | return ran_arr_buf[0]; |
794 | 0 | } |
795 | | |
796 | | /* =================== Knuth TAOCP 2002 ========================== */ |
797 | | |
798 | | /* This program by D E Knuth is in the public domain and freely copyable. |
799 | | * It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6 |
800 | | * (or in the errata to the 2nd edition --- see |
801 | | * http://www-cs-faculty.stanford.edu/~knuth/taocp.html |
802 | | * in the changes to Volume 2 on pages 171 and following). */ |
803 | | |
804 | | /* N.B. The MODIFICATIONS introduced in the 9th printing (2002) are |
805 | | included here; there's no backwards compatibility with the original. */ |
806 | | |
807 | | |
808 | | static void ran_start(long seed) |
809 | 0 | { |
810 | 0 | register int t,j; |
811 | 0 | long x[KK+KK-1]; /* the preparation buffer */ |
812 | 0 | register long ss=(seed+2)&(MM-2); |
813 | 0 | for (j=0;j<KK;j++) { |
814 | 0 | x[j]=ss; /* bootstrap the buffer */ |
815 | 0 | ss<<=1; if (ss>=MM) ss-=MM-2; /* cyclic shift 29 bits */ |
816 | 0 | } |
817 | 0 | x[1]++; /* make x[1] (and only x[1]) odd */ |
818 | 0 | for (ss=seed&(MM-1),t=TT-1; t; ) { |
819 | 0 | for (j=KK-1;j>0;j--) x[j+j]=x[j], x[j+j-1]=0; /* "square" */ |
820 | 0 | for (j=KK+KK-2;j>=KK;j--) |
821 | 0 | x[j-(KK-LL)]=mod_diff(x[j-(KK-LL)],x[j]), |
822 | 0 | x[j-KK]=mod_diff(x[j-KK],x[j]); |
823 | 0 | if (is_odd(ss)) { /* "multiply by z" */ |
824 | 0 | for (j=KK;j>0;j--) x[j]=x[j-1]; |
825 | 0 | x[0]=x[KK]; /* shift the buffer cyclically */ |
826 | 0 | x[LL]=mod_diff(x[LL],x[KK]); |
827 | 0 | } |
828 | 0 | if (ss) ss>>=1; else t--; |
829 | 0 | } |
830 | 0 | for (j=0;j<LL;j++) ran_x[j+KK-LL]=x[j]; |
831 | 0 | for (;j<KK;j++) ran_x[j-LL]=x[j]; |
832 | 0 | for (j=0;j<10;j++) ran_array(x,KK+KK-1); /* warm things up */ |
833 | 0 | ran_arr_ptr=&ran_arr_sentinel; |
834 | 0 | } |
835 | | /* ===================== end of Knuth's code ====================== */ |
836 | | |
837 | | static void RNG_Init_KT2(Int32 seed) |
838 | 0 | { |
839 | 0 | ran_start(seed % 1073741821); |
840 | 0 | KT_pos = 100; |
841 | 0 | } |
842 | | |
843 | | static Int32 KT_next(void) |
844 | 0 | { |
845 | 0 | if(KT_pos >= 100) { |
846 | 0 | ran_arr_cycle(); |
847 | 0 | KT_pos = 0; |
848 | 0 | } |
849 | 0 | return ran_x[(KT_pos)++]; |
850 | 0 | } |
851 | | |
852 | | static void RNG_Init_R_KT(Int32 seed) |
853 | 0 | { |
854 | 0 | SEXP fun, sseed, call, ans; |
855 | 0 | PROTECT(fun = findVar1(install(".TAOCP1997init"), R_BaseEnv, CLOSXP, FALSE)); |
856 | 0 | if(fun == R_UnboundValue) |
857 | 0 | error("function '.TAOCP1997init' is missing"); |
858 | 0 | PROTECT(sseed = ScalarInteger((int)(seed % 1073741821))); |
859 | 0 | PROTECT(call = lang2(fun, sseed)); |
860 | 0 | ans = eval(call, R_GlobalEnv); |
861 | 0 | memcpy(dummy, INTEGER(ans), 100*sizeof(int)); |
862 | 0 | UNPROTECT(3); |
863 | 0 | KT_pos = 100; |
864 | 0 | } |
865 | | |
866 | | /* Our PRNGs have at most 32 bit of precision. All generators except |
867 | | Knuth-TAOCP, Knuth-TAOCP-2002, and possibly the user-supplied ones |
868 | | have 31 or 32 bits of precision; the others are assumed to |
869 | | have at least 25. */ |
870 | | static R_INLINE double ru(void) |
871 | 0 | { |
872 | 0 | double U = 33554432.0; |
873 | 0 | return (floor(U*unif_rand()) + unif_rand())/U; |
874 | 0 | } |
875 | | |
876 | | static double R_unif_index_0(double dn) |
877 | 0 | { |
878 | 0 | double cut = INT_MAX; |
879 | |
|
880 | 0 | switch(RNG_kind) { |
881 | 0 | case KNUTH_TAOCP: |
882 | 0 | case USER_UNIF: |
883 | 0 | case KNUTH_TAOCP2: |
884 | 0 | cut = 33554431.0; /* 2^25 - 1 */ |
885 | 0 | break; |
886 | 0 | default: |
887 | 0 | break; |
888 | 0 | } |
889 | | |
890 | 0 | double u = dn > cut ? ru() : unif_rand(); |
891 | 0 | return floor(dn * u); |
892 | 0 | } |
893 | | |
894 | | //generate a random non-negative integer < 2 ^ bits in 16 bit chunks |
895 | | static double rbits(int bits) |
896 | 0 | { |
897 | 0 | uint_least64_t v = 0; |
898 | 0 | for (int n = 0; n <= bits; n += 16) { |
899 | 0 | int v1 = (int) floor(unif_rand() * 65536); |
900 | 0 | v = 65536 * v + v1; |
901 | 0 | } |
902 | 0 | const uint_least64_t one64 = 1L; |
903 | | // mask out the bits in the result that are not needed |
904 | 0 | return (double) (v & ((one64 << bits) - 1)); |
905 | 0 | } |
906 | | |
907 | | double R_unif_index(double dn) |
908 | 0 | { |
909 | 0 | if (Sample_kind == ROUNDING) |
910 | 0 | return R_unif_index_0(dn); |
911 | | |
912 | | // rejection sampling from integers below the next larger power of two |
913 | 0 | if (dn <= 0) |
914 | 0 | return 0.0; |
915 | 0 | int bits = (int) ceil(log2(dn)); |
916 | 0 | double dv; |
917 | 0 | do { dv = rbits(bits); } while (dn <= dv); |
918 | 0 | return dv; |
919 | 0 | } |
920 | | |
921 | 0 | Sampletype R_sample_kind(void) { return Sample_kind; } |