R: User-supplied Random Number Generation

Random.user {base} | R Documentation

## User-supplied Random Number Generation

### Description

Function `RNGkind` 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 point `user_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` (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 to `set.seed` or an essentially random seed if `RNGkind` 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 point `user_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()
    {
        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() { return &nseed; }
    int * user_unif_seedloc() { return (int *) &seed; }

    /*  ratio-of-uniforms for normal  */
    #include <math.h>
    static double x;

    double * user_norm_rand()
    {
        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 3.5.1 Index]