1 /*
2  *========================================================================
3  *  rng_XOR.c
4  *
5  * This generator takes a list of generators on the dieharder
6  * command line and XOR's their output together.
7  *========================================================================
8  */
9 
10 #include <dieharder/libdieharder.h>
11 
12 /*
13  * This is a special XOR generator that takes a list of GSL
14  * wrapped rngs and XOR's their uint output together to produce
15  * each new random number.  Note that it SKIPS THE FIRST ONE which
16  * MUST be the XOR rng itself.  So there have to be at least two -g X
17  * stanzas on the command line to use XOR, and if there aren't three
18  * or more it doesn't "do" anything but use the second one.
19  */
20 static unsigned long int XOR_get (void *vstate);
21 static double XOR_get_double (void *vstate);
22 static void XOR_set (void *vstate, unsigned long int s);
23 
24 typedef struct {
25   /*
26    * internal gsl random number generator vector
27    */
28   gsl_rng *grngs[GVECMAX];
29   unsigned int XOR_rnd;
30 } XOR_state_t;
31 
32 static inline unsigned long int
XOR_get(void * vstate)33 XOR_get (void *vstate)
34 {
35  XOR_state_t *state = (XOR_state_t *) vstate;
36  int i;
37 
38  /*
39   * There is always this one, or we are in deep trouble.  I am going
40   * to have to decorate this code with error checks...
41   */
42  state->XOR_rnd = gsl_rng_get(state->grngs[1]);
43  for(i=1;i<gvcount;i++){
44    state->XOR_rnd ^= gsl_rng_get(state->grngs[i]);
45  }
46  return state->XOR_rnd;
47 
48 }
49 
50 static double
XOR_get_double(void * vstate)51 XOR_get_double (void *vstate)
52 {
53   return XOR_get (vstate) / (double) UINT_MAX;
54 }
55 
XOR_set(void * vstate,unsigned long int s)56 static void XOR_set (void *vstate, unsigned long int s) {
57 
58  XOR_state_t *state = (XOR_state_t *) vstate;
59  int i;
60  uint seed_seed;
61 
62  /*
63   * OK, here's how it works.  grngs[0] is set to mt19937_1999, seeded
64   * as per usual, and used (ONLY) to see the remaining generators.
65   * The remaining generators.
66   */
67  state->grngs[0] = gsl_rng_alloc(dh_rng_types[14]);
68  seed_seed = s;
69  gsl_rng_set(state->grngs[0],seed_seed);
70  for(i=1;i<gvcount;i++){
71 
72    /*
73     * I may need to (and probably should) add a sanity check
74     * here or in choose_rng() to be sure that all of the rngs
75     * exist.
76     */
77    state->grngs[i] = gsl_rng_alloc(dh_rng_types[gnumbs[i]]);
78    gsl_rng_set(state->grngs[i],gsl_rng_get(state->grngs[0]));
79 
80  }
81 
82 }
83 
84 static const gsl_rng_type XOR_type =
85 {"XOR (supergenerator)",        /* name */
86  UINT_MAX,			/* RAND_MAX */
87  0,				/* RAND_MIN */
88  sizeof (XOR_state_t),
89  &XOR_set,
90  &XOR_get,
91  &XOR_get_double};
92 
93 const gsl_rng_type *gsl_rng_XOR = &XOR_type;
94