1 /*
2 *========================================================================
3 * See copyright in copyright.h and the accompanying file COPYING
4 *========================================================================
5 */
6
7 /*
8 *========================================================================
9 * This should be a nice, big case switch where we add EACH test
10 * we might want to do and either just configure and do it or
11 * prompt for input (if absolutely necessary) and then do it.
12 *========================================================================
13 */
14
15 /*
16 * This is a not-quite-drop-in replacement for my old get_rand_bits()
17 * routine contributed by John E. Davis.
18 *
19 * It should give us the "next N bits" from the random number stream,
20 * without dropping any. The return can even be of arbitrary size --
21 * we make the return a void pointer whose size is specified by the
22 * caller (and guaranteed to be big enough to hold the result).
23 */
24
get_rand_bits_uint(uint nbits,uint mask,gsl_rng * rng)25 inline static uint get_rand_bits_uint (uint nbits, uint mask, gsl_rng *rng)
26 {
27
28 static uint bit_buffer;
29 static uint bits_left_in_bit_buffer = 0;
30 uint bits,breturn;
31
32 /*
33 * If there are enough bits left in the bit buffer, shift them out into
34 * bits and return. I like to watch this happen, so I'm instrumenting
35 * this with some I/O from bits.c. I'm also adding the following
36 * conditionals so it works even if the mask isn't set by the caller
37 * and does the right thing if the mask is supposed to be all 1's
38 * (in which case this is a dumb routine to call, in some sense).
39 */
40 if(mask == 0){
41 mask = ((1u << nbits) - 1);
42 }
43 if(nbits == 32){
44 mask = 0xFFFFFFFF;
45 }
46 if(nbits > 32){
47 fprintf(stderr,"Warning! dieharder cannot yet work with\b");
48 fprintf(stderr," %u > 32 bit chunks. Exiting!\n\n",nbits);
49 exit(0);
50 }
51
52 /*
53 ******************************************************************
54 * OK, the way it works is:
55 First entry, nbits = 12
56 Mask = |00000000000000000000111111111111|
57 Buff = |00000000000000000000000000000000|
58 Not enough:
59 Bits = |00000000000000000000000000000000|
60 So we refill the bit_buffer (which now has 32 bits left):
61 Buff = |11110101010110110101010001110000|
62 We RIGHT shift this (32-nbits), aligning it for return,
63 & with mask, and return.
64 Bits = |00000000000000000000111101010101|
65 Need the next one. There are 20 bits left. Buff is
66 not changed. We right shift buffer by 20-12 = 8,
67 then & with mask to return:
68 Buff = |11110101010110110101010001110000|
69 ^ ^ 8 bits->
70 Bits = |00000000000000000000101101010100|
71 Ready for the next one. There are only 8 bits left
72 and we need 12. We LEFT shift Buff onto Bits
73 by needbits = 12-8 = 4
74 Buff = |11110101010110110101010001110000|
75 Bits = |01010101101101010100011100000000|
76 We refill the bit buffer Buff:
77 Buff = |01011110001111000000001101010010|
78 ^ ^
79 We right shift 32 - needbits and OR the result with
80 Bits, & mask, and return. The mask dumps the high part
81 from the old buffer.:
82 Bits = |00000000000000000000011100000101|
83 We're back around the horn with 28 bits left. This is
84 enough, so we just right shift until the window is aligned,
85 mask out what we want, decrement the counter of number
86 of bits left, return:
87 Buff = |01011110001111000000001101010010|'
88 ^ ^
89 Bits = |00000000000000000000111000111100|
90 and so on. Very nice.
91 ******************************************************************
92 * Therefore, this routine delivers bits in left to right bits
93 * order, which is fine.
94 */
95
96 /*
97 * FIRST of all, if nbits == 32 and rmax_bits == 32 (or for that matter,
98 * if we ever seek nbits == rmax_bits) we might as well just return the
99 * gsl rng right away and skip all the logic below. In the particular
100 * case of nbits == 32 == rmax_bits, this also avoids a nasty problem
101 * with bitshift operators on x86 architectures, see below. I left a
102 * local patch in below as well just to make double-dog sure that one
103 * never does (uintvar << 32) for some uint variable; probably should
104 * do the same for (uintvar >> 32) calls below.
105 */
106 if(nbits == rmax_bits){
107 return gsl_rng_get(rng);
108 }
109
110 MYDEBUG(D_BITS) {
111 printf("Entering get_rand_bits_uint. nbits = %d\n",nbits);
112 printf(" Mask = ");
113 dumpuintbits(&mask,1);
114 printf("\n");
115 printf("%u bits left\n",bits_left_in_bit_buffer);
116 printf(" Buff = ");
117 dumpuintbits(&bit_buffer,1);
118 printf("\n");
119 }
120
121 if (bits_left_in_bit_buffer >= nbits) {
122 bits_left_in_bit_buffer -= nbits;
123 bits = (bit_buffer >> bits_left_in_bit_buffer);
124 MYDEBUG(D_BITS) {
125 printf("Enough:\n");
126 printf(" Bits = ");
127 breturn = bits & mask;
128 dumpuintbits(&breturn,1);
129 printf("\n");
130 }
131 return bits & mask;
132 }
133
134 nbits = nbits - bits_left_in_bit_buffer;
135 /*
136 * This fixes an annoying quirk of the x86. It only uses the bottom five
137 * bits of the shift value. That means that if you shift right by 32 --
138 * required in this routine to return 32 bit integers from a 32 bit
139 * generator -- nothing happens as 32 is 0100000 and only the 00000 is used
140 * to shift! What a bitch!
141 *
142 * I'm going to FIRST try this -- which should work to clear the
143 * bits register if nbits for the shift is 32 -- and then very
144 * likely alter this to just check for rmax_bits == nbits == 32
145 * and if so just shovel gsl_rng_get(rng) straight through...
146 */
147 if(nbits == 32){
148 bits = 0;
149 } else {
150 bits = (bit_buffer << nbits);
151 }
152 MYDEBUG(D_BITS) {
153 printf("Not enough, need %u:\n",nbits);
154 printf(" Bits = ");
155 dumpuintbits(&bits,1);
156 printf("\n");
157 }
158 while (1) {
159 bit_buffer = gsl_rng_get (rng);
160 bits_left_in_bit_buffer = rmax_bits;
161
162 MYDEBUG(D_BITS) {
163 printf("Refilled bit_buffer\n");
164 printf("%u bits left\n",bits_left_in_bit_buffer);
165 printf(" Buff = ");
166 dumpuintbits(&bit_buffer,1);
167 printf("\n");
168 }
169
170 if (bits_left_in_bit_buffer >= nbits) {
171 bits_left_in_bit_buffer -= nbits;
172 bits |= (bit_buffer >> bits_left_in_bit_buffer);
173
174 MYDEBUG(D_BITS) {
175 printf("Returning:\n");
176 printf(" Bits = ");
177 breturn = bits & mask;
178 dumpuintbits(&breturn,1);
179 printf("\n");
180 }
181
182 return bits & mask;
183 }
184 nbits -= bits_left_in_bit_buffer;
185 bits |= (bit_buffer << nbits);
186
187 MYDEBUG(D_BITS) {
188 printf("This should never execute:\n");
189 printf(" Bits = ");
190 dumpuintbits(&bits,1);
191 printf("\n");
192 }
193
194 }
195
196 }
197
198 /*
199 * This is a drop-in-replacement for get_bit_ntuple() contributed by
200 * John E. Davis. It speeds up this code substantially but may
201 * require work if/when rngs that generate 64-bit rands come along.
202 * But then, so will other programs.
203 */
get_bit_ntuple_from_uint(uint bitstr,uint nbits,uint mask,uint boffset)204 inline static uint get_bit_ntuple_from_uint (uint bitstr, uint nbits,
205 uint mask, uint boffset)
206 {
207 uint result;
208 uint len;
209
210 /* Only rmax_bits in bitstr are meaningful */
211 boffset = boffset % rmax_bits;
212 result = bitstr >> boffset;
213
214 if (boffset + nbits <= rmax_bits)
215 return result & mask;
216
217 /* Need to wrap */
218 len = rmax_bits - boffset;
219 while (len < nbits)
220 {
221 result |= (bitstr << len);
222 len += rmax_bits;
223 }
224 return result & mask;
225 }
226
227 /*
228 * David Bauer doesn't like using the routine above to "fix" the
229 * problem that some generators don't return 32 bit random uints. This
230 * version of the routine just ignore rmax_bits. If a routine returns
231 * 31 or 24 bit uints, tough. This is harmless enough since nobody cares
232 * about obsolete generators that return signed uints or worse anyway, I
233 * imagine. It MIGHT affect people writing HW generators that return only
234 * 16 bits at a time or the like -- they need to be advised to wrap their
235 * call routines up to return uints. It's faster, too -- less checking
236 * of the stream, fewer conditionals.
237 */
get_bit_ntuple_from_whole_uint(uint bitstr,uint nbits,uint mask,uint boffset)238 inline static uint get_bit_ntuple_from_whole_uint (uint bitstr, uint nbits,
239 uint mask, uint boffset)
240 {
241 uint result;
242 uint len;
243
244 result = bitstr >> boffset;
245
246 if (boffset + nbits <= 32) return result & mask;
247
248 /* Need to wrap */
249 len = 32 - boffset;
250 while (len < nbits) {
251 result |= (bitstr << len);
252 len += 32;
253 }
254
255 return result & mask;
256
257 }
258
259