1) Unifdef USE_WEAK_SEEDING it is too obsolete to support and makes reading
harder. 2) ACM paper require seed to be in [1, 2^31-2] range, so use the same range shifting as already done for rand(3). Also protect srandomdev() + TYPE_0 case (non default) from negative seeds. 3) Don't check for valid "type" range in setstate(), it is always valid as calculated. Instead add a check that rear pointer not exceeed end pointer. MFC after: 1 week
This commit is contained in:
+14
-46
@@ -137,11 +137,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
*/
|
*/
|
||||||
#define MAX_TYPES 5 /* max number of types above */
|
#define MAX_TYPES 5 /* max number of types above */
|
||||||
|
|
||||||
#ifdef USE_WEAK_SEEDING
|
|
||||||
#define NSHUFF 0
|
|
||||||
#else /* !USE_WEAK_SEEDING */
|
|
||||||
#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
|
#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
|
||||||
#endif /* !USE_WEAK_SEEDING */
|
|
||||||
|
|
||||||
static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
|
static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
|
||||||
static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
|
static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
|
||||||
@@ -162,23 +158,12 @@ static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
|
|||||||
|
|
||||||
static uint32_t randtbl[DEG_3 + 1] = {
|
static uint32_t randtbl[DEG_3 + 1] = {
|
||||||
TYPE_3,
|
TYPE_3,
|
||||||
#ifdef USE_WEAK_SEEDING
|
0x2cf41758, 0x27bb3711, 0x4916d4d1, 0x7b02f59f, 0x9b8e28eb, 0xc0e80269,
|
||||||
/* Historic implementation compatibility */
|
0x696f5c16, 0x878f1ff5, 0x52d9c07f, 0x916a06cd, 0xb50b3a20, 0x2776970a,
|
||||||
/* The random sequences do not vary much with the seed */
|
0xee4eb2a6, 0xe94640ec, 0xb1d65612, 0x9d1ed968, 0x1043f6b7, 0xa3432a76,
|
||||||
0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
|
0x17eacbb9, 0x3c09e2eb, 0x4f8c2b3, 0x708a1f57, 0xee341814, 0x95d0e4d2,
|
||||||
0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
|
0xb06f216c, 0x8bd2e72e, 0x8f7c38d7, 0xcfc6a8fc, 0x2a59495, 0xa20d2a69,
|
||||||
0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
|
0xe29d12d1
|
||||||
0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
|
|
||||||
0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
|
|
||||||
0x27fb47b9,
|
|
||||||
#else /* !USE_WEAK_SEEDING */
|
|
||||||
0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
|
|
||||||
0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
|
|
||||||
0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
|
|
||||||
0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
|
|
||||||
0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
|
|
||||||
0xf3bec5da
|
|
||||||
#endif /* !USE_WEAK_SEEDING */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -215,16 +200,8 @@ static int rand_sep = SEP_3;
|
|||||||
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
|
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
good_rand(int32_t x)
|
good_rand(uint32_t ctx)
|
||||||
{
|
{
|
||||||
#ifdef USE_WEAK_SEEDING
|
|
||||||
/*
|
|
||||||
* Historic implementation compatibility.
|
|
||||||
* The random sequences do not vary much with the seed,
|
|
||||||
* even with overflowing.
|
|
||||||
*/
|
|
||||||
return (1103515245 * x + 12345);
|
|
||||||
#else /* !USE_WEAK_SEEDING */
|
|
||||||
/*
|
/*
|
||||||
* Compute x = (7^5 * x) mod (2^31 - 1)
|
* Compute x = (7^5 * x) mod (2^31 - 1)
|
||||||
* wihout overflowing 31 bits:
|
* wihout overflowing 31 bits:
|
||||||
@@ -233,18 +210,17 @@ good_rand(int32_t x)
|
|||||||
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
|
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
|
||||||
* October 1988, p. 1195.
|
* October 1988, p. 1195.
|
||||||
*/
|
*/
|
||||||
int32_t hi, lo;
|
int32_t hi, lo, x;
|
||||||
|
|
||||||
/* Can't be initialized with 0, so use another value. */
|
/* Transform to [1, 0x7ffffffe] range. */
|
||||||
if (x == 0)
|
x = (ctx % 0x7ffffffe) + 1;
|
||||||
x = 123459876;
|
|
||||||
hi = x / 127773;
|
hi = x / 127773;
|
||||||
lo = x % 127773;
|
lo = x % 127773;
|
||||||
x = 16807 * lo - 2836 * hi;
|
x = 16807 * lo - 2836 * hi;
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
x += 0x7fffffff;
|
x += 0x7fffffff;
|
||||||
return (x);
|
/* Transform to [0, 0x7ffffffd] range. */
|
||||||
#endif /* !USE_WEAK_SEEDING */
|
return (x - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -404,16 +380,8 @@ setstate(char *arg_state)
|
|||||||
uint32_t rear = new_state[0] / MAX_TYPES;
|
uint32_t rear = new_state[0] / MAX_TYPES;
|
||||||
char *ostate = (char *)(&state[-1]);
|
char *ostate = (char *)(&state[-1]);
|
||||||
|
|
||||||
switch(type) {
|
if (type != TYPE_0 && rear >= degrees[type])
|
||||||
case TYPE_0:
|
|
||||||
case TYPE_1:
|
|
||||||
case TYPE_2:
|
|
||||||
case TYPE_3:
|
|
||||||
case TYPE_4:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
|
||||||
if (rand_type == TYPE_0)
|
if (rand_type == TYPE_0)
|
||||||
state[-1] = rand_type;
|
state[-1] = rand_type;
|
||||||
else
|
else
|
||||||
@@ -455,7 +423,7 @@ random(void)
|
|||||||
|
|
||||||
if (rand_type == TYPE_0) {
|
if (rand_type == TYPE_0) {
|
||||||
i = state[0];
|
i = state[0];
|
||||||
state[0] = i = (good_rand(i)) & 0x7fffffff;
|
state[0] = i = good_rand(i);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Use local variables rather than static variables for speed.
|
* Use local variables rather than static variables for speed.
|
||||||
|
|||||||
Reference in New Issue
Block a user