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:

     ## 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)

