R: User-supplied Random Number Generation (original) (raw)
Random.user {base} | R Documentation |
---|
Description
Function [RNGkind](../../base/help/RNGkind.html)
allows user-coded uniform and normal random number generators to be supplied. The details are given here.
Details
A user-specified uniform RNG is called from entry points in dynamically-loaded compiled code. The user must supply the entry pointuser_unif_rand
, which takes no arguments and returns a_pointer to_ a double. The example below will show the general pattern. The generator should have at least 25 bits of precision.
Optionally, the user can supply the entry point user_unif_init
, which is called with an unsigned int
argument when[RNGkind](../../base/help/RNGkind.html)
(or set.seed
) is called, and is intended to be used to initialize the user's RNG code. The argument is intended to be used to set the ‘seeds’; it is the seed
argument toset.seed
or an essentially random seed if [RNGkind](../../base/help/RNGkind.html)
is called.
If only these functions are supplied, no information about the generator's state is recorded in .Random.seed
. Optionally, functions user_unif_nseed
and user_unif_seedloc
can be supplied which are called with no arguments and should return pointers to the number of seeds and to an integer (specifically, ‘Int32’) array of seeds. Calls to GetRNGstate
and PutRNGstate
will then copy this array to and from .Random.seed
.
A user-specified normal RNG is specified by a single entry pointuser_norm_rand
, which takes no arguments and returns a_pointer to_ a double.
Warning
As with all compiled code, mis-specifying these functions can crash R. Do include the ‘R_ext/Random.h’ header file for type checking.
Examples
## Not run:
## Marsaglia's congruential PRNG
#include <R_ext/Random.h>
static Int32 seed;
static double res;
static int nseed = 1;
double * user_unif_rand(void)
{
seed = 69069 * seed + 1;
res = seed * 2.32830643653869e-10;
return &res;
}
void user_unif_init(Int32 seed_in) { seed = seed_in; }
int * user_unif_nseed(void) { return &nseed; }
int * user_unif_seedloc(void) { return (int *) &seed; }
/* ratio-of-uniforms for normal */
#include <math.h>
static double x;
double * user_norm_rand(void)
{
double u, v, z;
do {
u = unif_rand();
v = 0.857764 * (2. * unif_rand() - 1);
x = v/u; z = 0.25 * x * x;
if (z < 1. - u) break;
if (z > 0.259/u + 0.35) continue;
} while (z > -log(u));
return &x;
}
## Use under Unix:
R CMD SHLIB urand.c
R
> dyn.load("urand.so")
> RNGkind("user")
> runif(10)
> .Random.seed
> RNGkind(, "user")
> rnorm(10)
> RNGkind()
[1] "user-supplied" "user-supplied"
## End(Not run)
[Package _base_ version 4.6.0 Index]