summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2016-06-05 13:39:31 +0000
committerache <ache@FreeBSD.org>2016-06-05 13:39:31 +0000
commit4ab0fcf85bd26f3eaf7a2f8693ed80e89d2be762 (patch)
tree1c086a2d853fa0b3b32baf88a346b4bfb2753c32 /lib
parent1d29d3ea453434cd2affdd1f6e7dc7fa17ffb85c (diff)
downloadFreeBSD-src-4ab0fcf85bd26f3eaf7a2f8693ed80e89d2be762.zip
FreeBSD-src-4ab0fcf85bd26f3eaf7a2f8693ed80e89d2be762.tar.gz
MFC: r300953
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: r300965 Micro optimize: C standard guarantees that right shift for unsigned value fills left bits with zero, and we have exact 32bit unsigned value (uint32_t), so there is no reason to add "& 0x7fffffff" here.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/random.c62
1 files changed, 15 insertions, 47 deletions
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
index f7b745e..fe8fc86 100644
--- a/lib/libc/stdlib/random.c
+++ b/lib/libc/stdlib/random.c
@@ -137,11 +137,7 @@ __FBSDID("$FreeBSD$");
*/
#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 */
-#endif /* !USE_WEAK_SEEDING */
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 };
@@ -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] = {
TYPE_3,
-#ifdef USE_WEAK_SEEDING
-/* Historic implementation compatibility */
-/* The random sequences do not vary much with the seed */
- 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
- 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
- 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
- 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 */
+ 0x2cf41758, 0x27bb3711, 0x4916d4d1, 0x7b02f59f, 0x9b8e28eb, 0xc0e80269,
+ 0x696f5c16, 0x878f1ff5, 0x52d9c07f, 0x916a06cd, 0xb50b3a20, 0x2776970a,
+ 0xee4eb2a6, 0xe94640ec, 0xb1d65612, 0x9d1ed968, 0x1043f6b7, 0xa3432a76,
+ 0x17eacbb9, 0x3c09e2eb, 0x4f8c2b3, 0x708a1f57, 0xee341814, 0x95d0e4d2,
+ 0xb06f216c, 0x8bd2e72e, 0x8f7c38d7, 0xcfc6a8fc, 0x2a59495, 0xa20d2a69,
+ 0xe29d12d1
};
/*
@@ -215,16 +200,8 @@ static int rand_sep = SEP_3;
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
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)
* wihout overflowing 31 bits:
@@ -233,18 +210,17 @@ good_rand(int32_t x)
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
*/
- int32_t hi, lo;
+ int32_t hi, lo, x;
- /* Can't be initialized with 0, so use another value. */
- if (x == 0)
- x = 123459876;
+ /* Transform to [1, 0x7ffffffe] range. */
+ x = (ctx % 0x7ffffffe) + 1;
hi = x / 127773;
lo = x % 127773;
x = 16807 * lo - 2836 * hi;
if (x < 0)
x += 0x7fffffff;
- return (x);
-#endif /* !USE_WEAK_SEEDING */
+ /* Transform to [0, 0x7ffffffd] range. */
+ return (x - 1);
}
/*
@@ -404,16 +380,8 @@ setstate(char *arg_state)
uint32_t rear = new_state[0] / MAX_TYPES;
char *ostate = (char *)(&state[-1]);
- switch(type) {
- case TYPE_0:
- case TYPE_1:
- case TYPE_2:
- case TYPE_3:
- case TYPE_4:
- break;
- default:
+ if (type != TYPE_0 && rear >= degrees[type])
return (NULL);
- }
if (rand_type == TYPE_0)
state[-1] = rand_type;
else
@@ -455,14 +423,14 @@ random(void)
if (rand_type == TYPE_0) {
i = state[0];
- state[0] = i = (good_rand(i)) & 0x7fffffff;
+ state[0] = i = good_rand(i);
} else {
/*
* Use local variables rather than static variables for speed.
*/
f = fptr; r = rptr;
*f += *r;
- i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ i = *f >> 1; /* chucking least random bit */
if (++f >= end_ptr) {
f = state;
++r;
OpenPOWER on IntegriCloud