1 /*
2  * This is a hack of the GSL's rng/types.c:
3  *
4  * Copyright (C) 2001 Brian Gough
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or (at
9  * your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  *******************************************************************
21  * This is being directly adapted from and modified for use in dieharder
22  * so it can maintain its own independent RNG space of types not limited
23  * by its internal limit of 100.  To avoid collisions, we'll start our number
24  * space above 100, and extend it to 1000.
25  *
26  * While we're at it, let's define the ranges:
27  *
28  *   0-199 gsl generators (fixed order from now on with room for growth)
29  *   200-399 libdieharder generators (fixed order from now on)
30  *   400-499 R-based generators (fixed order from now on)
31  *   500-599 hardware generators (e.g. /dev/random and friends)
32  *   600-699 user-defined generators (starting with dieharder example)
33  *   700-999 reserved for future integration with R-like environments
34  *
35  * Naturally, we can simply bump MAXRNGS and add more, but 1000 seems
36  * likely to last for "a while" and maybe "forever".
37  */
38 
39 #include <dieharder/libdieharder.h>
40 FILE *test_fp;
41 
dieharder_rng_types()42 void dieharder_rng_types()
43 {
44 
45  int i;
46 
47  /*
48   * Null the whole thing for starters
49   */
50  for(i=0;i<MAXRNGS;i++) dh_rng_types[i] = 0;
51 
52  /*
53   * Initialize gsl_types to fill it with the current gsl rngs.
54   */
55  gsl_types = gsl_rng_types_setup();
56 
57  /*
58   * Copy its contents over into dieharder_rng_generator_types.
59   */
60  i = 0;
61  while(gsl_types[i] != NULL){
62    dh_rng_types[i] = gsl_types[i];
63    i++;
64  }
65  dh_num_gsl_rngs = i;
66  MYDEBUG(D_TYPES){
67    printf("# startup:  Found %u GSL rngs.\n",dh_num_gsl_rngs);
68  }
69 
70  /*
71   * Now add the new ones in.  These positions are to be locked in by
72   * order within the ranges, so we need to be careful to get them
73   * "right" the first time.
74   *
75   * These are the dieharder generators.  I expect many users to use
76   * stdin-based raw input since it is by far the easiest one to come up
77   * with (and actually will work with e.g. /dev/random).  The file-based
78   * inputs will also be fairly common.  The rest are there for convenience,
79   * and to expose users to some new/interesting rngs.
80   */
81  i = 200;
82  dh_num_dieharder_rngs = 0;
83  ADD(gsl_rng_stdin_input_raw);
84  dh_num_dieharder_rngs++;
85  ADD(gsl_rng_file_input_raw);
86  dh_num_dieharder_rngs++;
87  ADD(gsl_rng_file_input);
88  dh_num_dieharder_rngs++;
89  ADD(gsl_rng_ca);
90  dh_num_dieharder_rngs++;
91  ADD(gsl_rng_uvag);
92  dh_num_dieharder_rngs++;
93  ADD(gsl_rng_aes);
94  dh_num_dieharder_rngs++;
95  ADD(gsl_rng_threefish);
96  dh_num_dieharder_rngs++;
97  ADD(gsl_rng_XOR);
98  dh_num_dieharder_rngs++;
99  ADD(gsl_rng_kiss);
100  dh_num_dieharder_rngs++;
101  ADD(gsl_rng_superkiss);
102  dh_num_dieharder_rngs++;
103  MYDEBUG(D_TYPES){
104    printf("# startup:  Found %u dieharder rngs.\n",dh_num_dieharder_rngs);
105  }
106 
107 
108  /*
109   * These are the R-based generators.  Honestly it would be lovely
110   * to merge them with the GSL permanently.
111   */
112  i = 400;
113  dh_num_R_rngs = 0;
114  ADD(gsl_rng_r_wichmann_hill);
115  dh_num_R_rngs++;
116  ADD(gsl_rng_r_marsaglia_mc);
117  dh_num_R_rngs++;
118  ADD(gsl_rng_r_super_duper);
119  dh_num_R_rngs++;
120  ADD(gsl_rng_r_mersenne_twister);
121  dh_num_R_rngs++;
122  ADD(gsl_rng_r_knuth_taocp);
123  dh_num_R_rngs++;
124  ADD(gsl_rng_r_knuth_taocp2);
125  dh_num_R_rngs++;
126  MYDEBUG(D_TYPES){
127    printf("# startup:  Found %u R rngs.\n",dh_num_R_rngs);
128  }
129 
130  /*
131   * These are hardware/system generators.  Again, it would be lovely to
132   * merge them with the GSL permanently.  It would also be good to wrap
133   * these in conditionals so that they are added iff the hardware
134   * interface exists.  Perhaps we should try doing this -- it requires a
135   * call to stat, I believe.  But not now.
136   */
137  i = 500;
138  dh_num_hardware_rngs = 0;
139  if ((test_fp = fopen("/dev/random","r"))) {
140    ADD(gsl_rng_dev_random);
141    fclose(test_fp);
142    dh_num_hardware_rngs++;
143  }
144  if ((test_fp = fopen("/dev/urandom","r"))) {
145    ADD(gsl_rng_dev_urandom);
146    fclose(test_fp);
147    dh_num_hardware_rngs++;
148  }
149  if ((test_fp = fopen("/dev/arandom","r"))) {
150    ADD(gsl_rng_dev_arandom);
151    fclose(test_fp);
152    dh_num_hardware_rngs++;
153  }
154  MYDEBUG(D_TYPES){
155    printf("# startup:  Found %u hardware rngs.\n",dh_num_hardware_rngs);
156  }
157 
158  /*
159   * Tally up all the generators we found.
160   */
161  dh_num_rngs = dh_num_gsl_rngs + dh_num_dieharder_rngs + dh_num_R_rngs +
162             dh_num_hardware_rngs;
163 
164 }
165 
166