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