1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*
This is a maximally equidistributed combined Tausworthe generator
based on code from GNU Scientific Library 1.5 (30 Jun 2004)
x_n = (s1_n ^ s2_n ^ s3_n)
s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
The period of this generator is about 2^88.
From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
This is available on the net from L'Ecuyer's home page,
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
There is an erratum in the paper "Tables of Maximally
Equidistributed Combined LFSR Generators", Mathematics of
Computation, 68, 225 (1999), 261--269:
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
... the k_j most significant bits of z_j must be non-
zero, for each j. (Note: this restriction also applies to the
computer code given in [4], but was mistakenly not mentioned in
that paper.)
This affects the seeding procedure by imposing the requirement
s1 > 1, s2 > 7, s3 > 15.
*/
#include <string.h>
#include "rand.h"
#include "../hash.h"
static inline int __seed(unsigned int x, unsigned int m)
{
return (x < m) ? x + m : x;
}
static void __init_rand(struct frand_state *state, unsigned int seed)
{
int cranks = 6;
#define LCG(x, seed) ((x) * 69069 ^ (seed))
state->s1 = __seed(LCG((2^31) + (2^17) + (2^7), seed), 1);
state->s2 = __seed(LCG(state->s1, seed), 7);
state->s3 = __seed(LCG(state->s2, seed), 15);
while (cranks--)
__rand(state);
}
void init_rand(struct frand_state *state)
{
__init_rand(state, 1);
}
void init_rand_seed(struct frand_state *state, unsigned int seed)
{
__init_rand(state, seed);
}
void __fill_random_buf(void *buf, unsigned int len, unsigned long seed)
{
long *ptr = buf;
while ((void *) ptr - buf < len) {
*ptr = seed;
ptr++;
seed *= GOLDEN_RATIO_PRIME;
seed >>= 3;
}
}
unsigned long fill_random_buf(struct frand_state *fs, void *buf,
unsigned int len)
{
unsigned long r = __rand(fs);
if (sizeof(int) != sizeof(long *))
r *= (unsigned long) __rand(fs);
__fill_random_buf(buf, len, r);
return r;
}
unsigned long fill_random_buf_percentage(struct frand_state *fs, void *buf,
unsigned int percentage,
unsigned int segment, unsigned int len)
{
unsigned long r = __rand(fs);
unsigned int this_len;
if (percentage == 100) {
memset(buf, 0, len);
return 0;
}
if (segment > len)
segment = len;
if (sizeof(int) != sizeof(long *))
r *= (unsigned long) __rand(fs);
while (len) {
/*
* Fill random chunk
*/
this_len = (segment * (100 - percentage)) / 100;
if (this_len > len)
this_len = len;
__fill_random_buf(buf, this_len, r);
len -= this_len;
buf += this_len;
if (this_len > len)
this_len = len;
memset(buf, 0, this_len);
len -= this_len;
buf += this_len;
}
return r;
}
|