Random.user               package: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.

     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 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:

     ##  Marsaglia's conguential 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 SHLIB urand.c
     R
     > dyn.load("urand.so")
     > RNGkind("user")
     > runif(10)
     > .Random.seed
     > RNGkind(, "user")
     > rnorm(10)
     > RNGkind()
     [1] "user-supplied" "user-supplied"

