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